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

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: Rebase Created 6 years, 10 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 <functional>
7 #include <limits> 8 #include <limits>
8 #include <set> 9 #include <set>
9 #include <utility> 10 #include <utility>
10 11
11 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
12 #include "chrome/browser/prerender/prerender_contents.h" 13 #include "chrome/browser/prerender/prerender_contents.h"
13 #include "chrome/browser/prerender/prerender_handle.h" 14 #include "chrome/browser/prerender/prerender_handle.h"
14 #include "chrome/browser/prerender/prerender_manager.h" 15 #include "chrome/browser/prerender/prerender_manager.h"
15 #include "chrome/browser/prerender/prerender_manager_factory.h" 16 #include "chrome/browser/prerender/prerender_manager_factory.h"
16 #include "chrome/browser/profiles/profile.h" 17 #include "chrome/browser/profiles/profile.h"
(...skipping 19 matching lines...) Expand all
36 RenderProcessHost* render_process_host = RenderProcessHost::FromID(child_id); 37 RenderProcessHost* render_process_host = RenderProcessHost::FromID(child_id);
37 if (!render_process_host) 38 if (!render_process_host)
38 return; 39 return;
39 render_process_host->Send(own_message.release()); 40 render_process_host->Send(own_message.release());
40 } 41 }
41 42
42 } // namespace 43 } // namespace
43 44
44 namespace prerender { 45 namespace prerender {
45 46
47 // Helper class to implement PrerenderContents::Observer and watch prerenders
48 // which launch other prerenders.
49 class PrerenderLinkManager::PendingPrerenderManager
50 : public PrerenderContents::Observer {
51 public:
52 explicit PendingPrerenderManager(PrerenderLinkManager* link_manager)
53 : link_manager_(link_manager) {}
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
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),
49 } 94 pending_prerender_manager_(new PendingPrerenderManager(this)) {}
50 95
51 PrerenderLinkManager::~PrerenderLinkManager() { 96 PrerenderLinkManager::~PrerenderLinkManager() {
52 for (std::list<LinkPrerender>::iterator i = prerenders_.begin(); 97 for (std::list<LinkPrerender>::iterator i = prerenders_.begin();
53 i != prerenders_.end(); ++i) { 98 i != prerenders_.end(); ++i) {
54 if (i->handle) { 99 if (i->handle) {
55 DCHECK(!i->handle->IsPrerendering()) 100 DCHECK(!i->handle->IsPrerendering())
56 << "All running prerenders should stop at the same time as the " 101 << "All running prerenders should stop at the same time as the "
57 << "PrerenderManager."; 102 << "PrerenderManager.";
58 delete i->handle; 103 delete i->handle;
59 i->handle = 0; 104 i->handle = 0;
(...skipping 10 matching lines...) Expand all
70 DCHECK_EQ(static_cast<LinkPrerender*>(NULL), 115 DCHECK_EQ(static_cast<LinkPrerender*>(NULL),
71 FindByLauncherChildIdAndPrerenderId(launcher_child_id, 116 FindByLauncherChildIdAndPrerenderId(launcher_child_id,
72 prerender_id)); 117 prerender_id));
73 content::RenderProcessHost* rph = 118 content::RenderProcessHost* rph =
74 content::RenderProcessHost::FromID(launcher_child_id); 119 content::RenderProcessHost::FromID(launcher_child_id);
75 // Guests inside <webview> do not support cross-process navigation and so we 120 // Guests inside <webview> do not support cross-process navigation and so we
76 // do not allow guests to prerender content. 121 // do not allow guests to prerender content.
77 if (rph && rph->IsGuest()) 122 if (rph && rph->IsGuest())
78 return; 123 return;
79 124
125 // Check if the launcher is itself an unswapped prerender.
126 PrerenderContents* prerender_contents =
127 manager_->GetPrerenderContentsForRoute(launcher_child_id,
128 render_view_route_id);
129 if (prerender_contents &&
130 prerender_contents->final_status() != FINAL_STATUS_MAX) {
131 // The launcher is a prerender about to be destroyed asynchronously, but
132 // its AddLinkRelPrerender message raced with shutdown. Ignore it.
133 DCHECK_NE(FINAL_STATUS_USED, prerender_contents->final_status());
134 return;
135 }
136
80 LinkPrerender 137 LinkPrerender
81 prerender(launcher_child_id, prerender_id, url, referrer, size, 138 prerender(launcher_child_id, prerender_id, url, referrer, size,
82 render_view_route_id, manager_->GetCurrentTimeTicks()); 139 render_view_route_id, manager_->GetCurrentTimeTicks(),
140 prerender_contents);
83 prerenders_.push_back(prerender); 141 prerenders_.push_back(prerender);
84 StartPrerenders(); 142 if (prerender_contents)
143 pending_prerender_manager_->ObserveLauncher(prerender_contents);
144 else
145 StartPrerenders();
85 } 146 }
86 147
87 void PrerenderLinkManager::OnCancelPrerender(int child_id, int prerender_id) { 148 void PrerenderLinkManager::OnCancelPrerender(int child_id, int prerender_id) {
88 LinkPrerender* prerender = FindByLauncherChildIdAndPrerenderId(child_id, 149 LinkPrerender* prerender = FindByLauncherChildIdAndPrerenderId(child_id,
89 prerender_id); 150 prerender_id);
90 if (!prerender) 151 if (!prerender)
91 return; 152 return;
92 153
93 CancelPrerender(prerender); 154 CancelPrerender(prerender);
94 StartPrerenders(); 155 StartPrerenders();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 } 192 }
132 } 193 }
133 194
134 PrerenderLinkManager::LinkPrerender::LinkPrerender( 195 PrerenderLinkManager::LinkPrerender::LinkPrerender(
135 int launcher_child_id, 196 int launcher_child_id,
136 int prerender_id, 197 int prerender_id,
137 const GURL& url, 198 const GURL& url,
138 const content::Referrer& referrer, 199 const content::Referrer& referrer,
139 const gfx::Size& size, 200 const gfx::Size& size,
140 int render_view_route_id, 201 int render_view_route_id,
141 TimeTicks creation_time) : launcher_child_id(launcher_child_id), 202 TimeTicks creation_time,
142 prerender_id(prerender_id), 203 PrerenderContents* deferred_launcher)
143 url(url), 204 : launcher_child_id(launcher_child_id),
144 referrer(referrer), 205 prerender_id(prerender_id),
145 size(size), 206 url(url),
146 render_view_route_id(render_view_route_id), 207 referrer(referrer),
147 creation_time(creation_time), 208 size(size),
148 handle(NULL), 209 render_view_route_id(render_view_route_id),
149 is_match_complete_replacement(false), 210 creation_time(creation_time),
150 has_been_abandoned(false) { 211 deferred_launcher(deferred_launcher),
212 handle(NULL),
213 is_match_complete_replacement(false),
214 has_been_abandoned(false) {
151 } 215 }
152 216
153 PrerenderLinkManager::LinkPrerender::~LinkPrerender() { 217 PrerenderLinkManager::LinkPrerender::~LinkPrerender() {
154 DCHECK_EQ(static_cast<PrerenderHandle*>(NULL), handle) 218 DCHECK_EQ(static_cast<PrerenderHandle*>(NULL), handle)
155 << "The PrerenderHandle should be destroyed before its Prerender."; 219 << "The PrerenderHandle should be destroyed before its Prerender.";
156 } 220 }
157 221
158 bool PrerenderLinkManager::IsEmpty() const { 222 bool PrerenderLinkManager::IsEmpty() const {
159 return prerenders_.empty(); 223 return prerenders_.empty();
160 } 224 }
(...skipping 16 matching lines...) Expand all
177 std::list<LinkPrerender*> abandoned_prerenders; 241 std::list<LinkPrerender*> abandoned_prerenders;
178 std::list<std::list<LinkPrerender>::iterator> pending_prerenders; 242 std::list<std::list<LinkPrerender>::iterator> pending_prerenders;
179 std::multiset<std::pair<int, int> > 243 std::multiset<std::pair<int, int> >
180 running_launcher_and_render_view_routes; 244 running_launcher_and_render_view_routes;
181 245
182 // Scan the list, counting how many prerenders have handles (and so were added 246 // 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 247 // to the PrerenderManager). The count is done for the system as a whole, and
184 // also per launcher. 248 // also per launcher.
185 for (std::list<LinkPrerender>::iterator i = prerenders_.begin(); 249 for (std::list<LinkPrerender>::iterator i = prerenders_.begin();
186 i != prerenders_.end(); ++i) { 250 i != prerenders_.end(); ++i) {
251 // Skip prerenders launched by a prerender.
252 if (i->deferred_launcher)
253 continue;
187 if (!i->handle) { 254 if (!i->handle) {
188 pending_prerenders.push_back(i); 255 pending_prerenders.push_back(i);
189 } else { 256 } else {
190 ++total_started_prerender_count; 257 ++total_started_prerender_count;
191 if (i->has_been_abandoned) { 258 if (i->has_been_abandoned) {
192 abandoned_prerenders.push_back(&(*i)); 259 abandoned_prerenders.push_back(&(*i));
193 } else { 260 } else {
194 // We do not count abandoned prerenders towards their launcher, since it 261 // We do not count abandoned prerenders towards their launcher, since it
195 // has already navigated on to another page. 262 // has already navigated on to another page.
196 std::pair<int, int> launcher_and_render_view_route( 263 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; 380 i->handle = NULL;
314 prerenders_.erase(i); 381 prerenders_.erase(i);
315 if (own_handle) 382 if (own_handle)
316 own_handle->OnCancel(); 383 own_handle->OnCancel();
317 return; 384 return;
318 } 385 }
319 } 386 }
320 NOTREACHED(); 387 NOTREACHED();
321 } 388 }
322 389
390 void PrerenderLinkManager::StartPendingPrerendersForLauncher(
391 PrerenderContents* launcher) {
392 for (std::list<LinkPrerender>::iterator i = prerenders_.begin();
393 i != prerenders_.end(); ++i) {
394 if (i->deferred_launcher == launcher)
395 i->deferred_launcher = NULL;
396 }
397 StartPrerenders();
398 }
399
400 void PrerenderLinkManager::CancelPendingPrerendersForLauncher(
401 PrerenderContents* launcher) {
402 // Remove all pending prerenders for this launcher.
403 std::vector<std::list<LinkPrerender>::iterator> to_erase;
404 for (std::list<LinkPrerender>::iterator i = prerenders_.begin();
405 i != prerenders_.end(); ++i) {
406 if (i->deferred_launcher == launcher) {
407 DCHECK(!i->handle);
408 to_erase.push_back(i);
409 }
410 }
411 std::for_each(to_erase.begin(), to_erase.end(),
412 std::bind1st(std::mem_fun(&std::list<LinkPrerender>::erase),
413 &prerenders_));
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
« no previous file with comments | « chrome/browser/prerender/prerender_link_manager.h ('k') | chrome/browser/prerender/prerender_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698