sqlite_persistent_cookie_store.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1// Copyright (c) 2010 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 "chrome/browser/net/sqlite_persistent_cookie_store.h"
6
7#include <list>
8
9#include "app/sql/meta_table.h"
10#include "app/sql/statement.h"
11#include "app/sql/transaction.h"
12#include "base/basictypes.h"
13#include "base/file_path.h"
14#include "base/file_util.h"
15#include "base/logging.h"
16#include "base/metrics/histogram.h"
17#include "base/ref_counted.h"
18#include "base/scoped_ptr.h"
19#include "base/string_util.h"
20#include "base/thread.h"
21#ifndef ANDROID
22#include "chrome/browser/browser_thread.h"
23#include "chrome/browser/diagnostics/sqlite_diagnostics.h"
24#endif
25
26#ifdef ANDROID
27base::Thread* getDbThread()
28{
29  static base::Thread* dbThread = NULL;
30  if (dbThread && dbThread->IsRunning())
31    return dbThread;
32
33  if (!dbThread)
34    dbThread = new base::Thread("db");
35
36  if (!dbThread)
37    return NULL;
38
39  base::Thread::Options options;
40  options.message_loop_type = MessageLoop::TYPE_DEFAULT;
41  if (!dbThread->StartWithOptions(options)) {
42    delete dbThread;
43    dbThread = NULL;
44  }
45  return dbThread;
46}
47#endif
48
49using base::Time;
50
51// This class is designed to be shared between any calling threads and the
52// database thread.  It batches operations and commits them on a timer.
53class SQLitePersistentCookieStore::Backend
54    : public base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend> {
55 public:
56<<<<<<< HEAD
57  // The passed database pointer must be already-initialized. This object will
58  // take ownership.
59  explicit Backend(sql::Connection* db)
60      : db_(db)
61      , num_pending_(0)
62#if defined(ANDROID)
63      , cookie_count_(0)
64#endif
65  {
66    DCHECK(db_) << "Database must exist.";
67=======
68  explicit Backend(const FilePath& path)
69      : path_(path),
70        db_(NULL),
71        num_pending_(0),
72        clear_local_state_on_exit_(false) {
73>>>>>>> chromium.org at r10.0.621.0
74  }
75
76  // Creates or load the SQLite database.
77  bool Load(std::vector<net::CookieMonster::CanonicalCookie*>* cookies);
78
79  // Batch a cookie addition.
80  void AddCookie(const net::CookieMonster::CanonicalCookie& cc);
81
82  // Batch a cookie access time update.
83  void UpdateCookieAccessTime(const net::CookieMonster::CanonicalCookie& cc);
84
85  // Batch a cookie deletion.
86  void DeleteCookie(const net::CookieMonster::CanonicalCookie& cc);
87
88<<<<<<< HEAD
89#if defined(ANDROID)
90  // Commit pending operations as soon as possible.
91  void Flush(Task* completion_task);
92#endif
93=======
94  // Commit pending operations as soon as possible.
95  void Flush(Task* completion_task);
96>>>>>>> chromium.org at r10.0.621.0
97
98  // Commit any pending operations and close the database.  This must be called
99  // before the object is destructed.
100  void Close();
101
102<<<<<<< HEAD
103#if defined(ANDROID)
104  int get_cookie_count() const { return cookie_count_; }
105  void set_cookie_count(int count) { cookie_count_ = count; }
106#endif
107=======
108  void SetClearLocalStateOnExit(bool clear_local_state);
109>>>>>>> chromium.org at r10.0.621.0
110
111 private:
112  friend class base::RefCountedThreadSafe<SQLitePersistentCookieStore::Backend>;
113
114  // You should call Close() before destructing this object.
115  ~Backend() {
116    DCHECK(!db_.get()) << "Close should have already been called.";
117    DCHECK(num_pending_ == 0 && pending_.empty());
118  }
119
120  // Database upgrade statements.
121  bool EnsureDatabaseVersion();
122
123  class PendingOperation {
124   public:
125    typedef enum {
126      COOKIE_ADD,
127      COOKIE_UPDATEACCESS,
128      COOKIE_DELETE,
129    } OperationType;
130
131    PendingOperation(OperationType op,
132                     const net::CookieMonster::CanonicalCookie& cc)
133        : op_(op), cc_(cc) { }
134
135    OperationType op() const { return op_; }
136    const net::CookieMonster::CanonicalCookie& cc() const { return cc_; }
137
138   private:
139    OperationType op_;
140    net::CookieMonster::CanonicalCookie cc_;
141  };
142
143 private:
144  // Batch a cookie operation (add or delete)
145  void BatchOperation(PendingOperation::OperationType op,
146                      const net::CookieMonster::CanonicalCookie& cc);
147  // Commit our pending operations to the database.
148#if defined(ANDROID)
149  void Commit(Task* completion_task);
150#else
151  void Commit();
152#endif
153  // Close() executed on the background thread.
154  void InternalBackgroundClose();
155
156  FilePath path_;
157  scoped_ptr<sql::Connection> db_;
158  sql::MetaTable meta_table_;
159
160  typedef std::list<PendingOperation*> PendingOperationsList;
161  PendingOperationsList pending_;
162  PendingOperationsList::size_type num_pending_;
163  // True if the persistent store should be deleted upon destruction.
164  bool clear_local_state_on_exit_;
165  // Guard |pending_|, |num_pending_| and |clear_local_state_on_exit_|.
166  Lock lock_;
167
168#if defined(ANDROID)
169  // Number of cookies that have actually been saved. Updated during Commit().
170  volatile int cookie_count_;
171#endif
172
173  DISALLOW_COPY_AND_ASSIGN(Backend);
174};
175
176// Version number of the database. In version 4, we migrated the time epoch.
177// If you open the DB with an older version on Mac or Linux, the times will
178// look wonky, but the file will likely be usable. On Windows version 3 and 4
179// are the same.
180//
181// Version 3 updated the database to include the last access time, so we can
182// expire them in decreasing order of use when we've reached the maximum
183// number of cookies.
184static const int kCurrentVersionNumber = 4;
185static const int kCompatibleVersionNumber = 3;
186
187namespace {
188
189// Initializes the cookies table, returning true on success.
190bool InitTable(sql::Connection* db) {
191  if (!db->DoesTableExist("cookies")) {
192    if (!db->Execute("CREATE TABLE cookies ("
193                     "creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY,"
194                     "host_key TEXT NOT NULL,"
195                     "name TEXT NOT NULL,"
196                     "value TEXT NOT NULL,"
197                     "path TEXT NOT NULL,"
198                     // We only store persistent, so we know it expires
199                     "expires_utc INTEGER NOT NULL,"
200                     "secure INTEGER NOT NULL,"
201                     "httponly INTEGER NOT NULL,"
202                     "last_access_utc INTEGER NOT NULL)"))
203      return false;
204  }
205
206  // Try to create the index every time. Older versions did not have this index,
207  // so we want those people to get it. Ignore errors, since it may exist.
208  db->Execute("CREATE INDEX cookie_times ON cookies (creation_utc)");
209  return true;
210}
211
212}  // namespace
213
214bool SQLitePersistentCookieStore::Backend::Load(
215    std::vector<net::CookieMonster::CanonicalCookie*>* cookies) {
216  // This function should be called only once per instance.
217  DCHECK(!db_.get());
218
219  db_.reset(new sql::Connection);
220  if (!db_->Open(path_)) {
221    NOTREACHED() << "Unable to open cookie DB.";
222    db_.reset();
223    return false;
224  }
225
226  db_->set_error_delegate(GetErrorHandlerForCookieDb());
227
228  if (!EnsureDatabaseVersion() || !InitTable(db_.get())) {
229    NOTREACHED() << "Unable to open cookie DB.";
230    db_.reset();
231    return false;
232  }
233
234  db_->Preload();
235
236  // Slurp all the cookies into the out-vector.
237  sql::Statement smt(db_->GetUniqueStatement(
238      "SELECT creation_utc, host_key, name, value, path, expires_utc, secure, "
239      "httponly, last_access_utc FROM cookies"));
240  if (!smt) {
241    NOTREACHED() << "select statement prep failed";
242    db_.reset();
243    return false;
244  }
245
246  while (smt.Step()) {
247    scoped_ptr<net::CookieMonster::CanonicalCookie> cc(
248        new net::CookieMonster::CanonicalCookie(
249            smt.ColumnString(2),                            // name
250            smt.ColumnString(3),                            // value
251            smt.ColumnString(1),                            // domain
252            smt.ColumnString(4),                            // path
253            smt.ColumnInt(6) != 0,                          // secure
254            smt.ColumnInt(7) != 0,                          // httponly
255            Time::FromInternalValue(smt.ColumnInt64(0)),    // creation_utc
256            Time::FromInternalValue(smt.ColumnInt64(8)),    // last_access_utc
257            true,                                           // has_expires
258            Time::FromInternalValue(smt.ColumnInt64(5))));  // expires_utc
259    DLOG_IF(WARNING,
260            cc->CreationDate() > Time::Now()) << L"CreationDate too recent";
261    cookies->push_back(cc.release());
262  }
263
264  return true;
265}
266
267bool SQLitePersistentCookieStore::Backend::EnsureDatabaseVersion() {
268  // Version check.
269  if (!meta_table_.Init(
270      db_.get(), kCurrentVersionNumber, kCompatibleVersionNumber)) {
271    return false;
272  }
273
274  if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
275    LOG(WARNING) << "Cookie database is too new.";
276    return false;
277  }
278
279  int cur_version = meta_table_.GetVersionNumber();
280  if (cur_version == 2) {
281    sql::Transaction transaction(db_.get());
282    if (!transaction.Begin())
283      return false;
284    if (!db_->Execute("ALTER TABLE cookies ADD COLUMN last_access_utc "
285                     "INTEGER DEFAULT 0") ||
286        !db_->Execute("UPDATE cookies SET last_access_utc = creation_utc")) {
287      LOG(WARNING) << "Unable to update cookie database to version 3.";
288      return false;
289    }
290    ++cur_version;
291    meta_table_.SetVersionNumber(cur_version);
292    meta_table_.SetCompatibleVersionNumber(
293        std::min(cur_version, kCompatibleVersionNumber));
294    transaction.Commit();
295  }
296
297  if (cur_version == 3) {
298    // The time epoch changed for Mac & Linux in this version to match Windows.
299    // This patch came after the main epoch change happened, so some
300    // developers have "good" times for cookies added by the more recent
301    // versions. So we have to be careful to only update times that are under
302    // the old system (which will appear to be from before 1970 in the new
303    // system). The magic number used below is 1970 in our time units.
304    sql::Transaction transaction(db_.get());
305    transaction.Begin();
306#if !defined(OS_WIN)
307    db_->Execute(
308        "UPDATE cookies "
309        "SET creation_utc = creation_utc + 11644473600000000 "
310        "WHERE rowid IN "
311        "(SELECT rowid FROM cookies WHERE "
312          "creation_utc > 0 AND creation_utc < 11644473600000000)");
313    db_->Execute(
314        "UPDATE cookies "
315        "SET expires_utc = expires_utc + 11644473600000000 "
316        "WHERE rowid IN "
317        "(SELECT rowid FROM cookies WHERE "
318          "expires_utc > 0 AND expires_utc < 11644473600000000)");
319    db_->Execute(
320        "UPDATE cookies "
321        "SET last_access_utc = last_access_utc + 11644473600000000 "
322        "WHERE rowid IN "
323        "(SELECT rowid FROM cookies WHERE "
324          "last_access_utc > 0 AND last_access_utc < 11644473600000000)");
325#endif
326    ++cur_version;
327    meta_table_.SetVersionNumber(cur_version);
328    transaction.Commit();
329  }
330
331  // Put future migration cases here.
332
333  // When the version is too old, we just try to continue anyway, there should
334  // not be a released product that makes a database too old for us to handle.
335  LOG_IF(WARNING, cur_version < kCurrentVersionNumber) <<
336      "Cookie database version " << cur_version << " is too old to handle.";
337
338  return true;
339}
340
341void SQLitePersistentCookieStore::Backend::AddCookie(
342    const net::CookieMonster::CanonicalCookie& cc) {
343  BatchOperation(PendingOperation::COOKIE_ADD, cc);
344}
345
346void SQLitePersistentCookieStore::Backend::UpdateCookieAccessTime(
347    const net::CookieMonster::CanonicalCookie& cc) {
348  BatchOperation(PendingOperation::COOKIE_UPDATEACCESS, cc);
349}
350
351void SQLitePersistentCookieStore::Backend::DeleteCookie(
352    const net::CookieMonster::CanonicalCookie& cc) {
353  BatchOperation(PendingOperation::COOKIE_DELETE, cc);
354}
355
356void SQLitePersistentCookieStore::Backend::BatchOperation(
357    PendingOperation::OperationType op,
358    const net::CookieMonster::CanonicalCookie& cc) {
359  // Commit every 30 seconds.
360  static const int kCommitIntervalMs = 30 * 1000;
361  // Commit right away if we have more than 512 outstanding operations.
362  static const size_t kCommitAfterBatchSize = 512;
363#ifndef ANDROID
364  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::DB));
365#endif
366
367  // We do a full copy of the cookie here, and hopefully just here.
368  scoped_ptr<PendingOperation> po(new PendingOperation(op, cc));
369
370  PendingOperationsList::size_type num_pending;
371  {
372    AutoLock locked(lock_);
373    pending_.push_back(po.release());
374    num_pending = ++num_pending_;
375  }
376
377#ifdef ANDROID
378  if (!getDbThread())
379    return;
380  MessageLoop* loop = getDbThread()->message_loop();
381#endif
382
383  if (num_pending == 1) {
384    // We've gotten our first entry for this batch, fire off the timer.
385#ifdef ANDROID
386    loop->PostDelayedTask(FROM_HERE, NewRunnableMethod(
387        this, &Backend::Commit, static_cast<Task*>(NULL)), kCommitIntervalMs);
388#else
389    BrowserThread::PostDelayedTask(
390        BrowserThread::DB, FROM_HERE,
391        NewRunnableMethod(this, &Backend::Commit), kCommitIntervalMs);
392#endif
393  } else if (num_pending == kCommitAfterBatchSize) {
394    // We've reached a big enough batch, fire off a commit now.
395#ifdef ANDROID
396    loop->PostTask(FROM_HERE, NewRunnableMethod(
397        this, &Backend::Commit, static_cast<Task*>(NULL)));
398#else
399    BrowserThread::PostTask(
400        BrowserThread::DB, FROM_HERE,
401        NewRunnableMethod(this, &Backend::Commit));
402#endif
403  }
404}
405
406#if defined(ANDROID)
407void SQLitePersistentCookieStore::Backend::Commit(Task* completion_task) {
408#else
409void SQLitePersistentCookieStore::Backend::Commit() {
410  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
411<<<<<<< HEAD
412#endif
413
414#if defined(ANDROID)
415  if (completion_task) {
416    // We post this task to the current thread, so it won't run until we exit.
417    MessageLoop::current()->PostTask(FROM_HERE, completion_task);
418  }
419#endif
420=======
421>>>>>>> chromium.org at r10.0.621.0
422
423  PendingOperationsList ops;
424  {
425    AutoLock locked(lock_);
426    pending_.swap(ops);
427    num_pending_ = 0;
428  }
429
430  // Maybe an old timer fired or we are already Close()'ed.
431  if (!db_.get() || ops.empty())
432    return;
433
434  sql::Statement add_smt(db_->GetCachedStatement(SQL_FROM_HERE,
435      "INSERT INTO cookies (creation_utc, host_key, name, value, path, "
436      "expires_utc, secure, httponly, last_access_utc) "
437      "VALUES (?,?,?,?,?,?,?,?,?)"));
438  if (!add_smt) {
439    NOTREACHED();
440    return;
441  }
442
443  sql::Statement update_access_smt(db_->GetCachedStatement(SQL_FROM_HERE,
444      "UPDATE cookies SET last_access_utc=? WHERE creation_utc=?"));
445  if (!update_access_smt) {
446    NOTREACHED();
447    return;
448  }
449
450  sql::Statement del_smt(db_->GetCachedStatement(SQL_FROM_HERE,
451                         "DELETE FROM cookies WHERE creation_utc=?"));
452  if (!del_smt) {
453    NOTREACHED();
454    return;
455  }
456
457  sql::Transaction transaction(db_.get());
458  if (!transaction.Begin()) {
459    NOTREACHED();
460    return;
461  }
462#if defined(ANDROID)
463  int cookie_delta = 0;
464#endif
465  for (PendingOperationsList::iterator it = ops.begin();
466       it != ops.end(); ++it) {
467    // Free the cookies as we commit them to the database.
468    scoped_ptr<PendingOperation> po(*it);
469    switch (po->op()) {
470      case PendingOperation::COOKIE_ADD:
471#if defined(ANDROID)
472        ++cookie_delta;
473#endif
474        add_smt.Reset();
475        add_smt.BindInt64(0, po->cc().CreationDate().ToInternalValue());
476        add_smt.BindString(1, po->cc().Domain());
477        add_smt.BindString(2, po->cc().Name());
478        add_smt.BindString(3, po->cc().Value());
479        add_smt.BindString(4, po->cc().Path());
480        add_smt.BindInt64(5, po->cc().ExpiryDate().ToInternalValue());
481        add_smt.BindInt(6, po->cc().IsSecure());
482        add_smt.BindInt(7, po->cc().IsHttpOnly());
483        add_smt.BindInt64(8, po->cc().LastAccessDate().ToInternalValue());
484        if (!add_smt.Run())
485          NOTREACHED() << "Could not add a cookie to the DB.";
486        break;
487
488      case PendingOperation::COOKIE_UPDATEACCESS:
489        update_access_smt.Reset();
490        update_access_smt.BindInt64(0,
491            po->cc().LastAccessDate().ToInternalValue());
492        update_access_smt.BindInt64(1,
493            po->cc().CreationDate().ToInternalValue());
494        if (!update_access_smt.Run())
495          NOTREACHED() << "Could not update cookie last access time in the DB.";
496        break;
497
498      case PendingOperation::COOKIE_DELETE:
499#if defined(ANDROID)
500        --cookie_delta;
501#endif
502        del_smt.Reset();
503        del_smt.BindInt64(0, po->cc().CreationDate().ToInternalValue());
504        if (!del_smt.Run())
505          NOTREACHED() << "Could not delete a cookie from the DB.";
506        break;
507
508      default:
509        NOTREACHED();
510        break;
511    }
512  }
513  bool succeeded = transaction.Commit();
514#if defined(ANDROID)
515  if (succeeded)
516      cookie_count_ += cookie_delta;
517#endif
518  UMA_HISTOGRAM_ENUMERATION("Cookie.BackingStoreUpdateResults",
519                            succeeded ? 0 : 1, 2);
520}
521
522<<<<<<< HEAD
523#if defined(ANDROID)
524void SQLitePersistentCookieStore::Backend::Flush(Task* completion_task) {
525// Keep this #ifdef when upstreaming to Chromium.
526#if defined(ANDROID)
527    if (!getDbThread()) {
528      if (completion_task)
529        MessageLoop::current()->PostTask(FROM_HERE, completion_task);
530      return;
531    }
532
533    MessageLoop* loop = getDbThread()->message_loop();
534    loop->PostTask(FROM_HERE, NewRunnableMethod(
535        this, &Backend::Commit, completion_task));
536#else
537    DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::DB));
538    BrowserThread::PostTask(
539        BrowserThread::DB, FROM_HERE, NewRunnableMethod(
540            this, &Backend::Commit, completion_task));
541#endif
542}
543#endif
544=======
545void SQLitePersistentCookieStore::Backend::Flush(Task* completion_task) {
546  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::DB));
547  BrowserThread::PostTask(
548      BrowserThread::DB, FROM_HERE, NewRunnableMethod(this, &Backend::Commit));
549  if (completion_task) {
550    // We want the completion task to run immediately after Commit() returns.
551    // Posting it from here means there is less chance of another task getting
552    // onto the message queue first, than if we posted it from Commit() itself.
553    BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, completion_task);
554  }
555}
556>>>>>>> chromium.org at r10.0.621.0
557
558// Fire off a close message to the background thread.  We could still have a
559// pending commit timer that will be holding a reference on us, but if/when
560// this fires we will already have been cleaned up and it will be ignored.
561void SQLitePersistentCookieStore::Backend::Close() {
562#ifndef ANDROID
563  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::DB));
564#endif
565
566#ifdef ANDROID
567  if (!getDbThread())
568    return;
569
570  MessageLoop* loop = getDbThread()->message_loop();
571  loop->PostTask(FROM_HERE,
572      NewRunnableMethod(this, &Backend::InternalBackgroundClose));
573#else
574  // Must close the backend on the background thread.
575  BrowserThread::PostTask(
576      BrowserThread::DB, FROM_HERE,
577      NewRunnableMethod(this, &Backend::InternalBackgroundClose));
578#endif
579}
580
581void SQLitePersistentCookieStore::Backend::InternalBackgroundClose() {
582#ifndef ANDROID
583  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
584#endif
585  // Commit any pending operations
586#if defined(ANDROID)
587  Commit(NULL);
588#else
589  Commit();
590<<<<<<< HEAD
591#endif
592  delete db_;
593  db_ = NULL;
594=======
595
596  db_.reset();
597
598  if (clear_local_state_on_exit_)
599    file_util::Delete(path_, false);
600>>>>>>> chromium.org at r10.0.621.0
601}
602
603void SQLitePersistentCookieStore::Backend::SetClearLocalStateOnExit(
604    bool clear_local_state) {
605  AutoLock locked(lock_);
606  clear_local_state_on_exit_ = clear_local_state;
607}
608SQLitePersistentCookieStore::SQLitePersistentCookieStore(const FilePath& path)
609    : backend_(new Backend(path)) {
610}
611
612SQLitePersistentCookieStore::~SQLitePersistentCookieStore() {
613  if (backend_.get()) {
614    backend_->Close();
615    // Release our reference, it will probably still have a reference if the
616    // background thread has not run Close() yet.
617    backend_ = NULL;
618  }
619}
620
621<<<<<<< HEAD
622// Version number of the database. In version 4, we migrated the time epoch.
623// If you open the DB with an older version on Mac or Linux, the times will
624// look wonky, but the file will likely be usable. On Windows version 3 and 4
625// are the same.
626//
627// Version 3 updated the database to include the last access time, so we can
628// expire them in decreasing order of use when we've reached the maximum
629// number of cookies.
630static const int kCurrentVersionNumber = 4;
631static const int kCompatibleVersionNumber = 3;
632
633namespace {
634
635// Initializes the cookies table, returning true on success.
636bool InitTable(sql::Connection* db) {
637  if (!db->DoesTableExist("cookies")) {
638    if (!db->Execute("CREATE TABLE cookies ("
639                     "creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY,"
640                     "host_key TEXT NOT NULL,"
641                     "name TEXT NOT NULL,"
642                     "value TEXT NOT NULL,"
643                     "path TEXT NOT NULL,"
644#if defined(ANDROID)
645                     // On some mobile platforms, we persist session cookies
646                     // because the OS can kill the browser during a session.
647                     // If so, expires_utc is set to 0. When the field is read
648                     // into a Time object, Time::is_null() will return true.
649#else
650                     // We only store persistent, so we know it expires
651#endif
652                     "expires_utc INTEGER NOT NULL,"
653                     "secure INTEGER NOT NULL,"
654                     "httponly INTEGER NOT NULL,"
655                     "last_access_utc INTEGER NOT NULL)"))
656      return false;
657  }
658
659  // Try to create the index every time. Older versions did not have this index,
660  // so we want those people to get it. Ignore errors, since it may exist.
661#ifdef ANDROID
662  db->Execute("CREATE INDEX IF NOT EXISTS cookie_times ON cookies (creation_utc)");
663#else
664  db->Execute("CREATE INDEX cookie_times ON cookies (creation_utc)");
665#endif
666  return true;
667}
668
669}  // namespace
670
671bool SQLitePersistentCookieStore::Load(
672    std::vector<net::CookieMonster::CanonicalCookie*>* cookies) {
673  scoped_ptr<sql::Connection> db(new sql::Connection);
674  if (!db->Open(path_)) {
675    NOTREACHED() << "Unable to open cookie DB.";
676    return false;
677  }
678
679#ifndef ANDROID
680  // GetErrorHandlerForCookieDb is defined in sqlite_diagnostics.h
681  // which we do not currently include on Android
682  db->set_error_delegate(GetErrorHandlerForCookieDb());
683#endif
684
685  if (!EnsureDatabaseVersion(db.get()) || !InitTable(db.get())) {
686    NOTREACHED() << "Unable to initialize cookie DB.";
687    return false;
688  }
689
690  db->Preload();
691
692  // Slurp all the cookies into the out-vector.
693  sql::Statement smt(db->GetUniqueStatement(
694      "SELECT creation_utc, host_key, name, value, path, expires_utc, secure, "
695      "httponly, last_access_utc FROM cookies"));
696  if (!smt) {
697    NOTREACHED() << "select statement prep failed";
698    return false;
699  }
700
701  while (smt.Step()) {
702#if defined(ANDROID)
703    base::Time expires = Time::FromInternalValue(smt.ColumnInt64(5));
704#endif
705    scoped_ptr<net::CookieMonster::CanonicalCookie> cc(
706        new net::CookieMonster::CanonicalCookie(
707            smt.ColumnString(2),                            // name
708            smt.ColumnString(3),                            // value
709            smt.ColumnString(1),                            // domain
710            smt.ColumnString(4),                            // path
711            smt.ColumnInt(6) != 0,                          // secure
712            smt.ColumnInt(7) != 0,                          // httponly
713            Time::FromInternalValue(smt.ColumnInt64(0)),    // creation_utc
714            Time::FromInternalValue(smt.ColumnInt64(8)),    // last_access_utc
715#if defined(ANDROID)
716            !expires.is_null(),                             // has_expires
717            expires));                                      // expires_utc
718#else
719            true,                                           // has_expires
720            Time::FromInternalValue(smt.ColumnInt64(5))));  // expires_utc
721#endif
722    DLOG_IF(WARNING,
723            cc->CreationDate() > Time::Now()) << L"CreationDate too recent";
724    cookies->push_back(cc.release());
725  }
726
727  // Create the backend, this will take ownership of the db pointer.
728  backend_ = new Backend(db.release());
729#if defined(ANDROID)
730  backend_->set_cookie_count(cookies->size());
731#endif
732  return true;
733}
734
735bool SQLitePersistentCookieStore::EnsureDatabaseVersion(sql::Connection* db) {
736  // Version check.
737  if (!meta_table_.Init(db, kCurrentVersionNumber, kCompatibleVersionNumber))
738    return false;
739
740  if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
741    LOG(WARNING) << "Cookie database is too new.";
742    return false;
743  }
744
745  int cur_version = meta_table_.GetVersionNumber();
746  if (cur_version == 2) {
747    sql::Transaction transaction(db);
748    if (!transaction.Begin())
749      return false;
750    if (!db->Execute("ALTER TABLE cookies ADD COLUMN last_access_utc "
751                     "INTEGER DEFAULT 0") ||
752        !db->Execute("UPDATE cookies SET last_access_utc = creation_utc")) {
753      LOG(WARNING) << "Unable to update cookie database to version 3.";
754      return false;
755    }
756    ++cur_version;
757    meta_table_.SetVersionNumber(cur_version);
758    meta_table_.SetCompatibleVersionNumber(
759        std::min(cur_version, kCompatibleVersionNumber));
760    transaction.Commit();
761  }
762
763  if (cur_version == 3) {
764    // The time epoch changed for Mac & Linux in this version to match Windows.
765    // This patch came after the main epoch change happened, so some
766    // developers have "good" times for cookies added by the more recent
767    // versions. So we have to be careful to only update times that are under
768    // the old system (which will appear to be from before 1970 in the new
769    // system). The magic number used below is 1970 in our time units.
770    sql::Transaction transaction(db);
771    transaction.Begin();
772#if !defined(OS_WIN)
773    db->Execute(
774        "UPDATE cookies "
775        "SET creation_utc = creation_utc + 11644473600000000 "
776        "WHERE rowid IN "
777        "(SELECT rowid FROM cookies WHERE "
778          "creation_utc > 0 AND creation_utc < 11644473600000000)");
779    db->Execute(
780        "UPDATE cookies "
781        "SET expires_utc = expires_utc + 11644473600000000 "
782        "WHERE rowid IN "
783        "(SELECT rowid FROM cookies WHERE "
784          "expires_utc > 0 AND expires_utc < 11644473600000000)");
785    db->Execute(
786        "UPDATE cookies "
787        "SET last_access_utc = last_access_utc + 11644473600000000 "
788        "WHERE rowid IN "
789        "(SELECT rowid FROM cookies WHERE "
790          "last_access_utc > 0 AND last_access_utc < 11644473600000000)");
791#endif
792    ++cur_version;
793    meta_table_.SetVersionNumber(cur_version);
794    transaction.Commit();
795  }
796
797  // Put future migration cases here.
798
799  // When the version is too old, we just try to continue anyway, there should
800  // not be a released product that makes a database too old for us to handle.
801  LOG_IF(WARNING, cur_version < kCurrentVersionNumber) <<
802      "Cookie database version " << cur_version << " is too old to handle.";
803
804  return true;
805=======
806bool SQLitePersistentCookieStore::Load(
807    std::vector<net::CookieMonster::CanonicalCookie*>* cookies) {
808  return backend_->Load(cookies);
809>>>>>>> chromium.org at r10.0.621.0
810}
811
812void SQLitePersistentCookieStore::AddCookie(
813    const net::CookieMonster::CanonicalCookie& cc) {
814  if (backend_.get())
815    backend_->AddCookie(cc);
816}
817
818void SQLitePersistentCookieStore::UpdateCookieAccessTime(
819    const net::CookieMonster::CanonicalCookie& cc) {
820  if (backend_.get())
821    backend_->UpdateCookieAccessTime(cc);
822}
823
824void SQLitePersistentCookieStore::DeleteCookie(
825    const net::CookieMonster::CanonicalCookie& cc) {
826  if (backend_.get())
827    backend_->DeleteCookie(cc);
828}
829
830<<<<<<< HEAD
831#if defined(ANDROID)
832void SQLitePersistentCookieStore::Flush(Task* completion_callback) {
833  if (backend_.get())
834    backend_->Flush(completion_callback);
835  else {
836    if (completion_callback)
837      MessageLoop::current()->PostTask(FROM_HERE, completion_callback);
838  }
839}
840#endif
841
842#if defined(ANDROID)
843int SQLitePersistentCookieStore::GetCookieCount() {
844  int result = backend_ ? backend_->get_cookie_count() : 0;
845  return result;
846}
847#endif
848
849// static
850void SQLitePersistentCookieStore::ClearLocalState(
851    const FilePath& path) {
852  file_util::Delete(path, false);
853=======
854void SQLitePersistentCookieStore::SetClearLocalStateOnExit(
855    bool clear_local_state) {
856  if (backend_.get())
857    backend_->SetClearLocalStateOnExit(clear_local_state);
858}
859
860void SQLitePersistentCookieStore::Flush(Task* completion_task) {
861  if (backend_.get())
862    backend_->Flush(completion_task);
863  else if (completion_task)
864    MessageLoop::current()->PostTask(FROM_HERE, completion_task);
865>>>>>>> chromium.org at r10.0.621.0
866}
867