Home | History | Annotate | Download | only in indexed_db
      1 // Copyright (c) 2013 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 "content/browser/indexed_db/indexed_db_backing_store.h"
      6 
      7 #include "base/file_util.h"
      8 #include "base/logging.h"
      9 #include "base/metrics/histogram.h"
     10 #include "base/strings/string_piece.h"
     11 #include "base/strings/string_util.h"
     12 #include "base/strings/utf_string_conversions.h"
     13 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
     14 #include "content/browser/indexed_db/indexed_db_metadata.h"
     15 #include "content/browser/indexed_db/indexed_db_tracing.h"
     16 #include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
     17 #include "content/browser/indexed_db/leveldb/leveldb_database.h"
     18 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
     19 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
     20 #include "content/common/indexed_db/indexed_db_key.h"
     21 #include "content/common/indexed_db/indexed_db_key_path.h"
     22 #include "content/common/indexed_db/indexed_db_key_range.h"
     23 #include "third_party/WebKit/public/platform/WebIDBTypes.h"
     24 #include "third_party/WebKit/public/web/WebSerializedScriptValueVersion.h"
     25 #include "third_party/leveldatabase/env_chromium.h"
     26 #include "webkit/common/database/database_identifier.h"
     27 
     28 using base::StringPiece;
     29 
     30 namespace content {
     31 
     32 namespace {
     33 
     34 static std::string ComputeOriginIdentifier(const GURL& origin_url) {
     35   return webkit_database::GetIdentifierFromOrigin(origin_url) + "@1";
     36 }
     37 
     38 static base::FilePath ComputeFileName(const GURL& origin_url) {
     39   return base::FilePath()
     40       .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url))
     41       .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb"));
     42 }
     43 
     44 }  // namespace
     45 
     46 static const int64 kKeyGeneratorInitialNumber =
     47     1;  // From the IndexedDB specification.
     48 
     49 enum IndexedDBBackingStoreErrorSource {
     50   // 0 - 2 are no longer used.
     51   FIND_KEY_IN_INDEX = 3,
     52   GET_IDBDATABASE_METADATA,
     53   GET_INDEXES,
     54   GET_KEY_GENERATOR_CURRENT_NUMBER,
     55   GET_OBJECT_STORES,
     56   GET_RECORD,
     57   KEY_EXISTS_IN_OBJECT_STORE,
     58   LOAD_CURRENT_ROW,
     59   SET_UP_METADATA,
     60   GET_PRIMARY_KEY_VIA_INDEX,
     61   KEY_EXISTS_IN_INDEX,
     62   VERSION_EXISTS,
     63   DELETE_OBJECT_STORE,
     64   SET_MAX_OBJECT_STORE_ID,
     65   SET_MAX_INDEX_ID,
     66   GET_NEW_DATABASE_ID,
     67   GET_NEW_VERSION_NUMBER,
     68   CREATE_IDBDATABASE_METADATA,
     69   DELETE_DATABASE,
     70   TRANSACTION_COMMIT_METHOD,  // TRANSACTION_COMMIT is a WinNT.h macro
     71   GET_DATABASE_NAMES,
     72   INTERNAL_ERROR_MAX,
     73 };
     74 
     75 static void RecordInternalError(const char* type,
     76                                 IndexedDBBackingStoreErrorSource location) {
     77   std::string name;
     78   name.append("WebCore.IndexedDB.BackingStore.").append(type).append("Error");
     79   base::Histogram::FactoryGet(name,
     80                               1,
     81                               INTERNAL_ERROR_MAX,
     82                               INTERNAL_ERROR_MAX + 1,
     83                               base::HistogramBase::kUmaTargetedHistogramFlag)
     84       ->Add(location);
     85 }
     86 
     87 // Use to signal conditions that usually indicate developer error, but
     88 // could be caused by data corruption.  A macro is used instead of an
     89 // inline function so that the assert and log report the line number.
     90 #define REPORT_ERROR(type, location)                      \
     91   do {                                                    \
     92     LOG(ERROR) << "IndexedDB " type " Error: " #location; \
     93     NOTREACHED();                                         \
     94     RecordInternalError(type, location);                  \
     95   } while (0)
     96 
     97 #define INTERNAL_READ_ERROR(location) REPORT_ERROR("Read", location)
     98 #define INTERNAL_CONSISTENCY_ERROR(location) \
     99   REPORT_ERROR("Consistency", location)
    100 #define INTERNAL_WRITE_ERROR(location) REPORT_ERROR("Write", location)
    101 
    102 static void PutBool(LevelDBTransaction* transaction,
    103                     const StringPiece& key,
    104                     bool value) {
    105   std::string buffer;
    106   EncodeBool(value, &buffer);
    107   transaction->Put(key, &buffer);
    108 }
    109 
    110 template <typename DBOrTransaction>
    111 static bool GetInt(DBOrTransaction* db,
    112                    const StringPiece& key,
    113                    int64* found_int,
    114                    bool* found) {
    115   std::string result;
    116   bool ok = db->Get(key, &result, found);
    117   if (!ok)
    118     return false;
    119   if (!*found)
    120     return true;
    121   StringPiece slice(result);
    122   return DecodeInt(&slice, found_int) && slice.empty();
    123 }
    124 
    125 static void PutInt(LevelDBTransaction* transaction,
    126                    const StringPiece& key,
    127                    int64 value) {
    128   DCHECK_GE(value, 0);
    129   std::string buffer;
    130   EncodeInt(value, &buffer);
    131   transaction->Put(key, &buffer);
    132 }
    133 
    134 template <typename DBOrTransaction>
    135 WARN_UNUSED_RESULT static bool GetVarInt(DBOrTransaction* db,
    136                                          const StringPiece& key,
    137                                          int64* found_int,
    138                                          bool* found) {
    139   std::string result;
    140   bool ok = db->Get(key, &result, found);
    141   if (!ok)
    142     return false;
    143   if (!*found)
    144     return true;
    145   StringPiece slice(result);
    146   return DecodeVarInt(&slice, found_int) && slice.empty();
    147 }
    148 
    149 static void PutVarInt(LevelDBTransaction* transaction,
    150                       const StringPiece& key,
    151                       int64 value) {
    152   std::string buffer;
    153   EncodeVarInt(value, &buffer);
    154   transaction->Put(key, &buffer);
    155 }
    156 
    157 template <typename DBOrTransaction>
    158 WARN_UNUSED_RESULT static bool GetString(DBOrTransaction* db,
    159                                          const StringPiece& key,
    160                                          base::string16* found_string,
    161                                          bool* found) {
    162   std::string result;
    163   *found = false;
    164   bool ok = db->Get(key, &result, found);
    165   if (!ok)
    166     return false;
    167   if (!*found)
    168     return true;
    169   StringPiece slice(result);
    170   return DecodeString(&slice, found_string) && slice.empty();
    171 }
    172 
    173 static void PutString(LevelDBTransaction* transaction,
    174                       const StringPiece& key,
    175                       const base::string16& value) {
    176   std::string buffer;
    177   EncodeString(value, &buffer);
    178   transaction->Put(key, &buffer);
    179 }
    180 
    181 static void PutIDBKeyPath(LevelDBTransaction* transaction,
    182                           const StringPiece& key,
    183                           const IndexedDBKeyPath& value) {
    184   std::string buffer;
    185   EncodeIDBKeyPath(value, &buffer);
    186   transaction->Put(key, &buffer);
    187 }
    188 
    189 static int CompareKeys(const StringPiece& a, const StringPiece& b) {
    190   return Compare(a, b, false /*index_keys*/);
    191 }
    192 
    193 static int CompareIndexKeys(const StringPiece& a, const StringPiece& b) {
    194   return Compare(a, b, true /*index_keys*/);
    195 }
    196 
    197 class Comparator : public LevelDBComparator {
    198  public:
    199   virtual int Compare(const StringPiece& a, const StringPiece& b) const
    200       OVERRIDE {
    201     return content::Compare(a, b, false /*index_keys*/);
    202   }
    203   virtual const char* Name() const OVERRIDE { return "idb_cmp1"; }
    204 };
    205 
    206 // 0 - Initial version.
    207 // 1 - Adds UserIntVersion to DatabaseMetaData.
    208 // 2 - Adds DataVersion to to global metadata.
    209 static const int64 kLatestKnownSchemaVersion = 2;
    210 WARN_UNUSED_RESULT static bool IsSchemaKnown(LevelDBDatabase* db, bool* known) {
    211   int64 db_schema_version = 0;
    212   bool found = false;
    213   bool ok = GetInt(db, SchemaVersionKey::Encode(), &db_schema_version, &found);
    214   if (!ok)
    215     return false;
    216   if (!found) {
    217     *known = true;
    218     return true;
    219   }
    220   if (db_schema_version > kLatestKnownSchemaVersion) {
    221     *known = false;
    222     return true;
    223   }
    224 
    225   const uint32 latest_known_data_version =
    226       blink::kSerializedScriptValueVersion;
    227   int64 db_data_version = 0;
    228   ok = GetInt(db, DataVersionKey::Encode(), &db_data_version, &found);
    229   if (!ok)
    230     return false;
    231   if (!found) {
    232     *known = true;
    233     return true;
    234   }
    235 
    236   if (db_data_version > latest_known_data_version) {
    237     *known = false;
    238     return true;
    239   }
    240 
    241   *known = true;
    242   return true;
    243 }
    244 
    245 WARN_UNUSED_RESULT static bool SetUpMetadata(
    246     LevelDBDatabase* db,
    247     const std::string& origin_identifier) {
    248   const uint32 latest_known_data_version =
    249       blink::kSerializedScriptValueVersion;
    250   const std::string schema_version_key = SchemaVersionKey::Encode();
    251   const std::string data_version_key = DataVersionKey::Encode();
    252 
    253   scoped_refptr<LevelDBTransaction> transaction = new LevelDBTransaction(db);
    254 
    255   int64 db_schema_version = 0;
    256   int64 db_data_version = 0;
    257   bool found = false;
    258   bool ok =
    259       GetInt(transaction.get(), schema_version_key, &db_schema_version, &found);
    260   if (!ok) {
    261     INTERNAL_READ_ERROR(SET_UP_METADATA);
    262     return false;
    263   }
    264   if (!found) {
    265     // Initialize new backing store.
    266     db_schema_version = kLatestKnownSchemaVersion;
    267     PutInt(transaction.get(), schema_version_key, db_schema_version);
    268     db_data_version = latest_known_data_version;
    269     PutInt(transaction.get(), data_version_key, db_data_version);
    270   } else {
    271     // Upgrade old backing store.
    272     DCHECK_LE(db_schema_version, kLatestKnownSchemaVersion);
    273     if (db_schema_version < 1) {
    274       db_schema_version = 1;
    275       PutInt(transaction.get(), schema_version_key, db_schema_version);
    276       const std::string start_key =
    277           DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier);
    278       const std::string stop_key =
    279           DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier);
    280       scoped_ptr<LevelDBIterator> it = db->CreateIterator();
    281       for (it->Seek(start_key);
    282            it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
    283            it->Next()) {
    284         int64 database_id = 0;
    285         found = false;
    286         bool ok = GetInt(transaction.get(), it->Key(), &database_id, &found);
    287         if (!ok) {
    288           INTERNAL_READ_ERROR(SET_UP_METADATA);
    289           return false;
    290         }
    291         if (!found) {
    292           INTERNAL_CONSISTENCY_ERROR(SET_UP_METADATA);
    293           return false;
    294         }
    295         std::string int_version_key = DatabaseMetaDataKey::Encode(
    296             database_id, DatabaseMetaDataKey::USER_INT_VERSION);
    297         PutVarInt(transaction.get(),
    298                   int_version_key,
    299                   IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
    300       }
    301     }
    302     if (db_schema_version < 2) {
    303       db_schema_version = 2;
    304       PutInt(transaction.get(), schema_version_key, db_schema_version);
    305       db_data_version = blink::kSerializedScriptValueVersion;
    306       PutInt(transaction.get(), data_version_key, db_data_version);
    307     }
    308   }
    309 
    310   // All new values will be written using this serialization version.
    311   found = false;
    312   ok = GetInt(transaction.get(), data_version_key, &db_data_version, &found);
    313   if (!ok) {
    314     INTERNAL_READ_ERROR(SET_UP_METADATA);
    315     return false;
    316   }
    317   if (!found) {
    318     INTERNAL_CONSISTENCY_ERROR(SET_UP_METADATA);
    319     return false;
    320   }
    321   if (db_data_version < latest_known_data_version) {
    322     db_data_version = latest_known_data_version;
    323     PutInt(transaction.get(), data_version_key, db_data_version);
    324   }
    325 
    326   DCHECK_EQ(db_schema_version, kLatestKnownSchemaVersion);
    327   DCHECK_EQ(db_data_version, latest_known_data_version);
    328 
    329   if (!transaction->Commit()) {
    330     INTERNAL_WRITE_ERROR(SET_UP_METADATA);
    331     return false;
    332   }
    333   return true;
    334 }
    335 
    336 template <typename DBOrTransaction>
    337 WARN_UNUSED_RESULT static bool GetMaxObjectStoreId(DBOrTransaction* db,
    338                                                    int64 database_id,
    339                                                    int64* max_object_store_id) {
    340   const std::string max_object_store_id_key = DatabaseMetaDataKey::Encode(
    341       database_id, DatabaseMetaDataKey::MAX_OBJECT_STORE_ID);
    342   bool ok =
    343       GetMaxObjectStoreId(db, max_object_store_id_key, max_object_store_id);
    344   return ok;
    345 }
    346 
    347 template <typename DBOrTransaction>
    348 WARN_UNUSED_RESULT static bool GetMaxObjectStoreId(
    349     DBOrTransaction* db,
    350     const std::string& max_object_store_id_key,
    351     int64* max_object_store_id) {
    352   *max_object_store_id = -1;
    353   bool found = false;
    354   bool ok = GetInt(db, max_object_store_id_key, max_object_store_id, &found);
    355   if (!ok)
    356     return false;
    357   if (!found)
    358     *max_object_store_id = 0;
    359 
    360   DCHECK_GE(*max_object_store_id, 0);
    361   return true;
    362 }
    363 
    364 class DefaultLevelDBFactory : public LevelDBFactory {
    365  public:
    366   virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name,
    367                                       const LevelDBComparator* comparator,
    368                                       scoped_ptr<LevelDBDatabase>* db,
    369                                       bool* is_disk_full) OVERRIDE {
    370     return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full);
    371   }
    372   virtual bool DestroyLevelDB(const base::FilePath& file_name) OVERRIDE {
    373     return LevelDBDatabase::Destroy(file_name);
    374   }
    375 };
    376 
    377 IndexedDBBackingStore::IndexedDBBackingStore(
    378     const GURL& origin_url,
    379     scoped_ptr<LevelDBDatabase> db,
    380     scoped_ptr<LevelDBComparator> comparator)
    381     : origin_url_(origin_url),
    382       origin_identifier_(ComputeOriginIdentifier(origin_url)),
    383       db_(db.Pass()),
    384       comparator_(comparator.Pass()) {}
    385 
    386 IndexedDBBackingStore::~IndexedDBBackingStore() {
    387   // db_'s destructor uses comparator_. The order of destruction is important.
    388   db_.reset();
    389   comparator_.reset();
    390 }
    391 
    392 IndexedDBBackingStore::RecordIdentifier::RecordIdentifier(
    393     const std::string& primary_key,
    394     int64 version)
    395     : primary_key_(primary_key), version_(version) {
    396   DCHECK(!primary_key.empty());
    397 }
    398 IndexedDBBackingStore::RecordIdentifier::RecordIdentifier()
    399     : primary_key_(), version_(-1) {}
    400 IndexedDBBackingStore::RecordIdentifier::~RecordIdentifier() {}
    401 
    402 IndexedDBBackingStore::Cursor::CursorOptions::CursorOptions() {}
    403 IndexedDBBackingStore::Cursor::CursorOptions::~CursorOptions() {}
    404 
    405 enum IndexedDBBackingStoreOpenResult {
    406   INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS,
    407   INDEXED_DB_BACKING_STORE_OPEN_SUCCESS,
    408   INDEXED_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY,
    409   INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_SCHEMA,
    410   INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_DESTROY_FAILED,
    411   INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_FAILED,
    412   INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_SUCCESS,
    413   INDEXED_DB_BACKING_STORE_OPEN_FAILED_IO_ERROR_CHECKING_SCHEMA,
    414   INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR,
    415   INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED,
    416   INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII,
    417   INDEXED_DB_BACKING_STORE_OPEN_DISK_FULL_DEPRECATED,
    418   INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG,
    419   INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY,
    420   INDEXED_DB_BACKING_STORE_OPEN_MAX,
    421 };
    422 
    423 // static
    424 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
    425     const GURL& origin_url,
    426     const base::FilePath& path_base,
    427     blink::WebIDBDataLoss* data_loss,
    428     std::string* data_loss_message,
    429     bool* disk_full) {
    430   *data_loss = blink::WebIDBDataLossNone;
    431   DefaultLevelDBFactory leveldb_factory;
    432   return IndexedDBBackingStore::Open(origin_url,
    433                                      path_base,
    434                                      data_loss,
    435                                      data_loss_message,
    436                                      disk_full,
    437                                      &leveldb_factory);
    438 }
    439 
    440 static std::string OriginToCustomHistogramSuffix(const GURL& origin_url) {
    441   if (origin_url.host() == "docs.google.com")
    442     return ".Docs";
    443   return std::string();
    444 }
    445 
    446 static void HistogramOpenStatus(IndexedDBBackingStoreOpenResult result,
    447                                 const GURL& origin_url) {
    448   UMA_HISTOGRAM_ENUMERATION("WebCore.IndexedDB.BackingStore.OpenStatus",
    449                             result,
    450                             INDEXED_DB_BACKING_STORE_OPEN_MAX);
    451   const std::string suffix = OriginToCustomHistogramSuffix(origin_url);
    452   // Data from the WebCore.IndexedDB.BackingStore.OpenStatus histogram is used
    453   // to generate a graph. So as not to alter the meaning of that graph,
    454   // continue to collect all stats there (above) but also now collect docs stats
    455   // separately (below).
    456   if (!suffix.empty()) {
    457     base::LinearHistogram::FactoryGet(
    458         "WebCore.IndexedDB.BackingStore.OpenStatus" + suffix,
    459         1,
    460         INDEXED_DB_BACKING_STORE_OPEN_MAX,
    461         INDEXED_DB_BACKING_STORE_OPEN_MAX + 1,
    462         base::HistogramBase::kUmaTargetedHistogramFlag)->Add(result);
    463   }
    464 }
    465 
    466 static bool IsPathTooLong(const base::FilePath& leveldb_dir) {
    467   int limit = file_util::GetMaximumPathComponentLength(leveldb_dir.DirName());
    468   if (limit == -1) {
    469     DLOG(WARNING) << "GetMaximumPathComponentLength returned -1";
    470     // In limited testing, ChromeOS returns 143, other OSes 255.
    471 #if defined(OS_CHROMEOS)
    472     limit = 143;
    473 #else
    474     limit = 255;
    475 #endif
    476   }
    477   size_t component_length = leveldb_dir.BaseName().value().length();
    478   if (component_length > static_cast<uint32_t>(limit)) {
    479     DLOG(WARNING) << "Path component length (" << component_length
    480                   << ") exceeds maximum (" << limit
    481                   << ") allowed by this filesystem.";
    482     const int min = 140;
    483     const int max = 300;
    484     const int num_buckets = 12;
    485     UMA_HISTOGRAM_CUSTOM_COUNTS(
    486         "WebCore.IndexedDB.BackingStore.OverlyLargeOriginLength",
    487         component_length,
    488         min,
    489         max,
    490         num_buckets);
    491     return true;
    492   }
    493   return false;
    494 }
    495 
    496 // static
    497 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
    498     const GURL& origin_url,
    499     const base::FilePath& path_base,
    500     blink::WebIDBDataLoss* data_loss,
    501     std::string* data_loss_message,
    502     bool* is_disk_full,
    503     LevelDBFactory* leveldb_factory) {
    504   IDB_TRACE("IndexedDBBackingStore::Open");
    505   DCHECK(!path_base.empty());
    506   *data_loss = blink::WebIDBDataLossNone;
    507   *data_loss_message = "";
    508   *is_disk_full = false;
    509 
    510   scoped_ptr<LevelDBComparator> comparator(new Comparator());
    511 
    512   if (!IsStringASCII(path_base.AsUTF8Unsafe())) {
    513     HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII,
    514                         origin_url);
    515   }
    516   if (!base::CreateDirectory(path_base)) {
    517     LOG(ERROR) << "Unable to create IndexedDB database path "
    518                << path_base.AsUTF8Unsafe();
    519     HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY,
    520                         origin_url);
    521     return scoped_refptr<IndexedDBBackingStore>();
    522   }
    523 
    524   const base::FilePath file_path =
    525       path_base.Append(ComputeFileName(origin_url));
    526 
    527   if (IsPathTooLong(file_path)) {
    528     HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG,
    529                         origin_url);
    530     return scoped_refptr<IndexedDBBackingStore>();
    531   }
    532 
    533   scoped_ptr<LevelDBDatabase> db;
    534   leveldb::Status status = leveldb_factory->OpenLevelDB(
    535       file_path, comparator.get(), &db, is_disk_full);
    536 
    537   DCHECK(!db == !status.ok());
    538   if (!status.ok()) {
    539     if (leveldb_env::IndicatesDiskFull(status)) {
    540       *is_disk_full = true;
    541     } else if (leveldb_env::IsCorruption(status)) {
    542       *data_loss = blink::WebIDBDataLossTotal;
    543       *data_loss_message = leveldb_env::GetCorruptionMessage(status);
    544     }
    545   }
    546 
    547   bool is_schema_known = false;
    548   if (db) {
    549     bool ok = IsSchemaKnown(db.get(), &is_schema_known);
    550     if (!ok) {
    551       LOG(ERROR) << "IndexedDB had IO error checking schema, treating it as "
    552                     "failure to open";
    553       HistogramOpenStatus(
    554           INDEXED_DB_BACKING_STORE_OPEN_FAILED_IO_ERROR_CHECKING_SCHEMA,
    555           origin_url);
    556       db.reset();
    557       *data_loss = blink::WebIDBDataLossTotal;
    558       *data_loss_message = "I/O error checking schema";
    559     } else if (!is_schema_known) {
    560       LOG(ERROR) << "IndexedDB backing store had unknown schema, treating it "
    561                     "as failure to open";
    562       HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_SCHEMA,
    563                           origin_url);
    564       db.reset();
    565       *data_loss = blink::WebIDBDataLossTotal;
    566       *data_loss_message = "Unknown schema";
    567     }
    568   }
    569 
    570   DCHECK(status.ok() || !is_schema_known || leveldb_env::IsIOError(status) ||
    571          leveldb_env::IsCorruption(status));
    572 
    573   if (db) {
    574     HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_SUCCESS, origin_url);
    575   } else if (leveldb_env::IsIOError(status)) {
    576     LOG(ERROR) << "Unable to open backing store, not trying to recover - "
    577                << status.ToString();
    578     HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY, origin_url);
    579     return scoped_refptr<IndexedDBBackingStore>();
    580   } else {
    581     DCHECK(!is_schema_known || leveldb_env::IsCorruption(status));
    582     LOG(ERROR) << "IndexedDB backing store open failed, attempting cleanup";
    583     bool success = leveldb_factory->DestroyLevelDB(file_path);
    584     if (!success) {
    585       LOG(ERROR) << "IndexedDB backing store cleanup failed";
    586       HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_DESTROY_FAILED,
    587                           origin_url);
    588       return scoped_refptr<IndexedDBBackingStore>();
    589     }
    590 
    591     LOG(ERROR) << "IndexedDB backing store cleanup succeeded, reopening";
    592     leveldb_factory->OpenLevelDB(file_path, comparator.get(), &db, NULL);
    593     if (!db) {
    594       LOG(ERROR) << "IndexedDB backing store reopen after recovery failed";
    595       HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_FAILED,
    596                           origin_url);
    597       return scoped_refptr<IndexedDBBackingStore>();
    598     }
    599     HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_SUCCESS,
    600                         origin_url);
    601   }
    602 
    603   if (!db) {
    604     NOTREACHED();
    605     HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR,
    606                         origin_url);
    607     return scoped_refptr<IndexedDBBackingStore>();
    608   }
    609 
    610   return Create(origin_url, db.Pass(), comparator.Pass());
    611 }
    612 
    613 // static
    614 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
    615     const GURL& origin_url) {
    616   DefaultLevelDBFactory leveldb_factory;
    617   return IndexedDBBackingStore::OpenInMemory(origin_url, &leveldb_factory);
    618 }
    619 
    620 // static
    621 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
    622     const GURL& origin_url,
    623     LevelDBFactory* leveldb_factory) {
    624   IDB_TRACE("IndexedDBBackingStore::OpenInMemory");
    625 
    626   scoped_ptr<LevelDBComparator> comparator(new Comparator());
    627   scoped_ptr<LevelDBDatabase> db =
    628       LevelDBDatabase::OpenInMemory(comparator.get());
    629   if (!db) {
    630     LOG(ERROR) << "LevelDBDatabase::OpenInMemory failed.";
    631     HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED,
    632                         origin_url);
    633     return scoped_refptr<IndexedDBBackingStore>();
    634   }
    635   HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS, origin_url);
    636 
    637   return Create(origin_url, db.Pass(), comparator.Pass());
    638 }
    639 
    640 // static
    641 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create(
    642     const GURL& origin_url,
    643     scoped_ptr<LevelDBDatabase> db,
    644     scoped_ptr<LevelDBComparator> comparator) {
    645   // TODO(jsbell): Handle comparator name changes.
    646 
    647   scoped_refptr<IndexedDBBackingStore> backing_store(
    648       new IndexedDBBackingStore(origin_url, db.Pass(), comparator.Pass()));
    649   if (!SetUpMetadata(backing_store->db_.get(),
    650                      backing_store->origin_identifier_))
    651     return scoped_refptr<IndexedDBBackingStore>();
    652 
    653   return backing_store;
    654 }
    655 
    656 std::vector<base::string16> IndexedDBBackingStore::GetDatabaseNames() {
    657   std::vector<base::string16> found_names;
    658   const std::string start_key =
    659       DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier_);
    660   const std::string stop_key =
    661       DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier_);
    662 
    663   DCHECK(found_names.empty());
    664 
    665   scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
    666   for (it->Seek(start_key);
    667        it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
    668        it->Next()) {
    669     StringPiece slice(it->Key());
    670     DatabaseNameKey database_name_key;
    671     if (!DatabaseNameKey::Decode(&slice, &database_name_key)) {
    672       INTERNAL_CONSISTENCY_ERROR(GET_DATABASE_NAMES);
    673       continue;
    674     }
    675     found_names.push_back(database_name_key.database_name());
    676   }
    677   return found_names;
    678 }
    679 
    680 bool IndexedDBBackingStore::GetIDBDatabaseMetaData(
    681     const base::string16& name,
    682     IndexedDBDatabaseMetadata* metadata,
    683     bool* found) {
    684   const std::string key = DatabaseNameKey::Encode(origin_identifier_, name);
    685   *found = false;
    686 
    687   bool ok = GetInt(db_.get(), key, &metadata->id, found);
    688   if (!ok) {
    689     INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA);
    690     return false;
    691   }
    692   if (!*found)
    693     return true;
    694 
    695   ok = GetString(db_.get(),
    696                  DatabaseMetaDataKey::Encode(metadata->id,
    697                                              DatabaseMetaDataKey::USER_VERSION),
    698                  &metadata->version,
    699                  found);
    700   if (!ok) {
    701     INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA);
    702     return false;
    703   }
    704   if (!*found) {
    705     INTERNAL_CONSISTENCY_ERROR(GET_IDBDATABASE_METADATA);
    706     return false;
    707   }
    708 
    709   ok = GetVarInt(db_.get(),
    710                  DatabaseMetaDataKey::Encode(
    711                      metadata->id, DatabaseMetaDataKey::USER_INT_VERSION),
    712                  &metadata->int_version,
    713                  found);
    714   if (!ok) {
    715     INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA);
    716     return false;
    717   }
    718   if (!*found) {
    719     INTERNAL_CONSISTENCY_ERROR(GET_IDBDATABASE_METADATA);
    720     return false;
    721   }
    722 
    723   if (metadata->int_version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION)
    724     metadata->int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
    725 
    726   ok = GetMaxObjectStoreId(
    727       db_.get(), metadata->id, &metadata->max_object_store_id);
    728   if (!ok) {
    729     INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA);
    730     return false;
    731   }
    732 
    733   return true;
    734 }
    735 
    736 WARN_UNUSED_RESULT static bool GetNewDatabaseId(LevelDBTransaction* transaction,
    737                                                 int64* new_id) {
    738   *new_id = -1;
    739   int64 max_database_id = -1;
    740   bool found = false;
    741   bool ok =
    742       GetInt(transaction, MaxDatabaseIdKey::Encode(), &max_database_id, &found);
    743   if (!ok) {
    744     INTERNAL_READ_ERROR(GET_NEW_DATABASE_ID);
    745     return false;
    746   }
    747   if (!found)
    748     max_database_id = 0;
    749 
    750   DCHECK_GE(max_database_id, 0);
    751 
    752   int64 database_id = max_database_id + 1;
    753   PutInt(transaction, MaxDatabaseIdKey::Encode(), database_id);
    754   *new_id = database_id;
    755   return true;
    756 }
    757 
    758 bool IndexedDBBackingStore::CreateIDBDatabaseMetaData(
    759     const base::string16& name,
    760     const base::string16& version,
    761     int64 int_version,
    762     int64* row_id) {
    763   scoped_refptr<LevelDBTransaction> transaction =
    764       new LevelDBTransaction(db_.get());
    765 
    766   bool ok = GetNewDatabaseId(transaction.get(), row_id);
    767   if (!ok)
    768     return false;
    769   DCHECK_GE(*row_id, 0);
    770 
    771   if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION)
    772     int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
    773 
    774   PutInt(transaction.get(),
    775          DatabaseNameKey::Encode(origin_identifier_, name),
    776          *row_id);
    777   PutString(
    778       transaction.get(),
    779       DatabaseMetaDataKey::Encode(*row_id, DatabaseMetaDataKey::USER_VERSION),
    780       version);
    781   PutVarInt(transaction.get(),
    782             DatabaseMetaDataKey::Encode(*row_id,
    783                                         DatabaseMetaDataKey::USER_INT_VERSION),
    784             int_version);
    785   if (!transaction->Commit()) {
    786     INTERNAL_WRITE_ERROR(CREATE_IDBDATABASE_METADATA);
    787     return false;
    788   }
    789   return true;
    790 }
    791 
    792 bool IndexedDBBackingStore::UpdateIDBDatabaseIntVersion(
    793     IndexedDBBackingStore::Transaction* transaction,
    794     int64 row_id,
    795     int64 int_version) {
    796   if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION)
    797     int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
    798   DCHECK_GE(int_version, 0) << "int_version was " << int_version;
    799   PutVarInt(transaction->transaction(),
    800             DatabaseMetaDataKey::Encode(row_id,
    801                                         DatabaseMetaDataKey::USER_INT_VERSION),
    802             int_version);
    803   return true;
    804 }
    805 
    806 static void DeleteRange(LevelDBTransaction* transaction,
    807                         const std::string& begin,
    808                         const std::string& end) {
    809   scoped_ptr<LevelDBIterator> it = transaction->CreateIterator();
    810   for (it->Seek(begin); it->IsValid() && CompareKeys(it->Key(), end) < 0;
    811        it->Next())
    812     transaction->Remove(it->Key());
    813 }
    814 
    815 bool IndexedDBBackingStore::DeleteDatabase(const base::string16& name) {
    816   IDB_TRACE("IndexedDBBackingStore::DeleteDatabase");
    817   scoped_ptr<LevelDBWriteOnlyTransaction> transaction =
    818       LevelDBWriteOnlyTransaction::Create(db_.get());
    819 
    820   IndexedDBDatabaseMetadata metadata;
    821   bool success = false;
    822   bool ok = GetIDBDatabaseMetaData(name, &metadata, &success);
    823   if (!ok)
    824     return false;
    825   if (!success)
    826     return true;
    827 
    828   const std::string start_key = DatabaseMetaDataKey::Encode(
    829       metadata.id, DatabaseMetaDataKey::ORIGIN_NAME);
    830   const std::string stop_key = DatabaseMetaDataKey::Encode(
    831       metadata.id + 1, DatabaseMetaDataKey::ORIGIN_NAME);
    832   scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
    833   for (it->Seek(start_key);
    834        it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
    835        it->Next())
    836     transaction->Remove(it->Key());
    837 
    838   const std::string key = DatabaseNameKey::Encode(origin_identifier_, name);
    839   transaction->Remove(key);
    840 
    841   if (!transaction->Commit()) {
    842     INTERNAL_WRITE_ERROR(DELETE_DATABASE);
    843     return false;
    844   }
    845   return true;
    846 }
    847 
    848 static bool CheckObjectStoreAndMetaDataType(const LevelDBIterator* it,
    849                                             const std::string& stop_key,
    850                                             int64 object_store_id,
    851                                             int64 meta_data_type) {
    852   if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0)
    853     return false;
    854 
    855   StringPiece slice(it->Key());
    856   ObjectStoreMetaDataKey meta_data_key;
    857   bool ok = ObjectStoreMetaDataKey::Decode(&slice, &meta_data_key);
    858   DCHECK(ok);
    859   if (meta_data_key.ObjectStoreId() != object_store_id)
    860     return false;
    861   if (meta_data_key.MetaDataType() != meta_data_type)
    862     return false;
    863   return true;
    864 }
    865 
    866 // TODO(jsbell): This should do some error handling rather than
    867 // plowing ahead when bad data is encountered.
    868 bool IndexedDBBackingStore::GetObjectStores(
    869     int64 database_id,
    870     IndexedDBDatabaseMetadata::ObjectStoreMap* object_stores) {
    871   IDB_TRACE("IndexedDBBackingStore::GetObjectStores");
    872   if (!KeyPrefix::IsValidDatabaseId(database_id))
    873     return false;
    874   const std::string start_key =
    875       ObjectStoreMetaDataKey::Encode(database_id, 1, 0);
    876   const std::string stop_key =
    877       ObjectStoreMetaDataKey::EncodeMaxKey(database_id);
    878 
    879   DCHECK(object_stores->empty());
    880 
    881   scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
    882   it->Seek(start_key);
    883   while (it->IsValid() && CompareKeys(it->Key(), stop_key) < 0) {
    884     StringPiece slice(it->Key());
    885     ObjectStoreMetaDataKey meta_data_key;
    886     bool ok = ObjectStoreMetaDataKey::Decode(&slice, &meta_data_key);
    887     DCHECK(ok);
    888     if (meta_data_key.MetaDataType() != ObjectStoreMetaDataKey::NAME) {
    889       INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
    890       // Possible stale metadata, but don't fail the load.
    891       it->Next();
    892       continue;
    893     }
    894 
    895     int64 object_store_id = meta_data_key.ObjectStoreId();
    896 
    897     // TODO(jsbell): Do this by direct key lookup rather than iteration, to
    898     // simplify.
    899     base::string16 object_store_name;
    900     {
    901       StringPiece slice(it->Value());
    902       if (!DecodeString(&slice, &object_store_name) || !slice.empty())
    903         INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
    904     }
    905 
    906     it->Next();
    907     if (!CheckObjectStoreAndMetaDataType(it.get(),
    908                                          stop_key,
    909                                          object_store_id,
    910                                          ObjectStoreMetaDataKey::KEY_PATH)) {
    911       INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
    912       break;
    913     }
    914     IndexedDBKeyPath key_path;
    915     {
    916       StringPiece slice(it->Value());
    917       if (!DecodeIDBKeyPath(&slice, &key_path) || !slice.empty())
    918         INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
    919     }
    920 
    921     it->Next();
    922     if (!CheckObjectStoreAndMetaDataType(
    923              it.get(),
    924              stop_key,
    925              object_store_id,
    926              ObjectStoreMetaDataKey::AUTO_INCREMENT)) {
    927       INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
    928       break;
    929     }
    930     bool auto_increment;
    931     {
    932       StringPiece slice(it->Value());
    933       if (!DecodeBool(&slice, &auto_increment) || !slice.empty())
    934         INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
    935     }
    936 
    937     it->Next();  // Is evicatble.
    938     if (!CheckObjectStoreAndMetaDataType(it.get(),
    939                                          stop_key,
    940                                          object_store_id,
    941                                          ObjectStoreMetaDataKey::EVICTABLE)) {
    942       INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
    943       break;
    944     }
    945 
    946     it->Next();  // Last version.
    947     if (!CheckObjectStoreAndMetaDataType(
    948              it.get(),
    949              stop_key,
    950              object_store_id,
    951              ObjectStoreMetaDataKey::LAST_VERSION)) {
    952       INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
    953       break;
    954     }
    955 
    956     it->Next();  // Maximum index id allocated.
    957     if (!CheckObjectStoreAndMetaDataType(
    958              it.get(),
    959              stop_key,
    960              object_store_id,
    961              ObjectStoreMetaDataKey::MAX_INDEX_ID)) {
    962       INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
    963       break;
    964     }
    965     int64 max_index_id;
    966     {
    967       StringPiece slice(it->Value());
    968       if (!DecodeInt(&slice, &max_index_id) || !slice.empty())
    969         INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
    970     }
    971 
    972     it->Next();  // [optional] has key path (is not null)
    973     if (CheckObjectStoreAndMetaDataType(it.get(),
    974                                         stop_key,
    975                                         object_store_id,
    976                                         ObjectStoreMetaDataKey::HAS_KEY_PATH)) {
    977       bool has_key_path;
    978       {
    979         StringPiece slice(it->Value());
    980         if (!DecodeBool(&slice, &has_key_path))
    981           INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
    982       }
    983       // This check accounts for two layers of legacy coding:
    984       // (1) Initially, has_key_path was added to distinguish null vs. string.
    985       // (2) Later, null vs. string vs. array was stored in the key_path itself.
    986       // So this check is only relevant for string-type key_paths.
    987       if (!has_key_path &&
    988           (key_path.type() == blink::WebIDBKeyPathTypeString &&
    989            !key_path.string().empty())) {
    990         INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
    991         break;
    992       }
    993       if (!has_key_path)
    994         key_path = IndexedDBKeyPath();
    995       it->Next();
    996     }
    997 
    998     int64 key_generator_current_number = -1;
    999     if (CheckObjectStoreAndMetaDataType(
   1000             it.get(),
   1001             stop_key,
   1002             object_store_id,
   1003             ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER)) {
   1004       StringPiece slice(it->Value());
   1005       if (!DecodeInt(&slice, &key_generator_current_number) || !slice.empty())
   1006         INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
   1007 
   1008       // TODO(jsbell): Return key_generator_current_number, cache in
   1009       // object store, and write lazily to backing store.  For now,
   1010       // just assert that if it was written it was valid.
   1011       DCHECK_GE(key_generator_current_number, kKeyGeneratorInitialNumber);
   1012       it->Next();
   1013     }
   1014 
   1015     IndexedDBObjectStoreMetadata metadata(object_store_name,
   1016                                           object_store_id,
   1017                                           key_path,
   1018                                           auto_increment,
   1019                                           max_index_id);
   1020     if (!GetIndexes(database_id, object_store_id, &metadata.indexes))
   1021       return false;
   1022     (*object_stores)[object_store_id] = metadata;
   1023   }
   1024   return true;
   1025 }
   1026 
   1027 WARN_UNUSED_RESULT static bool SetMaxObjectStoreId(
   1028     LevelDBTransaction* transaction,
   1029     int64 database_id,
   1030     int64 object_store_id) {
   1031   const std::string max_object_store_id_key = DatabaseMetaDataKey::Encode(
   1032       database_id, DatabaseMetaDataKey::MAX_OBJECT_STORE_ID);
   1033   int64 max_object_store_id = -1;
   1034   bool ok = GetMaxObjectStoreId(
   1035       transaction, max_object_store_id_key, &max_object_store_id);
   1036   if (!ok) {
   1037     INTERNAL_READ_ERROR(SET_MAX_OBJECT_STORE_ID);
   1038     return false;
   1039   }
   1040 
   1041   if (object_store_id <= max_object_store_id) {
   1042     INTERNAL_CONSISTENCY_ERROR(SET_MAX_OBJECT_STORE_ID);
   1043     return false;
   1044   }
   1045   PutInt(transaction, max_object_store_id_key, object_store_id);
   1046   return true;
   1047 }
   1048 
   1049 bool IndexedDBBackingStore::CreateObjectStore(
   1050     IndexedDBBackingStore::Transaction* transaction,
   1051     int64 database_id,
   1052     int64 object_store_id,
   1053     const base::string16& name,
   1054     const IndexedDBKeyPath& key_path,
   1055     bool auto_increment) {
   1056   IDB_TRACE("IndexedDBBackingStore::CreateObjectStore");
   1057   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   1058     return false;
   1059   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   1060   if (!SetMaxObjectStoreId(leveldb_transaction, database_id, object_store_id))
   1061     return false;
   1062 
   1063   const std::string name_key = ObjectStoreMetaDataKey::Encode(
   1064       database_id, object_store_id, ObjectStoreMetaDataKey::NAME);
   1065   const std::string key_path_key = ObjectStoreMetaDataKey::Encode(
   1066       database_id, object_store_id, ObjectStoreMetaDataKey::KEY_PATH);
   1067   const std::string auto_increment_key = ObjectStoreMetaDataKey::Encode(
   1068       database_id, object_store_id, ObjectStoreMetaDataKey::AUTO_INCREMENT);
   1069   const std::string evictable_key = ObjectStoreMetaDataKey::Encode(
   1070       database_id, object_store_id, ObjectStoreMetaDataKey::EVICTABLE);
   1071   const std::string last_version_key = ObjectStoreMetaDataKey::Encode(
   1072       database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION);
   1073   const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode(
   1074       database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID);
   1075   const std::string has_key_path_key = ObjectStoreMetaDataKey::Encode(
   1076       database_id, object_store_id, ObjectStoreMetaDataKey::HAS_KEY_PATH);
   1077   const std::string key_generator_current_number_key =
   1078       ObjectStoreMetaDataKey::Encode(
   1079           database_id,
   1080           object_store_id,
   1081           ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER);
   1082   const std::string names_key = ObjectStoreNamesKey::Encode(database_id, name);
   1083 
   1084   PutString(leveldb_transaction, name_key, name);
   1085   PutIDBKeyPath(leveldb_transaction, key_path_key, key_path);
   1086   PutInt(leveldb_transaction, auto_increment_key, auto_increment);
   1087   PutInt(leveldb_transaction, evictable_key, false);
   1088   PutInt(leveldb_transaction, last_version_key, 1);
   1089   PutInt(leveldb_transaction, max_index_id_key, kMinimumIndexId);
   1090   PutBool(leveldb_transaction, has_key_path_key, !key_path.IsNull());
   1091   PutInt(leveldb_transaction,
   1092          key_generator_current_number_key,
   1093          kKeyGeneratorInitialNumber);
   1094   PutInt(leveldb_transaction, names_key, object_store_id);
   1095   return true;
   1096 }
   1097 
   1098 bool IndexedDBBackingStore::DeleteObjectStore(
   1099     IndexedDBBackingStore::Transaction* transaction,
   1100     int64 database_id,
   1101     int64 object_store_id) {
   1102   IDB_TRACE("IndexedDBBackingStore::DeleteObjectStore");
   1103   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   1104     return false;
   1105   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   1106 
   1107   base::string16 object_store_name;
   1108   bool found = false;
   1109   bool ok = GetString(
   1110       leveldb_transaction,
   1111       ObjectStoreMetaDataKey::Encode(
   1112           database_id, object_store_id, ObjectStoreMetaDataKey::NAME),
   1113       &object_store_name,
   1114       &found);
   1115   if (!ok) {
   1116     INTERNAL_READ_ERROR(DELETE_OBJECT_STORE);
   1117     return false;
   1118   }
   1119   if (!found) {
   1120     INTERNAL_CONSISTENCY_ERROR(DELETE_OBJECT_STORE);
   1121     return false;
   1122   }
   1123 
   1124   DeleteRange(
   1125       leveldb_transaction,
   1126       ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0),
   1127       ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id));
   1128 
   1129   leveldb_transaction->Remove(
   1130       ObjectStoreNamesKey::Encode(database_id, object_store_name));
   1131 
   1132   DeleteRange(leveldb_transaction,
   1133               IndexFreeListKey::Encode(database_id, object_store_id, 0),
   1134               IndexFreeListKey::EncodeMaxKey(database_id, object_store_id));
   1135   DeleteRange(leveldb_transaction,
   1136               IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0),
   1137               IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id));
   1138 
   1139   return ClearObjectStore(transaction, database_id, object_store_id);
   1140 }
   1141 
   1142 bool IndexedDBBackingStore::GetRecord(
   1143     IndexedDBBackingStore::Transaction* transaction,
   1144     int64 database_id,
   1145     int64 object_store_id,
   1146     const IndexedDBKey& key,
   1147     std::string* record) {
   1148   IDB_TRACE("IndexedDBBackingStore::GetRecord");
   1149   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   1150     return false;
   1151   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   1152 
   1153   const std::string leveldb_key =
   1154       ObjectStoreDataKey::Encode(database_id, object_store_id, key);
   1155   std::string data;
   1156 
   1157   record->clear();
   1158 
   1159   bool found = false;
   1160   bool ok = leveldb_transaction->Get(leveldb_key, &data, &found);
   1161   if (!ok) {
   1162     INTERNAL_READ_ERROR(GET_RECORD);
   1163     return false;
   1164   }
   1165   if (!found)
   1166     return true;
   1167   if (data.empty()) {
   1168     INTERNAL_READ_ERROR(GET_RECORD);
   1169     return false;
   1170   }
   1171 
   1172   int64 version;
   1173   StringPiece slice(data);
   1174   if (!DecodeVarInt(&slice, &version)) {
   1175     INTERNAL_READ_ERROR(GET_RECORD);
   1176     return false;
   1177   }
   1178 
   1179   *record = slice.as_string();
   1180   return true;
   1181 }
   1182 
   1183 WARN_UNUSED_RESULT static bool GetNewVersionNumber(
   1184     LevelDBTransaction* transaction,
   1185     int64 database_id,
   1186     int64 object_store_id,
   1187     int64* new_version_number) {
   1188   const std::string last_version_key = ObjectStoreMetaDataKey::Encode(
   1189       database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION);
   1190 
   1191   *new_version_number = -1;
   1192   int64 last_version = -1;
   1193   bool found = false;
   1194   bool ok = GetInt(transaction, last_version_key, &last_version, &found);
   1195   if (!ok) {
   1196     INTERNAL_READ_ERROR(GET_NEW_VERSION_NUMBER);
   1197     return false;
   1198   }
   1199   if (!found)
   1200     last_version = 0;
   1201 
   1202   DCHECK_GE(last_version, 0);
   1203 
   1204   int64 version = last_version + 1;
   1205   PutInt(transaction, last_version_key, version);
   1206 
   1207   // TODO(jsbell): Think about how we want to handle the overflow scenario.
   1208   DCHECK(version > last_version);
   1209 
   1210   *new_version_number = version;
   1211   return true;
   1212 }
   1213 
   1214 bool IndexedDBBackingStore::PutRecord(
   1215     IndexedDBBackingStore::Transaction* transaction,
   1216     int64 database_id,
   1217     int64 object_store_id,
   1218     const IndexedDBKey& key,
   1219     const std::string& value,
   1220     RecordIdentifier* record_identifier) {
   1221   IDB_TRACE("IndexedDBBackingStore::PutRecord");
   1222   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   1223     return false;
   1224   DCHECK(key.IsValid());
   1225 
   1226   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   1227   int64 version = -1;
   1228   bool ok = GetNewVersionNumber(
   1229       leveldb_transaction, database_id, object_store_id, &version);
   1230   if (!ok)
   1231     return false;
   1232   DCHECK_GE(version, 0);
   1233   const std::string object_storedata_key =
   1234       ObjectStoreDataKey::Encode(database_id, object_store_id, key);
   1235 
   1236   std::string v;
   1237   EncodeVarInt(version, &v);
   1238   v.append(value);
   1239 
   1240   leveldb_transaction->Put(object_storedata_key, &v);
   1241 
   1242   const std::string exists_entry_key =
   1243       ExistsEntryKey::Encode(database_id, object_store_id, key);
   1244   std::string version_encoded;
   1245   EncodeInt(version, &version_encoded);
   1246   leveldb_transaction->Put(exists_entry_key, &version_encoded);
   1247 
   1248   std::string key_encoded;
   1249   EncodeIDBKey(key, &key_encoded);
   1250   record_identifier->Reset(key_encoded, version);
   1251   return true;
   1252 }
   1253 
   1254 bool IndexedDBBackingStore::ClearObjectStore(
   1255     IndexedDBBackingStore::Transaction* transaction,
   1256     int64 database_id,
   1257     int64 object_store_id) {
   1258   IDB_TRACE("IndexedDBBackingStore::ClearObjectStore");
   1259   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   1260     return false;
   1261   const std::string start_key =
   1262       KeyPrefix(database_id, object_store_id).Encode();
   1263   const std::string stop_key =
   1264       KeyPrefix(database_id, object_store_id + 1).Encode();
   1265 
   1266   DeleteRange(transaction->transaction(), start_key, stop_key);
   1267   return true;
   1268 }
   1269 
   1270 bool IndexedDBBackingStore::DeleteRecord(
   1271     IndexedDBBackingStore::Transaction* transaction,
   1272     int64 database_id,
   1273     int64 object_store_id,
   1274     const RecordIdentifier& record_identifier) {
   1275   IDB_TRACE("IndexedDBBackingStore::DeleteRecord");
   1276   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   1277     return false;
   1278   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   1279 
   1280   const std::string object_store_data_key = ObjectStoreDataKey::Encode(
   1281       database_id, object_store_id, record_identifier.primary_key());
   1282   leveldb_transaction->Remove(object_store_data_key);
   1283 
   1284   const std::string exists_entry_key = ExistsEntryKey::Encode(
   1285       database_id, object_store_id, record_identifier.primary_key());
   1286   leveldb_transaction->Remove(exists_entry_key);
   1287   return true;
   1288 }
   1289 
   1290 bool IndexedDBBackingStore::GetKeyGeneratorCurrentNumber(
   1291     IndexedDBBackingStore::Transaction* transaction,
   1292     int64 database_id,
   1293     int64 object_store_id,
   1294     int64* key_generator_current_number) {
   1295   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   1296     return false;
   1297   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   1298 
   1299   const std::string key_generator_current_number_key =
   1300       ObjectStoreMetaDataKey::Encode(
   1301           database_id,
   1302           object_store_id,
   1303           ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER);
   1304 
   1305   *key_generator_current_number = -1;
   1306   std::string data;
   1307 
   1308   bool found = false;
   1309   bool ok =
   1310       leveldb_transaction->Get(key_generator_current_number_key, &data, &found);
   1311   if (!ok) {
   1312     INTERNAL_READ_ERROR(GET_KEY_GENERATOR_CURRENT_NUMBER);
   1313     return false;
   1314   }
   1315   if (found && !data.empty()) {
   1316     StringPiece slice(data);
   1317     if (!DecodeInt(&slice, key_generator_current_number) || !slice.empty()) {
   1318       INTERNAL_READ_ERROR(GET_KEY_GENERATOR_CURRENT_NUMBER);
   1319       return false;
   1320     }
   1321     return true;
   1322   }
   1323 
   1324   // Previously, the key generator state was not stored explicitly
   1325   // but derived from the maximum numeric key present in existing
   1326   // data. This violates the spec as the data may be cleared but the
   1327   // key generator state must be preserved.
   1328   // TODO(jsbell): Fix this for all stores on database open?
   1329   const std::string start_key =
   1330       ObjectStoreDataKey::Encode(database_id, object_store_id, MinIDBKey());
   1331   const std::string stop_key =
   1332       ObjectStoreDataKey::Encode(database_id, object_store_id, MaxIDBKey());
   1333 
   1334   scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator();
   1335   int64 max_numeric_key = 0;
   1336 
   1337   for (it->Seek(start_key);
   1338        it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
   1339        it->Next()) {
   1340     StringPiece slice(it->Key());
   1341     ObjectStoreDataKey data_key;
   1342     if (!ObjectStoreDataKey::Decode(&slice, &data_key)) {
   1343       INTERNAL_READ_ERROR(GET_KEY_GENERATOR_CURRENT_NUMBER);
   1344       return false;
   1345     }
   1346     scoped_ptr<IndexedDBKey> user_key = data_key.user_key();
   1347     if (user_key->type() == blink::WebIDBKeyTypeNumber) {
   1348       int64 n = static_cast<int64>(user_key->number());
   1349       if (n > max_numeric_key)
   1350         max_numeric_key = n;
   1351     }
   1352   }
   1353 
   1354   *key_generator_current_number = max_numeric_key + 1;
   1355   return true;
   1356 }
   1357 
   1358 bool IndexedDBBackingStore::MaybeUpdateKeyGeneratorCurrentNumber(
   1359     IndexedDBBackingStore::Transaction* transaction,
   1360     int64 database_id,
   1361     int64 object_store_id,
   1362     int64 new_number,
   1363     bool check_current) {
   1364   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   1365     return false;
   1366 
   1367   if (check_current) {
   1368     int64 current_number;
   1369     bool ok = GetKeyGeneratorCurrentNumber(
   1370         transaction, database_id, object_store_id, &current_number);
   1371     if (!ok)
   1372       return false;
   1373     if (new_number <= current_number)
   1374       return true;
   1375   }
   1376 
   1377   const std::string key_generator_current_number_key =
   1378       ObjectStoreMetaDataKey::Encode(
   1379           database_id,
   1380           object_store_id,
   1381           ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER);
   1382   PutInt(
   1383       transaction->transaction(), key_generator_current_number_key, new_number);
   1384   return true;
   1385 }
   1386 
   1387 bool IndexedDBBackingStore::KeyExistsInObjectStore(
   1388     IndexedDBBackingStore::Transaction* transaction,
   1389     int64 database_id,
   1390     int64 object_store_id,
   1391     const IndexedDBKey& key,
   1392     RecordIdentifier* found_record_identifier,
   1393     bool* found) {
   1394   IDB_TRACE("IndexedDBBackingStore::KeyExistsInObjectStore");
   1395   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   1396     return false;
   1397   *found = false;
   1398   const std::string leveldb_key =
   1399       ObjectStoreDataKey::Encode(database_id, object_store_id, key);
   1400   std::string data;
   1401 
   1402   bool ok = transaction->transaction()->Get(leveldb_key, &data, found);
   1403   if (!ok) {
   1404     INTERNAL_READ_ERROR(KEY_EXISTS_IN_OBJECT_STORE);
   1405     return false;
   1406   }
   1407   if (!*found)
   1408     return true;
   1409   if (!data.size()) {
   1410     INTERNAL_READ_ERROR(KEY_EXISTS_IN_OBJECT_STORE);
   1411     return false;
   1412   }
   1413 
   1414   int64 version;
   1415   StringPiece slice(data);
   1416   if (!DecodeVarInt(&slice, &version))
   1417     return false;
   1418 
   1419   std::string encoded_key;
   1420   EncodeIDBKey(key, &encoded_key);
   1421   found_record_identifier->Reset(encoded_key, version);
   1422   return true;
   1423 }
   1424 
   1425 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it,
   1426                                      const std::string& stop_key,
   1427                                      int64 index_id,
   1428                                      unsigned char meta_data_type) {
   1429   if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0)
   1430     return false;
   1431 
   1432   StringPiece slice(it->Key());
   1433   IndexMetaDataKey meta_data_key;
   1434   bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key);
   1435   DCHECK(ok);
   1436   if (meta_data_key.IndexId() != index_id)
   1437     return false;
   1438   if (meta_data_key.meta_data_type() != meta_data_type)
   1439     return false;
   1440   return true;
   1441 }
   1442 
   1443 // TODO(jsbell): This should do some error handling rather than plowing ahead
   1444 // when bad data is encountered.
   1445 bool IndexedDBBackingStore::GetIndexes(
   1446     int64 database_id,
   1447     int64 object_store_id,
   1448     IndexedDBObjectStoreMetadata::IndexMap* indexes) {
   1449   IDB_TRACE("IndexedDBBackingStore::GetIndexes");
   1450   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   1451     return false;
   1452   const std::string start_key =
   1453       IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0);
   1454   const std::string stop_key =
   1455       IndexMetaDataKey::Encode(database_id, object_store_id + 1, 0, 0);
   1456 
   1457   DCHECK(indexes->empty());
   1458 
   1459   scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
   1460   it->Seek(start_key);
   1461   while (it->IsValid() && CompareKeys(it->Key(), stop_key) < 0) {
   1462     StringPiece slice(it->Key());
   1463     IndexMetaDataKey meta_data_key;
   1464     bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key);
   1465     DCHECK(ok);
   1466     if (meta_data_key.meta_data_type() != IndexMetaDataKey::NAME) {
   1467       INTERNAL_CONSISTENCY_ERROR(GET_INDEXES);
   1468       // Possible stale metadata due to http://webkit.org/b/85557 but don't fail
   1469       // the load.
   1470       it->Next();
   1471       continue;
   1472     }
   1473 
   1474     // TODO(jsbell): Do this by direct key lookup rather than iteration, to
   1475     // simplify.
   1476     int64 index_id = meta_data_key.IndexId();
   1477     base::string16 index_name;
   1478     {
   1479       StringPiece slice(it->Value());
   1480       if (!DecodeString(&slice, &index_name) || !slice.empty())
   1481         INTERNAL_CONSISTENCY_ERROR(GET_INDEXES);
   1482     }
   1483 
   1484     it->Next();  // unique flag
   1485     if (!CheckIndexAndMetaDataKey(
   1486              it.get(), stop_key, index_id, IndexMetaDataKey::UNIQUE)) {
   1487       INTERNAL_CONSISTENCY_ERROR(GET_INDEXES);
   1488       break;
   1489     }
   1490     bool index_unique;
   1491     {
   1492       StringPiece slice(it->Value());
   1493       if (!DecodeBool(&slice, &index_unique) || !slice.empty())
   1494         INTERNAL_CONSISTENCY_ERROR(GET_INDEXES);
   1495     }
   1496 
   1497     it->Next();  // key_path
   1498     if (!CheckIndexAndMetaDataKey(
   1499              it.get(), stop_key, index_id, IndexMetaDataKey::KEY_PATH)) {
   1500       INTERNAL_CONSISTENCY_ERROR(GET_INDEXES);
   1501       break;
   1502     }
   1503     IndexedDBKeyPath key_path;
   1504     {
   1505       StringPiece slice(it->Value());
   1506       if (!DecodeIDBKeyPath(&slice, &key_path) || !slice.empty())
   1507         INTERNAL_CONSISTENCY_ERROR(GET_INDEXES);
   1508     }
   1509 
   1510     it->Next();  // [optional] multi_entry flag
   1511     bool index_multi_entry = false;
   1512     if (CheckIndexAndMetaDataKey(
   1513             it.get(), stop_key, index_id, IndexMetaDataKey::MULTI_ENTRY)) {
   1514       StringPiece slice(it->Value());
   1515       if (!DecodeBool(&slice, &index_multi_entry) || !slice.empty())
   1516         INTERNAL_CONSISTENCY_ERROR(GET_INDEXES);
   1517 
   1518       it->Next();
   1519     }
   1520 
   1521     (*indexes)[index_id] = IndexedDBIndexMetadata(
   1522         index_name, index_id, key_path, index_unique, index_multi_entry);
   1523   }
   1524   return true;
   1525 }
   1526 
   1527 WARN_UNUSED_RESULT static bool SetMaxIndexId(LevelDBTransaction* transaction,
   1528                                              int64 database_id,
   1529                                              int64 object_store_id,
   1530                                              int64 index_id) {
   1531   int64 max_index_id = -1;
   1532   const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode(
   1533       database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID);
   1534   bool found = false;
   1535   bool ok = GetInt(transaction, max_index_id_key, &max_index_id, &found);
   1536   if (!ok) {
   1537     INTERNAL_READ_ERROR(SET_MAX_INDEX_ID);
   1538     return false;
   1539   }
   1540   if (!found)
   1541     max_index_id = kMinimumIndexId;
   1542 
   1543   if (index_id <= max_index_id) {
   1544     INTERNAL_CONSISTENCY_ERROR(SET_MAX_INDEX_ID);
   1545     return false;
   1546   }
   1547 
   1548   PutInt(transaction, max_index_id_key, index_id);
   1549   return true;
   1550 }
   1551 
   1552 bool IndexedDBBackingStore::CreateIndex(
   1553     IndexedDBBackingStore::Transaction* transaction,
   1554     int64 database_id,
   1555     int64 object_store_id,
   1556     int64 index_id,
   1557     const base::string16& name,
   1558     const IndexedDBKeyPath& key_path,
   1559     bool is_unique,
   1560     bool is_multi_entry) {
   1561   IDB_TRACE("IndexedDBBackingStore::CreateIndex");
   1562   if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
   1563     return false;
   1564   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   1565   if (!SetMaxIndexId(
   1566            leveldb_transaction, database_id, object_store_id, index_id))
   1567     return false;
   1568 
   1569   const std::string name_key = IndexMetaDataKey::Encode(
   1570       database_id, object_store_id, index_id, IndexMetaDataKey::NAME);
   1571   const std::string unique_key = IndexMetaDataKey::Encode(
   1572       database_id, object_store_id, index_id, IndexMetaDataKey::UNIQUE);
   1573   const std::string key_path_key = IndexMetaDataKey::Encode(
   1574       database_id, object_store_id, index_id, IndexMetaDataKey::KEY_PATH);
   1575   const std::string multi_entry_key = IndexMetaDataKey::Encode(
   1576       database_id, object_store_id, index_id, IndexMetaDataKey::MULTI_ENTRY);
   1577 
   1578   PutString(leveldb_transaction, name_key, name);
   1579   PutBool(leveldb_transaction, unique_key, is_unique);
   1580   PutIDBKeyPath(leveldb_transaction, key_path_key, key_path);
   1581   PutBool(leveldb_transaction, multi_entry_key, is_multi_entry);
   1582   return true;
   1583 }
   1584 
   1585 bool IndexedDBBackingStore::DeleteIndex(
   1586     IndexedDBBackingStore::Transaction* transaction,
   1587     int64 database_id,
   1588     int64 object_store_id,
   1589     int64 index_id) {
   1590   IDB_TRACE("IndexedDBBackingStore::DeleteIndex");
   1591   if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
   1592     return false;
   1593   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   1594 
   1595   const std::string index_meta_data_start =
   1596       IndexMetaDataKey::Encode(database_id, object_store_id, index_id, 0);
   1597   const std::string index_meta_data_end =
   1598       IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
   1599   DeleteRange(leveldb_transaction, index_meta_data_start, index_meta_data_end);
   1600 
   1601   const std::string index_data_start =
   1602       IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id);
   1603   const std::string index_data_end =
   1604       IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
   1605   DeleteRange(leveldb_transaction, index_data_start, index_data_end);
   1606   return true;
   1607 }
   1608 
   1609 bool IndexedDBBackingStore::PutIndexDataForRecord(
   1610     IndexedDBBackingStore::Transaction* transaction,
   1611     int64 database_id,
   1612     int64 object_store_id,
   1613     int64 index_id,
   1614     const IndexedDBKey& key,
   1615     const RecordIdentifier& record_identifier) {
   1616   IDB_TRACE("IndexedDBBackingStore::PutIndexDataForRecord");
   1617   DCHECK(key.IsValid());
   1618   if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
   1619     return false;
   1620 
   1621   std::string encoded_key;
   1622   EncodeIDBKey(key, &encoded_key);
   1623 
   1624   const std::string index_data_key =
   1625       IndexDataKey::Encode(database_id,
   1626                            object_store_id,
   1627                            index_id,
   1628                            encoded_key,
   1629                            record_identifier.primary_key(),
   1630                            0);
   1631 
   1632   std::string data;
   1633   EncodeVarInt(record_identifier.version(), &data);
   1634   data.append(record_identifier.primary_key());
   1635 
   1636   transaction->transaction()->Put(index_data_key, &data);
   1637   return true;
   1638 }
   1639 
   1640 static bool FindGreatestKeyLessThanOrEqual(LevelDBTransaction* transaction,
   1641                                            const std::string& target,
   1642                                            std::string* found_key) {
   1643   scoped_ptr<LevelDBIterator> it = transaction->CreateIterator();
   1644   it->Seek(target);
   1645 
   1646   if (!it->IsValid()) {
   1647     it->SeekToLast();
   1648     if (!it->IsValid())
   1649       return false;
   1650   }
   1651 
   1652   while (CompareIndexKeys(it->Key(), target) > 0) {
   1653     it->Prev();
   1654     if (!it->IsValid())
   1655       return false;
   1656   }
   1657 
   1658   do {
   1659     *found_key = it->Key().as_string();
   1660 
   1661     // There can be several index keys that compare equal. We want the last one.
   1662     it->Next();
   1663   } while (it->IsValid() && !CompareIndexKeys(it->Key(), target));
   1664 
   1665   return true;
   1666 }
   1667 
   1668 static bool VersionExists(LevelDBTransaction* transaction,
   1669                           int64 database_id,
   1670                           int64 object_store_id,
   1671                           int64 version,
   1672                           const std::string& encoded_primary_key,
   1673                           bool* exists) {
   1674   const std::string key =
   1675       ExistsEntryKey::Encode(database_id, object_store_id, encoded_primary_key);
   1676   std::string data;
   1677 
   1678   bool ok = transaction->Get(key, &data, exists);
   1679   if (!ok) {
   1680     INTERNAL_READ_ERROR(VERSION_EXISTS);
   1681     return false;
   1682   }
   1683   if (!*exists)
   1684     return true;
   1685 
   1686   StringPiece slice(data);
   1687   int64 decoded;
   1688   if (!DecodeInt(&slice, &decoded) || !slice.empty())
   1689     return false;
   1690   *exists = (decoded == version);
   1691   return true;
   1692 }
   1693 
   1694 bool IndexedDBBackingStore::FindKeyInIndex(
   1695     IndexedDBBackingStore::Transaction* transaction,
   1696     int64 database_id,
   1697     int64 object_store_id,
   1698     int64 index_id,
   1699     const IndexedDBKey& key,
   1700     std::string* found_encoded_primary_key,
   1701     bool* found) {
   1702   IDB_TRACE("IndexedDBBackingStore::FindKeyInIndex");
   1703   DCHECK(KeyPrefix::ValidIds(database_id, object_store_id, index_id));
   1704 
   1705   DCHECK(found_encoded_primary_key->empty());
   1706   *found = false;
   1707 
   1708   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   1709   const std::string leveldb_key =
   1710       IndexDataKey::Encode(database_id, object_store_id, index_id, key);
   1711   scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator();
   1712   it->Seek(leveldb_key);
   1713 
   1714   for (;;) {
   1715     if (!it->IsValid())
   1716       return true;
   1717     if (CompareIndexKeys(it->Key(), leveldb_key) > 0)
   1718       return true;
   1719 
   1720     StringPiece slice(it->Value());
   1721 
   1722     int64 version;
   1723     if (!DecodeVarInt(&slice, &version)) {
   1724       INTERNAL_READ_ERROR(FIND_KEY_IN_INDEX);
   1725       return false;
   1726     }
   1727     *found_encoded_primary_key = slice.as_string();
   1728 
   1729     bool exists = false;
   1730     bool ok = VersionExists(leveldb_transaction,
   1731                             database_id,
   1732                             object_store_id,
   1733                             version,
   1734                             *found_encoded_primary_key,
   1735                             &exists);
   1736     if (!ok)
   1737       return false;
   1738     if (!exists) {
   1739       // Delete stale index data entry and continue.
   1740       leveldb_transaction->Remove(it->Key());
   1741       it->Next();
   1742       continue;
   1743     }
   1744     *found = true;
   1745     return true;
   1746   }
   1747 }
   1748 
   1749 bool IndexedDBBackingStore::GetPrimaryKeyViaIndex(
   1750     IndexedDBBackingStore::Transaction* transaction,
   1751     int64 database_id,
   1752     int64 object_store_id,
   1753     int64 index_id,
   1754     const IndexedDBKey& key,
   1755     scoped_ptr<IndexedDBKey>* primary_key) {
   1756   IDB_TRACE("IndexedDBBackingStore::GetPrimaryKeyViaIndex");
   1757   if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
   1758     return false;
   1759 
   1760   bool found = false;
   1761   std::string found_encoded_primary_key;
   1762   bool ok = FindKeyInIndex(transaction,
   1763                            database_id,
   1764                            object_store_id,
   1765                            index_id,
   1766                            key,
   1767                            &found_encoded_primary_key,
   1768                            &found);
   1769   if (!ok) {
   1770     INTERNAL_READ_ERROR(GET_PRIMARY_KEY_VIA_INDEX);
   1771     return false;
   1772   }
   1773   if (!found)
   1774     return true;
   1775   if (!found_encoded_primary_key.size()) {
   1776     INTERNAL_READ_ERROR(GET_PRIMARY_KEY_VIA_INDEX);
   1777     return false;
   1778   }
   1779 
   1780   StringPiece slice(found_encoded_primary_key);
   1781   return DecodeIDBKey(&slice, primary_key) && slice.empty();
   1782 }
   1783 
   1784 bool IndexedDBBackingStore::KeyExistsInIndex(
   1785     IndexedDBBackingStore::Transaction* transaction,
   1786     int64 database_id,
   1787     int64 object_store_id,
   1788     int64 index_id,
   1789     const IndexedDBKey& index_key,
   1790     scoped_ptr<IndexedDBKey>* found_primary_key,
   1791     bool* exists) {
   1792   IDB_TRACE("IndexedDBBackingStore::KeyExistsInIndex");
   1793   if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
   1794     return false;
   1795 
   1796   *exists = false;
   1797   std::string found_encoded_primary_key;
   1798   bool ok = FindKeyInIndex(transaction,
   1799                            database_id,
   1800                            object_store_id,
   1801                            index_id,
   1802                            index_key,
   1803                            &found_encoded_primary_key,
   1804                            exists);
   1805   if (!ok) {
   1806     INTERNAL_READ_ERROR(KEY_EXISTS_IN_INDEX);
   1807     return false;
   1808   }
   1809   if (!*exists)
   1810     return true;
   1811   if (found_encoded_primary_key.empty()) {
   1812     INTERNAL_READ_ERROR(KEY_EXISTS_IN_INDEX);
   1813     return false;
   1814   }
   1815 
   1816   StringPiece slice(found_encoded_primary_key);
   1817   return DecodeIDBKey(&slice, found_primary_key) && slice.empty();
   1818 }
   1819 
   1820 IndexedDBBackingStore::Cursor::Cursor(
   1821     const IndexedDBBackingStore::Cursor* other)
   1822     : transaction_(other->transaction_),
   1823       cursor_options_(other->cursor_options_),
   1824       current_key_(new IndexedDBKey(*other->current_key_)) {
   1825   if (other->iterator_) {
   1826     iterator_ = transaction_->CreateIterator();
   1827 
   1828     if (other->iterator_->IsValid()) {
   1829       iterator_->Seek(other->iterator_->Key());
   1830       DCHECK(iterator_->IsValid());
   1831     }
   1832   }
   1833 }
   1834 
   1835 IndexedDBBackingStore::Cursor::Cursor(LevelDBTransaction* transaction,
   1836                                       const CursorOptions& cursor_options)
   1837     : transaction_(transaction), cursor_options_(cursor_options) {}
   1838 IndexedDBBackingStore::Cursor::~Cursor() {}
   1839 
   1840 bool IndexedDBBackingStore::Cursor::FirstSeek() {
   1841   iterator_ = transaction_->CreateIterator();
   1842   if (cursor_options_.forward)
   1843     iterator_->Seek(cursor_options_.low_key);
   1844   else
   1845     iterator_->Seek(cursor_options_.high_key);
   1846 
   1847   return Continue(0, READY);
   1848 }
   1849 
   1850 bool IndexedDBBackingStore::Cursor::Advance(uint32 count) {
   1851   while (count--) {
   1852     if (!Continue())
   1853       return false;
   1854   }
   1855   return true;
   1856 }
   1857 
   1858 bool IndexedDBBackingStore::Cursor::Continue(const IndexedDBKey* key,
   1859                                              const IndexedDBKey* primary_key,
   1860                                              IteratorState next_state) {
   1861   DCHECK(!key || key->IsValid());
   1862   DCHECK(!primary_key || primary_key->IsValid());
   1863 
   1864   // TODO(alecflett): avoid a copy here?
   1865   IndexedDBKey previous_key = current_key_ ? *current_key_ : IndexedDBKey();
   1866 
   1867   bool first_iteration = true;
   1868 
   1869   // When iterating with PrevNoDuplicate, spec requires that the
   1870   // value we yield for each key is the first duplicate in forwards
   1871   // order.
   1872   IndexedDBKey last_duplicate_key;
   1873 
   1874   bool forward = cursor_options_.forward;
   1875 
   1876   for (;;) {
   1877     if (next_state == SEEK) {
   1878       // TODO(jsbell): Optimize seeking for reverse cursors as well.
   1879       if (first_iteration && key && forward) {
   1880         std::string leveldb_key;
   1881         if (primary_key) {
   1882           leveldb_key = EncodeKey(*key, *primary_key);
   1883         } else {
   1884           leveldb_key = EncodeKey(*key);
   1885         }
   1886         iterator_->Seek(leveldb_key);
   1887         first_iteration = false;
   1888       } else if (forward) {
   1889         iterator_->Next();
   1890       } else {
   1891         iterator_->Prev();
   1892       }
   1893     } else {
   1894       next_state = SEEK;  // for subsequent iterations
   1895     }
   1896 
   1897     if (!iterator_->IsValid()) {
   1898       if (!forward && last_duplicate_key.IsValid()) {
   1899         // We need to walk forward because we hit the end of
   1900         // the data.
   1901         forward = true;
   1902         continue;
   1903       }
   1904 
   1905       return false;
   1906     }
   1907 
   1908     if (IsPastBounds()) {
   1909       if (!forward && last_duplicate_key.IsValid()) {
   1910         // We need to walk forward because now we're beyond the
   1911         // bounds defined by the cursor.
   1912         forward = true;
   1913         continue;
   1914       }
   1915 
   1916       return false;
   1917     }
   1918 
   1919     if (!HaveEnteredRange())
   1920       continue;
   1921 
   1922     // The row may not load because there's a stale entry in the
   1923     // index. This is not fatal.
   1924     if (!LoadCurrentRow())
   1925       continue;
   1926 
   1927     if (key) {
   1928       if (forward) {
   1929         if (primary_key && current_key_->IsEqual(*key) &&
   1930             this->primary_key().IsLessThan(*primary_key))
   1931           continue;
   1932         if (current_key_->IsLessThan(*key))
   1933           continue;
   1934       } else {
   1935         if (primary_key && key->IsEqual(*current_key_) &&
   1936             primary_key->IsLessThan(this->primary_key()))
   1937           continue;
   1938         if (key->IsLessThan(*current_key_))
   1939           continue;
   1940       }
   1941     }
   1942 
   1943     if (cursor_options_.unique) {
   1944       if (previous_key.IsValid() && current_key_->IsEqual(previous_key)) {
   1945         // We should never be able to walk forward all the way
   1946         // to the previous key.
   1947         DCHECK(!last_duplicate_key.IsValid());
   1948         continue;
   1949       }
   1950 
   1951       if (!forward) {
   1952         if (!last_duplicate_key.IsValid()) {
   1953           last_duplicate_key = *current_key_;
   1954           continue;
   1955         }
   1956 
   1957         // We need to walk forward because we hit the boundary
   1958         // between key ranges.
   1959         if (!last_duplicate_key.IsEqual(*current_key_)) {
   1960           forward = true;
   1961           continue;
   1962         }
   1963 
   1964         continue;
   1965       }
   1966     }
   1967     break;
   1968   }
   1969 
   1970   DCHECK(!last_duplicate_key.IsValid() ||
   1971          (forward && last_duplicate_key.IsEqual(*current_key_)));
   1972   return true;
   1973 }
   1974 
   1975 bool IndexedDBBackingStore::Cursor::HaveEnteredRange() const {
   1976   if (cursor_options_.forward) {
   1977     int compare = CompareIndexKeys(iterator_->Key(), cursor_options_.low_key);
   1978     if (cursor_options_.low_open) {
   1979       return compare > 0;
   1980     }
   1981     return compare >= 0;
   1982   }
   1983   int compare = CompareIndexKeys(iterator_->Key(), cursor_options_.high_key);
   1984   if (cursor_options_.high_open) {
   1985     return compare < 0;
   1986   }
   1987   return compare <= 0;
   1988 }
   1989 
   1990 bool IndexedDBBackingStore::Cursor::IsPastBounds() const {
   1991   if (cursor_options_.forward) {
   1992     int compare = CompareIndexKeys(iterator_->Key(), cursor_options_.high_key);
   1993     if (cursor_options_.high_open) {
   1994       return compare >= 0;
   1995     }
   1996     return compare > 0;
   1997   }
   1998   int compare = CompareIndexKeys(iterator_->Key(), cursor_options_.low_key);
   1999   if (cursor_options_.low_open) {
   2000     return compare <= 0;
   2001   }
   2002   return compare < 0;
   2003 }
   2004 
   2005 const IndexedDBKey& IndexedDBBackingStore::Cursor::primary_key() const {
   2006   return *current_key_;
   2007 }
   2008 
   2009 const IndexedDBBackingStore::RecordIdentifier&
   2010 IndexedDBBackingStore::Cursor::record_identifier() const {
   2011   return record_identifier_;
   2012 }
   2013 
   2014 class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor {
   2015  public:
   2016   ObjectStoreKeyCursorImpl(
   2017       LevelDBTransaction* transaction,
   2018       const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
   2019       : IndexedDBBackingStore::Cursor(transaction, cursor_options) {}
   2020 
   2021   virtual Cursor* Clone() OVERRIDE {
   2022     return new ObjectStoreKeyCursorImpl(this);
   2023   }
   2024 
   2025   // IndexedDBBackingStore::Cursor
   2026   virtual std::string* value() OVERRIDE {
   2027     NOTREACHED();
   2028     return NULL;
   2029   }
   2030   virtual bool LoadCurrentRow() OVERRIDE;
   2031 
   2032  protected:
   2033   virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
   2034     return ObjectStoreDataKey::Encode(
   2035         cursor_options_.database_id, cursor_options_.object_store_id, key);
   2036   }
   2037   virtual std::string EncodeKey(const IndexedDBKey& key,
   2038                                 const IndexedDBKey& primary_key) OVERRIDE {
   2039     NOTREACHED();
   2040     return std::string();
   2041   }
   2042 
   2043  private:
   2044   explicit ObjectStoreKeyCursorImpl(const ObjectStoreKeyCursorImpl* other)
   2045       : IndexedDBBackingStore::Cursor(other) {}
   2046 };
   2047 
   2048 bool ObjectStoreKeyCursorImpl::LoadCurrentRow() {
   2049   StringPiece slice(iterator_->Key());
   2050   ObjectStoreDataKey object_store_data_key;
   2051   if (!ObjectStoreDataKey::Decode(&slice, &object_store_data_key)) {
   2052     INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
   2053     return false;
   2054   }
   2055 
   2056   current_key_ = object_store_data_key.user_key();
   2057 
   2058   int64 version;
   2059   slice = StringPiece(iterator_->Value());
   2060   if (!DecodeVarInt(&slice, &version)) {
   2061     INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
   2062     return false;
   2063   }
   2064 
   2065   // TODO(jsbell): This re-encodes what was just decoded; try and optimize.
   2066   std::string encoded_key;
   2067   EncodeIDBKey(*current_key_, &encoded_key);
   2068   record_identifier_.Reset(encoded_key, version);
   2069 
   2070   return true;
   2071 }
   2072 
   2073 class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor {
   2074  public:
   2075   ObjectStoreCursorImpl(
   2076       LevelDBTransaction* transaction,
   2077       const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
   2078       : IndexedDBBackingStore::Cursor(transaction, cursor_options) {}
   2079 
   2080   virtual Cursor* Clone() OVERRIDE { return new ObjectStoreCursorImpl(this); }
   2081 
   2082   // IndexedDBBackingStore::Cursor
   2083   virtual std::string* value() OVERRIDE { return &current_value_; }
   2084   virtual bool LoadCurrentRow() OVERRIDE;
   2085 
   2086  protected:
   2087   virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
   2088     return ObjectStoreDataKey::Encode(
   2089         cursor_options_.database_id, cursor_options_.object_store_id, key);
   2090   }
   2091   virtual std::string EncodeKey(const IndexedDBKey& key,
   2092                                 const IndexedDBKey& primary_key) OVERRIDE {
   2093     NOTREACHED();
   2094     return std::string();
   2095   }
   2096 
   2097  private:
   2098   explicit ObjectStoreCursorImpl(const ObjectStoreCursorImpl* other)
   2099       : IndexedDBBackingStore::Cursor(other),
   2100         current_value_(other->current_value_) {}
   2101 
   2102   std::string current_value_;
   2103 };
   2104 
   2105 bool ObjectStoreCursorImpl::LoadCurrentRow() {
   2106   StringPiece slice(iterator_->Key());
   2107   ObjectStoreDataKey object_store_data_key;
   2108   if (!ObjectStoreDataKey::Decode(&slice, &object_store_data_key)) {
   2109     INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
   2110     return false;
   2111   }
   2112 
   2113   current_key_ = object_store_data_key.user_key();
   2114 
   2115   int64 version;
   2116   slice = StringPiece(iterator_->Value());
   2117   if (!DecodeVarInt(&slice, &version)) {
   2118     INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
   2119     return false;
   2120   }
   2121 
   2122   // TODO(jsbell): This re-encodes what was just decoded; try and optimize.
   2123   std::string encoded_key;
   2124   EncodeIDBKey(*current_key_, &encoded_key);
   2125   record_identifier_.Reset(encoded_key, version);
   2126 
   2127   current_value_ = slice.as_string();
   2128   return true;
   2129 }
   2130 
   2131 class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor {
   2132  public:
   2133   IndexKeyCursorImpl(
   2134       LevelDBTransaction* transaction,
   2135       const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
   2136       : IndexedDBBackingStore::Cursor(transaction, cursor_options) {}
   2137 
   2138   virtual Cursor* Clone() OVERRIDE { return new IndexKeyCursorImpl(this); }
   2139 
   2140   // IndexedDBBackingStore::Cursor
   2141   virtual std::string* value() OVERRIDE {
   2142     NOTREACHED();
   2143     return NULL;
   2144   }
   2145   virtual const IndexedDBKey& primary_key() const OVERRIDE {
   2146     return *primary_key_;
   2147   }
   2148   virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier()
   2149       const OVERRIDE {
   2150     NOTREACHED();
   2151     return record_identifier_;
   2152   }
   2153   virtual bool LoadCurrentRow() OVERRIDE;
   2154 
   2155  protected:
   2156   virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
   2157     return IndexDataKey::Encode(cursor_options_.database_id,
   2158                                 cursor_options_.object_store_id,
   2159                                 cursor_options_.index_id,
   2160                                 key);
   2161   }
   2162   virtual std::string EncodeKey(const IndexedDBKey& key,
   2163                                 const IndexedDBKey& primary_key) OVERRIDE {
   2164     return IndexDataKey::Encode(cursor_options_.database_id,
   2165                                 cursor_options_.object_store_id,
   2166                                 cursor_options_.index_id,
   2167                                 key,
   2168                                 primary_key);
   2169   }
   2170 
   2171  private:
   2172   explicit IndexKeyCursorImpl(const IndexKeyCursorImpl* other)
   2173       : IndexedDBBackingStore::Cursor(other),
   2174         primary_key_(new IndexedDBKey(*other->primary_key_)) {}
   2175 
   2176   scoped_ptr<IndexedDBKey> primary_key_;
   2177 };
   2178 
   2179 bool IndexKeyCursorImpl::LoadCurrentRow() {
   2180   StringPiece slice(iterator_->Key());
   2181   IndexDataKey index_data_key;
   2182   if (!IndexDataKey::Decode(&slice, &index_data_key)) {
   2183     INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
   2184     return false;
   2185   }
   2186 
   2187   current_key_ = index_data_key.user_key();
   2188   DCHECK(current_key_);
   2189 
   2190   slice = StringPiece(iterator_->Value());
   2191   int64 index_data_version;
   2192   if (!DecodeVarInt(&slice, &index_data_version)) {
   2193     INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
   2194     return false;
   2195   }
   2196 
   2197   if (!DecodeIDBKey(&slice, &primary_key_) || !slice.empty()) {
   2198     INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
   2199     return false;
   2200   }
   2201 
   2202   std::string primary_leveldb_key =
   2203       ObjectStoreDataKey::Encode(index_data_key.DatabaseId(),
   2204                                  index_data_key.ObjectStoreId(),
   2205                                  *primary_key_);
   2206 
   2207   std::string result;
   2208   bool found = false;
   2209   bool ok = transaction_->Get(primary_leveldb_key, &result, &found);
   2210   if (!ok) {
   2211     INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
   2212     return false;
   2213   }
   2214   if (!found) {
   2215     transaction_->Remove(iterator_->Key());
   2216     return false;
   2217   }
   2218   if (!result.size()) {
   2219     INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
   2220     return false;
   2221   }
   2222 
   2223   int64 object_store_data_version;
   2224   slice = StringPiece(result);
   2225   if (!DecodeVarInt(&slice, &object_store_data_version)) {
   2226     INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
   2227     return false;
   2228   }
   2229 
   2230   if (object_store_data_version != index_data_version) {
   2231     transaction_->Remove(iterator_->Key());
   2232     return false;
   2233   }
   2234 
   2235   return true;
   2236 }
   2237 
   2238 class IndexCursorImpl : public IndexedDBBackingStore::Cursor {
   2239  public:
   2240   IndexCursorImpl(
   2241       LevelDBTransaction* transaction,
   2242       const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
   2243       : IndexedDBBackingStore::Cursor(transaction, cursor_options) {}
   2244 
   2245   virtual Cursor* Clone() OVERRIDE { return new IndexCursorImpl(this); }
   2246 
   2247   // IndexedDBBackingStore::Cursor
   2248   virtual std::string* value() OVERRIDE { return &current_value_; }
   2249   virtual const IndexedDBKey& primary_key() const OVERRIDE {
   2250     return *primary_key_;
   2251   }
   2252   virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier()
   2253       const OVERRIDE {
   2254     NOTREACHED();
   2255     return record_identifier_;
   2256   }
   2257   virtual bool LoadCurrentRow() OVERRIDE;
   2258 
   2259  protected:
   2260   virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
   2261     return IndexDataKey::Encode(cursor_options_.database_id,
   2262                                 cursor_options_.object_store_id,
   2263                                 cursor_options_.index_id,
   2264                                 key);
   2265   }
   2266   virtual std::string EncodeKey(const IndexedDBKey& key,
   2267                                 const IndexedDBKey& primary_key) OVERRIDE {
   2268     return IndexDataKey::Encode(cursor_options_.database_id,
   2269                                 cursor_options_.object_store_id,
   2270                                 cursor_options_.index_id,
   2271                                 key,
   2272                                 primary_key);
   2273   }
   2274 
   2275  private:
   2276   explicit IndexCursorImpl(const IndexCursorImpl* other)
   2277       : IndexedDBBackingStore::Cursor(other),
   2278         primary_key_(new IndexedDBKey(*other->primary_key_)),
   2279         current_value_(other->current_value_),
   2280         primary_leveldb_key_(other->primary_leveldb_key_) {}
   2281 
   2282   scoped_ptr<IndexedDBKey> primary_key_;
   2283   std::string current_value_;
   2284   std::string primary_leveldb_key_;
   2285 };
   2286 
   2287 bool IndexCursorImpl::LoadCurrentRow() {
   2288   StringPiece slice(iterator_->Key());
   2289   IndexDataKey index_data_key;
   2290   if (!IndexDataKey::Decode(&slice, &index_data_key)) {
   2291     INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
   2292     return false;
   2293   }
   2294 
   2295   current_key_ = index_data_key.user_key();
   2296   DCHECK(current_key_);
   2297 
   2298   slice = StringPiece(iterator_->Value());
   2299   int64 index_data_version;
   2300   if (!DecodeVarInt(&slice, &index_data_version)) {
   2301     INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
   2302     return false;
   2303   }
   2304   if (!DecodeIDBKey(&slice, &primary_key_)) {
   2305     INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
   2306     return false;
   2307   }
   2308 
   2309   primary_leveldb_key_ =
   2310       ObjectStoreDataKey::Encode(index_data_key.DatabaseId(),
   2311                                  index_data_key.ObjectStoreId(),
   2312                                  *primary_key_);
   2313 
   2314   std::string result;
   2315   bool found = false;
   2316   bool ok = transaction_->Get(primary_leveldb_key_, &result, &found);
   2317   if (!ok) {
   2318     INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
   2319     return false;
   2320   }
   2321   if (!found) {
   2322     transaction_->Remove(iterator_->Key());
   2323     return false;
   2324   }
   2325   if (!result.size()) {
   2326     INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
   2327     return false;
   2328   }
   2329 
   2330   int64 object_store_data_version;
   2331   slice = StringPiece(result);
   2332   if (!DecodeVarInt(&slice, &object_store_data_version)) {
   2333     INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
   2334     return false;
   2335   }
   2336 
   2337   if (object_store_data_version != index_data_version) {
   2338     transaction_->Remove(iterator_->Key());
   2339     return false;
   2340   }
   2341 
   2342   current_value_ = slice.as_string();
   2343   return true;
   2344 }
   2345 
   2346 bool ObjectStoreCursorOptions(
   2347     LevelDBTransaction* transaction,
   2348     int64 database_id,
   2349     int64 object_store_id,
   2350     const IndexedDBKeyRange& range,
   2351     indexed_db::CursorDirection direction,
   2352     IndexedDBBackingStore::Cursor::CursorOptions* cursor_options) {
   2353   cursor_options->database_id = database_id;
   2354   cursor_options->object_store_id = object_store_id;
   2355 
   2356   bool lower_bound = range.lower().IsValid();
   2357   bool upper_bound = range.upper().IsValid();
   2358   cursor_options->forward =
   2359       (direction == indexed_db::CURSOR_NEXT_NO_DUPLICATE ||
   2360        direction == indexed_db::CURSOR_NEXT);
   2361   cursor_options->unique = (direction == indexed_db::CURSOR_NEXT_NO_DUPLICATE ||
   2362                             direction == indexed_db::CURSOR_PREV_NO_DUPLICATE);
   2363 
   2364   if (!lower_bound) {
   2365     cursor_options->low_key =
   2366         ObjectStoreDataKey::Encode(database_id, object_store_id, MinIDBKey());
   2367     cursor_options->low_open = true;  // Not included.
   2368   } else {
   2369     cursor_options->low_key =
   2370         ObjectStoreDataKey::Encode(database_id, object_store_id, range.lower());
   2371     cursor_options->low_open = range.lowerOpen();
   2372   }
   2373 
   2374   if (!upper_bound) {
   2375     cursor_options->high_key =
   2376         ObjectStoreDataKey::Encode(database_id, object_store_id, MaxIDBKey());
   2377 
   2378     if (cursor_options->forward) {
   2379       cursor_options->high_open = true;  // Not included.
   2380     } else {
   2381       // We need a key that exists.
   2382       if (!FindGreatestKeyLessThanOrEqual(transaction,
   2383                                           cursor_options->high_key,
   2384                                           &cursor_options->high_key))
   2385         return false;
   2386       cursor_options->high_open = false;
   2387     }
   2388   } else {
   2389     cursor_options->high_key =
   2390         ObjectStoreDataKey::Encode(database_id, object_store_id, range.upper());
   2391     cursor_options->high_open = range.upperOpen();
   2392 
   2393     if (!cursor_options->forward) {
   2394       // For reverse cursors, we need a key that exists.
   2395       std::string found_high_key;
   2396       if (!FindGreatestKeyLessThanOrEqual(
   2397                transaction, cursor_options->high_key, &found_high_key))
   2398         return false;
   2399 
   2400       // If the target key should not be included, but we end up with a smaller
   2401       // key, we should include that.
   2402       if (cursor_options->high_open &&
   2403           CompareIndexKeys(found_high_key, cursor_options->high_key) < 0)
   2404         cursor_options->high_open = false;
   2405 
   2406       cursor_options->high_key = found_high_key;
   2407     }
   2408   }
   2409 
   2410   return true;
   2411 }
   2412 
   2413 bool IndexCursorOptions(
   2414     LevelDBTransaction* transaction,
   2415     int64 database_id,
   2416     int64 object_store_id,
   2417     int64 index_id,
   2418     const IndexedDBKeyRange& range,
   2419     indexed_db::CursorDirection direction,
   2420     IndexedDBBackingStore::Cursor::CursorOptions* cursor_options) {
   2421   DCHECK(transaction);
   2422   if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
   2423     return false;
   2424 
   2425   cursor_options->database_id = database_id;
   2426   cursor_options->object_store_id = object_store_id;
   2427   cursor_options->index_id = index_id;
   2428 
   2429   bool lower_bound = range.lower().IsValid();
   2430   bool upper_bound = range.upper().IsValid();
   2431   cursor_options->forward =
   2432       (direction == indexed_db::CURSOR_NEXT_NO_DUPLICATE ||
   2433        direction == indexed_db::CURSOR_NEXT);
   2434   cursor_options->unique = (direction == indexed_db::CURSOR_NEXT_NO_DUPLICATE ||
   2435                             direction == indexed_db::CURSOR_PREV_NO_DUPLICATE);
   2436 
   2437   if (!lower_bound) {
   2438     cursor_options->low_key =
   2439         IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id);
   2440     cursor_options->low_open = false;  // Included.
   2441   } else {
   2442     cursor_options->low_key = IndexDataKey::Encode(
   2443         database_id, object_store_id, index_id, range.lower());
   2444     cursor_options->low_open = range.lowerOpen();
   2445   }
   2446 
   2447   if (!upper_bound) {
   2448     cursor_options->high_key =
   2449         IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
   2450     cursor_options->high_open = false;  // Included.
   2451 
   2452     if (!cursor_options->forward) {  // We need a key that exists.
   2453       if (!FindGreatestKeyLessThanOrEqual(transaction,
   2454                                           cursor_options->high_key,
   2455                                           &cursor_options->high_key))
   2456         return false;
   2457       cursor_options->high_open = false;
   2458     }
   2459   } else {
   2460     cursor_options->high_key = IndexDataKey::Encode(
   2461         database_id, object_store_id, index_id, range.upper());
   2462     cursor_options->high_open = range.upperOpen();
   2463 
   2464     std::string found_high_key;
   2465     // Seek to the *last* key in the set of non-unique keys
   2466     if (!FindGreatestKeyLessThanOrEqual(
   2467              transaction, cursor_options->high_key, &found_high_key))
   2468       return false;
   2469 
   2470     // If the target key should not be included, but we end up with a smaller
   2471     // key, we should include that.
   2472     if (cursor_options->high_open &&
   2473         CompareIndexKeys(found_high_key, cursor_options->high_key) < 0)
   2474       cursor_options->high_open = false;
   2475 
   2476     cursor_options->high_key = found_high_key;
   2477   }
   2478 
   2479   return true;
   2480 }
   2481 
   2482 scoped_ptr<IndexedDBBackingStore::Cursor>
   2483 IndexedDBBackingStore::OpenObjectStoreCursor(
   2484     IndexedDBBackingStore::Transaction* transaction,
   2485     int64 database_id,
   2486     int64 object_store_id,
   2487     const IndexedDBKeyRange& range,
   2488     indexed_db::CursorDirection direction) {
   2489   IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreCursor");
   2490   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   2491   IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
   2492   if (!ObjectStoreCursorOptions(leveldb_transaction,
   2493                                 database_id,
   2494                                 object_store_id,
   2495                                 range,
   2496                                 direction,
   2497                                 &cursor_options))
   2498     return scoped_ptr<IndexedDBBackingStore::Cursor>();
   2499   scoped_ptr<ObjectStoreCursorImpl> cursor(
   2500       new ObjectStoreCursorImpl(leveldb_transaction, cursor_options));
   2501   if (!cursor->FirstSeek())
   2502     return scoped_ptr<IndexedDBBackingStore::Cursor>();
   2503 
   2504   return cursor.PassAs<IndexedDBBackingStore::Cursor>();
   2505 }
   2506 
   2507 scoped_ptr<IndexedDBBackingStore::Cursor>
   2508 IndexedDBBackingStore::OpenObjectStoreKeyCursor(
   2509     IndexedDBBackingStore::Transaction* transaction,
   2510     int64 database_id,
   2511     int64 object_store_id,
   2512     const IndexedDBKeyRange& range,
   2513     indexed_db::CursorDirection direction) {
   2514   IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreKeyCursor");
   2515   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   2516   IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
   2517   if (!ObjectStoreCursorOptions(leveldb_transaction,
   2518                                 database_id,
   2519                                 object_store_id,
   2520                                 range,
   2521                                 direction,
   2522                                 &cursor_options))
   2523     return scoped_ptr<IndexedDBBackingStore::Cursor>();
   2524   scoped_ptr<ObjectStoreKeyCursorImpl> cursor(
   2525       new ObjectStoreKeyCursorImpl(leveldb_transaction, cursor_options));
   2526   if (!cursor->FirstSeek())
   2527     return scoped_ptr<IndexedDBBackingStore::Cursor>();
   2528 
   2529   return cursor.PassAs<IndexedDBBackingStore::Cursor>();
   2530 }
   2531 
   2532 scoped_ptr<IndexedDBBackingStore::Cursor>
   2533 IndexedDBBackingStore::OpenIndexKeyCursor(
   2534     IndexedDBBackingStore::Transaction* transaction,
   2535     int64 database_id,
   2536     int64 object_store_id,
   2537     int64 index_id,
   2538     const IndexedDBKeyRange& range,
   2539     indexed_db::CursorDirection direction) {
   2540   IDB_TRACE("IndexedDBBackingStore::OpenIndexKeyCursor");
   2541   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   2542   IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
   2543   if (!IndexCursorOptions(leveldb_transaction,
   2544                           database_id,
   2545                           object_store_id,
   2546                           index_id,
   2547                           range,
   2548                           direction,
   2549                           &cursor_options))
   2550     return scoped_ptr<IndexedDBBackingStore::Cursor>();
   2551   scoped_ptr<IndexKeyCursorImpl> cursor(
   2552       new IndexKeyCursorImpl(leveldb_transaction, cursor_options));
   2553   if (!cursor->FirstSeek())
   2554     return scoped_ptr<IndexedDBBackingStore::Cursor>();
   2555 
   2556   return cursor.PassAs<IndexedDBBackingStore::Cursor>();
   2557 }
   2558 
   2559 scoped_ptr<IndexedDBBackingStore::Cursor>
   2560 IndexedDBBackingStore::OpenIndexCursor(
   2561     IndexedDBBackingStore::Transaction* transaction,
   2562     int64 database_id,
   2563     int64 object_store_id,
   2564     int64 index_id,
   2565     const IndexedDBKeyRange& range,
   2566     indexed_db::CursorDirection direction) {
   2567   IDB_TRACE("IndexedDBBackingStore::OpenIndexCursor");
   2568   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   2569   IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
   2570   if (!IndexCursorOptions(leveldb_transaction,
   2571                           database_id,
   2572                           object_store_id,
   2573                           index_id,
   2574                           range,
   2575                           direction,
   2576                           &cursor_options))
   2577     return scoped_ptr<IndexedDBBackingStore::Cursor>();
   2578   scoped_ptr<IndexCursorImpl> cursor(
   2579       new IndexCursorImpl(leveldb_transaction, cursor_options));
   2580   if (!cursor->FirstSeek())
   2581     return scoped_ptr<IndexedDBBackingStore::Cursor>();
   2582 
   2583   return cursor.PassAs<IndexedDBBackingStore::Cursor>();
   2584 }
   2585 
   2586 IndexedDBBackingStore::Transaction::Transaction(
   2587     IndexedDBBackingStore* backing_store)
   2588     : backing_store_(backing_store) {}
   2589 
   2590 IndexedDBBackingStore::Transaction::~Transaction() {}
   2591 
   2592 void IndexedDBBackingStore::Transaction::Begin() {
   2593   IDB_TRACE("IndexedDBBackingStore::Transaction::Begin");
   2594   DCHECK(!transaction_.get());
   2595   transaction_ = new LevelDBTransaction(backing_store_->db_.get());
   2596 }
   2597 
   2598 bool IndexedDBBackingStore::Transaction::Commit() {
   2599   IDB_TRACE("IndexedDBBackingStore::Transaction::Commit");
   2600   DCHECK(transaction_.get());
   2601   bool result = transaction_->Commit();
   2602   transaction_ = NULL;
   2603   if (!result)
   2604     INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
   2605   return result;
   2606 }
   2607 
   2608 void IndexedDBBackingStore::Transaction::Rollback() {
   2609   IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback");
   2610   DCHECK(transaction_.get());
   2611   transaction_->Rollback();
   2612   transaction_ = NULL;
   2613 }
   2614 
   2615 }  // namespace content
   2616