Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: chrome/browser/prerender/prerender_manager.cc

Issue 98373010: Refactor prerender pending swap logic. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: I can order correctly words Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/prerender/prerender_manager.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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(); 448 DeleteOldEntries();
562 to_delete_prerenders_.clear(); 449 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 450
573 // First, try to find prerender data with the correct session storage 451 // First, try to find prerender data with the correct session storage
574 // namespace. 452 // namespace.
453 // TODO(ajwong): This doesn't handle isolated apps correctly.
575 PrerenderData* prerender_data = FindPrerenderData( 454 PrerenderData* prerender_data = FindPrerenderData(
576 url, 455 url,
577 web_contents->GetController().GetDefaultSessionStorageNamespace()); 456 web_contents->GetController().GetDefaultSessionStorageNamespace());
578 457
579 // If this failed, we may still find a prerender for the same URL, but a 458 // 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 459 // different session storage namespace. If we do, we might have to perform
581 // a merge. 460 // a merge.
582 if (!prerender_data) { 461 if (!prerender_data) {
583 prerender_data = FindPrerenderData(url, NULL); 462 prerender_data = FindPrerenderData(url, NULL);
584 } else { 463 } else {
585 RecordEvent(prerender_data->contents(), 464 RecordEvent(prerender_data->contents(),
586 PRERENDER_EVENT_SWAPIN_CANDIDATE_NAMESPACE_MATCHES); 465 PRERENDER_EVENT_SWAPIN_CANDIDATE_NAMESPACE_MATCHES);
587 } 466 }
588 467
589 if (!prerender_data) 468 if (!prerender_data)
590 return NULL; 469 return false;
591 RecordEvent(prerender_data->contents(), PRERENDER_EVENT_SWAPIN_CANDIDATE); 470 RecordEvent(prerender_data->contents(), PRERENDER_EVENT_SWAPIN_CANDIDATE);
592 DCHECK(prerender_data->contents()); 471 DCHECK(prerender_data->contents());
593 472
594 // If there is currently a merge pending for this prerender data, 473 // 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 474 // or this webcontents, do not swap in, but give the merge a chance to
596 // finish and swap into the intended target webcontents. 475 // finish and swap into the intended target webcontents.
597 if (prerender_data != swap_candidate && prerender_data->pending_swap()) { 476 if (prerender_data->pending_swap())
598 return NULL; 477 return false;
599 }
600 478
601 RecordEvent(prerender_data->contents(), 479 RecordEvent(prerender_data->contents(),
602 PRERENDER_EVENT_SWAPIN_NO_MERGE_PENDING); 480 PRERENDER_EVENT_SWAPIN_NO_MERGE_PENDING);
603 SessionStorageNamespace* target_namespace = 481 SessionStorageNamespace* target_namespace =
604 web_contents->GetController().GetDefaultSessionStorageNamespace(); 482 web_contents->GetController().GetDefaultSessionStorageNamespace();
605 SessionStorageNamespace* prerender_namespace = 483 SessionStorageNamespace* prerender_namespace =
606 prerender_data->contents()->GetSessionStorageNamespace(); 484 prerender_data->contents()->GetSessionStorageNamespace();
607 // Only when actually prerendering is session storage namespace merging an 485 // Only when actually prerendering is session storage namespace merging an
608 // issue. For the control group, it will be assumed that the merge succeeded. 486 // issue. For the control group, it will be assumed that the merge succeeded.
609 if (prerender_namespace && prerender_namespace != target_namespace && 487 if (prerender_namespace && prerender_namespace != target_namespace &&
610 !prerender_namespace->IsAliasOf(target_namespace)) { 488 !prerender_namespace->IsAliasOf(target_namespace)) {
611 if (!ShouldMergeSessionStorageNamespaces()) { 489 if (!ShouldMergeSessionStorageNamespaces()) {
612 RecordEvent(prerender_data->contents(), 490 RecordEvent(prerender_data->contents(),
613 PRERENDER_EVENT_SWAPIN_MERGING_DISABLED); 491 PRERENDER_EVENT_SWAPIN_MERGING_DISABLED);
614 return NULL; 492 return false;
615 } 493 }
616 RecordEvent(prerender_data->contents(), 494 RecordEvent(prerender_data->contents(),
617 PRERENDER_EVENT_SWAPIN_ISSUING_MERGE); 495 PRERENDER_EVENT_SWAPIN_ISSUING_MERGE);
618 // There should never be a |pending_swap| if we get to here: 496 prerender_data->set_pending_swap(new PendingSwap(
619 // Per check above, |pending_swap| may only be != NULL when 497 this, web_contents, prerender_data, url));
620 // processing a successful merge, as indicated by |swap_candidate| 498 prerender_data->pending_swap()->BeginSwap();
621 // != NULL. But in that case, there should be no need for yet another merge. 499 // Although this returns false, creating a PendingSwap registers with
622 DCHECK(!prerender_data->pending_swap()); 500 // PrerenderTracker to throttle MAIN_FRAME navigations while the swap is
623 if (prerender_data->pending_swap()) { 501 // pending.
624 // In retail builds, log this error and bail. 502 return false;
625 RecordEvent(prerender_data->contents(), 503 }
626 PRERENDER_EVENT_MERGE_FOR_SWAPIN_CANDIDATE); 504
627 return NULL; 505 // No need to merge; swap synchronously.
628 } 506 WebContents* new_web_contents = SwapInternal(url, web_contents,
629 PendingSwap* pending_swap = new PendingSwap( 507 prerender_data);
630 prerender_tracker_, 508 if (!new_web_contents)
631 web_contents, 509 return false;
632 prerender_data, 510
633 url, 511 // Record the new target_contents for the callers.
634 base::Bind(&PrerenderManager::ProcessMergeResult, 512 params->target_contents = new_web_contents;
635 AsWeakPtr(), 513 return true;
636 prerender_data, 514 }
637 true, 515
638 SessionStorageNamespace::MERGE_RESULT_NOT_MERGEABLE), 516 WebContents* PrerenderManager::SwapInternal(
639 base::Bind(&PrerenderManager::ProcessMergeResult, 517 const GURL& url,
640 AsWeakPtr(), 518 WebContents* web_contents,
641 prerender_data, 519 PrerenderData* prerender_data) {
642 false)); 520 DCHECK(CalledOnValidThread());
643 prerender_data->set_pending_swap(pending_swap); 521 DCHECK(!IsWebContentsPrerendering(web_contents, NULL));
644 prerender_namespace->Merge( 522
645 true, 523 // Only swap if the target WebContents has a CoreTabHelper delegate to swap
646 prerender_data->contents()->child_id(), 524 // out of it. For a normal WebContents, this is if it is in a TabStripModel.
647 target_namespace, 525 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(web_contents);
648 pending_swap->GetMergeResultCallback()); 526 if (!core_tab_helper || !core_tab_helper->delegate()) {
649 base::MessageLoop::current()->PostDelayedTask( 527 RecordEvent(prerender_data->contents(), PRERENDER_EVENT_SWAPIN_NO_DELEGATE);
650 FROM_HERE,
651 pending_swap->GetTimeoutCallback(),
652 base::TimeDelta::FromMilliseconds(
653 kSessionStorageNamespaceMergeTimeoutMs));
654 return NULL; 528 return NULL;
655 } 529 }
656 530
657 if (IsNoSwapInExperiment(prerender_data->contents()->experiment_id())) 531 if (IsNoSwapInExperiment(prerender_data->contents()->experiment_id()))
658 return NULL; 532 return NULL;
659 533
660 if (WebContents* new_web_contents = 534 if (WebContents* new_web_contents =
661 prerender_data->contents()->prerender_contents()) { 535 prerender_data->contents()->prerender_contents()) {
662 if (web_contents == new_web_contents) 536 if (web_contents == new_web_contents)
663 return NULL; // Do not swap in to ourself. 537 return NULL; // Do not swap in to ourself.
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 CHECK(prerender_data->contents()->GetRouteId(&route_id)); 601 CHECK(prerender_data->contents()->GetRouteId(&route_id));
728 602
729 // Try to set the prerendered page as used, so any subsequent attempts to 603 // Try to set the prerendered page as used, so any subsequent attempts to
730 // cancel on other threads will fail. If this fails because the prerender 604 // cancel on other threads will fail. If this fails because the prerender
731 // was already cancelled, possibly on another thread, fail. 605 // was already cancelled, possibly on another thread, fail.
732 if (!prerender_tracker_->TryUse(child_id, route_id)) 606 if (!prerender_tracker_->TryUse(child_id, route_id))
733 return NULL; 607 return NULL;
734 608
735 // At this point, we've determined that we will use the prerender. 609 // At this point, we've determined that we will use the prerender.
736 if (prerender_data->pending_swap()) 610 if (prerender_data->pending_swap())
737 prerender_data->pending_swap()->SwapSuccessful(); 611 prerender_data->pending_swap()->set_swap_successful(true);
738 ScopedVector<PrerenderData>::iterator to_erase = 612 ScopedVector<PrerenderData>::iterator to_erase =
739 FindIteratorForPrerenderContents(prerender_data->contents()); 613 FindIteratorForPrerenderContents(prerender_data->contents());
740 DCHECK(active_prerenders_.end() != to_erase); 614 DCHECK(active_prerenders_.end() != to_erase);
741 DCHECK_EQ(prerender_data, *to_erase); 615 DCHECK_EQ(prerender_data, *to_erase);
742 scoped_ptr<PrerenderContents> 616 scoped_ptr<PrerenderContents>
743 prerender_contents(prerender_data->ReleaseContents()); 617 prerender_contents(prerender_data->ReleaseContents());
744 active_prerenders_.erase(to_erase); 618 active_prerenders_.erase(to_erase);
745 619
746 if (!prerender_contents->load_start_time().is_null()) { 620 if (!prerender_contents->load_start_time().is_null()) {
747 histograms_->RecordTimeUntilUsed( 621 histograms_->RecordTimeUntilUsed(
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
844 NeedMatchCompleteDummyForFinalStatus(final_status) && 718 NeedMatchCompleteDummyForFinalStatus(final_status) &&
845 ActuallyPrerendering()) { 719 ActuallyPrerendering()) {
846 // TODO(tburkard): I'd like to DCHECK that we are actually prerendering. 720 // TODO(tburkard): I'd like to DCHECK that we are actually prerendering.
847 // However, what if new conditions are added and 721 // However, what if new conditions are added and
848 // NeedMatchCompleteDummyForFinalStatus is not being updated. Not sure 722 // NeedMatchCompleteDummyForFinalStatus is not being updated. Not sure
849 // what's the best thing to do here. For now, I will just check whether 723 // what's the best thing to do here. For now, I will just check whether
850 // we are actually prerendering. 724 // we are actually prerendering.
851 (*it)->MakeIntoMatchCompleteReplacement(); 725 (*it)->MakeIntoMatchCompleteReplacement();
852 } else { 726 } else {
853 to_delete_prerenders_.push_back(*it); 727 to_delete_prerenders_.push_back(*it);
854 (*it)->ClearPendingSwap();
855 active_prerenders_.weak_erase(it); 728 active_prerenders_.weak_erase(it);
856 } 729 }
857 730
858 // Destroy the old WebContents relatively promptly to reduce resource usage. 731 // Destroy the old WebContents relatively promptly to reduce resource usage.
859 PostCleanupTask(); 732 PostCleanupTask();
860 } 733 }
861 734
862 // static 735 // static
863 void PrerenderManager::RecordPerceivedPageLoadTime( 736 void PrerenderManager::RecordPerceivedPageLoadTime(
864 base::TimeDelta perceived_page_load_time, 737 base::TimeDelta perceived_page_load_time,
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after
1275 1148
1276 void PrerenderManager::PrerenderData::ClearPendingSwap() { 1149 void PrerenderManager::PrerenderData::ClearPendingSwap() {
1277 pending_swap_.reset(NULL); 1150 pending_swap_.reset(NULL);
1278 } 1151 }
1279 1152
1280 PrerenderContents* PrerenderManager::PrerenderData::ReleaseContents() { 1153 PrerenderContents* PrerenderManager::PrerenderData::ReleaseContents() {
1281 return contents_.release(); 1154 return contents_.release();
1282 } 1155 }
1283 1156
1284 PrerenderManager::PendingSwap::PendingSwap( 1157 PrerenderManager::PendingSwap::PendingSwap(
1285 PrerenderTracker* prerender_tracker, 1158 PrerenderManager* manager,
1286 content::WebContents* target_contents, 1159 content::WebContents* target_contents,
1287 PrerenderData* prerender_data, 1160 PrerenderData* prerender_data,
1288 const GURL& url, 1161 const GURL& url)
1289 const base::Closure& timeout_cb,
1290 const SessionStorageNamespace::MergeResultCallback& merge_result_cb)
1291 : content::WebContentsObserver(target_contents), 1162 : content::WebContentsObserver(target_contents),
1292 prerender_tracker_(prerender_tracker), 1163 manager_(manager),
1293 target_contents_(target_contents), 1164 target_contents_(target_contents),
1294 prerender_data_(prerender_data), 1165 prerender_data_(prerender_data),
1295 url_(url), 1166 url_(url),
1296 timeout_cb_(timeout_cb), 1167 start_time_(base::TimeTicks::Now()),
1297 merge_result_cb_(merge_result_cb), 1168 swap_successful_(false),
1298 start_time_(base::TimeTicks::Now()) { 1169 weak_factory_(this) {
1299 RenderViewCreated(target_contents->GetRenderViewHost()); 1170 RenderViewCreated(target_contents->GetRenderViewHost());
1300 } 1171 }
1301 1172
1302 PrerenderManager::PendingSwap::~PendingSwap() { 1173 PrerenderManager::PendingSwap::~PendingSwap() {
1303 timeout_cb_.Cancel(); 1174 for (size_t i = 0; i < rvh_ids_.size(); i++) {
1304 merge_result_cb_.Cancel(); 1175 manager_->prerender_tracker()->RemovePrerenderPendingSwap(
1305 for (size_t i = 0; i < rvh_ids_.size(); i++) { 1176 rvh_ids_[i], swap_successful_);
1306 prerender_tracker_->RemovePrerenderPendingSwap(rvh_ids_[i], false); 1177 }
1307 }
1308 } 1178 }
1309 1179
1310 const base::Closure& PrerenderManager::PendingSwap::GetTimeoutCallback() { 1180 void PrerenderManager::PendingSwap::BeginSwap() {
1311 return timeout_cb_.callback(); 1181 SessionStorageNamespace* target_namespace =
1312 } 1182 target_contents_->GetController().GetDefaultSessionStorageNamespace();
1183 SessionStorageNamespace* prerender_namespace =
1184 prerender_data_->contents()->GetSessionStorageNamespace();
1313 1185
1314 void PrerenderManager::PendingSwap::SwapSuccessful() { 1186 prerender_namespace->Merge(
1315 for (size_t i = 0; i < rvh_ids_.size(); i++) { 1187 true, prerender_data_->contents()->child_id(),
1316 prerender_tracker_->RemovePrerenderPendingSwap(rvh_ids_[i], true); 1188 target_namespace,
1317 } 1189 base::Bind(&PrerenderManager::PendingSwap::OnMergeCompleted,
1318 rvh_ids_.clear(); 1190 weak_factory_.GetWeakPtr()));
1319 }
1320 1191
1321 const SessionStorageNamespace::MergeResultCallback& 1192 merge_timeout_.Start(
1322 PrerenderManager::PendingSwap::GetMergeResultCallback() { 1193 FROM_HERE,
1323 return merge_result_cb_.callback(); 1194 base::TimeDelta::FromMilliseconds(
1195 kSessionStorageNamespaceMergeTimeoutMs),
1196 this, &PrerenderManager::PendingSwap::OnMergeTimeout);
1324 } 1197 }
1325 1198
1326 void PrerenderManager::PendingSwap::ProvisionalChangeToMainFrameUrl( 1199 void PrerenderManager::PendingSwap::ProvisionalChangeToMainFrameUrl(
1327 const GURL& url, 1200 const GURL& url,
1328 content::RenderViewHost* render_view_host) { 1201 content::RenderViewHost* render_view_host) {
1329 // We must only cancel the pending swap if the |url| navigated to is not 1202 // 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 1203 // the URL being attempted to be swapped in. That's because in the normal
1331 // flow, a ProvisionalChangeToMainFrameUrl will happen for the URL attempted 1204 // flow, a ProvisionalChangeToMainFrameUrl will happen for the URL attempted
1332 // to be swapped in immediately after the pending swap has issued its merge. 1205 // to be swapped in immediately after the pending swap has issued its merge.
1333 if (url != url_) 1206 if (url != url_)
1334 prerender_data_->ClearPendingSwap(); 1207 prerender_data_->ClearPendingSwap();
1335 } 1208 }
1336 1209
1337 void PrerenderManager::PendingSwap::DidCommitProvisionalLoadForFrame( 1210 void PrerenderManager::PendingSwap::DidCommitProvisionalLoadForFrame(
1338 int64 frame_id, 1211 int64 frame_id,
1339 const string16& frame_unique_name, 1212 const string16& frame_unique_name,
1340 bool is_main_frame, 1213 bool is_main_frame,
1341 const GURL& validated_url, 1214 const GURL& validated_url,
1342 content::PageTransition transition_type, 1215 content::PageTransition transition_type,
1343 content::RenderViewHost* render_view_host){ 1216 content::RenderViewHost* render_view_host){
1344 if (!is_main_frame) 1217 if (!is_main_frame)
1345 return; 1218 return;
1346 if (validated_url != url_) 1219 prerender_data_->ClearPendingSwap();
1347 prerender_data_->ClearPendingSwap();
1348 } 1220 }
1349 1221
1350 void PrerenderManager::PendingSwap::RenderViewCreated( 1222 void PrerenderManager::PendingSwap::RenderViewCreated(
1351 content::RenderViewHost* render_view_host) { 1223 content::RenderViewHost* render_view_host) {
1224 // Record the RVH id in the tracker to install throttles on MAIN_FRAME
1225 // requests from that route.
1352 int child_id = render_view_host->GetProcess()->GetID(); 1226 int child_id = render_view_host->GetProcess()->GetID();
1353 int route_id = render_view_host->GetRoutingID(); 1227 int route_id = render_view_host->GetRoutingID();
1354 PrerenderTracker::ChildRouteIdPair child_route_id_pair(child_id, route_id); 1228 PrerenderTracker::ChildRouteIdPair child_route_id_pair(child_id, route_id);
1355 rvh_ids_.push_back(child_route_id_pair); 1229 rvh_ids_.push_back(child_route_id_pair);
1356 prerender_tracker_->AddPrerenderPendingSwap(child_route_id_pair, url_); 1230 manager_->prerender_tracker()->AddPrerenderPendingSwap(
1231 child_route_id_pair, url_);
1357 } 1232 }
1358 1233
1359 void PrerenderManager::PendingSwap::DidFailProvisionalLoad( 1234 void PrerenderManager::PendingSwap::DidFailProvisionalLoad(
1360 int64 frame_id, 1235 int64 frame_id,
1361 const string16& frame_unique_name, 1236 const string16& frame_unique_name,
1362 bool is_main_frame, 1237 bool is_main_frame,
1363 const GURL& validated_url, 1238 const GURL& validated_url,
1364 int error_code, 1239 int error_code,
1365 const string16& error_description, 1240 const string16& error_description,
1366 content::RenderViewHost* render_view_host) { 1241 content::RenderViewHost* render_view_host) {
1242 if (!is_main_frame)
1243 return;
1367 prerender_data_->ClearPendingSwap(); 1244 prerender_data_->ClearPendingSwap();
1368 } 1245 }
1369 1246
1370 void PrerenderManager::PendingSwap::WebContentsDestroyed( 1247 void PrerenderManager::PendingSwap::WebContentsDestroyed(
1371 content::WebContents* web_contents) { 1248 content::WebContents* web_contents) {
1372 prerender_data_->ClearPendingSwap(); 1249 prerender_data_->ClearPendingSwap();
1373 } 1250 }
1374 1251
1375 base::TimeDelta PrerenderManager::PendingSwap::GetElapsedTime() { 1252 void PrerenderManager::PendingSwap::RecordEvent(PrerenderEvent event) const {
1376 return base::TimeTicks::Now() - start_time_; 1253 manager_->RecordEvent(prerender_data_->contents(), event);
1254 }
1255
1256 void PrerenderManager::PendingSwap::OnMergeCompleted(
1257 SessionStorageNamespace::MergeResult result) {
1258 UMA_HISTOGRAM_TIMES("Prerender.SessionStorageNamespaceMergeTime",
1259 base::TimeTicks::Now() - start_time_);
1260 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_MERGE_DONE);
1261
1262 // Log the exact merge result in a histogram.
1263 switch (result) {
1264 case SessionStorageNamespace::MERGE_RESULT_NAMESPACE_NOT_FOUND:
1265 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_NAMESPACE_NOT_FOUND);
1266 break;
1267 case SessionStorageNamespace::MERGE_RESULT_NAMESPACE_NOT_ALIAS:
1268 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_NAMESPACE_NOT_ALIAS);
1269 break;
1270 case SessionStorageNamespace::MERGE_RESULT_NOT_LOGGING:
1271 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_NOT_LOGGING);
1272 break;
1273 case SessionStorageNamespace::MERGE_RESULT_NO_TRANSACTIONS:
1274 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_NO_TRANSACTIONS);
1275 break;
1276 case SessionStorageNamespace::MERGE_RESULT_TOO_MANY_TRANSACTIONS:
1277 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_TOO_MANY_TRANSACTIONS);
1278 break;
1279 case SessionStorageNamespace::MERGE_RESULT_NOT_MERGEABLE:
1280 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_NOT_MERGEABLE);
1281 break;
1282 case SessionStorageNamespace::MERGE_RESULT_MERGEABLE:
1283 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_MERGEABLE);
1284 break;
1285 default:
1286 NOTREACHED();
1287 }
1288
1289 if (result != SessionStorageNamespace::MERGE_RESULT_MERGEABLE &&
1290 result != SessionStorageNamespace::MERGE_RESULT_NO_TRANSACTIONS) {
1291 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_MERGE_FAILED);
1292 prerender_data_->ClearPendingSwap();
1293 return;
1294 }
1295
1296 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_SWAPPING_IN);
1297 // Note that SwapInternal, on success, will delete |prerender_data_| and
1298 // |this|. Pass in a new GURL object rather than a reference to |url_|.
1299 //
1300 // TODO(davidben): See about deleting PrerenderData asynchronously so this
1301 // behavior is more reasonable.
1302 WebContents* new_web_contents =
1303 manager_->SwapInternal(GURL(url_), target_contents_, prerender_data_);
1304 if (!new_web_contents) {
1305 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_SWAPIN_FAILED);
1306 prerender_data_->ClearPendingSwap();
1307 }
1308 }
1309
1310 void PrerenderManager::PendingSwap::OnMergeTimeout() {
1311 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_TIMED_OUT);
1312 prerender_data_->ClearPendingSwap();
1377 } 1313 }
1378 1314
1379 void PrerenderManager::SetPrerenderContentsFactory( 1315 void PrerenderManager::SetPrerenderContentsFactory(
1380 PrerenderContents::Factory* prerender_contents_factory) { 1316 PrerenderContents::Factory* prerender_contents_factory) {
1381 DCHECK(CalledOnValidThread()); 1317 DCHECK(CalledOnValidThread());
1382 prerender_contents_factory_.reset(prerender_contents_factory); 1318 prerender_contents_factory_.reset(prerender_contents_factory);
1383 } 1319 }
1384 1320
1385 1321
1386 void PrerenderManager::StartPendingPrerenders( 1322 void PrerenderManager::StartPendingPrerenders(
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after
1944 void PrerenderManager::RecordEvent(PrerenderContents* contents, 1880 void PrerenderManager::RecordEvent(PrerenderContents* contents,
1945 PrerenderEvent event) const { 1881 PrerenderEvent event) const {
1946 if (!contents) 1882 if (!contents)
1947 histograms_->RecordEvent(ORIGIN_NONE, kNoExperiment, event); 1883 histograms_->RecordEvent(ORIGIN_NONE, kNoExperiment, event);
1948 else 1884 else
1949 histograms_->RecordEvent(contents->origin(), contents->experiment_id(), 1885 histograms_->RecordEvent(contents->origin(), contents->experiment_id(),
1950 event); 1886 event);
1951 } 1887 }
1952 1888
1953 } // namespace prerender 1889 } // namespace prerender
OLDNEW
« no previous file with comments | « chrome/browser/prerender/prerender_manager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698