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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 "GET", | 85 "GET", |
| 86 "HEAD", | 86 "HEAD", |
| 87 "OPTIONS", | 87 "OPTIONS", |
| 88 "POST", | 88 "POST", |
| 89 "TRACE", | 89 "TRACE", |
| 90 }; | 90 }; |
| 91 | 91 |
| 92 // Length of prerender history, for display in chrome://net-internals | 92 // Length of prerender history, for display in chrome://net-internals |
| 93 const int kHistoryLength = 100; | 93 const int kHistoryLength = 100; |
| 94 | 94 |
| 95 // Timeout, in ms, for a session storage namespace merge. | |
| 96 const int kSessionStorageNamespaceMergeTimeoutMs = 500; | |
| 97 | |
| 98 // If true, all session storage merges hang indefinitely. | |
| 99 bool g_hang_session_storage_merges_for_testing = false; | |
| 100 | |
| 101 // Indicates whether a Prerender has been cancelled such that we need | 95 // Indicates whether a Prerender has been cancelled such that we need |
| 102 // a dummy replacement for the purpose of recording the correct PPLT for | 96 // a dummy replacement for the purpose of recording the correct PPLT for |
| 103 // the Match Complete case. | 97 // the Match Complete case. |
| 104 // Traditionally, "Match" means that a prerendered page was actually visited & | 98 // Traditionally, "Match" means that a prerendered page was actually visited & |
| 105 // the prerender was used. Our goal is to have "Match" cases line up in the | 99 // the prerender was used. Our goal is to have "Match" cases line up in the |
| 106 // control group & the experiment group, so that we can make meaningful | 100 // control group & the experiment group, so that we can make meaningful |
| 107 // comparisons of improvements. However, in the control group, since we don't | 101 // comparisons of improvements. However, in the control group, since we don't |
| 108 // actually perform prerenders, many of the cancellation reasons cannot be | 102 // actually perform prerenders, many of the cancellation reasons cannot be |
| 109 // detected. Therefore, in the Prerender group, when we cancel for one of these | 103 // detected. Therefore, in the Prerender group, when we cancel for one of these |
| 110 // reasons, we keep track of a dummy Prerender representing what we would | 104 // reasons, we keep track of a dummy Prerender representing what we would |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 417 | 411 |
| 418 DeleteOldEntries(); | 412 DeleteOldEntries(); |
| 419 to_delete_prerenders_.clear(); | 413 to_delete_prerenders_.clear(); |
| 420 | 414 |
| 421 // First, try to find prerender data with the correct session storage | 415 // First, try to find prerender data with the correct session storage |
| 422 // namespace. | 416 // namespace. |
| 423 // TODO(ajwong): This doesn't handle isolated apps correctly. | 417 // TODO(ajwong): This doesn't handle isolated apps correctly. |
| 424 PrerenderData* prerender_data = FindPrerenderData( | 418 PrerenderData* prerender_data = FindPrerenderData( |
| 425 url, | 419 url, |
| 426 web_contents->GetController().GetDefaultSessionStorageNamespace()); | 420 web_contents->GetController().GetDefaultSessionStorageNamespace()); |
| 427 | |
| 428 // If this failed, we may still find a prerender for the same URL, but a | |
| 429 // different session storage namespace. If we do, we might have to perform | |
| 430 // a merge. | |
| 431 if (!prerender_data) { | |
| 432 prerender_data = FindPrerenderData(url, NULL); | |
| 433 } else { | |
| 434 RecordEvent(prerender_data->contents(), | |
| 435 PRERENDER_EVENT_SWAPIN_CANDIDATE_NAMESPACE_MATCHES); | |
| 436 } | |
| 437 | |
| 438 if (!prerender_data) | 421 if (!prerender_data) |
| 439 return false; | 422 return false; |
| 440 RecordEvent(prerender_data->contents(), PRERENDER_EVENT_SWAPIN_CANDIDATE); | 423 |
| 441 DCHECK(prerender_data->contents()); | 424 DCHECK(prerender_data->contents()); |
| 442 | 425 |
| 443 // If there is currently a merge pending for this prerender data, don't swap. | |
| 444 if (prerender_data->pending_swap()) | |
| 445 return false; | |
| 446 | |
| 447 // Abort any existing pending swap on the target contents. | |
| 448 PrerenderData* pending_swap = | |
| 449 FindPrerenderDataForTargetContents(web_contents); | |
| 450 if (pending_swap) { | |
| 451 pending_swap->ClearPendingSwap(); | |
| 452 DCHECK(FindPrerenderDataForTargetContents(web_contents) == NULL); | |
| 453 } | |
| 454 | |
| 455 RecordEvent(prerender_data->contents(), | |
| 456 PRERENDER_EVENT_SWAPIN_NO_MERGE_PENDING); | |
| 457 SessionStorageNamespace* target_namespace = | |
| 458 web_contents->GetController().GetDefaultSessionStorageNamespace(); | |
| 459 SessionStorageNamespace* prerender_namespace = | |
| 460 prerender_data->contents()->GetSessionStorageNamespace(); | |
| 461 // Only when actually prerendering is session storage namespace merging an | |
| 462 // issue. For the control group, it will be assumed that the merge succeeded. | |
| 463 if (prerender_namespace && prerender_namespace != target_namespace && | |
| 464 !prerender_namespace->IsAliasOf(target_namespace)) { | |
| 465 if (!ShouldMergeSessionStorageNamespaces()) { | |
| 466 RecordEvent(prerender_data->contents(), | |
| 467 PRERENDER_EVENT_SWAPIN_MERGING_DISABLED); | |
| 468 return false; | |
| 469 } | |
| 470 RecordEvent(prerender_data->contents(), | |
| 471 PRERENDER_EVENT_SWAPIN_ISSUING_MERGE); | |
| 472 prerender_data->set_pending_swap(new PendingSwap( | |
| 473 this, web_contents, prerender_data, url, | |
| 474 params->should_replace_current_entry)); | |
| 475 prerender_data->pending_swap()->BeginSwap(); | |
| 476 // Although this returns false, creating a PendingSwap registers with | |
| 477 // PrerenderTracker to throttle MAIN_FRAME navigations while the swap is | |
| 478 // pending. | |
| 479 return false; | |
| 480 } | |
| 481 | |
| 482 // No need to merge; swap synchronously. | 426 // No need to merge; swap synchronously. |
|
mmenke
2014/12/12 16:04:48
Merge? What's that? :)
davidben
2014/12/12 20:41:19
Done.
| |
| 483 WebContents* new_web_contents = SwapInternal( | 427 WebContents* new_web_contents = SwapInternal( |
| 484 url, web_contents, prerender_data, | 428 url, web_contents, prerender_data, |
| 485 params->should_replace_current_entry); | 429 params->should_replace_current_entry); |
| 486 if (!new_web_contents) | 430 if (!new_web_contents) |
| 487 return false; | 431 return false; |
| 488 | 432 |
| 489 // Record the new target_contents for the callers. | 433 // Record the new target_contents for the callers. |
| 490 params->target_contents = new_web_contents; | 434 params->target_contents = new_web_contents; |
| 491 return true; | 435 return true; |
| 492 } | 436 } |
| 493 | 437 |
| 494 WebContents* PrerenderManager::SwapInternal( | 438 WebContents* PrerenderManager::SwapInternal( |
| 495 const GURL& url, | 439 const GURL& url, |
| 496 WebContents* web_contents, | 440 WebContents* web_contents, |
| 497 PrerenderData* prerender_data, | 441 PrerenderData* prerender_data, |
| 498 bool should_replace_current_entry) { | 442 bool should_replace_current_entry) { |
| 499 DCHECK(CalledOnValidThread()); | 443 DCHECK(CalledOnValidThread()); |
| 500 DCHECK(!IsWebContentsPrerendering(web_contents, NULL)); | 444 DCHECK(!IsWebContentsPrerendering(web_contents, NULL)); |
| 501 | 445 |
| 502 // Only swap if the target WebContents has a CoreTabHelper delegate to swap | 446 // Only swap if the target WebContents has a CoreTabHelper delegate to swap |
| 503 // out of it. For a normal WebContents, this is if it is in a TabStripModel. | 447 // out of it. For a normal WebContents, this is if it is in a TabStripModel. |
| 504 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(web_contents); | 448 CoreTabHelper* core_tab_helper = CoreTabHelper::FromWebContents(web_contents); |
| 505 if (!core_tab_helper || !core_tab_helper->delegate()) { | 449 if (!core_tab_helper || !core_tab_helper->delegate()) { |
| 506 RecordEvent(prerender_data->contents(), PRERENDER_EVENT_SWAPIN_NO_DELEGATE); | |
| 507 return NULL; | 450 return NULL; |
| 508 } | 451 } |
|
mmenke
2014/12/12 16:04:48
nit: Remove braces
davidben
2014/12/12 20:41:19
Done.
| |
| 509 | 452 |
| 510 PrerenderTabHelper* target_tab_helper = | 453 PrerenderTabHelper* target_tab_helper = |
| 511 PrerenderTabHelper::FromWebContents(web_contents); | 454 PrerenderTabHelper::FromWebContents(web_contents); |
| 512 if (!target_tab_helper) { | 455 if (!target_tab_helper) { |
| 513 NOTREACHED(); | 456 NOTREACHED(); |
| 514 return NULL; | 457 return NULL; |
| 515 } | 458 } |
| 516 | 459 |
| 517 if (IsNoSwapInExperiment(prerender_data->contents()->experiment_id())) | 460 if (IsNoSwapInExperiment(prerender_data->contents()->experiment_id())) |
| 518 return NULL; | 461 return NULL; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 609 histograms_->RecordAbandonTimeUntilUsed( | 552 histograms_->RecordAbandonTimeUntilUsed( |
| 610 prerender_data->contents()->origin(), | 553 prerender_data->contents()->origin(), |
| 611 prerender_data->abandon_time().is_null() ? | 554 prerender_data->abandon_time().is_null() ? |
| 612 base::TimeDelta() : | 555 base::TimeDelta() : |
| 613 GetCurrentTimeTicks() - prerender_data->abandon_time()); | 556 GetCurrentTimeTicks() - prerender_data->abandon_time()); |
| 614 | 557 |
| 615 histograms_->RecordPerSessionCount(prerender_data->contents()->origin(), | 558 histograms_->RecordPerSessionCount(prerender_data->contents()->origin(), |
| 616 ++prerenders_per_session_count_); | 559 ++prerenders_per_session_count_); |
| 617 histograms_->RecordUsedPrerender(prerender_data->contents()->origin()); | 560 histograms_->RecordUsedPrerender(prerender_data->contents()->origin()); |
| 618 | 561 |
| 619 if (prerender_data->pending_swap()) | |
| 620 prerender_data->pending_swap()->set_swap_successful(true); | |
| 621 ScopedVector<PrerenderData>::iterator to_erase = | 562 ScopedVector<PrerenderData>::iterator to_erase = |
| 622 FindIteratorForPrerenderContents(prerender_data->contents()); | 563 FindIteratorForPrerenderContents(prerender_data->contents()); |
| 623 DCHECK(active_prerenders_.end() != to_erase); | 564 DCHECK(active_prerenders_.end() != to_erase); |
| 624 DCHECK_EQ(prerender_data, *to_erase); | 565 DCHECK_EQ(prerender_data, *to_erase); |
| 625 scoped_ptr<PrerenderContents> | 566 scoped_ptr<PrerenderContents> |
| 626 prerender_contents(prerender_data->ReleaseContents()); | 567 prerender_contents(prerender_data->ReleaseContents()); |
| 627 active_prerenders_.erase(to_erase); | 568 active_prerenders_.erase(to_erase); |
| 628 | 569 |
| 629 // Mark prerender as used. | 570 // Mark prerender as used. |
| 630 prerender_contents->PrepareForUse(); | 571 prerender_contents->PrepareForUse(); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 693 ActuallyPrerendering() && | 634 ActuallyPrerendering() && |
| 694 GetMode() == PRERENDER_MODE_EXPERIMENT_MATCH_COMPLETE_GROUP) { | 635 GetMode() == PRERENDER_MODE_EXPERIMENT_MATCH_COMPLETE_GROUP) { |
| 695 // TODO(tburkard): I'd like to DCHECK that we are actually prerendering. | 636 // TODO(tburkard): I'd like to DCHECK that we are actually prerendering. |
| 696 // However, what if new conditions are added and | 637 // However, what if new conditions are added and |
| 697 // NeedMatchCompleteDummyForFinalStatus is not being updated. Not sure | 638 // NeedMatchCompleteDummyForFinalStatus is not being updated. Not sure |
| 698 // what's the best thing to do here. For now, I will just check whether | 639 // what's the best thing to do here. For now, I will just check whether |
| 699 // we are actually prerendering. | 640 // we are actually prerendering. |
| 700 (*it)->MakeIntoMatchCompleteReplacement(); | 641 (*it)->MakeIntoMatchCompleteReplacement(); |
| 701 } else { | 642 } else { |
| 702 to_delete_prerenders_.push_back(*it); | 643 to_delete_prerenders_.push_back(*it); |
| 703 (*it)->ClearPendingSwap(); | |
| 704 active_prerenders_.weak_erase(it); | 644 active_prerenders_.weak_erase(it); |
| 705 } | 645 } |
| 706 | 646 |
| 707 // Destroy the old WebContents relatively promptly to reduce resource usage. | 647 // Destroy the old WebContents relatively promptly to reduce resource usage. |
| 708 PostCleanupTask(); | 648 PostCleanupTask(); |
| 709 } | 649 } |
| 710 | 650 |
| 711 void PrerenderManager::RecordPageLoadTimeNotSwappedIn( | 651 void PrerenderManager::RecordPageLoadTimeNotSwappedIn( |
| 712 Origin origin, | 652 Origin origin, |
| 713 base::TimeDelta page_load_time, | 653 base::TimeDelta page_load_time, |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1021 PrerenderHandle* handle) { | 961 PrerenderHandle* handle) { |
| 1022 DCHECK_LT(0, handle_count_); | 962 DCHECK_LT(0, handle_count_); |
| 1023 DCHECK_NE(static_cast<PrerenderContents*>(NULL), contents_); | 963 DCHECK_NE(static_cast<PrerenderContents*>(NULL), contents_); |
| 1024 | 964 |
| 1025 if (--handle_count_ == 0) { | 965 if (--handle_count_ == 0) { |
| 1026 // This will eventually remove this object from active_prerenders_. | 966 // This will eventually remove this object from active_prerenders_. |
| 1027 contents_->Destroy(FINAL_STATUS_CANCELLED); | 967 contents_->Destroy(FINAL_STATUS_CANCELLED); |
| 1028 } | 968 } |
| 1029 } | 969 } |
| 1030 | 970 |
| 1031 void PrerenderManager::PrerenderData::ClearPendingSwap() { | |
| 1032 pending_swap_.reset(NULL); | |
| 1033 } | |
| 1034 | |
| 1035 PrerenderContents* PrerenderManager::PrerenderData::ReleaseContents() { | 971 PrerenderContents* PrerenderManager::PrerenderData::ReleaseContents() { |
| 1036 return contents_.release(); | 972 return contents_.release(); |
| 1037 } | 973 } |
| 1038 | 974 |
| 1039 PrerenderManager::PendingSwap::PendingSwap( | |
| 1040 PrerenderManager* manager, | |
| 1041 content::WebContents* target_contents, | |
| 1042 PrerenderData* prerender_data, | |
| 1043 const GURL& url, | |
| 1044 bool should_replace_current_entry) | |
| 1045 : content::WebContentsObserver(target_contents), | |
| 1046 manager_(manager), | |
| 1047 prerender_data_(prerender_data), | |
| 1048 url_(url), | |
| 1049 should_replace_current_entry_(should_replace_current_entry), | |
| 1050 start_time_(base::TimeTicks::Now()), | |
| 1051 seen_target_route_id_(false), | |
| 1052 swap_successful_(false), | |
| 1053 weak_factory_(this) { | |
| 1054 } | |
| 1055 | |
| 1056 PrerenderManager::PendingSwap::~PendingSwap() { | |
| 1057 manager_->prerender_tracker()->RemovePrerenderPendingSwap( | |
| 1058 target_route_id_, swap_successful_); | |
| 1059 } | |
| 1060 | |
| 1061 void PrerenderManager::PendingSwap::BeginSwap() { | |
| 1062 if (g_hang_session_storage_merges_for_testing) | |
| 1063 return; | |
| 1064 | |
| 1065 SessionStorageNamespace* target_namespace = | |
| 1066 web_contents()->GetController().GetDefaultSessionStorageNamespace(); | |
| 1067 SessionStorageNamespace* prerender_namespace = | |
| 1068 prerender_data_->contents()->GetSessionStorageNamespace(); | |
| 1069 | |
| 1070 prerender_namespace->Merge( | |
| 1071 true, prerender_data_->contents()->child_id(), | |
| 1072 target_namespace, | |
| 1073 base::Bind(&PrerenderManager::PendingSwap::OnMergeCompleted, | |
| 1074 weak_factory_.GetWeakPtr())); | |
| 1075 | |
| 1076 merge_timeout_.Start( | |
| 1077 FROM_HERE, | |
| 1078 base::TimeDelta::FromMilliseconds( | |
| 1079 kSessionStorageNamespaceMergeTimeoutMs), | |
| 1080 this, &PrerenderManager::PendingSwap::OnMergeTimeout); | |
| 1081 } | |
| 1082 | |
| 1083 void PrerenderManager::PendingSwap::AboutToNavigateRenderFrame( | |
| 1084 RenderFrameHost* render_frame_host) { | |
| 1085 // TODO(davidben): Update prerendering for --site-per-process. | |
| 1086 if (render_frame_host->GetParent()) | |
| 1087 return; | |
| 1088 | |
| 1089 if (seen_target_route_id_) { | |
| 1090 // A second navigation began browser-side. | |
| 1091 prerender_data_->ClearPendingSwap(); | |
| 1092 return; | |
| 1093 } | |
| 1094 | |
| 1095 seen_target_route_id_ = true; | |
| 1096 target_route_id_ = PrerenderTracker::ChildRouteIdPair( | |
| 1097 render_frame_host->GetProcess()->GetID(), | |
| 1098 render_frame_host->GetRoutingID()); | |
| 1099 manager_->prerender_tracker()->AddPrerenderPendingSwap( | |
| 1100 target_route_id_, url_); | |
| 1101 } | |
| 1102 | |
| 1103 void PrerenderManager::PendingSwap::DidStartProvisionalLoadForFrame( | |
| 1104 content::RenderFrameHost* render_frame_host, | |
| 1105 const GURL& validated_url, | |
| 1106 bool is_error_page, | |
| 1107 bool is_iframe_srcdoc) { | |
| 1108 if (render_frame_host->GetParent()) | |
| 1109 return; | |
| 1110 | |
| 1111 // We must only cancel the pending swap if the url navigated to is not | |
| 1112 // the URL being attempted to be swapped in. That's because in the normal | |
| 1113 // flow, a ProvisionalChangeToMainFrameUrl will happen for the URL attempted | |
| 1114 // to be swapped in immediately after the pending swap has issued its merge. | |
| 1115 if (validated_url != url_) | |
| 1116 prerender_data_->ClearPendingSwap(); | |
| 1117 } | |
| 1118 | |
| 1119 void PrerenderManager::PendingSwap::DidCommitProvisionalLoadForFrame( | |
| 1120 content::RenderFrameHost* render_frame_host, | |
| 1121 const GURL& validated_url, | |
| 1122 ui::PageTransition transition_type) { | |
| 1123 if (render_frame_host->GetParent()) | |
| 1124 return; | |
| 1125 prerender_data_->ClearPendingSwap(); | |
| 1126 } | |
| 1127 | |
| 1128 void PrerenderManager::PendingSwap::DidFailProvisionalLoad( | |
| 1129 content::RenderFrameHost* render_frame_host, | |
| 1130 const GURL& validated_url, | |
| 1131 int error_code, | |
| 1132 const base::string16& error_description) { | |
| 1133 if (render_frame_host->GetParent()) | |
| 1134 return; | |
| 1135 prerender_data_->ClearPendingSwap(); | |
| 1136 } | |
| 1137 | |
| 1138 void PrerenderManager::PendingSwap::WebContentsDestroyed() { | |
| 1139 prerender_data_->ClearPendingSwap(); | |
| 1140 } | |
| 1141 | |
| 1142 void PrerenderManager::PendingSwap::RecordEvent(PrerenderEvent event) const { | |
| 1143 manager_->RecordEvent(prerender_data_->contents(), event); | |
| 1144 } | |
| 1145 | |
| 1146 void PrerenderManager::PendingSwap::OnMergeCompleted( | |
| 1147 SessionStorageNamespace::MergeResult result) { | |
| 1148 UMA_HISTOGRAM_TIMES("Prerender.SessionStorageNamespaceMergeTime", | |
| 1149 base::TimeTicks::Now() - start_time_); | |
| 1150 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_MERGE_DONE); | |
| 1151 | |
| 1152 // Log the exact merge result in a histogram. | |
| 1153 switch (result) { | |
| 1154 case SessionStorageNamespace::MERGE_RESULT_NAMESPACE_NOT_FOUND: | |
| 1155 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_NAMESPACE_NOT_FOUND); | |
| 1156 break; | |
| 1157 case SessionStorageNamespace::MERGE_RESULT_NAMESPACE_NOT_ALIAS: | |
| 1158 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_NAMESPACE_NOT_ALIAS); | |
| 1159 break; | |
| 1160 case SessionStorageNamespace::MERGE_RESULT_NOT_LOGGING: | |
| 1161 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_NOT_LOGGING); | |
| 1162 break; | |
| 1163 case SessionStorageNamespace::MERGE_RESULT_NO_TRANSACTIONS: | |
| 1164 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_NO_TRANSACTIONS); | |
| 1165 break; | |
| 1166 case SessionStorageNamespace::MERGE_RESULT_TOO_MANY_TRANSACTIONS: | |
| 1167 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_TOO_MANY_TRANSACTIONS); | |
| 1168 break; | |
| 1169 case SessionStorageNamespace::MERGE_RESULT_NOT_MERGEABLE: | |
| 1170 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_NOT_MERGEABLE); | |
| 1171 break; | |
| 1172 case SessionStorageNamespace::MERGE_RESULT_MERGEABLE: | |
| 1173 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_RESULT_MERGEABLE); | |
| 1174 break; | |
| 1175 default: | |
| 1176 NOTREACHED(); | |
| 1177 } | |
| 1178 | |
| 1179 if (result != SessionStorageNamespace::MERGE_RESULT_MERGEABLE && | |
| 1180 result != SessionStorageNamespace::MERGE_RESULT_NO_TRANSACTIONS) { | |
| 1181 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_MERGE_FAILED); | |
| 1182 prerender_data_->ClearPendingSwap(); | |
| 1183 return; | |
| 1184 } | |
| 1185 | |
| 1186 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_SWAPPING_IN); | |
| 1187 | |
| 1188 // Note that SwapInternal will, on success, delete |prerender_data_| and | |
| 1189 // |this|. It will also delete |this| in some failure cases. Pass in a new | |
| 1190 // GURL object rather than a reference to |url_|. Also hold on to |manager_| | |
| 1191 // and |prerender_data_|. | |
| 1192 // | |
| 1193 // TODO(davidben): Can we make this less fragile? | |
| 1194 PrerenderManager* manager = manager_; | |
| 1195 PrerenderData* prerender_data = prerender_data_; | |
| 1196 WebContents* new_web_contents = | |
| 1197 manager_->SwapInternal(GURL(url_), | |
| 1198 web_contents(), | |
| 1199 prerender_data_, | |
| 1200 should_replace_current_entry_); | |
| 1201 if (!new_web_contents) { | |
| 1202 manager->RecordEvent(prerender_data->contents(), | |
| 1203 PRERENDER_EVENT_MERGE_RESULT_SWAPIN_FAILED); | |
| 1204 // Depending on whether SwapInternal called Destroy() or simply failed to | |
| 1205 // swap, |this| may or may not be deleted. Either way, if the swap failed, | |
| 1206 // |prerender_data| is deleted asynchronously, so this call is a no-op if | |
| 1207 // |this| is already gone. | |
| 1208 prerender_data->ClearPendingSwap(); | |
| 1209 } | |
| 1210 } | |
| 1211 | |
| 1212 void PrerenderManager::PendingSwap::OnMergeTimeout() { | |
| 1213 RecordEvent(PRERENDER_EVENT_MERGE_RESULT_TIMED_OUT); | |
| 1214 prerender_data_->ClearPendingSwap(); | |
| 1215 } | |
| 1216 | |
| 1217 void PrerenderManager::SetPrerenderContentsFactory( | 975 void PrerenderManager::SetPrerenderContentsFactory( |
| 1218 PrerenderContents::Factory* prerender_contents_factory) { | 976 PrerenderContents::Factory* prerender_contents_factory) { |
| 1219 DCHECK(CalledOnValidThread()); | 977 DCHECK(CalledOnValidThread()); |
| 1220 prerender_contents_factory_.reset(prerender_contents_factory); | 978 prerender_contents_factory_.reset(prerender_contents_factory); |
| 1221 } | 979 } |
| 1222 | 980 |
| 1223 void PrerenderManager::SourceNavigatedAway(PrerenderData* prerender_data) { | 981 void PrerenderManager::SourceNavigatedAway(PrerenderData* prerender_data) { |
| 1224 // The expiry time of our prerender data will likely change because of | 982 // The expiry time of our prerender data will likely change because of |
| 1225 // this navigation. This requires a resort of active_prerenders_. | 983 // this navigation. This requires a resort of active_prerenders_. |
| 1226 ScopedVector<PrerenderData>::iterator it = | 984 ScopedVector<PrerenderData>::iterator it = |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1485 const GURL& url, | 1243 const GURL& url, |
| 1486 const SessionStorageNamespace* session_storage_namespace) { | 1244 const SessionStorageNamespace* session_storage_namespace) { |
| 1487 for (ScopedVector<PrerenderData>::iterator it = active_prerenders_.begin(); | 1245 for (ScopedVector<PrerenderData>::iterator it = active_prerenders_.begin(); |
| 1488 it != active_prerenders_.end(); ++it) { | 1246 it != active_prerenders_.end(); ++it) { |
| 1489 if ((*it)->contents()->Matches(url, session_storage_namespace)) | 1247 if ((*it)->contents()->Matches(url, session_storage_namespace)) |
| 1490 return *it; | 1248 return *it; |
| 1491 } | 1249 } |
| 1492 return NULL; | 1250 return NULL; |
| 1493 } | 1251 } |
| 1494 | 1252 |
| 1495 PrerenderManager::PrerenderData* | |
| 1496 PrerenderManager::FindPrerenderDataForTargetContents( | |
| 1497 WebContents* target_contents) { | |
| 1498 for (ScopedVector<PrerenderData>::iterator it = active_prerenders_.begin(); | |
| 1499 it != active_prerenders_.end(); ++it) { | |
| 1500 if ((*it)->pending_swap() && | |
| 1501 (*it)->pending_swap()->web_contents() == target_contents) | |
| 1502 return *it; | |
| 1503 } | |
| 1504 return NULL; | |
| 1505 } | |
| 1506 | |
| 1507 ScopedVector<PrerenderManager::PrerenderData>::iterator | 1253 ScopedVector<PrerenderManager::PrerenderData>::iterator |
| 1508 PrerenderManager::FindIteratorForPrerenderContents( | 1254 PrerenderManager::FindIteratorForPrerenderContents( |
| 1509 PrerenderContents* prerender_contents) { | 1255 PrerenderContents* prerender_contents) { |
| 1510 for (ScopedVector<PrerenderData>::iterator it = active_prerenders_.begin(); | 1256 for (ScopedVector<PrerenderData>::iterator it = active_prerenders_.begin(); |
| 1511 it != active_prerenders_.end(); ++it) { | 1257 it != active_prerenders_.end(); ++it) { |
| 1512 if (prerender_contents == (*it)->contents()) | 1258 if (prerender_contents == (*it)->contents()) |
| 1513 return it; | 1259 return it; |
| 1514 } | 1260 } |
| 1515 return active_prerenders_.end(); | 1261 return active_prerenders_.end(); |
| 1516 } | 1262 } |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1753 if (logged_in_state_.get()) | 1499 if (logged_in_state_.get()) |
| 1754 logged_in_state_->erase(domain_key); | 1500 logged_in_state_->erase(domain_key); |
| 1755 } | 1501 } |
| 1756 | 1502 |
| 1757 void PrerenderManager::LoggedInPredictorDataReceived( | 1503 void PrerenderManager::LoggedInPredictorDataReceived( |
| 1758 scoped_ptr<LoggedInStateMap> new_map) { | 1504 scoped_ptr<LoggedInStateMap> new_map) { |
| 1759 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1505 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1760 logged_in_state_.swap(new_map); | 1506 logged_in_state_.swap(new_map); |
| 1761 } | 1507 } |
| 1762 | 1508 |
| 1763 void PrerenderManager::RecordEvent(PrerenderContents* contents, | |
| 1764 PrerenderEvent event) const { | |
| 1765 if (!contents) | |
| 1766 histograms_->RecordEvent(ORIGIN_NONE, kNoExperiment, event); | |
| 1767 else | |
| 1768 histograms_->RecordEvent(contents->origin(), contents->experiment_id(), | |
| 1769 event); | |
| 1770 } | |
| 1771 | |
| 1772 // static | 1509 // static |
| 1773 void PrerenderManager::RecordCookieEvent(int process_id, | 1510 void PrerenderManager::RecordCookieEvent(int process_id, |
| 1774 int frame_id, | 1511 int frame_id, |
| 1775 const GURL& url, | 1512 const GURL& url, |
| 1776 const GURL& frame_url, | 1513 const GURL& frame_url, |
| 1777 bool is_for_blocking_resource, | 1514 bool is_for_blocking_resource, |
| 1778 PrerenderContents::CookieEvent event, | 1515 PrerenderContents::CookieEvent event, |
| 1779 const net::CookieList* cookie_list) { | 1516 const net::CookieList* cookie_list) { |
| 1780 RenderFrameHost* rfh = RenderFrameHost::FromID(process_id, frame_id); | 1517 RenderFrameHost* rfh = RenderFrameHost::FromID(process_id, frame_id); |
| 1781 WebContents* web_contents = WebContents::FromRenderFrameHost(rfh); | 1518 WebContents* web_contents = WebContents::FromRenderFrameHost(rfh); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1829 | 1566 |
| 1830 void PrerenderManager::OnHistoryServiceDidQueryURL( | 1567 void PrerenderManager::OnHistoryServiceDidQueryURL( |
| 1831 Origin origin, | 1568 Origin origin, |
| 1832 uint8 experiment_id, | 1569 uint8 experiment_id, |
| 1833 bool success, | 1570 bool success, |
| 1834 const history::URLRow& url_row, | 1571 const history::URLRow& url_row, |
| 1835 const history::VisitVector& /*visits*/) { | 1572 const history::VisitVector& /*visits*/) { |
| 1836 histograms_->RecordPrerenderPageVisitedStatus(origin, experiment_id, success); | 1573 histograms_->RecordPrerenderPageVisitedStatus(origin, experiment_id, success); |
| 1837 } | 1574 } |
| 1838 | 1575 |
| 1839 // static | |
| 1840 void PrerenderManager::HangSessionStorageMergesForTesting() { | |
| 1841 g_hang_session_storage_merges_for_testing = true; | |
| 1842 } | |
| 1843 | |
| 1844 void PrerenderManager::RecordNetworkBytes(Origin origin, | 1576 void PrerenderManager::RecordNetworkBytes(Origin origin, |
| 1845 bool used, | 1577 bool used, |
| 1846 int64 prerender_bytes) { | 1578 int64 prerender_bytes) { |
| 1847 if (!ActuallyPrerendering()) | 1579 if (!ActuallyPrerendering()) |
| 1848 return; | 1580 return; |
| 1849 int64 recent_profile_bytes = | 1581 int64 recent_profile_bytes = |
| 1850 profile_network_bytes_ - last_recorded_profile_network_bytes_; | 1582 profile_network_bytes_ - last_recorded_profile_network_bytes_; |
| 1851 last_recorded_profile_network_bytes_ = profile_network_bytes_; | 1583 last_recorded_profile_network_bytes_ = profile_network_bytes_; |
| 1852 DCHECK_GE(recent_profile_bytes, 0); | 1584 DCHECK_GE(recent_profile_bytes, 0); |
| 1853 histograms_->RecordNetworkBytes( | 1585 histograms_->RecordNetworkBytes( |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1896 content::RenderProcessHost* host) { | 1628 content::RenderProcessHost* host) { |
| 1897 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1629 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1898 prerender_process_hosts_.erase(host); | 1630 prerender_process_hosts_.erase(host); |
| 1899 BrowserThread::PostTask( | 1631 BrowserThread::PostTask( |
| 1900 BrowserThread::IO, FROM_HERE, | 1632 BrowserThread::IO, FROM_HERE, |
| 1901 base::Bind(&PrerenderTracker::RemovePrerenderCookieStoreOnIOThread, | 1633 base::Bind(&PrerenderTracker::RemovePrerenderCookieStoreOnIOThread, |
| 1902 base::Unretained(prerender_tracker()), host->GetID(), false)); | 1634 base::Unretained(prerender_tracker()), host->GetID(), false)); |
| 1903 } | 1635 } |
| 1904 | 1636 |
| 1905 } // namespace prerender | 1637 } // namespace prerender |
| OLD | NEW |