| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/common/net/cookie_monster_sqlite.h" | 5 #include "chrome/browser/net/sqlite_persistent_cookie_store.h" |
| 6 | 6 |
| 7 #include <list> | 7 #include <list> |
| 8 | 8 |
| 9 #include "app/sql/statement.h" |
| 10 #include "app/sql/transaction.h" |
| 9 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
| 10 #include "base/logging.h" | 12 #include "base/logging.h" |
| 11 #include "base/ref_counted.h" | 13 #include "base/ref_counted.h" |
| 14 #include "base/scoped_ptr.h" |
| 12 #include "base/string_util.h" | 15 #include "base/string_util.h" |
| 13 #include "base/thread.h" | 16 #include "base/thread.h" |
| 14 #include "chrome/common/sqlite_compiled_statement.h" | |
| 15 #include "chrome/common/sqlite_utils.h" | |
| 16 | 17 |
| 17 using base::Time; | 18 using base::Time; |
| 18 | 19 |
| 19 // This class is designed to be shared between any calling threads and the | 20 // This class is designed to be shared between any calling threads and the |
| 20 // database thread. It batches operations and commits them on a timer. | 21 // database thread. It batches operations and commits them on a timer. |
| 21 class SQLitePersistentCookieStore::Backend | 22 class SQLitePersistentCookieStore::Backend |
| 22 : public base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend> { | 23 : public base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend> { |
| 23 public: | 24 public: |
| 24 // The passed database pointer must be already-initialized. This object will | 25 // The passed database pointer must be already-initialized. This object will |
| 25 // take ownership. | 26 // take ownership. |
| 26 explicit Backend(sqlite3* db, MessageLoop* loop) | 27 explicit Backend(sql::Connection* db, MessageLoop* loop) |
| 27 : db_(db), | 28 : db_(db), |
| 28 background_loop_(loop), | 29 background_loop_(loop), |
| 29 cache_(new SqliteStatementCache(db)), | |
| 30 num_pending_(0) { | 30 num_pending_(0) { |
| 31 DCHECK(db_) << "Database must exist."; | 31 DCHECK(db_) << "Database must exist."; |
| 32 } | 32 } |
| 33 | 33 |
| 34 // You should call Close() before destructing this object. | 34 // You should call Close() before destructing this object. |
| 35 ~Backend() { | 35 ~Backend() { |
| 36 DCHECK(!db_) << "Close should have already been called."; | 36 DCHECK(!db_) << "Close should have already been called."; |
| 37 DCHECK(num_pending_ == 0 && pending_.empty()); | 37 DCHECK(num_pending_ == 0 && pending_.empty()); |
| 38 } | 38 } |
| 39 | 39 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 private: | 78 private: |
| 79 // Batch a cookie operation (add or delete) | 79 // Batch a cookie operation (add or delete) |
| 80 void BatchOperation(PendingOperation::OperationType op, | 80 void BatchOperation(PendingOperation::OperationType op, |
| 81 const std::string& key, | 81 const std::string& key, |
| 82 const net::CookieMonster::CanonicalCookie& cc); | 82 const net::CookieMonster::CanonicalCookie& cc); |
| 83 // Commit our pending operations to the database. | 83 // Commit our pending operations to the database. |
| 84 void Commit(); | 84 void Commit(); |
| 85 // Close() executed on the background thread. | 85 // Close() executed on the background thread. |
| 86 void InternalBackgroundClose(); | 86 void InternalBackgroundClose(); |
| 87 | 87 |
| 88 sqlite3* db_; | 88 sql::Connection* db_; |
| 89 MessageLoop* background_loop_; | 89 MessageLoop* background_loop_; |
| 90 SqliteStatementCache* cache_; | |
| 91 | 90 |
| 92 typedef std::list<PendingOperation*> PendingOperationsList; | 91 typedef std::list<PendingOperation*> PendingOperationsList; |
| 93 PendingOperationsList pending_; | 92 PendingOperationsList pending_; |
| 94 PendingOperationsList::size_type num_pending_; | 93 PendingOperationsList::size_type num_pending_; |
| 95 Lock pending_lock_; // Guard pending_ and num_pending_ | 94 Lock pending_lock_; // Guard pending_ and num_pending_ |
| 96 | 95 |
| 97 DISALLOW_COPY_AND_ASSIGN(Backend); | 96 DISALLOW_COPY_AND_ASSIGN(Backend); |
| 98 }; | 97 }; |
| 99 | 98 |
| 100 void SQLitePersistentCookieStore::Backend::AddCookie( | 99 void SQLitePersistentCookieStore::Backend::AddCookie( |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 { | 151 { |
| 153 AutoLock locked(pending_lock_); | 152 AutoLock locked(pending_lock_); |
| 154 pending_.swap(ops); | 153 pending_.swap(ops); |
| 155 num_pending_ = 0; | 154 num_pending_ = 0; |
| 156 } | 155 } |
| 157 | 156 |
| 158 // Maybe an old timer fired or we are already Close()'ed. | 157 // Maybe an old timer fired or we are already Close()'ed. |
| 159 if (!db_ || ops.empty()) | 158 if (!db_ || ops.empty()) |
| 160 return; | 159 return; |
| 161 | 160 |
| 162 SQLITE_UNIQUE_STATEMENT(add_smt, *cache_, | 161 sql::Statement add_smt(db_->GetCachedStatement(SQL_FROM_HERE, |
| 163 "INSERT INTO cookies (creation_utc, host_key, name, value, path, " | 162 "INSERT INTO cookies (creation_utc, host_key, name, value, path, " |
| 164 "expires_utc, secure, httponly, last_access_utc) " | 163 "expires_utc, secure, httponly, last_access_utc) " |
| 165 "VALUES (?,?,?,?,?,?,?,?,?)"); | 164 "VALUES (?,?,?,?,?,?,?,?,?)")); |
| 166 if (!add_smt.is_valid()) { | 165 if (!add_smt) { |
| 167 NOTREACHED(); | 166 NOTREACHED(); |
| 168 return; | 167 return; |
| 169 } | 168 } |
| 170 | 169 |
| 171 SQLITE_UNIQUE_STATEMENT(update_access_smt, *cache_, | 170 sql::Statement update_access_smt(db_->GetCachedStatement(SQL_FROM_HERE, |
| 172 "UPDATE cookies SET last_access_utc=? " | 171 "UPDATE cookies SET last_access_utc=? WHERE creation_utc=?")); |
| 173 "WHERE creation_utc=?"); | 172 if (!update_access_smt) { |
| 174 if (!update_access_smt.is_valid()) { | |
| 175 NOTREACHED(); | 173 NOTREACHED(); |
| 176 return; | 174 return; |
| 177 } | 175 } |
| 178 | 176 |
| 179 SQLITE_UNIQUE_STATEMENT(del_smt, *cache_, | 177 sql::Statement del_smt(db_->GetCachedStatement(SQL_FROM_HERE, |
| 180 "DELETE FROM cookies WHERE creation_utc=?"); | 178 "DELETE FROM cookies WHERE creation_utc=?")); |
| 181 if (!del_smt.is_valid()) { | 179 if (!del_smt) { |
| 182 NOTREACHED(); | 180 NOTREACHED(); |
| 183 return; | 181 return; |
| 184 } | 182 } |
| 185 | 183 |
| 186 SQLTransaction transaction(db_); | 184 sql::Transaction transaction(db_); |
| 187 transaction.Begin(); | 185 if (!transaction.Begin()) { |
| 186 NOTREACHED(); |
| 187 return; |
| 188 } |
| 188 for (PendingOperationsList::iterator it = ops.begin(); | 189 for (PendingOperationsList::iterator it = ops.begin(); |
| 189 it != ops.end(); ++it) { | 190 it != ops.end(); ++it) { |
| 190 // Free the cookies as we commit them to the database. | 191 // Free the cookies as we commit them to the database. |
| 191 scoped_ptr<PendingOperation> po(*it); | 192 scoped_ptr<PendingOperation> po(*it); |
| 192 switch (po->op()) { | 193 switch (po->op()) { |
| 193 case PendingOperation::COOKIE_ADD: | 194 case PendingOperation::COOKIE_ADD: |
| 194 add_smt->reset(); | 195 add_smt.Reset(); |
| 195 add_smt->bind_int64(0, po->cc().CreationDate().ToInternalValue()); | 196 add_smt.BindInt64(0, po->cc().CreationDate().ToInternalValue()); |
| 196 add_smt->bind_string(1, po->key()); | 197 add_smt.BindString(1, po->key()); |
| 197 add_smt->bind_string(2, po->cc().Name()); | 198 add_smt.BindString(2, po->cc().Name()); |
| 198 add_smt->bind_string(3, po->cc().Value()); | 199 add_smt.BindString(3, po->cc().Value()); |
| 199 add_smt->bind_string(4, po->cc().Path()); | 200 add_smt.BindString(4, po->cc().Path()); |
| 200 add_smt->bind_int64(5, po->cc().ExpiryDate().ToInternalValue()); | 201 add_smt.BindInt64(5, po->cc().ExpiryDate().ToInternalValue()); |
| 201 add_smt->bind_int(6, po->cc().IsSecure()); | 202 add_smt.BindInt(6, po->cc().IsSecure()); |
| 202 add_smt->bind_int(7, po->cc().IsHttpOnly()); | 203 add_smt.BindInt(7, po->cc().IsHttpOnly()); |
| 203 add_smt->bind_int64(8, po->cc().LastAccessDate().ToInternalValue()); | 204 add_smt.BindInt64(8, po->cc().LastAccessDate().ToInternalValue()); |
| 204 if (add_smt->step() != SQLITE_DONE) { | 205 if (!add_smt.Run()) |
| 205 NOTREACHED() << "Could not add a cookie to the DB."; | 206 NOTREACHED() << "Could not add a cookie to the DB."; |
| 206 } | |
| 207 break; | 207 break; |
| 208 | 208 |
| 209 case PendingOperation::COOKIE_UPDATEACCESS: | 209 case PendingOperation::COOKIE_UPDATEACCESS: |
| 210 update_access_smt->reset(); | 210 update_access_smt.Reset(); |
| 211 update_access_smt->bind_int64(0, | 211 update_access_smt.BindInt64(0, |
| 212 po->cc().LastAccessDate().ToInternalValue()); | 212 po->cc().LastAccessDate().ToInternalValue()); |
| 213 update_access_smt->bind_int64(1, | 213 update_access_smt.BindInt64(1, |
| 214 po->cc().CreationDate().ToInternalValue()); | 214 po->cc().CreationDate().ToInternalValue()); |
| 215 if (update_access_smt->step() != SQLITE_DONE) { | 215 if (!update_access_smt.Run()) |
| 216 NOTREACHED() << "Could not update cookie last access time in the DB."; | 216 NOTREACHED() << "Could not update cookie last access time in the DB."; |
| 217 } | |
| 218 break; | 217 break; |
| 219 | 218 |
| 220 case PendingOperation::COOKIE_DELETE: | 219 case PendingOperation::COOKIE_DELETE: |
| 221 del_smt->reset(); | 220 del_smt.Reset(); |
| 222 del_smt->bind_int64(0, po->cc().CreationDate().ToInternalValue()); | 221 del_smt.BindInt64(0, po->cc().CreationDate().ToInternalValue()); |
| 223 if (del_smt->step() != SQLITE_DONE) { | 222 if (!del_smt.Run()) |
| 224 NOTREACHED() << "Could not delete a cookie from the DB."; | 223 NOTREACHED() << "Could not delete a cookie from the DB."; |
| 225 } | |
| 226 break; | 224 break; |
| 227 | 225 |
| 228 default: | 226 default: |
| 229 NOTREACHED(); | 227 NOTREACHED(); |
| 230 break; | 228 break; |
| 231 } | 229 } |
| 232 } | 230 } |
| 233 transaction.Commit(); | 231 transaction.Commit(); |
| 234 } | 232 } |
| 235 | 233 |
| 236 // Fire off a close message to the background thread. We could still have a | 234 // Fire off a close message to the background thread. We could still have a |
| 237 // pending commit timer that will be holding a reference on us, but if/when | 235 // pending commit timer that will be holding a reference on us, but if/when |
| 238 // this fires we will already have been cleaned up and it will be ignored. | 236 // this fires we will already have been cleaned up and it will be ignored. |
| 239 void SQLitePersistentCookieStore::Backend::Close() { | 237 void SQLitePersistentCookieStore::Backend::Close() { |
| 240 DCHECK(MessageLoop::current() != background_loop_); | 238 DCHECK(MessageLoop::current() != background_loop_); |
| 241 // Must close the backend on the background thread. | 239 // Must close the backend on the background thread. |
| 242 // TODO(abarth): What if the DB thread is being destroyed on the UI thread? | 240 // TODO(abarth): What if the DB thread is being destroyed on the UI thread? |
| 243 background_loop_->PostTask(FROM_HERE, | 241 background_loop_->PostTask(FROM_HERE, |
| 244 NewRunnableMethod(this, &Backend::InternalBackgroundClose)); | 242 NewRunnableMethod(this, &Backend::InternalBackgroundClose)); |
| 245 } | 243 } |
| 246 | 244 |
| 247 void SQLitePersistentCookieStore::Backend::InternalBackgroundClose() { | 245 void SQLitePersistentCookieStore::Backend::InternalBackgroundClose() { |
| 248 DCHECK(MessageLoop::current() == background_loop_); | 246 DCHECK(MessageLoop::current() == background_loop_); |
| 249 // Commit any pending operations | 247 // Commit any pending operations |
| 250 Commit(); | 248 Commit(); |
| 251 // We must destroy the cache before closing the database. | 249 |
| 252 delete cache_; | 250 delete db_; |
| 253 cache_ = NULL; | |
| 254 sqlite3_close(db_); | |
| 255 db_ = NULL; | 251 db_ = NULL; |
| 256 } | 252 } |
| 257 | 253 |
| 258 SQLitePersistentCookieStore::SQLitePersistentCookieStore( | 254 SQLitePersistentCookieStore::SQLitePersistentCookieStore( |
| 259 const std::wstring& path, MessageLoop* background_loop) | 255 const FilePath& path, |
| 256 MessageLoop* background_loop) |
| 260 : path_(path), | 257 : path_(path), |
| 261 background_loop_(background_loop) { | 258 background_loop_(background_loop) { |
| 262 DCHECK(background_loop) << "SQLitePersistentCookieStore needs a MessageLoop"; | 259 DCHECK(background_loop) << "SQLitePersistentCookieStore needs a MessageLoop"; |
| 263 } | 260 } |
| 264 | 261 |
| 265 SQLitePersistentCookieStore::~SQLitePersistentCookieStore() { | 262 SQLitePersistentCookieStore::~SQLitePersistentCookieStore() { |
| 266 if (backend_.get()) { | 263 if (backend_.get()) { |
| 267 backend_->Close(); | 264 backend_->Close(); |
| 268 // Release our reference, it will probably still have a reference if the | 265 // Release our reference, it will probably still have a reference if the |
| 269 // background thread has not run Close() yet. | 266 // background thread has not run Close() yet. |
| 270 backend_ = NULL; | 267 backend_ = NULL; |
| 271 } | 268 } |
| 272 } | 269 } |
| 273 | 270 |
| 274 // Version number of the database. In version 4, we migrated the time epoch. | 271 // Version number of the database. In version 4, we migrated the time epoch. |
| 275 // If you open the DB with an older version on Mac or Linux, the times will | 272 // If you open the DB with an older version on Mac or Linux, the times will |
| 276 // look wonky, but the file will likely be usable. On Windows version 3 and 4 | 273 // look wonky, but the file will likely be usable. On Windows version 3 and 4 |
| 277 // are the same. | 274 // are the same. |
| 278 // | 275 // |
| 279 // Version 3 updated the database to include the last access time, so we can | 276 // Version 3 updated the database to include the last access time, so we can |
| 280 // expire them in decreasing order of use when we've reached the maximum | 277 // expire them in decreasing order of use when we've reached the maximum |
| 281 // number of cookies. | 278 // number of cookies. |
| 282 static const int kCurrentVersionNumber = 4; | 279 static const int kCurrentVersionNumber = 4; |
| 283 static const int kCompatibleVersionNumber = 3; | 280 static const int kCompatibleVersionNumber = 3; |
| 284 | 281 |
| 285 namespace { | 282 namespace { |
| 286 | 283 |
| 287 // Initializes the cookies table, returning true on success. | 284 // Initializes the cookies table, returning true on success. |
| 288 bool InitTable(sqlite3* db) { | 285 bool InitTable(sql::Connection* db) { |
| 289 if (!DoesSqliteTableExist(db, "cookies")) { | 286 if (!db->DoesTableExist("cookies")) { |
| 290 if (sqlite3_exec(db, "CREATE TABLE cookies (" | 287 if (!db->Execute("CREATE TABLE cookies (" |
| 291 "creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY," | 288 "creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY," |
| 292 "host_key TEXT NOT NULL," | 289 "host_key TEXT NOT NULL," |
| 293 "name TEXT NOT NULL," | 290 "name TEXT NOT NULL," |
| 294 "value TEXT NOT NULL," | 291 "value TEXT NOT NULL," |
| 295 "path TEXT NOT NULL," | 292 "path TEXT NOT NULL," |
| 296 // We only store persistent, so we know it expires | 293 // We only store persistent, so we know it expires |
| 297 "expires_utc INTEGER NOT NULL," | 294 "expires_utc INTEGER NOT NULL," |
| 298 "secure INTEGER NOT NULL," | 295 "secure INTEGER NOT NULL," |
| 299 "httponly INTEGER NOT NULL," | 296 "httponly INTEGER NOT NULL," |
| 300 "last_access_utc INTEGER NOT NULL)", | 297 "last_access_utc INTEGER NOT NULL)")) |
| 301 NULL, NULL, NULL) != SQLITE_OK) | |
| 302 return false; | 298 return false; |
| 303 } | 299 } |
| 304 | 300 |
| 305 // Try to create the index every time. Older versions did not have this index, | 301 // Try to create the index every time. Older versions did not have this index, |
| 306 // so we want those people to get it. Ignore errors, since it may exist. | 302 // so we want those people to get it. Ignore errors, since it may exist. |
| 307 sqlite3_exec(db, "CREATE INDEX cookie_times ON cookies (creation_utc)", | 303 db->Execute("CREATE INDEX cookie_times ON cookies (creation_utc)"); |
| 308 NULL, NULL, NULL); | |
| 309 | |
| 310 return true; | 304 return true; |
| 311 } | 305 } |
| 312 | 306 |
| 313 } // namespace | 307 } // namespace |
| 314 | 308 |
| 315 bool SQLitePersistentCookieStore::Load( | 309 bool SQLitePersistentCookieStore::Load( |
| 316 std::vector<net::CookieMonster::KeyedCanonicalCookie>* cookies) { | 310 std::vector<net::CookieMonster::KeyedCanonicalCookie>* cookies) { |
| 317 DCHECK(!path_.empty()); | 311 scoped_ptr<sql::Connection> db(new sql::Connection); |
| 318 sqlite3* db; | 312 if (!db->Init(path_)) { |
| 319 if (sqlite3_open(WideToUTF8(path_).c_str(), &db) != SQLITE_OK) { | |
| 320 NOTREACHED() << "Unable to open cookie DB."; | 313 NOTREACHED() << "Unable to open cookie DB."; |
| 321 return false; | 314 return false; |
| 322 } | 315 } |
| 323 | 316 |
| 324 if (!EnsureDatabaseVersion(db) || !InitTable(db)) { | 317 if (!EnsureDatabaseVersion(db.get()) || !InitTable(db.get())) { |
| 325 NOTREACHED() << "Unable to initialize cookie DB."; | 318 NOTREACHED() << "Unable to initialize cookie DB."; |
| 326 sqlite3_close(db); | |
| 327 return false; | 319 return false; |
| 328 } | 320 } |
| 329 | 321 |
| 330 MetaTableHelper::PrimeCache(std::string(), db); | 322 db->Preload(); |
| 331 | 323 |
| 332 // Slurp all the cookies into the out-vector. | 324 // Slurp all the cookies into the out-vector. |
| 333 SQLStatement smt; | 325 sql::Statement smt(db->GetUniqueStatement( |
| 334 if (smt.prepare(db, | |
| 335 "SELECT creation_utc, host_key, name, value, path, expires_utc, secure, " | 326 "SELECT creation_utc, host_key, name, value, path, expires_utc, secure, " |
| 336 "httponly, last_access_utc FROM cookies") != SQLITE_OK) { | 327 "httponly, last_access_utc FROM cookies")); |
| 328 if (!smt) { |
| 337 NOTREACHED() << "select statement prep failed"; | 329 NOTREACHED() << "select statement prep failed"; |
| 338 sqlite3_close(db); | |
| 339 return false; | 330 return false; |
| 340 } | 331 } |
| 341 | 332 |
| 342 while (smt.step() == SQLITE_ROW) { | 333 while (smt.Step()) { |
| 343 std::string key = smt.column_string(1); | |
| 344 scoped_ptr<net::CookieMonster::CanonicalCookie> cc( | 334 scoped_ptr<net::CookieMonster::CanonicalCookie> cc( |
| 345 new net::CookieMonster::CanonicalCookie( | 335 new net::CookieMonster::CanonicalCookie( |
| 346 smt.column_string(2), // name | 336 smt.ColumnString(2), // name |
| 347 smt.column_string(3), // value | 337 smt.ColumnString(3), // value |
| 348 smt.column_string(4), // path | 338 smt.ColumnString(4), // path |
| 349 smt.column_int(6) != 0, // secure | 339 smt.ColumnInt(6) != 0, // secure |
| 350 smt.column_int(7) != 0, // httponly | 340 smt.ColumnInt(7) != 0, // httponly |
| 351 Time::FromInternalValue(smt.column_int64(0)), // creation_utc | 341 Time::FromInternalValue(smt.ColumnInt64(0)), // creation_utc |
| 352 Time::FromInternalValue(smt.column_int64(8)), // last_access_utc | 342 Time::FromInternalValue(smt.ColumnInt64(8)), // last_access_utc |
| 353 true, // has_expires | 343 true, // has_expires |
| 354 Time::FromInternalValue(smt.column_int64(5)))); // expires_utc | 344 Time::FromInternalValue(smt.ColumnInt64(5)))); // expires_utc |
| 355 // Memory allocation failed. | |
| 356 if (!cc.get()) | |
| 357 break; | |
| 358 | |
| 359 DLOG_IF(WARNING, | 345 DLOG_IF(WARNING, |
| 360 cc->CreationDate() > Time::Now()) << L"CreationDate too recent"; | 346 cc->CreationDate() > Time::Now()) << L"CreationDate too recent"; |
| 361 cookies->push_back( | 347 cookies->push_back( |
| 362 net::CookieMonster::KeyedCanonicalCookie(smt.column_string(1), | 348 net::CookieMonster::KeyedCanonicalCookie(smt.ColumnString(1), |
| 363 cc.release())); | 349 cc.release())); |
| 364 } | 350 } |
| 365 | 351 |
| 366 // Create the backend, this will take ownership of the db pointer. | 352 // Create the backend, this will take ownership of the db pointer. |
| 367 backend_ = new Backend(db, background_loop_); | 353 backend_ = new Backend(db.release(), background_loop_); |
| 368 | |
| 369 return true; | 354 return true; |
| 370 } | 355 } |
| 371 | 356 |
| 372 bool SQLitePersistentCookieStore::EnsureDatabaseVersion(sqlite3* db) { | 357 bool SQLitePersistentCookieStore::EnsureDatabaseVersion(sql::Connection* db) { |
| 373 // Version check. | 358 // Version check. |
| 374 if (!meta_table_.Init(std::string(), kCurrentVersionNumber, | 359 if (!meta_table_.Init(db, kCurrentVersionNumber, kCompatibleVersionNumber)) |
| 375 kCompatibleVersionNumber, db)) | |
| 376 return false; | 360 return false; |
| 377 | 361 |
| 378 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { | 362 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { |
| 379 LOG(WARNING) << "Cookie database is too new."; | 363 LOG(WARNING) << "Cookie database is too new."; |
| 380 return false; | 364 return false; |
| 381 } | 365 } |
| 382 | 366 |
| 383 int cur_version = meta_table_.GetVersionNumber(); | 367 int cur_version = meta_table_.GetVersionNumber(); |
| 384 if (cur_version == 2) { | 368 if (cur_version == 2) { |
| 385 SQLTransaction transaction(db); | 369 sql::Transaction transaction(db); |
| 386 transaction.Begin(); | 370 if (!transaction.Begin()) |
| 387 if ((sqlite3_exec(db, | 371 return false; |
| 388 "ALTER TABLE cookies ADD COLUMN last_access_utc " | 372 if (!db->Execute("ALTER TABLE cookies ADD COLUMN last_access_utc " |
| 389 "INTEGER DEFAULT 0", NULL, NULL, NULL) != SQLITE_OK) || | 373 "INTEGER DEFAULT 0") || |
| 390 (sqlite3_exec(db, | 374 !db->Execute("UPDATE cookies SET last_access_utc = creation_utc")) { |
| 391 "UPDATE cookies SET last_access_utc = creation_utc", | |
| 392 NULL, NULL, NULL) != SQLITE_OK)) { | |
| 393 LOG(WARNING) << "Unable to update cookie database to version 3."; | 375 LOG(WARNING) << "Unable to update cookie database to version 3."; |
| 394 return false; | 376 return false; |
| 395 } | 377 } |
| 396 ++cur_version; | 378 ++cur_version; |
| 397 meta_table_.SetVersionNumber(cur_version); | 379 meta_table_.SetVersionNumber(cur_version); |
| 398 meta_table_.SetCompatibleVersionNumber( | 380 meta_table_.SetCompatibleVersionNumber( |
| 399 std::min(cur_version, kCompatibleVersionNumber)); | 381 std::min(cur_version, kCompatibleVersionNumber)); |
| 400 transaction.Commit(); | 382 transaction.Commit(); |
| 401 } | 383 } |
| 402 | 384 |
| 403 if (cur_version == 3) { | 385 if (cur_version == 3) { |
| 404 // The time epoch changed for Mac & Linux in this version to match Windows. | 386 // The time epoch changed for Mac & Linux in this version to match Windows. |
| 405 // This patch came after the main epoch change happened, so some | 387 // This patch came after the main epoch change happened, so some |
| 406 // developers have "good" times for cookies added by the more recent | 388 // developers have "good" times for cookies added by the more recent |
| 407 // versions. So we have to be careful to only update times that are under | 389 // versions. So we have to be careful to only update times that are under |
| 408 // the old system (which will appear to be from before 1970 in the new | 390 // the old system (which will appear to be from before 1970 in the new |
| 409 // system). The magic number used below is 1970 in our time units. | 391 // system). The magic number used below is 1970 in our time units. |
| 410 SQLTransaction transaction(db); | 392 sql::Transaction transaction(db); |
| 411 transaction.Begin(); | 393 transaction.Begin(); |
| 412 #if !defined(OS_WIN) | 394 #if !defined(OS_WIN) |
| 413 sqlite3_exec(db, | 395 db->Execute( |
| 414 "UPDATE cookies " | 396 "UPDATE cookies " |
| 415 "SET creation_utc = creation_utc + 11644473600000000 " | 397 "SET creation_utc = creation_utc + 11644473600000000 " |
| 416 "WHERE rowid IN " | 398 "WHERE rowid IN " |
| 417 "(SELECT rowid FROM cookies WHERE " | 399 "(SELECT rowid FROM cookies WHERE " |
| 418 "creation_utc > 0 AND creation_utc < 11644473600000000)", | 400 "creation_utc > 0 AND creation_utc < 11644473600000000)"); |
| 419 NULL, NULL, NULL); | 401 db->Execute( |
| 420 sqlite3_exec(db, | |
| 421 "UPDATE cookies " | 402 "UPDATE cookies " |
| 422 "SET expires_utc = expires_utc + 11644473600000000 " | 403 "SET expires_utc = expires_utc + 11644473600000000 " |
| 423 "WHERE rowid IN " | 404 "WHERE rowid IN " |
| 424 "(SELECT rowid FROM cookies WHERE " | 405 "(SELECT rowid FROM cookies WHERE " |
| 425 "expires_utc > 0 AND expires_utc < 11644473600000000)", | 406 "expires_utc > 0 AND expires_utc < 11644473600000000)"); |
| 426 NULL, NULL, NULL); | 407 db->Execute( |
| 427 sqlite3_exec(db, | |
| 428 "UPDATE cookies " | 408 "UPDATE cookies " |
| 429 "SET last_access_utc = last_access_utc + 11644473600000000 " | 409 "SET last_access_utc = last_access_utc + 11644473600000000 " |
| 430 "WHERE rowid IN " | 410 "WHERE rowid IN " |
| 431 "(SELECT rowid FROM cookies WHERE " | 411 "(SELECT rowid FROM cookies WHERE " |
| 432 "last_access_utc > 0 AND last_access_utc < 11644473600000000)", | 412 "last_access_utc > 0 AND last_access_utc < 11644473600000000)"); |
| 433 NULL, NULL, NULL); | |
| 434 #endif | 413 #endif |
| 435 ++cur_version; | 414 ++cur_version; |
| 436 meta_table_.SetVersionNumber(cur_version); | 415 meta_table_.SetVersionNumber(cur_version); |
| 437 transaction.Commit(); | 416 transaction.Commit(); |
| 438 } | 417 } |
| 439 | 418 |
| 440 // Put future migration cases here. | 419 // Put future migration cases here. |
| 441 | 420 |
| 442 // When the version is too old, we just try to continue anyway, there should | 421 // When the version is too old, we just try to continue anyway, there should |
| 443 // not be a released product that makes a database too old for us to handle. | 422 // not be a released product that makes a database too old for us to handle. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 458 const net::CookieMonster::CanonicalCookie& cc) { | 437 const net::CookieMonster::CanonicalCookie& cc) { |
| 459 if (backend_.get()) | 438 if (backend_.get()) |
| 460 backend_->UpdateCookieAccessTime(cc); | 439 backend_->UpdateCookieAccessTime(cc); |
| 461 } | 440 } |
| 462 | 441 |
| 463 void SQLitePersistentCookieStore::DeleteCookie( | 442 void SQLitePersistentCookieStore::DeleteCookie( |
| 464 const net::CookieMonster::CanonicalCookie& cc) { | 443 const net::CookieMonster::CanonicalCookie& cc) { |
| 465 if (backend_.get()) | 444 if (backend_.get()) |
| 466 backend_->DeleteCookie(cc); | 445 backend_->DeleteCookie(cc); |
| 467 } | 446 } |
| OLD | NEW |