Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Side by Side Diff: chrome/browser/prerender/prerender_manager.cc

Issue 6901128: Cancel prerenders that spawn post requests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Method name changes and more tests. Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 // Time window for which we will record windowed PLT's from the last 43 // Time window for which we will record windowed PLT's from the last
44 // observed link rel=prefetch tag. 44 // observed link rel=prefetch tag.
45 const int kWindowDurationSeconds = 30; 45 const int kWindowDurationSeconds = 30;
46 46
47 // Time interval at which periodic cleanups are performed. 47 // Time interval at which periodic cleanups are performed.
48 const int kPeriodicCleanupIntervalMs = 1000; 48 const int kPeriodicCleanupIntervalMs = 1000;
49 49
50 // Time interval before a new prerender is allowed. 50 // Time interval before a new prerender is allowed.
51 const int kMinTimeBetweenPrerendersMs = 500; 51 const int kMinTimeBetweenPrerendersMs = 500;
52 52
53 // Valid HTTP methods for prerendering.
54 const char* const kValidHttpMethods[] = {
55 "OPTIONS",
56 "GET",
57 "HEAD",
58 "TRACE",
59 };
60
53 } // namespace 61 } // namespace
54 62
55 // static 63 // static
56 int PrerenderManager::prerenders_per_session_count_ = 0; 64 int PrerenderManager::prerenders_per_session_count_ = 0;
57 65
58 // static 66 // static
59 PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = 67 PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ =
60 PRERENDER_MODE_ENABLED; 68 PRERENDER_MODE_ENABLED;
61 69
62 // static 70 // static
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 GURL new_url(string16(decoded_url.data(), decoded_url.length())); 112 GURL new_url(string16(decoded_url.data(), decoded_url.length()));
105 if (!new_url.is_empty() && new_url.is_valid()) { 113 if (!new_url.is_empty() && new_url.is_valid()) {
106 *alias_url = new_url; 114 *alias_url = new_url;
107 return true; 115 return true;
108 } 116 }
109 return false; 117 return false;
110 } 118 }
111 return false; 119 return false;
112 } 120 }
113 121
122 // static
123 bool PrerenderManager::IsValidHttpMethod(const std::string& method) {
124 for (size_t i = 0; i < arraysize(kValidHttpMethods); ++i) {
cbentzel 2011/05/02 20:27:38 DCHECK_EQ(method, StringToUpperASCII(method)) at
dominich 2011/05/02 21:04:55 Done.
125 // method has been canonicalized to upper case at this point so we can just
126 // compare.
127 if (method.compare(kValidHttpMethods[i]) == 0)
128 return true;
129 }
130
131 return false;
132 }
133
114 struct PrerenderManager::PrerenderContentsData { 134 struct PrerenderManager::PrerenderContentsData {
115 PrerenderContents* contents_; 135 PrerenderContents* contents_;
116 base::Time start_time_; 136 base::Time start_time_;
117 PrerenderContentsData(PrerenderContents* contents, base::Time start_time) 137 PrerenderContentsData(PrerenderContents* contents, base::Time start_time)
118 : contents_(contents), 138 : contents_(contents),
119 start_time_(start_time) { 139 start_time_(start_time) {
120 } 140 }
121 }; 141 };
122 142
123 struct PrerenderManager::PendingContentsData { 143 struct PrerenderManager::PendingContentsData {
124 PendingContentsData(const GURL& url, 144 PendingContentsData(const GURL& url,
125 const GURL& referrer) 145 const GURL& referrer)
126 : url_(url), referrer_(referrer) { } 146 : url_(url), referrer_(referrer) { }
127 ~PendingContentsData() {} 147 ~PendingContentsData() {}
128 GURL url_; 148 GURL url_;
129 GURL referrer_; 149 GURL referrer_;
130 }; 150 };
131 151
132 void HandlePrefetchTagOnUIThread( 152 void HandlePrefetchTag(
133 const base::WeakPtr<PrerenderManager>& prerender_manager_weak_ptr, 153 const base::WeakPtr<PrerenderManager>& prerender_manager_weak_ptr,
134 const std::pair<int, int>& child_route_id_pair, 154 int render_process_id,
155 int render_view_id,
135 const GURL& url, 156 const GURL& url,
136 const GURL& referrer, 157 const GURL& referrer,
137 bool make_pending) { 158 bool make_pending) {
138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
139 PrerenderManager* prerender_manager = prerender_manager_weak_ptr.get(); 160 PrerenderManager* prerender_manager = prerender_manager_weak_ptr.get();
140 if (!prerender_manager || !prerender_manager->is_enabled()) 161 if (!prerender_manager || !prerender_manager->is_enabled())
141 return; 162 return;
142 prerender_manager->RecordPrefetchTagObserved(); 163 prerender_manager->RecordPrefetchTagObserved();
164
165 std::pair<int, int> child_route_id_pair = std::make_pair(render_process_id,
166 render_view_id);
143 // TODO(cbentzel): Should the decision to make pending be done on the 167 // TODO(cbentzel): Should the decision to make pending be done on the
144 // UI thread rather than the IO thread? The page may have 168 // UI thread rather than the IO thread? The page may have
145 // become activated at this point. 169 // become activated at this point.
146 if (make_pending) 170 if (make_pending)
147 prerender_manager->AddPendingPreload(child_route_id_pair, url, referrer); 171 prerender_manager->AddPendingPreload(child_route_id_pair, url, referrer);
148 else 172 else
149 prerender_manager->AddPreload(child_route_id_pair, url, referrer); 173 prerender_manager->AddPreload(child_route_id_pair, url, referrer);
150 } 174 }
151 175
176 void DestroyPreloadForRenderView(
177 const base::WeakPtr<PrerenderManager>& prerender_manager_weak_ptr,
178 int render_process_id,
179 int render_view_id,
180 FinalStatus final_status) {
181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
182 PrerenderManager* prerender_manager = prerender_manager_weak_ptr.get();
183 if (!prerender_manager)
184 return;
185
186 prerender_manager->DestroyPreloadForChildRouteIdPair(
187 std::make_pair(render_process_id, render_view_id),
188 final_status);
189 }
190
152 PrerenderManager::PrerenderManager(Profile* profile) 191 PrerenderManager::PrerenderManager(Profile* profile)
153 : rate_limit_enabled_(true), 192 : rate_limit_enabled_(true),
154 enabled_(true), 193 enabled_(true),
155 profile_(profile), 194 profile_(profile),
156 max_prerender_age_(base::TimeDelta::FromSeconds( 195 max_prerender_age_(base::TimeDelta::FromSeconds(
157 kDefaultMaxPrerenderAgeSeconds)), 196 kDefaultMaxPrerenderAgeSeconds)),
158 max_prerender_memory_mb_(kDefaultMaxPrerenderMemoryMB), 197 max_prerender_memory_mb_(kDefaultMaxPrerenderMemoryMB),
159 max_elements_(kDefaultMaxPrerenderElements), 198 max_elements_(kDefaultMaxPrerenderElements),
160 prerender_contents_factory_(PrerenderContents::CreateFactory()), 199 prerender_contents_factory_(PrerenderContents::CreateFactory()),
161 last_prerender_start_time_(GetCurrentTimeTicks() - 200 last_prerender_start_time_(GetCurrentTimeTicks() -
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 StartSchedulingPeriodicCleanups(); 299 StartSchedulingPeriodicCleanups();
261 return true; 300 return true;
262 } 301 }
263 302
264 void PrerenderManager::AddPendingPreload( 303 void PrerenderManager::AddPendingPreload(
265 const std::pair<int, int>& child_route_id_pair, 304 const std::pair<int, int>& child_route_id_pair,
266 const GURL& url, 305 const GURL& url,
267 const GURL& referrer) { 306 const GURL& referrer) {
268 DCHECK(CalledOnValidThread()); 307 DCHECK(CalledOnValidThread());
269 // Check if this is coming from a valid prerender RenderViewHost. 308 // Check if this is coming from a valid prerender RenderViewHost.
270 bool is_valid_prerender = false; 309 bool is_valid_prerender =
271 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); 310 (FindPrerenderContentsForChildRouteIdPair(child_route_id_pair) !=
272 it != prerender_list_.end(); ++it) { 311 prerender_list_.end());
273 PrerenderContents* prerender_contents = it->contents_;
274
275 int child_id;
276 int route_id;
277 bool has_child_id = prerender_contents->GetChildId(&child_id);
278 bool has_route_id = has_child_id &&
279 prerender_contents->GetRouteId(&route_id);
280
281 if (has_child_id && has_route_id &&
282 child_id == child_route_id_pair.first &&
283 route_id == child_route_id_pair.second) {
284 is_valid_prerender = true;
285 break;
286 }
287 }
288 312
289 // If not, we could check to see if the RenderViewHost specified by the 313 // If not, we could check to see if the RenderViewHost specified by the
290 // child_route_id_pair exists and if so just start prerendering, as this 314 // child_route_id_pair exists and if so just start prerendering, as this
291 // suggests that the link was clicked, though this might prerender something 315 // suggests that the link was clicked, though this might prerender something
292 // that the user has already navigated away from. For now, we'll be 316 // that the user has already navigated away from. For now, we'll be
293 // conservative and skip the prerender which will mean some prerender requests 317 // conservative and skip the prerender which will mean some prerender requests
294 // from prerendered pages will be missed if the user navigates quickly. 318 // from prerendered pages will be missed if the user navigates quickly.
295 if (!is_valid_prerender) { 319 if (!is_valid_prerender) {
296 RecordFinalStatus(FINAL_STATUS_PENDING_SKIPPED); 320 RecordFinalStatus(FINAL_STATUS_PENDING_SKIPPED);
297 return; 321 return;
298 } 322 }
299 323
300 PendingPrerenderList::iterator it = 324 PendingPrerenderList::iterator it =
301 pending_prerender_list_.find(child_route_id_pair); 325 pending_prerender_list_.find(child_route_id_pair);
302 if (it == pending_prerender_list_.end()) { 326 if (it == pending_prerender_list_.end()) {
303 PendingPrerenderList::value_type el = std::make_pair(child_route_id_pair, 327 PendingPrerenderList::value_type el = std::make_pair(child_route_id_pair,
304 std::vector<PendingContentsData>()); 328 std::vector<PendingContentsData>());
305 it = pending_prerender_list_.insert(el).first; 329 it = pending_prerender_list_.insert(el).first;
306 } 330 }
307 331
308 it->second.push_back(PendingContentsData(url, referrer)); 332 it->second.push_back(PendingContentsData(url, referrer));
309 } 333 }
310 334
335 std::list<PrerenderManager::PrerenderContentsData>::iterator
336 PrerenderManager::FindPrerenderContentsForChildRouteIdPair(
337 const std::pair<int, int>& child_route_id_pair) {
338 std::list<PrerenderContentsData>::iterator it = prerender_list_.begin();
339 for (; it != prerender_list_.end(); ++it) {
340 PrerenderContents* prerender_contents = it->contents_;
341
342 int child_id;
343 int route_id;
344 bool has_child_id = prerender_contents->GetChildId(&child_id);
345 bool has_route_id = has_child_id &&
346 prerender_contents->GetRouteId(&route_id);
347
348 if (has_child_id && has_route_id &&
349 child_id == child_route_id_pair.first &&
350 route_id == child_route_id_pair.second) {
351 break;
352 }
353 }
354 return it;
355 }
356
357 void PrerenderManager::DestroyPreloadForChildRouteIdPair(
358 const std::pair<int, int>& child_route_id_pair,
359 FinalStatus final_status) {
360 DCHECK(CalledOnValidThread());
361 std::list<PrerenderContentsData>::iterator it =
362 FindPrerenderContentsForChildRouteIdPair(child_route_id_pair);
363 if (it != prerender_list_.end()) {
364 PrerenderContents* prerender_contents = it->contents_;
365 prerender_contents->set_final_status(final_status);
366 RemovePendingPreload(prerender_contents);
367
368 delete prerender_contents;
369 prerender_list_.erase(it);
370 }
371 }
372
311 void PrerenderManager::DeleteOldEntries() { 373 void PrerenderManager::DeleteOldEntries() {
312 DCHECK(CalledOnValidThread()); 374 DCHECK(CalledOnValidThread());
313 while (!prerender_list_.empty()) { 375 while (!prerender_list_.empty()) {
314 PrerenderContentsData data = prerender_list_.front(); 376 PrerenderContentsData data = prerender_list_.front();
315 if (IsPrerenderElementFresh(data.start_time_)) 377 if (IsPrerenderElementFresh(data.start_time_))
316 return; 378 return;
317 prerender_list_.pop_front(); 379 prerender_list_.pop_front();
318 data.contents_->set_final_status(FINAL_STATUS_TIMED_OUT); 380 data.contents_->set_final_status(FINAL_STATUS_TIMED_OUT);
319 delete data.contents_; 381 delete data.contents_;
320 } 382 }
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after
770 return prerendered_tab_contents_set_.count(tab_contents) > 0; 832 return prerendered_tab_contents_set_.count(tab_contents) > 0;
771 } 833 }
772 834
773 bool PrerenderManager::WouldTabContentsBePrerendered( 835 bool PrerenderManager::WouldTabContentsBePrerendered(
774 TabContents* tab_contents) const { 836 TabContents* tab_contents) const {
775 DCHECK(CalledOnValidThread()); 837 DCHECK(CalledOnValidThread());
776 return would_be_prerendered_tab_contents_set_.count(tab_contents) > 0; 838 return would_be_prerendered_tab_contents_set_.count(tab_contents) > 0;
777 } 839 }
778 840
779 } // namespace prerender 841 } // namespace prerender
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698