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
3 // found in the LICENSE file.
5 #include "chrome/browser/prerender/prerender_tracker.h"
8 #include "base/logging.h"
9 #include "chrome/browser/prerender/prerender_pending_swap_throttle.h"
10 #include "content/public/browser/browser_thread.h"
11 #include "content/public/browser/render_process_host.h"
12 #include "net/url_request/url_request_context.h"
13 #include "net/url_request/url_request_context_getter.h"
15 using content::BrowserThread
;
19 PrerenderTracker::PrerenderTracker() {
20 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
23 PrerenderTracker::~PrerenderTracker() {
26 bool PrerenderTracker::IsPendingSwapRequestOnIOThread(
27 int render_process_id
, int render_frame_id
, const GURL
& url
) const {
28 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
30 ChildRouteIdPair
render_frame_route_id_pair(
31 render_process_id
, render_frame_id
);
32 PendingSwapThrottleMap::const_iterator it
=
33 pending_swap_throttle_map_
.find(render_frame_route_id_pair
);
34 return (it
!= pending_swap_throttle_map_
.end() && it
->second
.url
== url
);
37 void PrerenderTracker::AddPendingSwapThrottleOnIOThread(
38 int render_process_id
,
41 const base::WeakPtr
<PrerenderPendingSwapThrottle
>& throttle
) {
42 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
44 ChildRouteIdPair
render_frame_route_id_pair(
45 render_process_id
, render_frame_id
);
46 PendingSwapThrottleMap::iterator it
=
47 pending_swap_throttle_map_
.find(render_frame_route_id_pair
);
48 DCHECK(it
!= pending_swap_throttle_map_
.end());
49 if (it
== pending_swap_throttle_map_
.end())
51 CHECK(!it
->second
.throttle
);
52 it
->second
.throttle
= throttle
;
55 void PrerenderTracker::AddPrerenderPendingSwapOnIOThread(
56 const ChildRouteIdPair
& render_frame_route_id_pair
,
58 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
59 std::pair
<PendingSwapThrottleMap::iterator
, bool> insert_result
=
60 pending_swap_throttle_map_
.insert(std::make_pair(
61 render_frame_route_id_pair
, PendingSwapThrottleData(url
)));
62 DCHECK(insert_result
.second
);
65 void PrerenderTracker::RemovePrerenderPendingSwapOnIOThread(
66 const ChildRouteIdPair
& render_frame_route_id_pair
,
67 bool swap_successful
) {
68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
69 PendingSwapThrottleMap::iterator it
=
70 pending_swap_throttle_map_
.find(render_frame_route_id_pair
);
71 DCHECK(it
!= pending_swap_throttle_map_
.end());
72 // Cancel or resume all throttled resources.
73 if (it
->second
.throttle
) {
75 it
->second
.throttle
->Cancel();
77 it
->second
.throttle
->Resume();
79 pending_swap_throttle_map_
.erase(render_frame_route_id_pair
);
82 void PrerenderTracker::AddPrerenderPendingSwap(
83 const ChildRouteIdPair
& render_frame_route_id_pair
,
85 BrowserThread::PostTask(
86 BrowserThread::IO
, FROM_HERE
,
87 base::Bind(&PrerenderTracker::AddPrerenderPendingSwapOnIOThread
,
88 base::Unretained(this), render_frame_route_id_pair
, url
));
91 void PrerenderTracker::RemovePrerenderPendingSwap(
92 const ChildRouteIdPair
& render_frame_route_id_pair
,
93 bool swap_successful
) {
94 BrowserThread::PostTask(
95 BrowserThread::IO
, FROM_HERE
,
96 base::Bind(&PrerenderTracker::RemovePrerenderPendingSwapOnIOThread
,
97 base::Unretained(this), render_frame_route_id_pair
,
101 PrerenderTracker::PendingSwapThrottleData::PendingSwapThrottleData(
102 const GURL
& swap_url
)
106 PrerenderTracker::PendingSwapThrottleData::~PendingSwapThrottleData() {
109 scoped_refptr
<PrerenderCookieStore
>
110 PrerenderTracker::GetPrerenderCookieStoreForRenderProcess(
112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
113 PrerenderCookieStoreMap::const_iterator it
=
114 prerender_cookie_store_map_
.find(process_id
);
116 if (it
== prerender_cookie_store_map_
.end())
122 void PrerenderTracker::OnCookieChangedForURL(
124 net::CookieMonster
* cookie_monster
,
126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
128 // We only care about cookie changes by non-prerender tabs, since only those
129 // get applied to the underlying cookie store. Therefore, if a cookie change
130 // originated from a prerender, there is nothing to do.
131 if (ContainsKey(prerender_cookie_store_map_
, process_id
))
134 // Since the cookie change did not come from a prerender, broadcast it too
135 // all prerenders so that they can be cancelled if there is a conflict.
136 for (PrerenderCookieStoreMap::iterator it
=
137 prerender_cookie_store_map_
.begin();
138 it
!= prerender_cookie_store_map_
.end();
140 it
->second
->OnCookieChangedForURL(cookie_monster
, url
);
144 void PrerenderTracker::RemovePrerenderCookieStoreOnIOThread(int process_id
,
146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
148 PrerenderCookieStoreMap::iterator it
=
149 prerender_cookie_store_map_
.find(process_id
);
151 if (it
== prerender_cookie_store_map_
.end())
154 std::vector
<GURL
> cookie_change_urls
;
156 it
->second
->ApplyChanges(&cookie_change_urls
);
158 scoped_refptr
<net::CookieMonster
> cookie_monster(
159 it
->second
->default_cookie_monster());
161 prerender_cookie_store_map_
.erase(it
);
163 // For each cookie updated by ApplyChanges, we need to call
164 // OnCookieChangedForURL so that any potentially conflicting prerenders
166 for (std::vector
<GURL
>::const_iterator url_it
= cookie_change_urls
.begin();
167 url_it
!= cookie_change_urls
.end();
169 OnCookieChangedForURL(process_id
, cookie_monster
.get(), *url_it
);
173 void PrerenderTracker::AddPrerenderCookieStoreOnIOThread(
175 scoped_refptr
<net::URLRequestContextGetter
> request_context
,
176 const base::Closure
& cookie_conflict_cb
) {
177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
178 DCHECK(request_context
.get() != NULL
);
179 net::CookieMonster
* cookie_monster
=
180 request_context
->GetURLRequestContext()->cookie_store()->
182 DCHECK(cookie_monster
!= NULL
);
183 bool exists
= (prerender_cookie_store_map_
.find(process_id
) !=
184 prerender_cookie_store_map_
.end());
188 prerender_cookie_store_map_
[process_id
] =
189 new PrerenderCookieStore(make_scoped_refptr(cookie_monster
),
193 } // namespace prerender