From 1c7fa0a26fed6f48fbb2a7fe5724c5f9143610ff Mon Sep 17 00:00:00 2001 From: "gavinp@chromium.org" Date: Sat, 14 Jul 2012 15:20:42 +0000 Subject: Revert 146735 - Handle interface to prerenders. It broke the windows aura build, which isn't on standard tries. The prerender_manager now returns a PrerenderHandle* when creating a prerender; this is a useful object for canceling the prerender, as well as signaling navigation, etc... BUG=None Review URL: https://chromiumcodereview.appspot.com/10553029 TBR=gavinp@chromium.org Review URL: https://chromiumcodereview.appspot.com/10783013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@146736 0039d316-1c4b-4281-b951-d872f2087c98 --- .../predictors/autocomplete_action_predictor.cc | 19 - .../predictors/autocomplete_action_predictor.h | 24 - chrome/browser/prerender/prerender_browsertest.cc | 140 ++--- chrome/browser/prerender/prerender_contents.cc | 135 +++-- chrome/browser/prerender/prerender_contents.h | 73 +-- chrome/browser/prerender/prerender_final_status.h | 4 +- chrome/browser/prerender/prerender_handle.cc | 71 --- chrome/browser/prerender/prerender_handle.h | 79 --- chrome/browser/prerender/prerender_link_manager.cc | 68 +-- chrome/browser/prerender/prerender_link_manager.h | 14 +- chrome/browser/prerender/prerender_manager.cc | 578 ++++++++++----------- chrome/browser/prerender/prerender_manager.h | 212 ++++---- chrome/browser/prerender/prerender_unittest.cc | 365 ++++--------- chrome/browser/ui/omnibox/omnibox_edit_model.cc | 15 +- chrome/chrome_browser.gypi | 2 - 15 files changed, 660 insertions(+), 1139 deletions(-) delete mode 100644 chrome/browser/prerender/prerender_handle.cc delete mode 100644 chrome/browser/prerender/prerender_handle.h diff --git a/chrome/browser/predictors/autocomplete_action_predictor.cc b/chrome/browser/predictors/autocomplete_action_predictor.cc index 642bc7c..2ac67fa 100644 --- a/chrome/browser/predictors/autocomplete_action_predictor.cc +++ b/chrome/browser/predictors/autocomplete_action_predictor.cc @@ -26,7 +26,6 @@ #include "chrome/browser/predictors/predictor_database.h" #include "chrome/browser/predictors/predictor_database_factory.h" #include "chrome/browser/prerender/prerender_field_trial.h" -#include "chrome/browser/prerender/prerender_handle.h" #include "chrome/browser/prerender/prerender_manager.h" #include "chrome/browser/prerender/prerender_manager_factory.h" #include "chrome/browser/profiles/profile.h" @@ -120,8 +119,6 @@ AutocompleteActionPredictor::~AutocompleteActionPredictor() { main_profile_predictor_->incognito_predictor_ = NULL; else if (incognito_predictor_) incognito_predictor_->main_profile_predictor_ = NULL; - if (prerender_handle_.get()) - prerender_handle_->OnCancel(); } void AutocompleteActionPredictor::RegisterTransitionalMatches( @@ -156,22 +153,6 @@ void AutocompleteActionPredictor::ClearTransitionalMatches() { transitional_matches_.clear(); } -void AutocompleteActionPredictor::StartPrerendering( - const GURL& url, - content::SessionStorageNamespace* session_storage_namespace, - const gfx::Size& size) { - if (prerender_handle_.get()) - prerender_handle_->OnNavigateAway(); - if (prerender::PrerenderManager* prerender_manager = - prerender::PrerenderManagerFactory::GetForProfile(profile_)) { - prerender_handle_.reset( - prerender_manager->AddPrerenderFromOmnibox( - url, session_storage_namespace, size)); - } else { - prerender_handle_.reset(); - } -} - // Given a match, return a recommended action. AutocompleteActionPredictor::Action AutocompleteActionPredictor::RecommendAction( diff --git a/chrome/browser/predictors/autocomplete_action_predictor.h b/chrome/browser/predictors/autocomplete_action_predictor.h index 34a725a..d78ced96 100644 --- a/chrome/browser/predictors/autocomplete_action_predictor.h +++ b/chrome/browser/predictors/autocomplete_action_predictor.h @@ -9,7 +9,6 @@ #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/string16.h" #include "chrome/browser/history/history_types.h" @@ -26,22 +25,10 @@ class HistoryService; class PredictorsHandler; class Profile; -namespace content { -class SessionStorageNamespace; -} - -namespace gfx { -class Size; -} - namespace history { class URLDatabase; } -namespace prerender { -class PrerenderHandle; -} - namespace predictors { // This class is responsible for determining the correct predictive network @@ -91,15 +78,6 @@ class AutocompleteActionPredictor Action RecommendAction(const string16& user_text, const AutocompleteMatch& match) const; - // Begin prerendering |url| with |session_storage_namespace|. The |size| gives - // the initial size for the target prerender. The predictor will run at most - // one prerender at a time, so launching a prerender will cancel our previous - // prerenders (if any). - void StartPrerendering( - const GURL& url, - content::SessionStorageNamespace* session_storage_namespace, - const gfx::Size& size); - // Return true if the suggestion type warrants a TCP/IP preconnection. // i.e., it is now quite likely that the user will select the related domain. static bool IsPreconnectable(const AutocompleteMatch& match); @@ -220,8 +198,6 @@ class AutocompleteActionPredictor // This is cleared after every Omnibox navigation. std::vector transitional_matches_; - scoped_ptr prerender_handle_; - // This allows us to predict the effect of confidence threshold changes on // accuracy. This is cleared after every omnibox navigation. mutable std::vector > tracked_urls_; diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc index 89f278e..104dffc 100644 --- a/chrome/browser/prerender/prerender_browsertest.cc +++ b/chrome/browser/prerender/prerender_browsertest.cc @@ -19,7 +19,6 @@ #include "chrome/browser/favicon/favicon_tab_helper.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/prerender/prerender_contents.h" -#include "chrome/browser/prerender/prerender_handle.h" #include "chrome/browser/prerender/prerender_link_manager.h" #include "chrome/browser/prerender/prerender_link_manager_factory.h" #include "chrome/browser/prerender/prerender_manager.h" @@ -33,7 +32,6 @@ #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tab_contents/tab_contents.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_paths.h" @@ -48,7 +46,6 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/url_constants.h" -#include "content/public/test/test_navigation_observer.h" #include "grit/generated_resources.h" #include "net/base/mock_host_resolver.h" #include "net/url_request/url_request_context.h" @@ -116,11 +113,13 @@ bool ShouldRenderPrerenderedPageCorrectly(FinalStatus status) { case FINAL_STATUS_USED: case FINAL_STATUS_WINDOW_OPENER: case FINAL_STATUS_APP_TERMINATING: + case FINAL_STATUS_FRAGMENT_MISMATCH: case FINAL_STATUS_CACHE_OR_HISTORY_CLEARED: // We'll crash the renderer after it's loaded. case FINAL_STATUS_RENDERER_CRASHED: case FINAL_STATUS_CANCELLED: case FINAL_STATUS_DEVTOOLS_ATTACHED: + case FINAL_STATUS_SESSION_STORAGE_NAMESPACE_MISMATCH: return true; default: return false; @@ -230,15 +229,12 @@ class TestPrerenderContents : public PrerenderContents { } } - virtual void AddPendingPrerender( - base::WeakPtr weak_prerender_handle, - const GURL& url, - const content::Referrer& referrer, - const gfx::Size& size) OVERRIDE { - PrerenderContents::AddPendingPrerender( - weak_prerender_handle, url, referrer, size); + virtual void AddPendingPrerender(const GURL& url, + const content::Referrer& referrer, + const gfx::Size& size) OVERRIDE { + PrerenderContents::AddPendingPrerender(url, referrer, size); if (expected_pending_prerenders_ > 0 && - pending_prerenders().size() == expected_pending_prerenders_) { + pending_prerender_list()->size() == expected_pending_prerenders_) { MessageLoop::current()->Quit(); } } @@ -264,28 +260,13 @@ class TestPrerenderContents : public PrerenderContents { // Waits until the prerender has |expected_pending_prerenders| pending // prerenders. void WaitForPendingPrerenders(size_t expected_pending_prerenders) { - if (pending_prerenders().size() < expected_pending_prerenders) { + if (pending_prerender_list()->size() < expected_pending_prerenders) { expected_pending_prerenders_ = expected_pending_prerenders; ui_test_utils::RunMessageLoop(); expected_pending_prerenders_ = 0; } - EXPECT_EQ(expected_pending_prerenders, pending_prerenders().size()); - } - - bool UrlIsPending(const GURL& url) const { - for (std::vector::const_iterator - it = pending_prerenders().begin(), - end = pending_prerenders().end(); - it != end; - ++it) { - if (it->url == url && it->weak_prerender_handle) { - EXPECT_TRUE(IsPendingEntry(*it->weak_prerender_handle)); - EXPECT_TRUE(it->weak_prerender_handle->IsPending()); - return true; - } - } - return false; + EXPECT_EQ(expected_pending_prerenders, pending_prerender_list()->size()); } // For tests that open the prerender in a new background tab, the RenderView @@ -295,12 +276,6 @@ class TestPrerenderContents : public PrerenderContents { int number_of_loads() const { return number_of_loads_; } - FinalStatus expected_final_status() const { return expected_final_status_; } - - bool quit_message_loop_on_destruction() const { - return quit_message_loop_on_destruction_; - } - private: virtual void OnRenderViewHostCreated( RenderViewHost* new_render_view_host) OVERRIDE { @@ -517,15 +492,6 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { virtual ~PrerenderBrowserTest() {} - content::SessionStorageNamespace* GetSessionStorageNamespace() const { - TabContents* tab_contents = - current_browser()->tab_strip_model()->GetActiveTabContents(); - if (!tab_contents) - return NULL; - return tab_contents->web_contents()->GetRenderViewHost()-> - GetSessionStorageNamespace(); - } - virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { #if defined(ENABLE_SAFE_BROWSING) SafeBrowsingService::RegisterFactory(safe_browsing_factory_.get()); @@ -739,21 +705,17 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { } bool UrlIsInPrerenderManager(const std::string& html_file) const { - return UrlIsInPrerenderManager(test_server()->GetURL(html_file)); + GURL dest_url = test_server()->GetURL(html_file); + return (GetPrerenderManager()->FindEntry(dest_url) != NULL); } - bool UrlIsInPrerenderManager(const GURL& url) const { - return GetPrerenderManager()->FindPrerenderData( - url, GetSessionStorageNamespace()) != NULL; + bool UrlIsInPrerenderManager(const GURL& url) { + return (GetPrerenderManager()->FindEntry(url) != NULL); } - // This only checks to see if the URL is pending in our TestPrerenderContents. - bool UrlIsPending(const std::string& html_file) const { - TestPrerenderContents* test_prerender_contents = GetPrerenderContents(); - if (!test_prerender_contents) - return false; + bool UrlIsPendingInPrerenderManager(const std::string& html_file) const { GURL dest_url = test_server()->GetURL(html_file); - return test_prerender_contents->UrlIsPending(dest_url); + return GetPrerenderManager()->IsPendingEntry(dest_url); } void set_use_https_src(bool use_https_src_server) { @@ -804,11 +766,8 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { #endif TestPrerenderContents* GetPrerenderContents() const { - PrerenderManager::PrerenderData* prerender_data = - GetPrerenderManager()->FindPrerenderData( - dest_url_, GetSessionStorageNamespace()); return static_cast( - prerender_data ? prerender_data->contents() : NULL); + GetPrerenderManager()->FindEntry(dest_url_)); } void set_loader_path(const std::string& path) { @@ -893,15 +852,6 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { prerender_contents_factory_); FinalStatus expected_final_status = expected_final_status_queue.front(); - // We construct launch_nav_observer so that we can be certain our loader - // page has finished loading before continuing. This prevents ambiguous - // NOTIFICATION_LOAD_STOP events from making tests flaky. - WebContents* web_contents = chrome::GetActiveWebContents(current_browser()); - ui_test_utils::WindowedNotificationObserver loader_nav_observer( - content::NOTIFICATION_LOAD_STOP, - content::Source( - &web_contents->GetController())); - // ui_test_utils::NavigateToURL uses its own observer and message loop. // Since the test needs to wait until the prerendered page has stopped // loading, rather than the page directly navigated to, need to @@ -911,9 +861,6 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { false)); ui_test_utils::RunMessageLoop(); - // Now that we've run the prerender until it stopped loading, we can now - // also make sure the launcher has finished loading. - loader_nav_observer.Wait(); TestPrerenderContents* prerender_contents = GetPrerenderContents(); @@ -937,8 +884,7 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { } else { // In the failure case, we should have removed |dest_url_| from the // prerender_manager. We ignore dummy PrerenderContents (as indicated - // by not having started), and PrerenderContents that are expected to - // be left in the manager until the test finishes. + // by not having started). EXPECT_TRUE(prerender_contents == NULL || !prerender_contents->prerendering_has_started()); } @@ -1005,24 +951,12 @@ class PrerenderBrowserTest : virtual public InProcessBrowserTest { RenderViewHost* render_view_host = chrome::GetActiveWebContents(current_browser())->GetRenderViewHost(); - render_view_host->ExecuteJavascriptInWebFrame( - string16(), ASCIIToUTF16(javascript_function_name)); + string16(), + ASCIIToUTF16(javascript_function_name)); - if (prerender_contents->quit_message_loop_on_destruction()) { - // Run message loop until the prerender contents is destroyed. - ui_test_utils::RunMessageLoop(); - } else { - // We don't expect to pick up a running prerender, so instead - // observe one navigation. - content::TestNavigationObserver observer( - content::NotificationService::AllSources(), NULL, 1); - base::RunLoop run_loop; - observer.WaitForObservation( - base::Bind(&ui_test_utils::RunThisRunLoop, - base::Unretained(&run_loop)), - ui_test_utils::GetQuitTaskForRunLoop(&run_loop)); - } + // Run message loop until the prerender contents is destroyed. + ui_test_utils::RunMessageLoop(); } WaitForLoadPrerenderContentsFactory* prerender_contents_factory_; @@ -1505,14 +1439,14 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderInfiniteLoop) { // Next url should be in pending list but not an active entry. EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileB)); - EXPECT_TRUE(UrlIsPending(kHtmlFileB)); + EXPECT_TRUE(UrlIsPendingInPrerenderManager(kHtmlFileB)); NavigateToDestURL(); // Make sure the PrerenderContents for the next url is now in the manager // and not pending. EXPECT_TRUE(UrlIsInPrerenderManager(kHtmlFileB)); - EXPECT_FALSE(UrlIsPending(kHtmlFileB)); + EXPECT_FALSE(UrlIsPendingInPrerenderManager(kHtmlFileB)); } // Checks that we don't prerender in an infinite loop and multiple links are @@ -1540,8 +1474,8 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderInfiniteLoopMultiple) { // Next url should be in pending list but not an active entry. EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileB)); EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileC)); - EXPECT_TRUE(UrlIsPending(kHtmlFileB)); - EXPECT_TRUE(UrlIsPending(kHtmlFileC)); + EXPECT_TRUE(UrlIsPendingInPrerenderManager(kHtmlFileB)); + EXPECT_TRUE(UrlIsPendingInPrerenderManager(kHtmlFileC)); NavigateToDestURL(); @@ -1552,8 +1486,8 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderInfiniteLoopMultiple) { bool url_c_is_active_prerender = UrlIsInPrerenderManager(kHtmlFileC); EXPECT_TRUE((url_b_is_active_prerender || url_c_is_active_prerender) && !(url_b_is_active_prerender && url_c_is_active_prerender)); - EXPECT_FALSE(UrlIsPending(kHtmlFileB)); - EXPECT_FALSE(UrlIsPending(kHtmlFileC)); + EXPECT_FALSE(UrlIsPendingInPrerenderManager(kHtmlFileB)); + EXPECT_FALSE(UrlIsPendingInPrerenderManager(kHtmlFileC)); } // See crbug.com/131836. @@ -1706,7 +1640,7 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderRendererCrash) { IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DISABLED_PrerenderPageNavigateFragment) { PrerenderTestURL("files/prerender/prerender_fragment.html", - FINAL_STATUS_APP_TERMINATING, + FINAL_STATUS_FRAGMENT_MISMATCH, 1); NavigateToURL("files/prerender/prerender_fragment.html#fragment"); } @@ -1717,7 +1651,7 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DISABLED_PrerenderFragmentNavigatePage) { PrerenderTestURL("files/prerender/prerender_fragment.html#fragment", - FINAL_STATUS_APP_TERMINATING, + FINAL_STATUS_FRAGMENT_MISMATCH, 1); NavigateToURL("files/prerender/prerender_fragment.html"); } @@ -1728,7 +1662,7 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DISABLED_PrerenderFragmentNavigateFragment) { PrerenderTestURL("files/prerender/prerender_fragment.html#other_fragment", - FINAL_STATUS_APP_TERMINATING, + FINAL_STATUS_FRAGMENT_MISMATCH, 1); NavigateToURL("files/prerender/prerender_fragment.html#fragment"); } @@ -1740,7 +1674,7 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DISABLED_PrerenderClientRedirectFromFragment) { PrerenderTestURL( CreateClientRedirect("files/prerender/prerender_fragment.html#fragment"), - FINAL_STATUS_APP_TERMINATING, + FINAL_STATUS_FRAGMENT_MISMATCH, 2); NavigateToURL("files/prerender/prerender_fragment.html"); } @@ -1752,7 +1686,7 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DISABLED_PrerenderClientRedirectToFragment) { PrerenderTestURL( CreateClientRedirect("files/prerender/prerender_fragment.html"), - FINAL_STATUS_APP_TERMINATING, + FINAL_STATUS_FRAGMENT_MISMATCH, 2); NavigateToURL("files/prerender/prerender_fragment.html#fragment"); } @@ -1914,7 +1848,7 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPrint) { IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSameDomainWindowOpenerWindowOpen) { PrerenderTestURL("files/prerender/prerender_page.html", - FINAL_STATUS_APP_TERMINATING, + FINAL_STATUS_WINDOW_OPENER, 1); OpenDestURLViaWindowOpen(); } @@ -1924,7 +1858,7 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSameDomainWindowOpenerClickTarget) { PrerenderTestURL("files/prerender/prerender_page.html", - FINAL_STATUS_APP_TERMINATING, + FINAL_STATUS_WINDOW_OPENER, 1); OpenDestURLViaClickTarget(); } @@ -2207,21 +2141,21 @@ IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickNewWindow) { PrerenderTestURL("files/prerender/prerender_page_with_link.html", - FINAL_STATUS_APP_TERMINATING, + FINAL_STATUS_SESSION_STORAGE_NAMESPACE_MISMATCH, 1); OpenDestURLViaClickNewWindow(); } IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickNewForegroundTab) { PrerenderTestURL("files/prerender/prerender_page_with_link.html", - FINAL_STATUS_APP_TERMINATING, + FINAL_STATUS_SESSION_STORAGE_NAMESPACE_MISMATCH, 1); OpenDestURLViaClickNewForegroundTab(); } IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickNewBackgroundTab) { PrerenderTestURL("files/prerender/prerender_page_with_link.html", - FINAL_STATUS_APP_TERMINATING, + FINAL_STATUS_SESSION_STORAGE_NAMESPACE_MISMATCH, 1); OpenDestURLViaClickNewBackgroundTab(); } diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc index 0b3e1b9..6267ec2 100644 --- a/chrome/browser/prerender/prerender_contents.cc +++ b/chrome/browser/prerender/prerender_contents.cc @@ -5,7 +5,6 @@ #include "chrome/browser/prerender/prerender_contents.h" #include -#include #include #include "base/process_util.h" @@ -13,7 +12,6 @@ #include "chrome/browser/history/history_tab_helper.h" #include "chrome/browser/history/history_types.h" #include "chrome/browser/prerender/prerender_final_status.h" -#include "chrome/browser/prerender/prerender_handle.h" #include "chrome/browser/prerender/prerender_manager.h" #include "chrome/browser/prerender/prerender_render_view_host_observer.h" #include "chrome/browser/prerender/prerender_tracker.h" @@ -28,7 +26,6 @@ #include "content/public/browser/notification_service.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" -#include "content/public/browser/session_storage_namespace.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/browser/web_contents_view.h" @@ -38,13 +35,29 @@ using content::DownloadItem; using content::OpenURLParams; using content::RenderViewHost; using content::ResourceRedirectDetails; -using content::SessionStorageNamespace; using content::WebContents; namespace prerender { namespace { +// Compares URLs ignoring any ref for the purposes of matching URLs when +// prerendering. +struct PrerenderURLPredicate { + explicit PrerenderURLPredicate(const GURL& url) + : url_(url) { + } + + bool operator()(const GURL& url) const { + return url.scheme() == url_.scheme() && + url.host() == url_.host() && + url.port() == url_.port() && + url.path() == url_.path() && + url.query() == url_.query(); + } + GURL url_; +}; + // Tells the render process at |child_id| whether |url| is a new prerendered // page, or whether |url| is being removed as a prerendered page. Currently // this will only inform the render process that created the prerendered page @@ -81,6 +94,24 @@ class PrerenderContentsFactoryImpl : public PrerenderContents::Factory { } }; +struct PrerenderContents::PendingPrerenderInfo { + PendingPrerenderInfo(const GURL& url, + const content::Referrer& referrer, + const gfx::Size& size); + const GURL url; + const content::Referrer referrer; + const gfx::Size size; +}; + +PrerenderContents::PendingPrerenderInfo::PendingPrerenderInfo( + const GURL& url, + const content::Referrer& referrer, + const gfx::Size& size) + : url(url), + referrer(referrer), + size(size) { +} + // TabContentsDelegateImpl ----------------------------------------------------- class PrerenderContents::TabContentsDelegateImpl @@ -92,7 +123,7 @@ class PrerenderContents::TabContentsDelegateImpl // content::WebContentsDelegate implementation: virtual WebContents* OpenURLFromTab(WebContents* source, - const OpenURLParams& params) OVERRIDE { + const OpenURLParams& params) OVERRIDE { // |OpenURLFromTab| is typically called when a frame performs a navigation // that requires the browser to perform the transition instead of WebKit. // Examples include prerendering a site that redirects to an app URL, @@ -188,61 +219,34 @@ class PrerenderContents::TabContentsDelegateImpl PrerenderContents* prerender_contents_; }; -void PrerenderContents::AddPendingPrerender( - const base::WeakPtr weak_prerender_handle, - const GURL& url, - const content::Referrer& referrer, - const gfx::Size& size) { - pending_prerenders_.push_back( - PendingPrerenderInfo(weak_prerender_handle, url, referrer, size)); +void PrerenderContents::AddPendingPrerender(const GURL& url, + const content::Referrer& referrer, + const gfx::Size& size) { + pending_prerender_list_.push_back(PendingPrerenderInfo(url, referrer, size)); } -bool PrerenderContents::IsPendingEntry( - const PrerenderHandle& prerender_handle) const { - for (std::vector::const_iterator it = - pending_prerenders_.begin(); - it != pending_prerenders_.end(); +bool PrerenderContents::IsPendingEntry(const GURL& url) const { + for (PendingPrerenderList::const_iterator it = + pending_prerender_list_.begin(); + it != pending_prerender_list_.end(); ++it) { - if (it->weak_prerender_handle.get() == &prerender_handle) + if (it->url == url) return true; } return false; } void PrerenderContents::StartPendingPrerenders() { - SessionStorageNamespace* session_storage_namespace = NULL; - if (RenderViewHost* render_view_host = GetRenderViewHostMutable()) - session_storage_namespace = render_view_host->GetSessionStorageNamespace(); - DCHECK(child_id_ == -1 || session_storage_namespace); - - std::vector pending_prerender_list; - pending_prerender_list.swap(pending_prerenders_); - for (std::vector::iterator it = - pending_prerender_list.begin(); + PendingPrerenderList pending_prerender_list; + pending_prerender_list.swap(pending_prerender_list_); + for (PendingPrerenderList::iterator it = pending_prerender_list.begin(); it != pending_prerender_list.end(); ++it) { - if (it->weak_prerender_handle && it->weak_prerender_handle->IsValid()) { - prerender_manager_->StartPendingPrerender( - it->weak_prerender_handle.get(), ORIGIN_LINK_REL_PRERENDER, child_id_, - it->url, it->referrer, it->size, session_storage_namespace); - } + prerender_manager_->AddPrerenderFromLinkRelPrerender( + child_id_, route_id_, it->url, it->referrer, it->size); } } -PrerenderContents::PendingPrerenderInfo::PendingPrerenderInfo( - const base::WeakPtr weak_prerender_handle, - const GURL& url, - const content::Referrer& referrer, - const gfx::Size& size) - : weak_prerender_handle(weak_prerender_handle), - url(url), - referrer(referrer), - size(size) { -} - -PrerenderContents::PendingPrerenderInfo::~PendingPrerenderInfo() { -} - PrerenderContents::PrerenderContents( PrerenderManager* prerender_manager, PrerenderTracker* prerender_tracker, @@ -258,7 +262,6 @@ PrerenderContents::PrerenderContents( referrer_(referrer), profile_(profile), page_id_(0), - session_storage_namespace_id_(-1), has_stopped_loading_(false), has_finished_loading_(false), final_status_(FINAL_STATUS_MAX), @@ -272,13 +275,6 @@ PrerenderContents::PrerenderContents( DCHECK(prerender_manager != NULL); } -void PrerenderContents::MakeIntoDummyReplacementOf( - const PrerenderContents* original_prerender_contents) { - load_start_time_ = original_prerender_contents->load_start_time_; - session_storage_namespace_id_ = - original_prerender_contents->session_storage_namespace_id_; -} - bool PrerenderContents::Init() { return AddAliasURL(prerender_url_); } @@ -291,7 +287,7 @@ PrerenderContents::Factory* PrerenderContents::CreateFactory() { void PrerenderContents::StartPrerendering( int creator_child_id, const gfx::Size& size, - SessionStorageNamespace* session_storage_namespace, + content::SessionStorageNamespace* session_storage_namespace, bool is_control_group) { DCHECK(profile_ != NULL); DCHECK(!size.IsEmpty()); @@ -302,15 +298,11 @@ void PrerenderContents::StartPrerendering( DCHECK_EQ(1U, alias_urls_.size()); creator_child_id_ = creator_child_id; - session_storage_namespace_id_ = session_storage_namespace->id(); size_ = size; InformRenderProcessAboutPrerender(prerender_url_, true, creator_child_id_); - DCHECK(load_start_time_.is_null()); - load_start_time_ = base::TimeTicks::Now(); - // Everything after this point sets up the WebContents object and associated // RenderView for the prerender page. Don't do this for members of the // control group. @@ -366,6 +358,9 @@ void PrerenderContents::StartPrerendering( this, content::NOTIFICATION_RESOURCE_RECEIVED_REDIRECT, content::Source(GetWebContents())); + DCHECK(load_start_time_.is_null()); + load_start_time_ = base::TimeTicks::Now(); + // Transfer over the user agent override. new_contents->SetUserAgentOverride( prerender_manager_->config().user_agent_override); @@ -499,7 +494,7 @@ void PrerenderContents::OnRenderViewHostCreated( } WebContents* PrerenderContents::CreateWebContents( - SessionStorageNamespace* session_storage_namespace) { + content::SessionStorageNamespace* session_storage_namespace) { return WebContents::Create(profile_, NULL, MSG_ROUTING_NONE, NULL, session_storage_namespace); } @@ -551,15 +546,17 @@ void PrerenderContents::AddAliasURLsFromOtherPrerenderContents( } } -bool PrerenderContents::Matches( - const GURL& url, - const SessionStorageNamespace* session_storage_namespace) const { - DCHECK(child_id_ == -1 || session_storage_namespace); - if (session_storage_namespace && - session_storage_namespace_id_ != session_storage_namespace->id()) - return false; - return std::count_if(alias_urls_.begin(), alias_urls_.end(), - std::bind2nd(std::equal_to(), url)) != 0; +bool PrerenderContents::MatchesURL(const GURL& url, GURL* matching_url) const { + std::vector::const_iterator matching_url_iterator = + std::find_if(alias_urls_.begin(), + alias_urls_.end(), + PrerenderURLPredicate(url)); + if (matching_url_iterator != alias_urls_.end()) { + if (matching_url) + *matching_url = *matching_url_iterator; + return true; + } + return false; } void PrerenderContents::RenderViewGone(base::TerminationStatus status) { diff --git a/chrome/browser/prerender/prerender_contents.h b/chrome/browser/prerender/prerender_contents.h index 7b0a914..50bc771 100644 --- a/chrome/browser/prerender/prerender_contents.h +++ b/chrome/browser/prerender/prerender_contents.h @@ -5,12 +5,12 @@ #ifndef CHROME_BROWSER_PRERENDER_PRERENDER_CONTENTS_H_ #define CHROME_BROWSER_PRERENDER_PRERENDER_CONTENTS_H_ +#include #include #include #include #include "base/memory/scoped_ptr.h" -#include "base/memory/weak_ptr.h" #include "base/time.h" #include "base/values.h" #include "chrome/browser/prerender/prerender_final_status.h" @@ -36,7 +36,6 @@ class WebContents; namespace prerender { -class PrerenderHandle; class PrerenderManager; class PrerenderRenderViewHostObserver; class PrerenderTracker; @@ -66,6 +65,10 @@ class PrerenderContents : public content::NotificationObserver, DISALLOW_COPY_AND_ASSIGN(Factory); }; + // Information on pages that the prerendered page has tried to prerender. + struct PendingPrerenderInfo; + typedef std::list PendingPrerenderList; + // Indicates how this PrerenderContents relates to MatchComplete. This is to // figure out which histograms to use to record the FinalStatus, Match (record // all prerenders and control group prerenders) or MatchComplete (record @@ -76,7 +79,7 @@ class PrerenderContents : public content::NotificationObserver, // MatchComplete. MATCH_COMPLETE_DEFAULT, // A prerender that used to be a regular prerender, but has since been - // replaced by a MatchComplete dummy. Therefore, we will record this only + // replaced by a MatchComplete dummy. Therefore, we will record this only // for Match, but not for MatchComplete. MATCH_COMPLETE_REPLACED, // A prerender that is a MatchComplete dummy replacing a regular prerender. @@ -91,12 +94,6 @@ class PrerenderContents : public content::NotificationObserver, virtual ~PrerenderContents(); - // For MatchComplete correctness, create a dummy replacement prerender - // contents to stand in for this prerender contents that (which we are about - // to destroy). - void MakeIntoDummyReplacementOf( - const PrerenderContents* original_prerender_contents); - bool Init(); static Factory* CreateFactory(); @@ -158,10 +155,11 @@ class PrerenderContents : public content::NotificationObserver, base::TimeTicks load_start_time() const { return load_start_time_; } // Indicates whether this prerendered page can be used for the provided - // |url| and |session_storage_namespace|. - bool Matches( - const GURL& url, - const content::SessionStorageNamespace* session_storage_namespace) const; + // URL, i.e. whether there is a match. |matching_url| is optional and will be + // set to the URL that is found as a match if it is provided. + // TODO(gavinp,mmenke): Rework matching to be based on both the URL + // and the session WebStorage. + bool MatchesURL(const GURL& url, GURL* matching_url) const; // content::WebContentsObserver implementation. virtual void DidStopLoading() OVERRIDE; @@ -213,37 +211,19 @@ class PrerenderContents : public content::NotificationObserver, // MouseEvent being dispatched by a link to a website installed as an app. bool IsCrossSiteNavigationPending() const; - // Adds a pending prerender to the list. If |weak_prerender_handle| still - // exists when this page is made visible, it will be launched. - virtual void AddPendingPrerender( - base::WeakPtr weak_prerender_handle, - const GURL& url, - const content::Referrer& referrer, - const gfx::Size& size); + // Adds a pending prerender to the list. + virtual void AddPendingPrerender(const GURL& url, + const content::Referrer& referrer, + const gfx::Size& size); // Returns true if |url| corresponds to a pending prerender. - bool IsPendingEntry(const PrerenderHandle& prerender_handle) const; + bool IsPendingEntry(const GURL& url) const; // Reissues any pending prerender requests from the prerendered page. Also // clears the list of pending requests. void StartPendingPrerenders(); protected: - // Information on pages that the prerendered page has tried to prerender. - struct PendingPrerenderInfo { - PendingPrerenderInfo( - base::WeakPtr weak_prerender_handle, - const GURL& url, - const content::Referrer& referrer, - const gfx::Size& size); - ~PendingPrerenderInfo(); - - base::WeakPtr weak_prerender_handle; - GURL url; - content::Referrer referrer; - gfx::Size size; - }; - PrerenderContents(PrerenderManager* prerender_manager, PrerenderTracker* prerender_tracker, Profile* profile, @@ -261,8 +241,8 @@ class PrerenderContents : public content::NotificationObserver, return notification_registrar_; } - const std::vector& pending_prerenders() const { - return pending_prerenders_; + const PendingPrerenderList* pending_prerender_list() const { + return &pending_prerender_list_; } bool prerendering_has_been_cancelled() const { @@ -274,11 +254,6 @@ class PrerenderContents : public content::NotificationObserver, bool prerendering_has_started_; - // Time at which we started to load the URL. This is used to compute - // the time elapsed from initiating a prerender until the time the - // (potentially only partially) prerendered page is shown to the user. - base::TimeTicks load_start_time_; - private: class TabContentsDelegateImpl; @@ -327,11 +302,6 @@ class PrerenderContents : public content::NotificationObserver, // such as HTTP redirects or javascript redirects. std::vector alias_urls_; - // The session storage namespace id for use in matching. We must save it - // rather than get it from the RenderViewHost since in the control group - // we won't have a RenderViewHost. - int64 session_storage_namespace_id_; - bool has_stopped_loading_; // True when the main frame has finished loading. @@ -350,6 +320,11 @@ class PrerenderContents : public content::NotificationObserver, // Used solely to prevent double deletion. bool prerendering_has_been_cancelled_; + // Time at which we started to load the URL. This is used to compute + // the time elapsed from initiating a prerender until the time the + // (potentially only partially) prerendered page is shown to the user. + base::TimeTicks load_start_time_; + // Process Metrics of the render process associated with the // RenderViewHost for this object. scoped_ptr process_metrics_; @@ -372,7 +347,7 @@ class PrerenderContents : public content::NotificationObserver, uint8 experiment_id_; // List of all pages the prerendered page has tried to prerender. - std::vector pending_prerenders_; + PendingPrerenderList pending_prerender_list_; // The process that created the child id. int creator_child_id_; diff --git a/chrome/browser/prerender/prerender_final_status.h b/chrome/browser/prerender/prerender_final_status.h index 1ad3508..9bad336 100644 --- a/chrome/browser/prerender/prerender_final_status.h +++ b/chrome/browser/prerender/prerender_final_status.h @@ -41,14 +41,14 @@ enum FinalStatus { FINAL_STATUS_WINDOW_OPENER = 26, // Obsolete: FINAL_STATUS_PAGE_ID_CONFLICT = 27, FINAL_STATUS_SAFE_BROWSING = 28, - // Obsolete: FINAL_STATUS_FRAGMENT_MISMATCH = 29, + FINAL_STATUS_FRAGMENT_MISMATCH = 29, FINAL_STATUS_SSL_CLIENT_CERTIFICATE_REQUESTED = 30, FINAL_STATUS_CACHE_OR_HISTORY_CLEARED = 31, FINAL_STATUS_CANCELLED = 32, FINAL_STATUS_SSL_ERROR = 33, FINAL_STATUS_CROSS_SITE_NAVIGATION_PENDING = 34, FINAL_STATUS_DEVTOOLS_ATTACHED = 35, - // Obsolete: FINAL_STATUS_SESSION_STORAGE_NAMESPACE_MISMATCH = 36, + FINAL_STATUS_SESSION_STORAGE_NAMESPACE_MISMATCH = 36, // Obsolete: FINAL_STATUS_NO_USE_GROUP = 37, // Obsolete: FINAL_STATUS_MATCH_COMPLETE_DUMMY = 38, FINAL_STATUS_DUPLICATE = 39, diff --git a/chrome/browser/prerender/prerender_handle.cc b/chrome/browser/prerender/prerender_handle.cc deleted file mode 100644 index 24de791..0000000 --- a/chrome/browser/prerender/prerender_handle.cc +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2012 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/prerender/prerender_handle.h" - -#include - -#include "chrome/browser/prerender/prerender_contents.h" - -namespace prerender { - -PrerenderHandle::~PrerenderHandle() { - DCHECK(!IsValid()); - // This shouldn't occur, but we also shouldn't leak if it does. - if (IsValid()) - OnCancel(); -} - -void PrerenderHandle::OnNavigateAway() { - DCHECK(CalledOnValidThread()); - if (!IsValid()) - return; - prerender_data_->OnNavigateAwayByHandle(); - prerender_data_.reset(); -} - -void PrerenderHandle::OnCancel() { - DCHECK(CalledOnValidThread()); - if (!IsValid()) - return; - prerender_data_->OnCancelByHandle(); - prerender_data_.reset(); -} - -bool PrerenderHandle::IsValid() const { - return prerender_data_ != NULL; -} - -bool PrerenderHandle::IsPending() const { - DCHECK(CalledOnValidThread()); - return prerender_data_ && !prerender_data_->contents(); -} - -bool PrerenderHandle::IsPrerendering() const { - DCHECK(CalledOnValidThread()); - return prerender_data_ && prerender_data_->contents(); -} - -bool PrerenderHandle::IsFinishedLoading() const { - DCHECK(CalledOnValidThread()); - if (!prerender_data_ || IsPending()) - return false; - return prerender_data_->contents()->has_finished_loading(); -} - -PrerenderHandle::PrerenderHandle( - PrerenderManager::PrerenderData* prerender_data) - : prerender_data_(prerender_data->AsWeakPtr()), - weak_ptr_factory_(this) { - prerender_data->OnNewHandle(); -} - -void PrerenderHandle::SwapPrerenderDataWith( - PrerenderHandle* other_prerender_handle) { - DCHECK(CalledOnValidThread()); - DCHECK(other_prerender_handle); - std::swap(prerender_data_, other_prerender_handle->prerender_data_); -} - -} // namespace prerender diff --git a/chrome/browser/prerender/prerender_handle.h b/chrome/browser/prerender/prerender_handle.h deleted file mode 100644 index 90a9dcc..0000000 --- a/chrome/browser/prerender/prerender_handle.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2012 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_PRERENDER_PRERENDER_HANDLE_H_ -#define CHROME_BROWSER_PRERENDER_PRERENDER_HANDLE_H_ - -#include "base/basictypes.h" -#include "base/memory/weak_ptr.h" -#include "base/threading/non_thread_safe.h" -#include "chrome/browser/prerender/prerender_manager.h" - -class GURL; - -namespace content { -class SessionStorageNamespace; -} - -namespace prerender { - -class PrerenderContents; - -// A class representing a running prerender to a client of the PrerenderManager. -// Methods on PrerenderManager which start prerenders return a caller-owned -// PrerenderHandle* to the client (or NULL if they are unable to start a -// prerender). Because the PrerenderManager can stop running prerenders at any -// time, callers may wish to check PrerenderHandle::IsValid() before operating -// on their prerenders. -class PrerenderHandle : public base::NonThreadSafe { - public: - // Before calling the destructor, the caller must invalidate the handle by - // calling either OnNavigateAway or OnCancel. - ~PrerenderHandle(); - - // The launcher is navigating away from the context that launched this - // prerender. The prerender will likely stay alive briefly though, in case we - // are going through a redirect chain that will target it. This call - // invalidates the handle. If the prerender handle is already invalid, this - // call does nothing. - void OnNavigateAway(); - - // The launcher has taken explicit action to remove this prerender (for - // instance, removing a link element from a document). This call invalidates - // the handle. If the prerender handle is already invalid, this call does - // nothing. - void OnCancel(); - - // True if the prerender handle is still connected to a (pending or running) - // prerender. Handles can become invalid through explicit requests by the - // client, such as calling OnCancel() or OnNavigateAway(), and handles - // also become invalid when the PrerenderManager cancels prerenders. - bool IsValid() const; - - // True if this prerender was launched by a page that was itself being - // prerendered, and so has not yet been started. - bool IsPending() const; - - // True if this prerender is currently active. - bool IsPrerendering() const; - - // True if we started a prerender, and it has finished loading. - bool IsFinishedLoading() const; - - private: - friend class PrerenderManager; - - explicit PrerenderHandle(PrerenderManager::PrerenderData* prerender_data); - - void SwapPrerenderDataWith(PrerenderHandle* other_prerender_handle); - - base::WeakPtr prerender_data_; - base::WeakPtrFactory weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(PrerenderHandle); -}; - -} // namespace prerender - -#endif // CHROME_BROWSER_PRERENDER_PRERENDER_HANDLE_H_ diff --git a/chrome/browser/prerender/prerender_link_manager.cc b/chrome/browser/prerender/prerender_link_manager.cc index 27793ee..c12e6cc 100644 --- a/chrome/browser/prerender/prerender_link_manager.cc +++ b/chrome/browser/prerender/prerender_link_manager.cc @@ -9,7 +9,6 @@ #include #include "chrome/browser/prerender/prerender_contents.h" -#include "chrome/browser/prerender/prerender_handle.h" #include "chrome/browser/prerender/prerender_manager.h" #include "chrome/browser/prerender/prerender_manager_factory.h" #include "chrome/browser/profiles/profile.h" @@ -30,13 +29,6 @@ PrerenderLinkManager::PrerenderLinkManager(PrerenderManager* manager) } PrerenderLinkManager::~PrerenderLinkManager() { - for (IdPairToPrerenderHandleMap::iterator it = ids_to_handle_map_.begin(); - it != ids_to_handle_map_.end(); - ++it) { - PrerenderHandle* prerender_handle = it->second; - prerender_handle->OnCancel(); - delete prerender_handle; - } } bool PrerenderLinkManager::OnAddPrerender(int child_id, @@ -52,28 +44,20 @@ bool PrerenderLinkManager::OnAddPrerender(int child_id, << ", size = (" << size.width() << ", " << size.height() << ")" << ", render_view_route_id = " << render_view_route_id; - const ChildAndPrerenderIdPair child_and_prerender_id(child_id, prerender_id); - DCHECK_EQ(0U, ids_to_handle_map_.count(child_and_prerender_id)); - // TODO(gavinp): Add tests to ensure fragments work, then remove this fragment // clearing code. url_canon::Replacements replacements; replacements.ClearRef(); const GURL url = orig_url.ReplaceComponents(replacements); - scoped_ptr prerender_handle( - manager_->AddPrerenderFromLinkRelPrerender( - child_id, render_view_route_id, url, referrer, size)); - if (prerender_handle.get()) { - std::pair insert_result = - ids_to_handle_map_.insert(IdPairToPrerenderHandleMap::value_type( - child_and_prerender_id, NULL)); - DCHECK(insert_result.second); - delete insert_result.first->second; - insert_result.first->second = prerender_handle.release(); - return true; + if (!manager_->AddPrerenderFromLinkRelPrerender( + child_id, render_view_route_id, url, referrer, size)) { + return false; } - return false; + const ChildAndPrerenderIdPair child_and_prerender_id(child_id, prerender_id); + DCHECK_EQ(0U, ids_to_url_map_.count(child_and_prerender_id)); + ids_to_url_map_.insert(std::make_pair(child_and_prerender_id, url)); + return true; } // TODO(gavinp): Once an observer interface is provided down to the WebKit @@ -85,28 +69,24 @@ void PrerenderLinkManager::OnCancelPrerender(int child_id, int prerender_id) { DVLOG(2) << "OnCancelPrerender, child_id = " << child_id << ", prerender_id = " << prerender_id; const ChildAndPrerenderIdPair child_and_prerender_id(child_id, prerender_id); - IdPairToPrerenderHandleMap::iterator id_to_handle_iter = - ids_to_handle_map_.find(child_and_prerender_id); - if (id_to_handle_iter == ids_to_handle_map_.end()) { + IdPairToUrlMap::iterator id_url_iter = + ids_to_url_map_.find(child_and_prerender_id); + if (id_url_iter == ids_to_url_map_.end()) { DVLOG(5) << "... canceling a prerender that doesn't exist."; return; } - PrerenderHandle* prerender_handle = id_to_handle_iter->second; - prerender_handle->OnCancel(); - RemovePrerender(id_to_handle_iter); + const GURL url = id_url_iter->second; + ids_to_url_map_.erase(id_url_iter); + manager_->MaybeCancelPrerender(url); } void PrerenderLinkManager::OnAbandonPrerender(int child_id, int prerender_id) { DVLOG(2) << "OnAbandonPrerender, child_id = " << child_id << ", prerender_id = " << prerender_id; + // TODO(gavinp,cbentzel): Implement reasonable behaviour for + // navigation away from launcher. const ChildAndPrerenderIdPair child_and_prerender_id(child_id, prerender_id); - IdPairToPrerenderHandleMap::iterator id_to_handle_iter = - ids_to_handle_map_.find(child_and_prerender_id); - if (id_to_handle_iter == ids_to_handle_map_.end()) - return; - PrerenderHandle* prerender_handle = id_to_handle_iter->second; - prerender_handle->OnNavigateAway(); - RemovePrerender(id_to_handle_iter); + ids_to_url_map_.erase(child_and_prerender_id); } void PrerenderLinkManager::OnChannelClosing(int child_id) { @@ -116,9 +96,9 @@ void PrerenderLinkManager::OnChannelClosing(int child_id) { const ChildAndPrerenderIdPair child_and_maximum_prerender_id( child_id, std::numeric_limits::max()); std::queue prerender_ids_to_abandon; - for (IdPairToPrerenderHandleMap::iterator - i = ids_to_handle_map_.lower_bound(child_and_minimum_prerender_id), - e = ids_to_handle_map_.upper_bound(child_and_maximum_prerender_id); + for (IdPairToUrlMap::iterator + i = ids_to_url_map_.lower_bound(child_and_minimum_prerender_id), + e = ids_to_url_map_.upper_bound(child_and_maximum_prerender_id); i != e; ++i) { prerender_ids_to_abandon.push(i->first.second); } @@ -131,14 +111,8 @@ void PrerenderLinkManager::OnChannelClosing(int child_id) { } bool PrerenderLinkManager::IsEmpty() const { - return ids_to_handle_map_.empty(); -} - -void PrerenderLinkManager::RemovePrerender( - const IdPairToPrerenderHandleMap::iterator& id_to_handle_iter) { - PrerenderHandle* prerender_handle = id_to_handle_iter->second; - delete prerender_handle; - ids_to_handle_map_.erase(id_to_handle_iter); + return ids_to_url_map_.empty(); } } // namespace prerender + diff --git a/chrome/browser/prerender/prerender_link_manager.h b/chrome/browser/prerender/prerender_link_manager.h index d9e9c00..5f091c2 100644 --- a/chrome/browser/prerender/prerender_link_manager.h +++ b/chrome/browser/prerender/prerender_link_manager.h @@ -9,6 +9,7 @@ #include #include "base/basictypes.h" +#include "base/gtest_prod_util.h" #include "chrome/browser/profiles/profile_keyed_service.h" #include "googleurl/src/gurl.h" @@ -24,7 +25,6 @@ class Size; namespace prerender { -class PrerenderHandle; class PrerenderManager; // PrerenderLinkManager implements the API on Link elements for all documents @@ -69,20 +69,14 @@ class PrerenderLinkManager : public ProfileKeyedService { friend class PrerenderTest; typedef std::pair ChildAndPrerenderIdPair; - typedef std::map - IdPairToPrerenderHandleMap; + typedef std::map IdPairToUrlMap; - void RemovePrerender( - const IdPairToPrerenderHandleMap::iterator& id_to_handle_iter); + void RemovePrerender(const IdPairToUrlMap::iterator& id_url_iter); bool IsEmpty() const; PrerenderManager* manager_; - - // A map from child process id and prerender id to PrerenderHandles. We map - // from this pair because the prerender ids are only unique within their - // renderer process. - IdPairToPrerenderHandleMap ids_to_handle_map_; + IdPairToUrlMap ids_to_url_map_; DISALLOW_COPY_AND_ASSIGN(PrerenderLinkManager); }; diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc index 6eee18a..5d04091 100644 --- a/chrome/browser/prerender/prerender_manager.cc +++ b/chrome/browser/prerender/prerender_manager.cc @@ -4,8 +4,7 @@ #include "chrome/browser/prerender/prerender_manager.h" -#include -#include +#include #include #include @@ -25,7 +24,6 @@ #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/prerender/prerender_field_trial.h" #include "chrome/browser/prerender/prerender_final_status.h" -#include "chrome/browser/prerender/prerender_handle.h" #include "chrome/browser/prerender/prerender_histograms.h" #include "chrome/browser/prerender/prerender_history.h" #include "chrome/browser/prerender/prerender_local_predictor.h" @@ -108,8 +106,10 @@ bool NeedMatchCompleteDummyForFinalStatus(FinalStatus final_status) { final_status != FINAL_STATUS_MANAGER_SHUTDOWN && final_status != FINAL_STATUS_APP_TERMINATING && final_status != FINAL_STATUS_WINDOW_OPENER && + final_status != FINAL_STATUS_FRAGMENT_MISMATCH && final_status != FINAL_STATUS_CACHE_OR_HISTORY_CLEARED && final_status != FINAL_STATUS_CANCELLED && + final_status != FINAL_STATUS_SESSION_STORAGE_NAMESPACE_MISMATCH && final_status != FINAL_STATUS_DEVTOOLS_ATTACHED && final_status != FINAL_STATUS_CROSS_SITE_NAVIGATION_PENDING; } @@ -171,6 +171,18 @@ int PrerenderManager::prerenders_per_session_count_ = 0; PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = PRERENDER_MODE_ENABLED; +struct PrerenderManager::PrerenderContentsData { + PrerenderContents* contents_; + base::Time start_time_; + int active_count_; + PrerenderContentsData(PrerenderContents* contents, base::Time start_time) + : contents_(contents), + start_time_(start_time), + active_count_(1) { + CHECK(contents); + } +}; + struct PrerenderManager::NavigationRecord { GURL url_; base::TimeTicks time_; @@ -205,32 +217,25 @@ void PrerenderManager::Shutdown() { DoShutdown(); } -PrerenderHandle* PrerenderManager::AddPrerenderFromLinkRelPrerender( +bool PrerenderManager::AddPrerenderFromLinkRelPrerender( int process_id, int route_id, const GURL& url, const content::Referrer& referrer, - const gfx::Size& size) { + gfx::Size size) { #if defined(OS_ANDROID) // TODO(jcivelli): http://crbug.com/113322 We should have an option to disable // link-prerender and enable omnibox-prerender only. return false; #else - DCHECK(!size.IsEmpty()); - if (PrerenderData* parent_prerender_data = - FindPrerenderDataForChildAndRoute(process_id, route_id)) { + std::pair child_route_id_pair(process_id, route_id); + PrerenderContentsDataList::iterator it = + FindPrerenderContentsForChildRouteIdPair(child_route_id_pair); + if (it != prerender_list_.end()) { // Instead of prerendering from inside of a running prerender, we will defer // this request until its launcher is made visible. - if (PrerenderContents* contents = parent_prerender_data->contents_) { - pending_prerender_list_.push_back( - linked_ptr(new PrerenderData(this))); - PrerenderHandle* prerender_handle = - new PrerenderHandle(pending_prerender_list_.back().get()); - contents->AddPendingPrerender( - prerender_handle->weak_ptr_factory_.GetWeakPtr(), - url, referrer, size); - return prerender_handle; - } + it->contents_->AddPendingPrerender(url, referrer, size); + return true; } // Unit tests pass in a process_id == -1. @@ -238,10 +243,21 @@ PrerenderHandle* PrerenderManager::AddPrerenderFromLinkRelPrerender( if (process_id != -1) { RenderViewHost* source_render_view_host = RenderViewHost::FromID(process_id, route_id); - if (!source_render_view_host) - return NULL; + if (!source_render_view_host || !source_render_view_host->GetView()) + return false; session_storage_namespace = source_render_view_host->GetSessionStorageNamespace(); + + if (size.IsEmpty()) { + // Use the size of the tab requesting the prerendering. + WebContents* web_contents = + WebContents::FromRenderViewHost(source_render_view_host); + if (web_contents && web_contents->GetView()) { + gfx::Rect container_bounds; + web_contents->GetView()->GetContainerBounds(&container_bounds); + size = container_bounds.size(); + } + } } return AddPrerender(ORIGIN_LINK_REL_PRERENDER, @@ -250,31 +266,44 @@ PrerenderHandle* PrerenderManager::AddPrerenderFromLinkRelPrerender( #endif } -PrerenderHandle* PrerenderManager::AddPrerenderFromOmnibox( +bool PrerenderManager::AddPrerenderFromOmnibox( const GURL& url, SessionStorageNamespace* session_storage_namespace, - const gfx::Size& size) { + gfx::Size size) { if (!IsOmniboxEnabled(profile_)) - return NULL; - return AddPrerender(ORIGIN_OMNIBOX, -1, url, content::Referrer(), size, + return false; + return AddPrerender(ORIGIN_OMNIBOX, -1, url, + content::Referrer(), size, session_storage_namespace); } +void PrerenderManager::MaybeCancelPrerender(const GURL& url) { + PrerenderContentsDataList::iterator it = FindPrerenderContentsForURL(url); + if (it == prerender_list_.end()) + return; + PrerenderContentsData& prerender_contents_data = *it; + if (--prerender_contents_data.active_count_ == 0) + prerender_contents_data.contents_->Destroy(FINAL_STATUS_CANCELLED); +} + void PrerenderManager::DestroyPrerenderForRenderView( int process_id, int view_id, FinalStatus final_status) { DCHECK(CalledOnValidThread()); - if (PrerenderData* prerender_data = - FindPrerenderDataForChildAndRoute(process_id, view_id)) { - prerender_data->contents_->Destroy(final_status); + PrerenderContentsDataList::iterator it = + FindPrerenderContentsForChildRouteIdPair( + std::make_pair(process_id, view_id)); + if (it != prerender_list_.end()) { + PrerenderContents* prerender_contents = it->contents_; + prerender_contents->Destroy(final_status); } } void PrerenderManager::CancelAllPrerenders() { DCHECK(CalledOnValidThread()); - while (!active_prerender_list_.empty()) { - PrerenderContents* prerender_contents = - active_prerender_list_.front()->contents(); - prerender_contents->Destroy(FINAL_STATUS_CANCELLED); + while (!prerender_list_.empty()) { + PrerenderContentsData data = prerender_list_.front(); + DCHECK(data.contents_); + data.contents_->Destroy(FINAL_STATUS_CANCELLED); } } @@ -283,37 +312,27 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, DCHECK(CalledOnValidThread()); DCHECK(!IsWebContentsPrerendering(web_contents)); - RenderViewHost* old_render_view_host = web_contents->GetRenderViewHost(); - - DeleteOldEntries(); - DeletePendingDeleteEntries(); - PrerenderData* prerender_data = FindPrerenderData( - url, old_render_view_host->GetSessionStorageNamespace()); - if (!prerender_data) - return false; - DCHECK(prerender_data->contents_); - if (IsNoSwapInExperiment(prerender_data->contents_->experiment_id())) + scoped_ptr prerender_contents( + GetEntryButNotSpecifiedWC(url, web_contents)); + if (prerender_contents.get() == NULL) return false; - if (TabContents* new_tab_contents = - prerender_data->contents_->prerender_contents()) { - if (web_contents == new_tab_contents->web_contents()) - return false; // Do not swap in to ourself. - } - - scoped_ptr prerender_contents(prerender_data->contents_); - std::list >::iterator to_erase = - FindIteratorForPrerenderContents(prerender_contents.get()); - DCHECK(active_prerender_list_.end() != to_erase); - DCHECK_EQ(prerender_data, to_erase->get()); - active_prerender_list_.erase(to_erase); - // Do not use the prerendered version if there is an opener object. if (web_contents->HasOpener()) { prerender_contents.release()->Destroy(FINAL_STATUS_WINDOW_OPENER); return false; } + // Even if we match, the location.hash might be different. Record this as a + // separate final status. + GURL matching_url; + bool url_matches = prerender_contents->MatchesURL(url, &matching_url); + DCHECK(url_matches); + if (url_matches && url.ref() != matching_url.ref()) { + prerender_contents.release()->Destroy(FINAL_STATUS_FRAGMENT_MISMATCH); + return false; + } + // If we are just in the control group (which can be detected by noticing // that prerendering hasn't even started yet), record that |web_contents| now // would be showing a prerendered contents, but otherwise, don't do anything. @@ -340,6 +359,22 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, return false; } + // If the session storage namespaces don't match, cancel the prerender. + RenderViewHost* old_render_view_host = web_contents->GetRenderViewHost(); + RenderViewHost* new_render_view_host = + prerender_contents->prerender_contents()->web_contents()-> + GetRenderViewHost(); + DCHECK(old_render_view_host); + DCHECK(new_render_view_host); + if (old_render_view_host->GetSessionStorageNamespace() != + new_render_view_host->GetSessionStorageNamespace()) { + DestroyAndMarkMatchCompleteAsUsed( + prerender_contents.release(), + FINAL_STATUS_SESSION_STORAGE_NAMESPACE_MISMATCH); + return false; + } + + // If we don't want to use prerenders at all, we are done. // For bookkeeping purposes, we need to mark this WebContents to // reflect that it would have been prerendered. if (GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP) { @@ -358,8 +393,6 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, if (!prerender_tracker_->TryUse(child_id, route_id)) return false; - // At this point, we've determined that we will use the prerender. - if (!prerender_contents->load_start_time().is_null()) { histograms_->RecordTimeUntilUsed(GetCurrentTimeTicks() - prerender_contents->load_start_time(), @@ -370,17 +403,10 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, histograms_->RecordUsedPrerender(prerender_contents->origin()); prerender_contents->set_final_status(FINAL_STATUS_USED); - RenderViewHost* new_render_view_host = - prerender_contents->prerender_contents()->web_contents()-> - GetRenderViewHost(); new_render_view_host->Send( new PrerenderMsg_SetIsPrerendering(new_render_view_host->GetRoutingID(), false)); - // Start pending prerender requests from the PrerenderContents, if there are - // any. - prerender_contents->StartPendingPrerenders(); - TabContents* new_tab_contents = prerender_contents->ReleasePrerenderContents(); TabContents* old_tab_contents = TabContents::FromWebContents(web_contents); @@ -413,6 +439,10 @@ bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, DCHECK(prerender_tab_helper != NULL); prerender_tab_helper->PrerenderSwappedIn(); + // Start pending prerender requests from the PrerenderContents, if there are + // any. + prerender_contents->StartPendingPrerenders(); + if (old_tab_contents->web_contents()->NeedToFireBeforeUnload()) { // Schedule the delete to occur after the tab has run its unload handlers. on_close_tab_contents_deleters_.push_back( @@ -439,46 +469,50 @@ void PrerenderManager::MoveEntryToPendingDelete(PrerenderContents* entry, DCHECK_EQ(0, std::count(pending_delete_list_.begin(), pending_delete_list_.end(), entry)); - std::list >::iterator it = - FindIteratorForPrerenderContents(entry); - - // If this PrerenderContents is being deleted due to a cancellation, - // we need to create a dummy replacement for PPLT accounting purposes - // for the Match Complete group. - // This is the case if the cancellation is for any reason that would not - // occur in the control group case. - if (it != active_prerender_list_.end()) { - if (entry->match_complete_status() == - PrerenderContents::MATCH_COMPLETE_DEFAULT && - NeedMatchCompleteDummyForFinalStatus(final_status) && - ActuallyPrerendering()) { - // TODO(tburkard): I'd like to DCHECK that we are actually prerendering. - // However, what if new conditions are added and - // NeedMatchCompleteDummyForFinalStatus, is not being updated. Not sure - // what's the best thing to do here. For now, I will just check whether - // we are actually prerendering. - entry->set_match_complete_status( - PrerenderContents::MATCH_COMPLETE_REPLACED); - PrerenderContents* dummy_replacement_prerender_contents = - CreatePrerenderContents(entry->prerender_url(), entry->referrer(), - entry->origin(), entry->experiment_id()); - dummy_replacement_prerender_contents->MakeIntoDummyReplacementOf(entry); - DCHECK(dummy_replacement_prerender_contents); - - dummy_replacement_prerender_contents->set_match_complete_status( - PrerenderContents::MATCH_COMPLETE_REPLACEMENT_PENDING); - DCHECK(dummy_replacement_prerender_contents->Init()); - dummy_replacement_prerender_contents-> - AddAliasURLsFromOtherPrerenderContents(entry); - dummy_replacement_prerender_contents->set_match_complete_status( - PrerenderContents::MATCH_COMPLETE_REPLACEMENT); - - it->get()->contents_ = dummy_replacement_prerender_contents; - } else { - active_prerender_list_.erase(it); + for (PrerenderContentsDataList::iterator it = prerender_list_.begin(); + it != prerender_list_.end(); + ++it) { + if (it->contents_ == entry) { + bool swapped_in_dummy_replacement = false; + + // If this PrerenderContents is being deleted due to a cancellation, + // we need to create a dummy replacement for PPLT accounting purposes + // for the Match Complete group. + // This is the case if the cancellation is for any reason that would not + // occur in the control group case. + if (entry->match_complete_status() == + PrerenderContents::MATCH_COMPLETE_DEFAULT && + NeedMatchCompleteDummyForFinalStatus(final_status) && + ActuallyPrerendering()) { + // TODO(tburkard): I'd like to DCHECK that we are actually prerendering. + // However, what if new conditions are added and + // NeedMatchCompleteDummyForFinalStatus, is not being updated. Not sure + // what's the best thing to do here. For now, I will just check whether + // we are actually prerendering. + entry->set_match_complete_status( + PrerenderContents::MATCH_COMPLETE_REPLACED); + if (PrerenderContents* dummy_replacement_prerender_contents = + CreatePrerenderContents(entry->prerender_url(), + entry->referrer(), + entry->origin(), + entry->experiment_id())) { + dummy_replacement_prerender_contents->set_match_complete_status( + PrerenderContents::MATCH_COMPLETE_REPLACEMENT_PENDING); + if (!dummy_replacement_prerender_contents->Init()) + break; + dummy_replacement_prerender_contents-> + AddAliasURLsFromOtherPrerenderContents(entry); + dummy_replacement_prerender_contents->set_match_complete_status( + PrerenderContents::MATCH_COMPLETE_REPLACEMENT); + it->contents_ = dummy_replacement_prerender_contents; + swapped_in_dummy_replacement = true; + } + } + if (!swapped_in_dummy_replacement) + prerender_list_.erase(it); + break; } } - AddToHistory(entry); pending_delete_list_.push_back(entry); @@ -589,12 +623,10 @@ bool PrerenderManager::IsNoUseGroup() { bool PrerenderManager::IsWebContentsPrerendering( WebContents* web_contents) const { DCHECK(CalledOnValidThread()); - for (std::list >::const_iterator it = - active_prerender_list_.begin(); - it != active_prerender_list_.end(); + for (PrerenderContentsDataList::const_iterator it = prerender_list_.begin(); + it != prerender_list_.end(); ++it) { - TabContents* prerender_tab_contents = - it->get()->contents_->prerender_contents(); + TabContents* prerender_tab_contents = it->contents_->prerender_contents(); if (prerender_tab_contents && prerender_tab_contents->web_contents() == web_contents) { return true; @@ -615,6 +647,12 @@ bool PrerenderManager::IsWebContentsPrerendering( return false; } +bool PrerenderManager::DidPrerenderFinishLoading(const GURL& url) const { + DCHECK(CalledOnValidThread()); + PrerenderContents* contents = FindEntry(url); + return contents ? contents->has_finished_loading() : false; +} + void PrerenderManager::MarkWebContentsAsPrerendered(WebContents* web_contents) { DCHECK(CalledOnValidThread()); prerendered_tab_contents_set_.insert(web_contents); @@ -730,142 +768,55 @@ void PrerenderManager::AddCondition(const PrerenderCondition* condition) { prerender_conditions_.push_back(condition); } -void PrerenderManager::RecordNavigation(const GURL& url) { +bool PrerenderManager::IsPendingEntry(const GURL& url) const { DCHECK(CalledOnValidThread()); - - navigations_.push_back(NavigationRecord(url, GetCurrentTimeTicks())); - CleanUpOldNavigations(); -} - -// protected -PrerenderManager::PrerenderData::PrerenderData(PrerenderManager* manager) - : manager_(manager), contents_(NULL), handle_count_(0) { -} - -PrerenderManager::PrerenderData::PrerenderData(PrerenderManager* manager, - PrerenderContents* contents) - : manager_(manager), contents_(contents), handle_count_(0) { -} - -void PrerenderManager::PrerenderData::OnNewHandle() { - DCHECK(contents_ || handle_count_ == 0) << - "Cannot create multiple handles to a pending prerender."; - ++handle_count_; -} - -void PrerenderManager::PrerenderData::OnNavigateAwayByHandle() { - // TODO(gavinp): Implement reasonable behaviour for navigation away from - // launcher. We can't just call OnCancel, because many cases have redirect - // chains that will eventually lead to the correct prerendered page, and we - // don't want to delete our prerender just as it is going to be used. - - if (!contents_) { - DCHECK_EQ(1, handle_count_); - // Pending prerenders are not maintained in the active_prerender_list_, so - // they will not get normal expiry. Since this prerender hasn't even been - // launched yet, and it's held by a page that is being prerendered, we will - // just delete it. - manager_->DestroyPendingPrerenderData(this); + for (PrerenderContentsDataList::const_iterator it = prerender_list_.begin(); + it != prerender_list_.end(); + ++it) { + if (it->contents_->IsPendingEntry(url)) + return true; } + return false; } -void PrerenderManager::PrerenderData::OnCancelByHandle() { - DCHECK_LE(1, handle_count_); - DCHECK(contents_ || handle_count_ == 1); - - if (--handle_count_ == 0) { - if (contents_) { - // This will eventually remove this object from active_prerender_list_, - // triggering the linked_ptr auto deletion. - contents_->Destroy(FINAL_STATUS_CANCELLED); - } else { - manager_->DestroyPendingPrerenderData(this); - } - } +bool PrerenderManager::IsPrerendering(const GURL& url) const { + DCHECK(CalledOnValidThread()); + return (FindEntry(url) != NULL); } -PrerenderManager::PrerenderData::~PrerenderData() { +void PrerenderManager::RecordNavigation(const GURL& url) { + DCHECK(CalledOnValidThread()); + + navigations_.push_back(NavigationRecord(url, GetCurrentTimeTicks())); + CleanUpOldNavigations(); } +// protected void PrerenderManager::SetPrerenderContentsFactory( PrerenderContents::Factory* prerender_contents_factory) { DCHECK(CalledOnValidThread()); prerender_contents_factory_.reset(prerender_contents_factory); } -void PrerenderManager::StartPendingPrerender( - PrerenderHandle* existing_prerender_handle, - Origin origin, - int process_id, - const GURL& url, - const content::Referrer& referrer, - const gfx::Size& size, - content::SessionStorageNamespace* session_storage_namespace) { - DCHECK(existing_prerender_handle); - DCHECK(existing_prerender_handle->IsValid()); - DCHECK(existing_prerender_handle->IsPending()); - - DVLOG(6) << "StartPendingPrerender"; - DVLOG(6) << "existing_prerender_handle->handle_count_ = " << - existing_prerender_handle->prerender_data_->handle_count_; - - DCHECK(process_id == -1 || session_storage_namespace); - - scoped_ptr swap_prerender_handle(AddPrerender( - origin, process_id, url, referrer, size, session_storage_namespace)); - if (swap_prerender_handle.get()) { - // AddPrerender has returned a new prerender handle to us. We want to make - // |existing_prerender_handle| active, so swap the underlying PrerenderData - // between the two handles, and delete our old handle (which will release - // our entry in the pending_prerender_list_). - existing_prerender_handle->SwapPrerenderDataWith( - swap_prerender_handle.get()); - swap_prerender_handle->OnCancel(); - return; - } - - // We could not start our Prerender. Canceling the existing handle will make - // it return false for PrerenderHandle::IsPending(), and will release the - // PrerenderData from pending_prerender_list_. - existing_prerender_handle->OnCancel(); -} - -void PrerenderManager::DestroyPendingPrerenderData( - PrerenderData* pending_prerender_data) { - for (std::list >::iterator - it = pending_prerender_list_.begin(); - it != pending_prerender_list_.end(); - ++it) { - if (it->get() == pending_prerender_data) { - DCHECK_GE(1, it->get()->handle_count_); - pending_prerender_list_.erase(it); - return; - } - } - NOTREACHED(); -} - void PrerenderManager::DoShutdown() { DestroyAllContents(FINAL_STATUS_MANAGER_SHUTDOWN); STLDeleteElements(&prerender_conditions_); on_close_tab_contents_deleters_.reset(); profile_ = NULL; - - DCHECK(active_prerender_list_.empty()); } // private -PrerenderHandle* PrerenderManager::AddPrerender( +bool PrerenderManager::AddPrerender( Origin origin, int process_id, const GURL& url_arg, const content::Referrer& referrer, - const gfx::Size& size, + gfx::Size size, SessionStorageNamespace* session_storage_namespace) { DCHECK(CalledOnValidThread()); if (!IsEnabled()) - return NULL; + return false; if (origin == ORIGIN_LINK_REL_PRERENDER && IsGoogleSearchResultURL(referrer.url)) { @@ -889,10 +840,10 @@ PrerenderHandle* PrerenderManager::AddPrerender( // histogram tracking. histograms_->RecordPrerender(origin, url_arg); - if (PrerenderData* preexisting_prerender_data = - FindPrerenderData(url, session_storage_namespace)) { + if (PrerenderContentsData* prerender_contents_data = FindEntryData(url)) { + ++prerender_contents_data->active_count_; RecordFinalStatus(origin, experiment, FINAL_STATUS_DUPLICATE); - return new PrerenderHandle(preexisting_prerender_data); + return true; } // Do not prerender if there are too many render processes, and we would @@ -910,7 +861,7 @@ PrerenderHandle* PrerenderManager::AddPrerender( profile_, url) && !content::RenderProcessHost::run_renderer_in_process()) { RecordFinalStatus(origin, experiment, FINAL_STATUS_TOO_MANY_PROCESSES); - return NULL; + return false; } #endif @@ -920,39 +871,64 @@ PrerenderHandle* PrerenderManager::AddPrerender( // this doesn't make sense as the next prerender request will be triggered // by a navigation and is unlikely to be the same site. RecordFinalStatus(origin, experiment, FINAL_STATUS_RATE_LIMIT_EXCEEDED); - return NULL; + return false; } PrerenderContents* prerender_contents = CreatePrerenderContents( url, referrer, origin, experiment); if (!prerender_contents || !prerender_contents->Init()) - return NULL; + return false; histograms_->RecordPrerenderStarted(origin); // TODO(cbentzel): Move invalid checks here instead of PrerenderContents? - active_prerender_list_.push_back( - linked_ptr(new PrerenderData(this, prerender_contents))); - PrerenderHandle* prerender_handle = - new PrerenderHandle(active_prerender_list_.back().get()); + PrerenderContentsData data(prerender_contents, GetCurrentTime()); + + prerender_list_.push_back(data); last_prerender_start_time_ = GetCurrentTimeTicks(); - gfx::Size contents_size = - size.IsEmpty() ? config_.default_tab_bounds.size() : size; + if (size.IsEmpty()) + size = config_.default_tab_bounds.size(); - prerender_contents->StartPrerendering(process_id, contents_size, - session_storage_namespace, - control_group_behavior); + data.contents_->StartPrerendering(process_id, size, session_storage_namespace, + control_group_behavior); - while (active_prerender_list_.size() > config_.max_elements) { - prerender_contents = active_prerender_list_.front()->contents_; - DCHECK(prerender_contents); - prerender_contents->Destroy(FINAL_STATUS_EVICTED); + while (prerender_list_.size() > config_.max_elements) { + data = prerender_list_.front(); + prerender_list_.pop_front(); + data.contents_->Destroy(FINAL_STATUS_EVICTED); } - StartSchedulingPeriodicCleanups(); - return prerender_handle; + return true; +} + +PrerenderContents* PrerenderManager::GetEntry(const GURL& url) { + return GetEntryButNotSpecifiedWC(url, NULL); +} + +PrerenderContents* PrerenderManager::GetEntryButNotSpecifiedWC( + const GURL& url, + WebContents* wc) { + DCHECK(CalledOnValidThread()); + DeleteOldEntries(); + DeletePendingDeleteEntries(); + for (PrerenderContentsDataList::iterator it = prerender_list_.begin(); + it != prerender_list_.end(); + ++it) { + PrerenderContents* prerender_contents = it->contents_; + if (prerender_contents->MatchesURL(url, NULL) && + !IsNoSwapInExperiment(prerender_contents->experiment_id())) { + if (!prerender_contents->prerender_contents() || + !wc || + prerender_contents->prerender_contents()->web_contents() != wc) { + prerender_list_.erase(it); + return prerender_contents; + } + } + } + // Entry not found. + return NULL; } void PrerenderManager::StartSchedulingPeriodicCleanups() { @@ -965,7 +941,10 @@ void PrerenderManager::StartSchedulingPeriodicCleanups() { &PrerenderManager::PeriodicCleanup); } -void PrerenderManager::StopSchedulingPeriodicCleanups() { +void PrerenderManager::MaybeStopSchedulingPeriodicCleanups() { + if (!prerender_list_.empty()) + return; + DCHECK(CalledOnValidThread()); repeating_timer_.Stop(); } @@ -974,22 +953,22 @@ void PrerenderManager::PeriodicCleanup() { DCHECK(CalledOnValidThread()); DeleteOldTabContents(); DeleteOldEntries(); - if (active_prerender_list_.empty()) - StopSchedulingPeriodicCleanups(); // Grab a copy of the current PrerenderContents pointers, so that we // will not interfere with potential deletions of the list. std::vector prerender_contents; - prerender_contents.reserve(active_prerender_list_.size()); - for (std::list >::iterator - it = active_prerender_list_.begin(); - it != active_prerender_list_.end(); - ++it) { - prerender_contents.push_back(it->get()->contents_); + for (PrerenderContentsDataList::iterator it = prerender_list_.begin(); + it != prerender_list_.end(); + ++it) { + DCHECK(it->contents_); + prerender_contents.push_back(it->contents_); + } + for (std::vector::iterator it = + prerender_contents.begin(); + it != prerender_contents.end(); + ++it) { + (*it)->DestroyWhenUsingTooManyResources(); } - std::for_each(prerender_contents.begin(), prerender_contents.end(), - std::mem_fun( - &PrerenderContents::DestroyWhenUsingTooManyResources)); DeletePendingDeleteEntries(); } @@ -1007,20 +986,21 @@ base::TimeDelta PrerenderManager::GetMaxAge() const { base::TimeDelta::FromSeconds(300) : config_.max_age); } -bool PrerenderManager::IsPrerenderFresh(const base::TimeTicks start) const { +bool PrerenderManager::IsPrerenderElementFresh(const base::Time start) const { DCHECK(CalledOnValidThread()); - return GetCurrentTimeTicks() - start < GetMaxAge(); + base::Time now = GetCurrentTime(); + return (now - start < GetMaxAge()); } void PrerenderManager::DeleteOldEntries() { DCHECK(CalledOnValidThread()); - while (!active_prerender_list_.empty()) { - PrerenderContents* contents = active_prerender_list_.front()->contents_; - DCHECK(contents); - if (IsPrerenderFresh(contents->load_start_time())) + while (!prerender_list_.empty()) { + PrerenderContentsData data = prerender_list_.front(); + if (IsPrerenderElementFresh(data.start_time_)) return; - contents->Destroy(FINAL_STATUS_TIMED_OUT); + data.contents_->Destroy(FINAL_STATUS_TIMED_OUT); } + MaybeStopSchedulingPeriodicCleanups(); } base::Time PrerenderManager::GetCurrentTime() const { @@ -1050,53 +1030,58 @@ void PrerenderManager::DeletePendingDeleteEntries() { } } -PrerenderManager::PrerenderData* PrerenderManager::FindPrerenderData( - const GURL& url, - const SessionStorageNamespace* session_storage_namespace) { - for (std::list >::iterator - it = active_prerender_list_.begin(); - it != active_prerender_list_.end(); +PrerenderManager::PrerenderContentsData* PrerenderManager::FindEntryData( + const GURL& url) { + DCHECK(CalledOnValidThread()); + PrerenderContentsDataList::iterator it = FindPrerenderContentsForURL(url); + if (it == prerender_list_.end()) + return NULL; + PrerenderContentsData& prerender_contents_data = *it; + return &prerender_contents_data; +} + +PrerenderContents* PrerenderManager::FindEntry(const GURL& url) const { + DCHECK(CalledOnValidThread()); + for (PrerenderContentsDataList::const_iterator it = prerender_list_.begin(); + it != prerender_list_.end(); ++it) { - PrerenderContents* prerender_contents = it->get()->contents_; - if (prerender_contents->Matches(url, session_storage_namespace)) - return it->get(); + if (it->contents_->MatchesURL(url, NULL)) + return it->contents_; } + // Entry not found. return NULL; } -PrerenderManager::PrerenderData* -PrerenderManager::FindPrerenderDataForChildAndRoute( - const int child_id, const int route_id) { - for (std::list >::iterator - it = active_prerender_list_.begin(); - it != active_prerender_list_.end(); - ++it) { - PrerenderContents* prerender_contents = it->get()->contents_; +PrerenderManager::PrerenderContentsDataList::iterator + PrerenderManager::FindPrerenderContentsForChildRouteIdPair( + const std::pair& child_route_id_pair) { + PrerenderContentsDataList::iterator it = prerender_list_.begin(); + for (; it != prerender_list_.end(); ++it) { + PrerenderContents* prerender_contents = it->contents_; - int contents_child_id; - if (!prerender_contents->GetChildId(&contents_child_id)) - continue; - int contents_route_id; - if (!prerender_contents->GetRouteId(&contents_route_id)) - continue; + int child_id; + int route_id; + bool has_child_id = prerender_contents->GetChildId(&child_id); + bool has_route_id = has_child_id && + prerender_contents->GetRouteId(&route_id); - if (contents_child_id == child_id && contents_route_id == route_id) - return it->get(); + if (has_child_id && has_route_id && + child_id == child_route_id_pair.first && + route_id == child_route_id_pair.second) { + break; + } } - return NULL; + return it; } -std::list >::iterator -PrerenderManager::FindIteratorForPrerenderContents( - PrerenderContents* prerender_contents) { - for (std::list >::iterator - it = active_prerender_list_.begin(); - it != active_prerender_list_.end(); - ++it) { - if (prerender_contents == it->get()->contents_) +PrerenderManager::PrerenderContentsDataList::iterator + PrerenderManager::FindPrerenderContentsForURL(const GURL& url) { + for (PrerenderContentsDataList::iterator it = prerender_list_.begin(); + it != prerender_list_.end(); ++it) { + if (it->contents_->MatchesURL(url, NULL)) return it; } - return active_prerender_list_.end(); + return prerender_list_.end(); } bool PrerenderManager::DoesRateLimitAllowPrerender() const { @@ -1158,21 +1143,23 @@ void PrerenderManager::AddToHistory(PrerenderContents* contents) { Value* PrerenderManager::GetActivePrerendersAsValue() const { ListValue* list_value = new ListValue(); - for (std::list >::const_iterator it = - active_prerender_list_.begin(); - it != active_prerender_list_.end(); + for (PrerenderContentsDataList::const_iterator it = prerender_list_.begin(); + it != prerender_list_.end(); ++it) { - if (Value* prerender_value = it->get()->contents_->GetAsValue()) - list_value->Append(prerender_value); + Value* prerender_value = it->contents_->GetAsValue(); + if (!prerender_value) + continue; + list_value->Append(prerender_value); } return list_value; } void PrerenderManager::DestroyAllContents(FinalStatus final_status) { DeleteOldTabContents(); - while (!active_prerender_list_.empty()) { - PrerenderContents* contents = active_prerender_list_.front()->contents_; - contents->Destroy(final_status); + while (!prerender_list_.empty()) { + PrerenderContentsData data = prerender_list_.front(); + prerender_list_.pop_front(); + data.contents_->Destroy(final_status); } DeletePendingDeleteEntries(); } @@ -1231,4 +1218,3 @@ PrerenderManager* FindPrerenderManagerUsingRenderProcessId( } } // namespace prerender - diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h index 3341572..1a667cc 100644 --- a/chrome/browser/prerender/prerender_manager.h +++ b/chrome/browser/prerender/prerender_manager.h @@ -6,7 +6,6 @@ #define CHROME_BROWSER_PRERENDER_PRERENDER_MANAGER_H_ #include -#include #include #include @@ -14,7 +13,6 @@ #include "base/hash_tables.h" #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" -#include "base/memory/linked_ptr.h" #include "base/memory/weak_ptr.h" #include "base/threading/non_thread_safe.h" #include "base/time.h" @@ -56,7 +54,6 @@ struct hash { namespace prerender { class PrerenderCondition; -class PrerenderHandle; class PrerenderHistograms; class PrerenderHistory; class PrerenderLocalPredictor; @@ -103,31 +100,36 @@ class PrerenderManager : public base::SupportsWeakPtr, // Entry points for adding prerenders. // Adds a prerender for |url| if valid. |process_id| and |route_id| identify - // the RenderView that the prerender request came from. If |size| is empty, a - // default from the PrerenderConfig is used. Returns a caller-owned - // PrerenderHandle* if the URL was added, NULL if it was not. If the launching - // RenderView is itself prerendering, the prerender is added as a pending - // prerender. - PrerenderHandle* AddPrerenderFromLinkRelPrerender( + // the RenderView that the prerender request came from. The |size| may be + // empty, and the current tab size will be used if it is. If the current + // active tab size cannot be found, we use a default from PrerenderConfig. + // Returns true if the URL was added, false if it was not. + // If the launching RenderView is itself prerendering, the prerender is added + // as a pending prerender. + bool AddPrerenderFromLinkRelPrerender( int process_id, int route_id, const GURL& url, const content::Referrer& referrer, - const gfx::Size& size); + gfx::Size size); // Adds a prerender for |url| if valid. As the prerender request is coming // from a source without a RenderViewHost (i.e., the omnibox) we don't have a // child or route id, or a referrer. This method uses sensible values for // those. The |session_storage_namespace| matches the namespace of the active - // tab at the time the prerender is generated from the omnibox. Returns a - // caller-owned PrerenderHandle*, or NULL. - PrerenderHandle* AddPrerenderFromOmnibox( + // tab at the time the prerender is generated from the omnibox. + bool AddPrerenderFromOmnibox( const GURL& url, content::SessionStorageNamespace* session_storage_namespace, - const gfx::Size& size); + gfx::Size size); - // If |process_id| and |view_id| refer to a running prerender, destroy - // it with |final_status|. + // Request cancelation of a previously added prerender. If the |active_count_| + // of the prerender is one, it will be canceled. Otherwise, |active_count_| + // will be decremented by one. + void MaybeCancelPrerender(const GURL& url); + + // Destroy all prerenders for the given child route id pair and assign a final + // status to them. virtual void DestroyPrerenderForRenderView(int process_id, int view_id, FinalStatus final_status); @@ -181,6 +183,10 @@ class PrerenderManager : public base::SupportsWeakPtr, // is prerendering a page. bool IsWebContentsPrerendering(content::WebContents* web_contents) const; + // Returns true if there is a prerendered page for the given URL and it has + // finished loading. Only valid if called before MaybeUsePrerenderedPage. + bool DidPrerenderFinishLoading(const GURL& url) const; + // Maintaining and querying the set of WebContents belonging to this // PrerenderManager that are currently showing prerendered pages. void MarkWebContentsAsPrerendered(content::WebContents* web_contents); @@ -230,6 +236,11 @@ class PrerenderManager : public base::SupportsWeakPtr, // Adds a condition. This is owned by the PrerenderManager. void AddCondition(const PrerenderCondition* condition); + bool IsPendingEntry(const GURL& url) const; + + // Returns true if |url| matches any URLs being prerendered. + bool IsPrerendering(const GURL& url) const; + // Records that some visible tab navigated (or was redirected) to the // provided URL. void RecordNavigation(const GURL& url); @@ -239,102 +250,94 @@ class PrerenderManager : public base::SupportsWeakPtr, PrerenderHistograms* histograms() const { return histograms_.get(); } protected: - class PrerenderData : public base::SupportsWeakPtr { - public: - // Constructor for a pending prerender, which will get its contents later. - explicit PrerenderData(PrerenderManager* manager); - - // Constructor for an active prerender. - PrerenderData(PrerenderManager* manager, PrerenderContents* contents); - - ~PrerenderData(); - - // A new PrerenderHandle has been created for this PrerenderData. - void OnNewHandle(); - - // The launcher associated with a handle is navigating away from the context - // that launched this prerender. If the prerender is active, it may stay - // alive briefly though, in case we we going through a redirect chain that - // will eventually land at it. - void OnNavigateAwayByHandle(); - - // The launcher associated with a handle has taken explicit action to cancel - // this prerender. We may well destroy the prerender in this case if no - // other handles continue to track it. - void OnCancelByHandle(); - - PrerenderContents* contents() { return contents_; } - - private: - friend class PrerenderManager; - - PrerenderManager* manager_; - PrerenderContents* contents_; - - // The number of distinct PrerenderHandles created for |this|, including - // ones that have called PrerenderData::OnNavigateAwayByHandle(), but not - // counting the ones that have called PrerenderData::OnCancelByHandle(). For - // pending prerenders, this will always be 1, since the PrerenderManager - // only merges handles of running prerenders. - int handle_count_; - - DISALLOW_COPY_AND_ASSIGN(PrerenderData); - }; - void SetPrerenderContentsFactory( PrerenderContents::Factory* prerender_contents_factory); - // Adds a prerender from a pending Prerender, called by - // PrerenderContents::StartPendingPrerenders. - void StartPendingPrerender( - PrerenderHandle* existing_prerender_handle, - Origin origin, - int process_id, - const GURL& url, - const content::Referrer& referrer, - const gfx::Size& size, - content::SessionStorageNamespace* session_storage_namespace); - - void DestroyPendingPrerenderData(PrerenderData* pending_prerender_data); - // Utility method that is called from the virtual Shutdown method on this // class but is called directly from the TestPrerenderManager in the unit // tests. void DoShutdown(); private: + // Test that needs needs access to internal functions. friend class PrerenderBrowserTest; - friend class PrerenderContents; - friend class PrerenderHandle; - friend class UnitTestPrerenderManager; + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, AliasURLTest); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, CancelAllTest); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, + CancelOmniboxRemovesOmniboxTest); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, + CancelOmniboxDoesNotRemoveLinkTest); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, ClearTest); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, ControlGroup); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, DropOldestRequestTest); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, DropSecondRequestTest); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, ExpireTest); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, FoundTest); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, FragmentMatchesFragmentTest); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, FragmentMatchesPageTest); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, LinkManagerAbandon); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, LinkManagerAddTwiceAbandonTwice); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, LinkManagerAddTwiceCancelTwice); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, + LinkManagerAddTwiceCancelTwiceThenAbandonTwice); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, LinkManagerCancel); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, LinkManagerCancelThenAbandon); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, LinkManagerCancelThenAddAgain); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, LinkManagerCancelTwice); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, LinkManagerExpireThenAddAgain); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, LinkManagerExpireThenCancel); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, NotSoRecentlyVisited); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, PageMatchesFragmentTest); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, PendingPrerenderTest); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, PPLTDummy); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, RateLimitInWindowTest); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, RateLimitOutsideWindowTest); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, RecentlyVisitedPPLTDummy); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, SourceRenderViewClosed); + FRIEND_TEST_ALL_PREFIXES(PrerenderTest, TwoElementPrerenderTest); + + struct PrerenderContentsData; + struct NavigationRecord; class OnCloseTabContentsDeleter; - struct NavigationRecord; + typedef std::list PrerenderContentsDataList; typedef base::hash_map WouldBePrerenderedMap; // Time window for which we record old navigations, in milliseconds. static const int kNavigationRecordWindowMs = 5000; - void OnCancelPrerenderHandle(PrerenderData* prerender_data); - - // Adds a prerender for |url| from |referrer| initiated from the process - // |child_id|. The |origin| specifies how the prerender was added. If |size| - // is empty, then PrerenderContents::StartPrerendering will instead use a - // default from PrerenderConfig. Returns a PrerenderHandle*, owned by the - // caller, or NULL. - PrerenderHandle* AddPrerender( + // Adds a prerender for |url| from referrer |referrer| initiated from the + // child process specified by |child_id|. The |origin| specifies how the + // prerender was added. If the |size| is empty, then + // PrerenderContents::StartPrerendering will instead use the size of the + // currently active tab. If the current active tab size cannot be found, it + // then uses a default from PrerenderConfig. + bool AddPrerender( Origin origin, int child_id, const GURL& url, const content::Referrer& referrer, - const gfx::Size& size, + gfx::Size size, content::SessionStorageNamespace* session_storage_namespace); - void StartSchedulingPeriodicCleanups(); - void StopSchedulingPeriodicCleanups(); + // Retrieves the PrerenderContents object for the specified URL, if it + // has been prerendered. The caller will then have ownership of the + // PrerenderContents object and is responsible for freeing it. + // Returns NULL if the specified URL has not been prerendered. + PrerenderContents* GetEntry(const GURL& url); - void EvictOldestPrerendersIfNecessary(); + // Identical to GetEntry, with one exception: + // The WebContents specified indicates the WC in which to swap the + // prerendering into. If the WebContents specified is the one + // to doing the prerendered itself, will return NULL. + PrerenderContents* GetEntryButNotSpecifiedWC(const GURL& url, + content::WebContents* wc); + + // Starts scheduling periodic cleanups. + void StartSchedulingPeriodicCleanups(); + // Stops scheduling periodic cleanups if they're no longer needed. + void MaybeStopSchedulingPeriodicCleanups(); // Deletes stale and cancelled prerendered PrerenderContents, as well as // WebContents that have been replaced by prerendered WebContents. @@ -348,7 +351,7 @@ class PrerenderManager : public base::SupportsWeakPtr, void PostCleanupTask(); base::TimeDelta GetMaxAge() const; - bool IsPrerenderFresh(base::TimeTicks start) const; + bool IsPrerenderElementFresh(const base::Time start) const; void DeleteOldEntries(); virtual base::Time GetCurrentTime() const; virtual base::TimeTicks GetCurrentTimeTicks() const; @@ -362,21 +365,20 @@ class PrerenderManager : public base::SupportsWeakPtr, // list. void DeletePendingDeleteEntries(); - // Finds the active PrerenderData object for a running prerender matching - // |url| and |session_storage_namespace|. - PrerenderData* FindPrerenderData( - const GURL& url, - const content::SessionStorageNamespace* session_storage_namespace); + // Finds the specified PrerenderContentsData/PrerenderContents and returns it, + // if it exists. Returns NULL otherwise. Unlike GetEntry, the + // PrerenderManager maintains ownership of the PrerenderContents. + PrerenderContentsData* FindEntryData(const GURL& url); + PrerenderContents* FindEntry(const GURL& url) const; - // If |child_id| and |route_id| correspond to a RenderView that is an active - // prerender, returns the PrerenderData object for that prerender. Otherwise, - // returns NULL. - PrerenderData* FindPrerenderDataForChildAndRoute(int child_id, int route_id); + // Returns the iterator to the PrerenderContentsData entry that is being + // prerendered from the given child route id pair. + PrerenderContentsDataList::iterator + FindPrerenderContentsForChildRouteIdPair( + const std::pair& child_route_id_pair); - // Given the |prerender_contents|, find the iterator in active_prerender_list_ - // correponding to the given prerender. - std::list >::iterator - FindIteratorForPrerenderContents(PrerenderContents* prerender_contents); + PrerenderContentsDataList::iterator + FindPrerenderContentsForURL(const GURL& url); bool DoesRateLimitAllowPrerender() const; @@ -437,12 +439,8 @@ class PrerenderManager : public base::SupportsWeakPtr, PrerenderTracker* prerender_tracker_; - // List of all running prerenders. It is kept sorted, in increasing order by - // expiry time. This list owns the PrerenderData objects contained in it. - std::list > active_prerender_list_; - - // List of all pending prerenders. - std::list > pending_prerender_list_; + // List of prerendered elements. + PrerenderContentsDataList prerender_list_; // List of recent navigations in this profile, sorted by ascending // navigate_time_. diff --git a/chrome/browser/prerender/prerender_unittest.cc b/chrome/browser/prerender/prerender_unittest.cc index 5a17ee0..b6403d9 100644 --- a/chrome/browser/prerender/prerender_unittest.cc +++ b/chrome/browser/prerender/prerender_unittest.cc @@ -7,7 +7,6 @@ #include "base/message_loop.h" #include "base/time.h" #include "chrome/browser/prerender/prerender_contents.h" -#include "chrome/browser/prerender/prerender_handle.h" #include "chrome/browser/prerender/prerender_link_manager.h" #include "chrome/browser/prerender/prerender_manager.h" #include "chrome/browser/prerender/prerender_origin.h" @@ -25,17 +24,20 @@ using content::Referrer; namespace prerender { -class UnitTestPrerenderManager; - namespace { class DummyPrerenderContents : public PrerenderContents { public: - DummyPrerenderContents(UnitTestPrerenderManager* test_prerender_manager, + DummyPrerenderContents(PrerenderManager* prerender_manager, PrerenderTracker* prerender_tracker, const GURL& url, Origin origin, - FinalStatus expected_final_status); + FinalStatus expected_final_status) + : PrerenderContents(prerender_manager, prerender_tracker, + NULL, url, Referrer(), origin, + PrerenderManager::kNoExperiment), + expected_final_status_(expected_final_status) { + } virtual ~DummyPrerenderContents() { EXPECT_EQ(expected_final_status_, final_status()); @@ -45,7 +47,14 @@ class DummyPrerenderContents : public PrerenderContents { int ALLOW_UNUSED creator_child_id, const gfx::Size& ALLOW_UNUSED size, content::SessionStorageNamespace* ALLOW_UNUSED session_storage_namespace, - bool is_control_group) OVERRIDE; + bool is_control_group) OVERRIDE { + // In the base PrerenderContents implementation, StartPrerendering will + // be called even when the PrerenderManager is part of the control group, + // but it will early exit before actually creating a new RenderView if + // |is_control_group| is true; + if (!is_control_group) + prerendering_has_started_ = true; + } virtual bool GetChildId(int* child_id) const OVERRIDE { *child_id = 0; @@ -64,20 +73,12 @@ class DummyPrerenderContents : public PrerenderContents { } private: - UnitTestPrerenderManager* test_prerender_manager_; FinalStatus expected_final_status_; }; -const gfx::Size kSize(640, 480); - -} // namespace - -class UnitTestPrerenderManager : public PrerenderManager { +class TestPrerenderManager : public PrerenderManager { public: - using PrerenderManager::kNavigationRecordWindowMs; - using PrerenderManager::GetMaxAge; - - explicit UnitTestPrerenderManager(PrerenderTracker* prerender_tracker) + explicit TestPrerenderManager(PrerenderTracker* prerender_tracker) : PrerenderManager(&profile_, prerender_tracker), time_(base::Time::Now()), time_ticks_(base::TimeTicks::Now()), @@ -86,36 +87,23 @@ class UnitTestPrerenderManager : public PrerenderManager { set_rate_limit_enabled(false); } - virtual ~UnitTestPrerenderManager() { + virtual ~TestPrerenderManager() { if (next_prerender_contents()) { next_prerender_contents_.release()->Destroy( FINAL_STATUS_MANAGER_SHUTDOWN); } + // Set the final status for all PrerenderContents with an expected final + // status of FINAL_STATUS_USED. These values are normally set when the + // prerendered RVH is swapped into a tab, which doesn't happen in these + // unit tests. + for (ScopedVector::iterator it = + used_prerender_contents_.begin(); + it != used_prerender_contents_.end(); ++it) { + (*it)->set_final_status(FINAL_STATUS_USED); + } DoShutdown(); } - PrerenderContents* FindEntry(const GURL& url) { - DeleteOldEntries(); - DeletePendingDeleteEntries(); - if (PrerenderData* data = FindPrerenderData(url, NULL)) - return data->contents(); - return NULL; - } - - PrerenderContents* FindAndUseEntry(const GURL& url) { - PrerenderData* prerender_data = FindPrerenderData(url, NULL); - if (!prerender_data) - return NULL; - PrerenderContents* prerender_contents = prerender_data->contents(); - prerender_contents->set_final_status(FINAL_STATUS_USED); - std::list >::iterator to_erase = - FindIteratorForPrerenderContents(prerender_contents); - DCHECK(to_erase != active_prerender_list_.end()); - active_prerender_list_.erase(to_erase); - prerender_contents->StartPendingPrerenders(); - return prerender_contents; - } - void AdvanceTime(base::TimeDelta delta) { time_ += delta; } @@ -171,15 +159,6 @@ class UnitTestPrerenderManager : public PrerenderManager { return next_prerender_contents_.get(); } - // from PrerenderManager - virtual base::Time GetCurrentTime() const OVERRIDE { - return time_; - } - - virtual base::TimeTicks GetCurrentTimeTicks() const OVERRIDE { - return time_ticks_; - } - private: void SetNextPrerenderContents(DummyPrerenderContents* prerender_contents) { DCHECK(!next_prerender_contents_.get()); @@ -188,6 +167,13 @@ class UnitTestPrerenderManager : public PrerenderManager { used_prerender_contents_.push_back(prerender_contents); } + virtual base::Time GetCurrentTime() const OVERRIDE { + return time_; + } + + virtual base::TimeTicks GetCurrentTimeTicks() const OVERRIDE { + return time_ticks_; + } virtual PrerenderContents* CreatePrerenderContents( const GURL& url, @@ -195,8 +181,8 @@ class UnitTestPrerenderManager : public PrerenderManager { Origin origin, uint8 experiment_id) OVERRIDE { DCHECK(next_prerender_contents_.get()); - EXPECT_EQ(url, next_prerender_contents_->prerender_url()); - EXPECT_EQ(origin, next_prerender_contents_->origin()); + DCHECK_EQ(next_prerender_contents_->prerender_url(), url); + DCHECK_EQ(next_prerender_contents_->origin(), origin); return next_prerender_contents_.release(); } @@ -222,32 +208,7 @@ class RestorePrerenderMode { PrerenderManager::PrerenderManagerMode prev_mode_; }; -DummyPrerenderContents::DummyPrerenderContents( - UnitTestPrerenderManager* test_prerender_manager, - PrerenderTracker* prerender_tracker, - const GURL& url, - Origin origin, - FinalStatus expected_final_status) - : PrerenderContents(test_prerender_manager, prerender_tracker, - NULL, url, Referrer(), origin, - PrerenderManager::kNoExperiment), - test_prerender_manager_(test_prerender_manager), - expected_final_status_(expected_final_status) { -} - -void DummyPrerenderContents::StartPrerendering( - int ALLOW_UNUSED creator_child_id, - const gfx::Size& ALLOW_UNUSED size, - content::SessionStorageNamespace* ALLOW_UNUSED session_storage_namespace, - bool is_control_group) { - // In the base PrerenderContents implementation, StartPrerendering will - // be called even when the PrerenderManager is part of the control group, - // but it will early exit before actually creating a new RenderView if - // |is_control_group| is true; - if (!is_control_group) - prerendering_has_started_ = true; - load_start_time_ = test_prerender_manager_->GetCurrentTimeTicks(); -} +} // namespace class PrerenderTest : public testing::Test { public: @@ -256,7 +217,7 @@ class PrerenderTest : public testing::Test { PrerenderTest() : ui_thread_(BrowserThread::UI, &message_loop_), prerender_manager_( - new UnitTestPrerenderManager(prerender_tracker())), + new TestPrerenderManager(prerender_tracker())), prerender_link_manager_( new PrerenderLinkManager(prerender_manager_.get())), last_prerender_id_(0) { @@ -266,11 +227,7 @@ class PrerenderTest : public testing::Test { switches::kPrerenderFromOmniboxSwitchValueEnabled); } - ~PrerenderTest() { - prerender_link_manager_->OnChannelClosing(kDefaultChildId); - } - - UnitTestPrerenderManager* prerender_manager() { + TestPrerenderManager* prerender_manager() { return prerender_manager_.get(); } @@ -295,7 +252,7 @@ class PrerenderTest : public testing::Test { return prerender_link_manager()->OnAddPrerender( kDefaultChildId, GetNextPrerenderID(), url, content::Referrer(), - kSize, kDefaultRenderViewRouteId); + gfx::Size(), kDefaultRenderViewRouteId); } private: @@ -306,23 +263,18 @@ class PrerenderTest : public testing::Test { // Needed to pass PrerenderManager's DCHECKs. MessageLoop message_loop_; content::TestBrowserThread ui_thread_; - scoped_ptr prerender_manager_; + scoped_ptr prerender_manager_; scoped_ptr prerender_link_manager_; int last_prerender_id_; }; -TEST_F(PrerenderTest, FoundTest) { - GURL url("http://www.google.com/"); - DummyPrerenderContents* prerender_contents = - prerender_manager()->CreateNextPrerenderContents( - url, - FINAL_STATUS_USED); - EXPECT_TRUE(AddSimplePrerender(url)); - EXPECT_TRUE(prerender_contents->prerendering_has_started()); - ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); +TEST_F(PrerenderTest, EmptyTest) { + EXPECT_FALSE(prerender_manager()->MaybeUsePrerenderedPage( + NULL, + GURL("http://www.google.com/"))); } -TEST_F(PrerenderTest, DuplicateTest) { +TEST_F(PrerenderTest, FoundTest) { GURL url("http://www.google.com/"); DummyPrerenderContents* prerender_contents = prerender_manager()->CreateNextPrerenderContents( @@ -330,19 +282,7 @@ TEST_F(PrerenderTest, DuplicateTest) { FINAL_STATUS_USED); EXPECT_TRUE(AddSimplePrerender(url)); EXPECT_TRUE(prerender_contents->prerendering_has_started()); - - scoped_ptr duplicate_prerender_handle( - prerender_manager()->AddPrerenderFromLinkRelPrerender( - kDefaultChildId, kDefaultRenderViewRouteId, url, - Referrer(url, WebKit::WebReferrerPolicyDefault), kSize)); - - EXPECT_TRUE(duplicate_prerender_handle->IsValid()); - EXPECT_TRUE(duplicate_prerender_handle->IsPrerendering()); - - ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); - - EXPECT_FALSE(duplicate_prerender_handle->IsValid()); - EXPECT_FALSE(duplicate_prerender_handle->IsPrerendering()); + ASSERT_EQ(prerender_contents, prerender_manager()->GetEntry(url)); } // Make sure that if queue a request, and a second prerender request for the @@ -367,7 +307,7 @@ TEST_F(PrerenderTest, DropSecondRequestTest) { prerender_manager()->next_prerender_contents()); EXPECT_FALSE(prerender_contents1->prerendering_has_started()); - ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); + ASSERT_EQ(prerender_contents, prerender_manager()->GetEntry(url)); } // Ensure that we expire a prerendered page after the max. permitted time. @@ -381,9 +321,9 @@ TEST_F(PrerenderTest, ExpireTest) { EXPECT_TRUE(AddSimplePrerender(url)); EXPECT_EQ(null, prerender_manager()->next_prerender_contents()); EXPECT_TRUE(prerender_contents->prerendering_has_started()); - prerender_manager()->AdvanceTimeTicks(prerender_manager()->GetMaxAge() + - base::TimeDelta::FromSeconds(1)); - ASSERT_EQ(null, prerender_manager()->FindEntry(url)); + prerender_manager()->AdvanceTime(prerender_manager()->GetMaxAge() + + base::TimeDelta::FromSeconds(1)); + ASSERT_EQ(null, prerender_manager()->GetEntry(url)); } // LRU Test. Make sure that if we prerender more than one request, that @@ -408,8 +348,8 @@ TEST_F(PrerenderTest, DropOldestRequestTest) { EXPECT_EQ(null, prerender_manager()->next_prerender_contents()); EXPECT_TRUE(prerender_contents1->prerendering_has_started()); - ASSERT_EQ(null, prerender_manager()->FindEntry(url)); - ASSERT_EQ(prerender_contents1, prerender_manager()->FindAndUseEntry(url1)); + ASSERT_EQ(null, prerender_manager()->GetEntry(url)); + ASSERT_EQ(prerender_contents1, prerender_manager()->GetEntry(url1)); } // Two element prerender test. Ensure that the LRU operates correctly if we @@ -444,9 +384,9 @@ TEST_F(PrerenderTest, TwoElementPrerenderTest) { EXPECT_EQ(null, prerender_manager()->next_prerender_contents()); EXPECT_TRUE(prerender_contents2->prerendering_has_started()); - ASSERT_EQ(null, prerender_manager()->FindEntry(url)); - ASSERT_EQ(prerender_contents1, prerender_manager()->FindAndUseEntry(url1)); - ASSERT_EQ(prerender_contents2, prerender_manager()->FindAndUseEntry(url2)); + ASSERT_EQ(null, prerender_manager()->GetEntry(url)); + ASSERT_EQ(prerender_contents1, prerender_manager()->GetEntry(url1)); + ASSERT_EQ(prerender_contents2, prerender_manager()->GetEntry(url2)); } TEST_F(PrerenderTest, AliasURLTest) { @@ -463,18 +403,16 @@ TEST_F(PrerenderTest, AliasURLTest) { prerender_manager()->CreateNextPrerenderContents( url, alias_urls, FINAL_STATUS_USED); EXPECT_TRUE(AddSimplePrerender(url)); - ASSERT_EQ(NULL, prerender_manager()->FindEntry(not_an_alias_url)); - ASSERT_EQ(prerender_contents, - prerender_manager()->FindAndUseEntry(alias_url1)); + ASSERT_EQ(NULL, prerender_manager()->GetEntry(not_an_alias_url)); + ASSERT_EQ(prerender_contents, prerender_manager()->GetEntry(alias_url1)); prerender_contents = prerender_manager()->CreateNextPrerenderContents( url, alias_urls, FINAL_STATUS_USED); EXPECT_TRUE(AddSimplePrerender(url)); - ASSERT_EQ(prerender_contents, - prerender_manager()->FindAndUseEntry(alias_url2)); + ASSERT_EQ(prerender_contents, prerender_manager()->GetEntry(alias_url2)); prerender_contents = prerender_manager()->CreateNextPrerenderContents( url, alias_urls, FINAL_STATUS_USED); EXPECT_TRUE(AddSimplePrerender(url)); - ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); + ASSERT_EQ(prerender_contents, prerender_manager()->GetEntry(url)); // Test that alias URLs can not be added. prerender_contents = prerender_manager()->CreateNextPrerenderContents( @@ -483,7 +421,7 @@ TEST_F(PrerenderTest, AliasURLTest) { EXPECT_TRUE(AddSimplePrerender(url)); EXPECT_TRUE(AddSimplePrerender(alias_url1)); EXPECT_TRUE(AddSimplePrerender(alias_url2)); - ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); + ASSERT_EQ(prerender_contents, prerender_manager()->GetEntry(url)); } // Ensure that we ignore prerender requests within the rate limit. @@ -551,92 +489,14 @@ TEST_F(PrerenderTest, PendingPrerenderTest) { GURL pending_url("http://news.google.com/"); - DummyPrerenderContents* pending_prerender_contents = - prerender_manager()->CreateNextPrerenderContents( - pending_url, - ORIGIN_GWS_PRERENDER, - FINAL_STATUS_USED); - scoped_ptr pending_prerender_handle( - prerender_manager()->AddPrerenderFromLinkRelPrerender( - child_id, route_id, pending_url, - Referrer(url, WebKit::WebReferrerPolicyDefault), kSize)); - DCHECK(pending_prerender_handle.get()); - EXPECT_TRUE(pending_prerender_handle->IsValid()); - EXPECT_TRUE(pending_prerender_handle->IsPending()); + EXPECT_TRUE(prerender_manager()->AddPrerenderFromLinkRelPrerender( + child_id, route_id, + pending_url, Referrer(url, WebKit::WebReferrerPolicyDefault), + gfx::Size())); + EXPECT_TRUE(prerender_manager()->IsPendingEntry(pending_url)); EXPECT_TRUE(prerender_contents->prerendering_has_started()); - ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); - - EXPECT_FALSE(pending_prerender_handle->IsPending()); - ASSERT_EQ(pending_prerender_contents, - prerender_manager()->FindAndUseEntry(pending_url)); -} - -TEST_F(PrerenderTest, InvalidPendingPrerenderTest) { - GURL url("http://www.google.com/"); - DummyPrerenderContents* prerender_contents = - prerender_manager()->CreateNextPrerenderContents( - url, - FINAL_STATUS_USED); - EXPECT_TRUE(AddSimplePrerender(url)); - - int child_id; - int route_id; - ASSERT_TRUE(prerender_contents->GetChildId(&child_id)); - ASSERT_TRUE(prerender_contents->GetRouteId(&route_id)); - - // This pending URL has an unsupported scheme, and won't be able - // to start. - GURL pending_url("ftp://news.google.com/"); - - prerender_manager()->CreateNextPrerenderContents( - pending_url, - ORIGIN_GWS_PRERENDER, - FINAL_STATUS_UNSUPPORTED_SCHEME); - scoped_ptr pending_prerender_handle( - prerender_manager()->AddPrerenderFromLinkRelPrerender( - child_id, route_id, pending_url, - Referrer(url, WebKit::WebReferrerPolicyDefault), kSize)); - DCHECK(pending_prerender_handle.get()); - EXPECT_TRUE(pending_prerender_handle->IsValid()); - EXPECT_TRUE(pending_prerender_handle->IsPending()); - - EXPECT_TRUE(prerender_contents->prerendering_has_started()); - ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); - - EXPECT_FALSE(pending_prerender_handle->IsValid()); - EXPECT_FALSE(pending_prerender_handle->IsPending()); -} - -TEST_F(PrerenderTest, CancelPendingPrerenderTest) { - GURL url("http://www.google.com/"); - DummyPrerenderContents* prerender_contents = - prerender_manager()->CreateNextPrerenderContents( - url, - FINAL_STATUS_USED); - EXPECT_TRUE(AddSimplePrerender(url)); - - int child_id; - int route_id; - ASSERT_TRUE(prerender_contents->GetChildId(&child_id)); - ASSERT_TRUE(prerender_contents->GetRouteId(&route_id)); - - GURL pending_url("http://news.google.com/"); - - scoped_ptr pending_prerender_handle( - prerender_manager()->AddPrerenderFromLinkRelPrerender( - child_id, route_id, pending_url, - Referrer(url, WebKit::WebReferrerPolicyDefault), kSize)); - DCHECK(pending_prerender_handle.get()); - EXPECT_TRUE(pending_prerender_handle->IsValid()); - EXPECT_TRUE(pending_prerender_handle->IsPending()); - - EXPECT_TRUE(prerender_contents->prerendering_has_started()); - - pending_prerender_handle->OnCancel(); - EXPECT_FALSE(pending_prerender_handle->IsValid()); - - ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); + ASSERT_EQ(prerender_contents, prerender_manager()->GetEntry(url)); } // Tests that a PrerenderManager created for a browser session in the control @@ -664,7 +524,7 @@ TEST_F(PrerenderTest, SourceRenderViewClosed) { FINAL_STATUS_MANAGER_SHUTDOWN); EXPECT_FALSE(prerender_link_manager()->OnAddPrerender( 100, GetNextPrerenderID(), url, - Referrer(), kSize, 200)); + Referrer(), gfx::Size(), 200)); } // Tests that prerendering is cancelled when we launch a second prerender of @@ -687,14 +547,14 @@ TEST_F(PrerenderTest, NotSoRecentlyVisited) { prerender_manager()->RecordNavigation(url); prerender_manager()->AdvanceTimeTicks( base::TimeDelta::FromMilliseconds( - UnitTestPrerenderManager::kNavigationRecordWindowMs + 500)); + PrerenderManager::kNavigationRecordWindowMs + 500)); DummyPrerenderContents* prerender_contents = prerender_manager()->CreateNextPrerenderContents( url, FINAL_STATUS_USED); EXPECT_TRUE(AddSimplePrerender(url)); EXPECT_TRUE(prerender_contents->prerendering_has_started()); - ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); + ASSERT_EQ(prerender_contents, prerender_manager()->GetEntry(url)); } // Tests that our PPLT dummy prerender gets created properly. @@ -713,7 +573,7 @@ TEST_F(PrerenderTest, PPLTDummy) { // Adding this ftp URL will force the expected unsupported scheme error. prerender_contents->AddAliasURL(ftp_url); - ASSERT_EQ(pplt_dummy_contents, prerender_manager()->FindAndUseEntry(url)); + ASSERT_EQ(pplt_dummy_contents, prerender_manager()->GetEntry(url)); } // Tests that our PPLT dummy prerender gets created properly, even @@ -733,29 +593,29 @@ TEST_F(PrerenderTest, RecentlyVisitedPPLTDummy) { GURL ftp_url("ftp://ftp.google.com/"); prerender_contents->AddAliasURL(ftp_url); - ASSERT_EQ(pplt_dummy_contents, prerender_manager()->FindAndUseEntry(url)); + ASSERT_EQ(pplt_dummy_contents, prerender_manager()->GetEntry(url)); } -// Tests that the prerender link manager discards fragments when launching, -// and matches only occur on URLs without fragments. -// TODO(gavinp): Drop this test once we are fragment clean. -TEST_F(PrerenderTest, FragmentDroppedOnLaunchTest) { - GURL fragment_url("http://www.google.com/#test"); +// Tests that the prerender manager ignores fragment references when matching +// prerender URLs in the case the fragment is not in the prerender URL. +TEST_F(PrerenderTest, PageMatchesFragmentTest) { GURL url("http://www.google.com/"); + GURL fragment_url("http://www.google.com/#test"); DummyPrerenderContents* prerender_contents = prerender_manager()->CreateNextPrerenderContents(url, FINAL_STATUS_USED); - EXPECT_TRUE(AddSimplePrerender(fragment_url)); + EXPECT_TRUE(AddSimplePrerender(url)); EXPECT_TRUE(prerender_contents->prerendering_has_started()); - EXPECT_FALSE(prerender_manager()->FindEntry(fragment_url)); - ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); + ASSERT_EQ(prerender_contents, prerender_manager()->GetEntry(fragment_url)); } -// Tests that the prerender manager matches include the fragment. -// TODO(gavinp): Re-enable this once we are fragment clean. +// Tests that the prerender manager ignores fragment references when matching +// prerender URLs in the case the fragment is in the prerender URL. +// TODO(gavinp): Re-enable this in the Prerender API once we're officially // fragment clean. -TEST_F(PrerenderTest, DISABLED_FragmentMatchesTest) { +TEST_F(PrerenderTest, DISABLED_FragmentMatchesPageTest) { + GURL url("http://www.google.com/"); GURL fragment_url("http://www.google.com/#test"); DummyPrerenderContents* prerender_contents = @@ -763,14 +623,14 @@ TEST_F(PrerenderTest, DISABLED_FragmentMatchesTest) { FINAL_STATUS_USED); EXPECT_TRUE(AddSimplePrerender(fragment_url)); EXPECT_TRUE(prerender_contents->prerendering_has_started()); - ASSERT_EQ(prerender_contents, - prerender_manager()->FindAndUseEntry(fragment_url)); + ASSERT_EQ(prerender_contents, prerender_manager()->GetEntry(url)); } -// Tests that the prerender manager uses fragment references when matching -// prerender URLs in the case a different fragment is in both URLs. -// TODO(gavinp): Re-enable this once we are fragment clean. -TEST_F(PrerenderTest, DISABLED_FragmentsDifferTest) { +// Tests that the prerender manager ignores fragment references when matching +// prerender URLs in the case the fragment is in both URLs. +// TODO(gavinp): Re-enable this in the Prerender API once we're officially +// fragment clean. +TEST_F(PrerenderTest, DISABLED_FragmentMatchesFragmentTest) { GURL fragment_url("http://www.google.com/#test"); GURL other_fragment_url("http://www.google.com/#other_test"); @@ -779,12 +639,8 @@ TEST_F(PrerenderTest, DISABLED_FragmentsDifferTest) { FINAL_STATUS_USED); EXPECT_TRUE(AddSimplePrerender(fragment_url)); EXPECT_TRUE(prerender_contents->prerendering_has_started()); - - DummyPrerenderContents* null = NULL; - ASSERT_EQ(null, prerender_manager()->FindEntry(other_fragment_url)); - ASSERT_EQ(prerender_contents, - prerender_manager()->FindAndUseEntry(fragment_url)); + prerender_manager()->GetEntry(other_fragment_url)); } // Make sure that clearing works as expected. @@ -844,7 +700,7 @@ TEST_F(PrerenderTest, LinkManagerCancel) { EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled()); DummyPrerenderContents* null = NULL; - ASSERT_EQ(null, prerender_manager()->FindEntry(url)); + ASSERT_EQ(null, prerender_manager()->GetEntry(url)); EXPECT_TRUE(IsEmptyPrerenderLinkManager()); } @@ -872,10 +728,10 @@ TEST_F(PrerenderTest, LinkManagerCancelThenAbandon) { EXPECT_TRUE(IsEmptyPrerenderLinkManager()); EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled()); DummyPrerenderContents* null = NULL; - ASSERT_EQ(null, prerender_manager()->FindEntry(url)); + ASSERT_EQ(null, prerender_manager()->GetEntry(url)); } -// TODO(gavinp): Re-enabmed this test after abandon has an effect on Prerenders, +// TODO(gavinp): Update this test after abandon has an effect on Prerenders, // like shortening the timeouts. TEST_F(PrerenderTest, LinkManagerAbandon) { EXPECT_TRUE(IsEmptyPrerenderLinkManager()); @@ -894,7 +750,7 @@ TEST_F(PrerenderTest, LinkManagerAbandon) { last_prerender_id()); EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); - ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); + ASSERT_EQ(prerender_contents, prerender_manager()->GetEntry(url)); EXPECT_TRUE(IsEmptyPrerenderLinkManager()); } @@ -915,7 +771,7 @@ TEST_F(PrerenderTest, LinkManagerCancelTwice) { EXPECT_TRUE(IsEmptyPrerenderLinkManager()); EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled()); DummyPrerenderContents* null = NULL; - ASSERT_EQ(null, prerender_manager()->FindEntry(url)); + ASSERT_EQ(null, prerender_manager()->GetEntry(url)); prerender_link_manager()->OnCancelPrerender(kDefaultChildId, last_prerender_id()); } @@ -950,7 +806,7 @@ TEST_F(PrerenderTest, LinkManagerAddTwiceCancelTwice) { EXPECT_TRUE(IsEmptyPrerenderLinkManager()); EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled()); DummyPrerenderContents* null = NULL; - ASSERT_EQ(null, prerender_manager()->FindEntry(url)); + ASSERT_EQ(null, prerender_manager()->GetEntry(url)); } TEST_F(PrerenderTest, LinkManagerAddTwiceCancelTwiceThenAbandonTwice) { @@ -993,7 +849,7 @@ TEST_F(PrerenderTest, LinkManagerAddTwiceCancelTwiceThenAbandonTwice) { EXPECT_TRUE(IsEmptyPrerenderLinkManager()); EXPECT_TRUE(prerender_contents->prerendering_has_been_cancelled()); DummyPrerenderContents* null = NULL; - ASSERT_EQ(null, prerender_manager()->FindEntry(url)); + ASSERT_EQ(null, prerender_manager()->GetEntry(url)); } // TODO(gavinp): Update this test after abandon has an effect on Prerenders, @@ -1027,7 +883,7 @@ TEST_F(PrerenderTest, LinkManagerAddTwiceAbandonTwice) { EXPECT_TRUE(IsEmptyPrerenderLinkManager()); EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); - ASSERT_EQ(prerender_contents, prerender_manager()->FindAndUseEntry(url)); + ASSERT_EQ(prerender_contents, prerender_manager()->GetEntry(url)); } // TODO(gavinp): After abandon shortens the expire time on a Prerender, @@ -1046,17 +902,17 @@ TEST_F(PrerenderTest, LinkManagerExpireThenCancel) { EXPECT_TRUE(prerender_contents->prerendering_has_started()); EXPECT_FALSE(prerender_contents->prerendering_has_been_cancelled()); ASSERT_EQ(prerender_contents, prerender_manager()->FindEntry(url)); - prerender_manager()->AdvanceTimeTicks(prerender_manager()->GetMaxAge() + - base::TimeDelta::FromSeconds(1)); + prerender_manager()->AdvanceTime(prerender_manager()->GetMaxAge() + + base::TimeDelta::FromSeconds(1)); EXPECT_FALSE(IsEmptyPrerenderLinkManager()); DummyPrerenderContents* null = NULL; - ASSERT_EQ(null, prerender_manager()->FindEntry(url)); + ASSERT_EQ(null, prerender_manager()->GetEntry(url)); prerender_link_manager()->OnCancelPrerender(kDefaultChildId, last_prerender_id()); EXPECT_TRUE(IsEmptyPrerenderLinkManager()); - ASSERT_EQ(null, prerender_manager()->FindEntry(url)); + ASSERT_EQ(null, prerender_manager()->GetEntry(url)); } TEST_F(PrerenderTest, LinkManagerExpireThenAddAgain) { @@ -1068,19 +924,17 @@ TEST_F(PrerenderTest, LinkManagerExpireThenAddAgain) { EXPECT_TRUE(AddSimplePrerender(url)); EXPECT_TRUE(first_prerender_contents->prerendering_has_started()); EXPECT_FALSE(first_prerender_contents->prerendering_has_been_cancelled()); - ASSERT_EQ(first_prerender_contents, - prerender_manager()->FindAndUseEntry(url)); - prerender_manager()->AdvanceTimeTicks(prerender_manager()->GetMaxAge() + - base::TimeDelta::FromSeconds(1)); + ASSERT_EQ(first_prerender_contents, prerender_manager()->FindEntry(url)); + prerender_manager()->AdvanceTime(prerender_manager()->GetMaxAge() + + base::TimeDelta::FromSeconds(1)); DummyPrerenderContents* null = NULL; - ASSERT_EQ(null, prerender_manager()->FindEntry(url)); + ASSERT_EQ(null, prerender_manager()->GetEntry(url)); DummyPrerenderContents* second_prerender_contents = prerender_manager()->CreateNextPrerenderContents( url, FINAL_STATUS_USED); EXPECT_TRUE(AddSimplePrerender(url)); EXPECT_TRUE(second_prerender_contents->prerendering_has_started()); - ASSERT_EQ(second_prerender_contents, - prerender_manager()->FindAndUseEntry(url)); + ASSERT_EQ(second_prerender_contents, prerender_manager()->GetEntry(url)); // The PrerenderLinkManager is not empty since we never removed the first // prerender. EXPECT_FALSE(IsEmptyPrerenderLinkManager()); @@ -1101,14 +955,13 @@ TEST_F(PrerenderTest, LinkManagerCancelThenAddAgain) { EXPECT_TRUE(IsEmptyPrerenderLinkManager()); EXPECT_TRUE(first_prerender_contents->prerendering_has_been_cancelled()); DummyPrerenderContents* null = NULL; - ASSERT_EQ(null, prerender_manager()->FindEntry(url)); + ASSERT_EQ(null, prerender_manager()->GetEntry(url)); DummyPrerenderContents* second_prerender_contents = prerender_manager()->CreateNextPrerenderContents( url, FINAL_STATUS_USED); EXPECT_TRUE(AddSimplePrerender(url)); EXPECT_TRUE(second_prerender_contents->prerendering_has_started()); - ASSERT_EQ(second_prerender_contents, - prerender_manager()->FindAndUseEntry(url)); + ASSERT_EQ(second_prerender_contents, prerender_manager()->GetEntry(url)); EXPECT_FALSE(IsEmptyPrerenderLinkManager()); } diff --git a/chrome/browser/ui/omnibox/omnibox_edit_model.cc b/chrome/browser/ui/omnibox/omnibox_edit_model.cc index 51282ac..5661042 100644 --- a/chrome/browser/ui/omnibox/omnibox_edit_model.cc +++ b/chrome/browser/ui/omnibox/omnibox_edit_model.cc @@ -1122,13 +1122,18 @@ void OmniboxEditModel::DoPrerender(const AutocompleteMatch& match) { TabContents* tab = controller_->GetTabContents(); if (!tab) return; + prerender::PrerenderManager* prerender_manager = + prerender::PrerenderManagerFactory::GetForProfile(tab->profile()); + if (!prerender_manager) + return; + + content::RenderViewHost* current_host = + tab->web_contents()->GetRenderViewHost(); gfx::Rect container_bounds; tab->web_contents()->GetView()->GetContainerBounds(&container_bounds); - AutocompleteActionPredictorFactory::GetForProfile(profile_)-> - StartPrerendering(match.destination_url, - tab->web_contents()->GetRenderViewHost()-> - GetSessionStorageNamespace(), - container_bounds.size()); + prerender_manager->AddPrerenderFromOmnibox( + match.destination_url, current_host->GetSessionStorageNamespace(), + container_bounds.size()); } void OmniboxEditModel::DoPreconnect(const AutocompleteMatch& match) { diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index dc0426f..b001200 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1798,8 +1798,6 @@ 'browser/prerender/prerender_field_trial.h', 'browser/prerender/prerender_final_status.cc', 'browser/prerender/prerender_final_status.h', - 'browser/prerender/prerender_handle.cc', - 'browser/prerender/prerender_handle.h', 'browser/prerender/prerender_histograms.cc', 'browser/prerender/prerender_histograms.h', 'browser/prerender/prerender_history.cc', -- cgit v1.1