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

Unified 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, 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/prerender/prerender_link_manager.cc
diff --git a/chrome/browser/prerender/prerender_link_manager.cc b/chrome/browser/prerender/prerender_link_manager.cc
index 7726016c203f430ee05bb727dc56b28e7e8a7a64..8213dedd8701b4abb3250e952cc564b2297ef250 100644
--- a/chrome/browser/prerender/prerender_link_manager.cc
+++ b/chrome/browser/prerender/prerender_link_manager.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/prerender/prerender_link_manager.h"
+#include <functional>
#include <limits>
#include <set>
#include <utility>
@@ -43,10 +44,54 @@ void Send(int child_id, IPC::Message* raw_message) {
namespace prerender {
+// Helper class to implement PrerenderContents::Observer and watch prerenders
+// which launch other prerenders.
+class PrerenderLinkManager::PendingPrerenderManager
+ : public PrerenderContents::Observer {
+ public:
+ explicit PendingPrerenderManager(PrerenderLinkManager* link_manager)
+ : link_manager_(link_manager) {}
+
+ virtual ~PendingPrerenderManager() {
+ DCHECK(observed_launchers_.empty());
+ for (std::set<PrerenderContents*>::iterator i = observed_launchers_.begin();
+ i != observed_launchers_.end(); ++i) {
+ (*i)->RemoveObserver(this);
+ }
+ }
+
+ void ObserveLauncher(PrerenderContents* launcher) {
+ DCHECK_EQ(FINAL_STATUS_MAX, launcher->final_status());
+ if (observed_launchers_.find(launcher) != observed_launchers_.end())
+ return;
+ observed_launchers_.insert(launcher);
+ launcher->AddObserver(this);
+ }
+
+ virtual void OnPrerenderStart(PrerenderContents* launcher) OVERRIDE {}
+
+ virtual void OnPrerenderStop(PrerenderContents* launcher) OVERRIDE {
+ observed_launchers_.erase(launcher);
+ if (launcher->final_status() == FINAL_STATUS_USED) {
+ link_manager_->StartPendingPrerendersForLauncher(launcher);
+ } else {
+ link_manager_->CancelPendingPrerendersForLauncher(launcher);
+ }
+ }
+
+ private:
+ // A pointer to the parent PrerenderLinkManager.
+ PrerenderLinkManager* link_manager_;
+
+ // The set of PrerenderContentses being observed. Lifetimes are managed by
+ // OnPrerenderStop.
+ std::set<PrerenderContents*> observed_launchers_;
+};
+
PrerenderLinkManager::PrerenderLinkManager(PrerenderManager* manager)
: has_shutdown_(false),
- manager_(manager) {
-}
+ manager_(manager),
+ pending_prerender_manager_(new PendingPrerenderManager(this)) {}
PrerenderLinkManager::~PrerenderLinkManager() {
for (std::list<LinkPrerender>::iterator i = prerenders_.begin();
@@ -77,11 +122,27 @@ void PrerenderLinkManager::OnAddPrerender(int launcher_child_id,
if (rph && rph->IsGuest())
return;
+ // Check if the launcher is itself an unswapped prerender.
+ PrerenderContents* prerender_contents =
+ manager_->GetPrerenderContentsForRoute(launcher_child_id,
+ render_view_route_id);
+ if (prerender_contents &&
+ prerender_contents->final_status() != FINAL_STATUS_MAX) {
+ // The launcher is a prerender about to be destroyed asynchronously, but
+ // its AddLinkRelPrerender message raced with shutdown. Ignore it.
+ DCHECK_NE(FINAL_STATUS_USED, prerender_contents->final_status());
+ return;
+ }
+
LinkPrerender
prerender(launcher_child_id, prerender_id, url, referrer, size,
- render_view_route_id, manager_->GetCurrentTimeTicks());
+ render_view_route_id, manager_->GetCurrentTimeTicks(),
+ prerender_contents);
prerenders_.push_back(prerender);
- StartPrerenders();
+ if (prerender_contents)
+ pending_prerender_manager_->ObserveLauncher(prerender_contents);
+ else
+ StartPrerenders();
}
void PrerenderLinkManager::OnCancelPrerender(int child_id, int prerender_id) {
@@ -138,16 +199,19 @@ PrerenderLinkManager::LinkPrerender::LinkPrerender(
const content::Referrer& referrer,
const gfx::Size& size,
int render_view_route_id,
- TimeTicks creation_time) : launcher_child_id(launcher_child_id),
- prerender_id(prerender_id),
- url(url),
- referrer(referrer),
- size(size),
- render_view_route_id(render_view_route_id),
- creation_time(creation_time),
- handle(NULL),
- is_match_complete_replacement(false),
- has_been_abandoned(false) {
+ TimeTicks creation_time,
+ PrerenderContents* deferred_launcher)
+ : launcher_child_id(launcher_child_id),
+ prerender_id(prerender_id),
+ url(url),
+ referrer(referrer),
+ size(size),
+ render_view_route_id(render_view_route_id),
+ creation_time(creation_time),
+ deferred_launcher(deferred_launcher),
+ handle(NULL),
+ is_match_complete_replacement(false),
+ has_been_abandoned(false) {
}
PrerenderLinkManager::LinkPrerender::~LinkPrerender() {
@@ -184,6 +248,9 @@ void PrerenderLinkManager::StartPrerenders() {
// also per launcher.
for (std::list<LinkPrerender>::iterator i = prerenders_.begin();
i != prerenders_.end(); ++i) {
+ // Skip prerenders launched by a prerender.
+ if (i->deferred_launcher)
+ continue;
if (!i->handle) {
pending_prerenders.push_back(i);
} else {
@@ -320,6 +387,32 @@ void PrerenderLinkManager::CancelPrerender(LinkPrerender* prerender) {
NOTREACHED();
}
+void PrerenderLinkManager::StartPendingPrerendersForLauncher(
+ PrerenderContents* launcher) {
+ for (std::list<LinkPrerender>::iterator i = prerenders_.begin();
+ i != prerenders_.end(); ++i) {
+ if (i->deferred_launcher == launcher)
+ i->deferred_launcher = NULL;
+ }
+ StartPrerenders();
+}
+
+void PrerenderLinkManager::CancelPendingPrerendersForLauncher(
+ PrerenderContents* launcher) {
+ // Remove all pending prerenders for this launcher.
+ std::vector<std::list<LinkPrerender>::iterator> to_erase;
+ for (std::list<LinkPrerender>::iterator i = prerenders_.begin();
+ i != prerenders_.end(); ++i) {
+ if (i->deferred_launcher == launcher) {
+ DCHECK(!i->handle);
+ to_erase.push_back(i);
+ }
+ }
+ std::for_each(to_erase.begin(), to_erase.end(),
+ std::bind1st(std::mem_fun(&std::list<LinkPrerender>::erase),
+ &prerenders_));
+}
+
void PrerenderLinkManager::Shutdown() {
has_shutdown_ = true;
}
« 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