diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-29 03:56:51 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-29 03:56:51 +0000 |
commit | 14e60c8d78e36e0d8cd224dd907ebc350c6c4f06 (patch) | |
tree | 74fd3699c2cb4a69373258588747db41dd58d1e5 /chrome/browser/tab_contents | |
parent | e73273b0d0c0d7b77b3f3c095923307bab006938 (diff) | |
download | chromium_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.cc | 2 | ||||
-rw-r--r-- | chrome/browser/tab_contents/navigation_entry.h | 2 | ||||
-rw-r--r-- | chrome/browser/tab_contents/render_view_host_delegate_helper.cc | 2 | ||||
-rw-r--r-- | chrome/browser/tab_contents/render_view_host_manager.cc | 589 | ||||
-rw-r--r-- | chrome/browser/tab_contents/render_view_host_manager.h | 263 | ||||
-rw-r--r-- | chrome/browser/tab_contents/render_view_host_manager_unittest.cc | 116 | ||||
-rw-r--r-- | chrome/browser/tab_contents/site_instance.cc | 191 | ||||
-rw-r--r-- | chrome/browser/tab_contents/site_instance.h | 180 | ||||
-rw-r--r-- | chrome/browser/tab_contents/site_instance_unittest.cc | 458 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents.h | 2 |
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" |