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 |