summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-20 15:05:08 +0000
committermmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-20 15:05:08 +0000
commit28a05f3af8c3031d23b55630d811fc5c18505a3c (patch)
treecb4691e3b846236408c45695b72051412f68dbf3
parent2937a8c72bfd28188ccd0b3f3b54bc3303b5f537 (diff)
downloadchromium_src-28a05f3af8c3031d23b55630d811fc5c18505a3c.zip
chromium_src-28a05f3af8c3031d23b55630d811fc5c18505a3c.tar.gz
chromium_src-28a05f3af8c3031d23b55630d811fc5c18505a3c.tar.bz2
Safely cancel prerenders on threads other than the UI thread.
Previously, prerendering was cancelled on the IO thread by not doing something, and then passing a task to the UI thread to abort the prerender. This resulted in a race which could result in swapping in the prerender before the task was executed. This fixes that. BUG=83062 TEST=PrerenderStatusManagerTests, PrerenderBrowserTests Review URL: http://codereview.chromium.org/7038012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@86082 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/prerender/prerender_contents.cc104
-rw-r--r--chrome/browser/prerender/prerender_contents.h6
-rw-r--r--chrome/browser/prerender/prerender_manager.cc35
-rw-r--r--chrome/browser/prerender/prerender_manager.h11
-rw-r--r--chrome/browser/prerender/prerender_tracker.cc202
-rw-r--r--chrome/browser/prerender/prerender_tracker.h136
-rw-r--r--chrome/browser/prerender/prerender_tracker_unittest.cc294
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--content/browser/DEPS1
-rw-r--r--content/browser/renderer_host/resource_dispatcher_host.cc42
-rw-r--r--content/browser/renderer_host/resource_dispatcher_host.h11
12 files changed, 719 insertions, 126 deletions
diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc
index 0da2a6f..343c61a 100644
--- a/chrome/browser/prerender/prerender_contents.cc
+++ b/chrome/browser/prerender/prerender_contents.cc
@@ -16,6 +16,7 @@
#include "chrome/browser/prerender/prerender_final_status.h"
#include "chrome/browser/prerender/prerender_manager.h"
#include "chrome/browser/prerender/prerender_render_widget_host_view.h"
+#include "chrome/browser/prerender/prerender_tracker.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/renderer_preferences_util.h"
#include "chrome/browser/ui/login/login_prompt.h"
@@ -61,18 +62,6 @@ struct PrerenderUrlPredicate {
GURL url_;
};
-void AddChildRoutePair(ResourceDispatcherHost* resource_dispatcher_host,
- int child_id, int route_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- resource_dispatcher_host->AddPrerenderChildRoutePair(child_id, route_id);
-}
-
-void RemoveChildRoutePair(ResourceDispatcherHost* resource_dispatcher_host,
- int child_id, int route_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- resource_dispatcher_host->RemovePrerenderChildRoutePair(child_id, route_id);
-}
-
} // end namespace
class PrerenderContentsFactoryImpl : public PrerenderContents::Factory {
@@ -146,7 +135,9 @@ PrerenderContents::PrerenderContents(PrerenderManager* prerender_manager,
ALLOW_THIS_IN_INITIALIZER_LIST(tab_contents_observer_registrar_(this)),
has_stopped_loading_(false),
final_status_(FINAL_STATUS_MAX),
- prerendering_has_started_(false) {
+ prerendering_has_started_(false),
+ child_id_(-1),
+ route_id_(-1) {
DCHECK(prerender_manager != NULL);
}
@@ -187,18 +178,14 @@ void PrerenderContents::StartPrerenderingOld(
new PrerenderRenderWidgetHostView(render_view_host_, this);
view->Init(source_render_view_host->view());
- // Register this with the ResourceDispatcherHost as a prerender
- // RenderViewHost. This must be done before the Navigate message to catch all
- // resource requests, but as it is on the same thread as the Navigate message
- // (IO) there is no race condition.
- int process_id = render_view_host_->process()->id();
- int view_id = render_view_host_->routing_id();
+ child_id_ = render_view_host_->process()->id();
+ route_id_ = render_view_host_->routing_id();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- NewRunnableFunction(&AddChildRoutePair,
- g_browser_process->resource_dispatcher_host(),
- process_id, view_id));
+ // Register this with the PrerenderTracker as a prerendering RenderViewHost.
+ // This must be done before the Navigate message to catch all resource
+ // requests.
+ PrerenderTracker::GetInstance()->OnPrerenderingStarted(child_id_, route_id_,
+ prerender_manager_);
// Close ourselves when the application is shutting down.
notification_registrar_.Add(this, NotificationType::APP_TERMINATING,
@@ -292,20 +279,15 @@ void PrerenderContents::StartPrerendering(
render_view_host_observer_.reset(
new PrerenderRenderViewHostObserver(this, render_view_host_mutable()));
- int process_id;
- int view_id;
- CHECK(GetChildId(&process_id));
- CHECK(GetRouteId(&view_id));
+ child_id_ = render_view_host()->process()->id();
+ route_id_ = render_view_host()->routing_id();
// Register this with the ResourceDispatcherHost as a prerender
// RenderViewHost. This must be done before the Navigate message to catch all
// resource requests, but as it is on the same thread as the Navigate message
// (IO) there is no race condition.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- NewRunnableFunction(&AddChildRoutePair,
- g_browser_process->resource_dispatcher_host(),
- process_id, view_id));
+ PrerenderTracker::GetInstance()->OnPrerenderingStarted(child_id_, route_id_,
+ prerender_manager_);
// Close ourselves when the application is shutting down.
notification_registrar_.Add(this, NotificationType::APP_TERMINATING,
@@ -353,22 +335,16 @@ void PrerenderContents::StartPrerendering(
bool PrerenderContents::GetChildId(int* child_id) const {
CHECK(child_id);
- const RenderViewHost* prerender_render_view_host = render_view_host();
- if (prerender_render_view_host) {
- *child_id = prerender_render_view_host->process()->id();
- return true;
- }
- return false;
+ DCHECK_GE(child_id_, -1);
+ *child_id = child_id_;
+ return child_id_ != -1;
}
bool PrerenderContents::GetRouteId(int* route_id) const {
CHECK(route_id);
- const RenderViewHost* prerender_render_view_host = render_view_host();
- if (prerender_render_view_host) {
- *route_id = prerender_render_view_host->routing_id();
- return true;
- }
- return false;
+ DCHECK_GE(route_id_, -1);
+ *route_id = route_id_;
+ return route_id_ != -1;
}
void PrerenderContents::set_final_status(FinalStatus final_status) {
@@ -396,21 +372,13 @@ PrerenderContents::~PrerenderContents() {
if (prerendering_has_started())
RecordFinalStatus(final_status_);
- if (render_view_host_ || prerender_contents_.get()) {
- RenderViewHost* prerender_render_view_host = render_view_host_mutable();
-
- int process_id = prerender_render_view_host->process()->id();
- int view_id = prerender_render_view_host->routing_id();
+ // Only delete the RenderViewHost if we own it.
+ if (render_view_host_)
+ render_view_host_->Shutdown();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- NewRunnableFunction(&RemoveChildRoutePair,
- g_browser_process->resource_dispatcher_host(),
- process_id, view_id));
-
- // Only delete the RenderViewHost if we own it.
- if (render_view_host_)
- render_view_host_->Shutdown();
+ if (child_id_ != -1 && route_id_ != -1) {
+ PrerenderTracker::GetInstance()->OnPrerenderingFinished(
+ child_id_, route_id_);
}
}
@@ -739,6 +707,24 @@ void PrerenderContents::Destroy(FinalStatus final_status) {
if (prerender_manager_->IsPendingDelete(this))
return;
+ if (child_id_ != -1 && route_id_ != -1) {
+ // Cancel the prerender in the PrerenderTracker. This is needed
+ // because destroy may be called directly from the UI thread without calling
+ // TryCancel(). This is difficult to completely avoid, since prerendering
+ // can be cancelled before a RenderView is created.
+ bool is_cancelled =
+ PrerenderTracker::GetInstance()->TryCancel(child_id_, route_id_,
+ final_status);
+ CHECK(is_cancelled);
+
+ // A different final status may have been set already from another thread.
+ // If so, use it instead.
+ if (!PrerenderTracker::GetInstance()->GetFinalStatus(child_id_, route_id_,
+ &final_status)) {
+ NOTREACHED();
+ }
+ }
+
prerender_manager_->MoveEntryToPendingDelete(this);
set_final_status(final_status);
// We may destroy the PrerenderContents before we have initialized the
diff --git a/chrome/browser/prerender/prerender_contents.h b/chrome/browser/prerender/prerender_contents.h
index feaaab2..31c115e 100644
--- a/chrome/browser/prerender/prerender_contents.h
+++ b/chrome/browser/prerender/prerender_contents.h
@@ -323,6 +323,8 @@ class PrerenderContents : public RenderViewHostDelegate,
bool has_stopped_loading_;
+ // This must be the same value as the PrerenderTracker has recorded for
+ // |this|, when |this| has a RenderView.
FinalStatus final_status_;
bool prerendering_has_started_;
@@ -343,6 +345,10 @@ class PrerenderContents : public RenderViewHostDelegate,
scoped_ptr<TabContentsDelegateImpl> tab_contents_delegate_;
+ // These are -1 before a RenderView is created.
+ int child_id_;
+ int route_id_;
+
DISALLOW_COPY_AND_ASSIGN(PrerenderContents);
};
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index 053de20..f5ccebe 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -14,6 +14,7 @@
#include "chrome/browser/favicon/favicon_tab_helper.h"
#include "chrome/browser/prerender/prerender_contents.h"
#include "chrome/browser/prerender/prerender_final_status.h"
+#include "chrome/browser/prerender/prerender_tracker.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper_delegate.h"
@@ -390,9 +391,7 @@ void PrerenderManager::DeleteOldEntries() {
PrerenderContentsData data = prerender_list_.front();
if (IsPrerenderElementFresh(data.start_time_))
return;
- prerender_list_.pop_front();
- data.contents_->set_final_status(FINAL_STATUS_TIMED_OUT);
- delete data.contents_;
+ data.contents_->Destroy(FINAL_STATUS_TIMED_OUT);
}
MaybeStopSchedulingPeriodicCleanups();
}
@@ -439,6 +438,16 @@ bool PrerenderManager::MaybeUsePreloadedPageOld(TabContents* tab_contents,
return false;
}
+ int child_id, route_id;
+ CHECK(prerender_contents->GetChildId(&child_id));
+ CHECK(prerender_contents->GetRouteId(&route_id));
+
+ // Try to set the prerendered page as used, so any subsequent attempts to
+ // cancel on other threads will fail. If this fails because the prerender
+ // was already cancelled, possibly on another thread, fail.
+ if (!PrerenderTracker::GetInstance()->TryUse(child_id, route_id))
+ return false;
+
if (!prerender_contents->load_start_time().is_null())
RecordTimeUntilUsed(GetCurrentTimeTicks() -
prerender_contents->load_start_time());
@@ -447,11 +456,6 @@ bool PrerenderManager::MaybeUsePreloadedPageOld(TabContents* tab_contents,
++prerenders_per_session_count_);
prerender_contents->set_final_status(FINAL_STATUS_USED);
- int child_id;
- int route_id;
- CHECK(prerender_contents->GetChildId(&child_id));
- CHECK(prerender_contents->GetRouteId(&route_id));
-
RenderViewHost* render_view_host =
prerender_contents->render_view_host_mutable();
prerender_contents->set_render_view_host(NULL);
@@ -531,6 +535,16 @@ bool PrerenderManager::MaybeUsePreloadedPage(TabContents* tab_contents,
return false;
}
+ int child_id, route_id;
+ CHECK(prerender_contents->GetChildId(&child_id));
+ CHECK(prerender_contents->GetRouteId(&route_id));
+
+ // Try to set the prerendered page as used, so any subsequent attempts to
+ // cancel on other threads will fail. If this fails because the prerender
+ // was already cancelled, possibly on another thread, fail.
+ if (!PrerenderTracker::GetInstance()->TryUse(child_id, route_id))
+ return false;
+
if (!prerender_contents->load_start_time().is_null())
RecordTimeUntilUsed(GetCurrentTimeTicks() -
prerender_contents->load_start_time());
@@ -539,11 +553,6 @@ bool PrerenderManager::MaybeUsePreloadedPage(TabContents* tab_contents,
++prerenders_per_session_count_);
prerender_contents->set_final_status(FINAL_STATUS_USED);
- int child_id;
- int route_id;
- CHECK(prerender_contents->GetChildId(&child_id));
- CHECK(prerender_contents->GetRouteId(&route_id));
-
RenderViewHost* render_view_host =
prerender_contents->prerender_contents()->render_view_host();
DCHECK(render_view_host);
diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h
index a5e60d7..8917abc 100644
--- a/chrome/browser/prerender/prerender_manager.h
+++ b/chrome/browser/prerender/prerender_manager.h
@@ -48,15 +48,6 @@ void HandlePrefetchTag(
const GURL& referrer,
bool make_pending);
-// Given a renderer process id and view id, this will destroy any preloads and
-// pending preloads than are using or originated in the given render view.
-// Must be called on the UI thread.
-void DestroyPreloadForRenderView(
- const base::WeakPtr<PrerenderManager>& prerender_manager_weak_ptr,
- int render_process_id,
- int render_view_id,
- FinalStatus final_status);
-
// PrerenderManager is responsible for initiating and keeping prerendered
// views of webpages. All methods must be called on the UI thread unless
// indicated otherwise.
@@ -93,7 +84,7 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>,
// Destroy all preloads for the given child route id pair and assign a final
// status to them.
- void DestroyPreloadForChildRouteIdPair(
+ virtual void DestroyPreloadForChildRouteIdPair(
const std::pair<int, int>& child_route_id_pair,
FinalStatus final_status);
diff --git a/chrome/browser/prerender/prerender_tracker.cc b/chrome/browser/prerender/prerender_tracker.cc
new file mode 100644
index 0000000..c82acd3
--- /dev/null
+++ b/chrome/browser/prerender/prerender_tracker.cc
@@ -0,0 +1,202 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "chrome/browser/prerender/prerender_manager.h"
+#include "chrome/browser/prerender/prerender_tracker.h"
+#include "content/browser/browser_thread.h"
+
+namespace prerender {
+
+namespace {
+
+void DestroyPreloadForRenderView(
+ const base::WeakPtr<PrerenderManager>& prerender_manager_weak_ptr,
+ int child_id,
+ int route_id,
+ FinalStatus final_status) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ PrerenderManager* prerender_manager = prerender_manager_weak_ptr.get();
+ if (!prerender_manager)
+ return;
+
+ prerender_manager->DestroyPreloadForChildRouteIdPair(
+ std::make_pair(child_id, route_id),
+ final_status);
+}
+
+} // namespace
+
+struct RenderViewInfo {
+ explicit RenderViewInfo(PrerenderManager* prerender_manager)
+ : final_status(FINAL_STATUS_MAX),
+ prerender_manager(prerender_manager->AsWeakPtr()) {
+ }
+
+ FinalStatus final_status;
+ base::WeakPtr<PrerenderManager> prerender_manager;
+};
+
+// static
+PrerenderTracker* PrerenderTracker::GetInstance() {
+ return Singleton<PrerenderTracker>::get();
+}
+
+bool PrerenderTracker::TryUse(int child_id, int route_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ FinalStatus final_status = SetFinalStatus(child_id, route_id,
+ FINAL_STATUS_USED);
+ return final_status == FINAL_STATUS_USED;
+}
+
+bool PrerenderTracker::TryCancel(
+ int child_id,
+ int route_id,
+ FinalStatus final_status) {
+ DCHECK_NE(FINAL_STATUS_USED, final_status);
+ DCHECK(final_status >= 0 && final_status < FINAL_STATUS_MAX);
+
+ final_status = SetFinalStatus(child_id, route_id, final_status);
+ return final_status != FINAL_STATUS_USED && final_status != FINAL_STATUS_MAX;
+}
+
+bool PrerenderTracker::TryCancelOnIOThread(
+ int child_id,
+ int route_id,
+ FinalStatus final_status) {
+ DCHECK_NE(FINAL_STATUS_USED, final_status);
+ DCHECK(final_status >= 0 && final_status < FINAL_STATUS_MAX);
+
+ if (!IsPrerenderingOnIOThread(child_id, route_id))
+ return false;
+ return TryCancel(child_id, route_id, final_status);
+}
+
+bool PrerenderTracker::IsPrerenderingOnIOThread(int child_id,
+ int route_id) const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ ChildRouteIdPair child_route_id_pair(child_id, route_id);
+ return possibly_prerendering_io_thread_set_.end() !=
+ possibly_prerendering_io_thread_set_.find(child_route_id_pair);
+}
+
+bool PrerenderTracker::GetFinalStatus(int child_id, int route_id,
+ FinalStatus* final_status) const {
+ ChildRouteIdPair child_route_id_pair(child_id, route_id);
+
+ base::AutoLock lock(final_status_map_lock_);
+ FinalStatusMap::const_iterator final_status_it =
+ final_status_map_.find(child_route_id_pair);
+ if (final_status_map_.end() == final_status_map_.find(child_route_id_pair))
+ return false;
+ *final_status = final_status_it->second.final_status;
+ return true;
+}
+
+void PrerenderTracker::OnPrerenderingStarted(
+ int child_id, int route_id, PrerenderManager* prerender_manager) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK_GE(child_id, 0);
+ DCHECK_GE(route_id, 0);
+
+ ChildRouteIdPair child_route_id_pair(child_id, route_id);
+
+ // The RenderView should not already be prerendering.
+ DCHECK(final_status_map_.end() ==
+ final_status_map_.find(child_route_id_pair));
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableFunction(&AddPrerenderOnIOThreadTask, child_route_id_pair));
+
+ base::AutoLock lock(final_status_map_lock_);
+
+ final_status_map_.insert(
+ std::make_pair(child_route_id_pair, RenderViewInfo(prerender_manager)));
+}
+
+void PrerenderTracker::OnPrerenderingFinished(int child_id, int route_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK_GE(child_id, 0);
+ DCHECK_GE(route_id, 0);
+
+ ChildRouteIdPair child_route_id_pair(child_id, route_id);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableFunction(&RemovePrerenderOnIOThreadTask, child_route_id_pair));
+
+ base::AutoLock lock(final_status_map_lock_);
+ size_t num_erased = final_status_map_.erase(child_route_id_pair);
+ DCHECK_EQ(1u, num_erased);
+}
+
+PrerenderTracker::PrerenderTracker() {
+}
+
+PrerenderTracker::~PrerenderTracker() {
+}
+
+FinalStatus PrerenderTracker::SetFinalStatus(int child_id, int route_id,
+ FinalStatus final_status) {
+ DCHECK(final_status >= FINAL_STATUS_USED && final_status < FINAL_STATUS_MAX);
+
+ ChildRouteIdPair child_route_id_pair(child_id, route_id);
+
+ base::AutoLock lock(final_status_map_lock_);
+ FinalStatusMap::iterator final_status_it =
+ final_status_map_.find(child_route_id_pair);
+ if (final_status_it == final_status_map_.end()) {
+ // The RenderView has already been either used or destroyed.
+ return FINAL_STATUS_MAX;
+ }
+
+ if (final_status_it->second.final_status == FINAL_STATUS_MAX) {
+ final_status_it->second.final_status = final_status;
+ if (final_status != FINAL_STATUS_USED) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableFunction(&DestroyPreloadForRenderView,
+ final_status_it->second.prerender_manager,
+ child_id,
+ route_id,
+ final_status));
+ }
+ }
+ return final_status_it->second.final_status;
+}
+
+void PrerenderTracker::AddPrerenderOnIOThread(
+ const ChildRouteIdPair& child_route_id_pair) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(!IsPrerenderingOnIOThread(child_route_id_pair.first,
+ child_route_id_pair.second));
+
+ possibly_prerendering_io_thread_set_.insert(child_route_id_pair);
+}
+
+void PrerenderTracker::RemovePrerenderOnIOThread(
+ const ChildRouteIdPair& child_route_id_pair) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(IsPrerenderingOnIOThread(child_route_id_pair.first,
+ child_route_id_pair.second));
+
+ possibly_prerendering_io_thread_set_.erase(child_route_id_pair);
+}
+
+// static
+void PrerenderTracker::AddPrerenderOnIOThreadTask(
+ const ChildRouteIdPair& child_route_id_pair) {
+ GetInstance()->AddPrerenderOnIOThread(child_route_id_pair);
+}
+
+// static
+void PrerenderTracker::RemovePrerenderOnIOThreadTask(
+ const ChildRouteIdPair& child_route_id_pair) {
+ GetInstance()->RemovePrerenderOnIOThread(child_route_id_pair);
+}
+
+} // namespace prerender
diff --git a/chrome/browser/prerender/prerender_tracker.h b/chrome/browser/prerender/prerender_tracker.h
new file mode 100644
index 0000000..f263052
--- /dev/null
+++ b/chrome/browser/prerender/prerender_tracker.h
@@ -0,0 +1,136 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PRERENDER_PRERENDER_TRACKER_H_
+#define CHROME_BROWSER_PRERENDER_PRERENDER_TRACKER_H_
+#pragma once
+
+#include <map>
+#include <set>
+
+#include "base/memory/singleton.h"
+#include "base/synchronization/lock.h"
+#include "chrome/browser/prerender/prerender_final_status.h"
+
+namespace prerender {
+
+class PrerenderManager;
+struct RenderViewInfo;
+
+// PrerenderTracker is responsible for keeping track of all prerendering
+// RenderViews and their statuses. Its list is guaranteed to be up to date
+// and can be modified on any thread.
+class PrerenderTracker {
+ public:
+ // Returns the PrerenderTracker singleton.
+ static PrerenderTracker* GetInstance();
+
+ // Attempts to set the status of the specified RenderViewHost to
+ // FINAL_STATUS_USED. Returns true on success. Returns false if it has
+ // already been cancelled for any reason, or is no longer prerendering.
+ // Can only be called only on the IO thread. This method will not call
+ // PrerenderContents::set_final_status() on the corresponding
+ // PrerenderContents.
+ //
+ // If it returns true, all subsequent calls to TryCancel for the RenderView
+ // will return false.
+ bool TryUse(int child_id, int route_id);
+
+ // Attempts to cancel prerendering by the specified RenderView, setting the
+ // FinalStatus to |final_status|. Returns true if the specified prerender has
+ // been cancelled, either as a result of this call or for any other reason.
+ // If the call results in cancelling a PrerenderContents, a task to destroy
+ // it is also posted to the UI thread.
+ //
+ // When true is returned, it is guaranteed that the RenderView will never
+ // be displayed. When false is returned, the RenderView has either been
+ // swapped into a tab or has already been destroyed.
+ bool TryCancel(int child_id, int route_id, FinalStatus final_status);
+
+ // Same as above, but can only called on the IO Thread. Does not acquire a
+ // lock when the RenderView is not being prerendered.
+ bool TryCancelOnIOThread(int child_id, int route_id,
+ FinalStatus final_status);
+
+ // Returns whether or not a RenderView is prerendering. Can only be called on
+ // the IO thread. Does not acquire a lock, so may claim a RenderView that has
+ // been displayed or destroyed is still prerendering.
+ // TODO(mmenke): Remove external use of this method and make it private.
+ bool IsPrerenderingOnIOThread(int child_id, int route_id) const;
+
+ // Gets the FinalStatus of the specified prerendered RenderView. Returns
+ // |true| and sets |final_status| to the status of the RenderView if it
+ // is found, returns false otherwise.
+ bool GetFinalStatus(int child_id, int route_id,
+ FinalStatus* final_status) const;
+
+ protected:
+ friend class PrerenderContents;
+
+ FRIEND_TEST_ALL_PREFIXES(PrerenderTrackerTest, PrerenderTrackerUsed);
+ FRIEND_TEST_ALL_PREFIXES(PrerenderTrackerTest, PrerenderTrackerCancelled);
+ FRIEND_TEST_ALL_PREFIXES(PrerenderTrackerTest, PrerenderTrackerCancelledOnIO);
+ FRIEND_TEST_ALL_PREFIXES(PrerenderTrackerTest, PrerenderTrackerCancelledFast);
+ FRIEND_TEST_ALL_PREFIXES(PrerenderTrackerTest, PrerenderTrackerMultiple);
+
+ // Must be called when a RenderView starts prerendering, before the first
+ // navigation starts to avoid any races.
+ void OnPrerenderingStarted(int child_id, int route_id,
+ PrerenderManager* prerender_manager);
+
+ // Must be called when a RenderView stops prerendering, either because the
+ // RenderView was used or prerendering was cancelled and it is being
+ // destroyed.
+ void OnPrerenderingFinished(int child_id, int route_id);
+
+ private:
+ friend struct DefaultSingletonTraits<PrerenderTracker>;
+
+ typedef std::pair<int, int> ChildRouteIdPair;
+
+ // Map of child/route id pairs to final statuses.
+ typedef std::map<ChildRouteIdPair, RenderViewInfo> FinalStatusMap;
+ // Set of child/route id pairs that may be prerendering.
+ typedef std::set<ChildRouteIdPair> PossiblyPrerenderingChildRouteIdPairs;
+
+ PrerenderTracker();
+ ~PrerenderTracker();
+
+ // Attempts to set the FinalStatus of the specified RenderView to
+ // |final_status|. If the FinalStatus of the RenderView has already been
+ // set, does nothing. Returns the resulting FinalStatus of that RenderView,
+ // regardless of success or failure. If the RenderView isn't currently
+ // prerendering, returns FINAL_STATUS_MAX.
+ FinalStatus SetFinalStatus(int child_id, int route_id,
+ FinalStatus final_status);
+
+ // Add/remove the specified pair to |possibly_prerendering_io_thread_set_| on
+ // the IO Thread.
+ void AddPrerenderOnIOThread(const ChildRouteIdPair& child_route_id_pair);
+ void RemovePrerenderOnIOThread(const ChildRouteIdPair& child_route_id_pair);
+
+ // Tasks posted to the IO Thread to call the above functions.
+ static void AddPrerenderOnIOThreadTask(
+ const ChildRouteIdPair& child_route_id_pair);
+ static void RemovePrerenderOnIOThreadTask(
+ const ChildRouteIdPair& child_route_id_pair);
+
+ // |final_status_map_lock_| protects access to |final_status_map_|.
+ mutable base::Lock final_status_map_lock_;
+ // Map containing child/route id pairs and their final statuses. Must only be
+ // accessed while the lock is held. Values are always accurate and up to
+ // date.
+ FinalStatusMap final_status_map_;
+
+ // Superset of child/route id pairs that are prerendering. Can only access on
+ // the IO thread. May contain entries that have since been displayed. Only
+ // used to prevent locking when not needed.
+ PossiblyPrerenderingChildRouteIdPairs possibly_prerendering_io_thread_set_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrerenderTracker);
+};
+
+} // namespace prerender
+
+#endif // CHROME_BROWSER_PRERENDER_PRERENDER_TRACKER_H_
diff --git a/chrome/browser/prerender/prerender_tracker_unittest.cc b/chrome/browser/prerender/prerender_tracker_unittest.cc
new file mode 100644
index 0000000..4ed6f83
--- /dev/null
+++ b/chrome/browser/prerender/prerender_tracker_unittest.cc
@@ -0,0 +1,294 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <set>
+
+#include "base/logging.h"
+#include "chrome/browser/prerender/prerender_manager.h"
+#include "chrome/browser/prerender/prerender_tracker.h"
+#include "content/browser/browser_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace prerender {
+
+namespace {
+
+class TestPrerenderManager : public PrerenderManager {
+ public:
+ TestPrerenderManager() : PrerenderManager(NULL) {
+ rate_limit_enabled_ = false;
+ }
+
+ virtual void DestroyPreloadForChildRouteIdPair(
+ const std::pair<int, int>& child_route_id_pair,
+ FinalStatus final_status) OVERRIDE {
+ cancelled_id_pairs_.insert(child_route_id_pair);
+ }
+
+ bool WasPrerenderCancelled(int child_id, int route_id) {
+ std::pair<int, int> child_route_id_pair(child_id, route_id);
+ return cancelled_id_pairs_.count(child_route_id_pair) != 0;
+ }
+
+ // Set of all the RenderViews that have been cancelled.
+ std::set<std::pair<int, int> > cancelled_id_pairs_;
+};
+
+} // namespace
+
+class PrerenderTrackerTest : public testing::Test {
+ public:
+ PrerenderTrackerTest() :
+ ui_thread_(BrowserThread::UI, &message_loop_),
+ io_thread_(BrowserThread::IO, &message_loop_),
+ prerender_manager_(new TestPrerenderManager()) {
+ }
+
+ TestPrerenderManager* prerender_manager() {
+ return prerender_manager_.get();
+ }
+
+ PrerenderTracker* prerender_tracker() {
+ return PrerenderTracker::GetInstance();
+ }
+
+ int GetCurrentStatus(int child_id, int route_id) {
+ FinalStatus final_status;
+ if (!prerender_tracker()->GetFinalStatus(child_id, route_id,
+ &final_status)) {
+ return -1;
+ }
+ return final_status;
+ }
+
+ // Runs any tasks queued on either thread.
+ void RunEvents() {
+ message_loop_.RunAllPending();
+ }
+
+ private:
+ MessageLoop message_loop_;
+ BrowserThread ui_thread_;
+ BrowserThread io_thread_;
+
+ scoped_ptr<TestPrerenderManager> prerender_manager_;
+};
+
+// Check that a non-existant RenderView is handled correctly.
+TEST_F(PrerenderTrackerTest, PrerenderTrackerNull) {
+ FinalStatus final_status;
+ EXPECT_FALSE(prerender_tracker()->TryUse(0, 0));
+ EXPECT_FALSE(prerender_tracker()->TryCancel(0, 0, FINAL_STATUS_HTTPS));
+ EXPECT_FALSE(prerender_tracker()->TryCancelOnIOThread(
+ 0, 0, FINAL_STATUS_HTTPS));
+ EXPECT_FALSE(prerender_tracker()->IsPrerenderingOnIOThread(0, 0));
+ EXPECT_FALSE(prerender_tracker()->GetFinalStatus(0, 0, &final_status));
+ EXPECT_FALSE(prerender_manager()->WasPrerenderCancelled(0, 0));
+}
+
+// Check that a page that is used is handled correctly.
+TEST_F(PrerenderTrackerTest, PrerenderTrackerUsed) {
+ prerender_tracker()->OnPrerenderingStarted(0, 0, prerender_manager());
+ EXPECT_EQ(FINAL_STATUS_MAX, GetCurrentStatus(0, 0));
+
+ // This calls AddPrerenderOnIOThreadTask().
+ RunEvents();
+
+ EXPECT_TRUE(prerender_tracker()->IsPrerenderingOnIOThread(0, 0));
+ EXPECT_EQ(FINAL_STATUS_MAX, GetCurrentStatus(0, 0));
+
+ // Display the prerendered RenderView.
+ EXPECT_TRUE(prerender_tracker()->TryUse(0, 0));
+
+ // Make sure the page can't be destroyed or claim it was destroyed after
+ // it's been used.
+ EXPECT_FALSE(prerender_tracker()->TryCancel(0, 0, FINAL_STATUS_HTTPS));
+ EXPECT_FALSE(prerender_tracker()->TryCancelOnIOThread(
+ 0, 0, FINAL_STATUS_TIMED_OUT));
+ EXPECT_EQ(FINAL_STATUS_USED, GetCurrentStatus(0, 0));
+
+ // This would call DestroyPreloadForChildRouteIdPair(), if the prerender were
+ // cancelled.
+ RunEvents();
+
+ // These functions should all behave as before.
+ EXPECT_FALSE(prerender_tracker()->TryCancel(0, 0, FINAL_STATUS_HTTPS));
+ EXPECT_FALSE(prerender_tracker()->TryCancelOnIOThread(
+ 0, 0, FINAL_STATUS_TIMED_OUT));
+ EXPECT_EQ(FINAL_STATUS_USED, GetCurrentStatus(0, 0));
+
+ // This calls DestroyPreloadForChildRouteIdPair().
+ prerender_tracker()->OnPrerenderingFinished(0, 0);
+ EXPECT_TRUE(prerender_tracker()->IsPrerenderingOnIOThread(0, 0));
+
+ // This calls RemovePrerenderOnIOThreadTask().
+ RunEvents();
+
+ FinalStatus final_status;
+ EXPECT_FALSE(prerender_tracker()->GetFinalStatus(0, 0, &final_status));
+ EXPECT_FALSE(prerender_tracker()->IsPrerenderingOnIOThread(0, 0));
+ EXPECT_FALSE(prerender_tracker()->TryCancel(0, 0, FINAL_STATUS_HTTPS));
+ EXPECT_FALSE(prerender_manager()->WasPrerenderCancelled(0, 0));
+}
+
+// Check that a prerendered page cancelled by TryCancel() is handled correctly.
+TEST_F(PrerenderTrackerTest, PrerenderTrackerCancelled) {
+ prerender_tracker()->OnPrerenderingStarted(0, 0, prerender_manager());
+ EXPECT_EQ(FINAL_STATUS_MAX, GetCurrentStatus(0, 0));
+
+ // This calls AddPrerenderOnIOThreadTask().
+ RunEvents();
+
+ // Cancel the prerender.
+ EXPECT_TRUE(prerender_tracker()->TryCancel(0, 0, FINAL_STATUS_HTTPS));
+
+ EXPECT_FALSE(prerender_tracker()->TryUse(0, 0));
+ EXPECT_TRUE(prerender_tracker()->TryCancel(0, 0, FINAL_STATUS_TIMED_OUT));
+ EXPECT_TRUE(prerender_tracker()->TryCancelOnIOThread(
+ 0, 0, FINAL_STATUS_TIMED_OUT));
+ EXPECT_EQ(FINAL_STATUS_HTTPS, GetCurrentStatus(0, 0));
+
+ // This calls DestroyPreloadForChildRouteIdPair().
+ RunEvents();
+ EXPECT_TRUE(prerender_manager()->WasPrerenderCancelled(0, 0));
+
+ // These should all work until the prerendering RenderViewHost is destroyed.
+ EXPECT_TRUE(prerender_tracker()->TryCancel(0, 0, FINAL_STATUS_TIMED_OUT));
+ EXPECT_TRUE(prerender_tracker()->TryCancelOnIOThread(
+ 0, 0, FINAL_STATUS_TIMED_OUT));
+ EXPECT_EQ(FINAL_STATUS_HTTPS, GetCurrentStatus(0, 0));
+
+ prerender_tracker()->OnPrerenderingFinished(0, 0);
+ EXPECT_TRUE(prerender_tracker()->IsPrerenderingOnIOThread(0, 0));
+
+ // This calls RemovePrerenderOnIOThreadTask().
+ RunEvents();
+
+ FinalStatus final_status;
+ EXPECT_FALSE(prerender_tracker()->GetFinalStatus(0, 0, &final_status));
+ EXPECT_FALSE(prerender_tracker()->IsPrerenderingOnIOThread(0, 0));
+}
+
+// Check that a prerendered page cancelled on the IO thread by
+// TryCancelOnIOThread() is handled correctly.
+TEST_F(PrerenderTrackerTest, PrerenderTrackerCancelledOnIO) {
+ prerender_tracker()->OnPrerenderingStarted(0, 0, prerender_manager());
+ EXPECT_EQ(FINAL_STATUS_MAX, GetCurrentStatus(0, 0));
+
+ // This calls AddPrerenderOnIOThreadTask().
+ RunEvents();
+
+ // Cancel the prerender.
+ EXPECT_TRUE(prerender_tracker()->TryCancelOnIOThread(
+ 0, 0, FINAL_STATUS_TIMED_OUT));
+
+ EXPECT_FALSE(prerender_tracker()->TryUse(0, 0));
+ EXPECT_TRUE(prerender_tracker()->TryCancel(0, 0, FINAL_STATUS_HTTPS));
+ EXPECT_TRUE(prerender_tracker()->TryCancelOnIOThread(
+ 0, 0, FINAL_STATUS_HTTPS));
+ EXPECT_EQ(FINAL_STATUS_TIMED_OUT, GetCurrentStatus(0, 0));
+
+ // This calls DestroyPreloadForChildRouteIdPair().
+ RunEvents();
+ EXPECT_TRUE(prerender_manager()->WasPrerenderCancelled(0, 0));
+
+ // These should all work until the prerendering RenderViewHost is destroyed.
+ EXPECT_TRUE(prerender_tracker()->TryCancel(0, 0, FINAL_STATUS_HTTPS));
+ EXPECT_TRUE(prerender_tracker()->TryCancelOnIOThread(
+ 0, 0, FINAL_STATUS_HTTPS));
+ EXPECT_EQ(FINAL_STATUS_TIMED_OUT, GetCurrentStatus(0, 0));
+
+ prerender_tracker()->OnPrerenderingFinished(0, 0);
+ EXPECT_TRUE(prerender_tracker()->IsPrerenderingOnIOThread(0, 0));
+
+ // This calls RemovePrerenderOnIOThreadTask().
+ RunEvents();
+
+ FinalStatus final_status;
+ EXPECT_FALSE(prerender_tracker()->GetFinalStatus(0, 0, &final_status));
+ EXPECT_FALSE(prerender_tracker()->IsPrerenderingOnIOThread(0, 0));
+}
+
+// Check that a prerendered page cancelled before it reaches the IO thread is
+// handled correctly.
+TEST_F(PrerenderTrackerTest, PrerenderTrackerCancelledFast) {
+ prerender_tracker()->OnPrerenderingStarted(0, 0, prerender_manager());
+ // Cancel the prerender.
+ EXPECT_TRUE(prerender_tracker()->TryCancel(0, 0, FINAL_STATUS_HTTPS));
+
+ EXPECT_FALSE(prerender_tracker()->TryUse(0, 0));
+ EXPECT_TRUE(prerender_tracker()->TryCancel(0, 0, FINAL_STATUS_TIMED_OUT));
+
+ // This calls AddPrerenderOnIOThreadTask() and
+ // DestroyPreloadForChildRouteIdPair().
+ RunEvents();
+ EXPECT_TRUE(prerender_manager()->WasPrerenderCancelled(0, 0));
+
+ EXPECT_TRUE(prerender_tracker()->TryCancelOnIOThread(
+ 0, 0, FINAL_STATUS_TIMED_OUT));
+ EXPECT_TRUE(prerender_tracker()->TryCancel(0, 0, FINAL_STATUS_TIMED_OUT));
+ EXPECT_EQ(FINAL_STATUS_HTTPS, GetCurrentStatus(0, 0));
+
+ prerender_tracker()->OnPrerenderingFinished(0, 0);
+
+ // This calls RemovePrerenderOnIOThreadTask().
+ RunEvents();
+
+ FinalStatus final_status;
+ EXPECT_FALSE(prerender_tracker()->GetFinalStatus(0, 0, &final_status));
+ EXPECT_FALSE(prerender_tracker()->IsPrerenderingOnIOThread(0, 0));
+}
+
+// Check that handling two pages at once works.
+TEST_F(PrerenderTrackerTest, PrerenderTrackerMultiple) {
+ prerender_tracker()->OnPrerenderingStarted(0, 0, prerender_manager());
+
+ // This calls AddPrerenderOnIOThreadTask().
+ RunEvents();
+ EXPECT_TRUE(prerender_tracker()->IsPrerenderingOnIOThread(0, 0));
+ EXPECT_FALSE(prerender_tracker()->IsPrerenderingOnIOThread(1, 2));
+ EXPECT_FALSE(prerender_tracker()->TryUse(1, 2));
+ EXPECT_FALSE(prerender_tracker()->TryCancel(1, 2, FINAL_STATUS_HTTPS));
+
+ // Start second prerender.
+ prerender_tracker()->OnPrerenderingStarted(1, 2, prerender_manager());
+ // This calls AddPrerenderOnIOThreadTask().
+ RunEvents();
+
+ // Use (0, 0).
+ EXPECT_TRUE(prerender_tracker()->TryUse(0, 0));
+ EXPECT_EQ(FINAL_STATUS_USED, GetCurrentStatus(0, 0));
+ EXPECT_EQ(FINAL_STATUS_MAX, GetCurrentStatus(1, 2));
+
+ // Cancel (1, 2).
+ EXPECT_TRUE(prerender_tracker()->TryCancelOnIOThread(
+ 1, 2, FINAL_STATUS_HTTPS));
+
+ EXPECT_FALSE(prerender_tracker()->TryCancel(0, 0, FINAL_STATUS_HTTPS));
+ EXPECT_EQ(FINAL_STATUS_USED, GetCurrentStatus(0, 0));
+
+ EXPECT_FALSE(prerender_tracker()->TryUse(1, 2));
+ EXPECT_TRUE(prerender_tracker()->TryCancel(1, 2, FINAL_STATUS_HTTPS));
+ EXPECT_EQ(FINAL_STATUS_HTTPS, GetCurrentStatus(1, 2));
+
+ // This calls DestroyPreloadForChildRouteIdPair().
+ RunEvents();
+ EXPECT_FALSE(prerender_manager()->WasPrerenderCancelled(0, 0));
+ EXPECT_TRUE(prerender_manager()->WasPrerenderCancelled(1, 2));
+
+ prerender_tracker()->OnPrerenderingFinished(0, 0);
+ prerender_tracker()->OnPrerenderingFinished(1, 2);
+
+ // This calls RemovePrerenderOnIOThreadTask().
+ RunEvents();
+
+ FinalStatus final_status;
+ EXPECT_FALSE(prerender_tracker()->GetFinalStatus(0, 0, &final_status));
+ EXPECT_FALSE(prerender_tracker()->IsPrerenderingOnIOThread(0, 0));
+
+ EXPECT_FALSE(prerender_tracker()->GetFinalStatus(1, 2, &final_status));
+ EXPECT_FALSE(prerender_tracker()->IsPrerenderingOnIOThread(1, 2));
+}
+
+} // namespace prerender
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 5465fc8..d1c0605 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1653,6 +1653,8 @@
'browser/prerender/prerender_render_view_host_observer.h',
'browser/prerender/prerender_render_widget_host_view.cc',
'browser/prerender/prerender_render_widget_host_view.h',
+ 'browser/prerender/prerender_tracker.cc',
+ 'browser/prerender/prerender_tracker.h',
'browser/printing/background_printing_manager.cc',
'browser/printing/background_printing_manager.h',
'browser/printing/cloud_print/cloud_print_proxy_service.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 3fae730..b987f2c 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1502,6 +1502,7 @@
'browser/prefs/scoped_user_pref_update_unittest.cc',
'browser/prefs/session_startup_pref_unittest.cc',
'browser/prerender/prerender_manager_unittest.cc',
+ 'browser/prerender/prerender_tracker_unittest.cc',
'browser/printing/cloud_print/cloud_print_setup_source_unittest.cc',
'browser/printing/print_dialog_cloud_unittest.cc',
'browser/printing/print_job_unittest.cc',
diff --git a/content/browser/DEPS b/content/browser/DEPS
index 055ff1a..5678284 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -62,6 +62,7 @@ include_rules = [
# http://crbug.com/77090
"+chrome/browser/prerender/prerender_manager.h",
+ "+chrome/browser/prerender/prerender_tracker.h",
# http://crbug.com/76788
"+chrome/browser/profiles/profile.h",
diff --git a/content/browser/renderer_host/resource_dispatcher_host.cc b/content/browser/renderer_host/resource_dispatcher_host.cc
index 8fdc0c3..451f99e 100644
--- a/content/browser/renderer_host/resource_dispatcher_host.cc
+++ b/content/browser/renderer_host/resource_dispatcher_host.cc
@@ -26,6 +26,7 @@
#include "chrome/browser/external_protocol_handler.h"
#include "chrome/browser/net/url_request_tracking.h"
#include "chrome/browser/prerender/prerender_manager.h"
+#include "chrome/browser/prerender/prerender_tracker.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/renderer_host/download_resource_handler.h"
#include "chrome/browser/renderer_host/safe_browsing_resource_handler.h"
@@ -432,7 +433,9 @@ void ResourceDispatcherHost::BeginRequest(
}
const GURL referrer = MaybeStripReferrer(request_data.referrer);
- const bool is_prerendering = IsPrerenderingChildRoutePair(child_id, route_id);
+ const bool is_prerendering =
+ prerender::PrerenderTracker::GetInstance()->IsPrerenderingOnIOThread(
+ child_id, route_id);
// Handle a PREFETCH resource type. If prefetch is disabled, squelch the
// request. If prerendering is enabled, trigger a prerender for the URL
@@ -467,16 +470,11 @@ void ResourceDispatcherHost::BeginRequest(
// Abort any prerenders that spawn requests that use invalid HTTP methods.
if (is_prerendering &&
!prerender::PrerenderManager::IsValidHttpMethod(request_data.method)) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- NewRunnableFunction(
- prerender::DestroyPreloadForRenderView,
- resource_context.prerender_manager(),
- child_id,
- route_id,
- prerender::FINAL_STATUS_INVALID_HTTP_METHOD));
- AbortRequestBeforeItStarts(filter_, sync_result, route_id, request_id);
- return;
+ if (prerender::PrerenderTracker::GetInstance()->TryCancelOnIOThread(
+ child_id, route_id, prerender::FINAL_STATUS_INVALID_HTTP_METHOD)) {
+ AbortRequestBeforeItStarts(filter_, sync_result, route_id, request_id);
+ return;
+ }
}
// Construct the event handler.
@@ -2036,28 +2034,6 @@ net::RequestPriority ResourceDispatcherHost::DetermineRequestPriority(
}
}
-void ResourceDispatcherHost::AddPrerenderChildRoutePair(int child_id,
- int route_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(!IsPrerenderingChildRoutePair(child_id, route_id));
- prerender_child_route_pairs_.insert(std::make_pair(child_id, route_id));
-}
-
-void ResourceDispatcherHost::RemovePrerenderChildRoutePair(int child_id,
- int route_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(IsPrerenderingChildRoutePair(child_id, route_id));
- prerender_child_route_pairs_.erase(std::make_pair(child_id, route_id));
-}
-
-bool ResourceDispatcherHost::IsPrerenderingChildRoutePair(int child_id,
- int route_id) const {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- std::pair<int, int> c_r_pair = std::make_pair(child_id, route_id);
- return (prerender_child_route_pairs_.find(c_r_pair) !=
- prerender_child_route_pairs_.end());
-}
-
// static
bool ResourceDispatcherHost::is_prefetch_enabled() {
diff --git a/content/browser/renderer_host/resource_dispatcher_host.h b/content/browser/renderer_host/resource_dispatcher_host.h
index f7a5c64..f8643fe 100644
--- a/content/browser/renderer_host/resource_dispatcher_host.h
+++ b/content/browser/renderer_host/resource_dispatcher_host.h
@@ -244,14 +244,6 @@ class ResourceDispatcherHost : public net::URLRequest::Delegate {
static bool is_prefetch_enabled();
static void set_is_prefetch_enabled(bool value);
- void AddPrerenderChildRoutePair(int child_id, int route_id);
- void RemovePrerenderChildRoutePair(int child_id, int route_id);
-
- typedef std::set<std::pair<int, int> > PrerenderChildRouteIdPairs;
- const PrerenderChildRouteIdPairs& prerender_child_route_id_pairs() const {
- return prerender_child_route_pairs_;
- }
-
private:
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
TestBlockedRequestsProcessDies);
@@ -384,8 +376,6 @@ class ResourceDispatcherHost : public net::URLRequest::Delegate {
const GURL& new_first_party_for_cookies);
void OnReleaseDownloadedFile(int request_id);
- bool IsPrerenderingChildRoutePair(int child_id, int route_id) const;
-
ResourceHandler* CreateSafeBrowsingResourceHandler(
ResourceHandler* handler, int child_id, int route_id,
ResourceType::Type resource_type);
@@ -487,7 +477,6 @@ class ResourceDispatcherHost : public net::URLRequest::Delegate {
ResourceMessageFilter* filter_;
static bool is_prefetch_enabled_;
- PrerenderChildRouteIdPairs prerender_child_route_pairs_;
DISALLOW_COPY_AND_ASSIGN(ResourceDispatcherHost);