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

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: Response to Dominic's comments, part 3 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 FinalStatus final_status;
33 base::WeakPtr<PrerenderManager> prerender_manager;
34 };
35
36 // static
37 PrerenderTracker* PrerenderTracker::GetInstance() {
38 return Singleton<PrerenderTracker>::get();
39 }
40
41 bool PrerenderTracker::TryUse(int child_id, int route_id) {
42 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
43
44 FinalStatus final_status = SetFinalStatus(child_id, route_id,
45 FINAL_STATUS_USED);
46 return final_status == FINAL_STATUS_USED;
47 }
48
49 bool PrerenderTracker::TryCancel(
50 int child_id,
51 int route_id,
52 FinalStatus final_status) {
53 DCHECK_NE(FINAL_STATUS_USED, final_status);
54 DCHECK(final_status >= 0 && final_status < FINAL_STATUS_MAX);
55
56 final_status = SetFinalStatus(child_id, route_id, final_status);
57 return final_status != FINAL_STATUS_USED && final_status != FINAL_STATUS_MAX;
58 }
59
60 bool PrerenderTracker::TryCancelOnIOThread(
61 int child_id,
62 int route_id,
63 FinalStatus final_status) {
64 DCHECK_NE(FINAL_STATUS_USED, final_status);
65 DCHECK(final_status >= 0 && final_status < FINAL_STATUS_MAX);
66
67 if (!IsPrerenderingOnIOThread(child_id, route_id))
68 return false;
69 return TryCancel(child_id, route_id, final_status);
70 }
71
72 bool PrerenderTracker::IsPrerenderingOnIOThread(int child_id, int route_id) {
73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
74
75 ChildRouteIdPair child_route_id_pair(child_id, route_id);
76 return possibly_prerendering_io_thread_set_.end() !=
77 possibly_prerendering_io_thread_set_.find(child_route_id_pair);
78 }
79
80 bool PrerenderTracker::GetFinalStatus(int child_id, int route_id,
81 FinalStatus* final_status) {
82 ChildRouteIdPair child_route_id_pair(child_id, route_id);
83
84 base::AutoLock lock(final_status_map_lock_);
85 FinalStatusMap::iterator final_status_it =
86 final_status_map_.find(child_route_id_pair);
87 if (final_status_map_.end() == final_status_map_.find(child_route_id_pair))
88 return false;
89 *final_status = final_status_it->second.final_status;
90 return true;
91 }
92
93 void PrerenderTracker::OnPrerenderingStarted(
94 int child_id, int route_id, PrerenderManager* prerender_manager) {
95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
96 DCHECK_GE(child_id, 0);
97 DCHECK_GE(route_id, 0);
98
99 ChildRouteIdPair child_route_id_pair(child_id, route_id);
100
101 // The RenderView should not already be prerendering.
102 DCHECK(final_status_map_.end() ==
103 final_status_map_.find(child_route_id_pair));
104
105 BrowserThread::PostTask(
106 BrowserThread::IO, FROM_HERE,
107 NewRunnableFunction(&AddPrerenderOnIOThreadTask, child_route_id_pair));
108
109 base::AutoLock lock(final_status_map_lock_);
110
111 RenderViewInfo render_view_info;
112 render_view_info.final_status = FINAL_STATUS_MAX;
113 render_view_info.prerender_manager = prerender_manager->AsWeakPtr();
114 final_status_map_[child_route_id_pair] = render_view_info;
115 }
116
117 void PrerenderTracker::OnPrerenderingFinished(int child_id, int route_id) {
118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
119 DCHECK_GE(child_id, 0);
120 DCHECK_GE(route_id, 0);
121
122 ChildRouteIdPair child_route_id_pair(child_id, route_id);
123
124 BrowserThread::PostTask(
125 BrowserThread::IO, FROM_HERE,
126 NewRunnableFunction(&RemovePrerenderOnIOThreadTask, child_route_id_pair));
127
128 base::AutoLock lock(final_status_map_lock_);
129 size_t num_erased = final_status_map_.erase(child_route_id_pair);
130 DCHECK_EQ(1u, num_erased);
131 }
132
133 PrerenderTracker::PrerenderTracker() {
134 }
135
136 PrerenderTracker::~PrerenderTracker() {
137 }
138
139 FinalStatus PrerenderTracker::SetFinalStatus(int child_id, int route_id,
140 FinalStatus final_status) {
141 DCHECK(final_status >= FINAL_STATUS_USED && final_status < FINAL_STATUS_MAX);
142
143 ChildRouteIdPair child_route_id_pair(child_id, route_id);
144
145 base::AutoLock lock(final_status_map_lock_);
146 FinalStatusMap::iterator final_status_it =
147 final_status_map_.find(child_route_id_pair);
148 if (final_status_it == final_status_map_.end()) {
149 // The RenderView has already been either used or destroyed.
150 return FINAL_STATUS_MAX;
151 }
152
153 if (final_status_it->second.final_status == FINAL_STATUS_MAX) {
154 final_status_it->second.final_status = final_status;
155 if (final_status != FINAL_STATUS_USED) {
156 BrowserThread::PostTask(
157 BrowserThread::UI, FROM_HERE,
158 NewRunnableFunction(&DestroyPreloadForRenderView,
159 final_status_it->second.prerender_manager,
160 child_id,
161 route_id,
162 final_status));
163 }
164 }
165 return final_status_it->second.final_status;
166 }
167
168 void PrerenderTracker::AddPrerenderOnIOThread(
169 const ChildRouteIdPair& child_route_id_pair) {
170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
171 DCHECK(!IsPrerenderingOnIOThread(child_route_id_pair.first,
172 child_route_id_pair.second));
173
174 possibly_prerendering_io_thread_set_.insert(child_route_id_pair);
175 }
176
177 void PrerenderTracker::RemovePrerenderOnIOThread(
178 const ChildRouteIdPair& child_route_id_pair) {
179 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
180 DCHECK(IsPrerenderingOnIOThread(child_route_id_pair.first,
181 child_route_id_pair.second));
182
183 possibly_prerendering_io_thread_set_.erase(child_route_id_pair);
184 }
185
186 // static
187 void PrerenderTracker::AddPrerenderOnIOThreadTask(
dominich 2011/05/19 17:20:21 Take these out of the class and add to an anonymou
188 const ChildRouteIdPair& child_route_id_pair) {
189 GetInstance()->AddPrerenderOnIOThread(child_route_id_pair);
190 }
191
192 // static
193 void PrerenderTracker::RemovePrerenderOnIOThreadTask(
dominich 2011/05/19 17:20:21 See above comment re AddPrerenderOnIOThreadTask.
194 const ChildRouteIdPair& child_route_id_pair) {
195 GetInstance()->RemovePrerenderOnIOThread(child_route_id_pair);
196 }
197
198 } // namespace prerender
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698