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