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.
5 #include "chrome/browser/chromeos/login/profile_auth_data.h"
10 #include "base/bind_helpers.h"
11 #include "base/compiler_specific.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/run_loop.h"
14 #include "base/strings/string16.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "base/time/time.h"
17 #include "chrome/test/base/testing_profile.h"
18 #include "content/public/browser/browser_context.h"
19 #include "content/public/test/test_browser_thread_bundle.h"
20 #include "net/cookies/canonical_cookie.h"
21 #include "net/cookies/cookie_constants.h"
22 #include "net/cookies/cookie_monster.h"
23 #include "net/cookies/cookie_store.h"
24 #include "net/http/http_auth.h"
25 #include "net/http/http_auth_cache.h"
26 #include "net/http/http_network_session.h"
27 #include "net/http/http_transaction_factory.h"
28 #include "net/ssl/channel_id_service.h"
29 #include "net/ssl/channel_id_store.h"
30 #include "net/test/channel_id_test_util.h"
31 #include "net/url_request/url_request_context.h"
32 #include "net/url_request/url_request_context_getter.h"
33 #include "testing/gtest/include/gtest/gtest.h"
40 const char kProxyAuthURL
[] = "http://example.com/";
41 const char kProxyAuthRealm
[] = "realm";
42 const char kProxyAuthChallenge
[] = "challenge";
43 const char kProxyAuthPassword1
[] = "password 1";
44 const char kProxyAuthPassword2
[] = "password 2";
46 const char kGAIACookieURL
[] = "http://google.com/";
47 const char kSAMLIdPCookieURL
[] = "http://example.com/";
48 const char kCookieName
[] = "cookie";
49 const char kCookieValue1
[] = "value 1";
50 const char kCookieValue2
[] = "value 2";
51 const char kGAIACookieDomain
[] = "google.com";
52 const char kSAMLIdPCookieDomain
[] = "example.com";
54 const char kChannelIDServerIdentifier
[] = "server";
58 class ProfileAuthDataTest
: public testing::Test
{
61 void SetUp() override
;
63 void PopulateUserBrowserContext();
66 bool transfer_auth_cookies_and_channel_ids_on_first_login
,
67 bool transfer_saml_auth_cookies_on_subsequent_login
);
69 net::CookieList
GetUserCookies();
70 net::ChannelIDStore::ChannelIDList
GetUserChannelIDs();
72 void VerifyTransferredUserProxyAuthEntry();
73 void VerifyUserCookies(const std::string
& expected_gaia_cookie_value
,
74 const std::string
& expected_saml_idp_cookie_value
);
75 void VerifyUserChannelID(crypto::ECPrivateKey
* expected_key
);
78 scoped_ptr
<crypto::ECPrivateKey
> channel_id_key1_
;
79 scoped_ptr
<crypto::ECPrivateKey
> channel_id_key2_
;
82 void PopulateBrowserContext(content::BrowserContext
* browser_context
,
83 const std::string
& proxy_auth_password
,
84 const std::string
& cookie_value
,
85 scoped_ptr
<crypto::ECPrivateKey
> channel_id_key
);
87 net::URLRequestContext
* GetRequestContext(
88 content::BrowserContext
* browser_context
);
89 net::HttpAuthCache
* GetProxyAuth(content::BrowserContext
* browser_context
);
90 net::CookieMonster
* GetCookies(content::BrowserContext
* browser_context
);
91 net::ChannelIDStore
* GetChannelIDs(content::BrowserContext
* browser_context
);
93 void QuitLoop(const net::CookieList
& ignored
);
94 void StoreCookieListAndQuitLoop(const net::CookieList
& cookie_list
);
95 void StoreChannelIDListAndQuitLoop(
96 const net::ChannelIDStore::ChannelIDList
& channel_id_list
);
98 content::TestBrowserThreadBundle thread_bundle_
;
100 TestingProfile login_browser_context_
;
101 TestingProfile user_browser_context_
;
103 net::CookieList user_cookie_list_
;
104 net::ChannelIDStore::ChannelIDList user_channel_id_list_
;
106 scoped_ptr
<base::RunLoop
> run_loop_
;
109 void ProfileAuthDataTest::SetUp() {
110 channel_id_key1_
.reset(crypto::ECPrivateKey::Create());
111 channel_id_key2_
.reset(crypto::ECPrivateKey::Create());
112 PopulateBrowserContext(&login_browser_context_
, kProxyAuthPassword1
,
114 make_scoped_ptr(channel_id_key1_
->Copy()));
117 void ProfileAuthDataTest::PopulateUserBrowserContext() {
118 PopulateBrowserContext(&user_browser_context_
, kProxyAuthPassword2
,
120 make_scoped_ptr(channel_id_key2_
->Copy()));
123 void ProfileAuthDataTest::Transfer(
124 bool transfer_auth_cookies_and_channel_ids_on_first_login
,
125 bool transfer_saml_auth_cookies_on_subsequent_login
) {
126 base::RunLoop run_loop
;
127 ProfileAuthData::Transfer(
128 login_browser_context_
.GetRequestContext(),
129 user_browser_context_
.GetRequestContext(),
130 transfer_auth_cookies_and_channel_ids_on_first_login
,
131 transfer_saml_auth_cookies_on_subsequent_login
,
132 run_loop
.QuitClosure());
134 if (!transfer_auth_cookies_and_channel_ids_on_first_login
&&
135 !transfer_saml_auth_cookies_on_subsequent_login
) {
136 // When only proxy auth state is being transferred, the completion callback
137 // is invoked before the transfer has actually completed. Spin the loop once
138 // more to allow the transfer to complete.
139 base::RunLoop().RunUntilIdle();
143 net::CookieList
ProfileAuthDataTest::GetUserCookies() {
144 run_loop_
.reset(new base::RunLoop
);
145 GetCookies(&user_browser_context_
)->GetAllCookiesAsync(base::Bind(
146 &ProfileAuthDataTest::StoreCookieListAndQuitLoop
,
147 base::Unretained(this)));
149 return user_cookie_list_
;
152 net::ChannelIDStore::ChannelIDList
ProfileAuthDataTest::GetUserChannelIDs() {
153 run_loop_
.reset(new base::RunLoop
);
154 GetChannelIDs(&user_browser_context_
)->GetAllChannelIDs(base::Bind(
155 &ProfileAuthDataTest::StoreChannelIDListAndQuitLoop
,
156 base::Unretained(this)));
158 return user_channel_id_list_
;
161 void ProfileAuthDataTest::VerifyTransferredUserProxyAuthEntry() {
162 net::HttpAuthCache::Entry
* entry
=
163 GetProxyAuth(&user_browser_context_
)->Lookup(
166 net::HttpAuth::AUTH_SCHEME_BASIC
);
168 EXPECT_EQ(base::ASCIIToUTF16(kProxyAuthPassword1
),
169 entry
->credentials().password());
172 void ProfileAuthDataTest::VerifyUserCookies(
173 const std::string
& expected_gaia_cookie_value
,
174 const std::string
& expected_saml_idp_cookie_value
) {
175 net::CookieList user_cookies
= GetUserCookies();
176 ASSERT_EQ(2u, user_cookies
.size());
177 net::CanonicalCookie
* cookie
= &user_cookies
[0];
178 EXPECT_EQ(GURL(kSAMLIdPCookieURL
), cookie
->Source());
179 EXPECT_EQ(kCookieName
, cookie
->Name());
180 EXPECT_EQ(expected_saml_idp_cookie_value
, cookie
->Value());
181 EXPECT_EQ(kSAMLIdPCookieDomain
, cookie
->Domain());
182 cookie
= &user_cookies
[1];
183 EXPECT_EQ(GURL(kGAIACookieURL
), cookie
->Source());
184 EXPECT_EQ(kCookieName
, cookie
->Name());
185 EXPECT_EQ(expected_gaia_cookie_value
, cookie
->Value());
186 EXPECT_EQ(kGAIACookieDomain
, cookie
->Domain());
189 void ProfileAuthDataTest::VerifyUserChannelID(
190 crypto::ECPrivateKey
* expected_key
) {
191 net::ChannelIDStore::ChannelIDList user_channel_ids
= GetUserChannelIDs();
192 ASSERT_EQ(1u, user_channel_ids
.size());
193 net::ChannelIDStore::ChannelID
* channel_id
= &user_channel_ids
.front();
194 EXPECT_EQ(kChannelIDServerIdentifier
, channel_id
->server_identifier());
195 EXPECT_TRUE(net::KeysEqual(expected_key
, channel_id
->key()));
198 void ProfileAuthDataTest::PopulateBrowserContext(
199 content::BrowserContext
* browser_context
,
200 const std::string
& proxy_auth_password
,
201 const std::string
& cookie_value
,
202 scoped_ptr
<crypto::ECPrivateKey
> channel_id_key
) {
203 GetProxyAuth(browser_context
)->Add(
206 net::HttpAuth::AUTH_SCHEME_BASIC
,
208 net::AuthCredentials(base::string16(),
209 base::ASCIIToUTF16(proxy_auth_password
)),
212 net::CookieMonster
* cookies
= GetCookies(browser_context
);
213 // Ensure |cookies| is fully initialized.
214 run_loop_
.reset(new base::RunLoop
);
215 cookies
->GetAllCookiesAsync(base::Bind(&ProfileAuthDataTest::QuitLoop
,
216 base::Unretained(this)));
219 net::CookieList cookie_list
;
220 cookie_list
.push_back(net::CanonicalCookie(
221 GURL(kGAIACookieURL
), kCookieName
, cookie_value
, kGAIACookieDomain
,
222 std::string(), base::Time(), base::Time(), base::Time(), true, false,
223 false, net::COOKIE_PRIORITY_DEFAULT
));
224 cookie_list
.push_back(net::CanonicalCookie(
225 GURL(kSAMLIdPCookieURL
), kCookieName
, cookie_value
, kSAMLIdPCookieDomain
,
226 std::string(), base::Time(), base::Time(), base::Time(), true, false,
227 false, net::COOKIE_PRIORITY_DEFAULT
));
228 cookies
->ImportCookies(cookie_list
);
230 GetChannelIDs(browser_context
)
231 ->SetChannelID(make_scoped_ptr(new net::ChannelIDStore::ChannelID(
232 kChannelIDServerIdentifier
, base::Time(), channel_id_key
.Pass())));
235 net::URLRequestContext
* ProfileAuthDataTest::GetRequestContext(
236 content::BrowserContext
* browser_context
) {
237 return browser_context
->GetRequestContext()->GetURLRequestContext();
240 net::HttpAuthCache
* ProfileAuthDataTest::GetProxyAuth(
241 content::BrowserContext
* browser_context
) {
242 return GetRequestContext(browser_context
)->http_transaction_factory()->
243 GetSession()->http_auth_cache();
246 net::CookieMonster
* ProfileAuthDataTest::GetCookies(
247 content::BrowserContext
* browser_context
) {
248 return GetRequestContext(browser_context
)->cookie_store()->GetCookieMonster();
251 net::ChannelIDStore
* ProfileAuthDataTest::GetChannelIDs(
252 content::BrowserContext
* browser_context
) {
253 return GetRequestContext(browser_context
)->channel_id_service()->
257 void ProfileAuthDataTest::QuitLoop(const net::CookieList
& ignored
) {
261 void ProfileAuthDataTest::StoreCookieListAndQuitLoop(
262 const net::CookieList
& cookie_list
) {
263 user_cookie_list_
= cookie_list
;
267 void ProfileAuthDataTest::StoreChannelIDListAndQuitLoop(
268 const net::ChannelIDStore::ChannelIDList
& channel_id_list
) {
269 user_channel_id_list_
= channel_id_list
;
273 // Verifies that when no transfer of auth cookies or channel IDs is requested,
274 // only the proxy auth state is transferred.
275 TEST_F(ProfileAuthDataTest
, DoNotTransfer
) {
276 Transfer(false, false);
278 VerifyTransferredUserProxyAuthEntry();
279 EXPECT_TRUE(GetUserCookies().empty());
280 EXPECT_TRUE(GetUserChannelIDs().empty());
283 // Verifies that when the transfer of auth cookies and channel IDs on first
284 // login is requested, they do get transferred along with the proxy auth state
286 TEST_F(ProfileAuthDataTest
, TransferOnFirstLoginWithNewProfile
) {
287 Transfer(true, false);
289 VerifyTransferredUserProxyAuthEntry();
290 VerifyUserCookies(kCookieValue1
, kCookieValue1
);
291 VerifyUserChannelID(channel_id_key1_
.get());
294 // Verifies that even if the transfer of auth cookies and channel IDs on first
295 // login is requested, only the proxy auth state is transferred on subsequent
297 TEST_F(ProfileAuthDataTest
, TransferOnFirstLoginWithExistingProfile
) {
298 PopulateUserBrowserContext();
300 Transfer(true, false);
302 VerifyTransferredUserProxyAuthEntry();
303 VerifyUserCookies(kCookieValue2
, kCookieValue2
);
304 VerifyUserChannelID(channel_id_key2_
.get());
307 // Verifies that when the transfer of auth cookies set by a SAML IdP on
308 // subsequent login is requested, they do get transferred along with the proxy
309 // auth state on subsequent login.
310 TEST_F(ProfileAuthDataTest
, TransferOnSubsequentLogin
) {
311 PopulateUserBrowserContext();
313 Transfer(false, true);
315 VerifyTransferredUserProxyAuthEntry();
316 VerifyUserCookies(kCookieValue2
, kCookieValue1
);
317 VerifyUserChannelID(channel_id_key2_
.get());
320 } // namespace chromeos