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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 127 data.contents_->set_final_status(FINAL_STATUS_MANAGER_SHUTDOWN); | 127 data.contents_->set_final_status(FINAL_STATUS_MANAGER_SHUTDOWN); |
| 128 delete data.contents_; | 128 delete data.contents_; |
| 129 } | 129 } |
| 130 } | 130 } |
| 131 | 131 |
| 132 void PrerenderManager::SetPrerenderContentsFactory( | 132 void PrerenderManager::SetPrerenderContentsFactory( |
| 133 PrerenderContents::Factory* prerender_contents_factory) { | 133 PrerenderContents::Factory* prerender_contents_factory) { |
| 134 prerender_contents_factory_.reset(prerender_contents_factory); | 134 prerender_contents_factory_.reset(prerender_contents_factory); |
| 135 } | 135 } |
| 136 | 136 |
| 137 bool PrerenderManager::AddPreload(const GURL& url, | 137 bool PrerenderManager::AddPreload( |
| 138 const std::vector<GURL>& alias_urls, | 138 const std::pair<int, int>& child_route_id_pair, |
| 139 const GURL& referrer) { | 139 const GURL& url, |
| 140 const std::vector<GURL>& alias_urls, | |
| 141 const GURL& referrer) { | |
| 140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 141 DeleteOldEntries(); | 143 DeleteOldEntries(); |
| 142 if (FindEntry(url)) | 144 if (FindEntry(url)) |
| 143 return false; | 145 return false; |
| 144 | 146 |
| 145 // Local copy, since we may have to add an additional entry to it. | 147 // Local copy, since we may have to add an additional entry to it. |
| 146 std::vector<GURL> all_alias_urls = alias_urls; | 148 std::vector<GURL> all_alias_urls = alias_urls; |
| 147 | 149 |
| 148 GURL additional_alias_url; | 150 GURL additional_alias_url; |
| 149 if (IsControlGroup() && | 151 if (IsControlGroup() && |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 170 // Check if enough time has passed since the last prerender. | 172 // Check if enough time has passed since the last prerender. |
| 171 if (!DoesRateLimitAllowPrerender()) { | 173 if (!DoesRateLimitAllowPrerender()) { |
| 172 // Cancel the prerender. We could add it to the pending prerender list but | 174 // Cancel the prerender. We could add it to the pending prerender list but |
| 173 // this doesn't make sense as the next prerender request will be triggered | 175 // this doesn't make sense as the next prerender request will be triggered |
| 174 // by a navigation and is unlikely to be the same site. | 176 // by a navigation and is unlikely to be the same site. |
| 175 RecordFinalStatus(FINAL_STATUS_RATE_LIMIT_EXCEEDED); | 177 RecordFinalStatus(FINAL_STATUS_RATE_LIMIT_EXCEEDED); |
| 176 | 178 |
| 177 return false; | 179 return false; |
| 178 } | 180 } |
| 179 | 181 |
| 182 RenderViewHost* source_render_view_host = NULL; | |
| 183 // This test should fail only during unit tests. | |
| 184 if (child_route_id_pair.first != -1) { | |
| 185 source_render_view_host = | |
| 186 RenderViewHost::FromID(child_route_id_pair.first, | |
| 187 child_route_id_pair.second); | |
| 188 // Don't prerender page if parent RenderViewHost no longer exists, or it has | |
| 189 // no view. The latter should only happen when the RenderView has closed. | |
|
cbentzel
2011/04/19 17:42:41
Is it possible to add a browser test [or at least
mmenke
2011/04/19 20:00:01
I'm not sure about a browser test using our curren
| |
| 190 if (!source_render_view_host || !source_render_view_host->view()) | |
| 191 return false; | |
| 192 } | |
| 193 | |
| 180 // TODO(cbentzel): Move invalid checks here instead of PrerenderContents? | 194 // TODO(cbentzel): Move invalid checks here instead of PrerenderContents? |
| 181 PrerenderContentsData data(CreatePrerenderContents(url, all_alias_urls, | 195 PrerenderContentsData data(CreatePrerenderContents(url, all_alias_urls, |
| 182 referrer), | 196 referrer), |
| 183 GetCurrentTime()); | 197 GetCurrentTime()); |
| 184 | 198 |
| 185 prerender_list_.push_back(data); | 199 prerender_list_.push_back(data); |
| 186 if (IsControlGroup()) { | 200 if (IsControlGroup()) { |
| 187 data.contents_->set_final_status(FINAL_STATUS_CONTROL_GROUP); | 201 data.contents_->set_final_status(FINAL_STATUS_CONTROL_GROUP); |
| 188 } else { | 202 } else { |
| 189 last_prerender_start_time_ = GetCurrentTimeTicks(); | 203 last_prerender_start_time_ = GetCurrentTimeTicks(); |
| 190 data.contents_->StartPrerendering(); | 204 data.contents_->StartPrerendering(source_render_view_host); |
| 191 } | 205 } |
| 192 while (prerender_list_.size() > max_elements_) { | 206 while (prerender_list_.size() > max_elements_) { |
| 193 data = prerender_list_.front(); | 207 data = prerender_list_.front(); |
| 194 prerender_list_.pop_front(); | 208 prerender_list_.pop_front(); |
| 195 data.contents_->set_final_status(FINAL_STATUS_EVICTED); | 209 data.contents_->set_final_status(FINAL_STATUS_EVICTED); |
| 196 delete data.contents_; | 210 delete data.contents_; |
| 197 } | 211 } |
| 198 StartSchedulingPeriodicCleanups(); | 212 StartSchedulingPeriodicCleanups(); |
| 199 return true; | 213 return true; |
| 200 } | 214 } |
| 201 | 215 |
| 202 void PrerenderManager::AddPendingPreload( | 216 void PrerenderManager::AddPendingPreload( |
| 203 const std::pair<int,int>& child_route_id_pair, | 217 const std::pair<int, int>& child_route_id_pair, |
| 204 const GURL& url, | 218 const GURL& url, |
| 205 const std::vector<GURL>& alias_urls, | 219 const std::vector<GURL>& alias_urls, |
| 206 const GURL& referrer) { | 220 const GURL& referrer) { |
| 207 // Check if this is coming from a valid prerender rvh. | 221 // Check if this is coming from a valid prerender rvh. |
| 208 bool is_valid_prerender = false; | 222 bool is_valid_prerender = false; |
| 209 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); | 223 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); |
| 210 it != prerender_list_.end(); ++it) { | 224 it != prerender_list_.end(); ++it) { |
| 211 PrerenderContents* pc = it->contents_; | 225 PrerenderContents* pc = it->contents_; |
| 212 | 226 |
| 213 int child_id; | 227 int child_id; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 239 if (it == pending_prerender_list_.end()) { | 253 if (it == pending_prerender_list_.end()) { |
| 240 PendingPrerenderList::value_type el = std::make_pair(child_route_id_pair, | 254 PendingPrerenderList::value_type el = std::make_pair(child_route_id_pair, |
| 241 std::vector<PendingContentsData>()); | 255 std::vector<PendingContentsData>()); |
| 242 it = pending_prerender_list_.insert(el).first; | 256 it = pending_prerender_list_.insert(el).first; |
| 243 } | 257 } |
| 244 | 258 |
| 245 it->second.push_back(PendingContentsData(url, alias_urls, referrer)); | 259 it->second.push_back(PendingContentsData(url, alias_urls, referrer)); |
| 246 } | 260 } |
| 247 | 261 |
| 248 void PrerenderManager::DeleteOldEntries() { | 262 void PrerenderManager::DeleteOldEntries() { |
| 249 while (!prerender_list_.empty()) { | 263 std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); |
| 250 PrerenderContentsData data = prerender_list_.front(); | 264 while (it != prerender_list_.end()) { |
| 251 if (IsPrerenderElementFresh(data.start_time_)) | 265 if (it->contents_->pending_final_status() != FINAL_STATUS_MAX) { |
| 252 return; | 266 it->contents_->set_final_status(it->contents_->pending_final_status()); |
| 253 prerender_list_.pop_front(); | 267 } else if (!IsPrerenderElementFresh(it->start_time_)) { |
| 254 data.contents_->set_final_status(FINAL_STATUS_TIMED_OUT); | 268 it->contents_->set_final_status(FINAL_STATUS_TIMED_OUT); |
| 255 delete data.contents_; | 269 } else { |
| 270 ++it; | |
| 271 continue; | |
| 272 } | |
| 273 delete it->contents_; | |
| 274 it = prerender_list_.erase(it); | |
| 256 } | 275 } |
| 276 | |
| 257 if (prerender_list_.empty()) | 277 if (prerender_list_.empty()) |
| 258 StopSchedulingPeriodicCleanups(); | 278 StopSchedulingPeriodicCleanups(); |
| 259 } | 279 } |
| 260 | 280 |
| 261 PrerenderContents* PrerenderManager::GetEntry(const GURL& url) { | 281 PrerenderContents* PrerenderManager::GetEntry(const GURL& url) { |
| 262 DeleteOldEntries(); | 282 DeleteOldEntries(); |
| 263 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); | 283 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); |
| 264 it != prerender_list_.end(); | 284 it != prerender_list_.end(); |
| 265 ++it) { | 285 ++it) { |
| 266 PrerenderContents* pc = it->contents_; | 286 PrerenderContents* pc = it->contents_; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 310 | 330 |
| 311 // See if we have any pending prerender requests for this routing id and start | 331 // See if we have any pending prerender requests for this routing id and start |
| 312 // the preload if we do. | 332 // the preload if we do. |
| 313 std::pair<int, int> child_route_pair = std::make_pair(child_id, route_id); | 333 std::pair<int, int> child_route_pair = std::make_pair(child_id, route_id); |
| 314 PendingPrerenderList::iterator pending_it = | 334 PendingPrerenderList::iterator pending_it = |
| 315 pending_prerender_list_.find(child_route_pair); | 335 pending_prerender_list_.find(child_route_pair); |
| 316 if (pending_it != pending_prerender_list_.end()) { | 336 if (pending_it != pending_prerender_list_.end()) { |
| 317 for (std::vector<PendingContentsData>::iterator content_it = | 337 for (std::vector<PendingContentsData>::iterator content_it = |
| 318 pending_it->second.begin(); | 338 pending_it->second.begin(); |
| 319 content_it != pending_it->second.end(); ++content_it) { | 339 content_it != pending_it->second.end(); ++content_it) { |
| 320 AddPreload(content_it->url_, content_it->alias_urls_, | 340 AddPreload(pending_it->first, content_it->url_, content_it->alias_urls_, |
| 321 content_it->referrer_); | 341 content_it->referrer_); |
| 322 } | 342 } |
| 323 pending_prerender_list_.erase(pending_it); | 343 pending_prerender_list_.erase(pending_it); |
| 324 } | 344 } |
| 325 | 345 |
| 326 NotificationService::current()->Notify( | 346 NotificationService::current()->Notify( |
| 327 NotificationType::PRERENDER_CONTENTS_USED, | 347 NotificationType::PRERENDER_CONTENTS_USED, |
| 328 Source<std::pair<int, int> >(&child_route_pair), | 348 Source<std::pair<int, int> >(&child_route_pair), |
| 329 NotificationService::NoDetails()); | 349 NotificationService::NoDetails()); |
| 330 | 350 |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 577 | 597 |
| 578 bool PrerenderManager::IsTabContentsPrerendered(TabContents* tc) const { | 598 bool PrerenderManager::IsTabContentsPrerendered(TabContents* tc) const { |
| 579 return prerendered_tc_set_.count(tc) > 0; | 599 return prerendered_tc_set_.count(tc) > 0; |
| 580 } | 600 } |
| 581 | 601 |
| 582 bool PrerenderManager::WouldTabContentsBePrerendered(TabContents* tc) const { | 602 bool PrerenderManager::WouldTabContentsBePrerendered(TabContents* tc) const { |
| 583 return would_be_prerendered_tc_set_.count(tc) > 0; | 603 return would_be_prerendered_tc_set_.count(tc) > 0; |
| 584 } | 604 } |
| 585 | 605 |
| 586 } // namespace prerender | 606 } // namespace prerender |
| OLD | NEW |