| 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. |
| 190 if (!source_render_view_host || !source_render_view_host->view()) { |
| 191 RecordFinalStatus(FINAL_STATUS_SOURCE_RENDER_VIEW_CLOSED); |
| 192 return false; |
| 193 } |
| 194 } |
| 195 |
| 180 // TODO(cbentzel): Move invalid checks here instead of PrerenderContents? | 196 // TODO(cbentzel): Move invalid checks here instead of PrerenderContents? |
| 181 PrerenderContentsData data(CreatePrerenderContents(url, all_alias_urls, | 197 PrerenderContentsData data(CreatePrerenderContents(url, all_alias_urls, |
| 182 referrer), | 198 referrer), |
| 183 GetCurrentTime()); | 199 GetCurrentTime()); |
| 184 | 200 |
| 185 prerender_list_.push_back(data); | 201 prerender_list_.push_back(data); |
| 186 if (IsControlGroup()) { | 202 if (IsControlGroup()) { |
| 187 data.contents_->set_final_status(FINAL_STATUS_CONTROL_GROUP); | 203 data.contents_->set_final_status(FINAL_STATUS_CONTROL_GROUP); |
| 188 } else { | 204 } else { |
| 189 last_prerender_start_time_ = GetCurrentTimeTicks(); | 205 last_prerender_start_time_ = GetCurrentTimeTicks(); |
| 190 data.contents_->StartPrerendering(); | 206 data.contents_->StartPrerendering(source_render_view_host); |
| 191 } | 207 } |
| 192 while (prerender_list_.size() > max_elements_) { | 208 while (prerender_list_.size() > max_elements_) { |
| 193 data = prerender_list_.front(); | 209 data = prerender_list_.front(); |
| 194 prerender_list_.pop_front(); | 210 prerender_list_.pop_front(); |
| 195 data.contents_->set_final_status(FINAL_STATUS_EVICTED); | 211 data.contents_->set_final_status(FINAL_STATUS_EVICTED); |
| 196 delete data.contents_; | 212 delete data.contents_; |
| 197 } | 213 } |
| 198 StartSchedulingPeriodicCleanups(); | 214 StartSchedulingPeriodicCleanups(); |
| 199 return true; | 215 return true; |
| 200 } | 216 } |
| 201 | 217 |
| 202 void PrerenderManager::AddPendingPreload( | 218 void PrerenderManager::AddPendingPreload( |
| 203 const std::pair<int,int>& child_route_id_pair, | 219 const std::pair<int, int>& child_route_id_pair, |
| 204 const GURL& url, | 220 const GURL& url, |
| 205 const std::vector<GURL>& alias_urls, | 221 const std::vector<GURL>& alias_urls, |
| 206 const GURL& referrer) { | 222 const GURL& referrer) { |
| 207 // Check if this is coming from a valid prerender rvh. | 223 // Check if this is coming from a valid prerender rvh. |
| 208 bool is_valid_prerender = false; | 224 bool is_valid_prerender = false; |
| 209 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); | 225 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); |
| 210 it != prerender_list_.end(); ++it) { | 226 it != prerender_list_.end(); ++it) { |
| 211 PrerenderContents* pc = it->contents_; | 227 PrerenderContents* pc = it->contents_; |
| 212 | 228 |
| 213 int child_id; | 229 int child_id; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 239 if (it == pending_prerender_list_.end()) { | 255 if (it == pending_prerender_list_.end()) { |
| 240 PendingPrerenderList::value_type el = std::make_pair(child_route_id_pair, | 256 PendingPrerenderList::value_type el = std::make_pair(child_route_id_pair, |
| 241 std::vector<PendingContentsData>()); | 257 std::vector<PendingContentsData>()); |
| 242 it = pending_prerender_list_.insert(el).first; | 258 it = pending_prerender_list_.insert(el).first; |
| 243 } | 259 } |
| 244 | 260 |
| 245 it->second.push_back(PendingContentsData(url, alias_urls, referrer)); | 261 it->second.push_back(PendingContentsData(url, alias_urls, referrer)); |
| 246 } | 262 } |
| 247 | 263 |
| 248 void PrerenderManager::DeleteOldEntries() { | 264 void PrerenderManager::DeleteOldEntries() { |
| 249 while (!prerender_list_.empty()) { | 265 std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); |
| 250 PrerenderContentsData data = prerender_list_.front(); | 266 while (it != prerender_list_.end()) { |
| 251 if (IsPrerenderElementFresh(data.start_time_)) | 267 if (it->contents_->pending_final_status() != FINAL_STATUS_MAX) { |
| 252 return; | 268 it->contents_->set_final_status(it->contents_->pending_final_status()); |
| 253 prerender_list_.pop_front(); | 269 } else if (!IsPrerenderElementFresh(it->start_time_)) { |
| 254 data.contents_->set_final_status(FINAL_STATUS_TIMED_OUT); | 270 it->contents_->set_final_status(FINAL_STATUS_TIMED_OUT); |
| 255 delete data.contents_; | 271 } else { |
| 272 ++it; |
| 273 continue; |
| 274 } |
| 275 delete it->contents_; |
| 276 it = prerender_list_.erase(it); |
| 256 } | 277 } |
| 278 |
| 257 if (prerender_list_.empty()) | 279 if (prerender_list_.empty()) |
| 258 StopSchedulingPeriodicCleanups(); | 280 StopSchedulingPeriodicCleanups(); |
| 259 } | 281 } |
| 260 | 282 |
| 261 PrerenderContents* PrerenderManager::GetEntry(const GURL& url) { | 283 PrerenderContents* PrerenderManager::GetEntry(const GURL& url) { |
| 262 DeleteOldEntries(); | 284 DeleteOldEntries(); |
| 263 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); | 285 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); |
| 264 it != prerender_list_.end(); | 286 it != prerender_list_.end(); |
| 265 ++it) { | 287 ++it) { |
| 266 PrerenderContents* pc = it->contents_; | 288 PrerenderContents* pc = it->contents_; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 | 332 |
| 311 // See if we have any pending prerender requests for this routing id and start | 333 // See if we have any pending prerender requests for this routing id and start |
| 312 // the preload if we do. | 334 // the preload if we do. |
| 313 std::pair<int, int> child_route_pair = std::make_pair(child_id, route_id); | 335 std::pair<int, int> child_route_pair = std::make_pair(child_id, route_id); |
| 314 PendingPrerenderList::iterator pending_it = | 336 PendingPrerenderList::iterator pending_it = |
| 315 pending_prerender_list_.find(child_route_pair); | 337 pending_prerender_list_.find(child_route_pair); |
| 316 if (pending_it != pending_prerender_list_.end()) { | 338 if (pending_it != pending_prerender_list_.end()) { |
| 317 for (std::vector<PendingContentsData>::iterator content_it = | 339 for (std::vector<PendingContentsData>::iterator content_it = |
| 318 pending_it->second.begin(); | 340 pending_it->second.begin(); |
| 319 content_it != pending_it->second.end(); ++content_it) { | 341 content_it != pending_it->second.end(); ++content_it) { |
| 320 AddPreload(content_it->url_, content_it->alias_urls_, | 342 AddPreload(pending_it->first, content_it->url_, content_it->alias_urls_, |
| 321 content_it->referrer_); | 343 content_it->referrer_); |
| 322 } | 344 } |
| 323 pending_prerender_list_.erase(pending_it); | 345 pending_prerender_list_.erase(pending_it); |
| 324 } | 346 } |
| 325 | 347 |
| 326 NotificationService::current()->Notify( | 348 NotificationService::current()->Notify( |
| 327 NotificationType::PRERENDER_CONTENTS_USED, | 349 NotificationType::PRERENDER_CONTENTS_USED, |
| 328 Source<std::pair<int, int> >(&child_route_pair), | 350 Source<std::pair<int, int> >(&child_route_pair), |
| 329 NotificationService::NoDetails()); | 351 NotificationService::NoDetails()); |
| 330 | 352 |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 | 599 |
| 578 bool PrerenderManager::IsTabContentsPrerendered(TabContents* tc) const { | 600 bool PrerenderManager::IsTabContentsPrerendered(TabContents* tc) const { |
| 579 return prerendered_tc_set_.count(tc) > 0; | 601 return prerendered_tc_set_.count(tc) > 0; |
| 580 } | 602 } |
| 581 | 603 |
| 582 bool PrerenderManager::WouldTabContentsBePrerendered(TabContents* tc) const { | 604 bool PrerenderManager::WouldTabContentsBePrerendered(TabContents* tc) const { |
| 583 return would_be_prerendered_tc_set_.count(tc) > 0; | 605 return would_be_prerendered_tc_set_.count(tc) > 0; |
| 584 } | 606 } |
| 585 | 607 |
| 586 } // namespace prerender | 608 } // namespace prerender |
| OLD | NEW |