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

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: rebase 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 // method has been canonicalized to upper case at this point so we can just
125 // compare them.
126 DCHECK_EQ(method, StringToUpperASCII(method));
127 for (size_t i = 0; i < arraysize(kValidHttpMethods); ++i) {
128 if (method.compare(kValidHttpMethods[i]) == 0)
129 return true;
130 }
131
132 return false;
133 }
134
114 struct PrerenderManager::PrerenderContentsData { 135 struct PrerenderManager::PrerenderContentsData {
115 PrerenderContents* contents_; 136 PrerenderContents* contents_;
116 base::Time start_time_; 137 base::Time start_time_;
117 PrerenderContentsData(PrerenderContents* contents, base::Time start_time) 138 PrerenderContentsData(PrerenderContents* contents, base::Time start_time)
118 : contents_(contents), 139 : contents_(contents),
119 start_time_(start_time) { 140 start_time_(start_time) {
120 } 141 }
121 }; 142 };
122 143
123 struct PrerenderManager::PendingContentsData { 144 struct PrerenderManager::PendingContentsData {
124 PendingContentsData(const GURL& url, 145 PendingContentsData(const GURL& url,
125 const GURL& referrer) 146 const GURL& referrer)
126 : url_(url), referrer_(referrer) { } 147 : url_(url), referrer_(referrer) { }
127 ~PendingContentsData() {} 148 ~PendingContentsData() {}
128 GURL url_; 149 GURL url_;
129 GURL referrer_; 150 GURL referrer_;
130 }; 151 };
131 152
132 void HandlePrefetchTagOnUIThread( 153 void HandlePrefetchTag(
133 const base::WeakPtr<PrerenderManager>& prerender_manager_weak_ptr, 154 const base::WeakPtr<PrerenderManager>& prerender_manager_weak_ptr,
134 const std::pair<int, int>& child_route_id_pair, 155 int render_process_id,
156 int render_view_id,
135 const GURL& url, 157 const GURL& url,
136 const GURL& referrer, 158 const GURL& referrer,
137 bool make_pending) { 159 bool make_pending) {
138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
139 PrerenderManager* prerender_manager = prerender_manager_weak_ptr.get(); 161 PrerenderManager* prerender_manager = prerender_manager_weak_ptr.get();
140 if (!prerender_manager || !prerender_manager->is_enabled()) 162 if (!prerender_manager || !prerender_manager->is_enabled())
141 return; 163 return;
142 prerender_manager->RecordPrefetchTagObserved(); 164 prerender_manager->RecordPrefetchTagObserved();
165
166 std::pair<int, int> child_route_id_pair = std::make_pair(render_process_id,
167 render_view_id);
143 // TODO(cbentzel): Should the decision to make pending be done on the 168 // TODO(cbentzel): Should the decision to make pending be done on the
144 // UI thread rather than the IO thread? The page may have 169 // UI thread rather than the IO thread? The page may have
145 // become activated at this point. 170 // become activated at this point.
146 if (make_pending) 171 if (make_pending)
147 prerender_manager->AddPendingPreload(child_route_id_pair, url, referrer); 172 prerender_manager->AddPendingPreload(child_route_id_pair, url, referrer);
148 else 173 else
149 prerender_manager->AddPreload(child_route_id_pair, url, referrer); 174 prerender_manager->AddPreload(child_route_id_pair, url, referrer);
150 } 175 }
151 176
177 void DestroyPreloadForRenderView(
178 const base::WeakPtr<PrerenderManager>& prerender_manager_weak_ptr,
179 int render_process_id,
180 int render_view_id,
181 FinalStatus final_status) {
182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
183 PrerenderManager* prerender_manager = prerender_manager_weak_ptr.get();
184 if (!prerender_manager)
185 return;
186
187 prerender_manager->DestroyPreloadForChildRouteIdPair(
188 std::make_pair(render_process_id, render_view_id),
189 final_status);
190 }
191
152 PrerenderManager::PrerenderManager(Profile* profile) 192 PrerenderManager::PrerenderManager(Profile* profile)
153 : rate_limit_enabled_(true), 193 : rate_limit_enabled_(true),
154 enabled_(true), 194 enabled_(true),
155 profile_(profile), 195 profile_(profile),
156 max_prerender_age_(base::TimeDelta::FromSeconds( 196 max_prerender_age_(base::TimeDelta::FromSeconds(
157 kDefaultMaxPrerenderAgeSeconds)), 197 kDefaultMaxPrerenderAgeSeconds)),
158 max_prerender_memory_mb_(kDefaultMaxPrerenderMemoryMB), 198 max_prerender_memory_mb_(kDefaultMaxPrerenderMemoryMB),
159 max_elements_(kDefaultMaxPrerenderElements), 199 max_elements_(kDefaultMaxPrerenderElements),
160 prerender_contents_factory_(PrerenderContents::CreateFactory()), 200 prerender_contents_factory_(PrerenderContents::CreateFactory()),
161 last_prerender_start_time_(GetCurrentTimeTicks() - 201 last_prerender_start_time_(GetCurrentTimeTicks() -
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 StartSchedulingPeriodicCleanups(); 300 StartSchedulingPeriodicCleanups();
261 return true; 301 return true;
262 } 302 }
263 303
264 void PrerenderManager::AddPendingPreload( 304 void PrerenderManager::AddPendingPreload(
265 const std::pair<int, int>& child_route_id_pair, 305 const std::pair<int, int>& child_route_id_pair,
266 const GURL& url, 306 const GURL& url,
267 const GURL& referrer) { 307 const GURL& referrer) {
268 DCHECK(CalledOnValidThread()); 308 DCHECK(CalledOnValidThread());
269 // Check if this is coming from a valid prerender RenderViewHost. 309 // Check if this is coming from a valid prerender RenderViewHost.
270 bool is_valid_prerender = false; 310 bool is_valid_prerender =
271 for (std::list<PrerenderContentsData>::iterator it = prerender_list_.begin(); 311 (FindPrerenderContentsForChildRouteIdPair(child_route_id_pair) !=
272 it != prerender_list_.end(); ++it) { 312 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 313
289 // If not, we could check to see if the RenderViewHost specified by the 314 // 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 315 // 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 316 // 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 317 // 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 318 // conservative and skip the prerender which will mean some prerender requests
294 // from prerendered pages will be missed if the user navigates quickly. 319 // from prerendered pages will be missed if the user navigates quickly.
295 if (!is_valid_prerender) { 320 if (!is_valid_prerender) {
296 RecordFinalStatus(FINAL_STATUS_PENDING_SKIPPED); 321 RecordFinalStatus(FINAL_STATUS_PENDING_SKIPPED);
297 return; 322 return;
298 } 323 }
299 324
300 PendingPrerenderList::iterator it = 325 PendingPrerenderList::iterator it =
301 pending_prerender_list_.find(child_route_id_pair); 326 pending_prerender_list_.find(child_route_id_pair);
302 if (it == pending_prerender_list_.end()) { 327 if (it == pending_prerender_list_.end()) {
303 PendingPrerenderList::value_type el = std::make_pair(child_route_id_pair, 328 PendingPrerenderList::value_type el = std::make_pair(child_route_id_pair,
304 std::vector<PendingContentsData>()); 329 std::vector<PendingContentsData>());
305 it = pending_prerender_list_.insert(el).first; 330 it = pending_prerender_list_.insert(el).first;
306 } 331 }
307 332
308 it->second.push_back(PendingContentsData(url, referrer)); 333 it->second.push_back(PendingContentsData(url, referrer));
309 } 334 }
310 335
336 std::list<PrerenderManager::PrerenderContentsData>::iterator
337 PrerenderManager::FindPrerenderContentsForChildRouteIdPair(
338 const std::pair<int, int>& child_route_id_pair) {
339 std::list<PrerenderContentsData>::iterator it = prerender_list_.begin();
340 for (; it != prerender_list_.end(); ++it) {
341 PrerenderContents* prerender_contents = it->contents_;
342
343 int child_id;
344 int route_id;
345 bool has_child_id = prerender_contents->GetChildId(&child_id);
346 bool has_route_id = has_child_id &&
347 prerender_contents->GetRouteId(&route_id);
348
349 if (has_child_id && has_route_id &&
350 child_id == child_route_id_pair.first &&
351 route_id == child_route_id_pair.second) {
352 break;
353 }
354 }
355 return it;
356 }
357
358 void PrerenderManager::DestroyPreloadForChildRouteIdPair(
359 const std::pair<int, int>& child_route_id_pair,
360 FinalStatus final_status) {
361 DCHECK(CalledOnValidThread());
362 std::list<PrerenderContentsData>::iterator it =
363 FindPrerenderContentsForChildRouteIdPair(child_route_id_pair);
364 if (it != prerender_list_.end()) {
365 PrerenderContents* prerender_contents = it->contents_;
366 prerender_contents->set_final_status(final_status);
367 RemovePendingPreload(prerender_contents);
368
369 delete prerender_contents;
370 prerender_list_.erase(it);
371 }
372 }
373
311 void PrerenderManager::DeleteOldEntries() { 374 void PrerenderManager::DeleteOldEntries() {
312 DCHECK(CalledOnValidThread()); 375 DCHECK(CalledOnValidThread());
313 while (!prerender_list_.empty()) { 376 while (!prerender_list_.empty()) {
314 PrerenderContentsData data = prerender_list_.front(); 377 PrerenderContentsData data = prerender_list_.front();
315 if (IsPrerenderElementFresh(data.start_time_)) 378 if (IsPrerenderElementFresh(data.start_time_))
316 return; 379 return;
317 prerender_list_.pop_front(); 380 prerender_list_.pop_front();
318 data.contents_->set_final_status(FINAL_STATUS_TIMED_OUT); 381 data.contents_->set_final_status(FINAL_STATUS_TIMED_OUT);
319 delete data.contents_; 382 delete data.contents_;
320 } 383 }
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after
770 return prerendered_tab_contents_set_.count(tab_contents) > 0; 833 return prerendered_tab_contents_set_.count(tab_contents) > 0;
771 } 834 }
772 835
773 bool PrerenderManager::WouldTabContentsBePrerendered( 836 bool PrerenderManager::WouldTabContentsBePrerendered(
774 TabContents* tab_contents) const { 837 TabContents* tab_contents) const {
775 DCHECK(CalledOnValidThread()); 838 DCHECK(CalledOnValidThread());
776 return would_be_prerendered_tab_contents_set_.count(tab_contents) > 0; 839 return would_be_prerendered_tab_contents_set_.count(tab_contents) > 0;
777 } 840 }
778 841
779 } // namespace prerender 842 } // namespace prerender
OLDNEW
« no previous file with comments | « chrome/browser/prerender/prerender_manager.h ('k') | chrome/test/data/prerender/prerender_xhr_delete.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698