Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / prerender / prerender_tracker.cc
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.
4
5 #include "chrome/browser/prerender/prerender_tracker.h"
6
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"
14
15 using content::BrowserThread;
16
17 namespace prerender {
18
19 PrerenderTracker::PrerenderTracker() {
20   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
21 }
22
23 PrerenderTracker::~PrerenderTracker() {
24 }
25
26 bool PrerenderTracker::IsPendingSwapRequestOnIOThread(
27     int render_process_id, int render_frame_id, const GURL& url) const {
28   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
29
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);
35 }
36
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));
43
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;
53 }
54
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);
63 }
64
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();
78   }
79   pending_swap_throttle_map_.erase(render_frame_route_id_pair);
80 }
81
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));
89 }
90
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));
99 }
100
101 PrerenderTracker::PendingSwapThrottleData::PendingSwapThrottleData(
102     const GURL& swap_url)
103     : url(swap_url) {
104 }
105
106 PrerenderTracker::PendingSwapThrottleData::~PendingSwapThrottleData() {
107 }
108
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);
115
116   if (it == prerender_cookie_store_map_.end())
117     return NULL;
118
119   return it->second;
120 }
121
122 void PrerenderTracker::OnCookieChangedForURL(
123     int process_id,
124     net::CookieMonster* cookie_monster,
125     const GURL& url) {
126   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
127
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;
133
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);
141   }
142 }
143
144 void PrerenderTracker::RemovePrerenderCookieStoreOnIOThread(int process_id,
145                                                             bool was_swapped) {
146   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
147
148   PrerenderCookieStoreMap::iterator it =
149       prerender_cookie_store_map_.find(process_id);
150
151   if (it == prerender_cookie_store_map_.end())
152     return;
153
154   std::vector<GURL> cookie_change_urls;
155   if (was_swapped)
156     it->second->ApplyChanges(&cookie_change_urls);
157
158   scoped_refptr<net::CookieMonster> cookie_monster(
159       it->second->default_cookie_monster());
160
161   prerender_cookie_store_map_.erase(it);
162
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);
170   }
171 }
172
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);
191 }
192
193 }  // namespace prerender