Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/prerender/prerender_manager.h" | 5 #include "chrome/browser/prerender/prerender_manager.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <algorithm> |
| 8 #include <functional> | |
| 8 #include <string> | 9 #include <string> |
| 9 #include <vector> | 10 #include <vector> |
| 10 | 11 |
| 11 #include "base/bind.h" | 12 #include "base/bind.h" |
| 12 #include "base/bind_helpers.h" | 13 #include "base/bind_helpers.h" |
| 13 #include "base/logging.h" | 14 #include "base/logging.h" |
| 14 #include "base/memory/weak_ptr.h" | 15 #include "base/memory/weak_ptr.h" |
| 15 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
| 16 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
| 17 #include "base/time.h" | 18 #include "base/time.h" |
| 18 #include "base/utf_string_conversions.h" | 19 #include "base/utf_string_conversions.h" |
| 19 #include "base/values.h" | 20 #include "base/values.h" |
| 20 #include "chrome/browser/browser_process.h" | 21 #include "chrome/browser/browser_process.h" |
| 21 #include "chrome/browser/cancelable_request.h" | 22 #include "chrome/browser/cancelable_request.h" |
| 22 #include "chrome/browser/favicon/favicon_tab_helper.h" | 23 #include "chrome/browser/favicon/favicon_tab_helper.h" |
| 23 #include "chrome/browser/prerender/prerender_condition.h" | 24 #include "chrome/browser/prerender/prerender_condition.h" |
| 24 #include "chrome/browser/prerender/prerender_contents.h" | 25 #include "chrome/browser/prerender/prerender_contents.h" |
| 25 #include "chrome/browser/prerender/prerender_field_trial.h" | 26 #include "chrome/browser/prerender/prerender_field_trial.h" |
| 26 #include "chrome/browser/prerender/prerender_final_status.h" | 27 #include "chrome/browser/prerender/prerender_final_status.h" |
| 28 #include "chrome/browser/prerender/prerender_handle.h" | |
| 27 #include "chrome/browser/prerender/prerender_histograms.h" | 29 #include "chrome/browser/prerender/prerender_histograms.h" |
| 28 #include "chrome/browser/prerender/prerender_history.h" | 30 #include "chrome/browser/prerender/prerender_history.h" |
| 29 #include "chrome/browser/prerender/prerender_local_predictor.h" | 31 #include "chrome/browser/prerender/prerender_local_predictor.h" |
| 30 #include "chrome/browser/prerender/prerender_manager_factory.h" | 32 #include "chrome/browser/prerender/prerender_manager_factory.h" |
| 31 #include "chrome/browser/prerender/prerender_tab_helper.h" | 33 #include "chrome/browser/prerender/prerender_tab_helper.h" |
| 32 #include "chrome/browser/prerender/prerender_tracker.h" | 34 #include "chrome/browser/prerender/prerender_tracker.h" |
| 33 #include "chrome/browser/prerender/prerender_util.h" | 35 #include "chrome/browser/prerender/prerender_util.h" |
| 34 #include "chrome/browser/profiles/profile.h" | 36 #include "chrome/browser/profiles/profile.h" |
| 35 #include "chrome/browser/ui/tab_contents/core_tab_helper.h" | 37 #include "chrome/browser/ui/tab_contents/core_tab_helper.h" |
| 36 #include "chrome/browser/ui/tab_contents/core_tab_helper_delegate.h" | 38 #include "chrome/browser/ui/tab_contents/core_tab_helper_delegate.h" |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 99 // This ensures that there is no bias in terms of the page load times | 101 // This ensures that there is no bias in terms of the page load times |
| 100 // of the pages forming the difference between the two sets. | 102 // of the pages forming the difference between the two sets. |
| 101 | 103 |
| 102 bool NeedMatchCompleteDummyForFinalStatus(FinalStatus final_status) { | 104 bool NeedMatchCompleteDummyForFinalStatus(FinalStatus final_status) { |
| 103 return final_status != FINAL_STATUS_USED && | 105 return final_status != FINAL_STATUS_USED && |
| 104 final_status != FINAL_STATUS_TIMED_OUT && | 106 final_status != FINAL_STATUS_TIMED_OUT && |
| 105 final_status != FINAL_STATUS_EVICTED && | 107 final_status != FINAL_STATUS_EVICTED && |
| 106 final_status != FINAL_STATUS_MANAGER_SHUTDOWN && | 108 final_status != FINAL_STATUS_MANAGER_SHUTDOWN && |
| 107 final_status != FINAL_STATUS_APP_TERMINATING && | 109 final_status != FINAL_STATUS_APP_TERMINATING && |
| 108 final_status != FINAL_STATUS_WINDOW_OPENER && | 110 final_status != FINAL_STATUS_WINDOW_OPENER && |
| 109 final_status != FINAL_STATUS_FRAGMENT_MISMATCH && | |
| 110 final_status != FINAL_STATUS_CACHE_OR_HISTORY_CLEARED && | 111 final_status != FINAL_STATUS_CACHE_OR_HISTORY_CLEARED && |
| 111 final_status != FINAL_STATUS_CANCELLED && | 112 final_status != FINAL_STATUS_CANCELLED && |
| 112 final_status != FINAL_STATUS_SESSION_STORAGE_NAMESPACE_MISMATCH && | |
| 113 final_status != FINAL_STATUS_DEVTOOLS_ATTACHED && | 113 final_status != FINAL_STATUS_DEVTOOLS_ATTACHED && |
| 114 final_status != FINAL_STATUS_CROSS_SITE_NAVIGATION_PENDING; | 114 final_status != FINAL_STATUS_CROSS_SITE_NAVIGATION_PENDING; |
| 115 } | 115 } |
| 116 | 116 |
| 117 } // namespace | 117 } // namespace |
| 118 | 118 |
| 119 class PrerenderManager::OnCloseTabContentsDeleter | 119 class PrerenderManager::OnCloseTabContentsDeleter |
| 120 : public content::WebContentsDelegate, | 120 : public content::WebContentsDelegate, |
| 121 public base::SupportsWeakPtr< | 121 public base::SupportsWeakPtr< |
| 122 PrerenderManager::OnCloseTabContentsDeleter> { | 122 PrerenderManager::OnCloseTabContentsDeleter> { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 164 // static | 164 // static |
| 165 bool PrerenderManager::is_prefetch_enabled_ = false; | 165 bool PrerenderManager::is_prefetch_enabled_ = false; |
| 166 | 166 |
| 167 // static | 167 // static |
| 168 int PrerenderManager::prerenders_per_session_count_ = 0; | 168 int PrerenderManager::prerenders_per_session_count_ = 0; |
| 169 | 169 |
| 170 // static | 170 // static |
| 171 PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = | 171 PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = |
| 172 PRERENDER_MODE_ENABLED; | 172 PRERENDER_MODE_ENABLED; |
| 173 | 173 |
| 174 struct PrerenderManager::PrerenderContentsData { | |
| 175 PrerenderContents* contents_; | |
| 176 base::Time start_time_; | |
| 177 int active_count_; | |
| 178 PrerenderContentsData(PrerenderContents* contents, base::Time start_time) | |
| 179 : contents_(contents), | |
| 180 start_time_(start_time), | |
| 181 active_count_(1) { | |
| 182 CHECK(contents); | |
| 183 } | |
| 184 }; | |
| 185 | |
| 186 struct PrerenderManager::NavigationRecord { | 174 struct PrerenderManager::NavigationRecord { |
| 187 GURL url_; | 175 GURL url_; |
| 188 base::TimeTicks time_; | 176 base::TimeTicks time_; |
| 189 NavigationRecord(const GURL& url, base::TimeTicks time) | 177 NavigationRecord(const GURL& url, base::TimeTicks time) |
| 190 : url_(url), | 178 : url_(url), |
| 191 time_(time) { | 179 time_(time) { |
| 192 } | 180 } |
| 193 }; | 181 }; |
| 194 | 182 |
| 195 PrerenderManager::PrerenderManager(Profile* profile, | 183 PrerenderManager::PrerenderManager(Profile* profile, |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 211 } | 199 } |
| 212 | 200 |
| 213 PrerenderManager::~PrerenderManager() { | 201 PrerenderManager::~PrerenderManager() { |
| 214 } | 202 } |
| 215 | 203 |
| 216 void PrerenderManager::Shutdown() { | 204 void PrerenderManager::Shutdown() { |
| 217 DoShutdown(); | 205 DoShutdown(); |
| 218 } | 206 } |
| 219 | 207 |
| 220 bool PrerenderManager::AddPrerenderFromLinkRelPrerender( | 208 PrerenderHandle* PrerenderManager::AddPrerenderFromLinkRelPrerender( |
| 221 int process_id, | 209 int process_id, |
| 222 int route_id, | 210 int route_id, |
| 223 const GURL& url, | 211 const GURL& url, |
| 224 const content::Referrer& referrer, | 212 const content::Referrer& referrer, |
| 225 gfx::Size size) { | 213 const gfx::Size& size) { |
| 226 #if defined(OS_ANDROID) | 214 #if defined(OS_ANDROID) |
| 227 // TODO(jcivelli): http://crbug.com/113322 We should have an option to disable | 215 // TODO(jcivelli): http://crbug.com/113322 We should have an option to disable |
| 228 // link-prerender and enable omnibox-prerender only. | 216 // link-prerender and enable omnibox-prerender only. |
| 229 return false; | 217 return false; |
| 230 #else | 218 #else |
| 231 std::pair<int, int> child_route_id_pair(process_id, route_id); | 219 DCHECK(!size.IsEmpty()); |
| 232 PrerenderContentsDataList::iterator it = | 220 if (PrerenderData* parent_prerender_data = |
| 233 FindPrerenderContentsForChildRouteIdPair(child_route_id_pair); | 221 FindPrerenderDataForChildAndRoute(process_id, route_id)) { |
| 234 if (it != prerender_list_.end()) { | |
| 235 // Instead of prerendering from inside of a running prerender, we will defer | 222 // Instead of prerendering from inside of a running prerender, we will defer |
| 236 // this request until its launcher is made visible. | 223 // this request until its launcher is made visible. |
| 237 it->contents_->AddPendingPrerender(url, referrer, size); | 224 if (PrerenderContents* contents = parent_prerender_data->contents_) { |
| 238 return true; | 225 pending_prerender_list_.push_back( |
| 226 linked_ptr<PrerenderData>(new PrerenderData(this))); | |
| 227 PrerenderHandle* prerender_handle = | |
| 228 new PrerenderHandle(pending_prerender_list_.back().get()); | |
| 229 contents->AddPendingPrerender( | |
| 230 prerender_handle->weak_ptr_factory_.GetWeakPtr(), | |
| 231 url, referrer, size); | |
| 232 return prerender_handle; | |
| 233 } | |
| 239 } | 234 } |
| 240 | 235 |
| 241 // Unit tests pass in a process_id == -1. | 236 // Unit tests pass in a process_id == -1. |
| 242 SessionStorageNamespace* session_storage_namespace = NULL; | 237 SessionStorageNamespace* session_storage_namespace = NULL; |
| 243 if (process_id != -1) { | 238 if (process_id != -1) { |
| 244 RenderViewHost* source_render_view_host = | 239 RenderViewHost* source_render_view_host = |
| 245 RenderViewHost::FromID(process_id, route_id); | 240 RenderViewHost::FromID(process_id, route_id); |
| 246 if (!source_render_view_host || !source_render_view_host->GetView()) | 241 if (!source_render_view_host) |
| 247 return false; | 242 return NULL; |
| 248 session_storage_namespace = | 243 session_storage_namespace = |
| 249 source_render_view_host->GetSessionStorageNamespace(); | 244 source_render_view_host->GetSessionStorageNamespace(); |
| 250 | |
| 251 if (size.IsEmpty()) { | |
| 252 // Use the size of the tab requesting the prerendering. | |
| 253 WebContents* web_contents = | |
| 254 WebContents::FromRenderViewHost(source_render_view_host); | |
| 255 if (web_contents && web_contents->GetView()) { | |
| 256 gfx::Rect container_bounds; | |
| 257 web_contents->GetView()->GetContainerBounds(&container_bounds); | |
| 258 size = container_bounds.size(); | |
| 259 } | |
| 260 } | |
| 261 } | 245 } |
| 262 | 246 |
| 263 return AddPrerender(ORIGIN_LINK_REL_PRERENDER, | 247 return AddPrerender(ORIGIN_LINK_REL_PRERENDER, |
| 264 process_id, url, referrer, size, | 248 process_id, url, referrer, size, |
| 265 session_storage_namespace); | 249 session_storage_namespace); |
| 266 #endif | 250 #endif |
| 267 } | 251 } |
| 268 | 252 |
| 269 bool PrerenderManager::AddPrerenderFromOmnibox( | 253 PrerenderHandle* PrerenderManager::AddPrerenderFromOmnibox( |
| 270 const GURL& url, | 254 const GURL& url, |
| 271 SessionStorageNamespace* session_storage_namespace, | 255 SessionStorageNamespace* session_storage_namespace, |
| 272 gfx::Size size) { | 256 const gfx::Size& size) { |
| 273 if (!IsOmniboxEnabled(profile_)) | 257 if (!IsOmniboxEnabled(profile_)) |
| 274 return false; | 258 return NULL; |
| 275 return AddPrerender(ORIGIN_OMNIBOX, -1, url, | 259 return AddPrerender(ORIGIN_OMNIBOX, -1, url, content::Referrer(), size, |
| 276 content::Referrer(), size, | |
| 277 session_storage_namespace); | 260 session_storage_namespace); |
| 278 } | 261 } |
| 279 | 262 |
| 280 void PrerenderManager::MaybeCancelPrerender(const GURL& url) { | |
| 281 PrerenderContentsDataList::iterator it = FindPrerenderContentsForURL(url); | |
| 282 if (it == prerender_list_.end()) | |
| 283 return; | |
| 284 PrerenderContentsData& prerender_contents_data = *it; | |
| 285 if (--prerender_contents_data.active_count_ == 0) | |
| 286 prerender_contents_data.contents_->Destroy(FINAL_STATUS_CANCELLED); | |
| 287 } | |
| 288 | |
| 289 void PrerenderManager::DestroyPrerenderForRenderView( | 263 void PrerenderManager::DestroyPrerenderForRenderView( |
| 290 int process_id, int view_id, FinalStatus final_status) { | 264 int process_id, int view_id, FinalStatus final_status) { |
| 291 DCHECK(CalledOnValidThread()); | 265 DCHECK(CalledOnValidThread()); |
| 292 PrerenderContentsDataList::iterator it = | 266 if (PrerenderData* prerender_data = |
| 293 FindPrerenderContentsForChildRouteIdPair( | 267 FindPrerenderDataForChildAndRoute(process_id, view_id)) { |
| 294 std::make_pair(process_id, view_id)); | 268 prerender_data->contents_->Destroy(final_status); |
| 295 if (it != prerender_list_.end()) { | |
| 296 PrerenderContents* prerender_contents = it->contents_; | |
| 297 prerender_contents->Destroy(final_status); | |
| 298 } | 269 } |
| 299 } | 270 } |
| 300 | 271 |
| 301 void PrerenderManager::CancelAllPrerenders() { | 272 void PrerenderManager::CancelAllPrerenders() { |
| 302 DCHECK(CalledOnValidThread()); | 273 DCHECK(CalledOnValidThread()); |
| 303 while (!prerender_list_.empty()) { | 274 while (!active_prerender_list_.empty()) { |
| 304 PrerenderContentsData data = prerender_list_.front(); | 275 PrerenderContents* prerender_contents = |
| 305 DCHECK(data.contents_); | 276 active_prerender_list_.front()->contents(); |
| 306 data.contents_->Destroy(FINAL_STATUS_CANCELLED); | 277 prerender_contents->Destroy(FINAL_STATUS_CANCELLED); |
| 307 } | 278 } |
| 308 } | 279 } |
| 309 | 280 |
| 310 bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, | 281 bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, |
| 311 const GURL& url) { | 282 const GURL& url) { |
| 312 DCHECK(CalledOnValidThread()); | 283 DCHECK(CalledOnValidThread()); |
| 313 DCHECK(!IsWebContentsPrerendering(web_contents)); | 284 DCHECK(!IsWebContentsPrerendering(web_contents)); |
| 314 | 285 |
| 315 scoped_ptr<PrerenderContents> prerender_contents( | 286 RenderViewHost* old_render_view_host = web_contents->GetRenderViewHost(); |
| 316 GetEntryButNotSpecifiedWC(url, web_contents)); | 287 |
| 317 if (prerender_contents.get() == NULL) | 288 DeleteOldEntries(); |
| 289 DeletePendingDeleteEntries(); | |
| 290 PrerenderData* prerender_data = FindPrerenderData( | |
| 291 url, old_render_view_host->GetSessionStorageNamespace()); | |
| 292 if (!prerender_data) | |
| 318 return false; | 293 return false; |
| 294 DCHECK(prerender_data->contents_); | |
| 295 if (IsNoSwapInExperiment(prerender_data->contents_->experiment_id())) | |
| 296 return false; | |
| 297 | |
| 298 if (TabContents* new_tab_contents = | |
| 299 prerender_data->contents_->prerender_contents()) { | |
| 300 if (web_contents == new_tab_contents->web_contents()) | |
| 301 return false; // Do not swap in to ourself. | |
| 302 } | |
| 303 | |
| 304 scoped_ptr<PrerenderContents> prerender_contents(prerender_data->contents_); | |
| 305 std::list<linked_ptr<PrerenderData> >::iterator to_erase = | |
| 306 FindIteratorForPrerenderContents(prerender_contents.get()); | |
| 307 DCHECK(active_prerender_list_.end() != to_erase); | |
| 308 DCHECK_EQ(prerender_data, to_erase->get()); | |
| 309 active_prerender_list_.erase(to_erase); | |
| 319 | 310 |
| 320 // Do not use the prerendered version if there is an opener object. | 311 // Do not use the prerendered version if there is an opener object. |
| 321 if (web_contents->HasOpener()) { | 312 if (web_contents->HasOpener()) { |
| 322 prerender_contents.release()->Destroy(FINAL_STATUS_WINDOW_OPENER); | 313 prerender_contents.release()->Destroy(FINAL_STATUS_WINDOW_OPENER); |
| 323 return false; | 314 return false; |
| 324 } | 315 } |
| 325 | 316 |
| 326 // Even if we match, the location.hash might be different. Record this as a | |
| 327 // separate final status. | |
| 328 GURL matching_url; | |
| 329 bool url_matches = prerender_contents->MatchesURL(url, &matching_url); | |
| 330 DCHECK(url_matches); | |
| 331 if (url_matches && url.ref() != matching_url.ref()) { | |
| 332 prerender_contents.release()->Destroy(FINAL_STATUS_FRAGMENT_MISMATCH); | |
| 333 return false; | |
| 334 } | |
| 335 | |
| 336 // If we are just in the control group (which can be detected by noticing | 317 // If we are just in the control group (which can be detected by noticing |
| 337 // that prerendering hasn't even started yet), record that |web_contents| now | 318 // that prerendering hasn't even started yet), record that |web_contents| now |
| 338 // would be showing a prerendered contents, but otherwise, don't do anything. | 319 // would be showing a prerendered contents, but otherwise, don't do anything. |
| 339 if (!prerender_contents->prerendering_has_started()) { | 320 if (!prerender_contents->prerendering_has_started()) { |
| 340 MarkWebContentsAsWouldBePrerendered(web_contents); | 321 MarkWebContentsAsWouldBePrerendered(web_contents); |
| 341 prerender_contents.release()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); | 322 prerender_contents.release()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); |
| 342 return false; | 323 return false; |
| 343 } | 324 } |
| 344 | 325 |
| 345 // Don't use prerendered pages if debugger is attached to the tab. | 326 // Don't use prerendered pages if debugger is attached to the tab. |
| 346 // See http://crbug.com/98541 | 327 // See http://crbug.com/98541 |
| 347 if (content::DevToolsAgentHostRegistry::IsDebuggerAttached(web_contents)) { | 328 if (content::DevToolsAgentHostRegistry::IsDebuggerAttached(web_contents)) { |
| 348 DestroyAndMarkMatchCompleteAsUsed(prerender_contents.release(), | 329 DestroyAndMarkMatchCompleteAsUsed(prerender_contents.release(), |
| 349 FINAL_STATUS_DEVTOOLS_ATTACHED); | 330 FINAL_STATUS_DEVTOOLS_ATTACHED); |
| 350 return false; | 331 return false; |
| 351 } | 332 } |
| 352 | 333 |
| 353 // If the prerendered page is in the middle of a cross-site navigation, | 334 // If the prerendered page is in the middle of a cross-site navigation, |
| 354 // don't swap it in because there isn't a good way to merge histories. | 335 // don't swap it in because there isn't a good way to merge histories. |
| 355 if (prerender_contents->IsCrossSiteNavigationPending()) { | 336 if (prerender_contents->IsCrossSiteNavigationPending()) { |
| 356 DestroyAndMarkMatchCompleteAsUsed( | 337 DestroyAndMarkMatchCompleteAsUsed( |
| 357 prerender_contents.release(), | 338 prerender_contents.release(), |
| 358 FINAL_STATUS_CROSS_SITE_NAVIGATION_PENDING); | 339 FINAL_STATUS_CROSS_SITE_NAVIGATION_PENDING); |
| 359 return false; | 340 return false; |
| 360 } | 341 } |
| 361 | 342 |
| 362 // If the session storage namespaces don't match, cancel the prerender. | |
| 363 RenderViewHost* old_render_view_host = web_contents->GetRenderViewHost(); | |
| 364 RenderViewHost* new_render_view_host = | |
| 365 prerender_contents->prerender_contents()->web_contents()-> | |
| 366 GetRenderViewHost(); | |
| 367 DCHECK(old_render_view_host); | |
| 368 DCHECK(new_render_view_host); | |
| 369 if (old_render_view_host->GetSessionStorageNamespace() != | |
| 370 new_render_view_host->GetSessionStorageNamespace()) { | |
| 371 DestroyAndMarkMatchCompleteAsUsed( | |
| 372 prerender_contents.release(), | |
| 373 FINAL_STATUS_SESSION_STORAGE_NAMESPACE_MISMATCH); | |
| 374 return false; | |
| 375 } | |
| 376 | |
| 377 // If we don't want to use prerenders at all, we are done. | |
| 378 // For bookkeeping purposes, we need to mark this WebContents to | 343 // For bookkeeping purposes, we need to mark this WebContents to |
| 379 // reflect that it would have been prerendered. | 344 // reflect that it would have been prerendered. |
| 380 if (GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP) { | 345 if (GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP) { |
| 381 MarkWebContentsAsWouldBePrerendered(web_contents); | 346 MarkWebContentsAsWouldBePrerendered(web_contents); |
| 382 prerender_contents.release()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); | 347 prerender_contents.release()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); |
| 383 return false; | 348 return false; |
| 384 } | 349 } |
| 385 | 350 |
| 386 int child_id, route_id; | 351 int child_id, route_id; |
| 387 CHECK(prerender_contents->GetChildId(&child_id)); | 352 CHECK(prerender_contents->GetChildId(&child_id)); |
| 388 CHECK(prerender_contents->GetRouteId(&route_id)); | 353 CHECK(prerender_contents->GetRouteId(&route_id)); |
| 389 | 354 |
| 390 // Try to set the prerendered page as used, so any subsequent attempts to | 355 // Try to set the prerendered page as used, so any subsequent attempts to |
| 391 // cancel on other threads will fail. If this fails because the prerender | 356 // cancel on other threads will fail. If this fails because the prerender |
| 392 // was already cancelled, possibly on another thread, fail. | 357 // was already cancelled, possibly on another thread, fail. |
| 393 if (!prerender_tracker_->TryUse(child_id, route_id)) | 358 if (!prerender_tracker_->TryUse(child_id, route_id)) |
| 394 return false; | 359 return false; |
| 395 | 360 |
| 361 // At this point, we've determined that we will use the prerender. | |
| 362 | |
| 396 if (!prerender_contents->load_start_time().is_null()) { | 363 if (!prerender_contents->load_start_time().is_null()) { |
| 397 histograms_->RecordTimeUntilUsed(GetCurrentTimeTicks() - | 364 histograms_->RecordTimeUntilUsed(GetCurrentTimeTicks() - |
| 398 prerender_contents->load_start_time(), | 365 prerender_contents->load_start_time(), |
| 399 GetMaxAge()); | 366 GetMaxAge()); |
| 400 } | 367 } |
| 401 | 368 |
| 402 histograms_->RecordPerSessionCount(++prerenders_per_session_count_); | 369 histograms_->RecordPerSessionCount(++prerenders_per_session_count_); |
| 403 histograms_->RecordUsedPrerender(prerender_contents->origin()); | 370 histograms_->RecordUsedPrerender(prerender_contents->origin()); |
| 404 prerender_contents->set_final_status(FINAL_STATUS_USED); | 371 prerender_contents->set_final_status(FINAL_STATUS_USED); |
| 405 | 372 |
| 373 RenderViewHost* new_render_view_host = | |
| 374 prerender_contents->prerender_contents()->web_contents()-> | |
| 375 GetRenderViewHost(); | |
| 406 new_render_view_host->Send( | 376 new_render_view_host->Send( |
| 407 new PrerenderMsg_SetIsPrerendering(new_render_view_host->GetRoutingID(), | 377 new PrerenderMsg_SetIsPrerendering(new_render_view_host->GetRoutingID(), |
| 408 false)); | 378 false)); |
| 409 | 379 |
| 380 // Start pending prerender requests from the PrerenderContents, if there are | |
| 381 // any. | |
| 382 prerender_contents->StartPendingPrerenders(); | |
| 383 | |
| 410 TabContents* new_tab_contents = | 384 TabContents* new_tab_contents = |
| 411 prerender_contents->ReleasePrerenderContents(); | 385 prerender_contents->ReleasePrerenderContents(); |
| 412 TabContents* old_tab_contents = TabContents::FromWebContents(web_contents); | 386 TabContents* old_tab_contents = TabContents::FromWebContents(web_contents); |
| 413 DCHECK(new_tab_contents); | 387 DCHECK(new_tab_contents); |
| 414 DCHECK(old_tab_contents); | 388 DCHECK(old_tab_contents); |
| 415 | 389 |
| 416 MarkWebContentsAsPrerendered(new_tab_contents->web_contents()); | 390 MarkWebContentsAsPrerendered(new_tab_contents->web_contents()); |
| 417 | 391 |
| 418 // Merge the browsing history. | 392 // Merge the browsing history. |
| 419 new_tab_contents->web_contents()->GetController().CopyStateFromAndPrune( | 393 new_tab_contents->web_contents()->GetController().CopyStateFromAndPrune( |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 432 } | 406 } |
| 433 | 407 |
| 434 // Update PPLT metrics: | 408 // Update PPLT metrics: |
| 435 // If the tab has finished loading, record a PPLT of 0. | 409 // If the tab has finished loading, record a PPLT of 0. |
| 436 // If the tab is still loading, reset its start time to the current time. | 410 // If the tab is still loading, reset its start time to the current time. |
| 437 PrerenderTabHelper* prerender_tab_helper = | 411 PrerenderTabHelper* prerender_tab_helper = |
| 438 new_tab_contents->prerender_tab_helper(); | 412 new_tab_contents->prerender_tab_helper(); |
| 439 DCHECK(prerender_tab_helper != NULL); | 413 DCHECK(prerender_tab_helper != NULL); |
| 440 prerender_tab_helper->PrerenderSwappedIn(); | 414 prerender_tab_helper->PrerenderSwappedIn(); |
| 441 | 415 |
| 442 // Start pending prerender requests from the PrerenderContents, if there are | |
| 443 // any. | |
| 444 prerender_contents->StartPendingPrerenders(); | |
| 445 | |
| 446 if (old_tab_contents->web_contents()->NeedToFireBeforeUnload()) { | 416 if (old_tab_contents->web_contents()->NeedToFireBeforeUnload()) { |
| 447 // Schedule the delete to occur after the tab has run its unload handlers. | 417 // Schedule the delete to occur after the tab has run its unload handlers. |
| 448 on_close_tab_contents_deleters_.push_back( | 418 on_close_tab_contents_deleters_.push_back( |
| 449 new OnCloseTabContentsDeleter(this, old_tab_contents)); | 419 new OnCloseTabContentsDeleter(this, old_tab_contents)); |
| 450 old_tab_contents->web_contents()->GetRenderViewHost()-> | 420 old_tab_contents->web_contents()->GetRenderViewHost()-> |
| 451 FirePageBeforeUnload(false); | 421 FirePageBeforeUnload(false); |
| 452 } else { | 422 } else { |
| 453 // No unload handler to run, so delete asap. | 423 // No unload handler to run, so delete asap. |
| 454 ScheduleDeleteOldTabContents(old_tab_contents, NULL); | 424 ScheduleDeleteOldTabContents(old_tab_contents, NULL); |
| 455 } | 425 } |
| 456 | 426 |
| 457 // TODO(cbentzel): Should prerender_contents move to the pending delete | 427 // TODO(cbentzel): Should prerender_contents move to the pending delete |
| 458 // list, instead of deleting directly here? | 428 // list, instead of deleting directly here? |
| 459 AddToHistory(prerender_contents.get()); | 429 AddToHistory(prerender_contents.get()); |
| 460 RecordNavigation(url); | 430 RecordNavigation(url); |
| 461 return true; | 431 return true; |
| 462 } | 432 } |
| 463 | 433 |
| 464 void PrerenderManager::MoveEntryToPendingDelete(PrerenderContents* entry, | 434 void PrerenderManager::MoveEntryToPendingDelete(PrerenderContents* entry, |
| 465 FinalStatus final_status) { | 435 FinalStatus final_status) { |
| 466 DCHECK(CalledOnValidThread()); | 436 DCHECK(CalledOnValidThread()); |
| 467 DCHECK(entry); | 437 DCHECK(entry); |
| 468 // Confirm this entry has not already been moved to the pending delete list. | 438 // Confirm this entry has not already been moved to the pending delete list. |
| 469 DCHECK_EQ(0, std::count(pending_delete_list_.begin(), | 439 DCHECK_EQ(0, std::count(pending_delete_list_.begin(), |
| 470 pending_delete_list_.end(), entry)); | 440 pending_delete_list_.end(), entry)); |
| 471 | 441 |
| 472 for (PrerenderContentsDataList::iterator it = prerender_list_.begin(); | 442 std::list<linked_ptr<PrerenderData> >::iterator it = |
| 473 it != prerender_list_.end(); | 443 FindIteratorForPrerenderContents(entry); |
| 474 ++it) { | |
| 475 if (it->contents_ == entry) { | |
| 476 bool swapped_in_dummy_replacement = false; | |
| 477 | 444 |
| 478 // If this PrerenderContents is being deleted due to a cancellation, | 445 // If this PrerenderContents is being deleted due to a cancellation, |
| 479 // we need to create a dummy replacement for PPLT accounting purposes | 446 // we need to create a dummy replacement for PPLT accounting purposes |
| 480 // for the Match Complete group. | 447 // for the Match Complete group. |
| 481 // This is the case if the cancellation is for any reason that would not | 448 // This is the case if the cancellation is for any reason that would not |
| 482 // occur in the control group case. | 449 // occur in the control group case. |
| 483 if (entry->match_complete_status() == | 450 if (it != active_prerender_list_.end()) { |
| 484 PrerenderContents::MATCH_COMPLETE_DEFAULT && | 451 if (entry->match_complete_status() == |
| 485 NeedMatchCompleteDummyForFinalStatus(final_status) && | 452 PrerenderContents::MATCH_COMPLETE_DEFAULT && |
| 486 ActuallyPrerendering()) { | 453 NeedMatchCompleteDummyForFinalStatus(final_status) && |
| 487 // TODO(tburkard): I'd like to DCHECK that we are actually prerendering. | 454 ActuallyPrerendering()) { |
| 488 // However, what if new conditions are added and | 455 // TODO(tburkard): I'd like to DCHECK that we are actually prerendering. |
| 489 // NeedMatchCompleteDummyForFinalStatus, is not being updated. Not sure | 456 // However, what if new conditions are added and |
| 490 // what's the best thing to do here. For now, I will just check whether | 457 // NeedMatchCompleteDummyForFinalStatus, is not being updated. Not sure |
| 491 // we are actually prerendering. | 458 // what's the best thing to do here. For now, I will just check whether |
| 492 entry->set_match_complete_status( | 459 // we are actually prerendering. |
| 493 PrerenderContents::MATCH_COMPLETE_REPLACED); | 460 entry->set_match_complete_status( |
| 494 if (PrerenderContents* dummy_replacement_prerender_contents = | 461 PrerenderContents::MATCH_COMPLETE_REPLACED); |
| 495 CreatePrerenderContents(entry->prerender_url(), | 462 PrerenderContents* dummy_replacement_prerender_contents = |
| 496 entry->referrer(), | 463 CreatePrerenderContents(entry->prerender_url(), entry->referrer(), |
| 497 entry->origin(), | 464 entry->origin(), entry->experiment_id()); |
| 498 entry->experiment_id())) { | 465 dummy_replacement_prerender_contents->MakeIntoDummyReplacementOf(entry); |
| 499 dummy_replacement_prerender_contents->set_match_complete_status( | 466 DCHECK(dummy_replacement_prerender_contents); |
| 500 PrerenderContents::MATCH_COMPLETE_REPLACEMENT_PENDING); | 467 |
| 501 if (!dummy_replacement_prerender_contents->Init()) | 468 dummy_replacement_prerender_contents->set_match_complete_status( |
| 502 break; | 469 PrerenderContents::MATCH_COMPLETE_REPLACEMENT_PENDING); |
| 503 dummy_replacement_prerender_contents-> | 470 DCHECK(dummy_replacement_prerender_contents->Init()); |
| 504 AddAliasURLsFromOtherPrerenderContents(entry); | 471 dummy_replacement_prerender_contents-> |
| 505 dummy_replacement_prerender_contents->set_match_complete_status( | 472 AddAliasURLsFromOtherPrerenderContents(entry); |
| 506 PrerenderContents::MATCH_COMPLETE_REPLACEMENT); | 473 dummy_replacement_prerender_contents->set_match_complete_status( |
| 507 it->contents_ = dummy_replacement_prerender_contents; | 474 PrerenderContents::MATCH_COMPLETE_REPLACEMENT); |
| 508 swapped_in_dummy_replacement = true; | 475 |
| 509 } | 476 it->get()->contents_ = dummy_replacement_prerender_contents; |
| 510 } | 477 } else { |
| 511 if (!swapped_in_dummy_replacement) | 478 active_prerender_list_.erase(it); |
| 512 prerender_list_.erase(it); | |
| 513 break; | |
| 514 } | 479 } |
| 515 } | 480 } |
| 481 | |
| 516 AddToHistory(entry); | 482 AddToHistory(entry); |
| 517 pending_delete_list_.push_back(entry); | 483 pending_delete_list_.push_back(entry); |
| 518 | 484 |
| 519 // Destroy the old WebContents relatively promptly to reduce resource usage, | 485 // Destroy the old WebContents relatively promptly to reduce resource usage, |
| 520 // and in the case of HTML5 media, reduce the change of playing any sound. | 486 // and in the case of HTML5 media, reduce the change of playing any sound. |
| 521 PostCleanupTask(); | 487 PostCleanupTask(); |
| 522 } | 488 } |
| 523 | 489 |
| 524 // static | 490 // static |
| 525 void PrerenderManager::RecordPerceivedPageLoadTime( | 491 void PrerenderManager::RecordPerceivedPageLoadTime( |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 616 } | 582 } |
| 617 | 583 |
| 618 // static | 584 // static |
| 619 bool PrerenderManager::IsNoUseGroup() { | 585 bool PrerenderManager::IsNoUseGroup() { |
| 620 return GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP; | 586 return GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP; |
| 621 } | 587 } |
| 622 | 588 |
| 623 bool PrerenderManager::IsWebContentsPrerendering( | 589 bool PrerenderManager::IsWebContentsPrerendering( |
| 624 WebContents* web_contents) const { | 590 WebContents* web_contents) const { |
| 625 DCHECK(CalledOnValidThread()); | 591 DCHECK(CalledOnValidThread()); |
| 626 for (PrerenderContentsDataList::const_iterator it = prerender_list_.begin(); | 592 for (std::list<linked_ptr<PrerenderData> >::const_iterator it = |
| 627 it != prerender_list_.end(); | 593 active_prerender_list_.begin(); |
| 594 it != active_prerender_list_.end(); | |
| 628 ++it) { | 595 ++it) { |
| 629 TabContents* prerender_tab_contents = it->contents_->prerender_contents(); | 596 TabContents* prerender_tab_contents = |
| 597 it->get()->contents_->prerender_contents(); | |
| 630 if (prerender_tab_contents && | 598 if (prerender_tab_contents && |
| 631 prerender_tab_contents->web_contents() == web_contents) { | 599 prerender_tab_contents->web_contents() == web_contents) { |
| 632 return true; | 600 return true; |
| 633 } | 601 } |
| 634 } | 602 } |
| 635 | 603 |
| 636 // Also look through the pending-deletion list. | 604 // Also look through the pending-deletion list. |
| 637 for (std::list<PrerenderContents*>::const_iterator it = | 605 for (std::list<PrerenderContents*>::const_iterator it = |
| 638 pending_delete_list_.begin(); | 606 pending_delete_list_.begin(); |
| 639 it != pending_delete_list_.end(); | 607 it != pending_delete_list_.end(); |
| 640 ++it) { | 608 ++it) { |
| 641 TabContents* prerender_tab_contents = (*it)->prerender_contents(); | 609 TabContents* prerender_tab_contents = (*it)->prerender_contents(); |
| 642 if (prerender_tab_contents && | 610 if (prerender_tab_contents && |
| 643 prerender_tab_contents->web_contents() == web_contents) | 611 prerender_tab_contents->web_contents() == web_contents) |
| 644 return true; | 612 return true; |
| 645 } | 613 } |
| 646 | 614 |
| 647 return false; | 615 return false; |
| 648 } | 616 } |
| 649 | 617 |
| 650 bool PrerenderManager::DidPrerenderFinishLoading(const GURL& url) const { | |
| 651 DCHECK(CalledOnValidThread()); | |
| 652 PrerenderContents* contents = FindEntry(url); | |
| 653 return contents ? contents->has_finished_loading() : false; | |
| 654 } | |
| 655 | |
| 656 void PrerenderManager::MarkWebContentsAsPrerendered(WebContents* web_contents) { | 618 void PrerenderManager::MarkWebContentsAsPrerendered(WebContents* web_contents) { |
| 657 DCHECK(CalledOnValidThread()); | 619 DCHECK(CalledOnValidThread()); |
| 658 prerendered_tab_contents_set_.insert(web_contents); | 620 prerendered_tab_contents_set_.insert(web_contents); |
| 659 } | 621 } |
| 660 | 622 |
| 661 void PrerenderManager::MarkWebContentsAsWouldBePrerendered( | 623 void PrerenderManager::MarkWebContentsAsWouldBePrerendered( |
| 662 WebContents* web_contents) { | 624 WebContents* web_contents) { |
| 663 DCHECK(CalledOnValidThread()); | 625 DCHECK(CalledOnValidThread()); |
| 664 would_be_prerendered_map_[web_contents] = true; | 626 would_be_prerendered_map_[web_contents] = true; |
| 665 } | 627 } |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 761 histograms_->RecordFinalStatus(origin, | 723 histograms_->RecordFinalStatus(origin, |
| 762 experiment_id, | 724 experiment_id, |
| 763 mc_status, | 725 mc_status, |
| 764 final_status); | 726 final_status); |
| 765 } | 727 } |
| 766 | 728 |
| 767 void PrerenderManager::AddCondition(const PrerenderCondition* condition) { | 729 void PrerenderManager::AddCondition(const PrerenderCondition* condition) { |
| 768 prerender_conditions_.push_back(condition); | 730 prerender_conditions_.push_back(condition); |
| 769 } | 731 } |
| 770 | 732 |
| 771 bool PrerenderManager::IsPendingEntry(const GURL& url) const { | |
| 772 DCHECK(CalledOnValidThread()); | |
| 773 for (PrerenderContentsDataList::const_iterator it = prerender_list_.begin(); | |
| 774 it != prerender_list_.end(); | |
| 775 ++it) { | |
| 776 if (it->contents_->IsPendingEntry(url)) | |
| 777 return true; | |
| 778 } | |
| 779 return false; | |
| 780 } | |
| 781 | |
| 782 bool PrerenderManager::IsPrerendering(const GURL& url) const { | |
| 783 DCHECK(CalledOnValidThread()); | |
| 784 return (FindEntry(url) != NULL); | |
| 785 } | |
| 786 | |
| 787 void PrerenderManager::RecordNavigation(const GURL& url) { | 733 void PrerenderManager::RecordNavigation(const GURL& url) { |
| 788 DCHECK(CalledOnValidThread()); | 734 DCHECK(CalledOnValidThread()); |
| 789 | 735 |
| 790 navigations_.push_back(NavigationRecord(url, GetCurrentTimeTicks())); | 736 navigations_.push_back(NavigationRecord(url, GetCurrentTimeTicks())); |
| 791 CleanUpOldNavigations(); | 737 CleanUpOldNavigations(); |
| 792 } | 738 } |
| 793 | 739 |
| 794 // protected | 740 // protected |
| 741 PrerenderManager::PrerenderData::PrerenderData(PrerenderManager* manager) | |
| 742 : manager_(manager), contents_(NULL), handle_count_(0) { | |
| 743 } | |
| 744 | |
| 745 PrerenderManager::PrerenderData::PrerenderData(PrerenderManager* manager, | |
| 746 PrerenderContents* contents) | |
| 747 : manager_(manager), contents_(contents), handle_count_(0) { | |
| 748 } | |
| 749 | |
| 750 void PrerenderManager::PrerenderData::OnNewHandle() { | |
| 751 DCHECK(contents_ || handle_count_ == 0) << | |
| 752 "Cannot create multiple handles to a pending prerender."; | |
| 753 ++handle_count_; | |
| 754 } | |
| 755 | |
| 756 void PrerenderManager::PrerenderData::OnNavigateAwayByHandle() { | |
| 757 // TODO(gavinp): Implement reasonable behaviour for navigation away from | |
| 758 // launcher. We can't just call OnCancel, because many cases have redirect | |
| 759 // chains that will eventually lead to the correct prerendered page, and we | |
| 760 // don't want to delete our prerender just as it is going to be used. | |
| 761 | |
| 762 if (!contents_) { | |
| 763 DCHECK_EQ(1, handle_count_); | |
| 764 // Pending prerenders are not maintained in the active_prerender_list_, so | |
| 765 // they will not get normal expiry. Since this prerender hasn't even been | |
| 766 // launched yet, and it's held by a page that is being prerendered, we will | |
| 767 // just delete it. | |
| 768 manager_->DestroyPendingPrerenderData(this); | |
| 769 } | |
| 770 } | |
| 771 | |
| 772 void PrerenderManager::PrerenderData::OnCancelByHandle() { | |
| 773 DCHECK_LE(1, handle_count_); | |
| 774 DCHECK(contents_ || handle_count_ == 1); | |
| 775 | |
| 776 if (--handle_count_ == 0) { | |
| 777 if (contents_) { | |
| 778 // This will eventually remove this object from active_prerender_list_, | |
| 779 // triggering the linked_ptr auto deletion. | |
| 780 contents_->Destroy(FINAL_STATUS_CANCELLED); | |
| 781 } else { | |
| 782 manager_->DestroyPendingPrerenderData(this); | |
| 783 } | |
| 784 } | |
| 785 } | |
| 786 | |
| 787 PrerenderManager::PrerenderData::~PrerenderData() { | |
| 788 } | |
| 789 | |
| 795 void PrerenderManager::SetPrerenderContentsFactory( | 790 void PrerenderManager::SetPrerenderContentsFactory( |
| 796 PrerenderContents::Factory* prerender_contents_factory) { | 791 PrerenderContents::Factory* prerender_contents_factory) { |
| 797 DCHECK(CalledOnValidThread()); | 792 DCHECK(CalledOnValidThread()); |
| 798 prerender_contents_factory_.reset(prerender_contents_factory); | 793 prerender_contents_factory_.reset(prerender_contents_factory); |
| 799 } | 794 } |
| 800 | 795 |
| 796 void PrerenderManager::StartPendingPrerender( | |
| 797 PrerenderHandle* existing_prerender_handle, | |
| 798 Origin origin, | |
| 799 int process_id, | |
| 800 const GURL& url, | |
| 801 const content::Referrer& referrer, | |
| 802 const gfx::Size& size, | |
| 803 content::SessionStorageNamespace* session_storage_namespace) { | |
| 804 DCHECK(existing_prerender_handle); | |
| 805 DCHECK(existing_prerender_handle->IsValid()); | |
| 806 DCHECK(existing_prerender_handle->IsPending()); | |
| 807 | |
| 808 DVLOG(6) << "StartPendingPrerender"; | |
| 809 DVLOG(6) << "existing_prerender_handle->handle_count_ = " << | |
| 810 existing_prerender_handle->prerender_data_->handle_count_; | |
| 811 | |
| 812 DCHECK(process_id == -1 || session_storage_namespace); | |
| 813 | |
| 814 scoped_ptr<PrerenderHandle> swap_prerender_handle(AddPrerender( | |
| 815 origin, process_id, url, referrer, size, session_storage_namespace)); | |
| 816 if (swap_prerender_handle.get()) { | |
| 817 // AddPrerender has returned a new prerender handle to us. We want to make | |
| 818 // |existing_prerender_handle| active, so swap the underlying PrerenderData | |
| 819 // between the two handles, and delete our old handle (which will release | |
| 820 // our entry in the pending_prerender_list_). | |
| 821 existing_prerender_handle->SwapPrerenderDataWith( | |
| 822 swap_prerender_handle.get()); | |
| 823 swap_prerender_handle->OnCancel(); | |
| 824 return; | |
| 825 } | |
| 826 | |
| 827 // We could not start our Prerender. Canceling the existing handle will make | |
| 828 // it return false for PrerenderHandle::IsPending(), and will release the | |
| 829 // PrerenderData from pending_prerender_list_. | |
| 830 existing_prerender_handle->OnCancel(); | |
| 831 } | |
| 832 | |
| 833 void PrerenderManager::DestroyPendingPrerenderData( | |
| 834 PrerenderData* pending_prerender_data) { | |
| 835 for (std::list<linked_ptr<PrerenderData> >::iterator | |
| 836 it = pending_prerender_list_.begin(); | |
| 837 it != pending_prerender_list_.end(); | |
| 838 ++it) { | |
| 839 if (it->get() == pending_prerender_data) { | |
| 840 DCHECK_GE(1, it->get()->handle_count_); | |
|
gavinp
2012/07/14 14:04:52
This DCHECK was failing in the NavigateAway case;
| |
| 841 pending_prerender_list_.erase(it); | |
| 842 return; | |
| 843 } | |
| 844 } | |
| 845 NOTREACHED(); | |
| 846 } | |
| 847 | |
| 801 void PrerenderManager::DoShutdown() { | 848 void PrerenderManager::DoShutdown() { |
| 802 DestroyAllContents(FINAL_STATUS_MANAGER_SHUTDOWN); | 849 DestroyAllContents(FINAL_STATUS_MANAGER_SHUTDOWN); |
| 803 STLDeleteElements(&prerender_conditions_); | 850 STLDeleteElements(&prerender_conditions_); |
| 804 on_close_tab_contents_deleters_.reset(); | 851 on_close_tab_contents_deleters_.reset(); |
| 805 profile_ = NULL; | 852 profile_ = NULL; |
| 853 | |
| 854 DCHECK(active_prerender_list_.empty()); | |
| 806 } | 855 } |
| 807 | 856 |
| 808 // private | 857 // private |
| 809 bool PrerenderManager::AddPrerender( | 858 PrerenderHandle* PrerenderManager::AddPrerender( |
| 810 Origin origin, | 859 Origin origin, |
| 811 int process_id, | 860 int process_id, |
| 812 const GURL& url_arg, | 861 const GURL& url_arg, |
| 813 const content::Referrer& referrer, | 862 const content::Referrer& referrer, |
| 814 gfx::Size size, | 863 const gfx::Size& size, |
| 815 SessionStorageNamespace* session_storage_namespace) { | 864 SessionStorageNamespace* session_storage_namespace) { |
| 816 DCHECK(CalledOnValidThread()); | 865 DCHECK(CalledOnValidThread()); |
| 817 | 866 |
| 818 if (!IsEnabled()) | 867 if (!IsEnabled()) |
| 819 return false; | 868 return NULL; |
| 820 | 869 |
| 821 if (origin == ORIGIN_LINK_REL_PRERENDER && | 870 if (origin == ORIGIN_LINK_REL_PRERENDER && |
| 822 IsGoogleSearchResultURL(referrer.url)) { | 871 IsGoogleSearchResultURL(referrer.url)) { |
| 823 origin = ORIGIN_GWS_PRERENDER; | 872 origin = ORIGIN_GWS_PRERENDER; |
| 824 } | 873 } |
| 825 | 874 |
| 826 DeleteOldEntries(); | 875 DeleteOldEntries(); |
| 827 DeletePendingDeleteEntries(); | 876 DeletePendingDeleteEntries(); |
| 828 | 877 |
| 829 GURL url = url_arg; | 878 GURL url = url_arg; |
| 830 GURL alias_url; | 879 GURL alias_url; |
| 831 uint8 experiment = GetQueryStringBasedExperiment(url_arg); | 880 uint8 experiment = GetQueryStringBasedExperiment(url_arg); |
| 832 bool control_group_behavior = | 881 bool control_group_behavior = |
| 833 IsControlGroup() || IsControlGroupExperiment(experiment); | 882 IsControlGroup() || IsControlGroupExperiment(experiment); |
| 834 if (control_group_behavior && | 883 if (control_group_behavior && |
| 835 MaybeGetQueryStringBasedAliasURL(url, &alias_url)) { | 884 MaybeGetQueryStringBasedAliasURL(url, &alias_url)) { |
| 836 url = alias_url; | 885 url = alias_url; |
| 837 } | 886 } |
| 838 | 887 |
| 839 // From here on, we will record a FinalStatus so we need to register with the | 888 // From here on, we will record a FinalStatus so we need to register with the |
| 840 // histogram tracking. | 889 // histogram tracking. |
| 841 histograms_->RecordPrerender(origin, url_arg); | 890 histograms_->RecordPrerender(origin, url_arg); |
| 842 | 891 |
| 843 if (PrerenderContentsData* prerender_contents_data = FindEntryData(url)) { | 892 if (PrerenderData* preexisting_prerender_data = |
| 844 ++prerender_contents_data->active_count_; | 893 FindPrerenderData(url, session_storage_namespace)) { |
| 845 RecordFinalStatus(origin, experiment, FINAL_STATUS_DUPLICATE); | 894 RecordFinalStatus(origin, experiment, FINAL_STATUS_DUPLICATE); |
| 846 return true; | 895 return new PrerenderHandle(preexisting_prerender_data); |
| 847 } | 896 } |
| 848 | 897 |
| 849 // Do not prerender if there are too many render processes, and we would | 898 // Do not prerender if there are too many render processes, and we would |
| 850 // have to use an existing one. We do not want prerendering to happen in | 899 // have to use an existing one. We do not want prerendering to happen in |
| 851 // a shared process, so that we can always reliably lower the CPU | 900 // a shared process, so that we can always reliably lower the CPU |
| 852 // priority for prerendering. | 901 // priority for prerendering. |
| 853 // In single-process mode, ShouldTryToUseExistingProcessHost() always returns | 902 // In single-process mode, ShouldTryToUseExistingProcessHost() always returns |
| 854 // true, so that case needs to be explicitly checked for. | 903 // true, so that case needs to be explicitly checked for. |
| 855 // TODO(tburkard): Figure out how to cancel prerendering in the opposite | 904 // TODO(tburkard): Figure out how to cancel prerendering in the opposite |
| 856 // case, when a new tab is added to a process used for prerendering. | 905 // case, when a new tab is added to a process used for prerendering. |
| 857 // On Android we do reuse processes as we have a limited number of them and we | 906 // On Android we do reuse processes as we have a limited number of them and we |
| 858 // still want the benefits of prerendering even when several tabs are open. | 907 // still want the benefits of prerendering even when several tabs are open. |
| 859 #if !defined(OS_ANDROID) | 908 #if !defined(OS_ANDROID) |
| 860 if (content::RenderProcessHost::ShouldTryToUseExistingProcessHost( | 909 if (content::RenderProcessHost::ShouldTryToUseExistingProcessHost( |
| 861 profile_, url) && | 910 profile_, url) && |
| 862 !content::RenderProcessHost::run_renderer_in_process()) { | 911 !content::RenderProcessHost::run_renderer_in_process()) { |
| 863 RecordFinalStatus(origin, experiment, FINAL_STATUS_TOO_MANY_PROCESSES); | 912 RecordFinalStatus(origin, experiment, FINAL_STATUS_TOO_MANY_PROCESSES); |
| 864 return false; | 913 return NULL; |
| 865 } | 914 } |
| 866 #endif | 915 #endif |
| 867 | 916 |
| 868 // Check if enough time has passed since the last prerender. | 917 // Check if enough time has passed since the last prerender. |
| 869 if (!DoesRateLimitAllowPrerender()) { | 918 if (!DoesRateLimitAllowPrerender()) { |
| 870 // Cancel the prerender. We could add it to the pending prerender list but | 919 // Cancel the prerender. We could add it to the pending prerender list but |
| 871 // this doesn't make sense as the next prerender request will be triggered | 920 // this doesn't make sense as the next prerender request will be triggered |
| 872 // by a navigation and is unlikely to be the same site. | 921 // by a navigation and is unlikely to be the same site. |
| 873 RecordFinalStatus(origin, experiment, FINAL_STATUS_RATE_LIMIT_EXCEEDED); | 922 RecordFinalStatus(origin, experiment, FINAL_STATUS_RATE_LIMIT_EXCEEDED); |
| 874 return false; | 923 return NULL; |
| 875 } | 924 } |
| 876 | 925 |
| 877 PrerenderContents* prerender_contents = CreatePrerenderContents( | 926 PrerenderContents* prerender_contents = CreatePrerenderContents( |
| 878 url, referrer, origin, experiment); | 927 url, referrer, origin, experiment); |
| 879 if (!prerender_contents || !prerender_contents->Init()) | 928 if (!prerender_contents || !prerender_contents->Init()) |
| 880 return false; | 929 return NULL; |
| 881 | 930 |
| 882 histograms_->RecordPrerenderStarted(origin); | 931 histograms_->RecordPrerenderStarted(origin); |
| 883 | 932 |
| 884 // TODO(cbentzel): Move invalid checks here instead of PrerenderContents? | 933 // TODO(cbentzel): Move invalid checks here instead of PrerenderContents? |
| 885 PrerenderContentsData data(prerender_contents, GetCurrentTime()); | 934 active_prerender_list_.push_back( |
| 886 | 935 linked_ptr<PrerenderData>(new PrerenderData(this, prerender_contents))); |
| 887 prerender_list_.push_back(data); | 936 PrerenderHandle* prerender_handle = |
| 937 new PrerenderHandle(active_prerender_list_.back().get()); | |
| 888 | 938 |
| 889 last_prerender_start_time_ = GetCurrentTimeTicks(); | 939 last_prerender_start_time_ = GetCurrentTimeTicks(); |
| 890 | 940 |
| 891 if (size.IsEmpty()) | 941 gfx::Size contents_size = |
| 892 size = config_.default_tab_bounds.size(); | 942 size.IsEmpty() ? config_.default_tab_bounds.size() : size; |
| 893 | 943 |
| 894 data.contents_->StartPrerendering(process_id, size, session_storage_namespace, | 944 prerender_contents->StartPrerendering(process_id, contents_size, |
| 895 control_group_behavior); | 945 session_storage_namespace, |
| 946 control_group_behavior); | |
| 896 | 947 |
| 897 while (prerender_list_.size() > config_.max_elements) { | 948 while (active_prerender_list_.size() > config_.max_elements) { |
| 898 data = prerender_list_.front(); | 949 prerender_contents = active_prerender_list_.front()->contents_; |
| 899 prerender_list_.pop_front(); | 950 DCHECK(prerender_contents); |
| 900 data.contents_->Destroy(FINAL_STATUS_EVICTED); | 951 prerender_contents->Destroy(FINAL_STATUS_EVICTED); |
| 901 } | 952 } |
| 953 | |
| 902 StartSchedulingPeriodicCleanups(); | 954 StartSchedulingPeriodicCleanups(); |
| 903 return true; | 955 return prerender_handle; |
| 904 } | |
| 905 | |
| 906 PrerenderContents* PrerenderManager::GetEntry(const GURL& url) { | |
| 907 return GetEntryButNotSpecifiedWC(url, NULL); | |
| 908 } | |
| 909 | |
| 910 PrerenderContents* PrerenderManager::GetEntryButNotSpecifiedWC( | |
| 911 const GURL& url, | |
| 912 WebContents* wc) { | |
| 913 DCHECK(CalledOnValidThread()); | |
| 914 DeleteOldEntries(); | |
| 915 DeletePendingDeleteEntries(); | |
| 916 for (PrerenderContentsDataList::iterator it = prerender_list_.begin(); | |
| 917 it != prerender_list_.end(); | |
| 918 ++it) { | |
| 919 PrerenderContents* prerender_contents = it->contents_; | |
| 920 if (prerender_contents->MatchesURL(url, NULL) && | |
| 921 !IsNoSwapInExperiment(prerender_contents->experiment_id())) { | |
| 922 if (!prerender_contents->prerender_contents() || | |
| 923 !wc || | |
| 924 prerender_contents->prerender_contents()->web_contents() != wc) { | |
| 925 prerender_list_.erase(it); | |
| 926 return prerender_contents; | |
| 927 } | |
| 928 } | |
| 929 } | |
| 930 // Entry not found. | |
| 931 return NULL; | |
| 932 } | 956 } |
| 933 | 957 |
| 934 void PrerenderManager::StartSchedulingPeriodicCleanups() { | 958 void PrerenderManager::StartSchedulingPeriodicCleanups() { |
| 935 DCHECK(CalledOnValidThread()); | 959 DCHECK(CalledOnValidThread()); |
| 936 if (repeating_timer_.IsRunning()) | 960 if (repeating_timer_.IsRunning()) |
| 937 return; | 961 return; |
| 938 repeating_timer_.Start(FROM_HERE, | 962 repeating_timer_.Start(FROM_HERE, |
| 939 base::TimeDelta::FromMilliseconds(kPeriodicCleanupIntervalMs), | 963 base::TimeDelta::FromMilliseconds(kPeriodicCleanupIntervalMs), |
| 940 this, | 964 this, |
| 941 &PrerenderManager::PeriodicCleanup); | 965 &PrerenderManager::PeriodicCleanup); |
| 942 } | 966 } |
| 943 | 967 |
| 944 void PrerenderManager::MaybeStopSchedulingPeriodicCleanups() { | 968 void PrerenderManager::StopSchedulingPeriodicCleanups() { |
| 945 if (!prerender_list_.empty()) | |
| 946 return; | |
| 947 | |
| 948 DCHECK(CalledOnValidThread()); | 969 DCHECK(CalledOnValidThread()); |
| 949 repeating_timer_.Stop(); | 970 repeating_timer_.Stop(); |
| 950 } | 971 } |
| 951 | 972 |
| 952 void PrerenderManager::PeriodicCleanup() { | 973 void PrerenderManager::PeriodicCleanup() { |
| 953 DCHECK(CalledOnValidThread()); | 974 DCHECK(CalledOnValidThread()); |
| 954 DeleteOldTabContents(); | 975 DeleteOldTabContents(); |
| 955 DeleteOldEntries(); | 976 DeleteOldEntries(); |
| 977 if (active_prerender_list_.empty()) | |
| 978 StopSchedulingPeriodicCleanups(); | |
| 956 | 979 |
| 957 // Grab a copy of the current PrerenderContents pointers, so that we | 980 // Grab a copy of the current PrerenderContents pointers, so that we |
| 958 // will not interfere with potential deletions of the list. | 981 // will not interfere with potential deletions of the list. |
| 959 std::vector<PrerenderContents*> prerender_contents; | 982 std::vector<PrerenderContents*> prerender_contents; |
| 960 for (PrerenderContentsDataList::iterator it = prerender_list_.begin(); | 983 prerender_contents.reserve(active_prerender_list_.size()); |
| 961 it != prerender_list_.end(); | 984 for (std::list<linked_ptr<PrerenderData> >::iterator |
| 962 ++it) { | 985 it = active_prerender_list_.begin(); |
| 963 DCHECK(it->contents_); | 986 it != active_prerender_list_.end(); |
| 964 prerender_contents.push_back(it->contents_); | 987 ++it) { |
| 988 prerender_contents.push_back(it->get()->contents_); | |
| 965 } | 989 } |
| 966 for (std::vector<PrerenderContents*>::iterator it = | 990 std::for_each(prerender_contents.begin(), prerender_contents.end(), |
| 967 prerender_contents.begin(); | 991 std::mem_fun( |
| 968 it != prerender_contents.end(); | 992 &PrerenderContents::DestroyWhenUsingTooManyResources)); |
| 969 ++it) { | |
| 970 (*it)->DestroyWhenUsingTooManyResources(); | |
| 971 } | |
| 972 | 993 |
| 973 DeletePendingDeleteEntries(); | 994 DeletePendingDeleteEntries(); |
| 974 } | 995 } |
| 975 | 996 |
| 976 void PrerenderManager::PostCleanupTask() { | 997 void PrerenderManager::PostCleanupTask() { |
| 977 DCHECK(CalledOnValidThread()); | 998 DCHECK(CalledOnValidThread()); |
| 978 MessageLoop::current()->PostTask( | 999 MessageLoop::current()->PostTask( |
| 979 FROM_HERE, | 1000 FROM_HERE, |
| 980 base::Bind(&PrerenderManager::PeriodicCleanup, | 1001 base::Bind(&PrerenderManager::PeriodicCleanup, |
| 981 weak_factory_.GetWeakPtr())); | 1002 weak_factory_.GetWeakPtr())); |
| 982 } | 1003 } |
| 983 | 1004 |
| 984 base::TimeDelta PrerenderManager::GetMaxAge() const { | 1005 base::TimeDelta PrerenderManager::GetMaxAge() const { |
| 985 return (GetMode() == PRERENDER_MODE_EXPERIMENT_5MIN_TTL_GROUP ? | 1006 return (GetMode() == PRERENDER_MODE_EXPERIMENT_5MIN_TTL_GROUP ? |
| 986 base::TimeDelta::FromSeconds(300) : config_.max_age); | 1007 base::TimeDelta::FromSeconds(300) : config_.max_age); |
| 987 } | 1008 } |
| 988 | 1009 |
| 989 bool PrerenderManager::IsPrerenderElementFresh(const base::Time start) const { | 1010 bool PrerenderManager::IsPrerenderFresh(const base::TimeTicks start) const { |
| 990 DCHECK(CalledOnValidThread()); | 1011 DCHECK(CalledOnValidThread()); |
| 991 base::Time now = GetCurrentTime(); | 1012 return GetCurrentTimeTicks() - start < GetMaxAge(); |
| 992 return (now - start < GetMaxAge()); | |
| 993 } | 1013 } |
| 994 | 1014 |
| 995 void PrerenderManager::DeleteOldEntries() { | 1015 void PrerenderManager::DeleteOldEntries() { |
| 996 DCHECK(CalledOnValidThread()); | 1016 DCHECK(CalledOnValidThread()); |
| 997 while (!prerender_list_.empty()) { | 1017 while (!active_prerender_list_.empty()) { |
| 998 PrerenderContentsData data = prerender_list_.front(); | 1018 PrerenderContents* contents = active_prerender_list_.front()->contents_; |
| 999 if (IsPrerenderElementFresh(data.start_time_)) | 1019 DCHECK(contents); |
| 1020 if (IsPrerenderFresh(contents->load_start_time())) | |
| 1000 return; | 1021 return; |
| 1001 data.contents_->Destroy(FINAL_STATUS_TIMED_OUT); | 1022 contents->Destroy(FINAL_STATUS_TIMED_OUT); |
| 1002 } | 1023 } |
| 1003 MaybeStopSchedulingPeriodicCleanups(); | |
| 1004 } | 1024 } |
| 1005 | 1025 |
| 1006 base::Time PrerenderManager::GetCurrentTime() const { | 1026 base::Time PrerenderManager::GetCurrentTime() const { |
| 1007 return base::Time::Now(); | 1027 return base::Time::Now(); |
| 1008 } | 1028 } |
| 1009 | 1029 |
| 1010 base::TimeTicks PrerenderManager::GetCurrentTimeTicks() const { | 1030 base::TimeTicks PrerenderManager::GetCurrentTimeTicks() const { |
| 1011 return base::TimeTicks::Now(); | 1031 return base::TimeTicks::Now(); |
| 1012 } | 1032 } |
| 1013 | 1033 |
| 1014 PrerenderContents* PrerenderManager::CreatePrerenderContents( | 1034 PrerenderContents* PrerenderManager::CreatePrerenderContents( |
| 1015 const GURL& url, | 1035 const GURL& url, |
| 1016 const content::Referrer& referrer, | 1036 const content::Referrer& referrer, |
| 1017 Origin origin, | 1037 Origin origin, |
| 1018 uint8 experiment_id) { | 1038 uint8 experiment_id) { |
| 1019 DCHECK(CalledOnValidThread()); | 1039 DCHECK(CalledOnValidThread()); |
| 1020 return prerender_contents_factory_->CreatePrerenderContents( | 1040 return prerender_contents_factory_->CreatePrerenderContents( |
| 1021 this, prerender_tracker_, profile_, url, | 1041 this, prerender_tracker_, profile_, url, |
| 1022 referrer, origin, experiment_id); | 1042 referrer, origin, experiment_id); |
| 1023 } | 1043 } |
| 1024 | 1044 |
| 1025 void PrerenderManager::DeletePendingDeleteEntries() { | 1045 void PrerenderManager::DeletePendingDeleteEntries() { |
| 1026 while (!pending_delete_list_.empty()) { | 1046 while (!pending_delete_list_.empty()) { |
| 1027 PrerenderContents* contents = pending_delete_list_.front(); | 1047 PrerenderContents* contents = pending_delete_list_.front(); |
| 1028 pending_delete_list_.pop_front(); | 1048 pending_delete_list_.pop_front(); |
| 1029 delete contents; | 1049 delete contents; |
| 1030 } | 1050 } |
| 1031 } | 1051 } |
| 1032 | 1052 |
| 1033 PrerenderManager::PrerenderContentsData* PrerenderManager::FindEntryData( | 1053 PrerenderManager::PrerenderData* PrerenderManager::FindPrerenderData( |
| 1034 const GURL& url) { | 1054 const GURL& url, |
| 1035 DCHECK(CalledOnValidThread()); | 1055 const SessionStorageNamespace* session_storage_namespace) { |
| 1036 PrerenderContentsDataList::iterator it = FindPrerenderContentsForURL(url); | 1056 for (std::list<linked_ptr<PrerenderData> >::iterator |
| 1037 if (it == prerender_list_.end()) | 1057 it = active_prerender_list_.begin(); |
| 1038 return NULL; | 1058 it != active_prerender_list_.end(); |
| 1039 PrerenderContentsData& prerender_contents_data = *it; | |
| 1040 return &prerender_contents_data; | |
| 1041 } | |
| 1042 | |
| 1043 PrerenderContents* PrerenderManager::FindEntry(const GURL& url) const { | |
| 1044 DCHECK(CalledOnValidThread()); | |
| 1045 for (PrerenderContentsDataList::const_iterator it = prerender_list_.begin(); | |
| 1046 it != prerender_list_.end(); | |
| 1047 ++it) { | 1059 ++it) { |
| 1048 if (it->contents_->MatchesURL(url, NULL)) | 1060 PrerenderContents* prerender_contents = it->get()->contents_; |
| 1049 return it->contents_; | 1061 if (prerender_contents->Matches(url, session_storage_namespace)) |
| 1062 return it->get(); | |
| 1050 } | 1063 } |
| 1051 // Entry not found. | |
| 1052 return NULL; | 1064 return NULL; |
| 1053 } | 1065 } |
| 1054 | 1066 |
| 1055 PrerenderManager::PrerenderContentsDataList::iterator | 1067 PrerenderManager::PrerenderData* |
| 1056 PrerenderManager::FindPrerenderContentsForChildRouteIdPair( | 1068 PrerenderManager::FindPrerenderDataForChildAndRoute( |
| 1057 const std::pair<int, int>& child_route_id_pair) { | 1069 const int child_id, const int route_id) { |
| 1058 PrerenderContentsDataList::iterator it = prerender_list_.begin(); | 1070 for (std::list<linked_ptr<PrerenderData> >::iterator |
| 1059 for (; it != prerender_list_.end(); ++it) { | 1071 it = active_prerender_list_.begin(); |
| 1060 PrerenderContents* prerender_contents = it->contents_; | 1072 it != active_prerender_list_.end(); |
| 1073 ++it) { | |
| 1074 PrerenderContents* prerender_contents = it->get()->contents_; | |
| 1061 | 1075 |
| 1062 int child_id; | 1076 int contents_child_id; |
| 1063 int route_id; | 1077 if (!prerender_contents->GetChildId(&contents_child_id)) |
| 1064 bool has_child_id = prerender_contents->GetChildId(&child_id); | 1078 continue; |
| 1065 bool has_route_id = has_child_id && | 1079 int contents_route_id; |
| 1066 prerender_contents->GetRouteId(&route_id); | 1080 if (!prerender_contents->GetRouteId(&contents_route_id)) |
| 1081 continue; | |
| 1067 | 1082 |
| 1068 if (has_child_id && has_route_id && | 1083 if (contents_child_id == child_id && contents_route_id == route_id) |
| 1069 child_id == child_route_id_pair.first && | 1084 return it->get(); |
| 1070 route_id == child_route_id_pair.second) { | |
| 1071 break; | |
| 1072 } | |
| 1073 } | 1085 } |
| 1074 return it; | 1086 return NULL; |
| 1075 } | 1087 } |
| 1076 | 1088 |
| 1077 PrerenderManager::PrerenderContentsDataList::iterator | 1089 std::list<linked_ptr<PrerenderManager::PrerenderData> >::iterator |
| 1078 PrerenderManager::FindPrerenderContentsForURL(const GURL& url) { | 1090 PrerenderManager::FindIteratorForPrerenderContents( |
| 1079 for (PrerenderContentsDataList::iterator it = prerender_list_.begin(); | 1091 PrerenderContents* prerender_contents) { |
| 1080 it != prerender_list_.end(); ++it) { | 1092 for (std::list<linked_ptr<PrerenderData> >::iterator |
| 1081 if (it->contents_->MatchesURL(url, NULL)) | 1093 it = active_prerender_list_.begin(); |
| 1094 it != active_prerender_list_.end(); | |
| 1095 ++it) { | |
| 1096 if (prerender_contents == it->get()->contents_) | |
| 1082 return it; | 1097 return it; |
| 1083 } | 1098 } |
| 1084 return prerender_list_.end(); | 1099 return active_prerender_list_.end(); |
| 1085 } | 1100 } |
| 1086 | 1101 |
| 1087 bool PrerenderManager::DoesRateLimitAllowPrerender() const { | 1102 bool PrerenderManager::DoesRateLimitAllowPrerender() const { |
| 1088 DCHECK(CalledOnValidThread()); | 1103 DCHECK(CalledOnValidThread()); |
| 1089 base::TimeDelta elapsed_time = | 1104 base::TimeDelta elapsed_time = |
| 1090 GetCurrentTimeTicks() - last_prerender_start_time_; | 1105 GetCurrentTimeTicks() - last_prerender_start_time_; |
| 1091 histograms_->RecordTimeBetweenPrerenderRequests(elapsed_time); | 1106 histograms_->RecordTimeBetweenPrerenderRequests(elapsed_time); |
| 1092 if (!config_.rate_limit_enabled) | 1107 if (!config_.rate_limit_enabled) |
| 1093 return true; | 1108 return true; |
| 1094 return elapsed_time > | 1109 return elapsed_time > |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1136 void PrerenderManager::AddToHistory(PrerenderContents* contents) { | 1151 void PrerenderManager::AddToHistory(PrerenderContents* contents) { |
| 1137 PrerenderHistory::Entry entry(contents->prerender_url(), | 1152 PrerenderHistory::Entry entry(contents->prerender_url(), |
| 1138 contents->final_status(), | 1153 contents->final_status(), |
| 1139 contents->origin(), | 1154 contents->origin(), |
| 1140 base::Time::Now()); | 1155 base::Time::Now()); |
| 1141 prerender_history_->AddEntry(entry); | 1156 prerender_history_->AddEntry(entry); |
| 1142 } | 1157 } |
| 1143 | 1158 |
| 1144 Value* PrerenderManager::GetActivePrerendersAsValue() const { | 1159 Value* PrerenderManager::GetActivePrerendersAsValue() const { |
| 1145 ListValue* list_value = new ListValue(); | 1160 ListValue* list_value = new ListValue(); |
| 1146 for (PrerenderContentsDataList::const_iterator it = prerender_list_.begin(); | 1161 for (std::list<linked_ptr<PrerenderData> >::const_iterator it = |
| 1147 it != prerender_list_.end(); | 1162 active_prerender_list_.begin(); |
| 1163 it != active_prerender_list_.end(); | |
| 1148 ++it) { | 1164 ++it) { |
| 1149 Value* prerender_value = it->contents_->GetAsValue(); | 1165 if (Value* prerender_value = it->get()->contents_->GetAsValue()) |
| 1150 if (!prerender_value) | 1166 list_value->Append(prerender_value); |
| 1151 continue; | |
| 1152 list_value->Append(prerender_value); | |
| 1153 } | 1167 } |
| 1154 return list_value; | 1168 return list_value; |
| 1155 } | 1169 } |
| 1156 | 1170 |
| 1157 void PrerenderManager::DestroyAllContents(FinalStatus final_status) { | 1171 void PrerenderManager::DestroyAllContents(FinalStatus final_status) { |
| 1158 DeleteOldTabContents(); | 1172 DeleteOldTabContents(); |
| 1159 while (!prerender_list_.empty()) { | 1173 while (!active_prerender_list_.empty()) { |
| 1160 PrerenderContentsData data = prerender_list_.front(); | 1174 PrerenderContents* contents = active_prerender_list_.front()->contents_; |
| 1161 prerender_list_.pop_front(); | 1175 contents->Destroy(final_status); |
| 1162 data.contents_->Destroy(final_status); | |
| 1163 } | 1176 } |
| 1164 DeletePendingDeleteEntries(); | 1177 DeletePendingDeleteEntries(); |
| 1165 } | 1178 } |
| 1166 | 1179 |
| 1167 void PrerenderManager::DestroyAndMarkMatchCompleteAsUsed( | 1180 void PrerenderManager::DestroyAndMarkMatchCompleteAsUsed( |
| 1168 PrerenderContents* prerender_contents, | 1181 PrerenderContents* prerender_contents, |
| 1169 FinalStatus final_status) { | 1182 FinalStatus final_status) { |
| 1170 prerender_contents->set_match_complete_status( | 1183 prerender_contents->set_match_complete_status( |
| 1171 PrerenderContents::MATCH_COMPLETE_REPLACED); | 1184 PrerenderContents::MATCH_COMPLETE_REPLACED); |
| 1172 histograms_->RecordFinalStatus(prerender_contents->origin(), | 1185 histograms_->RecordFinalStatus(prerender_contents->origin(), |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1211 if (!render_process_host || !render_process_host->GetBrowserContext()) | 1224 if (!render_process_host || !render_process_host->GetBrowserContext()) |
| 1212 return NULL; | 1225 return NULL; |
| 1213 Profile* profile = Profile::FromBrowserContext( | 1226 Profile* profile = Profile::FromBrowserContext( |
| 1214 render_process_host->GetBrowserContext()); | 1227 render_process_host->GetBrowserContext()); |
| 1215 if (!profile) | 1228 if (!profile) |
| 1216 return NULL; | 1229 return NULL; |
| 1217 return PrerenderManagerFactory::GetInstance()->GetForProfile(profile); | 1230 return PrerenderManagerFactory::GetInstance()->GetForProfile(profile); |
| 1218 } | 1231 } |
| 1219 | 1232 |
| 1220 } // namespace prerender | 1233 } // namespace prerender |
| 1234 | |
| OLD | NEW |