Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / browser / prerender / prerender_tracker.cc
blobd362e838afc02648193e2682f359b09ea12aa8c2
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"
7 #include "base/bind.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;
17 namespace prerender {
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,
39 int render_frame_id,
40 const GURL& url,
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())
50 return;
51 CHECK(!it->second.throttle);
52 it->second.throttle = throttle;
55 void PrerenderTracker::AddPrerenderPendingSwapOnIOThread(
56 const ChildRouteIdPair& render_frame_route_id_pair,
57 const GURL& url) {
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) {
74 if (swap_successful)
75 it->second.throttle->Cancel();
76 else
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,
84 const GURL& url) {
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,
98 swap_successful));
101 PrerenderTracker::PendingSwapThrottleData::PendingSwapThrottleData(
102 const GURL& swap_url)
103 : url(swap_url) {
106 PrerenderTracker::PendingSwapThrottleData::~PendingSwapThrottleData() {
109 scoped_refptr<PrerenderCookieStore>
110 PrerenderTracker::GetPrerenderCookieStoreForRenderProcess(
111 int process_id) {
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())
117 return NULL;
119 return it->second;
122 void PrerenderTracker::OnCookieChangedForURL(
123 int process_id,
124 net::CookieMonster* cookie_monster,
125 const GURL& url) {
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))
132 return;
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();
139 ++it) {
140 it->second->OnCookieChangedForURL(cookie_monster, url);
144 void PrerenderTracker::RemovePrerenderCookieStoreOnIOThread(int process_id,
145 bool was_swapped) {
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())
152 return;
154 std::vector<GURL> cookie_change_urls;
155 if (was_swapped)
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
165 // will be aborted.
166 for (std::vector<GURL>::const_iterator url_it = cookie_change_urls.begin();
167 url_it != cookie_change_urls.end();
168 ++url_it) {
169 OnCookieChangedForURL(process_id, cookie_monster.get(), *url_it);
173 void PrerenderTracker::AddPrerenderCookieStoreOnIOThread(
174 int process_id,
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()->
181 GetCookieMonster();
182 DCHECK(cookie_monster != NULL);
183 bool exists = (prerender_cookie_store_map_.find(process_id) !=
184 prerender_cookie_store_map_.end());
185 DCHECK(!exists);
186 if (exists)
187 return;
188 prerender_cookie_store_map_[process_id] =
189 new PrerenderCookieStore(make_scoped_refptr(cookie_monster),
190 cookie_conflict_cb);
193 } // namespace prerender