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/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "base/time.h" | 9 #include "base/time.h" |
10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
46 | 46 |
47 struct PrerenderManager::PrerenderContentsData { | 47 struct PrerenderManager::PrerenderContentsData { |
48 PrerenderContents* contents_; | 48 PrerenderContents* contents_; |
49 base::Time start_time_; | 49 base::Time start_time_; |
50 PrerenderContentsData(PrerenderContents* contents, base::Time start_time) | 50 PrerenderContentsData(PrerenderContents* contents, base::Time start_time) |
51 : contents_(contents), | 51 : contents_(contents), |
52 start_time_(start_time) { | 52 start_time_(start_time) { |
53 } | 53 } |
54 }; | 54 }; |
55 | 55 |
56 struct PrerenderManager::PendingContentsData { | |
57 PendingContentsData(const GURL& url, const std::vector<GURL>& alias_urls, | |
58 const GURL& referrer) | |
59 : url_(url), alias_urls_(alias_urls), referrer_(referrer) { } | |
60 ~PendingContentsData() {} | |
61 GURL url_; | |
62 std::vector<GURL> alias_urls_; | |
63 GURL referrer_; | |
64 }; | |
65 | |
66 | |
56 PrerenderManager::PrerenderManager(Profile* profile) | 67 PrerenderManager::PrerenderManager(Profile* profile) |
57 : profile_(profile), | 68 : profile_(profile), |
58 max_prerender_age_(base::TimeDelta::FromSeconds( | 69 max_prerender_age_(base::TimeDelta::FromSeconds( |
59 kDefaultMaxPrerenderAgeSeconds)), | 70 kDefaultMaxPrerenderAgeSeconds)), |
60 max_elements_(kDefaultMaxPrerenderElements), | 71 max_elements_(kDefaultMaxPrerenderElements), |
61 prerender_contents_factory_(PrerenderContents::CreateFactory()) { | 72 prerender_contents_factory_(PrerenderContents::CreateFactory()) { |
62 } | 73 } |
63 | 74 |
64 PrerenderManager::~PrerenderManager() { | 75 PrerenderManager::~PrerenderManager() { |
65 while (!prerender_list_.empty()) { | 76 while (!prerender_list_.empty()) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
100 while (prerender_list_.size() > max_elements_) { | 111 while (prerender_list_.size() > max_elements_) { |
101 data = prerender_list_.front(); | 112 data = prerender_list_.front(); |
102 prerender_list_.pop_front(); | 113 prerender_list_.pop_front(); |
103 data.contents_->set_final_status(FINAL_STATUS_EVICTED); | 114 data.contents_->set_final_status(FINAL_STATUS_EVICTED); |
104 delete data.contents_; | 115 delete data.contents_; |
105 } | 116 } |
106 StartSchedulingPeriodicCleanups(); | 117 StartSchedulingPeriodicCleanups(); |
107 return true; | 118 return true; |
108 } | 119 } |
109 | 120 |
121 void PrerenderManager::AddPendingPreload( | |
122 const std::pair<int,int>& child_route_id_pair, | |
123 const GURL& url, | |
124 const std::vector<GURL>& alias_urls, | |
125 const GURL& referrer) { | |
126 PendingPrerenderList::iterator it = | |
cbentzel
2011/03/16 01:23:28
Should this do FindPendingEntry(url) and early ret
| |
127 pending_prerender_list_.find(child_route_id_pair); | |
128 if (it == pending_prerender_list_.end()) { | |
129 PendingPrerenderList::value_type el = std::make_pair(child_route_id_pair, | |
130 std::vector<PendingContentsData>()); | |
131 it = pending_prerender_list_.insert(el).first; | |
132 } | |
133 | |
134 it->second.push_back(PendingContentsData(url, alias_urls, referrer)); | |
135 } | |
136 | |
110 void PrerenderManager::DeleteOldEntries() { | 137 void PrerenderManager::DeleteOldEntries() { |
111 while (!prerender_list_.empty()) { | 138 while (!prerender_list_.empty()) { |
112 PrerenderContentsData data = prerender_list_.front(); | 139 PrerenderContentsData data = prerender_list_.front(); |
113 if (IsPrerenderElementFresh(data.start_time_)) | 140 if (IsPrerenderElementFresh(data.start_time_)) |
114 return; | 141 return; |
115 prerender_list_.pop_front(); | 142 prerender_list_.pop_front(); |
116 data.contents_->set_final_status(FINAL_STATUS_TIMED_OUT); | 143 data.contents_->set_final_status(FINAL_STATUS_TIMED_OUT); |
117 delete data.contents_; | 144 delete data.contents_; |
118 } | 145 } |
119 if (prerender_list_.empty()) | 146 if (prerender_list_.empty()) |
(...skipping 28 matching lines...) Expand all Loading... | |
148 | 175 |
149 RenderViewHost* rvh = pc->render_view_host(); | 176 RenderViewHost* rvh = pc->render_view_host(); |
150 // RenderViewHosts in PrerenderContents start out hidden. | 177 // RenderViewHosts in PrerenderContents start out hidden. |
151 // Since we are actually using it now, restore it. | 178 // Since we are actually using it now, restore it. |
152 rvh->WasRestored(); | 179 rvh->WasRestored(); |
153 pc->set_render_view_host(NULL); | 180 pc->set_render_view_host(NULL); |
154 rvh->Send(new ViewMsg_DisplayPrerenderedPage(rvh->routing_id())); | 181 rvh->Send(new ViewMsg_DisplayPrerenderedPage(rvh->routing_id())); |
155 tc->SwapInRenderViewHost(rvh); | 182 tc->SwapInRenderViewHost(rvh); |
156 MarkTabContentsAsPrerendered(tc); | 183 MarkTabContentsAsPrerendered(tc); |
157 | 184 |
185 // See if we have any pending prerender requests for this routing id and start | |
186 // the preload if we do. | |
187 std::pair<int, int> child_route_pair = std::make_pair(rvh->process()->id(), | |
188 rvh->routing_id()); | |
189 PendingPrerenderList::iterator pending_it = | |
190 pending_prerender_list_.find(child_route_pair); | |
191 if (pending_it != pending_prerender_list_.end()) { | |
192 for (std::vector<PendingContentsData>::iterator content_it = | |
193 pending_it->second.begin(); | |
194 content_it != pending_it->second.end(); ++content_it) { | |
195 AddPreload(content_it->url_, content_it->alias_urls_, | |
196 content_it->referrer_); | |
197 } | |
198 pending_prerender_list_.erase(pending_it); | |
199 } | |
200 | |
158 ViewHostMsg_FrameNavigate_Params* p = pc->navigate_params(); | 201 ViewHostMsg_FrameNavigate_Params* p = pc->navigate_params(); |
159 if (p != NULL) | 202 if (p != NULL) |
160 tc->DidNavigate(rvh, *p); | 203 tc->DidNavigate(rvh, *p); |
161 | 204 |
162 string16 title = pc->title(); | 205 string16 title = pc->title(); |
163 if (!title.empty()) | 206 if (!title.empty()) |
164 tc->UpdateTitle(rvh, pc->page_id(), UTF16ToWideHack(title)); | 207 tc->UpdateTitle(rvh, pc->page_id(), UTF16ToWideHack(title)); |
165 | 208 |
166 GURL icon_url = pc->icon_url(); | 209 GURL icon_url = pc->icon_url(); |
167 if (!icon_url.is_empty()) | 210 if (!icon_url.is_empty()) |
168 tc->fav_icon_helper().OnUpdateFavIconURL(pc->page_id(), icon_url); | 211 tc->fav_icon_helper().OnUpdateFavIconURL(pc->page_id(), icon_url); |
169 | 212 |
170 if (pc->has_stopped_loading()) | 213 if (pc->has_stopped_loading()) |
171 tc->DidStopLoading(); | 214 tc->DidStopLoading(); |
172 | 215 |
173 return true; | 216 return true; |
174 } | 217 } |
175 | 218 |
176 void PrerenderManager::RemoveEntry(PrerenderContents* entry) { | 219 void PrerenderManager::RemoveEntry(PrerenderContents* entry) { |
177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
178 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); | 221 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); |
179 it != prerender_list_.end(); | 222 it != prerender_list_.end(); |
180 ++it) { | 223 ++it) { |
181 if (it->contents_ == entry) { | 224 if (it->contents_ == entry) { |
225 RemovePendingPreload(entry); | |
182 prerender_list_.erase(it); | 226 prerender_list_.erase(it); |
183 break; | 227 break; |
184 } | 228 } |
185 } | 229 } |
186 DeleteOldEntries(); | 230 DeleteOldEntries(); |
187 } | 231 } |
188 | 232 |
189 base::Time PrerenderManager::GetCurrentTime() const { | 233 base::Time PrerenderManager::GetCurrentTime() const { |
190 return base::Time::Now(); | 234 return base::Time::Now(); |
191 } | 235 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
234 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); | 278 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); |
235 it != prerender_list_.end(); | 279 it != prerender_list_.end(); |
236 ++it) { | 280 ++it) { |
237 if (it->contents_->MatchesURL(url)) | 281 if (it->contents_->MatchesURL(url)) |
238 return it->contents_; | 282 return it->contents_; |
239 } | 283 } |
240 // Entry not found. | 284 // Entry not found. |
241 return NULL; | 285 return NULL; |
242 } | 286 } |
243 | 287 |
288 PrerenderManager::PendingContentsData* | |
289 PrerenderManager::FindPendingEntry(const GURL& url) { | |
cbentzel
2011/03/16 01:23:28
This should be const [I noticed FindEntry wasn't,
| |
290 for (PendingPrerenderList::iterator map_it = pending_prerender_list_.begin(); | |
291 map_it != pending_prerender_list_.end(); | |
292 ++map_it) { | |
293 for (std::vector<PendingContentsData>::iterator content_it = | |
294 map_it->second.begin(); | |
295 content_it != map_it->second.end(); | |
296 ++content_it) { | |
297 if (content_it->url_ == url) | |
cbentzel
2011/03/16 01:23:28
This will probably want to match against alias url
| |
298 return &(*content_it); | |
299 } | |
300 } | |
301 | |
302 return NULL; | |
303 } | |
304 | |
244 // static | 305 // static |
245 void PrerenderManager::RecordPrefetchTagObserved() { | 306 void PrerenderManager::RecordPrefetchTagObserved() { |
246 // Ensure that we are in the UI thread, and post to the UI thread if | 307 // Ensure that we are in the UI thread, and post to the UI thread if |
247 // necessary. | 308 // necessary. |
248 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 309 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
249 BrowserThread::PostTask( | 310 BrowserThread::PostTask( |
250 BrowserThread::UI, | 311 BrowserThread::UI, |
251 FROM_HERE, | 312 FROM_HERE, |
252 NewRunnableFunction( | 313 NewRunnableFunction( |
253 &PrerenderManager::RecordPrefetchTagObservedOnUIThread)); | 314 &PrerenderManager::RecordPrefetchTagObservedOnUIThread)); |
254 } else { | 315 } else { |
255 RecordPrefetchTagObservedOnUIThread(); | 316 RecordPrefetchTagObservedOnUIThread(); |
256 } | 317 } |
257 } | 318 } |
258 | 319 |
259 // static | 320 // static |
260 void PrerenderManager::RecordPrefetchTagObservedOnUIThread() { | 321 void PrerenderManager::RecordPrefetchTagObservedOnUIThread() { |
261 // Once we get here, we have to be on the UI thread. | 322 // Once we get here, we have to be on the UI thread. |
262 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
263 | 324 |
264 // If we observe multiple tags within the 30 second window, we will still | 325 // If we observe multiple tags within the 30 second window, we will still |
265 // reset the window to begin at the most recent occurrence, so that we will | 326 // reset the window to begin at the most recent occurrence, so that we will |
266 // always be in a window in the 30 seconds from each occurrence. | 327 // always be in a window in the 30 seconds from each occurrence. |
267 last_prefetch_seen_time_ = base::TimeTicks::Now(); | 328 last_prefetch_seen_time_ = base::TimeTicks::Now(); |
268 } | 329 } |
269 | 330 |
331 void PrerenderManager::RemovePendingPreload(PrerenderContents* entry) { | |
332 RenderViewHost* rvh = entry->render_view_host(); | |
333 | |
334 // If the entry doesn't have a RenderViewHost then it didn't start | |
335 // prerendering and there shouldn't be any pending preloads to remove. | |
336 if (rvh == NULL) | |
337 return; | |
338 | |
339 std::pair<int, int> child_route_pair = std::make_pair(rvh->process()->id(), | |
340 rvh->routing_id()); | |
341 pending_prerender_list_.erase(child_route_pair); | |
342 } | |
343 | |
270 // static | 344 // static |
271 bool PrerenderManager::ShouldRecordWindowedPPLT() { | 345 bool PrerenderManager::ShouldRecordWindowedPPLT() { |
272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
273 if (last_prefetch_seen_time_.is_null()) | 347 if (last_prefetch_seen_time_.is_null()) |
274 return false; | 348 return false; |
275 base::TimeDelta elapsed_time = | 349 base::TimeDelta elapsed_time = |
276 base::TimeTicks::Now() - last_prefetch_seen_time_; | 350 base::TimeTicks::Now() - last_prefetch_seen_time_; |
277 return elapsed_time <= base::TimeDelta::FromSeconds(kWindowedPPLTSeconds); | 351 return elapsed_time <= base::TimeDelta::FromSeconds(kWindowedPPLTSeconds); |
278 } | 352 } |
279 | 353 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
314 | 388 |
315 void PrerenderManager::MarkTabContentsAsNotPrerendered(TabContents* tc) { | 389 void PrerenderManager::MarkTabContentsAsNotPrerendered(TabContents* tc) { |
316 prerendered_tc_set_.erase(tc); | 390 prerendered_tc_set_.erase(tc); |
317 } | 391 } |
318 | 392 |
319 bool PrerenderManager::IsTabContentsPrerendered(TabContents* tc) const { | 393 bool PrerenderManager::IsTabContentsPrerendered(TabContents* tc) const { |
320 return prerendered_tc_set_.count(tc) > 0; | 394 return prerendered_tc_set_.count(tc) > 0; |
321 } | 395 } |
322 | 396 |
323 } // namespace prerender | 397 } // namespace prerender |
OLD | NEW |