Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/metrics/field_trial.h" | 8 #include "base/metrics/field_trial.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/time.h" | 10 #include "base/time.h" |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 41 // Time window for which we will record windowed PLT's from the last | 41 // Time window for which we will record windowed PLT's from the last |
| 42 // observed link rel=prefetch tag. | 42 // observed link rel=prefetch tag. |
| 43 const int kWindowDurationSeconds = 30; | 43 const int kWindowDurationSeconds = 30; |
| 44 | 44 |
| 45 // Time interval at which periodic cleanups are performed. | 45 // Time interval at which periodic cleanups are performed. |
| 46 const int kPeriodicCleanupIntervalMs = 1000; | 46 const int kPeriodicCleanupIntervalMs = 1000; |
| 47 | 47 |
| 48 // Time interval before a new prerender is allowed. | 48 // Time interval before a new prerender is allowed. |
| 49 const int kMinTimeBetweenPrerendersMs = 500; | 49 const int kMinTimeBetweenPrerendersMs = 500; |
| 50 | 50 |
| 51 // Valid HTTP methods for prerendering. | |
| 52 const char* kValidHttpMethods[] = { | |
|
cbentzel
2011/04/30 01:03:34
I've usually seen as
const char* const
dominich
2011/05/02 16:45:55
Done.
| |
| 53 "OPTIONS", "GET", "HEAD", "TRACE", "CONNECT", | |
|
cbentzel
2011/04/30 01:03:34
I'd do one of these per-line, and not include the
dominich
2011/05/02 16:45:55
Done.
| |
| 54 // "PUT", "POST", "DELETE" | |
| 55 }; | |
| 56 | |
| 51 } // namespace | 57 } // namespace |
| 52 | 58 |
| 53 // static | 59 // static |
| 54 int PrerenderManager::prerenders_per_session_count_ = 0; | 60 int PrerenderManager::prerenders_per_session_count_ = 0; |
| 55 | 61 |
| 56 // static | 62 // static |
| 57 PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = | 63 PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = |
| 58 PRERENDER_MODE_ENABLED; | 64 PRERENDER_MODE_ENABLED; |
| 59 | 65 |
| 60 // static | 66 // static |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 102 GURL new_url(string16(decoded_url.data(), decoded_url.length())); | 108 GURL new_url(string16(decoded_url.data(), decoded_url.length())); |
| 103 if (!new_url.is_empty() && new_url.is_valid()) { | 109 if (!new_url.is_empty() && new_url.is_valid()) { |
| 104 *alias_url = new_url; | 110 *alias_url = new_url; |
| 105 return true; | 111 return true; |
| 106 } | 112 } |
| 107 return false; | 113 return false; |
| 108 } | 114 } |
| 109 return false; | 115 return false; |
| 110 } | 116 } |
| 111 | 117 |
| 118 // static | |
| 119 bool PrerenderManager::IsValidHttpMethod(const std::string& method) { | |
| 120 for (size_t i = 0; i < arraysize(kValidHttpMethods); ++i) { | |
| 121 if (method == kValidHttpMethods[i]) | |
|
cbentzel
2011/04/30 01:03:34
I'm not sure if these are canonicalized to upper c
dominich
2011/05/02 16:45:55
Tested and they are. Added comment to confirm.
| |
| 122 return true; | |
| 123 } | |
| 124 | |
| 125 return false; | |
| 126 } | |
| 127 | |
| 112 struct PrerenderManager::PrerenderContentsData { | 128 struct PrerenderManager::PrerenderContentsData { |
| 113 PrerenderContents* contents_; | 129 PrerenderContents* contents_; |
| 114 base::Time start_time_; | 130 base::Time start_time_; |
| 115 PrerenderContentsData(PrerenderContents* contents, base::Time start_time) | 131 PrerenderContentsData(PrerenderContents* contents, base::Time start_time) |
| 116 : contents_(contents), | 132 : contents_(contents), |
| 117 start_time_(start_time) { | 133 start_time_(start_time) { |
| 118 } | 134 } |
| 119 }; | 135 }; |
| 120 | 136 |
| 121 struct PrerenderManager::PendingContentsData { | 137 struct PrerenderManager::PendingContentsData { |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 140 prerender_manager->RecordPrefetchTagObserved(); | 156 prerender_manager->RecordPrefetchTagObserved(); |
| 141 // TODO(cbentzel): Should the decision to make pending be done on the | 157 // TODO(cbentzel): Should the decision to make pending be done on the |
| 142 // UI thread rather than the IO thread? The page may have | 158 // UI thread rather than the IO thread? The page may have |
| 143 // become activated at this point. | 159 // become activated at this point. |
| 144 if (make_pending) | 160 if (make_pending) |
| 145 prerender_manager->AddPendingPreload(child_route_id_pair, url, referrer); | 161 prerender_manager->AddPendingPreload(child_route_id_pair, url, referrer); |
| 146 else | 162 else |
| 147 prerender_manager->AddPreload(child_route_id_pair, url, referrer); | 163 prerender_manager->AddPreload(child_route_id_pair, url, referrer); |
| 148 } | 164 } |
| 149 | 165 |
| 166 void DestroyPreloadForChildRouteIdPairOnUIThread( | |
| 167 const base::WeakPtr<PrerenderManager>& prerender_manager_weak_ptr, | |
| 168 const std::pair<int, int>& child_route_id_pair, | |
| 169 FinalStatus final_status) { | |
| 170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 171 PrerenderManager* prerender_manager = prerender_manager_weak_ptr.get(); | |
| 172 if (!prerender_manager) | |
| 173 return; | |
| 174 prerender_manager->DestroyPreloadForChildRouteIdPair(child_route_id_pair, | |
| 175 final_status); | |
| 176 } | |
| 177 | |
| 150 PrerenderManager::PrerenderManager(Profile* profile) | 178 PrerenderManager::PrerenderManager(Profile* profile) |
| 151 : rate_limit_enabled_(true), | 179 : rate_limit_enabled_(true), |
| 152 enabled_(true), | 180 enabled_(true), |
| 153 profile_(profile), | 181 profile_(profile), |
| 154 max_prerender_age_(base::TimeDelta::FromSeconds( | 182 max_prerender_age_(base::TimeDelta::FromSeconds( |
| 155 kDefaultMaxPrerenderAgeSeconds)), | 183 kDefaultMaxPrerenderAgeSeconds)), |
| 156 max_prerender_memory_mb_(kDefaultMaxPrerenderMemoryMB), | 184 max_prerender_memory_mb_(kDefaultMaxPrerenderMemoryMB), |
| 157 max_elements_(kDefaultMaxPrerenderElements), | 185 max_elements_(kDefaultMaxPrerenderElements), |
| 158 prerender_contents_factory_(PrerenderContents::CreateFactory()), | 186 prerender_contents_factory_(PrerenderContents::CreateFactory()), |
| 159 last_prerender_start_time_(GetCurrentTimeTicks() - | 187 last_prerender_start_time_(GetCurrentTimeTicks() - |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 258 StartSchedulingPeriodicCleanups(); | 286 StartSchedulingPeriodicCleanups(); |
| 259 return true; | 287 return true; |
| 260 } | 288 } |
| 261 | 289 |
| 262 void PrerenderManager::AddPendingPreload( | 290 void PrerenderManager::AddPendingPreload( |
| 263 const std::pair<int, int>& child_route_id_pair, | 291 const std::pair<int, int>& child_route_id_pair, |
| 264 const GURL& url, | 292 const GURL& url, |
| 265 const GURL& referrer) { | 293 const GURL& referrer) { |
| 266 DCHECK(CalledOnValidThread()); | 294 DCHECK(CalledOnValidThread()); |
| 267 // Check if this is coming from a valid prerender RenderViewHost. | 295 // Check if this is coming from a valid prerender RenderViewHost. |
| 268 bool is_valid_prerender = false; | 296 bool is_valid_prerender = |
| 269 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); | 297 (FindPrerenderContentsForChildRouteIdPair(child_route_id_pair) != |
| 270 it != prerender_list_.end(); ++it) { | 298 prerender_list_.end()); |
| 271 PrerenderContents* prerender_contents = it->contents_; | |
| 272 | |
| 273 int child_id; | |
| 274 int route_id; | |
| 275 bool has_child_id = prerender_contents->GetChildId(&child_id); | |
| 276 bool has_route_id = has_child_id && | |
| 277 prerender_contents->GetRouteId(&route_id); | |
| 278 | |
| 279 if (has_child_id && has_route_id && | |
| 280 child_id == child_route_id_pair.first && | |
| 281 route_id == child_route_id_pair.second) { | |
| 282 is_valid_prerender = true; | |
| 283 break; | |
| 284 } | |
| 285 } | |
| 286 | 299 |
| 287 // If not, we could check to see if the RenderViewHost specified by the | 300 // If not, we could check to see if the RenderViewHost specified by the |
| 288 // child_route_id_pair exists and if so just start prerendering, as this | 301 // child_route_id_pair exists and if so just start prerendering, as this |
| 289 // suggests that the link was clicked, though this might prerender something | 302 // suggests that the link was clicked, though this might prerender something |
| 290 // that the user has already navigated away from. For now, we'll be | 303 // that the user has already navigated away from. For now, we'll be |
| 291 // conservative and skip the prerender which will mean some prerender requests | 304 // conservative and skip the prerender which will mean some prerender requests |
| 292 // from prerendered pages will be missed if the user navigates quickly. | 305 // from prerendered pages will be missed if the user navigates quickly. |
| 293 if (!is_valid_prerender) { | 306 if (!is_valid_prerender) { |
| 294 RecordFinalStatus(FINAL_STATUS_PENDING_SKIPPED); | 307 RecordFinalStatus(FINAL_STATUS_PENDING_SKIPPED); |
| 295 return; | 308 return; |
| 296 } | 309 } |
| 297 | 310 |
| 298 PendingPrerenderList::iterator it = | 311 PendingPrerenderList::iterator it = |
| 299 pending_prerender_list_.find(child_route_id_pair); | 312 pending_prerender_list_.find(child_route_id_pair); |
| 300 if (it == pending_prerender_list_.end()) { | 313 if (it == pending_prerender_list_.end()) { |
| 301 PendingPrerenderList::value_type el = std::make_pair(child_route_id_pair, | 314 PendingPrerenderList::value_type el = std::make_pair(child_route_id_pair, |
| 302 std::vector<PendingContentsData>()); | 315 std::vector<PendingContentsData>()); |
| 303 it = pending_prerender_list_.insert(el).first; | 316 it = pending_prerender_list_.insert(el).first; |
| 304 } | 317 } |
| 305 | 318 |
| 306 it->second.push_back(PendingContentsData(url, referrer)); | 319 it->second.push_back(PendingContentsData(url, referrer)); |
| 307 } | 320 } |
| 308 | 321 |
| 322 std::list<PrerenderManager::PrerenderContentsData>::iterator | |
| 323 PrerenderManager::FindPrerenderContentsForChildRouteIdPair( | |
| 324 const std::pair<int, int>& child_route_id_pair) { | |
| 325 std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); | |
| 326 for (; it != prerender_list_.end(); ++it) { | |
| 327 PrerenderContents* prerender_contents = it->contents_; | |
| 328 | |
| 329 int child_id; | |
| 330 int route_id; | |
| 331 bool has_child_id = prerender_contents->GetChildId(&child_id); | |
| 332 bool has_route_id = has_child_id && | |
| 333 prerender_contents->GetRouteId(&route_id); | |
| 334 | |
| 335 if (has_child_id && has_route_id && | |
| 336 child_id == child_route_id_pair.first && | |
| 337 route_id == child_route_id_pair.second) { | |
| 338 break; | |
| 339 } | |
| 340 } | |
| 341 return it; | |
| 342 } | |
| 343 | |
| 344 void PrerenderManager::DestroyPreloadForChildRouteIdPair( | |
| 345 const std::pair<int, int>& child_route_id_pair, | |
| 346 FinalStatus final_status) { | |
| 347 DCHECK(CalledOnValidThread()); | |
| 348 std::list<PrerenderContentsData>::iterator it = | |
| 349 FindPrerenderContentsForChildRouteIdPair(child_route_id_pair); | |
| 350 if (it != prerender_list_.end()) { | |
| 351 PrerenderContents* prerender_contents = it->contents_; | |
| 352 prerender_contents->set_final_status(final_status); | |
| 353 RemovePendingPreload(prerender_contents); | |
| 354 | |
| 355 delete prerender_contents; | |
| 356 prerender_list_.erase(it); | |
| 357 } | |
| 358 } | |
| 359 | |
| 309 void PrerenderManager::DeleteOldEntries() { | 360 void PrerenderManager::DeleteOldEntries() { |
| 310 DCHECK(CalledOnValidThread()); | 361 DCHECK(CalledOnValidThread()); |
| 311 while (!prerender_list_.empty()) { | 362 while (!prerender_list_.empty()) { |
| 312 PrerenderContentsData data = prerender_list_.front(); | 363 PrerenderContentsData data = prerender_list_.front(); |
| 313 if (IsPrerenderElementFresh(data.start_time_)) | 364 if (IsPrerenderElementFresh(data.start_time_)) |
| 314 return; | 365 return; |
| 315 prerender_list_.pop_front(); | 366 prerender_list_.pop_front(); |
| 316 data.contents_->set_final_status(FINAL_STATUS_TIMED_OUT); | 367 data.contents_->set_final_status(FINAL_STATUS_TIMED_OUT); |
| 317 delete data.contents_; | 368 delete data.contents_; |
| 318 } | 369 } |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 678 return prerendered_tab_contents_set_.count(tab_contents) > 0; | 729 return prerendered_tab_contents_set_.count(tab_contents) > 0; |
| 679 } | 730 } |
| 680 | 731 |
| 681 bool PrerenderManager::WouldTabContentsBePrerendered( | 732 bool PrerenderManager::WouldTabContentsBePrerendered( |
| 682 TabContents* tab_contents) const { | 733 TabContents* tab_contents) const { |
| 683 DCHECK(CalledOnValidThread()); | 734 DCHECK(CalledOnValidThread()); |
| 684 return would_be_prerendered_tab_contents_set_.count(tab_contents) > 0; | 735 return would_be_prerendered_tab_contents_set_.count(tab_contents) > 0; |
| 685 } | 736 } |
| 686 | 737 |
| 687 } // namespace prerender | 738 } // namespace prerender |
| OLD | NEW |