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 "testing/gtest/include/gtest/gtest.h"
7 #include "base/basictypes.h"
8 #include "base/file_util.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/path_service.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/time/time.h"
14 #include "chrome/browser/password_manager/login_database.h"
15 #include "chrome/browser/password_manager/psl_matching_helper.h"
16 #include "chrome/common/chrome_paths.h"
17 #include "components/autofill/core/common/password_form.h"
18 #include "testing/gmock/include/gmock/gmock.h"
20 using autofill::PasswordForm
;
21 using base::ASCIIToUTF16
;
24 class LoginDatabaseTest
: public testing::Test
{
26 virtual void SetUp() {
27 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
28 file_
= temp_dir_
.path().AppendASCII("TestMetadataStoreMacDatabase");
30 ASSERT_TRUE(db_
.Init(file_
));
33 Pickle
SerializeVector(const std::vector
<base::string16
>& vec
) const {
34 return db_
.SerializeVector(vec
);
37 std::vector
<base::string16
> DeserializeVector(const Pickle
& pickle
) const {
38 return db_
.DeserializeVector(pickle
);
41 void FormsAreEqual(const PasswordForm
& expected
, const PasswordForm
& actual
) {
42 PasswordForm
expected_copy(expected
);
43 #if defined(OS_MACOSX)
44 // On the Mac we should never be storing passwords in the database.
45 expected_copy
.password_value
= ASCIIToUTF16("");
47 EXPECT_EQ(expected_copy
, actual
);
50 base::ScopedTempDir temp_dir_
;
55 TEST_F(LoginDatabaseTest
, Logins
) {
56 std::vector
<PasswordForm
*> result
;
58 // Verify the database is empty.
59 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
60 EXPECT_EQ(0U, result
.size());
62 // Example password form.
64 form
.origin
= GURL("http://accounts.google.com/LoginAuth");
65 form
.action
= GURL("http://accounts.google.com/Login");
66 form
.username_element
= ASCIIToUTF16("Email");
67 form
.username_value
= ASCIIToUTF16("test@gmail.com");
68 form
.password_element
= ASCIIToUTF16("Passwd");
69 form
.password_value
= ASCIIToUTF16("test");
70 form
.submit_element
= ASCIIToUTF16("signIn");
71 form
.signon_realm
= "http://www.google.com/";
72 form
.ssl_valid
= false;
73 form
.preferred
= false;
74 form
.scheme
= PasswordForm::SCHEME_HTML
;
76 form
.form_data
.name
= ASCIIToUTF16("form_name");
77 form
.form_data
.method
= ASCIIToUTF16("POST");
79 // Add it and make sure it is there and that all the fields were retrieved
81 EXPECT_TRUE(db_
.AddLogin(form
));
82 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
83 EXPECT_EQ(1U, result
.size());
84 FormsAreEqual(form
, *result
[0]);
88 // Match against an exact copy.
89 EXPECT_TRUE(db_
.GetLogins(form
, &result
));
90 EXPECT_EQ(1U, result
.size());
94 // The example site changes...
95 PasswordForm
form2(form
);
96 form2
.origin
= GURL("http://www.google.com/new/accounts/LoginAuth");
97 form2
.submit_element
= ASCIIToUTF16("reallySignIn");
99 // Match against an inexact copy
100 EXPECT_TRUE(db_
.GetLogins(form2
, &result
));
101 EXPECT_EQ(1U, result
.size());
105 // Uh oh, the site changed origin & action URLs all at once!
106 PasswordForm
form3(form2
);
107 form3
.action
= GURL("http://www.google.com/new/accounts/Login");
109 // signon_realm is the same, should match.
110 EXPECT_TRUE(db_
.GetLogins(form3
, &result
));
111 EXPECT_EQ(1U, result
.size());
115 // Imagine the site moves to a secure server for login.
116 PasswordForm
form4(form3
);
117 form4
.signon_realm
= "https://www.google.com/";
118 form4
.ssl_valid
= true;
120 // We have only an http record, so no match for this.
121 EXPECT_TRUE(db_
.GetLogins(form4
, &result
));
122 EXPECT_EQ(0U, result
.size());
124 // Let's imagine the user logs into the secure site.
125 EXPECT_TRUE(db_
.AddLogin(form4
));
126 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
127 EXPECT_EQ(2U, result
.size());
132 // Now the match works
133 EXPECT_TRUE(db_
.GetLogins(form4
, &result
));
134 EXPECT_EQ(1U, result
.size());
138 // The user chose to forget the original but not the new.
139 EXPECT_TRUE(db_
.RemoveLogin(form
));
140 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
141 EXPECT_EQ(1U, result
.size());
145 // The old form wont match the new site (http vs https).
146 EXPECT_TRUE(db_
.GetLogins(form
, &result
));
147 EXPECT_EQ(0U, result
.size());
149 // The user's request for the HTTPS site is intercepted
150 // by an attacker who presents an invalid SSL cert.
151 PasswordForm
form5(form4
);
154 // It will match in this case.
155 EXPECT_TRUE(db_
.GetLogins(form5
, &result
));
156 EXPECT_EQ(1U, result
.size());
160 // User changes his password.
161 PasswordForm
form6(form5
);
162 form6
.password_value
= ASCIIToUTF16("test6");
163 form6
.preferred
= true;
165 // We update, and check to make sure it matches the
166 // old form, and there is only one record.
167 int rows_changed
= 0;
168 EXPECT_TRUE(db_
.UpdateLogin(form6
, &rows_changed
));
169 EXPECT_EQ(1, rows_changed
);
171 EXPECT_TRUE(db_
.GetLogins(form5
, &result
));
172 EXPECT_EQ(1U, result
.size());
176 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
177 EXPECT_EQ(1U, result
.size());
178 // Password element was updated.
179 #if defined(OS_MACOSX)
180 // On the Mac we should never be storing passwords in the database.
181 EXPECT_EQ(base::string16(), result
[0]->password_value
);
183 EXPECT_EQ(form6
.password_value
, result
[0]->password_value
);
186 EXPECT_TRUE(form6
.preferred
);
190 // Make sure everything can disappear.
191 EXPECT_TRUE(db_
.RemoveLogin(form4
));
192 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
193 EXPECT_EQ(0U, result
.size());
196 TEST_F(LoginDatabaseTest
, TestPublicSuffixDomainMatching
) {
197 PSLMatchingHelper::EnablePublicSuffixDomainMatchingForTesting();
198 std::vector
<PasswordForm
*> result
;
200 // Verify the database is empty.
201 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
202 EXPECT_EQ(0U, result
.size());
204 // Example password form.
206 form
.origin
= GURL("https://foo.com/");
207 form
.action
= GURL("https://foo.com/login");
208 form
.username_element
= ASCIIToUTF16("username");
209 form
.username_value
= ASCIIToUTF16("test@gmail.com");
210 form
.password_element
= ASCIIToUTF16("password");
211 form
.password_value
= ASCIIToUTF16("test");
212 form
.submit_element
= ASCIIToUTF16("");
213 form
.signon_realm
= "https://foo.com/";
214 form
.ssl_valid
= true;
215 form
.preferred
= false;
216 form
.scheme
= PasswordForm::SCHEME_HTML
;
218 // Add it and make sure it is there.
219 EXPECT_TRUE(db_
.AddLogin(form
));
220 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
221 EXPECT_EQ(1U, result
.size());
225 // Match against an exact copy.
226 EXPECT_TRUE(db_
.GetLogins(form
, &result
));
227 EXPECT_EQ(1U, result
.size());
231 // We go to the mobile site.
232 PasswordForm
form2(form
);
233 form2
.origin
= GURL("https://mobile.foo.com/");
234 form2
.action
= GURL("https://mobile.foo.com/login");
235 form2
.signon_realm
= "https://mobile.foo.com/";
237 // Match against the mobile site.
238 EXPECT_TRUE(db_
.GetLogins(form2
, &result
));
239 EXPECT_EQ(1U, result
.size());
240 EXPECT_EQ("https://mobile.foo.com/", result
[0]->signon_realm
);
241 EXPECT_EQ("https://foo.com/", result
[0]->original_signon_realm
);
246 TEST_F(LoginDatabaseTest
, TestPublicSuffixDomainMatchingShouldMatchingApply
) {
247 PSLMatchingHelper::EnablePublicSuffixDomainMatchingForTesting();
248 std::vector
<PasswordForm
*> result
;
250 // Verify the database is empty.
251 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
252 EXPECT_EQ(0U, result
.size());
254 // Example password form.
256 form
.origin
= GURL("https://accounts.google.com/");
257 form
.action
= GURL("https://accounts.google.com/login");
258 form
.username_element
= ASCIIToUTF16("username");
259 form
.username_value
= ASCIIToUTF16("test@gmail.com");
260 form
.password_element
= ASCIIToUTF16("password");
261 form
.password_value
= ASCIIToUTF16("test");
262 form
.submit_element
= ASCIIToUTF16("");
263 form
.signon_realm
= "https://accounts.google.com/";
264 form
.ssl_valid
= true;
265 form
.preferred
= false;
266 form
.scheme
= PasswordForm::SCHEME_HTML
;
268 // Add it and make sure it is there.
269 EXPECT_TRUE(db_
.AddLogin(form
));
270 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
271 EXPECT_EQ(1U, result
.size());
275 // Match against an exact copy.
276 EXPECT_TRUE(db_
.GetLogins(form
, &result
));
277 EXPECT_EQ(1U, result
.size());
281 // We go to a different site on the same domain where feature is not needed.
282 PasswordForm
form2(form
);
283 form2
.origin
= GURL("https://some.other.google.com/");
284 form2
.action
= GURL("https://some.other.google.com/login");
285 form2
.signon_realm
= "https://some.other.google.com/";
287 // Match against the other site. Should not match since feature should not be
288 // enabled for this domain.
289 EXPECT_TRUE(db_
.GetLogins(form2
, &result
));
290 EXPECT_EQ(0U, result
.size());
293 // This test fails if the implementation of GetLogins uses GetCachedStatement
294 // instead of GetUniqueStatement, since REGEXP is in use. See
295 // http://crbug.com/248608.
296 TEST_F(LoginDatabaseTest
, TestPublicSuffixDomainMatchingDifferentSites
) {
297 PSLMatchingHelper::EnablePublicSuffixDomainMatchingForTesting();
298 std::vector
<PasswordForm
*> result
;
300 // Verify the database is empty.
301 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
302 EXPECT_EQ(0U, result
.size());
304 // Example password form.
306 form
.origin
= GURL("https://foo.com/");
307 form
.action
= GURL("https://foo.com/login");
308 form
.username_element
= ASCIIToUTF16("username");
309 form
.username_value
= ASCIIToUTF16("test@gmail.com");
310 form
.password_element
= ASCIIToUTF16("password");
311 form
.password_value
= ASCIIToUTF16("test");
312 form
.submit_element
= ASCIIToUTF16("");
313 form
.signon_realm
= "https://foo.com/";
314 form
.ssl_valid
= true;
315 form
.preferred
= false;
316 form
.scheme
= PasswordForm::SCHEME_HTML
;
318 // Add it and make sure it is there.
319 EXPECT_TRUE(db_
.AddLogin(form
));
320 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
321 EXPECT_EQ(1U, result
.size());
325 // Match against an exact copy.
326 EXPECT_TRUE(db_
.GetLogins(form
, &result
));
327 EXPECT_EQ(1U, result
.size());
331 // We go to the mobile site.
332 PasswordForm
form2(form
);
333 form2
.origin
= GURL("https://mobile.foo.com/");
334 form2
.action
= GURL("https://mobile.foo.com/login");
335 form2
.signon_realm
= "https://mobile.foo.com/";
337 // Match against the mobile site.
338 EXPECT_TRUE(db_
.GetLogins(form2
, &result
));
339 EXPECT_EQ(1U, result
.size());
340 EXPECT_EQ("https://mobile.foo.com/", result
[0]->signon_realm
);
341 EXPECT_EQ("https://foo.com/", result
[0]->original_signon_realm
);
345 // Add baz.com desktop site.
346 form
.origin
= GURL("https://baz.com/login/");
347 form
.action
= GURL("https://baz.com/login/");
348 form
.username_element
= ASCIIToUTF16("email");
349 form
.username_value
= ASCIIToUTF16("test@gmail.com");
350 form
.password_element
= ASCIIToUTF16("password");
351 form
.password_value
= ASCIIToUTF16("test");
352 form
.submit_element
= ASCIIToUTF16("");
353 form
.signon_realm
= "https://baz.com/";
354 form
.ssl_valid
= true;
355 form
.preferred
= false;
356 form
.scheme
= PasswordForm::SCHEME_HTML
;
358 // Add it and make sure it is there.
359 EXPECT_TRUE(db_
.AddLogin(form
));
360 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
361 EXPECT_EQ(2U, result
.size());
366 // We go to the mobile site of baz.com.
367 PasswordForm
form3(form
);
368 form3
.origin
= GURL("https://m.baz.com/login/");
369 form3
.action
= GURL("https://m.baz.com/login/");
370 form3
.signon_realm
= "https://m.baz.com/";
372 // Match against the mobile site of baz.com.
373 EXPECT_TRUE(db_
.GetLogins(form3
, &result
));
374 EXPECT_EQ(1U, result
.size());
375 EXPECT_EQ("https://m.baz.com/", result
[0]->signon_realm
);
376 EXPECT_EQ("https://baz.com/", result
[0]->original_signon_realm
);
381 PasswordForm
GetFormWithNewSignonRealm(PasswordForm form
,
382 std::string signon_realm
) {
383 PasswordForm
form2(form
);
384 form2
.origin
= GURL(signon_realm
);
385 form2
.action
= GURL(signon_realm
);
386 form2
.signon_realm
= signon_realm
;
390 TEST_F(LoginDatabaseTest
, TestPublicSuffixDomainMatchingRegexp
) {
391 PSLMatchingHelper::EnablePublicSuffixDomainMatchingForTesting();
392 std::vector
<PasswordForm
*> result
;
394 // Verify the database is empty.
395 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
396 EXPECT_EQ(0U, result
.size());
398 // Example password form.
400 form
.origin
= GURL("http://foo.com/");
401 form
.action
= GURL("http://foo.com/login");
402 form
.username_element
= ASCIIToUTF16("username");
403 form
.username_value
= ASCIIToUTF16("test@gmail.com");
404 form
.password_element
= ASCIIToUTF16("password");
405 form
.password_value
= ASCIIToUTF16("test");
406 form
.submit_element
= ASCIIToUTF16("");
407 form
.signon_realm
= "http://foo.com/";
408 form
.ssl_valid
= false;
409 form
.preferred
= false;
410 form
.scheme
= PasswordForm::SCHEME_HTML
;
412 // Add it and make sure it is there.
413 EXPECT_TRUE(db_
.AddLogin(form
));
414 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
415 EXPECT_EQ(1U, result
.size());
419 // Example password form that has - in the domain name.
420 PasswordForm form_dash
=
421 GetFormWithNewSignonRealm(form
, "http://www.foo-bar.com/");
423 // Add it and make sure it is there.
424 EXPECT_TRUE(db_
.AddLogin(form_dash
));
425 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
426 EXPECT_EQ(2U, result
.size());
431 // Match against an exact copy.
432 EXPECT_TRUE(db_
.GetLogins(form
, &result
));
433 EXPECT_EQ(1U, result
.size());
437 // www.foo.com should match.
438 PasswordForm form2
= GetFormWithNewSignonRealm(form
, "http://www.foo.com/");
439 EXPECT_TRUE(db_
.GetLogins(form2
, &result
));
440 EXPECT_EQ(1U, result
.size());
444 // a.b.foo.com should match.
445 form2
= GetFormWithNewSignonRealm(form
, "http://a.b.foo.com/");
446 EXPECT_TRUE(db_
.GetLogins(form2
, &result
));
447 EXPECT_EQ(1U, result
.size());
451 // a-b.foo.com should match.
452 form2
= GetFormWithNewSignonRealm(form
, "http://a-b.foo.com/");
453 EXPECT_TRUE(db_
.GetLogins(form2
, &result
));
454 EXPECT_EQ(1U, result
.size());
458 // foo-bar.com should match.
459 form2
= GetFormWithNewSignonRealm(form
, "http://foo-bar.com/");
460 EXPECT_TRUE(db_
.GetLogins(form2
, &result
));
461 EXPECT_EQ(1U, result
.size());
465 // www.foo-bar.com should match.
466 form2
= GetFormWithNewSignonRealm(form
, "http://www.foo-bar.com/");
467 EXPECT_TRUE(db_
.GetLogins(form2
, &result
));
468 EXPECT_EQ(1U, result
.size());
472 // a.b.foo-bar.com should match.
473 form2
= GetFormWithNewSignonRealm(form
, "http://a.b.foo-bar.com/");
474 EXPECT_TRUE(db_
.GetLogins(form2
, &result
));
475 EXPECT_EQ(1U, result
.size());
479 // a-b.foo-bar.com should match.
480 form2
= GetFormWithNewSignonRealm(form
, "http://a-b.foo-bar.com/");
481 EXPECT_TRUE(db_
.GetLogins(form2
, &result
));
482 EXPECT_EQ(1U, result
.size());
486 // foo.com with port 1337 should not match.
487 form2
= GetFormWithNewSignonRealm(form
, "http://foo.com:1337/");
488 EXPECT_TRUE(db_
.GetLogins(form2
, &result
));
489 EXPECT_EQ(0U, result
.size());
491 // http://foo.com should not match since the scheme is wrong.
492 form2
= GetFormWithNewSignonRealm(form
, "https://foo.com/");
493 EXPECT_TRUE(db_
.GetLogins(form2
, &result
));
494 EXPECT_EQ(0U, result
.size());
496 // notfoo.com should not match.
497 form2
= GetFormWithNewSignonRealm(form
, "http://notfoo.com/");
498 EXPECT_TRUE(db_
.GetLogins(form2
, &result
));
499 EXPECT_EQ(0U, result
.size());
501 // baz.com should not match.
502 form2
= GetFormWithNewSignonRealm(form
, "http://baz.com/");
503 EXPECT_TRUE(db_
.GetLogins(form2
, &result
));
504 EXPECT_EQ(0U, result
.size());
506 // foo-baz.com should not match.
507 form2
= GetFormWithNewSignonRealm(form
, "http://foo-baz.com/");
508 EXPECT_TRUE(db_
.GetLogins(form2
, &result
));
509 EXPECT_EQ(0U, result
.size());
512 static bool AddTimestampedLogin(LoginDatabase
* db
, std::string url
,
513 const std::string
& unique_string
,
514 const base::Time
& time
) {
515 // Example password form.
517 form
.origin
= GURL(url
+ std::string("/LoginAuth"));
518 form
.username_element
= ASCIIToUTF16(unique_string
);
519 form
.username_value
= ASCIIToUTF16(unique_string
);
520 form
.password_element
= ASCIIToUTF16(unique_string
);
521 form
.submit_element
= ASCIIToUTF16("signIn");
522 form
.signon_realm
= url
;
523 form
.date_created
= time
;
524 return db
->AddLogin(form
);
527 static void ClearResults(std::vector
<PasswordForm
*>* results
) {
528 for (size_t i
= 0; i
< results
->size(); ++i
) {
529 delete (*results
)[i
];
534 TEST_F(LoginDatabaseTest
, ClearPrivateData_SavedPasswords
) {
535 std::vector
<PasswordForm
*> result
;
537 // Verify the database is empty.
538 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
539 EXPECT_EQ(0U, result
.size());
541 base::Time now
= base::Time::Now();
542 base::TimeDelta one_day
= base::TimeDelta::FromDays(1);
544 // Create one with a 0 time.
545 EXPECT_TRUE(AddTimestampedLogin(&db_
, "1", "foo1", base::Time()));
546 // Create one for now and +/- 1 day.
547 EXPECT_TRUE(AddTimestampedLogin(&db_
, "2", "foo2", now
- one_day
));
548 EXPECT_TRUE(AddTimestampedLogin(&db_
, "3", "foo3", now
));
549 EXPECT_TRUE(AddTimestampedLogin(&db_
, "4", "foo4", now
+ one_day
));
551 // Verify inserts worked.
552 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
553 EXPECT_EQ(4U, result
.size());
554 ClearResults(&result
);
556 // Get everything from today's date and on.
557 EXPECT_TRUE(db_
.GetLoginsCreatedBetween(now
, base::Time(), &result
));
558 EXPECT_EQ(2U, result
.size());
559 ClearResults(&result
);
561 // Delete everything from today's date and on.
562 db_
.RemoveLoginsCreatedBetween(now
, base::Time());
564 // Should have deleted half of what we inserted.
565 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
566 EXPECT_EQ(2U, result
.size());
567 ClearResults(&result
);
569 // Delete with 0 date (should delete all).
570 db_
.RemoveLoginsCreatedBetween(base::Time(), base::Time());
572 // Verify nothing is left.
573 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
574 EXPECT_EQ(0U, result
.size());
577 TEST_F(LoginDatabaseTest
, BlacklistedLogins
) {
578 std::vector
<PasswordForm
*> result
;
580 // Verify the database is empty.
581 EXPECT_TRUE(db_
.GetBlacklistLogins(&result
));
582 ASSERT_EQ(0U, result
.size());
584 // Save a form as blacklisted.
586 form
.origin
= GURL("http://accounts.google.com/LoginAuth");
587 form
.action
= GURL("http://accounts.google.com/Login");
588 form
.username_element
= ASCIIToUTF16("Email");
589 form
.password_element
= ASCIIToUTF16("Passwd");
590 form
.submit_element
= ASCIIToUTF16("signIn");
591 form
.signon_realm
= "http://www.google.com/";
592 form
.ssl_valid
= false;
593 form
.preferred
= true;
594 form
.blacklisted_by_user
= true;
595 form
.scheme
= PasswordForm::SCHEME_HTML
;
596 EXPECT_TRUE(db_
.AddLogin(form
));
598 // Get all non-blacklisted logins (should be none).
599 EXPECT_TRUE(db_
.GetAutofillableLogins(&result
));
600 ASSERT_EQ(0U, result
.size());
602 // GetLogins should give the blacklisted result.
603 EXPECT_TRUE(db_
.GetLogins(form
, &result
));
604 EXPECT_EQ(1U, result
.size());
605 ClearResults(&result
);
607 // So should GetAllBlacklistedLogins.
608 EXPECT_TRUE(db_
.GetBlacklistLogins(&result
));
609 EXPECT_EQ(1U, result
.size());
610 ClearResults(&result
);
613 TEST_F(LoginDatabaseTest
, VectorSerialization
) {
615 std::vector
<base::string16
> vec
;
616 Pickle temp
= SerializeVector(vec
);
617 std::vector
<base::string16
> output
= DeserializeVector(temp
);
618 EXPECT_THAT(output
, Eq(vec
));
621 vec
.push_back(ASCIIToUTF16("first"));
622 vec
.push_back(ASCIIToUTF16("second"));
623 vec
.push_back(ASCIIToUTF16("third"));
625 temp
= SerializeVector(vec
);
626 output
= DeserializeVector(temp
);
627 EXPECT_THAT(output
, Eq(vec
));
630 #if defined(OS_POSIX)
631 // Only the current user has permission to read the database.
633 // Only POSIX because GetPosixFilePermissions() only exists on POSIX.
634 // This tests that sql::Connection::set_restrict_to_user() was called,
635 // and that function is a noop on non-POSIX platforms in any case.
636 TEST_F(LoginDatabaseTest
, FilePermissions
) {
637 int mode
= base::FILE_PERMISSION_MASK
;
638 EXPECT_TRUE(base::GetPosixFilePermissions(file_
, &mode
));
639 EXPECT_EQ((mode
& base::FILE_PERMISSION_USER_MASK
), mode
);
641 #endif // defined(OS_POSIX)