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

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

Issue 146983002: Move pending prerender logic into PrerenderLinkManager. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix prerender_unittests Created 6 years, 11 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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_link_manager.h" 5 #include "chrome/browser/prerender/prerender_link_manager.h"
6 6
7 #include <limits> 7 #include <limits>
8 #include <set> 8 #include <set>
9 #include <utility> 9 #include <utility>
10 10
(...skipping 25 matching lines...) Expand all
36 RenderProcessHost* render_process_host = RenderProcessHost::FromID(child_id); 36 RenderProcessHost* render_process_host = RenderProcessHost::FromID(child_id);
37 if (!render_process_host) 37 if (!render_process_host)
38 return; 38 return;
39 render_process_host->Send(own_message.release()); 39 render_process_host->Send(own_message.release());
40 } 40 }
41 41
42 } // namespace 42 } // namespace
43 43
44 namespace prerender { 44 namespace prerender {
45 45
46 // Helper class to implement PrerenderContents::Observer and watch prerenders
47 // which launch other prerenders.
48 class PrerenderLinkManager::PendingPrerenderManager
49 : public PrerenderContents::Observer {
50 public:
51 explicit PendingPrerenderManager(PrerenderLinkManager* link_manager)
52 : link_manager_(link_manager) {
53 }
gavinp 2014/01/30 19:58:49 This can move up a line too.
davidben 2014/01/30 21:01:51 Done.
54
55 virtual ~PendingPrerenderManager() {
56 DCHECK(observed_launchers_.empty());
57 for (std::set<PrerenderContents*>::iterator i = observed_launchers_.begin();
58 i != observed_launchers_.end(); ++i) {
59 (*i)->RemoveObserver(this);
60 }
61 }
62
63 void ObserveLauncher(PrerenderContents* launcher) {
64 DCHECK_EQ(FINAL_STATUS_MAX, launcher->final_status());
65 if (observed_launchers_.find(launcher) != observed_launchers_.end())
66 return;
67 observed_launchers_.insert(launcher);
68 launcher->AddObserver(this);
69 }
70
71 virtual void OnPrerenderStart(PrerenderContents* launcher) OVERRIDE {
72 }
gavinp 2014/01/30 19:58:49 Nit: Move this to the previous line. Also, add a
davidben 2014/01/30 21:01:51 Done.
73 virtual void OnPrerenderStop(PrerenderContents* launcher) OVERRIDE {
74 observed_launchers_.erase(launcher);
75 if (launcher->final_status() == FINAL_STATUS_USED) {
76 link_manager_->StartPendingPrerendersForLauncher(launcher);
77 } else {
78 link_manager_->CancelPendingPrerendersForLauncher(launcher);
79 }
80 }
81
82 private:
83 // A pointer to the parent PrerenderLinkManager.
84 PrerenderLinkManager* link_manager_;
85
86 // The set of PrerenderContentses being observed. Lifetimes are managed by
87 // OnPrerenderStop.
88 std::set<PrerenderContents*> observed_launchers_;
89 };
90
46 PrerenderLinkManager::PrerenderLinkManager(PrerenderManager* manager) 91 PrerenderLinkManager::PrerenderLinkManager(PrerenderManager* manager)
47 : has_shutdown_(false), 92 : has_shutdown_(false),
48 manager_(manager) { 93 manager_(manager),
94 pending_prerender_manager_(new PendingPrerenderManager(this)) {
gavinp 2014/01/30 19:58:49 Ditto.
davidben 2014/01/30 21:01:51 Done.
49 } 95 }
50 96
51 PrerenderLinkManager::~PrerenderLinkManager() { 97 PrerenderLinkManager::~PrerenderLinkManager() {
52 for (std::list<LinkPrerender>::iterator i = prerenders_.begin(); 98 for (std::list<LinkPrerender>::iterator i = prerenders_.begin();
53 i != prerenders_.end(); ++i) { 99 i != prerenders_.end(); ++i) {
54 if (i->handle) { 100 if (i->handle) {
55 DCHECK(!i->handle->IsPrerendering()) 101 DCHECK(!i->handle->IsPrerendering())
56 << "All running prerenders should stop at the same time as the " 102 << "All running prerenders should stop at the same time as the "
57 << "PrerenderManager."; 103 << "PrerenderManager.";
58 delete i->handle; 104 delete i->handle;
(...skipping 11 matching lines...) Expand all
70 DCHECK_EQ(static_cast<LinkPrerender*>(NULL), 116 DCHECK_EQ(static_cast<LinkPrerender*>(NULL),
71 FindByLauncherChildIdAndPrerenderId(launcher_child_id, 117 FindByLauncherChildIdAndPrerenderId(launcher_child_id,
72 prerender_id)); 118 prerender_id));
73 content::RenderProcessHost* rph = 119 content::RenderProcessHost* rph =
74 content::RenderProcessHost::FromID(launcher_child_id); 120 content::RenderProcessHost::FromID(launcher_child_id);
75 // Guests inside <webview> do not support cross-process navigation and so we 121 // Guests inside <webview> do not support cross-process navigation and so we
76 // do not allow guests to prerender content. 122 // do not allow guests to prerender content.
77 if (rph && rph->IsGuest()) 123 if (rph && rph->IsGuest())
78 return; 124 return;
79 125
126 // Check if the launcher is itself an unswapped prerender.
127 PrerenderContents* prerender_contents =
128 manager_->GetPrerenderContentsForRoute(launcher_child_id,
129 render_view_route_id);
130 if (prerender_contents &&
131 prerender_contents->final_status() != FINAL_STATUS_MAX) {
132 // The launcher is a prerender about to be destroyed asynchronously, but
133 // its AddLinkRelPrerender message raced with shutdown. Ignore it.
134 DCHECK_NE(FINAL_STATUS_USED, prerender_contents->final_status());
135 return;
136 }
137
80 LinkPrerender 138 LinkPrerender
81 prerender(launcher_child_id, prerender_id, url, referrer, size, 139 prerender(launcher_child_id, prerender_id, url, referrer, size,
82 render_view_route_id, manager_->GetCurrentTimeTicks()); 140 render_view_route_id, manager_->GetCurrentTimeTicks(),
141 prerender_contents);
83 prerenders_.push_back(prerender); 142 prerenders_.push_back(prerender);
84 StartPrerenders(); 143 if (prerender_contents) {
gavinp 2014/01/30 19:58:49 Nit: the {} on this are not necessary. I wouldn't
davidben 2014/01/30 21:01:51 Done.
144 pending_prerender_manager_->ObserveLauncher(prerender_contents);
145 } else {
146 StartPrerenders();
147 }
85 } 148 }
86 149
87 void PrerenderLinkManager::OnCancelPrerender(int child_id, int prerender_id) { 150 void PrerenderLinkManager::OnCancelPrerender(int child_id, int prerender_id) {
88 LinkPrerender* prerender = FindByLauncherChildIdAndPrerenderId(child_id, 151 LinkPrerender* prerender = FindByLauncherChildIdAndPrerenderId(child_id,
89 prerender_id); 152 prerender_id);
90 if (!prerender) 153 if (!prerender)
91 return; 154 return;
92 155
93 CancelPrerender(prerender); 156 CancelPrerender(prerender);
94 StartPrerenders(); 157 StartPrerenders();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 } 194 }
132 } 195 }
133 196
134 PrerenderLinkManager::LinkPrerender::LinkPrerender( 197 PrerenderLinkManager::LinkPrerender::LinkPrerender(
135 int launcher_child_id, 198 int launcher_child_id,
136 int prerender_id, 199 int prerender_id,
137 const GURL& url, 200 const GURL& url,
138 const content::Referrer& referrer, 201 const content::Referrer& referrer,
139 const gfx::Size& size, 202 const gfx::Size& size,
140 int render_view_route_id, 203 int render_view_route_id,
141 TimeTicks creation_time) : launcher_child_id(launcher_child_id), 204 TimeTicks creation_time,
142 prerender_id(prerender_id), 205 PrerenderContents* deferred_launcher)
143 url(url), 206 : launcher_child_id(launcher_child_id),
144 referrer(referrer), 207 prerender_id(prerender_id),
145 size(size), 208 url(url),
146 render_view_route_id(render_view_route_id), 209 referrer(referrer),
147 creation_time(creation_time), 210 size(size),
148 handle(NULL), 211 render_view_route_id(render_view_route_id),
149 is_match_complete_replacement(false), 212 creation_time(creation_time),
150 has_been_abandoned(false) { 213 deferred_launcher(deferred_launcher),
214 handle(NULL),
215 is_match_complete_replacement(false),
216 has_been_abandoned(false) {
151 } 217 }
152 218
153 PrerenderLinkManager::LinkPrerender::~LinkPrerender() { 219 PrerenderLinkManager::LinkPrerender::~LinkPrerender() {
154 DCHECK_EQ(static_cast<PrerenderHandle*>(NULL), handle) 220 DCHECK_EQ(static_cast<PrerenderHandle*>(NULL), handle)
155 << "The PrerenderHandle should be destroyed before its Prerender."; 221 << "The PrerenderHandle should be destroyed before its Prerender.";
156 } 222 }
157 223
158 bool PrerenderLinkManager::IsEmpty() const { 224 bool PrerenderLinkManager::IsEmpty() const {
159 return prerenders_.empty(); 225 return prerenders_.empty();
160 } 226 }
(...skipping 16 matching lines...) Expand all
177 std::list<LinkPrerender*> abandoned_prerenders; 243 std::list<LinkPrerender*> abandoned_prerenders;
178 std::list<std::list<LinkPrerender>::iterator> pending_prerenders; 244 std::list<std::list<LinkPrerender>::iterator> pending_prerenders;
179 std::multiset<std::pair<int, int> > 245 std::multiset<std::pair<int, int> >
180 running_launcher_and_render_view_routes; 246 running_launcher_and_render_view_routes;
181 247
182 // Scan the list, counting how many prerenders have handles (and so were added 248 // Scan the list, counting how many prerenders have handles (and so were added
183 // to the PrerenderManager). The count is done for the system as a whole, and 249 // to the PrerenderManager). The count is done for the system as a whole, and
184 // also per launcher. 250 // also per launcher.
185 for (std::list<LinkPrerender>::iterator i = prerenders_.begin(); 251 for (std::list<LinkPrerender>::iterator i = prerenders_.begin();
186 i != prerenders_.end(); ++i) { 252 i != prerenders_.end(); ++i) {
253 // Skip prerenders launched by a prerender.
254 if (i->deferred_launcher)
255 continue;
187 if (!i->handle) { 256 if (!i->handle) {
188 pending_prerenders.push_back(i); 257 pending_prerenders.push_back(i);
189 } else { 258 } else {
190 ++total_started_prerender_count; 259 ++total_started_prerender_count;
191 if (i->has_been_abandoned) { 260 if (i->has_been_abandoned) {
192 abandoned_prerenders.push_back(&(*i)); 261 abandoned_prerenders.push_back(&(*i));
193 } else { 262 } else {
194 // We do not count abandoned prerenders towards their launcher, since it 263 // We do not count abandoned prerenders towards their launcher, since it
195 // has already navigated on to another page. 264 // has already navigated on to another page.
196 std::pair<int, int> launcher_and_render_view_route( 265 std::pair<int, int> launcher_and_render_view_route(
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 i->handle = NULL; 382 i->handle = NULL;
314 prerenders_.erase(i); 383 prerenders_.erase(i);
315 if (own_handle) 384 if (own_handle)
316 own_handle->OnCancel(); 385 own_handle->OnCancel();
317 return; 386 return;
318 } 387 }
319 } 388 }
320 NOTREACHED(); 389 NOTREACHED();
321 } 390 }
322 391
392 void PrerenderLinkManager::StartPendingPrerendersForLauncher(
393 PrerenderContents* launcher) {
394 for (std::list<LinkPrerender>::iterator i = prerenders_.begin();
395 i != prerenders_.end(); ++i) {
396 if (i->deferred_launcher == launcher)
397 i->deferred_launcher = NULL;
398 }
399 StartPrerenders();
400 }
401
402 void PrerenderLinkManager::CancelPendingPrerendersForLauncher(
403 PrerenderContents* launcher) {
404 // Remove all pending prerenders for this launcher.
405 std::list<LinkPrerender>::iterator iter = prerenders_.begin();
406 while (iter != prerenders_.end()) {
407 // Increment iterator first so it isn't invalidated.
408 std::list<LinkPrerender>::iterator current = iter++;
gavinp 2014/01/30 19:58:49 This looks correct. However, just for absolute sa
davidben 2014/01/30 21:01:51 Done.
409 if (current->deferred_launcher == launcher) {
410 DCHECK(!current->handle);
411 prerenders_.erase(current);
412 }
413 }
414 }
415
323 void PrerenderLinkManager::Shutdown() { 416 void PrerenderLinkManager::Shutdown() {
324 has_shutdown_ = true; 417 has_shutdown_ = true;
325 } 418 }
326 419
327 // In practice, this is always called from either 420 // In practice, this is always called from either
328 // PrerenderLinkManager::OnAddPrerender in the regular case, or in the pending 421 // PrerenderLinkManager::OnAddPrerender in the regular case, or in the pending
329 // prerender case, from PrerenderHandle::AdoptPrerenderDataFrom. 422 // prerender case, from PrerenderHandle::AdoptPrerenderDataFrom.
330 void PrerenderLinkManager::OnPrerenderStart( 423 void PrerenderLinkManager::OnPrerenderStart(
331 PrerenderHandle* prerender_handle) { 424 PrerenderHandle* prerender_handle) {
332 LinkPrerender* prerender = FindByPrerenderHandle(prerender_handle); 425 LinkPrerender* prerender = FindByPrerenderHandle(prerender_handle);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 DCHECK(!prerender->is_match_complete_replacement); 464 DCHECK(!prerender->is_match_complete_replacement);
372 prerender->is_match_complete_replacement = true; 465 prerender->is_match_complete_replacement = true;
373 Send(prerender->launcher_child_id, 466 Send(prerender->launcher_child_id,
374 new PrerenderMsg_OnPrerenderStop(prerender->prerender_id)); 467 new PrerenderMsg_OnPrerenderStop(prerender->prerender_id));
375 // Do not call RemovePrerender here. The replacement needs to stay connected 468 // Do not call RemovePrerender here. The replacement needs to stay connected
376 // to the HTMLLinkElement in the renderer so it notices renderer-triggered 469 // to the HTMLLinkElement in the renderer so it notices renderer-triggered
377 // cancelations. 470 // cancelations.
378 } 471 }
379 472
380 } // namespace prerender 473 } // namespace prerender
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698