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

Side by Side 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: sync 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 unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/logging.h"
6 #include "chrome/browser/prerender/prerender_manager.h"
7 #include "chrome/browser/prerender/prerender_tracker.h"
8 #include "content/browser/browser_thread.h"
9
10 namespace prerender {
11
12 namespace {
13
14 void DestroyPreloadForRenderView(
15 const base::WeakPtr<PrerenderManager>& prerender_manager_weak_ptr,
16 int child_id,
17 int route_id,
18 FinalStatus final_status) {
19 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
20 PrerenderManager* prerender_manager = prerender_manager_weak_ptr.get();
21 if (!prerender_manager)
22 return;
23
24 prerender_manager->DestroyPreloadForChildRouteIdPair(
25 std::make_pair(child_id, route_id),
26 final_status);
27 }
28
29 } // namespace
30
31 struct RenderViewInfo {
32 explicit RenderViewInfo(PrerenderManager* prerender_manager)
33 : final_status(FINAL_STATUS_MAX),
34 prerender_manager(prerender_manager->AsWeakPtr()) {
35 }
36
37 FinalStatus final_status;
38 base::WeakPtr<PrerenderManager> prerender_manager;
39 };
40
41 // static
42 PrerenderTracker* PrerenderTracker::GetInstance() {
43 return Singleton<PrerenderTracker>::get();
44 }
45
46 bool PrerenderTracker::TryUse(int child_id, int route_id) {
47 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
48
49 FinalStatus final_status = SetFinalStatus(child_id, route_id,
50 FINAL_STATUS_USED);
51 return final_status == FINAL_STATUS_USED;
52 }
53
54 bool PrerenderTracker::TryCancel(
55 int child_id,
56 int route_id,
57 FinalStatus final_status) {
58 DCHECK_NE(FINAL_STATUS_USED, final_status);
59 DCHECK(final_status >= 0 && final_status < FINAL_STATUS_MAX);
60
61 final_status = SetFinalStatus(child_id, route_id, final_status);
62 return final_status != FINAL_STATUS_USED && final_status != FINAL_STATUS_MAX;
63 }
64
65 bool PrerenderTracker::TryCancelOnIOThread(
66 int child_id,
67 int route_id,
68 FinalStatus final_status) {
69 DCHECK_NE(FINAL_STATUS_USED, final_status);
70 DCHECK(final_status >= 0 && final_status < FINAL_STATUS_MAX);
71
72 if (!IsPrerenderingOnIOThread(child_id, route_id))
73 return false;
74 return TryCancel(child_id, route_id, final_status);
75 }
76
77 bool PrerenderTracker::IsPrerenderingOnIOThread(int child_id,
78 int route_id) const {
79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
80
81 ChildRouteIdPair child_route_id_pair(child_id, route_id);
82 return possibly_prerendering_io_thread_set_.end() !=
83 possibly_prerendering_io_thread_set_.find(child_route_id_pair);
84 }
85
86 bool PrerenderTracker::GetFinalStatus(int child_id, int route_id,
87 FinalStatus* final_status) const {
88 ChildRouteIdPair child_route_id_pair(child_id, route_id);
89
90 base::AutoLock lock(final_status_map_lock_);
91 FinalStatusMap::const_iterator final_status_it =
92 final_status_map_.find(child_route_id_pair);
93 if (final_status_map_.end() == final_status_map_.find(child_route_id_pair))
94 return false;
95 *final_status = final_status_it->second.final_status;
96 return true;
97 }
98
99 void PrerenderTracker::OnPrerenderingStarted(
100 int child_id, int route_id, PrerenderManager* prerender_manager) {
101 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
102 DCHECK_GE(child_id, 0);
103 DCHECK_GE(route_id, 0);
104
105 ChildRouteIdPair child_route_id_pair(child_id, route_id);
106
107 // The RenderView should not already be prerendering.
108 DCHECK(final_status_map_.end() ==
109 final_status_map_.find(child_route_id_pair));
110
111 BrowserThread::PostTask(
112 BrowserThread::IO, FROM_HERE,
113 NewRunnableFunction(&AddPrerenderOnIOThreadTask, child_route_id_pair));
114
115 base::AutoLock lock(final_status_map_lock_);
116
117 final_status_map_.insert(
118 std::make_pair(child_route_id_pair, RenderViewInfo(prerender_manager)));
119 }
120
121 void PrerenderTracker::OnPrerenderingFinished(int child_id, int route_id) {
122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
123 DCHECK_GE(child_id, 0);
124 DCHECK_GE(route_id, 0);
125
126 ChildRouteIdPair child_route_id_pair(child_id, route_id);
127
128 BrowserThread::PostTask(
129 BrowserThread::IO, FROM_HERE,
130 NewRunnableFunction(&RemovePrerenderOnIOThreadTask, child_route_id_pair));
131
132 base::AutoLock lock(final_status_map_lock_);
133 size_t num_erased = final_status_map_.erase(child_route_id_pair);
134 DCHECK_EQ(1u, num_erased);
135 }
136
137 PrerenderTracker::PrerenderTracker() {
138 }
139
140 PrerenderTracker::~PrerenderTracker() {
141 }
142
143 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
144 FinalStatus final_status) {
145 DCHECK(final_status >= FINAL_STATUS_USED && final_status < FINAL_STATUS_MAX);
146
147 ChildRouteIdPair child_route_id_pair(child_id, route_id);
148
149 base::AutoLock lock(final_status_map_lock_);
150 FinalStatusMap::iterator final_status_it =
151 final_status_map_.find(child_route_id_pair);
152 if (final_status_it == final_status_map_.end()) {
153 // The RenderView has already been either used or destroyed.
154 return FINAL_STATUS_MAX;
155 }
156
157 if (final_status_it->second.final_status == FINAL_STATUS_MAX) {
158 final_status_it->second.final_status = final_status;
159 if (final_status != FINAL_STATUS_USED) {
160 BrowserThread::PostTask(
161 BrowserThread::UI, FROM_HERE,
162 NewRunnableFunction(&DestroyPreloadForRenderView,
163 final_status_it->second.prerender_manager,
164 child_id,
165 route_id,
166 final_status));
167 }
168 }
169 return final_status_it->second.final_status;
170 }
171
172 void PrerenderTracker::AddPrerenderOnIOThread(
173 const ChildRouteIdPair& child_route_id_pair) {
174 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
175 DCHECK(!IsPrerenderingOnIOThread(child_route_id_pair.first,
176 child_route_id_pair.second));
177
178 possibly_prerendering_io_thread_set_.insert(child_route_id_pair);
179 }
180
181 void PrerenderTracker::RemovePrerenderOnIOThread(
182 const ChildRouteIdPair& child_route_id_pair) {
183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
184 DCHECK(IsPrerenderingOnIOThread(child_route_id_pair.first,
185 child_route_id_pair.second));
186
187 possibly_prerendering_io_thread_set_.erase(child_route_id_pair);
188 }
189
190 // static
191 void PrerenderTracker::AddPrerenderOnIOThreadTask(
192 const ChildRouteIdPair& child_route_id_pair) {
193 GetInstance()->AddPrerenderOnIOThread(child_route_id_pair);
194 }
195
196 // static
197 void PrerenderTracker::RemovePrerenderOnIOThreadTask(
198 const ChildRouteIdPair& child_route_id_pair) {
199 GetInstance()->RemovePrerenderOnIOThread(child_route_id_pair);
200 }
201
202 } // namespace prerender
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698