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

Unified Diff: chrome/browser/prerender/prerender_tracker.cc

Issue 7038012: Safely cancel prerenders on threads other than the UI thread (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Fix linux Created 9 years, 7 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
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,196 @@
+// 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 {
+ FinalStatus final_status;
dominich 2011/05/19 16:07:27 Should this have a constructor that takes the Prer
mmenke 2011/05/19 16:40:42 In order to do that, I'd also have to make a const
dominich 2011/05/19 16:55:47 I think that's only if you use operator[]. If you
mmenke 2011/05/19 17:19:10 You're right. Done as you suggest.
+ 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) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ std::pair<int, int> 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) {
+ std::pair<int, int> child_route_id_pair(child_id, route_id);
+
+ base::AutoLock lock(lock_);
+ FinalStatusMap::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_NE(-1, child_id);
+ DCHECK_NE(-1, route_id);
+
+ std::pair<int, int> 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(lock_);
+ final_status_map_[child_route_id_pair].final_status = FINAL_STATUS_MAX;
+ final_status_map_[child_route_id_pair].prerender_manager =
+ prerender_manager->AsWeakPtr();
+}
+
+void PrerenderTracker::OnPrerenderingFinished(int child_id, int route_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK_NE(-1, child_id);
+ DCHECK_NE(-1, route_id);
+
+ std::pair<int, int> child_route_id_pair(child_id, route_id);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ NewRunnableFunction(&RemovePrerenderOnIOThreadTask, child_route_id_pair));
+
+ base::AutoLock lock(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);
+
+ std::pair<int, int> child_route_id_pair(child_id, route_id);
+
+ base::AutoLock lock(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 std::pair<int, int>& 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 std::pair<int, int>& 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 std::pair<int, int>& child_route_id_pair) {
+ GetInstance()->AddPrerenderOnIOThread(child_route_id_pair);
+}
+
+// static
+void PrerenderTracker::RemovePrerenderOnIOThreadTask(
+ const std::pair<int, int>& 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

Powered by Google App Engine
This is Rietveld 408576698