Index: chrome/browser/prerender/prerender_tracker.cc |
=================================================================== |
--- chrome/browser/prerender/prerender_tracker.cc (revision 0) |
+++ chrome/browser/prerender/prerender_tracker.cc (revision 0) |
@@ -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, |
cbentzel
2011/05/23 12:08:15
I think it would be clearer if this signature chan
|
+ 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 |
Property changes on: chrome\browser\prerender\prerender_tracker.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |