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/chromeos/login/profile_auth_data.h"
7 #include "chrome/browser/profiles/profile.h"
8 #include "content/public/browser/browser_thread.h"
9 #include "net/cookies/cookie_monster.h"
10 #include "net/cookies/cookie_store.h"
11 #include "net/http/http_auth_cache.h"
12 #include "net/http/http_network_session.h"
13 #include "net/http/http_transaction_factory.h"
14 #include "net/ssl/server_bound_cert_service.h"
15 #include "net/ssl/server_bound_cert_store.h"
16 #include "net/url_request/url_request_context.h"
17 #include "net/url_request/url_request_context_getter.h"
19 using content::BrowserThread
;
25 class ProfileAuthDataTransferer
{
27 ProfileAuthDataTransferer(
28 Profile
* from_profile
,
30 bool transfer_cookies
,
31 const base::Closure
& completion_callback
);
36 void BeginTransferOnIOThread();
37 void MaybeDoCookieAndCertTransfer();
40 void OnTransferCookiesIfEmptyJar(const net::CookieList
& cookies_in_jar
);
41 void OnGetCookiesToTransfer(const net::CookieList
& cookies_to_transfer
);
42 void RetrieveDefaultCookies();
43 void OnGetServerBoundCertsToTransfer(
44 const net::ServerBoundCertStore::ServerBoundCertList
& certs
);
45 void RetrieveDefaultServerBoundCerts();
46 void TransferDefaultAuthCache();
48 scoped_refptr
<net::URLRequestContextGetter
> from_context_
;
49 scoped_refptr
<net::URLRequestContextGetter
> to_context_
;
50 bool transfer_cookies_
;
51 base::Closure completion_callback_
;
53 net::CookieList cookies_to_transfer_
;
54 net::ServerBoundCertStore::ServerBoundCertList certs_to_transfer_
;
57 bool got_server_bound_certs_
;
60 ProfileAuthDataTransferer::ProfileAuthDataTransferer(
61 Profile
* from_profile
,
63 bool transfer_cookies
,
64 const base::Closure
& completion_callback
)
65 : from_context_(from_profile
->GetRequestContext()),
66 to_context_(to_profile
->GetRequestContext()),
67 transfer_cookies_(transfer_cookies
),
68 completion_callback_(completion_callback
),
70 got_server_bound_certs_(false) {
73 void ProfileAuthDataTransferer::BeginTransfer() {
74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
75 // If we aren't transferring cookies, post the completion callback
76 // immediately. Otherwise, it will be called when both cookies and channel
77 // ids are finished transferring.
78 if (!transfer_cookies_
) {
79 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, completion_callback_
);
80 // Null the callback so that when Finish is called the callback won't be
82 completion_callback_
.Reset();
84 BrowserThread::PostTask(
85 BrowserThread::IO
, FROM_HERE
,
86 base::Bind(&ProfileAuthDataTransferer::BeginTransferOnIOThread
,
87 base::Unretained(this)));
90 void ProfileAuthDataTransferer::BeginTransferOnIOThread() {
91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
92 TransferDefaultAuthCache();
94 if (transfer_cookies_
) {
95 RetrieveDefaultCookies();
96 RetrieveDefaultServerBoundCerts();
102 // If both cookies and server bound certs have been retrieved, see if we need to
103 // do the actual transfer.
104 void ProfileAuthDataTransferer::MaybeDoCookieAndCertTransfer() {
105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
106 if (!(got_cookies_
&& got_server_bound_certs_
))
109 // Nothing to transfer over?
110 if (!cookies_to_transfer_
.size()) {
115 // Now let's see if the target cookie monster's jar is even empty.
116 net::CookieStore
* to_store
=
117 to_context_
->GetURLRequestContext()->cookie_store();
118 net::CookieMonster
* to_monster
= to_store
->GetCookieMonster();
119 to_monster
->GetAllCookiesAsync(
120 base::Bind(&ProfileAuthDataTransferer::OnTransferCookiesIfEmptyJar
,
121 base::Unretained(this)));
124 // Post the |completion_callback_| and delete ourself.
125 void ProfileAuthDataTransferer::Finish() {
126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
127 if (!completion_callback_
.is_null())
128 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, completion_callback_
);
132 // Callback for transferring |cookies_to_transfer_| into |to_context_|'s
133 // CookieMonster if its jar is completely empty. If authentication was
134 // performed by an extension, then the set of cookies that was acquired through
135 // such that process will be automatically transfered into the profile.
136 void ProfileAuthDataTransferer::OnTransferCookiesIfEmptyJar(
137 const net::CookieList
& cookies_in_jar
) {
138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
139 // Transfer only if the existing cookie jar is empty.
140 if (!cookies_in_jar
.size()) {
141 net::CookieStore
* to_store
=
142 to_context_
->GetURLRequestContext()->cookie_store();
143 net::CookieMonster
* to_monster
= to_store
->GetCookieMonster();
144 to_monster
->InitializeFrom(cookies_to_transfer_
);
146 net::ServerBoundCertService
* to_cert_service
=
147 to_context_
->GetURLRequestContext()->server_bound_cert_service();
148 to_cert_service
->GetCertStore()->InitializeFrom(certs_to_transfer_
);
154 // Callback for receiving |cookies_to_transfer| from the authentication profile
156 void ProfileAuthDataTransferer::OnGetCookiesToTransfer(
157 const net::CookieList
& cookies_to_transfer
) {
158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
161 cookies_to_transfer_
= cookies_to_transfer
;
162 MaybeDoCookieAndCertTransfer();
165 // Retrieves initial set of Profile cookies from the |from_context_|.
166 void ProfileAuthDataTransferer::RetrieveDefaultCookies() {
167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
169 net::CookieStore
* from_store
=
170 from_context_
->GetURLRequestContext()->cookie_store();
171 net::CookieMonster
* from_monster
= from_store
->GetCookieMonster();
172 from_monster
->SetKeepExpiredCookies();
173 from_monster
->GetAllCookiesAsync(
174 base::Bind(&ProfileAuthDataTransferer::OnGetCookiesToTransfer
,
175 base::Unretained(this)));
178 // Callback for receiving |cookies_to_transfer| from the authentication profile
180 void ProfileAuthDataTransferer::OnGetServerBoundCertsToTransfer(
181 const net::ServerBoundCertStore::ServerBoundCertList
& certs
) {
182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
183 certs_to_transfer_
= certs
;
184 got_server_bound_certs_
= true;
185 MaybeDoCookieAndCertTransfer();
188 // Retrieves server bound certs of |from_context_|.
189 void ProfileAuthDataTransferer::RetrieveDefaultServerBoundCerts() {
190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
191 net::ServerBoundCertService
* from_service
=
192 from_context_
->GetURLRequestContext()->server_bound_cert_service();
194 from_service
->GetCertStore()->GetAllServerBoundCerts(
195 base::Bind(&ProfileAuthDataTransferer::OnGetServerBoundCertsToTransfer
,
196 base::Unretained(this)));
199 // Transfers HTTP authentication cache from the |from_context_|
200 // into the |to_context_|. If user was required to authenticate with a proxy
201 // during the login, this authentication information will be transferred
202 // into the new session.
203 void ProfileAuthDataTransferer::TransferDefaultAuthCache() {
204 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
205 net::HttpAuthCache
* new_cache
= to_context_
->GetURLRequestContext()->
206 http_transaction_factory()->GetSession()->http_auth_cache();
207 new_cache
->UpdateAllFrom(*from_context_
->GetURLRequestContext()->
208 http_transaction_factory()->GetSession()->http_auth_cache());
213 void ProfileAuthData::Transfer(
214 Profile
* from_profile
,
216 bool transfer_cookies
,
217 const base::Closure
& completion_callback
) {
218 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
219 (new ProfileAuthDataTransferer(from_profile
, to_profile
, transfer_cookies
,
220 completion_callback
))->BeginTransfer();
223 } // namespace chromeos