Save errno for logging before potentially overwriting it.
[chromium-blink-merge.git] / android_webview / native / cookie_manager.cc
blob597fa05900d48d748628cf28a4c2cba60e1cd907
1 // Copyright (c) 2011 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 "android_webview/native/cookie_manager.h"
7 #include "android_webview/browser/aw_cookie_access_policy.h"
8 #include "android_webview/browser/scoped_allow_wait_for_legacy_web_view_api.h"
9 #include "android_webview/native/aw_browser_dependency_factory.h"
10 #include "base/android/jni_string.h"
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/lazy_instance.h"
14 #include "base/message_loop.h"
15 #include "base/message_loop/message_loop_proxy.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "base/threading/thread_restrictions.h"
18 #include "content/public/browser/browser_context.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/common/url_constants.h"
21 #include "jni/AwCookieManager_jni.h"
22 #include "net/cookies/cookie_monster.h"
23 #include "net/cookies/cookie_options.h"
24 #include "net/url_request/url_request_context.h"
26 using base::android::ConvertJavaStringToUTF8;
27 using base::android::ConvertJavaStringToUTF16;
28 using content::BrowserThread;
29 using net::CookieList;
30 using net::CookieMonster;
32 // In the future, we may instead want to inject an explicit CookieStore
33 // dependency into this object during process initialization to avoid
34 // depending on the URLRequestContext.
35 // See issue http://crbug.com/157683
37 // All functions on the CookieManager can be called from any thread, including
38 // threads without a message loop. BrowserThread::FILE is used to call methods
39 // on CookieMonster that needs to be called, and called back, on a chrome
40 // thread.
42 namespace android_webview {
44 namespace {
46 class CookieManager {
47 public:
48 static CookieManager* GetInstance();
50 void SetCookieMonster(net::CookieMonster* cookie_monster);
52 void SetAcceptCookie(bool accept);
53 bool AcceptCookie();
54 void SetCookie(const GURL& host, const std::string& cookie_value);
55 std::string GetCookie(const GURL& host);
56 void RemoveSessionCookie();
57 void RemoveAllCookie();
58 void RemoveExpiredCookie();
59 void FlushCookieStore();
60 bool HasCookies();
61 bool AllowFileSchemeCookies();
62 void SetAcceptFileSchemeCookies(bool accept);
64 private:
65 friend struct base::DefaultLazyInstanceTraits<CookieManager>;
67 CookieManager();
68 ~CookieManager();
70 typedef base::Callback<void(base::WaitableEvent*)> CookieTask;
71 void ExecCookieTask(const CookieTask& task,
72 const bool wait_for_completion);
74 void SetCookieAsyncHelper(
75 const GURL& host,
76 const std::string& value,
77 base::WaitableEvent* completion);
78 void SetCookieCompleted(bool success);
80 void GetCookieValueAsyncHelper(
81 const GURL& host,
82 std::string* result,
83 base::WaitableEvent* completion);
84 void GetCookieValueCompleted(base::WaitableEvent* completion,
85 std::string* result,
86 const std::string& value);
88 void RemoveSessionCookieAsyncHelper(base::WaitableEvent* completion);
89 void RemoveAllCookieAsyncHelper(base::WaitableEvent* completion);
90 void RemoveCookiesCompleted(int num_deleted);
92 void FlushCookieStoreAsyncHelper(base::WaitableEvent* completion);
94 void HasCookiesAsyncHelper(bool* result,
95 base::WaitableEvent* completion);
96 void HasCookiesCompleted(base::WaitableEvent* completion,
97 bool* result,
98 const CookieList& cookies);
100 scoped_refptr<net::CookieMonster> cookie_monster_;
102 DISALLOW_COPY_AND_ASSIGN(CookieManager);
105 base::LazyInstance<CookieManager>::Leaky g_lazy_instance;
107 // static
108 CookieManager* CookieManager::GetInstance() {
109 return g_lazy_instance.Pointer();
112 CookieManager::CookieManager() {
115 CookieManager::~CookieManager() {
118 // Executes the |task| on the FILE thread. |wait_for_completion| should only be
119 // true if the Java API method returns a value or is explicitly stated to be
120 // synchronous.
121 void CookieManager::ExecCookieTask(const CookieTask& task,
122 const bool wait_for_completion) {
123 base::WaitableEvent completion(false, false);
125 DCHECK(cookie_monster_.get());
127 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
128 base::Bind(task, wait_for_completion ? &completion : NULL));
130 if (wait_for_completion) {
131 ScopedAllowWaitForLegacyWebViewApi wait;
132 completion.Wait();
136 void CookieManager::SetCookieMonster(net::CookieMonster* cookie_monster) {
137 DCHECK(!cookie_monster_.get());
138 cookie_monster_ = cookie_monster;
141 void CookieManager::SetAcceptCookie(bool accept) {
142 AwCookieAccessPolicy::GetInstance()->SetGlobalAllowAccess(accept);
145 bool CookieManager::AcceptCookie() {
146 return AwCookieAccessPolicy::GetInstance()->GetGlobalAllowAccess();
149 void CookieManager::SetCookie(const GURL& host,
150 const std::string& cookie_value) {
151 ExecCookieTask(base::Bind(&CookieManager::SetCookieAsyncHelper,
152 base::Unretained(this),
153 host,
154 cookie_value), false);
157 void CookieManager::SetCookieAsyncHelper(
158 const GURL& host,
159 const std::string& value,
160 base::WaitableEvent* completion) {
161 DCHECK(!completion);
162 net::CookieOptions options;
163 options.set_include_httponly();
165 cookie_monster_->SetCookieWithOptionsAsync(
166 host, value, options,
167 base::Bind(&CookieManager::SetCookieCompleted, base::Unretained(this)));
170 void CookieManager::SetCookieCompleted(bool success) {
171 // The CookieManager API does not return a value for SetCookie,
172 // so we don't need to propagate the |success| value back to the caller.
175 std::string CookieManager::GetCookie(const GURL& host) {
176 std::string cookie_value;
177 ExecCookieTask(base::Bind(&CookieManager::GetCookieValueAsyncHelper,
178 base::Unretained(this),
179 host,
180 &cookie_value), true);
182 return cookie_value;
185 void CookieManager::GetCookieValueAsyncHelper(
186 const GURL& host,
187 std::string* result,
188 base::WaitableEvent* completion) {
189 net::CookieOptions options;
190 options.set_include_httponly();
192 cookie_monster_->GetCookiesWithOptionsAsync(
193 host,
194 options,
195 base::Bind(&CookieManager::GetCookieValueCompleted,
196 base::Unretained(this),
197 completion,
198 result));
201 void CookieManager::GetCookieValueCompleted(base::WaitableEvent* completion,
202 std::string* result,
203 const std::string& value) {
204 *result = value;
205 DCHECK(completion);
206 completion->Signal();
209 void CookieManager::RemoveSessionCookie() {
210 ExecCookieTask(base::Bind(&CookieManager::RemoveSessionCookieAsyncHelper,
211 base::Unretained(this)), false);
214 void CookieManager::RemoveSessionCookieAsyncHelper(
215 base::WaitableEvent* completion) {
216 DCHECK(!completion);
217 cookie_monster_->DeleteSessionCookiesAsync(
218 base::Bind(&CookieManager::RemoveCookiesCompleted,
219 base::Unretained(this)));
222 void CookieManager::RemoveCookiesCompleted(int num_deleted) {
223 // The CookieManager API does not return a value for removeSessionCookie or
224 // removeAllCookie, so we don't need to propagate the |num_deleted| value back
225 // to the caller.
228 void CookieManager::RemoveAllCookie() {
229 ExecCookieTask(base::Bind(&CookieManager::RemoveAllCookieAsyncHelper,
230 base::Unretained(this)), false);
233 // TODO(kristianm): Pass a null callback so it will not be invoked
234 // across threads.
235 void CookieManager::RemoveAllCookieAsyncHelper(
236 base::WaitableEvent* completion) {
237 DCHECK(!completion);
238 cookie_monster_->DeleteAllAsync(
239 base::Bind(&CookieManager::RemoveCookiesCompleted,
240 base::Unretained(this)));
243 void CookieManager::RemoveExpiredCookie() {
244 // HasCookies will call GetAllCookiesAsync, which in turn will force a GC.
245 HasCookies();
248 void CookieManager::FlushCookieStoreAsyncHelper(
249 base::WaitableEvent* completion) {
250 DCHECK(!completion);
251 cookie_monster_->FlushStore(base::Bind(&base::DoNothing));
254 void CookieManager::FlushCookieStore() {
255 ExecCookieTask(base::Bind(&CookieManager::FlushCookieStoreAsyncHelper,
256 base::Unretained(this)), false);
259 bool CookieManager::HasCookies() {
260 bool has_cookies;
261 ExecCookieTask(base::Bind(&CookieManager::HasCookiesAsyncHelper,
262 base::Unretained(this),
263 &has_cookies), true);
264 return has_cookies;
267 // TODO(kristianm): Simplify this, copying the entire list around
268 // should not be needed.
269 void CookieManager::HasCookiesAsyncHelper(bool* result,
270 base::WaitableEvent* completion) {
271 cookie_monster_->GetAllCookiesAsync(
272 base::Bind(&CookieManager::HasCookiesCompleted,
273 base::Unretained(this),
274 completion,
275 result));
278 void CookieManager::HasCookiesCompleted(base::WaitableEvent* completion,
279 bool* result,
280 const CookieList& cookies) {
281 *result = cookies.size() != 0;
282 DCHECK(completion);
283 completion->Signal();
286 bool CookieManager::AllowFileSchemeCookies() {
287 return cookie_monster_->IsCookieableScheme(chrome::kFileScheme);
290 void CookieManager::SetAcceptFileSchemeCookies(bool accept) {
291 // The docs on CookieManager base class state the API must not be called after
292 // creating a CookieManager instance (which contradicts its own internal
293 // implementation) but this code does rely on the essence of that comment, as
294 // the monster will DCHECK here if it has already been lazy initialized (i.e.
295 // if cookies have been read or written from the store). If that turns out to
296 // be a problemin future, it looks like it maybe possible to relax the DCHECK.
297 cookie_monster_->SetEnableFileScheme(accept);
300 } // namespace
302 static void SetAcceptCookie(JNIEnv* env, jobject obj, jboolean accept) {
303 CookieManager::GetInstance()->SetAcceptCookie(accept);
306 static jboolean AcceptCookie(JNIEnv* env, jobject obj) {
307 return CookieManager::GetInstance()->AcceptCookie();
310 static void SetCookie(JNIEnv* env, jobject obj, jstring url, jstring value) {
311 GURL host(ConvertJavaStringToUTF16(env, url));
312 std::string cookie_value(ConvertJavaStringToUTF8(env, value));
314 CookieManager::GetInstance()->SetCookie(host, cookie_value);
317 static jstring GetCookie(JNIEnv* env, jobject obj, jstring url) {
318 GURL host(ConvertJavaStringToUTF16(env, url));
320 return base::android::ConvertUTF8ToJavaString(
321 env,
322 CookieManager::GetInstance()->GetCookie(host)).Release();
325 static void RemoveSessionCookie(JNIEnv* env, jobject obj) {
326 CookieManager::GetInstance()->RemoveSessionCookie();
329 static void RemoveAllCookie(JNIEnv* env, jobject obj) {
330 CookieManager::GetInstance()->RemoveAllCookie();
333 static void RemoveExpiredCookie(JNIEnv* env, jobject obj) {
334 CookieManager::GetInstance()->RemoveExpiredCookie();
337 static void FlushCookieStore(JNIEnv* env, jobject obj) {
338 CookieManager::GetInstance()->FlushCookieStore();
341 static jboolean HasCookies(JNIEnv* env, jobject obj) {
342 return CookieManager::GetInstance()->HasCookies();
345 static jboolean AllowFileSchemeCookies(JNIEnv* env, jobject obj) {
346 return CookieManager::GetInstance()->AllowFileSchemeCookies();
349 static void SetAcceptFileSchemeCookies(JNIEnv* env, jobject obj,
350 jboolean accept) {
351 return CookieManager::GetInstance()->SetAcceptFileSchemeCookies(accept);
354 void SetCookieMonsterOnNetworkStackInit(net::CookieMonster* cookie_monster) {
355 CookieManager::GetInstance()->SetCookieMonster(cookie_monster);
358 bool RegisterCookieManager(JNIEnv* env) {
359 return RegisterNativesImpl(env);
362 } // android_webview namespace