blob: ff452564c4d2b159dc68d4754c0cae5c07de1158 [file] [log] [blame]
[email protected]f4dda4822012-02-17 20:03:071// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]28a05f3a2011-05-20 15:05:082// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]28a05f3a2011-05-20 15:05:085#include "chrome/browser/prerender/prerender_tracker.h"
[email protected]1459fb62011-05-25 19:03:276
[email protected]bbe3d5ec2011-10-10 17:07:217#include "base/bind.h"
[email protected]1459fb62011-05-25 19:03:278#include "base/logging.h"
9#include "chrome/browser/browser_process.h"
10#include "chrome/browser/prerender/prerender_manager.h"
[email protected]c38831a12011-10-28 12:44:4911#include "content/public/browser/browser_thread.h"
[email protected]9c1662b2012-03-06 15:44:3312#include "content/public/browser/render_view_host.h"
[email protected]ce967862012-02-09 22:47:0513#include "content/public/browser/resource_context.h"
[email protected]1459fb62011-05-25 19:03:2714#include "net/base/load_flags.h"
[email protected]28a05f3a2011-05-20 15:05:0815
[email protected]631bb742011-11-02 11:29:3916using content::BrowserThread;
[email protected]eaabba22012-03-07 15:02:1117using content::RenderViewHost;
[email protected]631bb742011-11-02 11:29:3918
[email protected]28a05f3a2011-05-20 15:05:0819namespace prerender {
20
[email protected]92e0a612011-05-30 21:37:0021namespace {
22
[email protected]dcee2a32011-06-28 19:21:5123void 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
[email protected]92e0a612011-05-30 21:37:0037} // namespace
38
[email protected]28a05f3a2011-05-20 15:05:0839struct RenderViewInfo {
40 explicit RenderViewInfo(PrerenderManager* prerender_manager)
41 : final_status(FINAL_STATUS_MAX),
42 prerender_manager(prerender_manager->AsWeakPtr()) {
43 }
[email protected]1459fb62011-05-25 19:03:2744 ~RenderViewInfo() {}
[email protected]28a05f3a2011-05-20 15:05:0845
46 FinalStatus final_status;
47 base::WeakPtr<PrerenderManager> prerender_manager;
48};
49
[email protected]1459fb62011-05-25 19:03:2750PrerenderTracker::PrerenderTracker() {
[email protected]ac4f4682012-12-08 22:39:2651 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]1459fb62011-05-25 19:03:2752}
53
54PrerenderTracker::~PrerenderTracker() {
[email protected]ac4f4682012-12-08 22:39:2655 DCHECK(final_status_map_.empty());
[email protected]28a05f3a2011-05-20 15:05:0856}
57
58bool PrerenderTracker::TryUse(int child_id, int route_id) {
[email protected]ac4f4682012-12-08 22:39:2659 DCHECK(CalledOnValidThread());
[email protected]33bb16e2011-05-23 21:27:5860 return SetFinalStatus(child_id, route_id, FINAL_STATUS_USED, NULL);
[email protected]28a05f3a2011-05-20 15:05:0861}
62
63bool 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
[email protected]33bb16e2011-05-23 21:27:5870 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;
[email protected]28a05f3a2011-05-20 15:05:0874}
75
76bool PrerenderTracker::TryCancelOnIOThread(
77 int child_id,
78 int route_id,
79 FinalStatus final_status) {
80 DCHECK_NE(FINAL_STATUS_USED, final_status);
[email protected]ac4f4682012-12-08 22:39:2681 DCHECK_LE(0, final_status);
82 DCHECK_GT(FINAL_STATUS_MAX, final_status);
[email protected]28a05f3a2011-05-20 15:05:0883
84 if (!IsPrerenderingOnIOThread(child_id, route_id))
85 return false;
86 return TryCancel(child_id, route_id, final_status);
87}
88
[email protected]28a05f3a2011-05-20 15:05:0889bool 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);
[email protected]ac4f4682012-12-08 22:39:2696 if (final_status_it == final_status_map_.end())
[email protected]28a05f3a2011-05-20 15:05:0897 return false;
98 *final_status = final_status_it->second.final_status;
99 return true;
100}
101
[email protected]ac4f4682012-12-08 22:39:26102void PrerenderTracker::OnPrerenderStart(
103 PrerenderContents* prerender_contents) {
104 DCHECK(CalledOnValidThread());
105 int child_id, route_id;
106 bool got_child_id = prerender_contents->GetChildId(&child_id);
107 DCHECK(got_child_id);
108 bool got_route_id = prerender_contents->GetRouteId(&route_id);
109 DCHECK(got_route_id);
[email protected]28a05f3a2011-05-20 15:05:08110
111 ChildRouteIdPair child_route_id_pair(child_id, route_id);
112
[email protected]28a05f3a2011-05-20 15:05:08113 BrowserThread::PostTask(
114 BrowserThread::IO, FROM_HERE,
[email protected]bbe3d5ec2011-10-10 17:07:21115 base::Bind(&AddPrerenderOnIOThreadTask, child_route_id_pair));
[email protected]28a05f3a2011-05-20 15:05:08116
117 base::AutoLock lock(final_status_map_lock_);
[email protected]ac4f4682012-12-08 22:39:26118 // The RenderView should not already be prerendering.
119 DCHECK_EQ(0u, final_status_map_.count(child_route_id_pair));
[email protected]28a05f3a2011-05-20 15:05:08120
121 final_status_map_.insert(
[email protected]ac4f4682012-12-08 22:39:26122 std::make_pair(child_route_id_pair,
123 RenderViewInfo(prerender_contents->prerender_manager())));
[email protected]28a05f3a2011-05-20 15:05:08124}
125
[email protected]ac4f4682012-12-08 22:39:26126void PrerenderTracker::OnPrerenderStop(
127 PrerenderContents* prerender_contents) {
128 DCHECK(CalledOnValidThread());
129 int child_id, route_id;
130 bool got_child_id = prerender_contents->GetChildId(&child_id);
131 DCHECK(got_child_id);
132 bool got_route_id = prerender_contents->GetRouteId(&route_id);
133 DCHECK(got_route_id);
[email protected]28a05f3a2011-05-20 15:05:08134
135 ChildRouteIdPair child_route_id_pair(child_id, route_id);
136
137 BrowserThread::PostTask(
138 BrowserThread::IO, FROM_HERE,
[email protected]bbe3d5ec2011-10-10 17:07:21139 base::Bind(&RemovePrerenderOnIOThreadTask, child_route_id_pair));
[email protected]28a05f3a2011-05-20 15:05:08140
141 base::AutoLock lock(final_status_map_lock_);
142 size_t num_erased = final_status_map_.erase(child_route_id_pair);
143 DCHECK_EQ(1u, num_erased);
144}
145
[email protected]33bb16e2011-05-23 21:27:58146bool PrerenderTracker::SetFinalStatus(int child_id, int route_id,
147 FinalStatus desired_final_status,
148 FinalStatus* actual_final_status) {
149 DCHECK(desired_final_status >= FINAL_STATUS_USED &&
150 desired_final_status < FINAL_STATUS_MAX);
[email protected]28a05f3a2011-05-20 15:05:08151
152 ChildRouteIdPair child_route_id_pair(child_id, route_id);
153
154 base::AutoLock lock(final_status_map_lock_);
155 FinalStatusMap::iterator final_status_it =
156 final_status_map_.find(child_route_id_pair);
157 if (final_status_it == final_status_map_.end()) {
158 // The RenderView has already been either used or destroyed.
[email protected]33bb16e2011-05-23 21:27:58159 if (actual_final_status)
160 *actual_final_status = FINAL_STATUS_MAX;
161 return false;
[email protected]28a05f3a2011-05-20 15:05:08162 }
163
164 if (final_status_it->second.final_status == FINAL_STATUS_MAX) {
[email protected]33bb16e2011-05-23 21:27:58165 final_status_it->second.final_status = desired_final_status;
166 if (desired_final_status != FINAL_STATUS_USED) {
[email protected]28a05f3a2011-05-20 15:05:08167 BrowserThread::PostTask(
168 BrowserThread::UI, FROM_HERE,
[email protected]bbe3d5ec2011-10-10 17:07:21169 base::Bind(&DestroyPrerenderForRenderViewOnUI,
170 final_status_it->second.prerender_manager, child_id,
171 route_id, desired_final_status));
[email protected]28a05f3a2011-05-20 15:05:08172 }
[email protected]33bb16e2011-05-23 21:27:58173
174 if (actual_final_status)
175 *actual_final_status = desired_final_status;
176 return true;
[email protected]28a05f3a2011-05-20 15:05:08177 }
[email protected]33bb16e2011-05-23 21:27:58178
179 if (actual_final_status)
180 *actual_final_status = final_status_it->second.final_status;
181 return false;
[email protected]28a05f3a2011-05-20 15:05:08182}
183
[email protected]1459fb62011-05-25 19:03:27184bool PrerenderTracker::IsPrerenderingOnIOThread(int child_id,
185 int route_id) const {
186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
187
188 ChildRouteIdPair child_route_id_pair(child_id, route_id);
[email protected]ac4f4682012-12-08 22:39:26189 return possibly_prerendering_io_thread_set_.count(child_route_id_pair) > 0;
[email protected]1459fb62011-05-25 19:03:27190}
191
[email protected]1f291cd2013-09-25 22:05:14192void PrerenderTracker::UpdatePrerenderStateForTransfer(int old_child_id,
193 int old_route_id,
194 int new_child_id,
195 int new_route_id) {
196 ChildRouteIdPair old_pair(old_child_id, old_route_id);
197 ChildRouteIdPair new_pair(new_child_id, new_route_id);
198
199 RemovePrerenderOnIOThread(old_pair);
200 AddPrerenderOnIOThread(new_pair);
201}
202
[email protected]28a05f3a2011-05-20 15:05:08203void PrerenderTracker::AddPrerenderOnIOThread(
204 const ChildRouteIdPair& child_route_id_pair) {
205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
206 DCHECK(!IsPrerenderingOnIOThread(child_route_id_pair.first,
207 child_route_id_pair.second));
208
209 possibly_prerendering_io_thread_set_.insert(child_route_id_pair);
210}
211
212void PrerenderTracker::RemovePrerenderOnIOThread(
213 const ChildRouteIdPair& child_route_id_pair) {
214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
215 DCHECK(IsPrerenderingOnIOThread(child_route_id_pair.first,
216 child_route_id_pair.second));
217
218 possibly_prerendering_io_thread_set_.erase(child_route_id_pair);
219}
220
221// static
[email protected]92e0a612011-05-30 21:37:00222PrerenderTracker* PrerenderTracker::GetDefault() {
223 return g_browser_process->prerender_tracker();
224}
225
226// static
[email protected]28a05f3a2011-05-20 15:05:08227void PrerenderTracker::AddPrerenderOnIOThreadTask(
228 const ChildRouteIdPair& child_route_id_pair) {
[email protected]92e0a612011-05-30 21:37:00229 GetDefault()->AddPrerenderOnIOThread(child_route_id_pair);
[email protected]28a05f3a2011-05-20 15:05:08230}
231
232// static
233void PrerenderTracker::RemovePrerenderOnIOThreadTask(
234 const ChildRouteIdPair& child_route_id_pair) {
[email protected]92e0a612011-05-30 21:37:00235 GetDefault()->RemovePrerenderOnIOThread(child_route_id_pair);
[email protected]28a05f3a2011-05-20 15:05:08236}
237
238} // namespace prerender