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 <algorithm> | 7 #include <algorithm> |
8 #include <functional> | 8 #include <functional> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
158 bool PrerenderManager::is_prefetch_enabled_ = false; | 158 bool PrerenderManager::is_prefetch_enabled_ = false; |
159 | 159 |
160 // static | 160 // static |
161 int PrerenderManager::prerenders_per_session_count_ = 0; | 161 int PrerenderManager::prerenders_per_session_count_ = 0; |
162 | 162 |
163 // static | 163 // static |
164 PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = | 164 PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = |
165 PRERENDER_MODE_ENABLED; | 165 PRERENDER_MODE_ENABLED; |
166 | 166 |
167 struct PrerenderManager::NavigationRecord { | 167 struct PrerenderManager::NavigationRecord { |
168 GURL url_; | 168 GURL url; |
169 base::TimeTicks time_; | 169 base::TimeTicks time; |
170 | |
170 NavigationRecord(const GURL& url, base::TimeTicks time) | 171 NavigationRecord(const GURL& url, base::TimeTicks time) |
171 : url_(url), | 172 : url(url), |
172 time_(time) { | 173 time(time) { |
173 } | 174 } |
mmenke
2012/10/15 15:28:28
While you're here, please put the constructor firs
gavinp
2012/10/15 18:32:39
Done.
| |
174 }; | 175 }; |
175 | 176 |
177 PrerenderManager::PrerenderedWebContentsData:: | |
178 PrerenderedWebContentsData(Origin origin) : origin(origin) { | |
179 } | |
180 | |
181 PrerenderManager::WouldBePrerenderedWebContentsData:: | |
182 WouldBePrerenderedWebContentsData(Origin origin) : origin(origin), | |
183 state(INITIAL_STATE) { | |
184 } | |
185 | |
176 PrerenderManager::PrerenderManager(Profile* profile, | 186 PrerenderManager::PrerenderManager(Profile* profile, |
177 PrerenderTracker* prerender_tracker) | 187 PrerenderTracker* prerender_tracker) |
178 : enabled_(true), | 188 : enabled_(true), |
179 profile_(profile), | 189 profile_(profile), |
180 prerender_tracker_(prerender_tracker), | 190 prerender_tracker_(prerender_tracker), |
181 prerender_contents_factory_(PrerenderContents::CreateFactory()), | 191 prerender_contents_factory_(PrerenderContents::CreateFactory()), |
182 last_prerender_start_time_(GetCurrentTimeTicks() - | 192 last_prerender_start_time_(GetCurrentTimeTicks() - |
183 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs)), | 193 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs)), |
184 weak_factory_(this), | 194 weak_factory_(this), |
185 prerender_history_(new PrerenderHistory(kHistoryLength)), | 195 prerender_history_(new PrerenderHistory(kHistoryLength)), |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
225 FindPrerenderDataForChildAndRoute(process_id, route_id)) { | 235 FindPrerenderDataForChildAndRoute(process_id, route_id)) { |
226 // Instead of prerendering from inside of a running prerender, we will defer | 236 // Instead of prerendering from inside of a running prerender, we will defer |
227 // this request until its launcher is made visible. | 237 // this request until its launcher is made visible. |
228 if (PrerenderContents* contents = parent_prerender_data->contents_) { | 238 if (PrerenderContents* contents = parent_prerender_data->contents_) { |
229 pending_prerender_list_.push_back( | 239 pending_prerender_list_.push_back( |
230 linked_ptr<PrerenderData>(new PrerenderData(this))); | 240 linked_ptr<PrerenderData>(new PrerenderData(this))); |
231 PrerenderHandle* prerender_handle = | 241 PrerenderHandle* prerender_handle = |
232 new PrerenderHandle(pending_prerender_list_.back().get()); | 242 new PrerenderHandle(pending_prerender_list_.back().get()); |
233 contents->AddPendingPrerender( | 243 contents->AddPendingPrerender( |
234 prerender_handle->weak_ptr_factory_.GetWeakPtr(), | 244 prerender_handle->weak_ptr_factory_.GetWeakPtr(), |
235 url, referrer, size); | 245 ORIGIN_LINK_REL_PRERENDER, url, referrer, size); |
236 return prerender_handle; | 246 return prerender_handle; |
237 } | 247 } |
238 } | 248 } |
239 | 249 |
240 // Unit tests pass in a process_id == -1. | 250 // Unit tests pass in a process_id == -1. |
241 SessionStorageNamespace* session_storage_namespace = NULL; | 251 SessionStorageNamespace* session_storage_namespace = NULL; |
242 if (process_id != -1) { | 252 if (process_id != -1) { |
243 RenderViewHost* source_render_view_host = | 253 RenderViewHost* source_render_view_host = |
244 RenderViewHost::FromID(process_id, route_id); | 254 RenderViewHost::FromID(process_id, route_id); |
245 if (!source_render_view_host) | 255 if (!source_render_view_host) |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
284 while (!active_prerender_list_.empty()) { | 294 while (!active_prerender_list_.empty()) { |
285 PrerenderContents* prerender_contents = | 295 PrerenderContents* prerender_contents = |
286 active_prerender_list_.front()->contents(); | 296 active_prerender_list_.front()->contents(); |
287 prerender_contents->Destroy(FINAL_STATUS_CANCELLED); | 297 prerender_contents->Destroy(FINAL_STATUS_CANCELLED); |
288 } | 298 } |
289 } | 299 } |
290 | 300 |
291 bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, | 301 bool PrerenderManager::MaybeUsePrerenderedPage(WebContents* web_contents, |
292 const GURL& url) { | 302 const GURL& url) { |
293 DCHECK(CalledOnValidThread()); | 303 DCHECK(CalledOnValidThread()); |
294 DCHECK(!IsWebContentsPrerendering(web_contents)); | 304 DCHECK(!IsWebContentsPrerendering(web_contents, NULL)); |
295 | 305 |
296 DeleteOldEntries(); | 306 DeleteOldEntries(); |
297 DeletePendingDeleteEntries(); | 307 DeletePendingDeleteEntries(); |
298 // TODO(ajwong): This doesn't handle isolated apps correctly. | 308 // TODO(ajwong): This doesn't handle isolated apps correctly. |
299 PrerenderData* prerender_data = FindPrerenderData( | 309 PrerenderData* prerender_data = FindPrerenderData( |
300 url, | 310 url, |
301 web_contents->GetController().GetDefaultSessionStorageNamespace()); | 311 web_contents->GetController().GetDefaultSessionStorageNamespace()); |
302 if (!prerender_data) | 312 if (!prerender_data) |
303 return false; | 313 return false; |
304 DCHECK(prerender_data->contents_); | 314 DCHECK(prerender_data->contents_); |
(...skipping 16 matching lines...) Expand all Loading... | |
321 // Do not use the prerendered version if there is an opener object. | 331 // Do not use the prerendered version if there is an opener object. |
322 if (web_contents->HasOpener()) { | 332 if (web_contents->HasOpener()) { |
323 prerender_contents.release()->Destroy(FINAL_STATUS_WINDOW_OPENER); | 333 prerender_contents.release()->Destroy(FINAL_STATUS_WINDOW_OPENER); |
324 return false; | 334 return false; |
325 } | 335 } |
326 | 336 |
327 // If we are just in the control group (which can be detected by noticing | 337 // If we are just in the control group (which can be detected by noticing |
328 // that prerendering hasn't even started yet), record that |web_contents| now | 338 // that prerendering hasn't even started yet), record that |web_contents| now |
329 // would be showing a prerendered contents, but otherwise, don't do anything. | 339 // would be showing a prerendered contents, but otherwise, don't do anything. |
330 if (!prerender_contents->prerendering_has_started()) { | 340 if (!prerender_contents->prerendering_has_started()) { |
331 MarkWebContentsAsWouldBePrerendered(web_contents); | 341 MarkWebContentsAsWouldBePrerendered(web_contents, |
342 prerender_contents->origin()); | |
332 prerender_contents.release()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); | 343 prerender_contents.release()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); |
333 return false; | 344 return false; |
334 } | 345 } |
335 | 346 |
336 // Don't use prerendered pages if debugger is attached to the tab. | 347 // Don't use prerendered pages if debugger is attached to the tab. |
337 // See http://crbug.com/98541 | 348 // See http://crbug.com/98541 |
338 if (content::DevToolsAgentHostRegistry::IsDebuggerAttached(web_contents)) { | 349 if (content::DevToolsAgentHostRegistry::IsDebuggerAttached(web_contents)) { |
339 DestroyAndMarkMatchCompleteAsUsed(prerender_contents.release(), | 350 DestroyAndMarkMatchCompleteAsUsed(prerender_contents.release(), |
340 FINAL_STATUS_DEVTOOLS_ATTACHED); | 351 FINAL_STATUS_DEVTOOLS_ATTACHED); |
341 return false; | 352 return false; |
342 } | 353 } |
343 | 354 |
344 // If the prerendered page is in the middle of a cross-site navigation, | 355 // If the prerendered page is in the middle of a cross-site navigation, |
345 // don't swap it in because there isn't a good way to merge histories. | 356 // don't swap it in because there isn't a good way to merge histories. |
346 if (prerender_contents->IsCrossSiteNavigationPending()) { | 357 if (prerender_contents->IsCrossSiteNavigationPending()) { |
347 DestroyAndMarkMatchCompleteAsUsed( | 358 DestroyAndMarkMatchCompleteAsUsed( |
348 prerender_contents.release(), | 359 prerender_contents.release(), |
349 FINAL_STATUS_CROSS_SITE_NAVIGATION_PENDING); | 360 FINAL_STATUS_CROSS_SITE_NAVIGATION_PENDING); |
350 return false; | 361 return false; |
351 } | 362 } |
352 | 363 |
353 // For bookkeeping purposes, we need to mark this WebContents to | 364 // For bookkeeping purposes, we need to mark this WebContents to |
354 // reflect that it would have been prerendered. | 365 // reflect that it would have been prerendered. |
355 if (GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP) { | 366 if (GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP) { |
356 MarkWebContentsAsWouldBePrerendered(web_contents); | 367 MarkWebContentsAsWouldBePrerendered(web_contents, |
368 prerender_contents->origin()); | |
357 prerender_contents.release()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); | 369 prerender_contents.release()->Destroy(FINAL_STATUS_WOULD_HAVE_BEEN_USED); |
358 return false; | 370 return false; |
359 } | 371 } |
360 | 372 |
361 int child_id, route_id; | 373 int child_id, route_id; |
362 CHECK(prerender_contents->GetChildId(&child_id)); | 374 CHECK(prerender_contents->GetChildId(&child_id)); |
363 CHECK(prerender_contents->GetRouteId(&route_id)); | 375 CHECK(prerender_contents->GetRouteId(&route_id)); |
364 | 376 |
365 // Try to set the prerendered page as used, so any subsequent attempts to | 377 // Try to set the prerendered page as used, so any subsequent attempts to |
366 // cancel on other threads will fail. If this fails because the prerender | 378 // cancel on other threads will fail. If this fails because the prerender |
367 // was already cancelled, possibly on another thread, fail. | 379 // was already cancelled, possibly on another thread, fail. |
368 if (!prerender_tracker_->TryUse(child_id, route_id)) | 380 if (!prerender_tracker_->TryUse(child_id, route_id)) |
369 return false; | 381 return false; |
370 | 382 |
371 // At this point, we've determined that we will use the prerender. | 383 // At this point, we've determined that we will use the prerender. |
372 | 384 |
373 if (!prerender_contents->load_start_time().is_null()) { | 385 if (!prerender_contents->load_start_time().is_null()) { |
374 histograms_->RecordTimeUntilUsed( | 386 histograms_->RecordTimeUntilUsed( |
387 prerender_contents->origin(), | |
375 GetCurrentTimeTicks() - prerender_contents->load_start_time(), | 388 GetCurrentTimeTicks() - prerender_contents->load_start_time(), |
376 config_.time_to_live); | 389 config_.time_to_live); |
377 } | 390 } |
378 | 391 |
379 histograms_->RecordPerSessionCount(++prerenders_per_session_count_); | 392 histograms_->RecordPerSessionCount(prerender_contents->origin(), |
393 ++prerenders_per_session_count_); | |
380 histograms_->RecordUsedPrerender(prerender_contents->origin()); | 394 histograms_->RecordUsedPrerender(prerender_contents->origin()); |
381 prerender_contents->set_final_status(FINAL_STATUS_USED); | 395 prerender_contents->set_final_status(FINAL_STATUS_USED); |
382 | 396 |
383 RenderViewHost* new_render_view_host = | 397 RenderViewHost* new_render_view_host = |
384 prerender_contents->prerender_contents()->web_contents()-> | 398 prerender_contents->prerender_contents()->web_contents()-> |
385 GetRenderViewHost(); | 399 GetRenderViewHost(); |
386 new_render_view_host->Send( | 400 new_render_view_host->Send( |
387 new PrerenderMsg_SetIsPrerendering(new_render_view_host->GetRoutingID(), | 401 new PrerenderMsg_SetIsPrerendering(new_render_view_host->GetRoutingID(), |
388 false)); | 402 false)); |
389 | 403 |
390 // Start pending prerender requests from the PrerenderContents, if there are | 404 // Start pending prerender requests from the PrerenderContents, if there are |
391 // any. | 405 // any. |
392 prerender_contents->StartPendingPrerenders(); | 406 prerender_contents->StartPendingPrerenders(); |
393 | 407 |
394 TabContents* new_tab_contents = | 408 TabContents* new_tab_contents = |
395 prerender_contents->ReleasePrerenderContents(); | 409 prerender_contents->ReleasePrerenderContents(); |
396 TabContents* old_tab_contents = TabContents::FromWebContents(web_contents); | 410 TabContents* old_tab_contents = TabContents::FromWebContents(web_contents); |
397 DCHECK(new_tab_contents); | 411 DCHECK(new_tab_contents); |
398 DCHECK(old_tab_contents); | 412 DCHECK(old_tab_contents); |
399 | 413 |
400 MarkWebContentsAsPrerendered(new_tab_contents->web_contents()); | 414 MarkWebContentsAsPrerendered(new_tab_contents->web_contents(), |
415 prerender_contents->origin()); | |
401 | 416 |
402 // Merge the browsing history. | 417 // Merge the browsing history. |
403 new_tab_contents->web_contents()->GetController().CopyStateFromAndPrune( | 418 new_tab_contents->web_contents()->GetController().CopyStateFromAndPrune( |
404 &old_tab_contents->web_contents()->GetController()); | 419 &old_tab_contents->web_contents()->GetController()); |
405 CoreTabHelper::FromWebContents(old_tab_contents->web_contents())->delegate()-> | 420 CoreTabHelper::FromWebContents(old_tab_contents->web_contents())->delegate()-> |
406 SwapTabContents(old_tab_contents->web_contents(), | 421 SwapTabContents(old_tab_contents->web_contents(), |
407 new_tab_contents->web_contents()); | 422 new_tab_contents->web_contents()); |
408 prerender_contents->CommitHistory(new_tab_contents); | 423 prerender_contents->CommitHistory(new_tab_contents); |
409 | 424 |
410 GURL icon_url = prerender_contents->icon_url(); | 425 GURL icon_url = prerender_contents->icon_url(); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
504 WebContents* web_contents, | 519 WebContents* web_contents, |
505 const GURL& url) { | 520 const GURL& url) { |
506 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 521 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
507 PrerenderManager* prerender_manager = | 522 PrerenderManager* prerender_manager = |
508 PrerenderManagerFactory::GetForProfile( | 523 PrerenderManagerFactory::GetForProfile( |
509 Profile::FromBrowserContext(web_contents->GetBrowserContext())); | 524 Profile::FromBrowserContext(web_contents->GetBrowserContext())); |
510 if (!prerender_manager) | 525 if (!prerender_manager) |
511 return; | 526 return; |
512 if (!prerender_manager->IsEnabled()) | 527 if (!prerender_manager->IsEnabled()) |
513 return; | 528 return; |
514 bool was_prerender = | 529 |
515 prerender_manager->IsWebContentsPrerendered(web_contents); | 530 Origin prerender_origin = ORIGIN_NONE; |
531 if (prerender_manager->IsWebContentsPrerendering(web_contents, | |
532 &prerender_origin)) { | |
533 prerender_manager->histograms_->RecordPageLoadTimeNotSwappedIn( | |
534 prerender_origin, perceived_page_load_time, url); | |
535 return; | |
536 } | |
537 | |
538 bool was_prerender = prerender_manager->IsWebContentsPrerendered( | |
539 web_contents, &prerender_origin); | |
516 bool was_complete_prerender = was_prerender || | 540 bool was_complete_prerender = was_prerender || |
517 prerender_manager->WouldWebContentsBePrerendered(web_contents); | 541 prerender_manager->WouldWebContentsBePrerendered(web_contents, |
518 if (prerender_manager->IsWebContentsPrerendering(web_contents)) { | 542 &prerender_origin); |
519 prerender_manager->histograms_->RecordPageLoadTimeNotSwappedIn( | 543 prerender_manager->histograms_->RecordPerceivedPageLoadTime( |
520 perceived_page_load_time, url); | 544 prerender_origin, perceived_page_load_time, was_prerender, |
521 } else { | 545 was_complete_prerender, url); |
522 prerender_manager->histograms_->RecordPerceivedPageLoadTime( | 546 |
523 perceived_page_load_time, was_prerender, was_complete_prerender, url); | 547 if (was_prerender) { |
524 prerender_manager->histograms_->RecordPercentLoadDoneAtSwapin( | 548 prerender_manager->histograms_->RecordPercentLoadDoneAtSwapin( |
525 fraction_plt_elapsed_at_swap_in); | 549 prerender_origin, fraction_plt_elapsed_at_swap_in); |
526 if (prerender_manager->local_predictor_.get()) { | 550 } |
527 prerender_manager->local_predictor_-> | 551 if (prerender_manager->local_predictor_.get()) { |
528 OnPLTEventForURL(url, perceived_page_load_time); | 552 prerender_manager->local_predictor_-> |
529 } | 553 OnPLTEventForURL(url, perceived_page_load_time); |
530 } | 554 } |
531 } | 555 } |
532 | 556 |
557 void PrerenderManager::RecordFractionPixelsFinalAtSwapin( | |
558 content::WebContents* web_contents, | |
559 double fraction) { | |
560 Origin origin = ORIGIN_NONE; | |
561 IsWebContentsPrerendered(web_contents, &origin); | |
mmenke
2012/10/15 15:28:28
Maybe add a DCHECK that IsWebContentsPrerendered r
gavinp
2012/10/15 18:32:39
Done.
| |
562 histograms_->RecordFractionPixelsFinalAtSwapin(origin, fraction); | |
563 } | |
564 | |
533 void PrerenderManager::set_enabled(bool enabled) { | 565 void PrerenderManager::set_enabled(bool enabled) { |
534 DCHECK(CalledOnValidThread()); | 566 DCHECK(CalledOnValidThread()); |
535 enabled_ = enabled; | 567 enabled_ = enabled; |
536 } | 568 } |
537 | 569 |
538 // static | 570 // static |
539 bool PrerenderManager::IsPrefetchEnabled() { | 571 bool PrerenderManager::IsPrefetchEnabled() { |
540 return is_prefetch_enabled_; | 572 return is_prefetch_enabled_; |
541 } | 573 } |
542 | 574 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
593 bool PrerenderManager::IsControlGroup() { | 625 bool PrerenderManager::IsControlGroup() { |
594 return GetMode() == PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP; | 626 return GetMode() == PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP; |
595 } | 627 } |
596 | 628 |
597 // static | 629 // static |
598 bool PrerenderManager::IsNoUseGroup() { | 630 bool PrerenderManager::IsNoUseGroup() { |
599 return GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP; | 631 return GetMode() == PRERENDER_MODE_EXPERIMENT_NO_USE_GROUP; |
600 } | 632 } |
601 | 633 |
602 bool PrerenderManager::IsWebContentsPrerendering( | 634 bool PrerenderManager::IsWebContentsPrerendering( |
603 WebContents* web_contents) const { | 635 WebContents* web_contents, |
636 Origin* origin) const { | |
604 DCHECK(CalledOnValidThread()); | 637 DCHECK(CalledOnValidThread()); |
605 if (GetPrerenderContents(web_contents)) | 638 if (PrerenderContents* prerender_contents = |
639 GetPrerenderContents(web_contents)) { | |
640 if (origin) | |
641 *origin = prerender_contents->origin(); | |
606 return true; | 642 return true; |
643 } | |
607 | 644 |
608 // Also look through the pending-deletion list. | 645 // Also look through the pending-deletion list. |
609 for (std::list<PrerenderContents*>::const_iterator it = | 646 for (std::list<PrerenderContents*>::const_iterator it = |
610 pending_delete_list_.begin(); | 647 pending_delete_list_.begin(); |
611 it != pending_delete_list_.end(); | 648 it != pending_delete_list_.end(); |
612 ++it) { | 649 ++it) { |
613 TabContents* prerender_tab_contents = (*it)->prerender_contents(); | 650 TabContents* prerender_tab_contents = (*it)->prerender_contents(); |
614 if (prerender_tab_contents && | 651 if (prerender_tab_contents && |
615 prerender_tab_contents->web_contents() == web_contents) | 652 prerender_tab_contents->web_contents() == web_contents) |
653 if (origin) | |
654 *origin = (*it)->origin(); | |
616 return true; | 655 return true; |
mmenke
2012/10/15 15:28:28
IMPORTANT: Add brackets!
mmenke
2012/10/15 15:37:15
One other comment: We really should have unit tes
gavinp
2012/10/15 18:32:39
OMG. Fixed.
gavinp
2012/10/15 18:43:00
Actually, I added a whole new unit test file: prer
mmenke
2012/10/15 18:46:22
IsWebContentsPrerendering is actually used for pre
| |
617 } | 656 } |
618 | 657 |
619 return false; | 658 return false; |
620 } | 659 } |
621 | 660 |
622 PrerenderContents* PrerenderManager::GetPrerenderContents( | 661 PrerenderContents* PrerenderManager::GetPrerenderContents( |
623 content::WebContents* web_contents) const { | 662 content::WebContents* web_contents) const { |
624 DCHECK(CalledOnValidThread()); | 663 DCHECK(CalledOnValidThread()); |
625 for (std::list<linked_ptr<PrerenderData> >::const_iterator it = | 664 for (std::list<linked_ptr<PrerenderData> >::const_iterator it = |
626 active_prerender_list_.begin(); | 665 active_prerender_list_.begin(); |
627 it != active_prerender_list_.end(); | 666 it != active_prerender_list_.end(); |
628 ++it) { | 667 ++it) { |
629 TabContents* prerender_tab_contents = | 668 TabContents* prerender_tab_contents = |
630 it->get()->contents_->prerender_contents(); | 669 it->get()->contents_->prerender_contents(); |
631 if (prerender_tab_contents && | 670 if (prerender_tab_contents && |
632 prerender_tab_contents->web_contents() == web_contents) { | 671 prerender_tab_contents->web_contents() == web_contents) { |
633 return it->get()->contents_; | 672 return it->get()->contents_; |
634 } | 673 } |
635 } | 674 } |
636 return NULL; | 675 return NULL; |
637 } | 676 } |
638 | 677 |
639 void PrerenderManager::MarkWebContentsAsPrerendered(WebContents* web_contents) { | 678 void PrerenderManager::MarkWebContentsAsPrerendered(WebContents* web_contents, |
679 Origin origin) { | |
640 DCHECK(CalledOnValidThread()); | 680 DCHECK(CalledOnValidThread()); |
641 prerendered_tab_contents_set_.insert(web_contents); | 681 prerendered_web_contents_data_.insert( |
682 base::hash_map<content::WebContents*, | |
683 PrerenderedWebContentsData>::value_type( | |
684 web_contents, PrerenderedWebContentsData(origin))); | |
642 } | 685 } |
643 | 686 |
644 void PrerenderManager::MarkWebContentsAsWouldBePrerendered( | 687 void PrerenderManager::MarkWebContentsAsWouldBePrerendered( |
645 WebContents* web_contents) { | 688 WebContents* web_contents, |
689 Origin origin) { | |
646 DCHECK(CalledOnValidThread()); | 690 DCHECK(CalledOnValidThread()); |
647 would_be_prerendered_map_[web_contents] = true; | 691 would_be_prerendered_map_.insert( |
692 base::hash_map<content::WebContents*, | |
693 WouldBePrerenderedWebContentsData>::value_type( | |
694 web_contents, | |
695 WouldBePrerenderedWebContentsData(origin))); | |
648 } | 696 } |
649 | 697 |
650 void PrerenderManager::MarkWebContentsAsNotPrerendered( | 698 void PrerenderManager::MarkWebContentsAsNotPrerendered( |
651 WebContents* web_contents) { | 699 WebContents* web_contents) { |
652 DCHECK(CalledOnValidThread()); | 700 DCHECK(CalledOnValidThread()); |
653 prerendered_tab_contents_set_.erase(web_contents); | 701 prerendered_web_contents_data_.erase(web_contents); |
654 WouldBePrerenderedMap::iterator it = | 702 base::hash_map<content::WebContents*, WouldBePrerenderedWebContentsData>:: |
655 would_be_prerendered_map_.find(web_contents); | 703 iterator it = would_be_prerendered_map_.find(web_contents); |
656 if (it != would_be_prerendered_map_.end()) { | 704 if (it != would_be_prerendered_map_.end()) { |
657 bool first_time = it->second; | 705 if (it->second.state == |
658 if (first_time) { | 706 WouldBePrerenderedWebContentsData::WAITING_FOR_PROVISIONAL_LOAD) { |
659 it->second = false; | 707 it->second.state = |
708 WouldBePrerenderedWebContentsData::SEEN_PROVISIONAL_LOAD; | |
660 } else { | 709 } else { |
661 would_be_prerendered_map_.erase(it); | 710 would_be_prerendered_map_.erase(it); |
662 } | 711 } |
663 } | 712 } |
664 } | 713 } |
665 | 714 |
666 bool PrerenderManager::IsWebContentsPrerendered( | 715 bool PrerenderManager::IsWebContentsPrerendered( |
667 content::WebContents* web_contents) const { | 716 content::WebContents* web_contents, |
717 Origin* origin) const { | |
668 DCHECK(CalledOnValidThread()); | 718 DCHECK(CalledOnValidThread()); |
669 return prerendered_tab_contents_set_.count(web_contents) > 0; | 719 base::hash_map<content::WebContents*, PrerenderedWebContentsData>:: |
720 const_iterator it = prerendered_web_contents_data_.find(web_contents); | |
721 if (it == prerendered_web_contents_data_.end()) | |
722 return false; | |
723 if (origin) | |
724 *origin = it->second.origin; | |
725 return true; | |
670 } | 726 } |
671 | 727 |
672 bool PrerenderManager::WouldWebContentsBePrerendered( | 728 bool PrerenderManager::WouldWebContentsBePrerendered( |
673 WebContents* web_contents) const { | 729 WebContents* web_contents, |
730 Origin* origin) const { | |
674 DCHECK(CalledOnValidThread()); | 731 DCHECK(CalledOnValidThread()); |
675 return would_be_prerendered_map_.count(web_contents) > 0; | 732 base::hash_map<content::WebContents*, WouldBePrerenderedWebContentsData>:: |
733 const_iterator it = would_be_prerendered_map_.find(web_contents); | |
734 if (it == would_be_prerendered_map_.end()) | |
735 return false; | |
736 if (origin) | |
737 *origin = it->second.origin; | |
738 return true; | |
676 } | 739 } |
677 | 740 |
678 bool PrerenderManager::HasRecentlyBeenNavigatedTo(const GURL& url) { | 741 bool PrerenderManager::HasRecentlyBeenNavigatedTo(Origin origin, |
742 const GURL& url) { | |
679 DCHECK(CalledOnValidThread()); | 743 DCHECK(CalledOnValidThread()); |
680 | 744 |
681 CleanUpOldNavigations(); | 745 CleanUpOldNavigations(); |
682 std::list<NavigationRecord>::const_reverse_iterator end = navigations_.rend(); | 746 std::list<NavigationRecord>::const_reverse_iterator end = navigations_.rend(); |
683 for (std::list<NavigationRecord>::const_reverse_iterator it = | 747 for (std::list<NavigationRecord>::const_reverse_iterator it = |
684 navigations_.rbegin(); | 748 navigations_.rbegin(); |
685 it != end; | 749 it != end; |
686 ++it) { | 750 ++it) { |
687 if (it->url_ == url) { | 751 if (it->url == url) { |
688 base::TimeDelta delta = GetCurrentTimeTicks() - it->time_; | 752 base::TimeDelta delta = GetCurrentTimeTicks() - it->time; |
689 histograms_->RecordTimeSinceLastRecentVisit(delta); | 753 histograms_->RecordTimeSinceLastRecentVisit(origin, delta); |
690 return true; | 754 return true; |
691 } | 755 } |
692 } | 756 } |
693 | 757 |
694 return false; | 758 return false; |
695 } | 759 } |
696 | 760 |
697 // static | 761 // static |
698 bool PrerenderManager::IsValidHttpMethod(const std::string& method) { | 762 bool PrerenderManager::IsValidHttpMethod(const std::string& method) { |
699 // method has been canonicalized to upper case at this point so we can just | 763 // method has been canonicalized to upper case at this point so we can just |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
961 #if !defined(OS_ANDROID) | 1025 #if !defined(OS_ANDROID) |
962 if (content::RenderProcessHost::ShouldTryToUseExistingProcessHost( | 1026 if (content::RenderProcessHost::ShouldTryToUseExistingProcessHost( |
963 profile_, url) && | 1027 profile_, url) && |
964 !content::RenderProcessHost::run_renderer_in_process()) { | 1028 !content::RenderProcessHost::run_renderer_in_process()) { |
965 RecordFinalStatus(origin, experiment, FINAL_STATUS_TOO_MANY_PROCESSES); | 1029 RecordFinalStatus(origin, experiment, FINAL_STATUS_TOO_MANY_PROCESSES); |
966 return NULL; | 1030 return NULL; |
967 } | 1031 } |
968 #endif | 1032 #endif |
969 | 1033 |
970 // Check if enough time has passed since the last prerender. | 1034 // Check if enough time has passed since the last prerender. |
971 if (!DoesRateLimitAllowPrerender()) { | 1035 if (!DoesRateLimitAllowPrerender(origin)) { |
972 // Cancel the prerender. We could add it to the pending prerender list but | 1036 // Cancel the prerender. We could add it to the pending prerender list but |
973 // this doesn't make sense as the next prerender request will be triggered | 1037 // this doesn't make sense as the next prerender request will be triggered |
974 // by a navigation and is unlikely to be the same site. | 1038 // by a navigation and is unlikely to be the same site. |
975 RecordFinalStatus(origin, experiment, FINAL_STATUS_RATE_LIMIT_EXCEEDED); | 1039 RecordFinalStatus(origin, experiment, FINAL_STATUS_RATE_LIMIT_EXCEEDED); |
976 return NULL; | 1040 return NULL; |
977 } | 1041 } |
978 | 1042 |
979 PrerenderContents* prerender_contents = CreatePrerenderContents( | 1043 PrerenderContents* prerender_contents = CreatePrerenderContents( |
980 url, referrer, origin, experiment); | 1044 url, referrer, origin, experiment); |
981 if (!prerender_contents || !prerender_contents->Init()) | 1045 if (!prerender_contents || !prerender_contents->Init()) |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1164 for (std::list<linked_ptr<PrerenderData> >::iterator | 1228 for (std::list<linked_ptr<PrerenderData> >::iterator |
1165 it = active_prerender_list_.begin(); | 1229 it = active_prerender_list_.begin(); |
1166 it != active_prerender_list_.end(); | 1230 it != active_prerender_list_.end(); |
1167 ++it) { | 1231 ++it) { |
1168 if (prerender_contents == it->get()->contents_) | 1232 if (prerender_contents == it->get()->contents_) |
1169 return it; | 1233 return it; |
1170 } | 1234 } |
1171 return active_prerender_list_.end(); | 1235 return active_prerender_list_.end(); |
1172 } | 1236 } |
1173 | 1237 |
1174 bool PrerenderManager::DoesRateLimitAllowPrerender() const { | 1238 bool PrerenderManager::DoesRateLimitAllowPrerender(Origin origin) const { |
1175 DCHECK(CalledOnValidThread()); | 1239 DCHECK(CalledOnValidThread()); |
1176 base::TimeDelta elapsed_time = | 1240 base::TimeDelta elapsed_time = |
1177 GetCurrentTimeTicks() - last_prerender_start_time_; | 1241 GetCurrentTimeTicks() - last_prerender_start_time_; |
1178 histograms_->RecordTimeBetweenPrerenderRequests(elapsed_time); | 1242 histograms_->RecordTimeBetweenPrerenderRequests(origin, elapsed_time); |
1179 if (!config_.rate_limit_enabled) | 1243 if (!config_.rate_limit_enabled) |
1180 return true; | 1244 return true; |
1181 return elapsed_time > | 1245 return elapsed_time > |
1182 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs); | 1246 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs); |
1183 } | 1247 } |
1184 | 1248 |
1185 void PrerenderManager::DeleteOldTabContents() { | 1249 void PrerenderManager::DeleteOldTabContents() { |
1186 while (!old_tab_contents_list_.empty()) { | 1250 while (!old_tab_contents_list_.empty()) { |
1187 TabContents* tab_contents = old_tab_contents_list_.front(); | 1251 TabContents* tab_contents = old_tab_contents_list_.front(); |
1188 old_tab_contents_list_.pop_front(); | 1252 old_tab_contents_list_.pop_front(); |
1189 // TODO(dominich): should we use Instant Unload Handler here? | 1253 // TODO(dominich): should we use Instant Unload Handler here? |
1190 delete tab_contents; | 1254 delete tab_contents; |
1191 } | 1255 } |
1192 } | 1256 } |
1193 | 1257 |
1194 void PrerenderManager::CleanUpOldNavigations() { | 1258 void PrerenderManager::CleanUpOldNavigations() { |
1195 DCHECK(CalledOnValidThread()); | 1259 DCHECK(CalledOnValidThread()); |
1196 | 1260 |
1197 // Cutoff. Navigations before this cutoff can be discarded. | 1261 // Cutoff. Navigations before this cutoff can be discarded. |
1198 base::TimeTicks cutoff = GetCurrentTimeTicks() - | 1262 base::TimeTicks cutoff = GetCurrentTimeTicks() - |
1199 base::TimeDelta::FromMilliseconds(kNavigationRecordWindowMs); | 1263 base::TimeDelta::FromMilliseconds(kNavigationRecordWindowMs); |
1200 while (!navigations_.empty()) { | 1264 while (!navigations_.empty()) { |
1201 if (navigations_.front().time_ > cutoff) | 1265 if (navigations_.front().time > cutoff) |
1202 break; | 1266 break; |
1203 navigations_.pop_front(); | 1267 navigations_.pop_front(); |
1204 } | 1268 } |
1205 } | 1269 } |
1206 | 1270 |
1207 void PrerenderManager::ScheduleDeleteOldTabContents( | 1271 void PrerenderManager::ScheduleDeleteOldTabContents( |
1208 TabContents* tab, | 1272 TabContents* tab, |
1209 OnCloseTabContentsDeleter* deleter) { | 1273 OnCloseTabContentsDeleter* deleter) { |
1210 old_tab_contents_list_.push_back(tab); | 1274 old_tab_contents_list_.push_back(tab); |
1211 PostCleanupTask(); | 1275 PostCleanupTask(); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1296 if (!render_process_host || !render_process_host->GetBrowserContext()) | 1360 if (!render_process_host || !render_process_host->GetBrowserContext()) |
1297 return NULL; | 1361 return NULL; |
1298 Profile* profile = Profile::FromBrowserContext( | 1362 Profile* profile = Profile::FromBrowserContext( |
1299 render_process_host->GetBrowserContext()); | 1363 render_process_host->GetBrowserContext()); |
1300 if (!profile) | 1364 if (!profile) |
1301 return NULL; | 1365 return NULL; |
1302 return PrerenderManagerFactory::GetInstance()->GetForProfile(profile); | 1366 return PrerenderManagerFactory::GetInstance()->GetForProfile(profile); |
1303 } | 1367 } |
1304 | 1368 |
1305 } // namespace prerender | 1369 } // namespace prerender |
OLD | NEW |