summaryrefslogtreecommitdiffstats
path: root/chrome/browser/tab_contents
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-29 03:56:51 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-29 03:56:51 +0000
commit14e60c8d78e36e0d8cd224dd907ebc350c6c4f06 (patch)
tree74fd3699c2cb4a69373258588747db41dd58d1e5 /chrome/browser/tab_contents
parente73273b0d0c0d7b77b3f3c095923307bab006938 (diff)
downloadchromium_src-14e60c8d78e36e0d8cd224dd907ebc350c6c4f06.zip
chromium_src-14e60c8d78e36e0d8cd224dd907ebc350c6c4f06.tar.gz
chromium_src-14e60c8d78e36e0d8cd224dd907ebc350c6c4f06.tar.bz2
Move render_view_host_manager* and site_instance* from tab_contents to renderer_host.
Review URL: http://codereview.chromium.org/150011 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19481 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/tab_contents')
-rw-r--r--chrome/browser/tab_contents/navigation_controller.cc2
-rw-r--r--chrome/browser/tab_contents/navigation_entry.h2
-rw-r--r--chrome/browser/tab_contents/render_view_host_delegate_helper.cc2
-rw-r--r--chrome/browser/tab_contents/render_view_host_manager.cc589
-rw-r--r--chrome/browser/tab_contents/render_view_host_manager.h263
-rw-r--r--chrome/browser/tab_contents/render_view_host_manager_unittest.cc116
-rw-r--r--chrome/browser/tab_contents/site_instance.cc191
-rw-r--r--chrome/browser/tab_contents/site_instance.h180
-rw-r--r--chrome/browser/tab_contents/site_instance_unittest.cc458
-rw-r--r--chrome/browser/tab_contents/tab_contents.h2
10 files changed, 4 insertions, 1801 deletions
diff --git a/chrome/browser/tab_contents/navigation_controller.cc b/chrome/browser/tab_contents/navigation_controller.cc
index b5ae80b..ef27e74 100644
--- a/chrome/browser/tab_contents/navigation_controller.cc
+++ b/chrome/browser/tab_contents/navigation_controller.cc
@@ -13,10 +13,10 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_url_handler.h"
#include "chrome/browser/profile.h"
+#include "chrome/browser/renderer_host/site_instance.h"
#include "chrome/browser/sessions/session_types.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/repost_form_warning.h"
-#include "chrome/browser/tab_contents/site_instance.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/navigation_types.h"
#include "chrome/common/notification_service.h"
diff --git a/chrome/browser/tab_contents/navigation_entry.h b/chrome/browser/tab_contents/navigation_entry.h
index 8e55746..366b460 100644
--- a/chrome/browser/tab_contents/navigation_entry.h
+++ b/chrome/browser/tab_contents/navigation_entry.h
@@ -8,8 +8,8 @@
#include "base/basictypes.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
+#include "chrome/browser/renderer_host/site_instance.h"
#include "chrome/browser/tab_contents/security_style.h"
-#include "chrome/browser/tab_contents/site_instance.h"
#include "chrome/common/page_transition_types.h"
#include "googleurl/src/gurl.h"
#include "grit/theme_resources.h"
diff --git a/chrome/browser/tab_contents/render_view_host_delegate_helper.cc b/chrome/browser/tab_contents/render_view_host_delegate_helper.cc
index 0395ab1..b8c4c0e 100644
--- a/chrome/browser/tab_contents/render_view_host_delegate_helper.cc
+++ b/chrome/browser/tab_contents/render_view_host_delegate_helper.cc
@@ -12,7 +12,7 @@
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_widget_host.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"
-#include "chrome/browser/tab_contents/site_instance.h"
+#include "chrome/browser/renderer_host/site_instance.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view.h"
#include "chrome/common/chrome_switches.h"
diff --git a/chrome/browser/tab_contents/render_view_host_manager.cc b/chrome/browser/tab_contents/render_view_host_manager.cc
deleted file mode 100644
index 68421a7..0000000
--- a/chrome/browser/tab_contents/render_view_host_manager.cc
+++ /dev/null
@@ -1,589 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/tab_contents/render_view_host_manager.h"
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "chrome/browser/dom_ui/dom_ui.h"
-#include "chrome/browser/dom_ui/dom_ui_factory.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/renderer_host/render_view_host_delegate.h"
-#include "chrome/browser/renderer_host/render_view_host_factory.h"
-#include "chrome/browser/renderer_host/render_widget_host_view.h"
-#include "chrome/browser/tab_contents/navigation_controller.h"
-#include "chrome/browser/tab_contents/navigation_entry.h"
-#include "chrome/browser/tab_contents/site_instance.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_type.h"
-#include "chrome/common/render_messages.h"
-
-namespace base {
-class WaitableEvent;
-}
-
-RenderViewHostManager::RenderViewHostManager(
- RenderViewHostDelegate* render_view_delegate,
- Delegate* delegate)
- : delegate_(delegate),
- cross_navigation_pending_(false),
- render_view_delegate_(render_view_delegate),
- render_view_host_(NULL),
- pending_render_view_host_(NULL),
- interstitial_page_(NULL) {
- registrar_.Add(this, NotificationType::RENDER_VIEW_HOST_DELETED,
- NotificationService::AllSources());
-}
-
-RenderViewHostManager::~RenderViewHostManager() {
- if (pending_render_view_host_)
- CancelPending();
-
- // We should always have a main RenderViewHost.
- RenderViewHost* render_view_host = render_view_host_;
- render_view_host_ = NULL;
- render_view_host->Shutdown();
-}
-
-void RenderViewHostManager::Init(Profile* profile,
- SiteInstance* site_instance,
- int routing_id,
- base::WaitableEvent* modal_dialog_event) {
- // Create a RenderViewHost, once we have an instance. It is important to
- // immediately give this SiteInstance to a RenderViewHost so that it is
- // ref counted.
- if (!site_instance)
- site_instance = SiteInstance::CreateSiteInstance(profile);
- render_view_host_ = RenderViewHostFactory::Create(
- site_instance, render_view_delegate_, routing_id, modal_dialog_event);
- NotificationService::current()->Notify(
- NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB,
- Source<RenderViewHostManager>(this),
- Details<RenderViewHost>(render_view_host_));
-}
-
-RenderViewHost* RenderViewHostManager::Navigate(const NavigationEntry& entry) {
- // This will possibly create (set to NULL) a DOM UI object for the pending
- // page. We'll use this later to give the page special access. This must
- // happen before the new renderer is created below so it will get bindings.
- pending_dom_ui_.reset(delegate_->CreateDOMUIForRenderManager(entry.url()));
-
- // Create a pending RenderViewHost. It will give us the one we should use
- RenderViewHost* dest_render_view_host = UpdateRendererStateForNavigate(entry);
- if (!dest_render_view_host)
- return NULL; // We weren't able to create a pending render view host.
-
- // If the current render_view_host_ isn't live, we should create it so
- // that we don't show a sad tab while the dest_render_view_host fetches
- // its first page. (Bug 1145340)
- if (dest_render_view_host != render_view_host_ &&
- !render_view_host_->IsRenderViewLive()) {
- delegate_->CreateRenderViewForRenderManager(render_view_host_);
- }
-
- // If the renderer crashed, then try to create a new one to satisfy this
- // navigation request.
- if (!dest_render_view_host->IsRenderViewLive()) {
- if (!delegate_->CreateRenderViewForRenderManager(dest_render_view_host))
- return NULL;
-
- // Now that we've created a new renderer, be sure to hide it if it isn't
- // our primary one. Otherwise, we might crash if we try to call Show()
- // on it later.
- if (dest_render_view_host != render_view_host_ &&
- dest_render_view_host->view()) {
- dest_render_view_host->view()->Hide();
- } else {
- // This is our primary renderer, notify here as we won't be calling
- // CommitPending (which does the notify).
- RenderViewHostSwitchedDetails details;
- details.new_host = render_view_host_;
- details.old_host = NULL;
- NotificationService::current()->Notify(
- NotificationType::RENDER_VIEW_HOST_CHANGED,
- Source<NavigationController>(
- &delegate_->GetControllerForRenderManager()),
- Details<RenderViewHostSwitchedDetails>(&details));
- }
- }
-
- return dest_render_view_host;
-}
-
-void RenderViewHostManager::Stop() {
- render_view_host_->Stop();
-
- // If we are cross-navigating, we should stop the pending renderers. This
- // will lead to a DidFailProvisionalLoad, which will properly destroy them.
- if (cross_navigation_pending_)
- pending_render_view_host_->Stop();
-}
-
-void RenderViewHostManager::SetIsLoading(bool is_loading) {
- render_view_host_->SetIsLoading(is_loading);
- if (pending_render_view_host_)
- pending_render_view_host_->SetIsLoading(is_loading);
-}
-
-bool RenderViewHostManager::ShouldCloseTabOnUnresponsiveRenderer() {
- if (!cross_navigation_pending_)
- return true;
-
- // If the tab becomes unresponsive during unload while doing a
- // cross-site navigation, proceed with the navigation. (This assumes that
- // the pending RenderViewHost is still responsive.)
- int pending_request_id = pending_render_view_host_->GetPendingRequestId();
- if (pending_request_id == -1) {
- // Haven't gotten around to starting the request, because we're still
- // waiting for the beforeunload handler to finish. We'll pretend that it
- // did finish, to let the navigation proceed. Note that there's a danger
- // that the beforeunload handler will later finish and possibly return
- // false (meaning the navigation should not proceed), but we'll ignore it
- // in this case because it took too long.
- if (pending_render_view_host_->are_navigations_suspended())
- pending_render_view_host_->SetNavigationsSuspended(false);
- } else {
- // The request has been started and paused, while we're waiting for the
- // unload handler to finish. We'll pretend that it did, by notifying the
- // IO thread to let the response continue. The pending renderer will then
- // be swapped in as part of the usual DidNavigate logic. (If the unload
- // handler later finishes, this call will be ignored because the state in
- // CrossSiteResourceHandler will already be cleaned up.)
- current_host()->process()->CrossSiteClosePageACK(
- pending_render_view_host_->process()->pid(), pending_request_id);
- }
- return false;
-}
-
-void RenderViewHostManager::DidNavigateMainFrame(
- RenderViewHost* render_view_host) {
- if (!cross_navigation_pending_) {
- DCHECK(!pending_render_view_host_);
-
- // We should only hear this from our current renderer.
- DCHECK(render_view_host == render_view_host_);
-
- // Even when there is no pending RVH, there may be a pending DOM UI.
- if (pending_dom_ui_.get())
- CommitPending();
- return;
- }
-
- if (render_view_host == pending_render_view_host_) {
- // The pending cross-site navigation completed, so show the renderer.
- CommitPending();
- cross_navigation_pending_ = false;
- } else if (render_view_host == render_view_host_) {
- // A navigation in the original page has taken place. Cancel the pending
- // one.
- CancelPending();
- cross_navigation_pending_ = false;
- } else {
- // No one else should be sending us DidNavigate in this state.
- DCHECK(false);
- }
-}
-
-void RenderViewHostManager::OnCrossSiteResponse(int new_render_process_host_id,
- int new_request_id) {
- // Should only see this while we have a pending renderer.
- if (!cross_navigation_pending_)
- return;
- DCHECK(pending_render_view_host_);
-
- // Tell the old renderer to run its onunload handler. When it finishes, it
- // will send a ClosePage_ACK to the ResourceDispatcherHost with the given
- // IDs (of the pending RVH's request), allowing the pending RVH's response to
- // resume.
- render_view_host_->ClosePage(new_render_process_host_id, new_request_id);
-
- // ResourceDispatcherHost has told us to run the onunload handler, which
- // means it is not a download or unsafe page, and we are going to perform the
- // navigation. Thus, we no longer need to remember that the RenderViewHost
- // is part of a pending cross-site request.
- pending_render_view_host_->SetHasPendingCrossSiteRequest(false,
- new_request_id);
-}
-
-void RenderViewHostManager::RendererAbortedProvisionalLoad(
- RenderViewHost* render_view_host) {
- // We used to cancel the pending renderer here for cross-site downloads.
- // However, it's not safe to do that because the download logic repeatedly
- // looks for this TabContents based on a render view ID. Instead, we just
- // leave the pending renderer around until the next navigation event
- // (Navigate, DidNavigate, etc), which will clean it up properly.
- // TODO(creis): All of this will go away when we move the cross-site logic
- // to ResourceDispatcherHost, so that we intercept responses rather than
- // navigation events. (That's necessary to support onunload anyway.) Once
- // we've made that change, we won't create a pending renderer until we know
- // the response is not a download.
-}
-
-void RenderViewHostManager::ShouldClosePage(bool proceed) {
- // Should only see this while we have a pending renderer. Otherwise, we
- // should ignore.
- if (!pending_render_view_host_) {
- bool proceed_to_fire_unload;
- delegate_->BeforeUnloadFiredFromRenderManager(proceed,
- &proceed_to_fire_unload);
-
- if (proceed_to_fire_unload) {
- // This is not a cross-site navigation, the tab is being closed.
- render_view_host_->FirePageUnload();
- }
- return;
- }
-
- if (proceed) {
- // Ok to unload the current page, so proceed with the cross-site
- // navigation. Note that if navigations are not currently suspended, it
- // might be because the renderer was deemed unresponsive and this call was
- // already made by ShouldCloseTabOnUnresponsiveRenderer. In that case, it
- // is ok to do nothing here.
- if (pending_render_view_host_->are_navigations_suspended())
- pending_render_view_host_->SetNavigationsSuspended(false);
- } else {
- // Current page says to cancel.
- CancelPending();
- cross_navigation_pending_ = false;
- }
-}
-
-void RenderViewHostManager::OnJavaScriptMessageBoxClosed(
- IPC::Message* reply_msg,
- bool success,
- const std::wstring& prompt) {
- render_view_host_->JavaScriptMessageBoxClosed(reply_msg, success, prompt);
-}
-
-void RenderViewHostManager::OnJavaScriptMessageBoxWindowDestroyed() {
- render_view_host_->JavaScriptMessageBoxWindowDestroyed();
-}
-
-void RenderViewHostManager::Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- // Debugging code to help isolate
- // http://code.google.com/p/chromium/issues/detail?id=6316 . We should never
- // reference a RVH that is about to be deleted.
- RenderViewHost* deleted_rvh = Source<RenderViewHost>(source).ptr();
- CHECK(deleted_rvh);
- CHECK(render_view_host_ != deleted_rvh);
- CHECK(pending_render_view_host_ != deleted_rvh);
-}
-
-bool RenderViewHostManager::ShouldTransitionCrossSite() {
- // True if we are using process-per-site-instance (default) or
- // process-per-site (kProcessPerSite).
- return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerTab);
-}
-
-bool RenderViewHostManager::ShouldSwapProcessesForNavigation(
- const NavigationEntry* cur_entry,
- const NavigationEntry* new_entry) const {
- if (!cur_entry || !new_entry)
- return false;
-
- // We can't switch a RenderView between view source and non-view source mode
- // without screwing up the session history sometimes (when navigating between
- // "view-source:http://foo.com/" and "http://foo.com/", WebKit doesn't treat
- // it as a new navigation). So require a view switch.
- if (cur_entry->IsViewSourceMode() != new_entry->IsViewSourceMode())
- return true;
-
- // For security, we should transition between processes when one is a DOM UI
- // page and one isn't.
- if (DOMUIFactory::HasDOMUIScheme(cur_entry->url()) !=
- DOMUIFactory::HasDOMUIScheme(new_entry->url()))
- return true;
-
- return false;
-}
-
-SiteInstance* RenderViewHostManager::GetSiteInstanceForEntry(
- const NavigationEntry& entry,
- SiteInstance* curr_instance) {
- // NOTE: This is only called when ShouldTransitionCrossSite is true.
-
- // If the entry has an instance already, we should use it.
- if (entry.site_instance())
- return entry.site_instance();
-
- // (UGLY) HEURISTIC, process-per-site only:
- //
- // If this navigation is generated, then it probably corresponds to a search
- // query. Given that search results typically lead to users navigating to
- // other sites, we don't really want to use the search engine hostname to
- // determine the site instance for this navigation.
- //
- // NOTE: This can be removed once we have a way to transition between
- // RenderViews in response to a link click.
- //
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessPerSite) &&
- entry.transition_type() == PageTransition::GENERATED)
- return curr_instance;
-
- const GURL& dest_url = entry.url();
-
- // If we haven't used our SiteInstance (and thus RVH) yet, then we can use it
- // for this entry. We won't commit the SiteInstance to this site until the
- // navigation commits (in DidNavigate), unless the navigation entry was
- // restored. As session restore loads all the pages immediately we need to set
- // the site first, otherwise after a restore none of the pages would share
- // renderers.
- if (!curr_instance->has_site()) {
- // If we've already created a SiteInstance for our destination, we don't
- // want to use this unused SiteInstance; use the existing one. (We don't
- // do this check if the curr_instance has a site, because for now, we want
- // to compare against the current URL and not the SiteInstance's site. In
- // this case, there is no current URL, so comparing against the site is ok.
- // See additional comments below.)
- if (curr_instance->HasRelatedSiteInstance(dest_url)) {
- return curr_instance->GetRelatedSiteInstance(dest_url);
- } else {
- if (entry.restored())
- curr_instance->SetSite(dest_url);
- return curr_instance;
- }
- }
-
- // Otherwise, only create a new SiteInstance for cross-site navigation.
-
- // TODO(creis): Once we intercept links and script-based navigations, we
- // will be able to enforce that all entries in a SiteInstance actually have
- // the same site, and it will be safe to compare the URL against the
- // SiteInstance's site, as follows:
- // const GURL& current_url = curr_instance->site();
- // For now, though, we're in a hybrid model where you only switch
- // SiteInstances if you type in a cross-site URL. This means we have to
- // compare the entry's URL to the last committed entry's URL.
- NavigationController& controller = delegate_->GetControllerForRenderManager();
- NavigationEntry* curr_entry = controller.GetLastCommittedEntry();
- if (interstitial_page_) {
- // The interstitial is currently the last committed entry, but we want to
- // compare against the last non-interstitial entry.
- curr_entry = controller.GetEntryAtOffset(-1);
- }
- // If there is no last non-interstitial entry (and curr_instance already
- // has a site), then we must have been opened from another tab. We want
- // to compare against the URL of the page that opened us, but we can't
- // get to it directly. The best we can do is check against the site of
- // the SiteInstance. This will be correct when we intercept links and
- // script-based navigations, but for now, it could place some pages in a
- // new process unnecessarily. We should only hit this case if a page tries
- // to open a new tab to an interstitial-inducing URL, and then navigates
- // the page to a different same-site URL. (This seems very unlikely in
- // practice.)
- const GURL& current_url = (curr_entry) ? curr_entry->url() :
- curr_instance->site();
-
- if (SiteInstance::IsSameWebSite(current_url, dest_url)) {
- return curr_instance;
- } else if (ShouldSwapProcessesForNavigation(curr_entry, &entry)) {
- // When we're swapping, we need to force the site instance AND browsing
- // instance to be different ones. This addresses special cases where we use
- // a single BrowsingInstance for all pages of a certain type (e.g., New Tab
- // Pages), keeping them in the same process. When you navigate away from
- // that page, we want to explicity ignore that BrowsingInstance and group
- // this page into the appropriate SiteInstance for its URL.
- return SiteInstance::CreateSiteInstanceForURL(
- delegate_->GetControllerForRenderManager().profile(), dest_url);
- } else {
- // Start the new renderer in a new SiteInstance, but in the current
- // BrowsingInstance. It is important to immediately give this new
- // SiteInstance to a RenderViewHost (if it is different than our current
- // SiteInstance), so that it is ref counted. This will happen in
- // CreatePendingRenderView.
- return curr_instance->GetRelatedSiteInstance(dest_url);
- }
-}
-
-bool RenderViewHostManager::CreatePendingRenderView(SiteInstance* instance) {
- NavigationEntry* curr_entry =
- delegate_->GetControllerForRenderManager().GetLastCommittedEntry();
- if (curr_entry) {
- DCHECK(!curr_entry->content_state().empty());
- // TODO(creis): Should send a message to the RenderView to let it know
- // we're about to switch away, so that it sends an UpdateState message.
- }
-
- pending_render_view_host_ = RenderViewHostFactory::Create(
- instance, render_view_delegate_, MSG_ROUTING_NONE, NULL);
- NotificationService::current()->Notify(
- NotificationType::RENDER_VIEW_HOST_CREATED_FOR_TAB,
- Source<RenderViewHostManager>(this),
- Details<RenderViewHost>(pending_render_view_host_));
-
- bool success = delegate_->CreateRenderViewForRenderManager(
- pending_render_view_host_);
- if (success) {
- // Don't show the view until we get a DidNavigate from it.
- pending_render_view_host_->view()->Hide();
- } else {
- CancelPending();
- }
- return success;
-}
-
-void RenderViewHostManager::CommitPending() {
- // First commit the DOM UI, if any.
- dom_ui_.swap(pending_dom_ui_);
- pending_dom_ui_.reset();
-
- // It's possible for the pending_render_view_host_ to be NULL when we aren't
- // crossing process boundaries. If so, we just needed to handle the DOM UI
- // committing above and we're done.
- if (!pending_render_view_host_)
- return;
-
- // Remember if the page was focused so we can focus the new renderer in
- // that case.
- bool focus_render_view = render_view_host_->view() &&
- render_view_host_->view()->HasFocus();
-
- // Hide the current view and prepare to destroy it.
- // TODO(creis): Get the old RenderViewHost to send us an UpdateState message
- // before we destroy it.
- if (render_view_host_->view())
- render_view_host_->view()->Hide();
- RenderViewHost* old_render_view_host = render_view_host_;
-
- // Swap in the pending view and make it active.
- render_view_host_ = pending_render_view_host_;
- pending_render_view_host_ = NULL;
-
- // If the view is gone, then this RenderViewHost died while it was hidden.
- // We ignored the RenderViewGone call at the time, so we should send it now
- // to make sure the sad tab shows up, etc.
- if (render_view_host_->view())
- render_view_host_->view()->Show();
- else
- delegate_->RenderViewGoneFromRenderManager(render_view_host_);
-
- // Make sure the size is up to date. (Fix for bug 1079768.)
- delegate_->UpdateRenderViewSizeForRenderManager();
-
- if (focus_render_view && render_view_host_->view())
- render_view_host_->view()->Focus();
-
- RenderViewHostSwitchedDetails details;
- details.new_host = render_view_host_;
- details.old_host = old_render_view_host;
- NotificationService::current()->Notify(
- NotificationType::RENDER_VIEW_HOST_CHANGED,
- Source<NavigationController>(&delegate_->GetControllerForRenderManager()),
- Details<RenderViewHostSwitchedDetails>(&details));
-
- old_render_view_host->Shutdown();
-
- // Let the task manager know that we've swapped RenderViewHosts, since it
- // might need to update its process groupings.
- delegate_->NotifySwappedFromRenderManager();
-}
-
-RenderViewHost* RenderViewHostManager::UpdateRendererStateForNavigate(
- const NavigationEntry& entry) {
- // If we are cross-navigating, then we want to get back to normal and navigate
- // as usual.
- if (cross_navigation_pending_) {
- if (pending_render_view_host_)
- CancelPending();
- cross_navigation_pending_ = false;
- }
-
- // render_view_host_ will not be deleted before the end of this method, so we
- // don't have to worry about this SiteInstance's ref count dropping to zero.
- SiteInstance* curr_instance = render_view_host_->site_instance();
-
- // Determine if we need a new SiteInstance for this entry.
- // Again, new_instance won't be deleted before the end of this method, so it
- // is safe to use a normal pointer here.
- SiteInstance* new_instance = curr_instance;
- if (ShouldTransitionCrossSite())
- new_instance = GetSiteInstanceForEntry(entry, curr_instance);
-
- if (new_instance != curr_instance ||
- ShouldSwapProcessesForNavigation(
- delegate_->GetLastCommittedNavigationEntryForRenderManager(),
- &entry)) {
- // New SiteInstance.
- DCHECK(!cross_navigation_pending_);
-
- // Create a pending RVH and navigate it.
- bool success = CreatePendingRenderView(new_instance);
- if (!success)
- return NULL;
-
- // Check if our current RVH is live before we set up a transition.
- if (!render_view_host_->IsRenderViewLive()) {
- if (!cross_navigation_pending_) {
- // The current RVH is not live. There's no reason to sit around with a
- // sad tab or a newly created RVH while we wait for the pending RVH to
- // navigate. Just switch to the pending RVH now and go back to non
- // cross-navigating (Note that we don't care about on{before}unload
- // handlers if the current RVH isn't live.)
- CommitPending();
- return render_view_host_;
- } else {
- NOTREACHED();
- return render_view_host_;
- }
- }
- // Otherwise, it's safe to treat this as a pending cross-site transition.
-
- // Make sure the old render view stops, in case a load is in progress.
- render_view_host_->Stop();
-
- // Suspend the new render view (i.e., don't let it send the cross-site
- // Navigate message) until we hear back from the old renderer's
- // onbeforeunload handler. If the handler returns false, we'll have to
- // cancel the request.
- DCHECK(!pending_render_view_host_->are_navigations_suspended());
- pending_render_view_host_->SetNavigationsSuspended(true);
-
- // Tell the CrossSiteRequestManager that this RVH has a pending cross-site
- // request, so that ResourceDispatcherHost will know to tell us to run the
- // old page's onunload handler before it sends the response.
- pending_render_view_host_->SetHasPendingCrossSiteRequest(true, -1);
-
- // We now have a pending RVH.
- DCHECK(!cross_navigation_pending_);
- cross_navigation_pending_ = true;
-
- // Tell the old render view to run its onbeforeunload handler, since it
- // doesn't otherwise know that the cross-site request is happening. This
- // will trigger a call to ShouldClosePage with the reply.
- render_view_host_->FirePageBeforeUnload();
-
- return pending_render_view_host_;
- } else {
- // The renderer can exit view source mode when any error or cancellation
- // happen. We must overwrite to recover the mode.
- if (entry.IsViewSourceMode()) {
- render_view_host_->Send(
- new ViewMsg_EnableViewSourceMode(render_view_host_->routing_id()));
- }
- }
-
- // Same SiteInstance can be used. Navigate render_view_host_ if we are not
- // cross navigating.
- DCHECK(!cross_navigation_pending_);
- return render_view_host_;
-}
-
-void RenderViewHostManager::CancelPending() {
- RenderViewHost* pending_render_view_host = pending_render_view_host_;
- pending_render_view_host_ = NULL;
- pending_render_view_host->Shutdown();
-
- pending_dom_ui_.reset();
-}
-
-void RenderViewHostManager::CrossSiteNavigationCanceled() {
- DCHECK(cross_navigation_pending_);
- cross_navigation_pending_ = false;
- if (pending_render_view_host_)
- CancelPending();
-}
diff --git a/chrome/browser/tab_contents/render_view_host_manager.h b/chrome/browser/tab_contents/render_view_host_manager.h
deleted file mode 100644
index 11ec445..0000000
--- a/chrome/browser/tab_contents/render_view_host_manager.h
+++ /dev/null
@@ -1,263 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_TAB_CONTENTS_RENDER_VIEW_HOST_MANAGER_H_
-#define CHROME_BROWSER_TAB_CONTENTS_RENDER_VIEW_HOST_MANAGER_H_
-
-#include "base/basictypes.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/common/notification_registrar.h"
-#include "chrome/common/notification_observer.h"
-
-class DOMUI;
-class InterstitialPage;
-class NavigationController;
-class NavigationEntry;
-class Profile;
-class RenderViewHostDelegate;
-class RenderWidgetHostView;
-class SiteInstance;
-
-// Manages RenderViewHosts for a TabContents. Normally there is only one and
-// it is easy to do. But we can also have transitions of processes (and hence
-// RenderViewHosts) that can get complex.
-class RenderViewHostManager : public NotificationObserver {
- public:
- // Functions implemented by our owner that we need.
- //
- // TODO(brettw) Clean this up! These are all the functions in TabContents that
- // are required to run this class. The design should probably be better such
- // that these are more clear.
- //
- // There is additional complexity that some of the functions we need in
- // TabContents are inherited and non-virtual. These are named with
- // "RenderManager" so that the duplicate implementation of them will be clear.
- class Delegate {
- public:
- // See tab_contents.h's implementation for more.
- virtual bool CreateRenderViewForRenderManager(
- RenderViewHost* render_view_host) = 0;
- virtual void BeforeUnloadFiredFromRenderManager(
- bool proceed, bool* proceed_to_fire_unload) = 0;
- virtual void DidStartLoadingFromRenderManager(
- RenderViewHost* render_view_host) = 0;
- virtual void RenderViewGoneFromRenderManager(
- RenderViewHost* render_view_host) = 0;
- virtual void UpdateRenderViewSizeForRenderManager() = 0;
- virtual void NotifySwappedFromRenderManager() = 0;
- virtual NavigationController& GetControllerForRenderManager() = 0;
-
- // Creates a DOMUI object for the given URL if one applies. Ownership of the
- // returned pointer will be passed to the caller. If no DOMUI applies,
- // returns NULL.
- virtual DOMUI* CreateDOMUIForRenderManager(const GURL& url) = 0;
-
- // Returns the navigation entry of the current navigation, or NULL if there
- // is none.
- virtual NavigationEntry*
- GetLastCommittedNavigationEntryForRenderManager() = 0;
- };
-
- // Both delegate pointers must be non-NULL and are not owned by this class.
- // They must outlive this class. The RenderViewHostDelegate is what will be
- // installed into all RenderViewHosts that are created.
- //
- // You must call Init() before using this class.
- RenderViewHostManager(RenderViewHostDelegate* render_view_delegate,
- Delegate* delegate);
- ~RenderViewHostManager();
-
- // For arguments, see TabContents constructor.
- void Init(Profile* profile,
- SiteInstance* site_instance,
- int routing_id,
- base::WaitableEvent* modal_dialog_event);
-
- // Returns the currently actuive RenderViewHost.
- //
- // This will be non-NULL between Init() and Shutdown(). You may want to NULL
- // check it in many cases, however. Windows can send us messages during the
- // destruction process after it has been shut down.
- RenderViewHost* current_host() const {
- return render_view_host_;
- }
-
- // Returns the view associated with the current RenderViewHost, or NULL if
- // there is no current one.
- RenderWidgetHostView* current_view() const {
- if (!render_view_host_)
- return NULL;
- return render_view_host_->view();
- }
-
- // Returns the pending render view host, or NULL if there is no pending one.
- RenderViewHost* pending_render_view_host() const {
- return pending_render_view_host_;
- }
-
- // Returns the current committed DOM UI or NULL if none applies.
- DOMUI* dom_ui() const { return dom_ui_.get(); }
-
- // Returns the DOM UI for the pending navigation, or NULL of none applies.
- DOMUI* pending_dom_ui() const { return pending_dom_ui_.get(); }
-
- // Called when we want to instruct the renderer to navigate to the given
- // navigation entry. It may create a new RenderViewHost or re-use an existing
- // one. The RenderViewHost to navigate will be returned. Returns NULL if one
- // could not be created.
- RenderViewHost* Navigate(const NavigationEntry& entry);
-
- // Instructs the various live views to stop. Called when the user directed the
- // page to stop loading.
- void Stop();
-
- // Notifies the regular and pending RenderViewHosts that a load is or is not
- // happening. Even though the message is only for one of them, we don't know
- // which one so we tell both.
- void SetIsLoading(bool is_loading);
-
- // Whether to close the tab or not when there is a hang during an unload
- // handler. If we are mid-crosssite navigation, then we should proceed
- // with the navigation instead of closing the tab.
- bool ShouldCloseTabOnUnresponsiveRenderer();
-
- // Called when a renderer's main frame navigates.
- void DidNavigateMainFrame(RenderViewHost* render_view_host);
-
- // Allows the TabContents to react when a cross-site response is ready to be
- // delivered to a pending RenderViewHost. We must first run the onunload
- // handler of the old RenderViewHost before we can allow it to proceed.
- void OnCrossSiteResponse(int new_render_process_host_id,
- int new_request_id);
-
- // Notifies that the navigation that initiated a cross-site transition has
- // been canceled.
- void CrossSiteNavigationCanceled();
-
- // Called when a provisional load on the given renderer is aborted.
- void RendererAbortedProvisionalLoad(RenderViewHost* render_view_host);
-
- // Actually implements this RenderViewHostDelegate function for the
- // TabContents.
- void ShouldClosePage(bool proceed);
-
- // Forwards the message to the RenderViewHost, which is the original one.
- void OnJavaScriptMessageBoxClosed(IPC::Message* reply_msg,
- bool success,
- const std::wstring& prompt);
-
- // Forwards this message to the RenderViewHost.
- void OnJavaScriptMessageBoxWindowDestroyed();
-
- // Sets the passed passed interstitial as the currently showing interstitial.
- // |interstitial_page| should be non NULL (use the remove_interstitial_page
- // method to unset the interstitial) and no interstitial page should be set
- // when there is already a non NULL interstitial page set.
- void set_interstitial_page(InterstitialPage* interstitial_page) {
- DCHECK(!interstitial_page_ && interstitial_page);
- interstitial_page_ = interstitial_page;
- }
-
- // Unsets the currently showing interstitial.
- void remove_interstitial_page() {
- DCHECK(interstitial_page_);
- interstitial_page_ = NULL;
- }
-
- // Returns the currently showing interstitial, NULL if no interstitial is
- // showing.
- InterstitialPage* interstitial_page() const {
- return interstitial_page_;
- }
-
- virtual void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details);
-
- private:
- friend class TestTabContents;
-
- // Returns whether this tab should transition to a new renderer for
- // cross-site URLs. Enabled unless we see the --process-per-tab command line
- // switch. Can be overridden in unit tests.
- bool ShouldTransitionCrossSite();
-
- // Returns true if the two navigation entries are incompatible in some way
- // other than site instances. Cases where this can happen include DOM UI
- // to regular web pages. It will cause us to swap RenderViewHosts (and hence
- // RenderProcessHosts) even if the site instance would otherwise be the same.
- // As part of this, we'll also force new SiteInstances and BrowsingInstances.
- // Either of the entries may be NULL.
- bool ShouldSwapProcessesForNavigation(
- const NavigationEntry* cur_entry,
- const NavigationEntry* new_entry) const;
-
- // Returns an appropriate SiteInstance object for the given NavigationEntry,
- // possibly reusing the current SiteInstance.
- // Never called if --process-per-tab is used.
- SiteInstance* GetSiteInstanceForEntry(const NavigationEntry& entry,
- SiteInstance* curr_instance);
-
- // Helper method to create a pending RenderViewHost for a cross-site
- // navigation.
- bool CreatePendingRenderView(SiteInstance* instance);
-
- // Sets the pending RenderViewHost/DOMUI to be the active one. Note that this
- // doesn't require the pending render_view_host_ pointer to be non-NULL, since
- // there could be DOM UI switching as well. Call this for every commit.
- void CommitPending();
-
- // Helper method to terminate the pending RenderViewHost.
- void CancelPending();
-
- RenderViewHost* UpdateRendererStateForNavigate(const NavigationEntry& entry);
-
- // Our delegate, not owned by us. Guaranteed non-NULL.
- Delegate* delegate_;
-
- // Whether a navigation requiring different RenderView's is pending. This is
- // either cross-site request is (in the new process model), or when required
- // for the view type (like view source versus not).
- bool cross_navigation_pending_;
-
- // Implemented by the owner of this class, this delegate is installed into all
- // the RenderViewHosts that we create.
- RenderViewHostDelegate* render_view_delegate_;
-
- // Our RenderView host and its associated DOM UI (if any, will be NULL for
- // non-DOM-UI pages). This object is responsible for all communication with
- // a child RenderView instance.
- RenderViewHost* render_view_host_;
- scoped_ptr<DOMUI> dom_ui_;
-
- // A RenderViewHost used to load a cross-site page. This remains hidden
- // while a cross-site request is pending until it calls DidNavigate. It may
- // have an associated DOM UI, in which case the DOM UI pointer will be non-
- // NULL.
- //
- // The pending_dom_ui may be non-NULL even when the pending_render_view_host_
- // is. This will happen when we're transitioning between two DOM UI pages:
- // the RVH won't be swapped, so the pending pointer will be unused, but there
- // will be a pending DOM UI associated with the navigation.
- RenderViewHost* pending_render_view_host_;
- scoped_ptr<DOMUI> pending_dom_ui_;
-
- // The intersitial page currently shown if any, not own by this class
- // (the InterstitialPage is self-owned, it deletes itself when hidden).
- InterstitialPage* interstitial_page_;
-
- NotificationRegistrar registrar_;
-
- DISALLOW_COPY_AND_ASSIGN(RenderViewHostManager);
-};
-
-// The "details" for a NOTIFY_RENDER_VIEW_HOST_CHANGED notification. The old
-// host can be NULL when the first RenderViewHost is set.
-struct RenderViewHostSwitchedDetails {
- RenderViewHost* old_host;
- RenderViewHost* new_host;
-};
-
-#endif // CHROME_BROWSER_TAB_CONTENTS_RENDER_VIEW_HOST_MANAGER_H_
diff --git a/chrome/browser/tab_contents/render_view_host_manager_unittest.cc b/chrome/browser/tab_contents/render_view_host_manager_unittest.cc
deleted file mode 100644
index 7a4bcc5..0000000
--- a/chrome/browser/tab_contents/render_view_host_manager_unittest.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/renderer_host/test_render_view_host.h"
-#include "chrome/browser/tab_contents/navigation_entry.h"
-#include "chrome/common/render_messages.h"
-#include "chrome/common/url_constants.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class RenderViewHostManagerTest : public RenderViewHostTestHarness {
- public:
- void NavigateActiveAndCommit(const GURL& url) {
- // Note: we navigate the active RenderViewHost because previous navigations
- // won't have committed yet, so NavigateAndCommit does the wrong thing
- // for us.
- controller().LoadURL(url, GURL(), 0);
- active_rvh()->SendNavigate(
- static_cast<MockRenderProcessHost*>(active_rvh()->process())->
- max_page_id() + 1,
- url);
- }
-};
-
-// Tests that when you navigate from the New TabPage to another page, and
-// then do that same thing in another tab, that the two resulting pages have
-// different SiteInstances, BrowsingInstances, and RenderProcessHosts. This is
-// a regression test for bug 9364.
-TEST_F(RenderViewHostManagerTest, NewTabPageProcesses) {
- GURL ntp(chrome::kChromeUINewTabURL);
- GURL dest("http://www.google.com/");
-
- // Navigate our first tab to the new tab page and then to the destination.
- NavigateActiveAndCommit(ntp);
- NavigateActiveAndCommit(dest);
-
- // Make a second tab.
- TestTabContents contents2(profile_.get(), NULL);
-
- // Load the two URLs in the second tab. Note that the first navigation creates
- // a RVH that's not pending (since there is no cross-site transition), so
- // we use the committed one, but the second one is the opposite.
- contents2.controller().LoadURL(ntp, GURL(), PageTransition::LINK);
- static_cast<TestRenderViewHost*>(contents2.render_manager()->
- current_host())->SendNavigate(100, ntp);
- contents2.controller().LoadURL(dest, GURL(), PageTransition::LINK);
- static_cast<TestRenderViewHost*>(contents2.render_manager()->
- pending_render_view_host())->SendNavigate(101, dest);
-
- // The two RVH's should be different in every way.
- EXPECT_NE(active_rvh()->process(), contents2.render_view_host()->process());
- EXPECT_NE(active_rvh()->site_instance(),
- contents2.render_view_host()->site_instance());
- EXPECT_NE(active_rvh()->site_instance()->browsing_instance(),
- contents2.render_view_host()->site_instance()->browsing_instance());
-
- // Navigate both to the new tab page, and verify that they share a
- // SiteInstance.
- NavigateActiveAndCommit(ntp);
-
- contents2.controller().LoadURL(ntp, GURL(), PageTransition::LINK);
- static_cast<TestRenderViewHost*>(contents2.render_manager()->
- pending_render_view_host())->SendNavigate(102, ntp);
-
- EXPECT_EQ(active_rvh()->site_instance(),
- contents2.render_view_host()->site_instance());
-}
-
-// When there is an error with the specified page, renderer exits view-source
-// mode. See WebFrameImpl::DidFail(). We check by this test that
-// EnableViewSourceMode message is sent on every navigation regardless
-// RenderView is being newly created or reused.
-TEST_F(RenderViewHostManagerTest, AlwaysSendEnableViewSourceMode) {
- const GURL kNtpUrl(chrome::kChromeUINewTabURL);
- const GURL kUrl("view-source:http://foo");
-
- // We have to navigate to some page at first since without this, the first
- // navigation will reuse the SiteInstance created by Init(), and the second
- // one will create a new SiteInstance. Because current_instance and
- // new_instance will be different, a new RenderViewHost will be created for
- // the second navigation. We have to avoid this in order to exercise the
- // target code patch.
- NavigateActiveAndCommit(kNtpUrl);
-
- // Navigate.
- controller().LoadURL(kUrl, GURL() /* referer */, PageTransition::TYPED);
- // Simulate response from RenderView for FirePageBeforeUnload.
- rvh()->TestOnMessageReceived(
- ViewHostMsg_ShouldClose_ACK(rvh()->routing_id(), true));
- ASSERT_TRUE(pending_rvh()); // New pending RenderViewHost will be created.
- RenderViewHost* last_rvh = pending_rvh();
- int new_id = static_cast<MockRenderProcessHost*>(pending_rvh()->process())->
- max_page_id() + 1;
- pending_rvh()->SendNavigate(new_id, kUrl);
- EXPECT_EQ(controller().last_committed_entry_index(), 1);
- ASSERT_TRUE(controller().GetLastCommittedEntry());
- EXPECT_TRUE(kUrl == controller().GetLastCommittedEntry()->url());
- EXPECT_FALSE(controller().pending_entry());
- // Because we're using TestTabContents and TestRenderViewHost in this
- // unittest, no one calls TabContents::RenderViewCreated(). So, we see no
- // EnableViewSourceMode message, here.
-
- // Clear queued messages before load.
- process()->sink().ClearMessages();
- // Navigate, again.
- controller().LoadURL(kUrl, GURL() /* referer */, PageTransition::TYPED);
- // The same RenderViewHost should be reused.
- EXPECT_FALSE(pending_rvh());
- EXPECT_TRUE(last_rvh == rvh());
- rvh()->SendNavigate(new_id, kUrl); // The same page_id returned.
- EXPECT_EQ(controller().last_committed_entry_index(), 1);
- EXPECT_FALSE(controller().pending_entry());
- // New message should be sent out to make sure to enter view-source mode.
- EXPECT_TRUE(process()->sink().GetUniqueMessageMatching(
- ViewMsg_EnableViewSourceMode::ID));
-}
diff --git a/chrome/browser/tab_contents/site_instance.cc b/chrome/browser/tab_contents/site_instance.cc
deleted file mode 100644
index a3e2f86..0000000
--- a/chrome/browser/tab_contents/site_instance.cc
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/tab_contents/site_instance.h"
-
-#include "chrome/browser/dom_ui/dom_ui_factory.h"
-#include "chrome/browser/renderer_host/browser_render_process_host.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/common/notification_service.h"
-#include "net/base/registry_controlled_domain.h"
-
-// We treat javascript:, about:crash, about:hang, and about:shorthang as the
-// same site as any URL since they are actually modifiers on existing pages.
-static bool IsURLSameAsAnySiteInstance(const GURL& url) {
- if (!url.is_valid())
- return false;
- return url.SchemeIs(chrome::kJavaScriptScheme) ||
- url.spec() == chrome::kAboutCrashURL ||
- url.spec() == chrome::kAboutHangURL ||
- url.spec() == chrome::kAboutShorthangURL;
-}
-
-SiteInstance::SiteInstance(BrowsingInstance* browsing_instance)
- : browsing_instance_(browsing_instance),
- render_process_host_factory_(NULL),
- process_(NULL),
- max_page_id_(-1),
- has_site_(false) {
- DCHECK(browsing_instance);
-
- registrar_.Add(this, NotificationType::RENDERER_PROCESS_TERMINATED,
- NotificationService::AllSources());
-}
-
-SiteInstance::~SiteInstance() {
- // Now that no one is referencing us, we can safely remove ourselves from
- // the BrowsingInstance. Any future visits to a page from this site
- // (within the same BrowsingInstance) can safely create a new SiteInstance.
- if (has_site_)
- browsing_instance_->UnregisterSiteInstance(this);
-}
-
-RenderProcessHost* SiteInstance::GetProcess() {
- // Create a new process if ours went away or was reused.
- if (!process_) {
- // See if we should reuse an old process
- if (RenderProcessHost::ShouldTryToUseExistingProcessHost())
- process_ = RenderProcessHost::GetExistingProcessHost(
- browsing_instance_->profile(), GetRendererType());
-
- // Otherwise (or if that fails), create a new one.
- if (!process_) {
- if (render_process_host_factory_) {
- process_ = render_process_host_factory_->CreateRenderProcessHost(
- browsing_instance_->profile());
- } else {
- process_ = new BrowserRenderProcessHost(browsing_instance_->profile());
- }
- }
-
- // Make sure the process starts at the right max_page_id
- process_->UpdateMaxPageID(max_page_id_);
- }
- DCHECK(process_);
-
- return process_;
-}
-
-void SiteInstance::SetSite(const GURL& url) {
- // A SiteInstance's site should not change.
- // TODO(creis): When following links or script navigations, we can currently
- // render pages from other sites in this SiteInstance. This will eventually
- // be fixed, but until then, we should still not set the site of a
- // SiteInstance more than once.
- DCHECK(!has_site_);
-
- // Remember that this SiteInstance has been used to load a URL, even if the
- // URL is invalid.
- has_site_ = true;
- site_ = GetSiteForURL(url);
-
- // Now that we have a site, register it with the BrowsingInstance. This
- // ensures that we won't create another SiteInstance for this site within
- // the same BrowsingInstance, because all same-site pages within a
- // BrowsingInstance can script each other.
- browsing_instance_->RegisterSiteInstance(this);
-}
-
-bool SiteInstance::HasRelatedSiteInstance(const GURL& url) {
- return browsing_instance_->HasSiteInstance(url);
-}
-
-SiteInstance* SiteInstance::GetRelatedSiteInstance(const GURL& url) {
- return browsing_instance_->GetSiteInstanceForURL(url);
-}
-
-/*static*/
-SiteInstance* SiteInstance::CreateSiteInstance(Profile* profile) {
- return new SiteInstance(new BrowsingInstance(profile));
-}
-
-/*static*/
-SiteInstance* SiteInstance::CreateSiteInstanceForURL(Profile* profile,
- const GURL& url) {
- // This BrowsingInstance may be deleted if it returns an existing
- // SiteInstance.
- scoped_refptr<BrowsingInstance> instance(new BrowsingInstance(profile));
- return instance->GetSiteInstanceForURL(url);
-}
-
-/*static*/
-GURL SiteInstance::GetSiteForURL(const GURL& url) {
- // URLs with no host should have an empty site.
- GURL site;
-
- // TODO(creis): For many protocols, we should just treat the scheme as the
- // site, since there is no host. e.g., file:, about:, chrome:
-
- // If the url has a host, then determine the site.
- if (url.has_host()) {
- // Only keep the scheme and registered domain as given by GetOrigin. This
- // may also include a port, which we need to drop.
- site = url.GetOrigin();
-
- // Remove port, if any.
- if (site.has_port()) {
- GURL::Replacements rep;
- rep.ClearPort();
- site = site.ReplaceComponents(rep);
- }
-
- // If this URL has a registered domain, we only want to remember that part.
- std::string domain =
- net::RegistryControlledDomainService::GetDomainAndRegistry(url);
- if (!domain.empty()) {
- GURL::Replacements rep;
- rep.SetHostStr(domain);
- site = site.ReplaceComponents(rep);
- }
- }
- return site;
-}
-
-/*static*/
-bool SiteInstance::IsSameWebSite(const GURL& url1, const GURL& url2) {
- // We infer web site boundaries based on the registered domain name of the
- // top-level page and the scheme. We do not pay attention to the port if
- // one is present, because pages served from different ports can still
- // access each other if they change their document.domain variable.
-
- // Some special URLs will match the site instance of any other URL. This is
- // done before checking both of them for validity, since we want these URLs
- // to have the same site instance as even an invalid one.
- if (IsURLSameAsAnySiteInstance(url1) || IsURLSameAsAnySiteInstance(url2))
- return true;
-
- // If either URL is invalid, they aren't part of the same site.
- if (!url1.is_valid() || !url2.is_valid())
- return false;
-
- // If the schemes differ, they aren't part of the same site.
- if (url1.scheme() != url2.scheme())
- return false;
-
- return net::RegistryControlledDomainService::SameDomainOrHost(url1, url2);
-}
-
-RenderProcessHost::Type SiteInstance::GetRendererType() {
- // We may not have a site at this point, which generally means this is a
- // normal navigation.
- if (!has_site_ || !site_.is_valid())
- return RenderProcessHost::TYPE_NORMAL;
-
- if (site_.SchemeIs(chrome::kExtensionScheme))
- return RenderProcessHost::TYPE_EXTENSION;
-
- if (DOMUIFactory::HasDOMUIScheme(site_))
- return RenderProcessHost::TYPE_DOMUI;
-
- return RenderProcessHost::TYPE_NORMAL;
-}
-
-void SiteInstance::Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details) {
- DCHECK(type == NotificationType::RENDERER_PROCESS_TERMINATED);
- RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr();
- if (rph == process_)
- process_ = NULL;
-}
diff --git a/chrome/browser/tab_contents/site_instance.h b/chrome/browser/tab_contents/site_instance.h
deleted file mode 100644
index 81c182d..0000000
--- a/chrome/browser/tab_contents/site_instance.h
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_TAB_CONTENTS_SITE_INSTANCE_H_
-#define CHROME_BROWSER_TAB_CONTENTS_SITE_INSTANCE_H_
-
-#include "chrome/browser/browsing_instance.h"
-#include "chrome/browser/renderer_host/render_process_host.h"
-#include "chrome/common/notification_registrar.h"
-#include "googleurl/src/gurl.h"
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// SiteInstance class
-//
-// A SiteInstance is a data structure that is associated with all pages in a
-// given instance of a web site. Here, a web site is identified by its
-// registered domain name and scheme. An instance includes all pages
-// that are connected (i.e., either a user or a script navigated from one
-// to the other). We represent instances using the BrowsingInstance class.
-//
-// In --process-per-tab, one SiteInstance is created for each tab (i.e., in the
-// TabContents constructor), unless the tab is created by script (i.e., in
-// TabContents::CreateNewView). This corresponds to one process per
-// BrowsingInstance.
-//
-// In process-per-site-instance (the current default process model),
-// SiteInstances are created (1) when the user manually creates a new tab
-// (which also creates a new BrowsingInstance), and (2) when the user navigates
-// across site boundaries (which uses the same BrowsingInstance). If the user
-// navigates within a site, or opens links in new tabs within a site, the same
-// SiteInstance is used.
-//
-// In --process-per-site, we consolidate all SiteInstances for a given site,
-// throughout the entire profile. This ensures that only one process will be
-// dedicated to each site.
-//
-// Each NavigationEntry for a TabContents points to the SiteInstance that
-// rendered it. Each RenderViewHost also points to the SiteInstance that it is
-// associated with. A SiteInstance keeps track of the number of these
-// references and deletes itself when the count goes to zero. This means that
-// a SiteInstance is only live as long as it is accessible, either from new
-// tabs with no NavigationEntries or in NavigationEntries in the history.
-//
-///////////////////////////////////////////////////////////////////////////////
-class SiteInstance : public base::RefCounted<SiteInstance>,
- public NotificationObserver {
- public:
- // Virtual to allow tests to extend it.
- virtual ~SiteInstance();
-
- // Get the BrowsingInstance to which this SiteInstance belongs.
- BrowsingInstance* browsing_instance() { return browsing_instance_; }
-
- // Sets the factory used to create new RenderProcessHosts. This will also be
- // passed on to SiteInstances spawned by this one.
- //
- // The factory must outlive the SiteInstance; ownership is not transferred. It
- // may be NULL, in which case the default BrowserRenderProcessHost will be
- // created (this is the behavior if you don't call this function).
- void set_render_process_host_factory(RenderProcessHostFactory* rph_factory) {
- render_process_host_factory_ = rph_factory;
- }
-
- // Update / Get the max page ID for this SiteInstance.
- void UpdateMaxPageID(int32 page_id) {
- if (page_id > max_page_id_)
- max_page_id_ = page_id;
- }
- int32 max_page_id() const { return max_page_id_; }
-
- // Returns the current process being used to render pages in this
- // SiteInstance. If the process has crashed or otherwise gone away, then
- // this method will create a new process and update our host ID accordingly.
- RenderProcessHost* GetProcess();
-
- // Set / Get the web site that this SiteInstance is rendering pages for.
- // This includes the scheme and registered domain, but not the port. If the
- // URL does not have a valid registered domain, then the full hostname is
- // stored.
- void SetSite(const GURL& url);
- const GURL& site() const { return site_; }
- bool has_site() const { return has_site_; }
-
- // Returns whether there is currently a related SiteInstance (registered with
- // BrowsingInstance) for the site of the given url. If so, we should try to
- // avoid dedicating an unused SiteInstance to it (e.g., in a new tab).
- bool HasRelatedSiteInstance(const GURL& url);
-
- // Gets a SiteInstance for the given URL that shares the current
- // BrowsingInstance, creating a new SiteInstance if necessary. This ensures
- // that a BrowsingInstance only has one SiteInstance per site, so that pages
- // in a BrowsingInstance have the ability to script each other. Callers
- // should ensure that this SiteInstance becomes ref counted, by storing it in
- // a scoped_refptr. (By having this method, we can hide the BrowsingInstance
- // class from the rest of the codebase.)
- // TODO(creis): This may be an argument to build a pass_refptr<T> class, as
- // Darin suggests.
- SiteInstance* GetRelatedSiteInstance(const GURL& url);
-
- // Factory method to create a new SiteInstance. This will create a new
- // new BrowsingInstance, so it should only be used when creating a new tab
- // from scratch (or similar circumstances). Callers should ensure that
- // this SiteInstance becomes ref counted, by storing it in a scoped_refptr.
- //
- // The render process host factory may be NULL. See SiteInstance constructor.
- //
- // TODO(creis): This may be an argument to build a pass_refptr<T> class, as
- // Darin suggests.
- static SiteInstance* CreateSiteInstance(Profile* profile);
-
- // Factory method to get the appropriate SiteInstance for the given URL, in
- // a new BrowsingInstance. Use this instead of CreateSiteInstance when you
- // know the URL, since it allows special site grouping rules to be applied
- // (for example, to group chrome-ui pages into the same instance).
- static SiteInstance* CreateSiteInstanceForURL(Profile* profile,
- const GURL& url);
-
- // Returns the site for the given URL, which includes only the scheme and
- // registered domain. Returns an empty GURL if the URL has no host.
- static GURL GetSiteForURL(const GURL& url);
-
- // Return whether both URLs are part of the same web site, for the purpose of
- // assigning them to processes accordingly. The decision is currently based
- // on the registered domain of the URLs (google.com, bbc.co.uk), as well as
- // the scheme (https, http). This ensures that two pages will be in
- // the same process if they can communicate with other via JavaScript.
- // (e.g., docs.google.com and mail.google.com have DOM access to each other
- // if they both set their document.domain properties to google.com.)
- static bool IsSameWebSite(const GURL& url1, const GURL& url2);
-
- protected:
- friend class BrowsingInstance;
-
- // Create a new SiteInstance. Protected to give access to BrowsingInstance
- // and tests; most callers should use CreateSiteInstance or
- // GetRelatedSiteInstance instead.
- SiteInstance(BrowsingInstance* browsing_instance);
-
- // Returns the type of renderer process this instance belongs in, for grouping
- // purposes.
- RenderProcessHost::Type GetRendererType();
-
- private:
- // NotificationObserver implementation.
- void Observe(NotificationType type,
- const NotificationSource& source,
- const NotificationDetails& details);
-
- NotificationRegistrar registrar_;
-
- // BrowsingInstance to which this SiteInstance belongs.
- scoped_refptr<BrowsingInstance> browsing_instance_;
-
- // Factory for new RenderProcessHosts, not owned by this class. NULL indiactes
- // that the default BrowserRenderProcessHost should be created.
- const RenderProcessHostFactory* render_process_host_factory_;
-
- // Current RenderProcessHost that is rendering pages for this SiteInstance.
- // This pointer will only change once the RenderProcessHost is destructed. It
- // will still remain the same even if the process crashes, since in that
- // scenario the RenderProcessHost remains the same.
- RenderProcessHost* process_;
-
- // The current max_page_id in the SiteInstance's RenderProcessHost. If the
- // rendering process dies, its replacement should start issuing page IDs that
- // are larger than this value.
- int32 max_page_id_;
-
- // The web site that this SiteInstance is rendering pages for.
- GURL site_;
-
- // Whether SetSite has been called.
- bool has_site_;
-
- DISALLOW_EVIL_CONSTRUCTORS(SiteInstance);
-};
-
-#endif // CHROME_BROWSER_TAB_CONTENTS_SITE_INSTANCE_H_
diff --git a/chrome/browser/tab_contents/site_instance_unittest.cc b/chrome/browser/tab_contents/site_instance_unittest.cc
deleted file mode 100644
index 12bb9f9..0000000
--- a/chrome/browser/tab_contents/site_instance_unittest.cc
+++ /dev/null
@@ -1,458 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/string16.h"
-#include "chrome/browser/child_process_security_policy.h"
-#include "chrome/browser/renderer_host/browser_render_process_host.h"
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/renderer_host/test_render_view_host.h"
-#include "chrome/browser/tab_contents/navigation_entry.h"
-#include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/render_messages.h"
-#include "chrome/test/testing_profile.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class SiteInstanceTest : public testing::Test {
- private:
- MessageLoopForUI message_loop_;
-};
-
-namespace {
-
-class TestBrowsingInstance : public BrowsingInstance {
- public:
- TestBrowsingInstance(Profile* profile, int* deleteCounter)
- : BrowsingInstance(profile),
- use_process_per_site(false),
- deleteCounter_(deleteCounter) {
- }
-
- ~TestBrowsingInstance() {
- (*deleteCounter_)++;
- }
-
- // Overrides BrowsingInstance::ShouldUseProcessPerSite so that we can test
- // both alternatives without using command-line switches.
- bool ShouldUseProcessPerSite(const GURL& url) {
- return use_process_per_site;
- }
-
- // Set by individual tests.
- bool use_process_per_site;
-
- private:
- int* deleteCounter_;
-};
-
-
-class TestSiteInstance : public SiteInstance {
- public:
- static TestSiteInstance* CreateTestSiteInstance(Profile* profile,
- int* siteDeleteCounter,
- int* browsingDeleteCounter) {
- TestBrowsingInstance* browsing_instance =
- new TestBrowsingInstance(profile, browsingDeleteCounter);
- return new TestSiteInstance(browsing_instance, siteDeleteCounter);
- }
-
- private:
- TestSiteInstance(BrowsingInstance* browsing_instance, int* deleteCounter)
- : SiteInstance(browsing_instance), deleteCounter_(deleteCounter) {}
- ~TestSiteInstance() {
- (*deleteCounter_)++;
- }
-
- int* deleteCounter_;
-};
-
-} // namespace
-
-// Test to ensure no memory leaks for SiteInstance objects.
-TEST_F(SiteInstanceTest, SiteInstanceDestructor) {
- // The existance of these factories will cause TabContents to create our test
- // one instead of the real one.
- MockRenderProcessHostFactory rph_factory;
- TestRenderViewHostFactory rvh_factory(&rph_factory);
- int siteDeleteCounter = 0;
- int browsingDeleteCounter = 0;
- const GURL url("test:foo");
-
- // Ensure that instances are deleted when their NavigationEntries are gone.
- TestSiteInstance* instance =
- TestSiteInstance::CreateTestSiteInstance(NULL, &siteDeleteCounter,
- &browsingDeleteCounter);
- EXPECT_EQ(0, siteDeleteCounter);
-
- NavigationEntry* e1 = new NavigationEntry(instance, 0, url, GURL(),
- string16(),
- PageTransition::LINK);
-
- // Redundantly setting e1's SiteInstance shouldn't affect the ref count.
- e1->set_site_instance(instance);
- EXPECT_EQ(0, siteDeleteCounter);
-
- // Add a second reference
- NavigationEntry* e2 = new NavigationEntry(instance, 0, url,
- GURL(), string16(),
- PageTransition::LINK);
-
- // Now delete both entries and be sure the SiteInstance goes away.
- delete e1;
- EXPECT_EQ(0, siteDeleteCounter);
- EXPECT_EQ(0, browsingDeleteCounter);
- delete e2;
- EXPECT_EQ(1, siteDeleteCounter);
- // instance is now deleted
- EXPECT_EQ(1, browsingDeleteCounter);
- // browsing_instance is now deleted
-
- // Ensure that instances are deleted when their RenderViewHosts are gone.
- scoped_ptr<TestingProfile> profile(new TestingProfile());
- instance =
- TestSiteInstance::CreateTestSiteInstance(profile.get(),
- &siteDeleteCounter,
- &browsingDeleteCounter);
- {
- TabContents contents(profile.get(), instance, MSG_ROUTING_NONE, NULL);
- EXPECT_EQ(1, siteDeleteCounter);
- EXPECT_EQ(1, browsingDeleteCounter);
- }
-
- // Make sure that we flush any messages related to the above TabContents
- // destruction.
- MessageLoop::current()->RunAllPending();
-
- EXPECT_EQ(2, siteDeleteCounter);
- EXPECT_EQ(2, browsingDeleteCounter);
- // contents is now deleted, along with instance and browsing_instance
-}
-
-// Test that NavigationEntries with SiteInstances can be cloned, but that their
-// SiteInstances can be changed afterwards. Also tests that the ref counts are
-// updated properly after the change.
-TEST_F(SiteInstanceTest, CloneNavigationEntry) {
- int siteDeleteCounter1 = 0;
- int siteDeleteCounter2 = 0;
- int browsingDeleteCounter = 0;
- const GURL url("test:foo");
-
- SiteInstance* instance1 =
- TestSiteInstance::CreateTestSiteInstance(NULL, &siteDeleteCounter1,
- &browsingDeleteCounter);
- SiteInstance* instance2 =
- TestSiteInstance::CreateTestSiteInstance(NULL, &siteDeleteCounter2,
- &browsingDeleteCounter);
-
- NavigationEntry* e1 = new NavigationEntry(instance1, 0, url, GURL(),
- string16(),
- PageTransition::LINK);
- // Clone the entry
- NavigationEntry* e2 = new NavigationEntry(*e1);
-
- // Should be able to change the SiteInstance of the cloned entry.
- e2->set_site_instance(instance2);
-
- // The first SiteInstance should go away after deleting e1, since e2 should
- // no longer be referencing it.
- delete e1;
- EXPECT_EQ(1, siteDeleteCounter1);
- EXPECT_EQ(0, siteDeleteCounter2);
-
- // The second SiteInstance should go away after deleting e2.
- delete e2;
- EXPECT_EQ(1, siteDeleteCounter1);
- EXPECT_EQ(1, siteDeleteCounter2);
-
- // Both BrowsingInstances are also now deleted
- EXPECT_EQ(2, browsingDeleteCounter);
-}
-
-// Test to ensure UpdateMaxPageID is working properly.
-TEST_F(SiteInstanceTest, UpdateMaxPageID) {
- scoped_refptr<SiteInstance> instance(SiteInstance::CreateSiteInstance(NULL));
- EXPECT_EQ(-1, instance->max_page_id());
-
- // Make sure max_page_id_ is monotonically increasing.
- instance->UpdateMaxPageID(3);
- instance->UpdateMaxPageID(1);
- EXPECT_EQ(3, instance->max_page_id());
-}
-
-// Test to ensure GetProcess returns and creates processes correctly.
-TEST_F(SiteInstanceTest, GetProcess) {
- // Ensure that GetProcess returns a process.
- scoped_ptr<TestingProfile> profile(new TestingProfile());
- scoped_ptr<RenderProcessHost> host1;
- scoped_refptr<SiteInstance> instance(
- SiteInstance::CreateSiteInstance(profile.get()));
- host1.reset(instance->GetProcess());
- EXPECT_TRUE(host1.get() != NULL);
-
- // Ensure that GetProcess creates a new process.
- scoped_refptr<SiteInstance> instance2(
- SiteInstance::CreateSiteInstance(profile.get()));
- scoped_ptr<RenderProcessHost> host2(instance2->GetProcess());
- EXPECT_TRUE(host2.get() != NULL);
- EXPECT_NE(host1.get(), host2.get());
-}
-
-// Test to ensure SetSite and site() work properly.
-TEST_F(SiteInstanceTest, SetSite) {
- scoped_refptr<SiteInstance> instance(SiteInstance::CreateSiteInstance(NULL));
- EXPECT_FALSE(instance->has_site());
- EXPECT_TRUE(instance->site().is_empty());
-
- instance->SetSite(GURL("http://www.google.com/index.html"));
- EXPECT_EQ(GURL("http://google.com"), instance->site());
-
- EXPECT_TRUE(instance->has_site());
-}
-
-// Test to ensure GetSiteForURL properly returns sites for URLs.
-TEST_F(SiteInstanceTest, GetSiteForURL) {
- // Pages are irrelevant.
- GURL test_url = GURL("http://www.google.com/index.html");
- EXPECT_EQ(GURL("http://google.com"), SiteInstance::GetSiteForURL(test_url));
-
- // Ports are irrlevant.
- test_url = GURL("https://www.google.com:8080");
- EXPECT_EQ(GURL("https://google.com"), SiteInstance::GetSiteForURL(test_url));
-
- // Javascript URLs have no site.
- test_url = GURL("javascript:foo();");
- EXPECT_EQ(GURL::EmptyGURL(), SiteInstance::GetSiteForURL(test_url));
-
- test_url = GURL("http://foo/a.html");
- EXPECT_EQ(GURL("http://foo"), SiteInstance::GetSiteForURL(test_url));
-
- test_url = GURL("file:///C:/Downloads/");
- EXPECT_EQ(GURL::EmptyGURL(), SiteInstance::GetSiteForURL(test_url));
-
- // TODO(creis): Do we want to special case file URLs to ensure they have
- // either no site or a special "file://" site? We currently return
- // "file://home/" as the site, which seems broken.
- // test_url = GURL("file://home/");
- // EXPECT_EQ(GURL::EmptyGURL(), SiteInstance::GetSiteForURL(test_url));
-}
-
-// Test of distinguishing URLs from different sites. Most of this logic is
-// tested in RegistryControlledDomainTest. This test focuses on URLs with
-// different schemes or ports.
-TEST_F(SiteInstanceTest, IsSameWebSite) {
- GURL url_foo = GURL("http://foo/a.html");
- GURL url_foo2 = GURL("http://foo/b.html");
- GURL url_foo_https = GURL("https://foo/a.html");
- GURL url_foo_port = GURL("http://foo:8080/a.html");
- GURL url_javascript = GURL("javascript:alert(1);");
- GURL url_crash = GURL("about:crash");
- GURL url_hang = GURL("about:hang");
- GURL url_shorthang = GURL("about:shorthang");
-
- // Same scheme and port -> same site.
- EXPECT_TRUE(SiteInstance::IsSameWebSite(url_foo, url_foo2));
-
- // Different scheme -> different site.
- EXPECT_FALSE(SiteInstance::IsSameWebSite(url_foo, url_foo_https));
-
- // Different port -> same site.
- // (Changes to document.domain make renderer ignore the port.)
- EXPECT_TRUE(SiteInstance::IsSameWebSite(url_foo, url_foo_port));
-
- // JavaScript links should be considered same site for anything.
- EXPECT_TRUE(SiteInstance::IsSameWebSite(url_javascript, url_foo));
- EXPECT_TRUE(SiteInstance::IsSameWebSite(url_javascript, url_foo_https));
- EXPECT_TRUE(SiteInstance::IsSameWebSite(url_javascript, url_foo_port));
-
- // The crash/hang URLs should also be treated as same site. (Bug 1143809.)
- EXPECT_TRUE(SiteInstance::IsSameWebSite(url_crash, url_foo));
- EXPECT_TRUE(SiteInstance::IsSameWebSite(url_hang, url_foo));
- EXPECT_TRUE(SiteInstance::IsSameWebSite(url_shorthang, url_foo));
-}
-
-// Test to ensure that there is only one SiteInstance per site in a given
-// BrowsingInstance, when process-per-site is not in use.
-TEST_F(SiteInstanceTest, OneSiteInstancePerSite) {
- int deleteCounter = 0;
- TestBrowsingInstance* browsing_instance =
- new TestBrowsingInstance(NULL, &deleteCounter);
- browsing_instance->use_process_per_site = false;
-
- const GURL url_a1("http://www.google.com/1.html");
- scoped_refptr<SiteInstance> site_instance_a1(
- browsing_instance->GetSiteInstanceForURL(url_a1));
- EXPECT_TRUE(site_instance_a1.get() != NULL);
-
- // A separate site should create a separate SiteInstance.
- const GURL url_b1("http://www.yahoo.com/");
- scoped_refptr<SiteInstance> site_instance_b1(
- browsing_instance->GetSiteInstanceForURL(url_b1));
- EXPECT_NE(site_instance_a1.get(), site_instance_b1.get());
-
- // Getting the new SiteInstance from the BrowsingInstance and from another
- // SiteInstance in the BrowsingInstance should give the same result.
- EXPECT_EQ(site_instance_b1.get(),
- site_instance_a1->GetRelatedSiteInstance(url_b1));
-
- // A second visit to the original site should return the same SiteInstance.
- const GURL url_a2("http://www.google.com/2.html");
- EXPECT_EQ(site_instance_a1.get(),
- browsing_instance->GetSiteInstanceForURL(url_a2));
- EXPECT_EQ(site_instance_a1.get(),
- site_instance_a1->GetRelatedSiteInstance(url_a2));
-
- // A visit to the original site in a new BrowsingInstance (same or different
- // profile) should return a different SiteInstance.
- TestBrowsingInstance* browsing_instance2 =
- new TestBrowsingInstance(NULL, &deleteCounter);
- browsing_instance2->use_process_per_site = false;
- // Ensure the new SiteInstance is ref counted so that it gets deleted.
- scoped_refptr<SiteInstance> site_instance_a2_2(
- browsing_instance2->GetSiteInstanceForURL(url_a2));
- EXPECT_NE(site_instance_a1.get(), site_instance_a2_2.get());
-
- // Should be able to see that we do have SiteInstances.
- EXPECT_TRUE(browsing_instance->HasSiteInstance(
- GURL("http://mail.google.com")));
- EXPECT_TRUE(browsing_instance2->HasSiteInstance(
- GURL("http://mail.google.com")));
- EXPECT_TRUE(browsing_instance->HasSiteInstance(
- GURL("http://mail.yahoo.com")));
-
- // Should be able to see that we don't have SiteInstances.
- EXPECT_FALSE(browsing_instance->HasSiteInstance(
- GURL("https://www.google.com")));
- EXPECT_FALSE(browsing_instance2->HasSiteInstance(
- GURL("http://www.yahoo.com")));
-
- // browsing_instances will be deleted when their SiteInstances are deleted
-}
-
-// Test to ensure that there is only one SiteInstance per site for an entire
-// Profile, if process-per-site is in use.
-TEST_F(SiteInstanceTest, OneSiteInstancePerSiteInProfile) {
- int deleteCounter = 0;
- TestBrowsingInstance* browsing_instance =
- new TestBrowsingInstance(NULL, &deleteCounter);
- browsing_instance->use_process_per_site = true;
-
- const GURL url_a1("http://www.google.com/1.html");
- scoped_refptr<SiteInstance> site_instance_a1(
- browsing_instance->GetSiteInstanceForURL(url_a1));
- EXPECT_TRUE(site_instance_a1.get() != NULL);
-
- // A separate site should create a separate SiteInstance.
- const GURL url_b1("http://www.yahoo.com/");
- scoped_refptr<SiteInstance> site_instance_b1(
- browsing_instance->GetSiteInstanceForURL(url_b1));
- EXPECT_NE(site_instance_a1.get(), site_instance_b1.get());
-
- // Getting the new SiteInstance from the BrowsingInstance and from another
- // SiteInstance in the BrowsingInstance should give the same result.
- EXPECT_EQ(site_instance_b1.get(),
- site_instance_a1->GetRelatedSiteInstance(url_b1));
-
- // A second visit to the original site should return the same SiteInstance.
- const GURL url_a2("http://www.google.com/2.html");
- EXPECT_EQ(site_instance_a1.get(),
- browsing_instance->GetSiteInstanceForURL(url_a2));
- EXPECT_EQ(site_instance_a1.get(),
- site_instance_a1->GetRelatedSiteInstance(url_a2));
-
- // A visit to the original site in a new BrowsingInstance (same profile)
- // should also return the same SiteInstance.
- // This BrowsingInstance doesn't get its own SiteInstance within the test, so
- // it won't be deleted by its children. Thus, we'll keep a ref count to it
- // to make sure it gets deleted.
- scoped_refptr<TestBrowsingInstance> browsing_instance2(
- new TestBrowsingInstance(NULL, &deleteCounter));
- browsing_instance2->use_process_per_site = true;
- EXPECT_EQ(site_instance_a1.get(),
- browsing_instance2->GetSiteInstanceForURL(url_a2));
-
- // A visit to the original site in a new BrowsingInstance (different profile)
- // should return a different SiteInstance.
- scoped_ptr<TestingProfile> profile(new TestingProfile());
- TestBrowsingInstance* browsing_instance3 =
- new TestBrowsingInstance(profile.get(), &deleteCounter);
- browsing_instance3->use_process_per_site = true;
- // Ensure the new SiteInstance is ref counted so that it gets deleted.
- scoped_refptr<SiteInstance> site_instance_a2_3(
- browsing_instance3->GetSiteInstanceForURL(url_a2));
- EXPECT_NE(site_instance_a1.get(), site_instance_a2_3.get());
-
- // Should be able to see that we do have SiteInstances.
- EXPECT_TRUE(browsing_instance->HasSiteInstance(
- GURL("http://mail.google.com"))); // visited before
- EXPECT_TRUE(browsing_instance2->HasSiteInstance(
- GURL("http://mail.google.com"))); // visited before
- EXPECT_TRUE(browsing_instance->HasSiteInstance(
- GURL("http://mail.yahoo.com"))); // visited before
- EXPECT_TRUE(browsing_instance2->HasSiteInstance(
- GURL("http://www.yahoo.com"))); // different BI, but same profile
-
- // Should be able to see that we don't have SiteInstances.
- EXPECT_FALSE(browsing_instance->HasSiteInstance(
- GURL("https://www.google.com"))); // not visited before
- EXPECT_FALSE(browsing_instance3->HasSiteInstance(
- GURL("http://www.yahoo.com"))); // different BI, different profile
-
- // browsing_instances will be deleted when their SiteInstances are deleted
-}
-
-static SiteInstance* CreateSiteInstance(RenderProcessHostFactory* factory,
- const GURL& url) {
- SiteInstance* instance = SiteInstance::CreateSiteInstanceForURL(NULL, url);
- instance->set_render_process_host_factory(factory);
- return instance;
-}
-
-// Test to ensure that pages that require certain privileges are grouped
-// in processes with similar pages.
-TEST_F(SiteInstanceTest, ProcessSharingByType) {
- MockRenderProcessHostFactory rph_factory;
- ChildProcessSecurityPolicy* policy =
- ChildProcessSecurityPolicy::GetInstance();
-
- // Make a bunch of mock renderers so that we hit the limit.
- std::vector<MockRenderProcessHost*> hosts;
- for (size_t i = 0; i < chrome::kMaxRendererProcessCount; ++i)
- hosts.push_back(new MockRenderProcessHost(NULL));
-
- // Create some extension instances and make sure they share a process.
- scoped_refptr<SiteInstance> extension1_instance(
- CreateSiteInstance(&rph_factory, GURL("chrome-extension://foo/bar")));
- policy->Add(extension1_instance->GetProcess()->pid());
- policy->GrantExtensionBindings(extension1_instance->GetProcess()->pid());
-
- scoped_refptr<SiteInstance> extension2_instance(
- CreateSiteInstance(&rph_factory, GURL("chrome-extension://baz/bar")));
-
- scoped_ptr<RenderProcessHost> extension_host(
- extension1_instance->GetProcess());
- EXPECT_EQ(extension1_instance->GetProcess(),
- extension2_instance->GetProcess());
-
- // Create some DOMUI instances and make sure they share a process.
- scoped_refptr<SiteInstance> dom1_instance(
- CreateSiteInstance(&rph_factory, GURL("chrome://newtab")));
- policy->Add(dom1_instance->GetProcess()->pid());
- policy->GrantDOMUIBindings(dom1_instance->GetProcess()->pid());
-
- scoped_refptr<SiteInstance> dom2_instance(
- CreateSiteInstance(&rph_factory, GURL("chrome://history")));
-
- scoped_ptr<RenderProcessHost> dom_host(dom1_instance->GetProcess());
- EXPECT_EQ(dom1_instance->GetProcess(), dom2_instance->GetProcess());
-
- // Make sure none of differing privilege processes are mixed.
- EXPECT_NE(extension1_instance->GetProcess(), dom1_instance->GetProcess());
-
- for (size_t i = 0; i < chrome::kMaxRendererProcessCount; ++i) {
- EXPECT_NE(extension1_instance->GetProcess(), hosts[i]);
- EXPECT_NE(dom1_instance->GetProcess(), hosts[i]);
- }
-
- STLDeleteContainerPointers(hosts.begin(), hosts.end());
-}
diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h
index e675400..0bbaa0b 100644
--- a/chrome/browser/tab_contents/tab_contents.h
+++ b/chrome/browser/tab_contents/tab_contents.h
@@ -23,11 +23,11 @@
#include "chrome/browser/find_notification_details.h"
#include "chrome/browser/shell_dialogs.h"
#include "chrome/browser/renderer_host/render_view_host_delegate.h"
+#include "chrome/browser/renderer_host/render_view_host_manager.h"
#include "chrome/browser/tab_contents/constrained_window.h"
#include "chrome/browser/tab_contents/infobar_delegate.h"
#include "chrome/browser/tab_contents/navigation_controller.h"
#include "chrome/browser/tab_contents/page_navigator.h"
-#include "chrome/browser/tab_contents/render_view_host_manager.h"
#include "chrome/common/gears_api.h"
#include "chrome/common/navigation_types.h"
#include "chrome/common/notification_registrar.h"