1 // Copyright 2015 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 "base/android/jni_android.h"
6 #include "base/android/jni_string.h"
8 #include "base/time/time.h"
9 #include "chrome/browser/android/cookies/cookies_fetcher.h"
10 #include "chrome/browser/profiles/profile_manager.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "jni/CookiesFetcher_jni.h"
13 #include "net/cookies/cookie_monster.h"
14 #include "net/cookies/cookie_store.h"
15 #include "net/url_request/url_request_context.h"
17 CookiesFetcher::CookiesFetcher(JNIEnv
* env
, jobject obj
, Profile
* profile
) {
20 CookiesFetcher::~CookiesFetcher() {
23 void CookiesFetcher::Destroy(JNIEnv
* env
, jobject obj
) {
27 void CookiesFetcher::PersistCookies(JNIEnv
* env
, jobject obj
) {
28 Profile
* profile
= ProfileManager::GetPrimaryUserProfile();
29 if (!profile
->HasOffTheRecordProfile()) {
30 // There is no work to be done. We might consider calling
31 // the Java callback if needed.
34 profile
= profile
->GetOffTheRecordProfile();
36 scoped_refptr
<net::URLRequestContextGetter
> getter(
37 profile
->GetRequestContext());
39 // Take a strong global reference to the Java counter part and hold
40 // on to it. This ensures the object would not be GC'd so we can call
42 jobject_
.Reset(env
, obj
);
44 // The rest must be done from the IO thread.
45 content::BrowserThread::PostTask(content::BrowserThread::IO
, FROM_HERE
,
46 base::Bind(&CookiesFetcher::PersistCookiesInternal
,
47 base::Unretained(this), getter
));
50 void CookiesFetcher::PersistCookiesInternal(
51 net::URLRequestContextGetter
* getter
) {
52 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
54 net::CookieStore
* store
= getter
->GetURLRequestContext()->cookie_store();
56 // Nullable sometimes according to docs. There is no work need to be done
57 // but we can consider calling the Java callback with empty output.
63 net::CookieMonster
* monster
= store
->GetCookieMonster();
65 monster
->GetAllCookiesAsync(base::Bind(
66 &CookiesFetcher::OnCookiesFetchFinished
, base::Unretained(this)));
69 void CookiesFetcher::OnCookiesFetchFinished(const net::CookieList
& cookies
) {
70 JNIEnv
* env
= base::android::AttachCurrentThread();
72 ScopedJavaLocalRef
<jobjectArray
> joa
=
73 Java_CookiesFetcher_createCookiesArray(
74 env
, jobject_
.obj(), cookies
.size());
77 for (net::CookieList::const_iterator i
= cookies
.begin();
78 i
!= cookies
.end(); ++i
) {
79 ScopedJavaLocalRef
<jobject
> java_cookie
= Java_CookiesFetcher_createCookie(
81 base::android::ConvertUTF8ToJavaString(env
, i
->Source()).obj(),
82 base::android::ConvertUTF8ToJavaString(env
, i
->Name()).obj(),
83 base::android::ConvertUTF8ToJavaString(env
, i
->Value()).obj(),
84 base::android::ConvertUTF8ToJavaString(env
, i
->Domain()).obj(),
85 base::android::ConvertUTF8ToJavaString(env
, i
->Path()).obj(),
86 i
->CreationDate().ToInternalValue(), i
->ExpiryDate().ToInternalValue(),
87 i
->LastAccessDate().ToInternalValue(), i
->IsSecure(), i
->IsHttpOnly(),
88 i
->IsFirstPartyOnly(), i
->Priority());
89 env
->SetObjectArrayElement(joa
.obj(), index
++, java_cookie
.obj());
92 Java_CookiesFetcher_onCookieFetchFinished(env
, jobject_
.obj(), joa
.obj());
94 // Give up the reference.
98 void CookiesFetcher::RestoreCookies(JNIEnv
* env
,
112 Profile
* profile
= ProfileManager::GetPrimaryUserProfile();
113 if (!profile
->HasOffTheRecordProfile()) {
114 return; // Don't create it. There is nothing to do.
116 profile
= profile
->GetOffTheRecordProfile();
118 scoped_refptr
<net::URLRequestContextGetter
> getter(
119 profile
->GetRequestContext());
121 net::CanonicalCookie
cookie(
122 GURL(base::android::ConvertJavaStringToUTF8(env
, url
)),
123 base::android::ConvertJavaStringToUTF8(env
, name
),
124 base::android::ConvertJavaStringToUTF8(env
, value
),
125 base::android::ConvertJavaStringToUTF8(env
, domain
),
126 base::android::ConvertJavaStringToUTF8(env
, path
),
127 base::Time::FromInternalValue(creation
),
128 base::Time::FromInternalValue(expiration
),
129 base::Time::FromInternalValue(last_access
), secure
, httponly
,
130 firstpartyonly
, static_cast<net::CookiePriority
>(priority
));
132 // The rest must be done from the IO thread.
133 content::BrowserThread::PostTask(
134 content::BrowserThread::IO
,
136 base::Bind(&CookiesFetcher::RestoreToCookieJarInternal
,
137 base::Unretained(this),
142 void CookiesFetcher::RestoreToCookieJarInternal(
143 net::URLRequestContextGetter
* getter
,
144 const net::CanonicalCookie
& cookie
) {
145 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
147 net::CookieStore
* store
= getter
->GetURLRequestContext()->cookie_store();
149 // Nullable sometimes according to docs.
154 net::CookieMonster
* monster
= store
->GetCookieMonster();
155 base::Callback
<void(bool success
)> cb
;
157 monster
->SetCookieWithDetailsAsync(
158 GURL(cookie
.Source()), cookie
.Name(), cookie
.Value(), cookie
.Domain(),
159 cookie
.Path(), cookie
.ExpiryDate(), cookie
.IsSecure(),
160 cookie
.IsHttpOnly(), cookie
.IsFirstPartyOnly(), cookie
.Priority(), cb
);
164 static jlong
Init(JNIEnv
* env
, jobject obj
) {
165 return reinterpret_cast<intptr_t>(new CookiesFetcher(env
, obj
, 0));
168 // Register native methods
169 bool RegisterCookiesFetcher(JNIEnv
* env
) {
170 return RegisterNativesImpl(env
);