Upstream version 5.34.98.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / password_manager / login_database_unittest.cc
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.
4
5 #include "testing/gtest/include/gtest/gtest.h"
6
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"
19
20 using autofill::PasswordForm;
21 using base::ASCIIToUTF16;
22 using ::testing::Eq;
23
24 class LoginDatabaseTest : public testing::Test {
25  protected:
26   virtual void SetUp() {
27     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
28     file_ = temp_dir_.path().AppendASCII("TestMetadataStoreMacDatabase");
29
30     ASSERT_TRUE(db_.Init(file_));
31   }
32
33   Pickle SerializeVector(const std::vector<base::string16>& vec) const {
34     return db_.SerializeVector(vec);
35   }
36
37   std::vector<base::string16> DeserializeVector(const Pickle& pickle) const {
38     return db_.DeserializeVector(pickle);
39   }
40
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("");
46 #endif
47     EXPECT_EQ(expected_copy, actual);
48   }
49
50   base::ScopedTempDir temp_dir_;
51   base::FilePath file_;
52   LoginDatabase db_;
53 };
54
55 TEST_F(LoginDatabaseTest, Logins) {
56   std::vector<PasswordForm*> result;
57
58   // Verify the database is empty.
59   EXPECT_TRUE(db_.GetAutofillableLogins(&result));
60   EXPECT_EQ(0U, result.size());
61
62   // Example password form.
63   PasswordForm 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;
75   form.times_used = 1;
76   form.form_data.name = ASCIIToUTF16("form_name");
77   form.form_data.method = ASCIIToUTF16("POST");
78
79   // Add it and make sure it is there and that all the fields were retrieved
80   // correctly.
81   EXPECT_TRUE(db_.AddLogin(form));
82   EXPECT_TRUE(db_.GetAutofillableLogins(&result));
83   EXPECT_EQ(1U, result.size());
84   FormsAreEqual(form, *result[0]);
85   delete result[0];
86   result.clear();
87
88   // Match against an exact copy.
89   EXPECT_TRUE(db_.GetLogins(form, &result));
90   EXPECT_EQ(1U, result.size());
91   delete result[0];
92   result.clear();
93
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");
98
99   // Match against an inexact copy
100   EXPECT_TRUE(db_.GetLogins(form2, &result));
101   EXPECT_EQ(1U, result.size());
102   delete result[0];
103   result.clear();
104
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");
108
109   // signon_realm is the same, should match.
110   EXPECT_TRUE(db_.GetLogins(form3, &result));
111   EXPECT_EQ(1U, result.size());
112   delete result[0];
113   result.clear();
114
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;
119
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());
123
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());
128   delete result[0];
129   delete result[1];
130   result.clear();
131
132   // Now the match works
133   EXPECT_TRUE(db_.GetLogins(form4, &result));
134   EXPECT_EQ(1U, result.size());
135   delete result[0];
136   result.clear();
137
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());
142   delete result[0];
143   result.clear();
144
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());
148
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);
152   form5.ssl_valid = 0;
153
154   // It will match in this case.
155   EXPECT_TRUE(db_.GetLogins(form5, &result));
156   EXPECT_EQ(1U, result.size());
157   delete result[0];
158   result.clear();
159
160   // User changes his password.
161   PasswordForm form6(form5);
162   form6.password_value = ASCIIToUTF16("test6");
163   form6.preferred = true;
164
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);
170   // matches
171   EXPECT_TRUE(db_.GetLogins(form5, &result));
172   EXPECT_EQ(1U, result.size());
173   delete result[0];
174   result.clear();
175   // Only one record.
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);
182 #else
183   EXPECT_EQ(form6.password_value, result[0]->password_value);
184 #endif
185   // Preferred login.
186   EXPECT_TRUE(form6.preferred);
187   delete result[0];
188   result.clear();
189
190   // Make sure everything can disappear.
191   EXPECT_TRUE(db_.RemoveLogin(form4));
192   EXPECT_TRUE(db_.GetAutofillableLogins(&result));
193   EXPECT_EQ(0U, result.size());
194 }
195
196 TEST_F(LoginDatabaseTest, TestPublicSuffixDomainMatching) {
197   PSLMatchingHelper::EnablePublicSuffixDomainMatchingForTesting();
198   std::vector<PasswordForm*> result;
199
200   // Verify the database is empty.
201   EXPECT_TRUE(db_.GetAutofillableLogins(&result));
202   EXPECT_EQ(0U, result.size());
203
204   // Example password form.
205   PasswordForm 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;
217
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());
222   delete result[0];
223   result.clear();
224
225   // Match against an exact copy.
226   EXPECT_TRUE(db_.GetLogins(form, &result));
227   EXPECT_EQ(1U, result.size());
228   delete result[0];
229   result.clear();
230
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/";
236
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);
242   delete result[0];
243   result.clear();
244 }
245
246 TEST_F(LoginDatabaseTest, TestPublicSuffixDomainMatchingShouldMatchingApply) {
247   PSLMatchingHelper::EnablePublicSuffixDomainMatchingForTesting();
248   std::vector<PasswordForm*> result;
249
250   // Verify the database is empty.
251   EXPECT_TRUE(db_.GetAutofillableLogins(&result));
252   EXPECT_EQ(0U, result.size());
253
254   // Example password form.
255   PasswordForm 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;
267
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());
272   delete result[0];
273   result.clear();
274
275   // Match against an exact copy.
276   EXPECT_TRUE(db_.GetLogins(form, &result));
277   EXPECT_EQ(1U, result.size());
278   delete result[0];
279   result.clear();
280
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/";
286
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());
291 }
292
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;
299
300   // Verify the database is empty.
301   EXPECT_TRUE(db_.GetAutofillableLogins(&result));
302   EXPECT_EQ(0U, result.size());
303
304   // Example password form.
305   PasswordForm 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;
317
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());
322   delete result[0];
323   result.clear();
324
325   // Match against an exact copy.
326   EXPECT_TRUE(db_.GetLogins(form, &result));
327   EXPECT_EQ(1U, result.size());
328   delete result[0];
329   result.clear();
330
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/";
336
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);
342   delete result[0];
343   result.clear();
344
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;
357
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());
362   delete result[0];
363   delete result[1];
364   result.clear();
365
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/";
371
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);
377   delete result[0];
378   result.clear();
379 }
380
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;
387   return form2;
388 }
389
390 TEST_F(LoginDatabaseTest, TestPublicSuffixDomainMatchingRegexp) {
391   PSLMatchingHelper::EnablePublicSuffixDomainMatchingForTesting();
392   std::vector<PasswordForm*> result;
393
394   // Verify the database is empty.
395   EXPECT_TRUE(db_.GetAutofillableLogins(&result));
396   EXPECT_EQ(0U, result.size());
397
398   // Example password form.
399   PasswordForm 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;
411
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());
416   delete result[0];
417   result.clear();
418
419   // Example password form that has - in the domain name.
420   PasswordForm form_dash =
421       GetFormWithNewSignonRealm(form, "http://www.foo-bar.com/");
422
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());
427   delete result[0];
428   delete result[1];
429   result.clear();
430
431   // Match against an exact copy.
432   EXPECT_TRUE(db_.GetLogins(form, &result));
433   EXPECT_EQ(1U, result.size());
434   delete result[0];
435   result.clear();
436
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());
441   delete result[0];
442   result.clear();
443
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());
448   delete result[0];
449   result.clear();
450
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());
455   delete result[0];
456   result.clear();
457
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());
462   delete result[0];
463   result.clear();
464
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());
469   delete result[0];
470   result.clear();
471
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());
476   delete result[0];
477   result.clear();
478
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());
483   delete result[0];
484   result.clear();
485
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());
490
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());
495
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());
500
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());
505
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());
510 }
511
512 static bool AddTimestampedLogin(LoginDatabase* db, std::string url,
513                                 const std::string& unique_string,
514                                 const base::Time& time) {
515   // Example password form.
516   PasswordForm 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);
525 }
526
527 static void ClearResults(std::vector<PasswordForm*>* results) {
528   for (size_t i = 0; i < results->size(); ++i) {
529     delete (*results)[i];
530   }
531   results->clear();
532 }
533
534 TEST_F(LoginDatabaseTest, ClearPrivateData_SavedPasswords) {
535   std::vector<PasswordForm*> result;
536
537   // Verify the database is empty.
538   EXPECT_TRUE(db_.GetAutofillableLogins(&result));
539   EXPECT_EQ(0U, result.size());
540
541   base::Time now = base::Time::Now();
542   base::TimeDelta one_day = base::TimeDelta::FromDays(1);
543
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));
550
551   // Verify inserts worked.
552   EXPECT_TRUE(db_.GetAutofillableLogins(&result));
553   EXPECT_EQ(4U, result.size());
554   ClearResults(&result);
555
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);
560
561   // Delete everything from today's date and on.
562   db_.RemoveLoginsCreatedBetween(now, base::Time());
563
564   // Should have deleted half of what we inserted.
565   EXPECT_TRUE(db_.GetAutofillableLogins(&result));
566   EXPECT_EQ(2U, result.size());
567   ClearResults(&result);
568
569   // Delete with 0 date (should delete all).
570   db_.RemoveLoginsCreatedBetween(base::Time(), base::Time());
571
572   // Verify nothing is left.
573   EXPECT_TRUE(db_.GetAutofillableLogins(&result));
574   EXPECT_EQ(0U, result.size());
575 }
576
577 TEST_F(LoginDatabaseTest, BlacklistedLogins) {
578   std::vector<PasswordForm*> result;
579
580   // Verify the database is empty.
581   EXPECT_TRUE(db_.GetBlacklistLogins(&result));
582   ASSERT_EQ(0U, result.size());
583
584   // Save a form as blacklisted.
585   PasswordForm form;
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));
597
598   // Get all non-blacklisted logins (should be none).
599   EXPECT_TRUE(db_.GetAutofillableLogins(&result));
600   ASSERT_EQ(0U, result.size());
601
602   // GetLogins should give the blacklisted result.
603   EXPECT_TRUE(db_.GetLogins(form, &result));
604   EXPECT_EQ(1U, result.size());
605   ClearResults(&result);
606
607   // So should GetAllBlacklistedLogins.
608   EXPECT_TRUE(db_.GetBlacklistLogins(&result));
609   EXPECT_EQ(1U, result.size());
610   ClearResults(&result);
611 }
612
613 TEST_F(LoginDatabaseTest, VectorSerialization) {
614   // Empty vector.
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));
619
620   // Normal data.
621   vec.push_back(ASCIIToUTF16("first"));
622   vec.push_back(ASCIIToUTF16("second"));
623   vec.push_back(ASCIIToUTF16("third"));
624
625   temp = SerializeVector(vec);
626   output = DeserializeVector(temp);
627   EXPECT_THAT(output, Eq(vec));
628 }
629
630 #if defined(OS_POSIX)
631 // Only the current user has permission to read the database.
632 //
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);
640 }
641 #endif  // defined(OS_POSIX)