OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/prerender/prerender_tracker.h" | 5 #include "chrome/browser/prerender/prerender_tracker.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "chrome/browser/browser_process.h" | 9 #include "chrome/browser/browser_process.h" |
10 #include "chrome/browser/prerender/prerender_manager.h" | 10 #include "chrome/browser/prerender/prerender_manager.h" |
11 #include "chrome/browser/prerender/prerender_pending_swap_throttle.h" | 11 #include "chrome/browser/prerender/prerender_pending_swap_throttle.h" |
12 #include "chrome/browser/prerender/prerender_resource_throttle.h" | 12 #include "chrome/browser/prerender/prerender_resource_throttle.h" |
13 #include "content/public/browser/browser_thread.h" | 13 #include "content/public/browser/browser_thread.h" |
14 #include "content/public/browser/resource_context.h" | 14 #include "content/public/browser/resource_context.h" |
15 #include "net/base/load_flags.h" | 15 #include "net/base/load_flags.h" |
16 | 16 |
17 using content::BrowserThread; | 17 using content::BrowserThread; |
18 | 18 |
19 namespace prerender { | 19 namespace prerender { |
20 | 20 |
21 namespace { | |
22 | |
23 void DestroyPrerenderForRenderViewOnUI( | |
24 const base::WeakPtr<PrerenderManager>& prerender_manager_weak_ptr, | |
25 int render_process_id, | |
26 int render_view_id, | |
27 FinalStatus final_status) { | |
28 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
29 PrerenderManager* prerender_manager = prerender_manager_weak_ptr.get(); | |
30 if (!prerender_manager) | |
31 return; | |
32 | |
33 prerender_manager->DestroyPrerenderForRenderView( | |
34 render_process_id, render_view_id, final_status); | |
35 } | |
36 | |
37 } // namespace | |
38 | |
39 struct RenderViewInfo { | 21 struct RenderViewInfo { |
40 explicit RenderViewInfo(PrerenderManager* prerender_manager) | 22 explicit RenderViewInfo(PrerenderManager* prerender_manager) |
41 : final_status(FINAL_STATUS_MAX), | 23 : final_status(FINAL_STATUS_MAX), |
42 prerender_manager(prerender_manager->AsWeakPtr()) { | 24 prerender_manager(prerender_manager->AsWeakPtr()) { |
43 } | 25 } |
44 ~RenderViewInfo() {} | 26 ~RenderViewInfo() {} |
45 | 27 |
46 FinalStatus final_status; | 28 FinalStatus final_status; |
47 base::WeakPtr<PrerenderManager> prerender_manager; | 29 base::WeakPtr<PrerenderManager> prerender_manager; |
48 }; | 30 }; |
49 | 31 |
50 PrerenderTracker::PrerenderTracker() { | 32 PrerenderTracker::PrerenderTracker() { |
51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 33 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
52 } | 34 } |
53 | 35 |
54 PrerenderTracker::~PrerenderTracker() { | 36 PrerenderTracker::~PrerenderTracker() { |
55 DCHECK(final_status_map_.empty()); | |
56 } | |
57 | |
58 bool PrerenderTracker::TryUse(int child_id, int route_id) { | |
59 DCHECK(CalledOnValidThread()); | |
60 return SetFinalStatus(child_id, route_id, FINAL_STATUS_USED, NULL); | |
61 } | |
62 | |
63 bool PrerenderTracker::TryCancel( | |
64 int child_id, | |
65 int route_id, | |
66 FinalStatus final_status) { | |
67 DCHECK_NE(FINAL_STATUS_USED, final_status); | |
68 DCHECK(final_status >= 0 && final_status < FINAL_STATUS_MAX); | |
69 | |
70 FinalStatus actual_final_status; | |
71 SetFinalStatus(child_id, route_id, final_status, &actual_final_status); | |
72 return actual_final_status != FINAL_STATUS_USED && | |
73 actual_final_status != FINAL_STATUS_MAX; | |
74 } | |
75 | |
76 bool PrerenderTracker::TryCancelOnIOThread( | |
77 int child_id, | |
78 int route_id, | |
79 FinalStatus final_status) { | |
80 DCHECK_NE(FINAL_STATUS_USED, final_status); | |
81 DCHECK_LE(0, final_status); | |
82 DCHECK_GT(FINAL_STATUS_MAX, final_status); | |
83 | |
84 if (!IsPrerenderingOnIOThread(child_id, route_id)) | |
85 return false; | |
86 return TryCancel(child_id, route_id, final_status); | |
87 } | |
88 | |
89 bool PrerenderTracker::GetFinalStatus(int child_id, int route_id, | |
90 FinalStatus* final_status) const { | |
91 ChildRouteIdPair child_route_id_pair(child_id, route_id); | |
92 | |
93 base::AutoLock lock(final_status_map_lock_); | |
94 FinalStatusMap::const_iterator final_status_it = | |
95 final_status_map_.find(child_route_id_pair); | |
96 if (final_status_it == final_status_map_.end()) | |
97 return false; | |
98 *final_status = final_status_it->second.final_status; | |
99 return true; | |
100 } | 37 } |
101 | 38 |
102 void PrerenderTracker::OnPrerenderStart( | 39 void PrerenderTracker::OnPrerenderStart( |
103 PrerenderContents* prerender_contents) { | 40 PrerenderContents* prerender_contents) { |
104 DCHECK(CalledOnValidThread()); | 41 DCHECK(CalledOnValidThread()); |
105 int child_id, route_id; | 42 int child_id, route_id; |
106 bool got_child_id = prerender_contents->GetChildId(&child_id); | 43 bool got_child_id = prerender_contents->GetChildId(&child_id); |
107 DCHECK(got_child_id); | 44 DCHECK(got_child_id); |
108 bool got_route_id = prerender_contents->GetRouteId(&route_id); | 45 bool got_route_id = prerender_contents->GetRouteId(&route_id); |
109 DCHECK(got_route_id); | 46 DCHECK(got_route_id); |
110 | 47 |
111 ChildRouteIdPair child_route_id_pair(child_id, route_id); | 48 ChildRouteIdPair child_route_id_pair(child_id, route_id); |
112 | 49 |
113 BrowserThread::PostTask( | 50 BrowserThread::PostTask( |
114 BrowserThread::IO, FROM_HERE, | 51 BrowserThread::IO, FROM_HERE, |
115 base::Bind(&AddPrerenderOnIOThreadTask, child_route_id_pair)); | 52 base::Bind(&AddPrerenderOnIOThreadTask, child_route_id_pair)); |
116 | |
117 base::AutoLock lock(final_status_map_lock_); | |
118 // The RenderView should not already be prerendering. | |
119 DCHECK_EQ(0u, final_status_map_.count(child_route_id_pair)); | |
120 | |
121 final_status_map_.insert( | |
122 std::make_pair(child_route_id_pair, | |
123 RenderViewInfo(prerender_contents->prerender_manager()))); | |
124 } | 53 } |
125 | 54 |
126 void PrerenderTracker::OnPrerenderStop( | 55 void PrerenderTracker::OnPrerenderStop( |
127 PrerenderContents* prerender_contents) { | 56 PrerenderContents* prerender_contents) { |
128 DCHECK(CalledOnValidThread()); | 57 DCHECK(CalledOnValidThread()); |
129 int child_id, route_id; | 58 int child_id, route_id; |
130 bool got_child_id = prerender_contents->GetChildId(&child_id); | 59 bool got_child_id = prerender_contents->GetChildId(&child_id); |
131 DCHECK(got_child_id); | 60 DCHECK(got_child_id); |
132 bool got_route_id = prerender_contents->GetRouteId(&route_id); | 61 bool got_route_id = prerender_contents->GetRouteId(&route_id); |
133 DCHECK(got_route_id); | 62 DCHECK(got_route_id); |
134 | 63 |
135 ChildRouteIdPair child_route_id_pair(child_id, route_id); | 64 ChildRouteIdPair child_route_id_pair(child_id, route_id); |
136 | 65 |
137 DCHECK_LT(prerender_contents->final_status(), FINAL_STATUS_MAX); | 66 DCHECK_LT(prerender_contents->final_status(), FINAL_STATUS_MAX); |
138 BrowserThread::PostTask( | 67 BrowserThread::PostTask( |
139 BrowserThread::IO, FROM_HERE, | 68 BrowserThread::IO, FROM_HERE, |
140 base::Bind(&RemovePrerenderOnIOThreadTask, child_route_id_pair, | 69 base::Bind(&RemovePrerenderOnIOThreadTask, child_route_id_pair, |
141 prerender_contents->final_status())); | 70 prerender_contents->final_status())); |
142 | |
143 base::AutoLock lock(final_status_map_lock_); | |
144 size_t num_erased = final_status_map_.erase(child_route_id_pair); | |
145 DCHECK_EQ(1u, num_erased); | |
146 } | |
147 | |
148 bool PrerenderTracker::SetFinalStatus(int child_id, int route_id, | |
149 FinalStatus desired_final_status, | |
150 FinalStatus* actual_final_status) { | |
151 DCHECK(desired_final_status >= FINAL_STATUS_USED && | |
152 desired_final_status < FINAL_STATUS_MAX); | |
153 | |
154 ChildRouteIdPair child_route_id_pair(child_id, route_id); | |
155 | |
156 base::AutoLock lock(final_status_map_lock_); | |
157 FinalStatusMap::iterator final_status_it = | |
158 final_status_map_.find(child_route_id_pair); | |
159 if (final_status_it == final_status_map_.end()) { | |
160 // The RenderView has already been either used or destroyed. | |
161 if (actual_final_status) | |
162 *actual_final_status = FINAL_STATUS_MAX; | |
163 return false; | |
164 } | |
165 | |
166 if (final_status_it->second.final_status == FINAL_STATUS_MAX) { | |
167 final_status_it->second.final_status = desired_final_status; | |
168 if (desired_final_status != FINAL_STATUS_USED) { | |
169 BrowserThread::PostTask( | |
170 BrowserThread::UI, FROM_HERE, | |
171 base::Bind(&DestroyPrerenderForRenderViewOnUI, | |
172 final_status_it->second.prerender_manager, child_id, | |
173 route_id, desired_final_status)); | |
174 } | |
175 | |
176 if (actual_final_status) | |
177 *actual_final_status = desired_final_status; | |
178 return true; | |
179 } | |
180 | |
181 if (actual_final_status) | |
182 *actual_final_status = final_status_it->second.final_status; | |
183 return false; | |
184 } | 71 } |
185 | 72 |
186 bool PrerenderTracker::IsPrerenderingOnIOThread(int child_id, | 73 bool PrerenderTracker::IsPrerenderingOnIOThread(int child_id, |
187 int route_id) const { | 74 int route_id) const { |
188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
189 | 76 |
190 ChildRouteIdPair child_route_id_pair(child_id, route_id); | 77 ChildRouteIdPair child_route_id_pair(child_id, route_id); |
191 return resource_throttle_io_thread_map_.count(child_route_id_pair) > 0; | 78 return resource_throttle_io_thread_map_.count(child_route_id_pair) > 0; |
192 } | 79 } |
193 | 80 |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 | 233 |
347 // static | 234 // static |
348 void PrerenderTracker::RemovePrerenderPendingSwapOnIOThreadTask( | 235 void PrerenderTracker::RemovePrerenderPendingSwapOnIOThreadTask( |
349 const ChildRouteIdPair& child_route_id_pair, | 236 const ChildRouteIdPair& child_route_id_pair, |
350 bool swap_successful) { | 237 bool swap_successful) { |
351 GetDefault()->RemovePrerenderPendingSwapOnIOThread(child_route_id_pair, | 238 GetDefault()->RemovePrerenderPendingSwapOnIOThread(child_route_id_pair, |
352 swap_successful); | 239 swap_successful); |
353 } | 240 } |
354 | 241 |
355 } // namespace prerender | 242 } // namespace prerender |
OLD | NEW |