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 <algorithm> | 7 #include <algorithm> |
| 8 #include <functional> | 8 #include <functional> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 427 | 427 |
| 428 void PrerenderManager::CancelAllPrerenders() { | 428 void PrerenderManager::CancelAllPrerenders() { |
| 429 DCHECK(CalledOnValidThread()); | 429 DCHECK(CalledOnValidThread()); |
| 430 while (!active_prerenders_.empty()) { | 430 while (!active_prerenders_.empty()) { |
| 431 PrerenderContents* prerender_contents = | 431 PrerenderContents* prerender_contents = |
| 432 active_prerenders_.front()->contents(); | 432 active_prerenders_.front()->contents(); |
| 433 prerender_contents->Destroy(FINAL_STATUS_CANCELLED); | 433 prerender_contents->Destroy(FINAL_STATUS_CANCELLED); |
| 434 } | 434 } |
| 435 } | 435 } |
| 436 | 436 |
| 437 void PrerenderManager::ProcessMergeResult( | |
| 438 PrerenderData* prerender_data, | |
| 439 bool timed_out, | |
| 440 content::SessionStorageNamespace::MergeResult result) { | |
| 441 PendingSwap* pending_swap = prerender_data->pending_swap(); | |
| 442 DCHECK(pending_swap); | |
| 443 // No pending_swap should never happen. If it does anyways (in a retail | |
| 444 // build), log this and bail. | |
| 445 if (!pending_swap) { | |
| 446 RecordEvent(prerender_data->contents(), | |
| 447 PRERENDER_EVENT_MERGE_RESULT_NO_PENDING_SWAPIN); | |
| 448 return; | |
| 449 } | |
| 450 if (timed_out) { | |
| 451 RecordEvent(prerender_data->contents(), | |
| 452 PRERENDER_EVENT_MERGE_RESULT_TIMEOUT_CB); | |
| 453 } else { | |
| 454 RecordEvent(prerender_data->contents(), | |
| 455 PRERENDER_EVENT_MERGE_RESULT_RESULT_CB); | |
| 456 UMA_HISTOGRAM_TIMES("Prerender.SessionStorageNamespaceMergeTime", | |
| 457 pending_swap->GetElapsedTime()); | |
| 458 } | |
| 459 | |
| 460 // Any return here must call ClearPendingSwap on |prerender_data| before | |
| 461 // returning, with one exception: when the prerender was ultimately swapped | |
| 462 // in. In that case, SwapInternal will take care of deleting | |
| 463 // |prerender_data| and sending the appropriate notifications to the tracker. | |
| 464 if (timed_out) { | |
| 465 RecordEvent(prerender_data->contents(), | |
| 466 PRERENDER_EVENT_MERGE_RESULT_TIMED_OUT); | |
| 467 prerender_data->ClearPendingSwap(); | |
| 468 return; | |
| 469 } | |
| 470 | |
| 471 RecordEvent(prerender_data->contents(), | |
| 472 PRERENDER_EVENT_MERGE_RESULT_MERGE_DONE); | |
| 473 | |
| 474 // Log the exact merge result in a histogram. | |
| 475 switch (result) { | |
| 476 case content::SessionStorageNamespace::MERGE_RESULT_NAMESPACE_NOT_FOUND: | |
| 477 RecordEvent(prerender_data->contents(), | |
| 478 PRERENDER_EVENT_MERGE_RESULT_RESULT_NAMESPACE_NOT_FOUND); | |
| 479 break; | |
| 480 case content::SessionStorageNamespace::MERGE_RESULT_NAMESPACE_NOT_ALIAS: | |
| 481 RecordEvent(prerender_data->contents(), | |
| 482 PRERENDER_EVENT_MERGE_RESULT_RESULT_NAMESPACE_NOT_ALIAS); | |
| 483 break; | |
| 484 case content::SessionStorageNamespace::MERGE_RESULT_NOT_LOGGING: | |
| 485 RecordEvent(prerender_data->contents(), | |
| 486 PRERENDER_EVENT_MERGE_RESULT_RESULT_NOT_LOGGING); | |
| 487 break; | |
| 488 case content::SessionStorageNamespace::MERGE_RESULT_NO_TRANSACTIONS: | |
| 489 RecordEvent(prerender_data->contents(), | |
| 490 PRERENDER_EVENT_MERGE_RESULT_RESULT_NO_TRANSACTIONS); | |
| 491 break; | |
| 492 case content::SessionStorageNamespace::MERGE_RESULT_TOO_MANY_TRANSACTIONS: | |
| 493 RecordEvent(prerender_data->contents(), | |
| 494 PRERENDER_EVENT_MERGE_RESULT_RESULT_TOO_MANY_TRANSACTIONS); | |
| 495 break; | |
| 496 case content::SessionStorageNamespace::MERGE_RESULT_NOT_MERGEABLE: | |
| 497 RecordEvent(prerender_data->contents(), | |
| 498 PRERENDER_EVENT_MERGE_RESULT_RESULT_NOT_MERGEABLE); | |
| 499 break; | |
| 500 case content::SessionStorageNamespace::MERGE_RESULT_MERGEABLE: | |
| 501 RecordEvent(prerender_data->contents(), | |
| 502 PRERENDER_EVENT_MERGE_RESULT_RESULT_MERGEABLE); | |
| 503 break; | |
| 504 default: | |
| 505 NOTREACHED(); | |
| 506 } | |
| 507 | |
| 508 if (result != content::SessionStorageNamespace::MERGE_RESULT_MERGEABLE && | |
| 509 result != | |
| 510 content::SessionStorageNamespace::MERGE_RESULT_NO_TRANSACTIONS) { | |
| 511 RecordEvent(prerender_data->contents(), | |
| 512 PRERENDER_EVENT_MERGE_RESULT_MERGE_FAILED); | |
| 513 prerender_data->ClearPendingSwap(); | |
| 514 return; | |
| 515 } | |
| 516 | |
| 517 RecordEvent(prerender_data->contents(), | |
| 518 PRERENDER_EVENT_MERGE_RESULT_SWAPPING_IN); | |
| 519 // Notice that SwapInInternal, on success, will delete |prerender_data| | |
| 520 // and |pending_swap|. Therefore, we have to pass a new GURL object rather | |
| 521 // than a reference to the one in |pending_swap|. | |
| 522 content::WebContents* new_web_contents = | |
| 523 SwapInternal(GURL(pending_swap->url()), | |
| 524 pending_swap->target_contents(), | |
| 525 prerender_data); | |
| 526 if (!new_web_contents) { | |
| 527 RecordEvent(prerender_data->contents(), | |
| 528 PRERENDER_EVENT_MERGE_RESULT_SWAPIN_FAILED); | |
| 529 prerender_data->ClearPendingSwap(); | |
| 530 } | |
| 531 } | |
| 532 | |
| 533 bool PrerenderManager::MaybeUsePrerenderedPage(const GURL& url, | 437 bool PrerenderManager::MaybeUsePrerenderedPage(const GURL& url, |
| 534 chrome::NavigateParams* params) { | 438 chrome::NavigateParams* params) { |
| 535 DCHECK(CalledOnValidThread()); | 439 DCHECK(CalledOnValidThread()); |
| 536 | 440 |
| 537 content::WebContents* web_contents = params->target_contents; | 441 content::WebContents* web_contents = params->target_contents; |
| 538 DCHECK(!IsWebContentsPrerendering(web_contents, NULL)); | 442 DCHECK(!IsWebContentsPrerendering(web_contents, NULL)); |
| 539 | 443 |
| 540 // Don't prerender if the navigation involves some special parameters. | 444 // Don't prerender if the navigation involves some special parameters. |
| 541 if (params->uses_post || !params->extra_headers.empty()) | 445 if (params->uses_post || !params->extra_headers.empty()) |
| 542 return false; | 446 return false; |
| 543 | 447 |
| 544 content::WebContents* new_web_contents = SwapInternal(url, web_contents, | |
| 545 NULL); | |
| 546 if (!new_web_contents) | |
| 547 return false; | |
| 548 | |
| 549 // Record the new target_contents for the callers. | |
| 550 params->target_contents = new_web_contents; | |
| 551 return true; | |
| 552 } | |
| 553 | |
| 554 content::WebContents* PrerenderManager::SwapInternal( | |
| 555 const GURL& url, | |
| 556 content::WebContents* web_contents, | |
| 557 PrerenderData* swap_candidate) { | |
| 558 DCHECK(CalledOnValidThread()); | |
| 559 DCHECK(!IsWebContentsPrerendering(web_contents, NULL)); | |
| 560 | |
| 561 DeleteOldEntries(); | |
| 562 to_delete_prerenders_.clear(); | |
| 563 // TODO(ajwong): This doesn't handle isolated apps correctly. | |
| 564 | |
| 565 // Only if this WebContents is used in a tabstrip may be swap. | |
| 566 // We check this by examining whether its CoreTabHelper has a delegate. | |
| 567 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(web_contents); | |
| 568 if (!core_tab_helper || !core_tab_helper->delegate()) { | |
| 569 RecordEvent(NULL, PRERENDER_EVENT_SWAPIN_NO_DELEGATE); | |
| 570 return NULL; | |
| 571 } | |
| 572 | |
| 573 // First, try to find prerender data with the correct session storage | 448 // First, try to find prerender data with the correct session storage |
| 574 // namespace. | 449 // namespace. |
| 575 PrerenderData* prerender_data = FindPrerenderData( | 450 PrerenderData* prerender_data = FindPrerenderData( |
| 576 url, | 451 url, |
| 577 web_contents->GetController().GetDefaultSessionStorageNamespace()); | 452 web_contents->GetController().GetDefaultSessionStorageNamespace()); |
| 578 | 453 |
| 579 // If this failed, we may still find a prerender for the same URL, but a | 454 // If this failed, we may still find a prerender for the same URL, but a |
| 580 // different session storage namespace. If we do, we might have to perform | 455 // different session storage namespace. If we do, we might have to perform |
| 581 // a merge. | 456 // a merge. |
| 582 if (!prerender_data) { | 457 if (!prerender_data) { |
| 583 prerender_data = FindPrerenderData(url, NULL); | 458 prerender_data = FindPrerenderData(url, NULL); |
| 584 } else { | 459 } else { |
| 585 RecordEvent(prerender_data->contents(), | 460 RecordEvent(prerender_data->contents(), |
| 586 PRERENDER_EVENT_SWAPIN_CANDIDATE_NAMESPACE_MATCHES); | 461 PRERENDER_EVENT_SWAPIN_CANDIDATE_NAMESPACE_MATCHES); |
| 587 } | 462 } |
| 588 | 463 |
| 589 if (!prerender_data) | 464 if (!prerender_data) |
| 590 return NULL; | 465 return false; |
| 591 RecordEvent(prerender_data->contents(), PRERENDER_EVENT_SWAPIN_CANDIDATE); | 466 RecordEvent(prerender_data->contents(), PRERENDER_EVENT_SWAPIN_CANDIDATE); |
| 592 DCHECK(prerender_data->contents()); | 467 DCHECK(prerender_data->contents()); |
| 593 | 468 |
| 594 // If there is currently a merge pending for this prerender data, | 469 // If there is currently a merge pending for this prerender data, |
| 595 // or this webcontents, do not swap in, but give the merge a chance to | 470 // or this webcontents, do not swap in, but give the merge a chance to |
| 596 // finish and swap into the intended target webcontents. | 471 // finish and swap into the intended target webcontents. |
|
mmenke
2013/12/09 17:06:36
"Or this webcontents"...Where do we check if the w
davidben
2013/12/09 20:00:32
Hrmf. I think that got lost in the original CL's r
| |
| 597 if (prerender_data != swap_candidate && prerender_data->pending_swap()) { | 472 if (prerender_data->pending_swap()) |
|
mmenke
2013/12/09 17:06:36
I'm confused.... In calls from MaybeUsePrerendere
mmenke
2013/12/09 17:13:34
Oh, this is an "and", rather than an "or"....that
| |
| 598 return NULL; | 473 return false; |
| 599 } | |
| 600 | 474 |
| 601 RecordEvent(prerender_data->contents(), | 475 RecordEvent(prerender_data->contents(), |
| 602 PRERENDER_EVENT_SWAPIN_NO_MERGE_PENDING); | 476 PRERENDER_EVENT_SWAPIN_NO_MERGE_PENDING); |
| 603 SessionStorageNamespace* target_namespace = | 477 SessionStorageNamespace* target_namespace = |
| 604 web_contents->GetController().GetDefaultSessionStorageNamespace(); | 478 web_contents->GetController().GetDefaultSessionStorageNamespace(); |
| 605 SessionStorageNamespace* prerender_namespace = | 479 SessionStorageNamespace* prerender_namespace = |
| 606 prerender_data->contents()->GetSessionStorageNamespace(); | 480 prerender_data->contents()->GetSessionStorageNamespace(); |
| 607 // Only when actually prerendering is session storage namespace merging an | 481 // Only when actually prerendering is session storage namespace merging an |
| 608 // issue. For the control group, it will be assumed that the merge succeeded. | 482 // issue. For the control group, it will be assumed that the merge succeeded. |
| 609 if (prerender_namespace && prerender_namespace != target_namespace && | 483 if (prerender_namespace && prerender_namespace != target_namespace && |
| 610 !prerender_namespace->IsAliasOf(target_namespace)) { | 484 !prerender_namespace->IsAliasOf(target_namespace)) { |
| 611 if (!ShouldMergeSessionStorageNamespaces()) { | 485 if (!ShouldMergeSessionStorageNamespaces()) { |
| 612 RecordEvent(prerender_data->contents(), | 486 RecordEvent(prerender_data->contents(), |
| 613 PRERENDER_EVENT_SWAPIN_MERGING_DISABLED); | 487 PRERENDER_EVENT_SWAPIN_MERGING_DISABLED); |
| 614 return NULL; | 488 return false; |
| 615 } | 489 } |
| 616 RecordEvent(prerender_data->contents(), | 490 RecordEvent(prerender_data->contents(), |
| 617 PRERENDER_EVENT_SWAPIN_ISSUING_MERGE); | 491 PRERENDER_EVENT_SWAPIN_ISSUING_MERGE); |
| 618 // There should never be a |pending_swap| if we get to here: | 492 prerender_data->set_pending_swap(new PendingSwap( |
| 619 // Per check above, |pending_swap| may only be != NULL when | 493 this, web_contents, prerender_data, url)); |
| 620 // processing a successful merge, as indicated by |swap_candidate| | 494 prerender_data->pending_swap()->BeginSwap(); |
| 621 // != NULL. But in that case, there should be no need for yet another merge. | 495 return false; |
| 622 DCHECK(!prerender_data->pending_swap()); | 496 } |
| 623 if (prerender_data->pending_swap()) { | 497 |
| 624 // In retail builds, log this error and bail. | 498 // No need to merge; swap synchronously. |
| 625 RecordEvent(prerender_data->contents(), | 499 WebContents* new_web_contents = SwapInternal(url, web_contents, |
| 626 PRERENDER_EVENT_MERGE_FOR_SWAPIN_CANDIDATE); | 500 prerender_data); |
| 627 return NULL; | 501 if (!new_web_contents) |
| 628 } | 502 return false; |
| 629 PendingSwap* pending_swap = new PendingSwap( | 503 |
| 630 prerender_tracker_, | 504 // Record the new target_contents for the callers. |
| 631 web_contents, | 505 params->target_contents = new_web_contents; |
| 632 prerender_data, | 506 return true; |
| 633 url, | 507 } |
| 634 base::Bind(&PrerenderManager::ProcessMergeResult, | 508 |
| 635 AsWeakPtr(), | 509 WebContents* PrerenderManager::SwapInternal( |
| 636 prerender_data, | 510 const GURL& url, |
| 637 true, | 511 WebContents* web_contents, |
| 638 SessionStorageNamespace::MERGE_RESULT_NOT_MERGEABLE), | 512 PrerenderData* prerender_data) { |
| 639 base::Bind(&PrerenderManager::ProcessMergeResult, | 513 DCHECK(CalledOnValidThread()); |
| 640 AsWeakPtr(), | 514 DCHECK(!IsWebContentsPrerendering(web_contents, NULL)); |
| 641 prerender_data, | 515 |
| 642 false)); | 516 DeleteOldEntries(); |
|
mmenke
2013/12/09 17:06:36
Couldn't this delete prerender_data?
davidben
2013/12/09 20:00:32
Hrm. So it can. I guess that's what the ClearPendi
| |
| 643 prerender_data->set_pending_swap(pending_swap); | 517 to_delete_prerenders_.clear(); |
| 644 prerender_namespace->Merge( | 518 // TODO(ajwong): This doesn't handle isolated apps correctly. |
| 645 true, | 519 |
| 646 prerender_data->contents()->child_id(), | 520 // Only if this WebContents is used in a tabstrip may be swap. |
| 647 target_namespace, | 521 // We check this by examining whether its CoreTabHelper has a delegate. |
| 648 pending_swap->GetMergeResultCallback()); | 522 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(web_contents); |
| 649 base::MessageLoop::current()->PostDelayedTask( | 523 if (!core_tab_helper || !core_tab_helper->delegate()) { |
| 650 FROM_HERE, | 524 RecordEvent(prerender_data->contents(), PRERENDER_EVENT_SWAPIN_NO_DELEGATE); |
| 651 pending_swap->GetTimeoutCallback(), | |
| 652 base::TimeDelta::FromMilliseconds( | |
| 653 kSessionStorageNamespaceMergeTimeoutMs)); | |
| 654 return NULL; | 525 return NULL; |
| 655 } | 526 } |
| 656 | 527 |
| 657 if (IsNoSwapInExperiment(prerender_data->contents()->experiment_id())) | 528 if (IsNoSwapInExperiment(prerender_data->contents()->experiment_id())) |
| 658 return NULL; | 529 return NULL; |
| 659 | 530 |
| 660 if (WebContents* new_web_contents = | 531 if (WebContents* new_web_contents = |
| 661 prerender_data->contents()->prerender_contents()) { | 532 prerender_data->contents()->prerender_contents()) { |
| 662 if (web_contents == new_web_contents) | 533 if (web_contents == new_web_contents) |
| 663 return NULL; // Do not swap in to ourself. | 534 return NULL; // Do not swap in to ourself. |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 844 NeedMatchCompleteDummyForFinalStatus(final_status) && | 715 NeedMatchCompleteDummyForFinalStatus(final_status) && |
| 845 ActuallyPrerendering()) { | 716 ActuallyPrerendering()) { |
| 846 // TODO(tburkard): I'd like to DCHECK that we are actually prerendering. | 717 // TODO(tburkard): I'd like to DCHECK that we are actually prerendering. |
| 847 // However, what if new conditions are added and | 718 // However, what if new conditions are added and |
| 848 // NeedMatchCompleteDummyForFinalStatus is not being updated. Not sure | 719 // NeedMatchCompleteDummyForFinalStatus is not being updated. Not sure |
| 849 // what's the best thing to do here. For now, I will just check whether | 720 // what's the best thing to do here. For now, I will just check whether |
| 850 // we are actually prerendering. | 721 // we are actually prerendering. |
| 851 (*it)->MakeIntoMatchCompleteReplacement(); | 722 (*it)->MakeIntoMatchCompleteReplacement(); |
| 852 } else { | 723 } else { |
| 853 to_delete_prerenders_.push_back(*it); | 724 to_delete_prerenders_.push_back(*it); |
| 854 (*it)->ClearPendingSwap(); | |
|
davidben
2013/12/06 19:36:34
Removing this line avoids nuisances where SwapInte
| |
| 855 active_prerenders_.weak_erase(it); | 725 active_prerenders_.weak_erase(it); |
| 856 } | 726 } |
| 857 | 727 |
| 858 // Destroy the old WebContents relatively promptly to reduce resource usage. | 728 // Destroy the old WebContents relatively promptly to reduce resource usage. |
| 859 PostCleanupTask(); | 729 PostCleanupTask(); |
| 860 } | 730 } |
| 861 | 731 |
| 862 // static | 732 // static |
| 863 void PrerenderManager::RecordPerceivedPageLoadTime( | 733 void PrerenderManager::RecordPerceivedPageLoadTime( |
| 864 base::TimeDelta perceived_page_load_time, | 734 base::TimeDelta perceived_page_load_time, |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1275 | 1145 |
| 1276 void PrerenderManager::PrerenderData::ClearPendingSwap() { | 1146 void PrerenderManager::PrerenderData::ClearPendingSwap() { |
| 1277 pending_swap_.reset(NULL); | 1147 pending_swap_.reset(NULL); |
| 1278 } | 1148 } |
| 1279 | 1149 |
| 1280 PrerenderContents* PrerenderManager::PrerenderData::ReleaseContents() { | 1150 PrerenderContents* PrerenderManager::PrerenderData::ReleaseContents() { |
| 1281 return contents_.release(); | 1151 return contents_.release(); |
| 1282 } | 1152 } |
| 1283 | 1153 |
| 1284 PrerenderManager::PendingSwap::PendingSwap( | 1154 PrerenderManager::PendingSwap::PendingSwap( |
| 1285 PrerenderTracker* prerender_tracker, | 1155 PrerenderManager* manager, |
| 1286 content::WebContents* target_contents, | 1156 content::WebContents* target_contents, |
| 1287 PrerenderData* prerender_data, | 1157 PrerenderData* prerender_data, |
| 1288 const GURL& url, | 1158 const GURL& url) |
| 1289 const base::Closure& timeout_cb, | |
| 1290 const SessionStorageNamespace::MergeResultCallback& merge_result_cb) | |
| 1291 : content::WebContentsObserver(target_contents), | 1159 : content::WebContentsObserver(target_contents), |
| 1292 prerender_tracker_(prerender_tracker), | 1160 manager_(manager), |
| 1293 target_contents_(target_contents), | 1161 target_contents_(target_contents), |
| 1294 prerender_data_(prerender_data), | 1162 prerender_data_(prerender_data), |
| 1295 url_(url), | 1163 url_(url), |
| 1296 timeout_cb_(timeout_cb), | 1164 start_time_(base::TimeTicks::Now()), |
| 1297 merge_result_cb_(merge_result_cb), | 1165 weak_factory_(this) { |
| 1298 start_time_(base::TimeTicks::Now()) { | |
| 1299 RenderViewCreated(target_contents->GetRenderViewHost()); | 1166 RenderViewCreated(target_contents->GetRenderViewHost()); |
| 1300 } | 1167 } |
| 1301 | 1168 |
| 1302 PrerenderManager::PendingSwap::~PendingSwap() { | 1169 PrerenderManager::PendingSwap::~PendingSwap() { |
| 1303 timeout_cb_.Cancel(); | 1170 for (size_t i = 0; i < rvh_ids_.size(); i++) { |
| 1304 merge_result_cb_.Cancel(); | 1171 manager_->prerender_tracker()->RemovePrerenderPendingSwap( |
| 1305 for (size_t i = 0; i < rvh_ids_.size(); i++) { | 1172 rvh_ids_[i], false); |
| 1306 prerender_tracker_->RemovePrerenderPendingSwap(rvh_ids_[i], false); | 1173 } |
| 1307 } | |
| 1308 } | 1174 } |
| 1309 | 1175 |
| 1310 const base::Closure& PrerenderManager::PendingSwap::GetTimeoutCallback() { | 1176 void PrerenderManager::PendingSwap::BeginSwap() { |
| 1311 return timeout_cb_.callback(); | 1177 SessionStorageNamespace* target_namespace = |
| 1312 } | 1178 target_contents_->GetController().GetDefaultSessionStorageNamespace(); |
| 1179 SessionStorageNamespace* prerender_namespace = | |
| 1180 prerender_data_->contents()->GetSessionStorageNamespace(); | |
| 1313 | 1181 |
| 1314 void PrerenderManager::PendingSwap::SwapSuccessful() { | 1182 prerender_namespace->Merge( |
| 1315 for (size_t i = 0; i < rvh_ids_.size(); i++) { | 1183 true, prerender_data_->contents()->child_id(), |
| 1316 prerender_tracker_->RemovePrerenderPendingSwap(rvh_ids_[i], true); | 1184 target_namespace, |
| 1317 } | 1185 base::Bind(&PrerenderManager::PendingSwap::OnMergeCompleted, |
| 1318 rvh_ids_.clear(); | 1186 weak_factory_.GetWeakPtr())); |
| 1319 } | |
| 1320 | 1187 |
| 1321 const SessionStorageNamespace::MergeResultCallback& | 1188 merge_timeout_.Start( |
| 1322 PrerenderManager::PendingSwap::GetMergeResultCallback() { | 1189 FROM_HERE, |
| 1323 return merge_result_cb_.callback(); | 1190 base::TimeDelta::FromMilliseconds( |
| 1191 kSessionStorageNamespaceMergeTimeoutMs), | |
| 1192 this, &PrerenderManager::PendingSwap::OnMergeTimeout); | |
| 1324 } | 1193 } |
| 1325 | 1194 |
| 1326 void PrerenderManager::PendingSwap::ProvisionalChangeToMainFrameUrl( | 1195 void PrerenderManager::PendingSwap::ProvisionalChangeToMainFrameUrl( |
| 1327 const GURL& url, | 1196 const GURL& url, |
| 1328 content::RenderViewHost* render_view_host) { | 1197 content::RenderViewHost* render_view_host) { |
| 1329 // We must only cancel the pending swap if the |url| navigated to is not | 1198 // We must only cancel the pending swap if the |url| navigated to is not |
| 1330 // the URL being attempted to be swapped in. That's because in the normal | 1199 // the URL being attempted to be swapped in. That's because in the normal |
| 1331 // flow, a ProvisionalChangeToMainFrameUrl will happen for the URL attempted | 1200 // flow, a ProvisionalChangeToMainFrameUrl will happen for the URL attempted |
| 1332 // to be swapped in immediately after the pending swap has issued its merge. | 1201 // to be swapped in immediately after the pending swap has issued its merge. |
| 1333 if (url != url_) | 1202 if (url != url_) |
| 1334 prerender_data_->ClearPendingSwap(); | 1203 prerender_data_->ClearPendingSwap(); |
| 1335 } | 1204 } |
| 1336 | 1205 |
| 1337 void PrerenderManager::PendingSwap::DidCommitProvisionalLoadForFrame( | 1206 void PrerenderManager::PendingSwap::DidCommitProvisionalLoadForFrame( |
| 1338 int64 frame_id, | 1207 int64 frame_id, |
| 1339 const string16& frame_unique_name, | 1208 const string16& frame_unique_name, |
| 1340 bool is_main_frame, | 1209 bool is_main_frame, |
| 1341 const GURL& validated_url, | 1210 const GURL& validated_url, |
| 1342 content::PageTransition transition_type, | 1211 content::PageTransition transition_type, |
| 1343 content::RenderViewHost* render_view_host){ | 1212 content::RenderViewHost* render_view_host){ |
| 1344 if (!is_main_frame) | 1213 if (!is_main_frame) |
| 1345 return; | 1214 return; |
| 1346 if (validated_url != url_) | 1215 prerender_data_->ClearPendingSwap(); |
|
davidben
2013/12/06 19:36:34
This check is unnecessary; the throttled load can'
mmenke
2013/12/09 17:06:36
Random comment not for this CL: Wonder if we shou
davidben
2013/12/09 20:00:32
We do. I believe the main interesting cancel hook
| |
| 1347 prerender_data_->ClearPendingSwap(); | |
| 1348 } | 1216 } |
| 1349 | 1217 |
| 1350 void PrerenderManager::PendingSwap::RenderViewCreated( | 1218 void PrerenderManager::PendingSwap::RenderViewCreated( |
| 1351 content::RenderViewHost* render_view_host) { | 1219 content::RenderViewHost* render_view_host) { |
| 1220 // Record the RVH id in the tracker to install throttles on MAIN_FRAME | |
| 1221 // requests from that route. | |
| 1352 int child_id = render_view_host->GetProcess()->GetID(); | 1222 int child_id = render_view_host->GetProcess()->GetID(); |
| 1353 int route_id = render_view_host->GetRoutingID(); | 1223 int route_id = render_view_host->GetRoutingID(); |
| 1354 PrerenderTracker::ChildRouteIdPair child_route_id_pair(child_id, route_id); | 1224 PrerenderTracker::ChildRouteIdPair child_route_id_pair(child_id, route_id); |
| 1355 rvh_ids_.push_back(child_route_id_pair); | 1225 rvh_ids_.push_back(child_route_id_pair); |
| 1356 prerender_tracker_->AddPrerenderPendingSwap(child_route_id_pair, url_); | 1226 manager_->prerender_tracker()->AddPrerenderPendingSwap( |
| 1227 child_route_id_pair, url_); | |
| 1357 } | 1228 } |
| 1358 | 1229 |
| 1359 void PrerenderManager::PendingSwap::DidFailProvisionalLoad( | 1230 void PrerenderManager::PendingSwap::DidFailProvisionalLoad( |
| 1360 int64 frame_id, | 1231 int64 frame_id, |
| 1361 const string16& frame_unique_name, | 1232 const string16& frame_unique_name, |
| 1362 bool is_main_frame, | 1233 bool is_main_frame, |
| 1363 const GURL& validated_url, | 1234 const GURL& validated_url, |
| 1364 int error_code, | 1235 int error_code, |
| 1365 const string16& error_description, | 1236 const string16& error_description, |
| 1366 content::RenderViewHost* render_view_host) { | 1237 content::RenderViewHost* render_view_host) { |
| 1238 if (!is_main_frame) | |
| 1239 return; | |
| 1367 prerender_data_->ClearPendingSwap(); | 1240 prerender_data_->ClearPendingSwap(); |
| 1368 } | 1241 } |
| 1369 | 1242 |
| 1370 void PrerenderManager::PendingSwap::WebContentsDestroyed( | 1243 void PrerenderManager::PendingSwap::WebContentsDestroyed( |
| 1371 content::WebContents* web_contents) { | 1244 content::WebContents* web_contents) { |
| 1372 prerender_data_->ClearPendingSwap(); | 1245 prerender_data_->ClearPendingSwap(); |
| 1373 } | 1246 } |
| 1374 | 1247 |
| 1375 base::TimeDelta PrerenderManager::PendingSwap::GetElapsedTime() { | 1248 void PrerenderManager::PendingSwap::SwapSuccessful() { |
| 1376 return base::TimeTicks::Now() - start_time_; | 1249 for (size_t i = 0; i < rvh_ids_.size(); i++) { |
| 1250 manager_->prerender_tracker()->RemovePrerenderPendingSwap( | |
| 1251 rvh_ids_[i], true); | |
| 1252 } | |
| 1253 rvh_ids_.clear(); | |
| 1254 } | |
| 1255 | |
| 1256 void PrerenderManager::PendingSwap::RecordEvent(PrerenderEvent event) const { | |
| 1257 manager_->RecordEvent(prerender_data_->contents(), event); | |
| 1258 } | |
| 1259 | |
| 1260 void PrerenderManager::PendingSwap::OnMergeCompleted( | |
| 1261 SessionStorageNamespace::MergeResult result) { | |
| 1262 UMA_HISTOGRAM_TIMES("Prerender.SessionStorageNamespaceMergeTime", | |
| 1263 base::TimeTicks::Now() - start_time_); | |
| 1264 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_MERGE_DONE); | |
| 1265 | |
| 1266 // Log the exact merge result in a histogram. | |
| 1267 switch (result) { | |
| 1268 case SessionStorageNamespace::MERGE_RESULT_NAMESPACE_NOT_FOUND: | |
| 1269 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_NAMESPACE_NOT_FOUND); | |
| 1270 break; | |
| 1271 case SessionStorageNamespace::MERGE_RESULT_NAMESPACE_NOT_ALIAS: | |
| 1272 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_NAMESPACE_NOT_ALIAS); | |
| 1273 break; | |
| 1274 case SessionStorageNamespace::MERGE_RESULT_NOT_LOGGING: | |
| 1275 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_NOT_LOGGING); | |
| 1276 break; | |
| 1277 case SessionStorageNamespace::MERGE_RESULT_NO_TRANSACTIONS: | |
| 1278 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_NO_TRANSACTIONS); | |
| 1279 break; | |
| 1280 case SessionStorageNamespace::MERGE_RESULT_TOO_MANY_TRANSACTIONS: | |
| 1281 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_TOO_MANY_TRANSACTIONS); | |
| 1282 break; | |
| 1283 case SessionStorageNamespace::MERGE_RESULT_NOT_MERGEABLE: | |
| 1284 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_NOT_MERGEABLE); | |
| 1285 break; | |
| 1286 case SessionStorageNamespace::MERGE_RESULT_MERGEABLE: | |
| 1287 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_MERGEABLE); | |
| 1288 break; | |
| 1289 default: | |
| 1290 NOTREACHED(); | |
| 1291 } | |
| 1292 | |
| 1293 if (result != SessionStorageNamespace::MERGE_RESULT_MERGEABLE && | |
| 1294 result != SessionStorageNamespace::MERGE_RESULT_NO_TRANSACTIONS) { | |
| 1295 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_MERGE_FAILED); | |
| 1296 prerender_data_->ClearPendingSwap(); | |
| 1297 return; | |
| 1298 } | |
| 1299 | |
| 1300 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_SWAPPING_IN); | |
| 1301 // Note that SwapInternal, on success, will delete |prerender_data_| and | |
| 1302 // |this|. Pass in a new GURL object rather than a reference to |url_|. | |
| 1303 WebContents* new_web_contents = | |
| 1304 manager_->SwapInternal(GURL(url_), target_contents_, prerender_data_); | |
| 1305 if (!new_web_contents) { | |
| 1306 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_SWAPIN_FAILED); | |
| 1307 prerender_data_->ClearPendingSwap(); | |
| 1308 } | |
| 1309 } | |
| 1310 | |
| 1311 void PrerenderManager::PendingSwap::OnMergeTimeout() { | |
| 1312 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_TIMED_OUT); | |
| 1313 prerender_data_->ClearPendingSwap(); | |
| 1377 } | 1314 } |
| 1378 | 1315 |
| 1379 void PrerenderManager::SetPrerenderContentsFactory( | 1316 void PrerenderManager::SetPrerenderContentsFactory( |
| 1380 PrerenderContents::Factory* prerender_contents_factory) { | 1317 PrerenderContents::Factory* prerender_contents_factory) { |
| 1381 DCHECK(CalledOnValidThread()); | 1318 DCHECK(CalledOnValidThread()); |
| 1382 prerender_contents_factory_.reset(prerender_contents_factory); | 1319 prerender_contents_factory_.reset(prerender_contents_factory); |
| 1383 } | 1320 } |
| 1384 | 1321 |
| 1385 | 1322 |
| 1386 void PrerenderManager::StartPendingPrerenders( | 1323 void PrerenderManager::StartPendingPrerenders( |
| (...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1944 void PrerenderManager::RecordEvent(PrerenderContents* contents, | 1881 void PrerenderManager::RecordEvent(PrerenderContents* contents, |
| 1945 PrerenderEvent event) const { | 1882 PrerenderEvent event) const { |
| 1946 if (!contents) | 1883 if (!contents) |
| 1947 histograms_->RecordEvent(ORIGIN_NONE, kNoExperiment, event); | 1884 histograms_->RecordEvent(ORIGIN_NONE, kNoExperiment, event); |
| 1948 else | 1885 else |
| 1949 histograms_->RecordEvent(contents->origin(), contents->experiment_id(), | 1886 histograms_->RecordEvent(contents->origin(), contents->experiment_id(), |
| 1950 event); | 1887 event); |
| 1951 } | 1888 } |
| 1952 | 1889 |
| 1953 } // namespace prerender | 1890 } // namespace prerender |
| OLD | NEW |