Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / prerender / prerender_cookie_store.cc
1 // Copyright 2014 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_cookie_store.h"
6
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "content/public/browser/browser_thread.h"
10
11 using content::BrowserThread;
12
13 namespace prerender {
14
15 PrerenderCookieStore::PrerenderCookieStore(
16     scoped_refptr<net::CookieMonster> default_cookie_monster,
17     const base::Closure& cookie_conflict_cb)
18     : in_forwarding_mode_(false),
19       default_cookie_monster_(default_cookie_monster),
20       changes_cookie_monster_(new net::CookieMonster(NULL, NULL)),
21       cookie_conflict_cb_(cookie_conflict_cb),
22       cookie_conflict_(false) {
23   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
24   DCHECK(default_cookie_monster_.get() != NULL);
25   DCHECK(default_cookie_monster_->loaded());
26 }
27
28 PrerenderCookieStore::~PrerenderCookieStore() {
29 }
30
31 void PrerenderCookieStore::SetCookieWithOptionsAsync(
32     const GURL& url,
33     const std::string& cookie_line,
34     const net::CookieOptions& options,
35     const SetCookiesCallback& callback) {
36   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
37
38   CookieOperation op;
39   op.op = COOKIE_OP_SET_COOKIE_WITH_OPTIONS_ASYNC;
40   op.url = url;
41   op.cookie_line = cookie_line;
42   op.options = options;
43
44   GetCookieStoreForCookieOpAndLog(op)->
45       SetCookieWithOptionsAsync(url, cookie_line, options, callback);
46 }
47
48 void PrerenderCookieStore::GetCookiesWithOptionsAsync(
49     const GURL& url,
50     const net::CookieOptions& options,
51     const GetCookiesCallback& callback) {
52   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
53   CookieOperation op;
54   op.op = COOKIE_OP_GET_COOKIES_WITH_OPTIONS_ASYNC;
55   op.url = url;
56   op.options = options;
57
58   GetCookieStoreForCookieOpAndLog(op)->
59       GetCookiesWithOptionsAsync(url, options, callback);
60 }
61
62 void PrerenderCookieStore::GetAllCookiesForURLAsync(
63     const GURL& url,
64     const GetCookieListCallback& callback) {
65   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
66
67   CookieOperation op;
68   op.op = COOKIE_OP_GET_ALL_COOKIES_FOR_URL_ASYNC;
69   op.url = url;
70
71   GetCookieStoreForCookieOpAndLog(op)->GetAllCookiesForURLAsync(url, callback);
72 }
73
74
75 void PrerenderCookieStore::DeleteCookieAsync(const GURL& url,
76                                              const std::string& cookie_name,
77                                              const base::Closure& callback) {
78   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
79
80   CookieOperation op;
81   op.op = COOKIE_OP_DELETE_COOKIE_ASYNC;
82   op.url = url;
83   op.cookie_name = cookie_name;
84
85   GetCookieStoreForCookieOpAndLog(op)->DeleteCookieAsync(url, cookie_name,
86                                                          callback);
87 }
88
89 void PrerenderCookieStore::DeleteAllCreatedBetweenAsync(
90     const base::Time& delete_begin,
91     const base::Time& delete_end,
92     const DeleteCallback& callback) {
93   NOTREACHED();
94 }
95
96 void PrerenderCookieStore::DeleteAllCreatedBetweenForHostAsync(
97     const base::Time delete_begin,
98     const base::Time delete_end,
99     const GURL& url,
100     const DeleteCallback& callback) {
101   NOTREACHED();
102 }
103
104 void PrerenderCookieStore::DeleteSessionCookiesAsync(const DeleteCallback&) {
105   NOTREACHED();
106 }
107
108 net::CookieMonster* PrerenderCookieStore::GetCookieMonster() {
109   NOTREACHED();
110   return NULL;
111 }
112
113 net::CookieStore* PrerenderCookieStore::GetCookieStoreForCookieOpAndLog(
114     const CookieOperation& op) {
115   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
116
117   std::string key = default_cookie_monster_->GetKey(op.url.host());
118   bool is_read_only = (op.op == COOKIE_OP_GET_COOKIES_WITH_OPTIONS_ASYNC ||
119                        op.op == COOKIE_OP_GET_ALL_COOKIES_FOR_URL_ASYNC);
120
121   if (in_forwarding_mode_)
122     return default_cookie_monster_.get();
123
124   DCHECK(changes_cookie_monster_.get() != NULL);
125
126   cookie_ops_.push_back(op);
127
128   bool key_copied = ContainsKey(copied_keys_, key);
129
130   if (key_copied)
131     return changes_cookie_monster_.get();
132
133   if (is_read_only) {
134     // Insert this key into the set of read keys, if it doesn't exist yet.
135     if (!ContainsKey(read_keys_, key))
136       read_keys_.insert(key);
137     return default_cookie_monster_.get();
138   }
139
140   // If this method hasn't returned yet, the key has not been copied yet,
141   // and we must copy it due to the requested write operation.
142
143   bool copy_success =
144       default_cookie_monster_->CopyCookiesForKeyToOtherCookieMonster(
145           key, changes_cookie_monster_.get());
146
147   // The copy must succeed.
148   DCHECK(copy_success);
149
150   copied_keys_.insert(key);
151
152   return changes_cookie_monster_.get();
153 }
154
155 void PrerenderCookieStore::ApplyChanges(std::vector<GURL>* cookie_change_urls) {
156   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
157
158   if (in_forwarding_mode_)
159     return;
160
161   // Apply all changes to the underlying cookie store.
162   for (std::vector<CookieOperation>::const_iterator it = cookie_ops_.begin();
163        it != cookie_ops_.end();
164        ++it) {
165     switch (it->op) {
166       case COOKIE_OP_SET_COOKIE_WITH_OPTIONS_ASYNC:
167         cookie_change_urls->push_back(it->url);
168         default_cookie_monster_->SetCookieWithOptionsAsync(
169             it->url, it->cookie_line, it->options, SetCookiesCallback());
170         break;
171       case COOKIE_OP_GET_COOKIES_WITH_OPTIONS_ASYNC:
172         default_cookie_monster_->GetCookiesWithOptionsAsync(
173             it->url, it->options, GetCookiesCallback());
174         break;
175       case COOKIE_OP_GET_ALL_COOKIES_FOR_URL_ASYNC:
176         default_cookie_monster_->GetAllCookiesForURLAsync(
177             it->url, GetCookieListCallback());
178         break;
179       case COOKIE_OP_DELETE_COOKIE_ASYNC:
180         cookie_change_urls->push_back(it->url);
181         default_cookie_monster_->DeleteCookieAsync(
182             it->url, it->cookie_name, base::Closure());
183         break;
184       case COOKIE_OP_MAX:
185         NOTREACHED();
186     }
187   }
188
189   in_forwarding_mode_ = true;
190   copied_keys_.clear();
191   cookie_ops_.clear();
192   changes_cookie_monster_ = NULL;
193 }
194
195 void PrerenderCookieStore::OnCookieChangedForURL(
196     net::CookieMonster* cookie_monster,
197     const GURL& url) {
198   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
199
200   // If the cookie was changed in a different cookie monster than the one
201   // being decorated, there is nothing to do).
202   if (cookie_monster != default_cookie_monster_.get())
203     return;
204
205   if (in_forwarding_mode_)
206     return;
207
208   // If we have encountered a conflict before, it has already been recorded
209   // and the cb has been issued, so nothing to do.
210   if (cookie_conflict_)
211     return;
212
213   std::string key = default_cookie_monster_->GetKey(url.host());
214
215   // If the key for the cookie which was modified was neither read nor written,
216   // nothing to do.
217   if ((!ContainsKey(read_keys_, key)) && (!ContainsKey(copied_keys_, key)))
218     return;
219
220   // There was a conflict in cookies. Call the conflict callback, which should
221   // cancel the prerender if necessary (i.e. if it hasn't already been
222   // cancelled for some other reason).
223   // Notice that there is a race here with swapping in the prerender, but this
224   // is the same issue that occurs when two tabs modify cookies for the
225   // same domain concurrently. Therefore, there is no need to do anything
226   // special to prevent this race condition.
227   cookie_conflict_ = true;
228   if (!cookie_conflict_cb_.is_null()) {
229     BrowserThread::PostTask(
230         BrowserThread::UI,
231         FROM_HERE,
232         cookie_conflict_cb_);
233   }
234 }
235
236 PrerenderCookieStore::CookieOperation::CookieOperation() {
237 }
238
239 PrerenderCookieStore::CookieOperation::~CookieOperation() {
240 }
241
242 }  // namespace prerender