| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 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 "base/file_util.h" | |
| 6 #include "base/path_service.h" | |
| 7 #include "base/string_number_conversions.h" | |
| 8 #include "base/time.h" | |
| 9 #include "base/utf_string_conversions.h" | |
| 10 #include "chrome/browser/webdata/logins_table.h" | |
| 11 #include "chrome/browser/webdata/web_database.h" | |
| 12 #include "chrome/common/chrome_paths.h" | |
| 13 #include "testing/gtest/include/gtest/gtest.h" | |
| 14 #include "webkit/forms/password_form.h" | |
| 15 | |
| 16 using base::Time; | |
| 17 using base::TimeDelta; | |
| 18 using webkit::forms::PasswordForm; | |
| 19 | |
| 20 class LoginsTableTest : public testing::Test { | |
| 21 public: | |
| 22 LoginsTableTest() {} | |
| 23 virtual ~LoginsTableTest() {} | |
| 24 | |
| 25 protected: | |
| 26 virtual void SetUp() { | |
| 27 PathService::Get(chrome::DIR_TEST_DATA, &file_); | |
| 28 const std::string test_db = "TestWebDatabase" + | |
| 29 base::Int64ToString(Time::Now().ToTimeT()) + | |
| 30 ".db"; | |
| 31 file_ = file_.AppendASCII(test_db); | |
| 32 file_util::Delete(file_, false); | |
| 33 } | |
| 34 | |
| 35 virtual void TearDown() { | |
| 36 file_util::Delete(file_, false); | |
| 37 } | |
| 38 | |
| 39 FilePath file_; | |
| 40 | |
| 41 private: | |
| 42 DISALLOW_COPY_AND_ASSIGN(LoginsTableTest); | |
| 43 }; | |
| 44 | |
| 45 TEST_F(LoginsTableTest, Logins) { | |
| 46 WebDatabase db; | |
| 47 | |
| 48 ASSERT_EQ(sql::INIT_OK, db.Init(file_)); | |
| 49 | |
| 50 std::vector<PasswordForm*> result; | |
| 51 | |
| 52 // Verify the database is empty. | |
| 53 EXPECT_TRUE(db.GetLoginsTable()->GetAllLogins(&result, true)); | |
| 54 EXPECT_EQ(0U, result.size()); | |
| 55 | |
| 56 // Example password form. | |
| 57 PasswordForm form; | |
| 58 form.origin = GURL("http://www.google.com/accounts/LoginAuth"); | |
| 59 form.action = GURL("http://www.google.com/accounts/Login"); | |
| 60 form.username_element = ASCIIToUTF16("Email"); | |
| 61 form.username_value = ASCIIToUTF16("test@gmail.com"); | |
| 62 form.password_element = ASCIIToUTF16("Passwd"); | |
| 63 form.password_value = ASCIIToUTF16("test"); | |
| 64 form.submit_element = ASCIIToUTF16("signIn"); | |
| 65 form.signon_realm = "http://www.google.com/"; | |
| 66 form.ssl_valid = false; | |
| 67 form.preferred = false; | |
| 68 form.scheme = PasswordForm::SCHEME_HTML; | |
| 69 | |
| 70 // Add it and make sure it is there. | |
| 71 EXPECT_TRUE(db.GetLoginsTable()->AddLogin(form)); | |
| 72 EXPECT_TRUE(db.GetLoginsTable()->GetAllLogins(&result, true)); | |
| 73 EXPECT_EQ(1U, result.size()); | |
| 74 delete result[0]; | |
| 75 result.clear(); | |
| 76 | |
| 77 // Match against an exact copy. | |
| 78 EXPECT_TRUE(db.GetLoginsTable()->GetLogins(form, &result)); | |
| 79 EXPECT_EQ(1U, result.size()); | |
| 80 delete result[0]; | |
| 81 result.clear(); | |
| 82 | |
| 83 // The example site changes... | |
| 84 PasswordForm form2(form); | |
| 85 form2.origin = GURL("http://www.google.com/new/accounts/LoginAuth"); | |
| 86 form2.submit_element = ASCIIToUTF16("reallySignIn"); | |
| 87 | |
| 88 // Match against an inexact copy | |
| 89 EXPECT_TRUE(db.GetLoginsTable()->GetLogins(form2, &result)); | |
| 90 EXPECT_EQ(1U, result.size()); | |
| 91 delete result[0]; | |
| 92 result.clear(); | |
| 93 | |
| 94 // Uh oh, the site changed origin & action URL's all at once! | |
| 95 PasswordForm form3(form2); | |
| 96 form3.action = GURL("http://www.google.com/new/accounts/Login"); | |
| 97 | |
| 98 // signon_realm is the same, should match. | |
| 99 EXPECT_TRUE(db.GetLoginsTable()->GetLogins(form3, &result)); | |
| 100 EXPECT_EQ(1U, result.size()); | |
| 101 delete result[0]; | |
| 102 result.clear(); | |
| 103 | |
| 104 // Imagine the site moves to a secure server for login. | |
| 105 PasswordForm form4(form3); | |
| 106 form4.signon_realm = "https://www.google.com/"; | |
| 107 form4.ssl_valid = true; | |
| 108 | |
| 109 // We have only an http record, so no match for this. | |
| 110 EXPECT_TRUE(db.GetLoginsTable()->GetLogins(form4, &result)); | |
| 111 EXPECT_EQ(0U, result.size()); | |
| 112 | |
| 113 // Let's imagine the user logs into the secure site. | |
| 114 EXPECT_TRUE(db.GetLoginsTable()->AddLogin(form4)); | |
| 115 EXPECT_TRUE(db.GetLoginsTable()->GetAllLogins(&result, true)); | |
| 116 EXPECT_EQ(2U, result.size()); | |
| 117 delete result[0]; | |
| 118 delete result[1]; | |
| 119 result.clear(); | |
| 120 | |
| 121 // Now the match works | |
| 122 EXPECT_TRUE(db.GetLoginsTable()->GetLogins(form4, &result)); | |
| 123 EXPECT_EQ(1U, result.size()); | |
| 124 delete result[0]; | |
| 125 result.clear(); | |
| 126 | |
| 127 // The user chose to forget the original but not the new. | |
| 128 EXPECT_TRUE(db.GetLoginsTable()->RemoveLogin(form)); | |
| 129 EXPECT_TRUE(db.GetLoginsTable()->GetAllLogins(&result, true)); | |
| 130 EXPECT_EQ(1U, result.size()); | |
| 131 delete result[0]; | |
| 132 result.clear(); | |
| 133 | |
| 134 // The old form wont match the new site (http vs https). | |
| 135 EXPECT_TRUE(db.GetLoginsTable()->GetLogins(form, &result)); | |
| 136 EXPECT_EQ(0U, result.size()); | |
| 137 | |
| 138 // The user's request for the HTTPS site is intercepted | |
| 139 // by an attacker who presents an invalid SSL cert. | |
| 140 PasswordForm form5(form4); | |
| 141 form5.ssl_valid = 0; | |
| 142 | |
| 143 // It will match in this case. | |
| 144 EXPECT_TRUE(db.GetLoginsTable()->GetLogins(form5, &result)); | |
| 145 EXPECT_EQ(1U, result.size()); | |
| 146 delete result[0]; | |
| 147 result.clear(); | |
| 148 | |
| 149 // User changes his password. | |
| 150 PasswordForm form6(form5); | |
| 151 form6.password_value = ASCIIToUTF16("test6"); | |
| 152 form6.preferred = true; | |
| 153 | |
| 154 // We update, and check to make sure it matches the | |
| 155 // old form, and there is only one record. | |
| 156 EXPECT_TRUE(db.GetLoginsTable()->UpdateLogin(form6)); | |
| 157 // matches | |
| 158 EXPECT_TRUE(db.GetLoginsTable()->GetLogins(form5, &result)); | |
| 159 EXPECT_EQ(1U, result.size()); | |
| 160 delete result[0]; | |
| 161 result.clear(); | |
| 162 // Only one record. | |
| 163 EXPECT_TRUE(db.GetLoginsTable()->GetAllLogins(&result, true)); | |
| 164 EXPECT_EQ(1U, result.size()); | |
| 165 // password element was updated. | |
| 166 EXPECT_EQ(form6.password_value, result[0]->password_value); | |
| 167 // Preferred login. | |
| 168 EXPECT_TRUE(form6.preferred); | |
| 169 delete result[0]; | |
| 170 result.clear(); | |
| 171 | |
| 172 // Make sure everything can disappear. | |
| 173 EXPECT_TRUE(db.GetLoginsTable()->RemoveLogin(form4)); | |
| 174 EXPECT_TRUE(db.GetLoginsTable()->GetAllLogins(&result, true)); | |
| 175 EXPECT_EQ(0U, result.size()); | |
| 176 } | |
| 177 | |
| 178 static bool AddTimestampedLogin(WebDatabase* db, std::string url, | |
| 179 const std::string& unique_string, | |
| 180 const Time& time) { | |
| 181 // Example password form. | |
| 182 PasswordForm form; | |
| 183 form.origin = GURL(url + std::string("/LoginAuth")); | |
| 184 form.username_element = ASCIIToUTF16(unique_string); | |
| 185 form.username_value = ASCIIToUTF16(unique_string); | |
| 186 form.password_element = ASCIIToUTF16(unique_string); | |
| 187 form.submit_element = ASCIIToUTF16("signIn"); | |
| 188 form.signon_realm = url; | |
| 189 form.date_created = time; | |
| 190 return db->GetLoginsTable()->AddLogin(form); | |
| 191 } | |
| 192 | |
| 193 static void ClearResults(std::vector<PasswordForm*>* results) { | |
| 194 for (size_t i = 0; i < results->size(); ++i) { | |
| 195 delete (*results)[i]; | |
| 196 } | |
| 197 results->clear(); | |
| 198 } | |
| 199 | |
| 200 TEST_F(LoginsTableTest, ClearPrivateData_SavedPasswords) { | |
| 201 WebDatabase db; | |
| 202 | |
| 203 ASSERT_EQ(sql::INIT_OK, db.Init(file_)); | |
| 204 | |
| 205 std::vector<PasswordForm*> result; | |
| 206 | |
| 207 // Verify the database is empty. | |
| 208 EXPECT_TRUE(db.GetLoginsTable()->GetAllLogins(&result, true)); | |
| 209 EXPECT_EQ(0U, result.size()); | |
| 210 | |
| 211 Time now = Time::Now(); | |
| 212 TimeDelta one_day = TimeDelta::FromDays(1); | |
| 213 | |
| 214 // Create one with a 0 time. | |
| 215 EXPECT_TRUE(AddTimestampedLogin(&db, "1", "foo1", Time())); | |
| 216 // Create one for now and +/- 1 day. | |
| 217 EXPECT_TRUE(AddTimestampedLogin(&db, "2", "foo2", now - one_day)); | |
| 218 EXPECT_TRUE(AddTimestampedLogin(&db, "3", "foo3", now)); | |
| 219 EXPECT_TRUE(AddTimestampedLogin(&db, "4", "foo4", now + one_day)); | |
| 220 | |
| 221 // Verify inserts worked. | |
| 222 EXPECT_TRUE(db.GetLoginsTable()->GetAllLogins(&result, true)); | |
| 223 EXPECT_EQ(4U, result.size()); | |
| 224 ClearResults(&result); | |
| 225 | |
| 226 // Delete everything from today's date and on. | |
| 227 db.GetLoginsTable()->RemoveLoginsCreatedBetween(now, Time()); | |
| 228 | |
| 229 // Should have deleted half of what we inserted. | |
| 230 EXPECT_TRUE(db.GetLoginsTable()->GetAllLogins(&result, true)); | |
| 231 EXPECT_EQ(2U, result.size()); | |
| 232 ClearResults(&result); | |
| 233 | |
| 234 // Delete with 0 date (should delete all). | |
| 235 db.GetLoginsTable()->RemoveLoginsCreatedBetween(Time(), Time()); | |
| 236 | |
| 237 // Verify nothing is left. | |
| 238 EXPECT_TRUE(db.GetLoginsTable()->GetAllLogins(&result, true)); | |
| 239 EXPECT_EQ(0U, result.size()); | |
| 240 } | |
| 241 | |
| 242 TEST_F(LoginsTableTest, BlacklistedLogins) { | |
| 243 WebDatabase db; | |
| 244 | |
| 245 ASSERT_EQ(sql::INIT_OK, db.Init(file_)); | |
| 246 std::vector<PasswordForm*> result; | |
| 247 | |
| 248 // Verify the database is empty. | |
| 249 EXPECT_TRUE(db.GetLoginsTable()->GetAllLogins(&result, true)); | |
| 250 ASSERT_EQ(0U, result.size()); | |
| 251 | |
| 252 // Save a form as blacklisted. | |
| 253 PasswordForm form; | |
| 254 form.origin = GURL("http://www.google.com/accounts/LoginAuth"); | |
| 255 form.action = GURL("http://www.google.com/accounts/Login"); | |
| 256 form.username_element = ASCIIToUTF16("Email"); | |
| 257 form.password_element = ASCIIToUTF16("Passwd"); | |
| 258 form.submit_element = ASCIIToUTF16("signIn"); | |
| 259 form.signon_realm = "http://www.google.com/"; | |
| 260 form.ssl_valid = false; | |
| 261 form.preferred = true; | |
| 262 form.blacklisted_by_user = true; | |
| 263 form.scheme = PasswordForm::SCHEME_HTML; | |
| 264 EXPECT_TRUE(db.GetLoginsTable()->AddLogin(form)); | |
| 265 | |
| 266 // Get all non-blacklisted logins (should be none). | |
| 267 EXPECT_TRUE(db.GetLoginsTable()->GetAllLogins(&result, false)); | |
| 268 ASSERT_EQ(0U, result.size()); | |
| 269 | |
| 270 // GetLogins should give the blacklisted result. | |
| 271 EXPECT_TRUE(db.GetLoginsTable()->GetLogins(form, &result)); | |
| 272 EXPECT_EQ(1U, result.size()); | |
| 273 ClearResults(&result); | |
| 274 | |
| 275 // So should GetAll including blacklisted. | |
| 276 EXPECT_TRUE(db.GetLoginsTable()->GetAllLogins(&result, true)); | |
| 277 EXPECT_EQ(1U, result.size()); | |
| 278 ClearResults(&result); | |
| 279 } | |
| OLD | NEW |