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/files/file_path.h"
      8 #include "base/files/file_util.h"
      9 #include "base/format_macros.h"
     10 #include "base/json/json_reader.h"
     11 #include "base/json/json_writer.h"
     12 #include "base/logging.h"
     13 #include "base/metrics/histogram.h"
     14 #include "base/strings/string_util.h"
     15 #include "base/strings/stringprintf.h"
     16 #include "base/strings/utf_string_conversions.h"
     17 #include "content/browser/child_process_security_policy_impl.h"
     18 #include "content/browser/indexed_db/indexed_db_blob_info.h"
     19 #include "content/browser/indexed_db/indexed_db_class_factory.h"
     20 #include "content/browser/indexed_db/indexed_db_database_error.h"
     21 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
     22 #include "content/browser/indexed_db/indexed_db_metadata.h"
     23 #include "content/browser/indexed_db/indexed_db_tracing.h"
     24 #include "content/browser/indexed_db/indexed_db_value.h"
     25 #include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
     26 #include "content/browser/indexed_db/leveldb/leveldb_database.h"
     27 #include "content/browser/indexed_db/leveldb/leveldb_factory.h"
     28 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
     29 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
     30 #include "content/common/indexed_db/indexed_db_key.h"
     31 #include "content/common/indexed_db/indexed_db_key_path.h"
     32 #include "content/common/indexed_db/indexed_db_key_range.h"
     33 #include "content/public/browser/browser_thread.h"
     34 #include "net/url_request/url_request_context.h"
     35 #include "storage/browser/blob/blob_data_handle.h"
     36 #include "storage/browser/fileapi/file_stream_writer.h"
     37 #include "storage/browser/fileapi/file_writer_delegate.h"
     38 #include "storage/browser/fileapi/local_file_stream_writer.h"
     39 #include "storage/common/database/database_identifier.h"
     40 #include "third_party/WebKit/public/platform/WebIDBTypes.h"
     41 #include "third_party/WebKit/public/web/WebSerializedScriptValueVersion.h"
     42 #include "third_party/leveldatabase/env_chromium.h"
     43 
     44 using base::FilePath;
     45 using base::StringPiece;
     46 using storage::FileWriterDelegate;
     47 
     48 namespace content {
     49 
     50 namespace {
     51 
     52 FilePath GetBlobDirectoryName(const FilePath& pathBase, int64 database_id) {
     53   return pathBase.AppendASCII(base::StringPrintf("%" PRIx64, database_id));
     54 }
     55 
     56 FilePath GetBlobDirectoryNameForKey(const FilePath& pathBase,
     57                                     int64 database_id,
     58                                     int64 key) {
     59   FilePath path = GetBlobDirectoryName(pathBase, database_id);
     60   path = path.AppendASCII(base::StringPrintf(
     61       "%02x", static_cast<int>(key & 0x000000000000ff00) >> 8));
     62   return path;
     63 }
     64 
     65 FilePath GetBlobFileNameForKey(const FilePath& pathBase,
     66                                int64 database_id,
     67                                int64 key) {
     68   FilePath path = GetBlobDirectoryNameForKey(pathBase, database_id, key);
     69   path = path.AppendASCII(base::StringPrintf("%" PRIx64, key));
     70   return path;
     71 }
     72 
     73 bool MakeIDBBlobDirectory(const FilePath& pathBase,
     74                           int64 database_id,
     75                           int64 key) {
     76   FilePath path = GetBlobDirectoryNameForKey(pathBase, database_id, key);
     77   return base::CreateDirectory(path);
     78 }
     79 
     80 static std::string ComputeOriginIdentifier(const GURL& origin_url) {
     81   return storage::GetIdentifierFromOrigin(origin_url) + "@1";
     82 }
     83 
     84 static base::FilePath ComputeFileName(const GURL& origin_url) {
     85   return base::FilePath()
     86       .AppendASCII(storage::GetIdentifierFromOrigin(origin_url))
     87       .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb"));
     88 }
     89 
     90 static base::FilePath ComputeBlobPath(const GURL& origin_url) {
     91   return base::FilePath()
     92       .AppendASCII(storage::GetIdentifierFromOrigin(origin_url))
     93       .AddExtension(FILE_PATH_LITERAL(".indexeddb.blob"));
     94 }
     95 
     96 static base::FilePath ComputeCorruptionFileName(const GURL& origin_url) {
     97   return ComputeFileName(origin_url)
     98       .Append(FILE_PATH_LITERAL("corruption_info.json"));
     99 }
    100 
    101 }  // namespace
    102 
    103 static const int64 kKeyGeneratorInitialNumber =
    104     1;  // From the IndexedDB specification.
    105 
    106 enum IndexedDBBackingStoreErrorSource {
    107   // 0 - 2 are no longer used.
    108   FIND_KEY_IN_INDEX = 3,
    109   GET_IDBDATABASE_METADATA,
    110   GET_INDEXES,
    111   GET_KEY_GENERATOR_CURRENT_NUMBER,
    112   GET_OBJECT_STORES,
    113   GET_RECORD,
    114   KEY_EXISTS_IN_OBJECT_STORE,
    115   LOAD_CURRENT_ROW,
    116   SET_UP_METADATA,
    117   GET_PRIMARY_KEY_VIA_INDEX,
    118   KEY_EXISTS_IN_INDEX,
    119   VERSION_EXISTS,
    120   DELETE_OBJECT_STORE,
    121   SET_MAX_OBJECT_STORE_ID,
    122   SET_MAX_INDEX_ID,
    123   GET_NEW_DATABASE_ID,
    124   GET_NEW_VERSION_NUMBER,
    125   CREATE_IDBDATABASE_METADATA,
    126   DELETE_DATABASE,
    127   TRANSACTION_COMMIT_METHOD,  // TRANSACTION_COMMIT is a WinNT.h macro
    128   GET_DATABASE_NAMES,
    129   DELETE_INDEX,
    130   CLEAR_OBJECT_STORE,
    131   READ_BLOB_JOURNAL,
    132   DECODE_BLOB_JOURNAL,
    133   GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER,
    134   GET_BLOB_INFO_FOR_RECORD,
    135   INTERNAL_ERROR_MAX,
    136 };
    137 
    138 static void RecordInternalError(const char* type,
    139                                 IndexedDBBackingStoreErrorSource location) {
    140   std::string name;
    141   name.append("WebCore.IndexedDB.BackingStore.").append(type).append("Error");
    142   base::Histogram::FactoryGet(name,
    143                               1,
    144                               INTERNAL_ERROR_MAX,
    145                               INTERNAL_ERROR_MAX + 1,
    146                               base::HistogramBase::kUmaTargetedHistogramFlag)
    147       ->Add(location);
    148 }
    149 
    150 // Use to signal conditions caused by data corruption.
    151 // A macro is used instead of an inline function so that the assert and log
    152 // report the line number.
    153 #define REPORT_ERROR(type, location)                      \
    154   do {                                                    \
    155     LOG(ERROR) << "IndexedDB " type " Error: " #location; \
    156     RecordInternalError(type, location);                  \
    157   } while (0)
    158 
    159 #define INTERNAL_READ_ERROR(location) REPORT_ERROR("Read", location)
    160 #define INTERNAL_CONSISTENCY_ERROR(location) \
    161   REPORT_ERROR("Consistency", location)
    162 #define INTERNAL_WRITE_ERROR(location) REPORT_ERROR("Write", location)
    163 
    164 // Use to signal conditions that usually indicate developer error, but
    165 // could be caused by data corruption.  A macro is used instead of an
    166 // inline function so that the assert and log report the line number.
    167 // TODO(cmumford): Improve test coverage so that all error conditions are
    168 // "tested" and then delete this macro.
    169 #define REPORT_ERROR_UNTESTED(type, location)             \
    170   do {                                                    \
    171     LOG(ERROR) << "IndexedDB " type " Error: " #location; \
    172     NOTREACHED();                                         \
    173     RecordInternalError(type, location);                  \
    174   } while (0)
    175 
    176 #define INTERNAL_READ_ERROR_UNTESTED(location) \
    177   REPORT_ERROR_UNTESTED("Read", location)
    178 #define INTERNAL_CONSISTENCY_ERROR_UNTESTED(location) \
    179   REPORT_ERROR_UNTESTED("Consistency", location)
    180 #define INTERNAL_WRITE_ERROR_UNTESTED(location) \
    181   REPORT_ERROR_UNTESTED("Write", location)
    182 
    183 static void PutBool(LevelDBTransaction* transaction,
    184                     const StringPiece& key,
    185                     bool value) {
    186   std::string buffer;
    187   EncodeBool(value, &buffer);
    188   transaction->Put(key, &buffer);
    189 }
    190 
    191 // Was able to use LevelDB to read the data w/o error, but the data read was not
    192 // in the expected format.
    193 static leveldb::Status InternalInconsistencyStatus() {
    194   return leveldb::Status::Corruption("Internal inconsistency");
    195 }
    196 
    197 static leveldb::Status InvalidDBKeyStatus() {
    198   return leveldb::Status::InvalidArgument("Invalid database key ID");
    199 }
    200 
    201 static leveldb::Status IOErrorStatus() {
    202   return leveldb::Status::IOError("IO Error");
    203 }
    204 
    205 template <typename DBOrTransaction>
    206 static leveldb::Status GetInt(DBOrTransaction* db,
    207                               const StringPiece& key,
    208                               int64* found_int,
    209                               bool* found) {
    210   std::string result;
    211   leveldb::Status s = db->Get(key, &result, found);
    212   if (!s.ok())
    213     return s;
    214   if (!*found)
    215     return leveldb::Status::OK();
    216   StringPiece slice(result);
    217   if (DecodeInt(&slice, found_int) && slice.empty())
    218     return s;
    219   return InternalInconsistencyStatus();
    220 }
    221 
    222 static void PutInt(LevelDBTransaction* transaction,
    223                    const StringPiece& key,
    224                    int64 value) {
    225   DCHECK_GE(value, 0);
    226   std::string buffer;
    227   EncodeInt(value, &buffer);
    228   transaction->Put(key, &buffer);
    229 }
    230 
    231 template <typename DBOrTransaction>
    232 WARN_UNUSED_RESULT static leveldb::Status GetVarInt(DBOrTransaction* db,
    233                                                     const StringPiece& key,
    234                                                     int64* found_int,
    235                                                     bool* found) {
    236   std::string result;
    237   leveldb::Status s = db->Get(key, &result, found);
    238   if (!s.ok())
    239     return s;
    240   if (!*found)
    241     return leveldb::Status::OK();
    242   StringPiece slice(result);
    243   if (DecodeVarInt(&slice, found_int) && slice.empty())
    244     return s;
    245   return InternalInconsistencyStatus();
    246 }
    247 
    248 static void PutVarInt(LevelDBTransaction* transaction,
    249                       const StringPiece& key,
    250                       int64 value) {
    251   std::string buffer;
    252   EncodeVarInt(value, &buffer);
    253   transaction->Put(key, &buffer);
    254 }
    255 
    256 template <typename DBOrTransaction>
    257 WARN_UNUSED_RESULT static leveldb::Status GetString(
    258     DBOrTransaction* db,
    259     const StringPiece& key,
    260     base::string16* found_string,
    261     bool* found) {
    262   std::string result;
    263   *found = false;
    264   leveldb::Status s = db->Get(key, &result, found);
    265   if (!s.ok())
    266     return s;
    267   if (!*found)
    268     return leveldb::Status::OK();
    269   StringPiece slice(result);
    270   if (DecodeString(&slice, found_string) && slice.empty())
    271     return s;
    272   return InternalInconsistencyStatus();
    273 }
    274 
    275 static void PutString(LevelDBTransaction* transaction,
    276                       const StringPiece& key,
    277                       const base::string16& value) {
    278   std::string buffer;
    279   EncodeString(value, &buffer);
    280   transaction->Put(key, &buffer);
    281 }
    282 
    283 static void PutIDBKeyPath(LevelDBTransaction* transaction,
    284                           const StringPiece& key,
    285                           const IndexedDBKeyPath& value) {
    286   std::string buffer;
    287   EncodeIDBKeyPath(value, &buffer);
    288   transaction->Put(key, &buffer);
    289 }
    290 
    291 static int CompareKeys(const StringPiece& a, const StringPiece& b) {
    292   return Compare(a, b, false /*index_keys*/);
    293 }
    294 
    295 static int CompareIndexKeys(const StringPiece& a, const StringPiece& b) {
    296   return Compare(a, b, true /*index_keys*/);
    297 }
    298 
    299 int IndexedDBBackingStore::Comparator::Compare(const StringPiece& a,
    300                                                const StringPiece& b) const {
    301   return content::Compare(a, b, false /*index_keys*/);
    302 }
    303 
    304 const char* IndexedDBBackingStore::Comparator::Name() const {
    305   return "idb_cmp1";
    306 }
    307 
    308 // 0 - Initial version.
    309 // 1 - Adds UserIntVersion to DatabaseMetaData.
    310 // 2 - Adds DataVersion to to global metadata.
    311 // 3 - Adds metadata needed for blob support.
    312 static const int64 kLatestKnownSchemaVersion = 3;
    313 WARN_UNUSED_RESULT static bool IsSchemaKnown(LevelDBDatabase* db, bool* known) {
    314   int64 db_schema_version = 0;
    315   bool found = false;
    316   leveldb::Status s =
    317       GetInt(db, SchemaVersionKey::Encode(), &db_schema_version, &found);
    318   if (!s.ok())
    319     return false;
    320   if (!found) {
    321     *known = true;
    322     return true;
    323   }
    324   if (db_schema_version > kLatestKnownSchemaVersion) {
    325     *known = false;
    326     return true;
    327   }
    328 
    329   const uint32 latest_known_data_version =
    330       blink::kSerializedScriptValueVersion;
    331   int64 db_data_version = 0;
    332   s = GetInt(db, DataVersionKey::Encode(), &db_data_version, &found);
    333   if (!s.ok())
    334     return false;
    335   if (!found) {
    336     *known = true;
    337     return true;
    338   }
    339 
    340   if (db_data_version > latest_known_data_version) {
    341     *known = false;
    342     return true;
    343   }
    344 
    345   *known = true;
    346   return true;
    347 }
    348 
    349 // TODO(ericu): Move this down into the member section of this file.  I'm
    350 // leaving it here for this CL as it's easier to see the diffs in place.
    351 WARN_UNUSED_RESULT leveldb::Status IndexedDBBackingStore::SetUpMetadata() {
    352   const uint32 latest_known_data_version =
    353       blink::kSerializedScriptValueVersion;
    354   const std::string schema_version_key = SchemaVersionKey::Encode();
    355   const std::string data_version_key = DataVersionKey::Encode();
    356 
    357   scoped_refptr<LevelDBTransaction> transaction =
    358       IndexedDBClassFactory::Get()->CreateLevelDBTransaction(db_.get());
    359 
    360   int64 db_schema_version = 0;
    361   int64 db_data_version = 0;
    362   bool found = false;
    363   leveldb::Status s =
    364       GetInt(transaction.get(), schema_version_key, &db_schema_version, &found);
    365   if (!s.ok()) {
    366     INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
    367     return s;
    368   }
    369   if (!found) {
    370     // Initialize new backing store.
    371     db_schema_version = kLatestKnownSchemaVersion;
    372     PutInt(transaction.get(), schema_version_key, db_schema_version);
    373     db_data_version = latest_known_data_version;
    374     PutInt(transaction.get(), data_version_key, db_data_version);
    375     // If a blob directory already exists for this database, blow it away.  It's
    376     // leftover from a partially-purged previous generation of data.
    377     if (!base::DeleteFile(blob_path_, true)) {
    378       INTERNAL_WRITE_ERROR_UNTESTED(SET_UP_METADATA);
    379       return IOErrorStatus();
    380     }
    381   } else {
    382     // Upgrade old backing store.
    383     DCHECK_LE(db_schema_version, kLatestKnownSchemaVersion);
    384     if (db_schema_version < 1) {
    385       db_schema_version = 1;
    386       PutInt(transaction.get(), schema_version_key, db_schema_version);
    387       const std::string start_key =
    388           DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier_);
    389       const std::string stop_key =
    390           DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier_);
    391       scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
    392       for (s = it->Seek(start_key);
    393            s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
    394            s = it->Next()) {
    395         int64 database_id = 0;
    396         found = false;
    397         s = GetInt(transaction.get(), it->Key(), &database_id, &found);
    398         if (!s.ok()) {
    399           INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
    400           return s;
    401         }
    402         if (!found) {
    403           INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_UP_METADATA);
    404           return InternalInconsistencyStatus();
    405         }
    406         std::string int_version_key = DatabaseMetaDataKey::Encode(
    407             database_id, DatabaseMetaDataKey::USER_INT_VERSION);
    408         PutVarInt(transaction.get(),
    409                   int_version_key,
    410                   IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
    411       }
    412     }
    413     if (s.ok() && db_schema_version < 2) {
    414       db_schema_version = 2;
    415       PutInt(transaction.get(), schema_version_key, db_schema_version);
    416       db_data_version = blink::kSerializedScriptValueVersion;
    417       PutInt(transaction.get(), data_version_key, db_data_version);
    418     }
    419     if (db_schema_version < 3) {
    420       db_schema_version = 3;
    421       if (!base::DeleteFile(blob_path_, true)) {
    422         INTERNAL_WRITE_ERROR_UNTESTED(SET_UP_METADATA);
    423         return IOErrorStatus();
    424       }
    425     }
    426   }
    427 
    428   if (!s.ok()) {
    429     INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
    430     return s;
    431   }
    432 
    433   // All new values will be written using this serialization version.
    434   found = false;
    435   s = GetInt(transaction.get(), data_version_key, &db_data_version, &found);
    436   if (!s.ok()) {
    437     INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
    438     return s;
    439   }
    440   if (!found) {
    441     INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_UP_METADATA);
    442     return InternalInconsistencyStatus();
    443   }
    444   if (db_data_version < latest_known_data_version) {
    445     db_data_version = latest_known_data_version;
    446     PutInt(transaction.get(), data_version_key, db_data_version);
    447   }
    448 
    449   DCHECK_EQ(db_schema_version, kLatestKnownSchemaVersion);
    450   DCHECK_EQ(db_data_version, latest_known_data_version);
    451 
    452   s = transaction->Commit();
    453   if (!s.ok())
    454     INTERNAL_WRITE_ERROR_UNTESTED(SET_UP_METADATA);
    455   return s;
    456 }
    457 
    458 template <typename DBOrTransaction>
    459 WARN_UNUSED_RESULT static leveldb::Status GetMaxObjectStoreId(
    460     DBOrTransaction* db,
    461     int64 database_id,
    462     int64* max_object_store_id) {
    463   const std::string max_object_store_id_key = DatabaseMetaDataKey::Encode(
    464       database_id, DatabaseMetaDataKey::MAX_OBJECT_STORE_ID);
    465   return GetMaxObjectStoreId(db, max_object_store_id_key, max_object_store_id);
    466 }
    467 
    468 template <typename DBOrTransaction>
    469 WARN_UNUSED_RESULT static leveldb::Status GetMaxObjectStoreId(
    470     DBOrTransaction* db,
    471     const std::string& max_object_store_id_key,
    472     int64* max_object_store_id) {
    473   *max_object_store_id = -1;
    474   bool found = false;
    475   leveldb::Status s =
    476       GetInt(db, max_object_store_id_key, max_object_store_id, &found);
    477   if (!s.ok())
    478     return s;
    479   if (!found)
    480     *max_object_store_id = 0;
    481 
    482   DCHECK_GE(*max_object_store_id, 0);
    483   return s;
    484 }
    485 
    486 class DefaultLevelDBFactory : public LevelDBFactory {
    487  public:
    488   DefaultLevelDBFactory() {}
    489   virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name,
    490                                       const LevelDBComparator* comparator,
    491                                       scoped_ptr<LevelDBDatabase>* db,
    492                                       bool* is_disk_full) OVERRIDE {
    493     return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full);
    494   }
    495   virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name)
    496       OVERRIDE {
    497     return LevelDBDatabase::Destroy(file_name);
    498   }
    499 
    500  private:
    501   DISALLOW_COPY_AND_ASSIGN(DefaultLevelDBFactory);
    502 };
    503 
    504 static bool GetBlobKeyGeneratorCurrentNumber(
    505     LevelDBTransaction* leveldb_transaction,
    506     int64 database_id,
    507     int64* blob_key_generator_current_number) {
    508   const std::string key_gen_key = DatabaseMetaDataKey::Encode(
    509       database_id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER);
    510 
    511   // Default to initial number if not found.
    512   int64 cur_number = DatabaseMetaDataKey::kBlobKeyGeneratorInitialNumber;
    513   std::string data;
    514 
    515   bool found = false;
    516   bool ok = leveldb_transaction->Get(key_gen_key, &data, &found).ok();
    517   if (!ok) {
    518     INTERNAL_READ_ERROR_UNTESTED(GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER);
    519     return false;
    520   }
    521   if (found) {
    522     StringPiece slice(data);
    523     if (!DecodeVarInt(&slice, &cur_number) || !slice.empty() ||
    524         !DatabaseMetaDataKey::IsValidBlobKey(cur_number)) {
    525       INTERNAL_READ_ERROR_UNTESTED(GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER);
    526       return false;
    527     }
    528   }
    529   *blob_key_generator_current_number = cur_number;
    530   return true;
    531 }
    532 
    533 static bool UpdateBlobKeyGeneratorCurrentNumber(
    534     LevelDBTransaction* leveldb_transaction,
    535     int64 database_id,
    536     int64 blob_key_generator_current_number) {
    537 #ifndef NDEBUG
    538   int64 old_number;
    539   if (!GetBlobKeyGeneratorCurrentNumber(
    540           leveldb_transaction, database_id, &old_number))
    541     return false;
    542   DCHECK_LT(old_number, blob_key_generator_current_number);
    543 #endif
    544   DCHECK(
    545       DatabaseMetaDataKey::IsValidBlobKey(blob_key_generator_current_number));
    546   const std::string key = DatabaseMetaDataKey::Encode(
    547       database_id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER);
    548 
    549   PutVarInt(leveldb_transaction, key, blob_key_generator_current_number);
    550   return true;
    551 }
    552 
    553 // TODO(ericu): Error recovery. If we persistently can't read the
    554 // blob journal, the safe thing to do is to clear it and leak the blobs,
    555 // though that may be costly. Still, database/directory deletion should always
    556 // clean things up, and we can write an fsck that will do a full correction if
    557 // need be.
    558 template <typename T>
    559 static leveldb::Status GetBlobJournal(const StringPiece& leveldb_key,
    560                                       T* leveldb_transaction,
    561                                       BlobJournalType* journal) {
    562   std::string data;
    563   bool found = false;
    564   leveldb::Status s = leveldb_transaction->Get(leveldb_key, &data, &found);
    565   if (!s.ok()) {
    566     INTERNAL_READ_ERROR(READ_BLOB_JOURNAL);
    567     return s;
    568   }
    569   journal->clear();
    570   if (!found || !data.size())
    571     return leveldb::Status::OK();
    572   StringPiece slice(data);
    573   if (!DecodeBlobJournal(&slice, journal)) {
    574     INTERNAL_CONSISTENCY_ERROR_UNTESTED(DECODE_BLOB_JOURNAL);
    575     s = InternalInconsistencyStatus();
    576   }
    577   return s;
    578 }
    579 
    580 static void ClearBlobJournal(LevelDBTransaction* leveldb_transaction,
    581                              const std::string& level_db_key) {
    582   leveldb_transaction->Remove(level_db_key);
    583 }
    584 
    585 static void UpdatePrimaryJournalWithBlobList(
    586     LevelDBTransaction* leveldb_transaction,
    587     const BlobJournalType& journal) {
    588   const std::string leveldb_key = BlobJournalKey::Encode();
    589   std::string data;
    590   EncodeBlobJournal(journal, &data);
    591   leveldb_transaction->Put(leveldb_key, &data);
    592 }
    593 
    594 static void UpdateLiveBlobJournalWithBlobList(
    595     LevelDBTransaction* leveldb_transaction,
    596     const BlobJournalType& journal) {
    597   const std::string leveldb_key = LiveBlobJournalKey::Encode();
    598   std::string data;
    599   EncodeBlobJournal(journal, &data);
    600   leveldb_transaction->Put(leveldb_key, &data);
    601 }
    602 
    603 static leveldb::Status MergeBlobsIntoLiveBlobJournal(
    604     LevelDBTransaction* leveldb_transaction,
    605     const BlobJournalType& journal) {
    606   BlobJournalType old_journal;
    607   const std::string key = LiveBlobJournalKey::Encode();
    608   leveldb::Status s = GetBlobJournal(key, leveldb_transaction, &old_journal);
    609   if (!s.ok())
    610     return s;
    611 
    612   old_journal.insert(old_journal.end(), journal.begin(), journal.end());
    613 
    614   UpdateLiveBlobJournalWithBlobList(leveldb_transaction, old_journal);
    615   return leveldb::Status::OK();
    616 }
    617 
    618 static void UpdateBlobJournalWithDatabase(
    619     LevelDBDirectTransaction* leveldb_transaction,
    620     int64 database_id) {
    621   BlobJournalType journal;
    622   journal.push_back(
    623       std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey));
    624   const std::string key = BlobJournalKey::Encode();
    625   std::string data;
    626   EncodeBlobJournal(journal, &data);
    627   leveldb_transaction->Put(key, &data);
    628 }
    629 
    630 static leveldb::Status MergeDatabaseIntoLiveBlobJournal(
    631     LevelDBDirectTransaction* leveldb_transaction,
    632     int64 database_id) {
    633   BlobJournalType journal;
    634   const std::string key = LiveBlobJournalKey::Encode();
    635   leveldb::Status s = GetBlobJournal(key, leveldb_transaction, &journal);
    636   if (!s.ok())
    637     return s;
    638   journal.push_back(
    639       std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey));
    640   std::string data;
    641   EncodeBlobJournal(journal, &data);
    642   leveldb_transaction->Put(key, &data);
    643   return leveldb::Status::OK();
    644 }
    645 
    646 // Blob Data is encoded as a series of:
    647 //   { is_file [bool], key [int64 as varInt],
    648 //     type [string-with-length, may be empty],
    649 //     (for Blobs only) size [int64 as varInt]
    650 //     (for Files only) fileName [string-with-length]
    651 //   }
    652 // There is no length field; just read until you run out of data.
    653 static std::string EncodeBlobData(
    654     const std::vector<IndexedDBBlobInfo*>& blob_info) {
    655   std::string ret;
    656   std::vector<IndexedDBBlobInfo*>::const_iterator iter;
    657   for (iter = blob_info.begin(); iter != blob_info.end(); ++iter) {
    658     const IndexedDBBlobInfo& info = **iter;
    659     EncodeBool(info.is_file(), &ret);
    660     EncodeVarInt(info.key(), &ret);
    661     EncodeStringWithLength(info.type(), &ret);
    662     if (info.is_file())
    663       EncodeStringWithLength(info.file_name(), &ret);
    664     else
    665       EncodeVarInt(info.size(), &ret);
    666   }
    667   return ret;
    668 }
    669 
    670 static bool DecodeBlobData(const std::string& data,
    671                            std::vector<IndexedDBBlobInfo>* output) {
    672   std::vector<IndexedDBBlobInfo> ret;
    673   output->clear();
    674   StringPiece slice(data);
    675   while (!slice.empty()) {
    676     bool is_file;
    677     int64 key;
    678     base::string16 type;
    679     int64 size;
    680     base::string16 file_name;
    681 
    682     if (!DecodeBool(&slice, &is_file))
    683       return false;
    684     if (!DecodeVarInt(&slice, &key) ||
    685         !DatabaseMetaDataKey::IsValidBlobKey(key))
    686       return false;
    687     if (!DecodeStringWithLength(&slice, &type))
    688       return false;
    689     if (is_file) {
    690       if (!DecodeStringWithLength(&slice, &file_name))
    691         return false;
    692       ret.push_back(IndexedDBBlobInfo(key, type, file_name));
    693     } else {
    694       if (!DecodeVarInt(&slice, &size) || size < 0)
    695         return false;
    696       ret.push_back(IndexedDBBlobInfo(type, static_cast<uint64>(size), key));
    697     }
    698   }
    699   output->swap(ret);
    700 
    701   return true;
    702 }
    703 
    704 IndexedDBBackingStore::IndexedDBBackingStore(
    705     IndexedDBFactory* indexed_db_factory,
    706     const GURL& origin_url,
    707     const base::FilePath& blob_path,
    708     net::URLRequestContext* request_context,
    709     scoped_ptr<LevelDBDatabase> db,
    710     scoped_ptr<LevelDBComparator> comparator,
    711     base::SequencedTaskRunner* task_runner)
    712     : indexed_db_factory_(indexed_db_factory),
    713       origin_url_(origin_url),
    714       blob_path_(blob_path),
    715       origin_identifier_(ComputeOriginIdentifier(origin_url)),
    716       request_context_(request_context),
    717       task_runner_(task_runner),
    718       db_(db.Pass()),
    719       comparator_(comparator.Pass()),
    720       active_blob_registry_(this) {
    721 }
    722 
    723 IndexedDBBackingStore::~IndexedDBBackingStore() {
    724   if (!blob_path_.empty() && !child_process_ids_granted_.empty()) {
    725     ChildProcessSecurityPolicyImpl* policy =
    726         ChildProcessSecurityPolicyImpl::GetInstance();
    727     std::set<int>::const_iterator iter;
    728     for (iter = child_process_ids_granted_.begin();
    729          iter != child_process_ids_granted_.end();
    730          ++iter) {
    731       policy->RevokeAllPermissionsForFile(*iter, blob_path_);
    732     }
    733   }
    734   STLDeleteContainerPairSecondPointers(incognito_blob_map_.begin(),
    735                                        incognito_blob_map_.end());
    736   // db_'s destructor uses comparator_. The order of destruction is important.
    737   db_.reset();
    738   comparator_.reset();
    739 }
    740 
    741 IndexedDBBackingStore::RecordIdentifier::RecordIdentifier(
    742     const std::string& primary_key,
    743     int64 version)
    744     : primary_key_(primary_key), version_(version) {
    745   DCHECK(!primary_key.empty());
    746 }
    747 IndexedDBBackingStore::RecordIdentifier::RecordIdentifier()
    748     : primary_key_(), version_(-1) {}
    749 IndexedDBBackingStore::RecordIdentifier::~RecordIdentifier() {}
    750 
    751 IndexedDBBackingStore::Cursor::CursorOptions::CursorOptions() {}
    752 IndexedDBBackingStore::Cursor::CursorOptions::~CursorOptions() {}
    753 
    754 enum IndexedDBBackingStoreOpenResult {
    755   INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS,
    756   INDEXED_DB_BACKING_STORE_OPEN_SUCCESS,
    757   INDEXED_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY,
    758   INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_SCHEMA,
    759   INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_DESTROY_FAILED,
    760   INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_FAILED,
    761   INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_SUCCESS,
    762   INDEXED_DB_BACKING_STORE_OPEN_FAILED_IO_ERROR_CHECKING_SCHEMA,
    763   INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR,
    764   INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED,
    765   INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII,
    766   INDEXED_DB_BACKING_STORE_OPEN_DISK_FULL_DEPRECATED,
    767   INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG,
    768   INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY,
    769   INDEXED_DB_BACKING_STORE_OPEN_FAILED_PRIOR_CORRUPTION,
    770   INDEXED_DB_BACKING_STORE_OPEN_FAILED_CLEANUP_JOURNAL_ERROR,
    771   INDEXED_DB_BACKING_STORE_OPEN_MAX,
    772 };
    773 
    774 // static
    775 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
    776     IndexedDBFactory* indexed_db_factory,
    777     const GURL& origin_url,
    778     const base::FilePath& path_base,
    779     net::URLRequestContext* request_context,
    780     blink::WebIDBDataLoss* data_loss,
    781     std::string* data_loss_message,
    782     bool* disk_full,
    783     base::SequencedTaskRunner* task_runner,
    784     bool clean_journal,
    785     leveldb::Status* status) {
    786   *data_loss = blink::WebIDBDataLossNone;
    787   DefaultLevelDBFactory leveldb_factory;
    788   return IndexedDBBackingStore::Open(indexed_db_factory,
    789                                      origin_url,
    790                                      path_base,
    791                                      request_context,
    792                                      data_loss,
    793                                      data_loss_message,
    794                                      disk_full,
    795                                      &leveldb_factory,
    796                                      task_runner,
    797                                      clean_journal,
    798                                      status);
    799 }
    800 
    801 static std::string OriginToCustomHistogramSuffix(const GURL& origin_url) {
    802   if (origin_url.host() == "docs.google.com")
    803     return ".Docs";
    804   return std::string();
    805 }
    806 
    807 static void HistogramOpenStatus(IndexedDBBackingStoreOpenResult result,
    808                                 const GURL& origin_url) {
    809   UMA_HISTOGRAM_ENUMERATION("WebCore.IndexedDB.BackingStore.OpenStatus",
    810                             result,
    811                             INDEXED_DB_BACKING_STORE_OPEN_MAX);
    812   const std::string suffix = OriginToCustomHistogramSuffix(origin_url);
    813   // Data from the WebCore.IndexedDB.BackingStore.OpenStatus histogram is used
    814   // to generate a graph. So as not to alter the meaning of that graph,
    815   // continue to collect all stats there (above) but also now collect docs stats
    816   // separately (below).
    817   if (!suffix.empty()) {
    818     base::LinearHistogram::FactoryGet(
    819         "WebCore.IndexedDB.BackingStore.OpenStatus" + suffix,
    820         1,
    821         INDEXED_DB_BACKING_STORE_OPEN_MAX,
    822         INDEXED_DB_BACKING_STORE_OPEN_MAX + 1,
    823         base::HistogramBase::kUmaTargetedHistogramFlag)->Add(result);
    824   }
    825 }
    826 
    827 static bool IsPathTooLong(const base::FilePath& leveldb_dir) {
    828   int limit = base::GetMaximumPathComponentLength(leveldb_dir.DirName());
    829   if (limit == -1) {
    830     DLOG(WARNING) << "GetMaximumPathComponentLength returned -1";
    831     // In limited testing, ChromeOS returns 143, other OSes 255.
    832 #if defined(OS_CHROMEOS)
    833     limit = 143;
    834 #else
    835     limit = 255;
    836 #endif
    837   }
    838   size_t component_length = leveldb_dir.BaseName().value().length();
    839   if (component_length > static_cast<uint32_t>(limit)) {
    840     DLOG(WARNING) << "Path component length (" << component_length
    841                   << ") exceeds maximum (" << limit
    842                   << ") allowed by this filesystem.";
    843     const int min = 140;
    844     const int max = 300;
    845     const int num_buckets = 12;
    846     UMA_HISTOGRAM_CUSTOM_COUNTS(
    847         "WebCore.IndexedDB.BackingStore.OverlyLargeOriginLength",
    848         component_length,
    849         min,
    850         max,
    851         num_buckets);
    852     return true;
    853   }
    854   return false;
    855 }
    856 
    857 leveldb::Status IndexedDBBackingStore::DestroyBackingStore(
    858     const base::FilePath& path_base,
    859     const GURL& origin_url) {
    860   const base::FilePath file_path =
    861       path_base.Append(ComputeFileName(origin_url));
    862   DefaultLevelDBFactory leveldb_factory;
    863   return leveldb_factory.DestroyLevelDB(file_path);
    864 }
    865 
    866 bool IndexedDBBackingStore::ReadCorruptionInfo(const base::FilePath& path_base,
    867                                                const GURL& origin_url,
    868                                                std::string* message) {
    869   const base::FilePath info_path =
    870       path_base.Append(ComputeCorruptionFileName(origin_url));
    871 
    872   if (IsPathTooLong(info_path))
    873     return false;
    874 
    875   const int64 max_json_len = 4096;
    876   int64 file_size(0);
    877   if (!GetFileSize(info_path, &file_size) || file_size > max_json_len)
    878     return false;
    879   if (!file_size) {
    880     NOTREACHED();
    881     return false;
    882   }
    883 
    884   base::File file(info_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
    885   bool success = false;
    886   if (file.IsValid()) {
    887     std::vector<char> bytes(file_size);
    888     if (file_size == file.Read(0, &bytes[0], file_size)) {
    889       std::string input_js(&bytes[0], file_size);
    890       base::JSONReader reader;
    891       scoped_ptr<base::Value> val(reader.ReadToValue(input_js));
    892       if (val && val->GetType() == base::Value::TYPE_DICTIONARY) {
    893         base::DictionaryValue* dict_val =
    894             static_cast<base::DictionaryValue*>(val.get());
    895         success = dict_val->GetString("message", message);
    896       }
    897     }
    898     file.Close();
    899   }
    900 
    901   base::DeleteFile(info_path, false);
    902 
    903   return success;
    904 }
    905 
    906 bool IndexedDBBackingStore::RecordCorruptionInfo(
    907     const base::FilePath& path_base,
    908     const GURL& origin_url,
    909     const std::string& message) {
    910   const base::FilePath info_path =
    911       path_base.Append(ComputeCorruptionFileName(origin_url));
    912   if (IsPathTooLong(info_path))
    913     return false;
    914 
    915   base::DictionaryValue root_dict;
    916   root_dict.SetString("message", message);
    917   std::string output_js;
    918   base::JSONWriter::Write(&root_dict, &output_js);
    919 
    920   base::File file(info_path,
    921                   base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
    922   if (!file.IsValid())
    923     return false;
    924   int written = file.Write(0, output_js.c_str(), output_js.length());
    925   return size_t(written) == output_js.length();
    926 }
    927 
    928 // static
    929 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
    930     IndexedDBFactory* indexed_db_factory,
    931     const GURL& origin_url,
    932     const base::FilePath& path_base,
    933     net::URLRequestContext* request_context,
    934     blink::WebIDBDataLoss* data_loss,
    935     std::string* data_loss_message,
    936     bool* is_disk_full,
    937     LevelDBFactory* leveldb_factory,
    938     base::SequencedTaskRunner* task_runner,
    939     bool clean_journal,
    940     leveldb::Status* status) {
    941   IDB_TRACE("IndexedDBBackingStore::Open");
    942   DCHECK(!path_base.empty());
    943   *data_loss = blink::WebIDBDataLossNone;
    944   *data_loss_message = "";
    945   *is_disk_full = false;
    946 
    947   *status = leveldb::Status::OK();
    948 
    949   scoped_ptr<LevelDBComparator> comparator(new Comparator());
    950 
    951   if (!base::IsStringASCII(path_base.AsUTF8Unsafe())) {
    952     HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII,
    953                         origin_url);
    954   }
    955   if (!base::CreateDirectory(path_base)) {
    956     *status =
    957         leveldb::Status::IOError("Unable to create IndexedDB database path");
    958     LOG(ERROR) << status->ToString() << ": \"" << path_base.AsUTF8Unsafe()
    959                << "\"";
    960     HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY,
    961                         origin_url);
    962     return scoped_refptr<IndexedDBBackingStore>();
    963   }
    964 
    965   const base::FilePath file_path =
    966       path_base.Append(ComputeFileName(origin_url));
    967   const base::FilePath blob_path =
    968       path_base.Append(ComputeBlobPath(origin_url));
    969 
    970   if (IsPathTooLong(file_path)) {
    971     *status = leveldb::Status::IOError("File path too long");
    972     HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG,
    973                         origin_url);
    974     return scoped_refptr<IndexedDBBackingStore>();
    975   }
    976 
    977   scoped_ptr<LevelDBDatabase> db;
    978   *status = leveldb_factory->OpenLevelDB(
    979       file_path, comparator.get(), &db, is_disk_full);
    980 
    981   DCHECK(!db == !status->ok());
    982   if (!status->ok()) {
    983     if (leveldb_env::IndicatesDiskFull(*status)) {
    984       *is_disk_full = true;
    985     } else if (leveldb_env::IsCorruption(*status)) {
    986       *data_loss = blink::WebIDBDataLossTotal;
    987       *data_loss_message = leveldb_env::GetCorruptionMessage(*status);
    988     }
    989   }
    990 
    991   bool is_schema_known = false;
    992   if (db) {
    993     std::string corruption_message;
    994     if (ReadCorruptionInfo(path_base, origin_url, &corruption_message)) {
    995       LOG(ERROR) << "IndexedDB recovering from a corrupted (and deleted) "
    996                     "database.";
    997       HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_PRIOR_CORRUPTION,
    998                           origin_url);
    999       db.reset();
   1000       *data_loss = blink::WebIDBDataLossTotal;
   1001       *data_loss_message =
   1002           "IndexedDB (database was corrupt): " + corruption_message;
   1003     } else if (!IsSchemaKnown(db.get(), &is_schema_known)) {
   1004       LOG(ERROR) << "IndexedDB had IO error checking schema, treating it as "
   1005                     "failure to open";
   1006       HistogramOpenStatus(
   1007           INDEXED_DB_BACKING_STORE_OPEN_FAILED_IO_ERROR_CHECKING_SCHEMA,
   1008           origin_url);
   1009       db.reset();
   1010       *data_loss = blink::WebIDBDataLossTotal;
   1011       *data_loss_message = "I/O error checking schema";
   1012     } else if (!is_schema_known) {
   1013       LOG(ERROR) << "IndexedDB backing store had unknown schema, treating it "
   1014                     "as failure to open";
   1015       HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_SCHEMA,
   1016                           origin_url);
   1017       db.reset();
   1018       *data_loss = blink::WebIDBDataLossTotal;
   1019       *data_loss_message = "Unknown schema";
   1020     }
   1021   }
   1022 
   1023   DCHECK(status->ok() || !is_schema_known || leveldb_env::IsIOError(*status) ||
   1024          leveldb_env::IsCorruption(*status));
   1025 
   1026   if (db) {
   1027     HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_SUCCESS, origin_url);
   1028   } else if (leveldb_env::IsIOError(*status)) {
   1029     LOG(ERROR) << "Unable to open backing store, not trying to recover - "
   1030                << status->ToString();
   1031     HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY, origin_url);
   1032     return scoped_refptr<IndexedDBBackingStore>();
   1033   } else {
   1034     DCHECK(!is_schema_known || leveldb_env::IsCorruption(*status));
   1035     LOG(ERROR) << "IndexedDB backing store open failed, attempting cleanup";
   1036     *status = leveldb_factory->DestroyLevelDB(file_path);
   1037     if (!status->ok()) {
   1038       LOG(ERROR) << "IndexedDB backing store cleanup failed";
   1039       HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_DESTROY_FAILED,
   1040                           origin_url);
   1041       return scoped_refptr<IndexedDBBackingStore>();
   1042     }
   1043 
   1044     LOG(ERROR) << "IndexedDB backing store cleanup succeeded, reopening";
   1045     leveldb_factory->OpenLevelDB(file_path, comparator.get(), &db, NULL);
   1046     if (!db) {
   1047       LOG(ERROR) << "IndexedDB backing store reopen after recovery failed";
   1048       HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_FAILED,
   1049                           origin_url);
   1050       return scoped_refptr<IndexedDBBackingStore>();
   1051     }
   1052     HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_SUCCESS,
   1053                         origin_url);
   1054   }
   1055 
   1056   if (!db) {
   1057     NOTREACHED();
   1058     HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR,
   1059                         origin_url);
   1060     return scoped_refptr<IndexedDBBackingStore>();
   1061   }
   1062 
   1063   scoped_refptr<IndexedDBBackingStore> backing_store =
   1064       Create(indexed_db_factory,
   1065              origin_url,
   1066              blob_path,
   1067              request_context,
   1068              db.Pass(),
   1069              comparator.Pass(),
   1070              task_runner,
   1071              status);
   1072 
   1073   if (clean_journal && backing_store.get() &&
   1074       !backing_store->CleanUpBlobJournal(LiveBlobJournalKey::Encode()).ok()) {
   1075     HistogramOpenStatus(
   1076         INDEXED_DB_BACKING_STORE_OPEN_FAILED_CLEANUP_JOURNAL_ERROR, origin_url);
   1077     return scoped_refptr<IndexedDBBackingStore>();
   1078   }
   1079   return backing_store;
   1080 }
   1081 
   1082 // static
   1083 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
   1084     const GURL& origin_url,
   1085     base::SequencedTaskRunner* task_runner,
   1086     leveldb::Status* status) {
   1087   DefaultLevelDBFactory leveldb_factory;
   1088   return IndexedDBBackingStore::OpenInMemory(
   1089       origin_url, &leveldb_factory, task_runner, status);
   1090 }
   1091 
   1092 // static
   1093 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
   1094     const GURL& origin_url,
   1095     LevelDBFactory* leveldb_factory,
   1096     base::SequencedTaskRunner* task_runner,
   1097     leveldb::Status* status) {
   1098   IDB_TRACE("IndexedDBBackingStore::OpenInMemory");
   1099 
   1100   scoped_ptr<LevelDBComparator> comparator(new Comparator());
   1101   scoped_ptr<LevelDBDatabase> db =
   1102       LevelDBDatabase::OpenInMemory(comparator.get());
   1103   if (!db) {
   1104     LOG(ERROR) << "LevelDBDatabase::OpenInMemory failed.";
   1105     HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED,
   1106                         origin_url);
   1107     return scoped_refptr<IndexedDBBackingStore>();
   1108   }
   1109   HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS, origin_url);
   1110 
   1111   return Create(NULL /* indexed_db_factory */,
   1112                 origin_url,
   1113                 base::FilePath(),
   1114                 NULL /* request_context */,
   1115                 db.Pass(),
   1116                 comparator.Pass(),
   1117                 task_runner,
   1118                 status);
   1119 }
   1120 
   1121 // static
   1122 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create(
   1123     IndexedDBFactory* indexed_db_factory,
   1124     const GURL& origin_url,
   1125     const base::FilePath& blob_path,
   1126     net::URLRequestContext* request_context,
   1127     scoped_ptr<LevelDBDatabase> db,
   1128     scoped_ptr<LevelDBComparator> comparator,
   1129     base::SequencedTaskRunner* task_runner,
   1130     leveldb::Status* status) {
   1131   // TODO(jsbell): Handle comparator name changes.
   1132   scoped_refptr<IndexedDBBackingStore> backing_store(
   1133       new IndexedDBBackingStore(indexed_db_factory,
   1134                                 origin_url,
   1135                                 blob_path,
   1136                                 request_context,
   1137                                 db.Pass(),
   1138                                 comparator.Pass(),
   1139                                 task_runner));
   1140   *status = backing_store->SetUpMetadata();
   1141   if (!status->ok())
   1142     return scoped_refptr<IndexedDBBackingStore>();
   1143 
   1144   return backing_store;
   1145 }
   1146 
   1147 void IndexedDBBackingStore::GrantChildProcessPermissions(int child_process_id) {
   1148   if (!child_process_ids_granted_.count(child_process_id)) {
   1149     child_process_ids_granted_.insert(child_process_id);
   1150     ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
   1151         child_process_id, blob_path_);
   1152   }
   1153 }
   1154 
   1155 std::vector<base::string16> IndexedDBBackingStore::GetDatabaseNames(
   1156     leveldb::Status* s) {
   1157   *s = leveldb::Status::OK();
   1158   std::vector<base::string16> found_names;
   1159   const std::string start_key =
   1160       DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier_);
   1161   const std::string stop_key =
   1162       DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier_);
   1163 
   1164   DCHECK(found_names.empty());
   1165 
   1166   scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
   1167   for (*s = it->Seek(start_key);
   1168        s->ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
   1169        *s = it->Next()) {
   1170     // Decode database name (in iterator key).
   1171     StringPiece slice(it->Key());
   1172     DatabaseNameKey database_name_key;
   1173     if (!DatabaseNameKey::Decode(&slice, &database_name_key) ||
   1174         !slice.empty()) {
   1175       INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_DATABASE_NAMES);
   1176       continue;
   1177     }
   1178 
   1179     // Decode database id (in iterator value).
   1180     int64 database_id = 0;
   1181     StringPiece valueSlice(it->Value());
   1182     if (!DecodeInt(&valueSlice, &database_id) || !valueSlice.empty()) {
   1183       INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_DATABASE_NAMES);
   1184       continue;
   1185     }
   1186 
   1187     // Look up version by id.
   1188     bool found = false;
   1189     int64 database_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
   1190     *s = GetVarInt(db_.get(),
   1191                    DatabaseMetaDataKey::Encode(
   1192                        database_id, DatabaseMetaDataKey::USER_INT_VERSION),
   1193                    &database_version,
   1194                    &found);
   1195     if (!s->ok() || !found) {
   1196       INTERNAL_READ_ERROR_UNTESTED(GET_DATABASE_NAMES);
   1197       continue;
   1198     }
   1199 
   1200     // Ignore stale metadata from failed initial opens.
   1201     if (database_version != IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION)
   1202       found_names.push_back(database_name_key.database_name());
   1203   }
   1204 
   1205   if (!s->ok())
   1206     INTERNAL_READ_ERROR(GET_DATABASE_NAMES);
   1207 
   1208   return found_names;
   1209 }
   1210 
   1211 leveldb::Status IndexedDBBackingStore::GetIDBDatabaseMetaData(
   1212     const base::string16& name,
   1213     IndexedDBDatabaseMetadata* metadata,
   1214     bool* found) {
   1215   const std::string key = DatabaseNameKey::Encode(origin_identifier_, name);
   1216   *found = false;
   1217 
   1218   leveldb::Status s = GetInt(db_.get(), key, &metadata->id, found);
   1219   if (!s.ok()) {
   1220     INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA);
   1221     return s;
   1222   }
   1223   if (!*found)
   1224     return leveldb::Status::OK();
   1225 
   1226   s = GetString(db_.get(),
   1227                 DatabaseMetaDataKey::Encode(metadata->id,
   1228                                             DatabaseMetaDataKey::USER_VERSION),
   1229                 &metadata->version,
   1230                 found);
   1231   if (!s.ok()) {
   1232     INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
   1233     return s;
   1234   }
   1235   if (!*found) {
   1236     INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
   1237     return InternalInconsistencyStatus();
   1238   }
   1239 
   1240   s = GetVarInt(db_.get(),
   1241                 DatabaseMetaDataKey::Encode(
   1242                     metadata->id, DatabaseMetaDataKey::USER_INT_VERSION),
   1243                 &metadata->int_version,
   1244                 found);
   1245   if (!s.ok()) {
   1246     INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
   1247     return s;
   1248   }
   1249   if (!*found) {
   1250     INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
   1251     return InternalInconsistencyStatus();
   1252   }
   1253 
   1254   if (metadata->int_version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION)
   1255     metadata->int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
   1256 
   1257   s = GetMaxObjectStoreId(
   1258       db_.get(), metadata->id, &metadata->max_object_store_id);
   1259   if (!s.ok()) {
   1260     INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
   1261   }
   1262 
   1263   // We don't cache this, we just check it if it's there.
   1264   int64 blob_key_generator_current_number =
   1265       DatabaseMetaDataKey::kInvalidBlobKey;
   1266 
   1267   s = GetVarInt(
   1268       db_.get(),
   1269       DatabaseMetaDataKey::Encode(
   1270           metadata->id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER),
   1271       &blob_key_generator_current_number,
   1272       found);
   1273   if (!s.ok()) {
   1274     INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
   1275     return s;
   1276   }
   1277   if (!*found) {
   1278     // This database predates blob support.
   1279     *found = true;
   1280   } else if (!DatabaseMetaDataKey::IsValidBlobKey(
   1281                  blob_key_generator_current_number)) {
   1282     INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
   1283     return InternalInconsistencyStatus();
   1284   }
   1285 
   1286   return s;
   1287 }
   1288 
   1289 WARN_UNUSED_RESULT static leveldb::Status GetNewDatabaseId(
   1290     LevelDBTransaction* transaction,
   1291     int64* new_id) {
   1292   *new_id = -1;
   1293   int64 max_database_id = -1;
   1294   bool found = false;
   1295   leveldb::Status s =
   1296       GetInt(transaction, MaxDatabaseIdKey::Encode(), &max_database_id, &found);
   1297   if (!s.ok()) {
   1298     INTERNAL_READ_ERROR_UNTESTED(GET_NEW_DATABASE_ID);
   1299     return s;
   1300   }
   1301   if (!found)
   1302     max_database_id = 0;
   1303 
   1304   DCHECK_GE(max_database_id, 0);
   1305 
   1306   int64 database_id = max_database_id + 1;
   1307   PutInt(transaction, MaxDatabaseIdKey::Encode(), database_id);
   1308   *new_id = database_id;
   1309   return leveldb::Status::OK();
   1310 }
   1311 
   1312 leveldb::Status IndexedDBBackingStore::CreateIDBDatabaseMetaData(
   1313     const base::string16& name,
   1314     const base::string16& version,
   1315     int64 int_version,
   1316     int64* row_id) {
   1317   // TODO(jsbell): Don't persist metadata if open fails. http://crbug.com/395472
   1318   scoped_refptr<LevelDBTransaction> transaction =
   1319       IndexedDBClassFactory::Get()->CreateLevelDBTransaction(db_.get());
   1320 
   1321   leveldb::Status s = GetNewDatabaseId(transaction.get(), row_id);
   1322   if (!s.ok())
   1323     return s;
   1324   DCHECK_GE(*row_id, 0);
   1325 
   1326   if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION)
   1327     int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
   1328 
   1329   PutInt(transaction.get(),
   1330          DatabaseNameKey::Encode(origin_identifier_, name),
   1331          *row_id);
   1332   PutString(
   1333       transaction.get(),
   1334       DatabaseMetaDataKey::Encode(*row_id, DatabaseMetaDataKey::USER_VERSION),
   1335       version);
   1336   PutVarInt(transaction.get(),
   1337             DatabaseMetaDataKey::Encode(*row_id,
   1338                                         DatabaseMetaDataKey::USER_INT_VERSION),
   1339             int_version);
   1340   PutVarInt(
   1341       transaction.get(),
   1342       DatabaseMetaDataKey::Encode(
   1343           *row_id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER),
   1344       DatabaseMetaDataKey::kBlobKeyGeneratorInitialNumber);
   1345 
   1346   s = transaction->Commit();
   1347   if (!s.ok())
   1348     INTERNAL_WRITE_ERROR_UNTESTED(CREATE_IDBDATABASE_METADATA);
   1349   return s;
   1350 }
   1351 
   1352 bool IndexedDBBackingStore::UpdateIDBDatabaseIntVersion(
   1353     IndexedDBBackingStore::Transaction* transaction,
   1354     int64 row_id,
   1355     int64 int_version) {
   1356   if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION)
   1357     int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
   1358   DCHECK_GE(int_version, 0) << "int_version was " << int_version;
   1359   PutVarInt(transaction->transaction(),
   1360             DatabaseMetaDataKey::Encode(row_id,
   1361                                         DatabaseMetaDataKey::USER_INT_VERSION),
   1362             int_version);
   1363   return true;
   1364 }
   1365 
   1366 // If you're deleting a range that contains user keys that have blob info, this
   1367 // won't clean up the blobs.
   1368 static leveldb::Status DeleteRangeBasic(LevelDBTransaction* transaction,
   1369                                         const std::string& begin,
   1370                                         const std::string& end,
   1371                                         bool upper_open) {
   1372   scoped_ptr<LevelDBIterator> it = transaction->CreateIterator();
   1373   leveldb::Status s;
   1374   for (s = it->Seek(begin); s.ok() && it->IsValid() &&
   1375                                 (upper_open ? CompareKeys(it->Key(), end) < 0
   1376                                             : CompareKeys(it->Key(), end) <= 0);
   1377        s = it->Next())
   1378     transaction->Remove(it->Key());
   1379   return s;
   1380 }
   1381 
   1382 static leveldb::Status DeleteBlobsInRange(
   1383     IndexedDBBackingStore::Transaction* transaction,
   1384     int64 database_id,
   1385     int64 object_store_id,
   1386     const std::string& start_key,
   1387     const std::string& end_key,
   1388     bool upper_open) {
   1389   scoped_ptr<LevelDBIterator> it = transaction->transaction()->CreateIterator();
   1390   leveldb::Status s = it->Seek(start_key);
   1391   for (; s.ok() && it->IsValid() &&
   1392              (upper_open ? CompareKeys(it->Key(), end_key) < 0
   1393                          : CompareKeys(it->Key(), end_key) <= 0);
   1394        s = it->Next()) {
   1395     StringPiece key_piece(it->Key());
   1396     std::string user_key =
   1397         BlobEntryKey::ReencodeToObjectStoreDataKey(&key_piece);
   1398     if (!user_key.size()) {
   1399       INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
   1400       return InternalInconsistencyStatus();
   1401     }
   1402     transaction->PutBlobInfo(
   1403         database_id, object_store_id, user_key, NULL, NULL);
   1404   }
   1405   return s;
   1406 }
   1407 
   1408 static leveldb::Status DeleteBlobsInObjectStore(
   1409     IndexedDBBackingStore::Transaction* transaction,
   1410     int64 database_id,
   1411     int64 object_store_id) {
   1412   std::string start_key, stop_key;
   1413   start_key =
   1414       BlobEntryKey::EncodeMinKeyForObjectStore(database_id, object_store_id);
   1415   stop_key =
   1416       BlobEntryKey::EncodeStopKeyForObjectStore(database_id, object_store_id);
   1417   return DeleteBlobsInRange(
   1418       transaction, database_id, object_store_id, start_key, stop_key, true);
   1419 }
   1420 
   1421 leveldb::Status IndexedDBBackingStore::DeleteDatabase(
   1422     const base::string16& name) {
   1423   IDB_TRACE("IndexedDBBackingStore::DeleteDatabase");
   1424   scoped_ptr<LevelDBDirectTransaction> transaction =
   1425       LevelDBDirectTransaction::Create(db_.get());
   1426 
   1427   leveldb::Status s;
   1428   s = CleanUpBlobJournal(BlobJournalKey::Encode());
   1429   if (!s.ok())
   1430     return s;
   1431 
   1432   IndexedDBDatabaseMetadata metadata;
   1433   bool success = false;
   1434   s = GetIDBDatabaseMetaData(name, &metadata, &success);
   1435   if (!s.ok())
   1436     return s;
   1437   if (!success)
   1438     return leveldb::Status::OK();
   1439 
   1440   const std::string start_key = DatabaseMetaDataKey::Encode(
   1441       metadata.id, DatabaseMetaDataKey::ORIGIN_NAME);
   1442   const std::string stop_key = DatabaseMetaDataKey::Encode(
   1443       metadata.id + 1, DatabaseMetaDataKey::ORIGIN_NAME);
   1444   scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
   1445   for (s = it->Seek(start_key);
   1446        s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
   1447        s = it->Next())
   1448     transaction->Remove(it->Key());
   1449   if (!s.ok()) {
   1450     INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE);
   1451     return s;
   1452   }
   1453 
   1454   const std::string key = DatabaseNameKey::Encode(origin_identifier_, name);
   1455   transaction->Remove(key);
   1456 
   1457   bool need_cleanup = false;
   1458   if (active_blob_registry()->MarkDeletedCheckIfUsed(
   1459           metadata.id, DatabaseMetaDataKey::kAllBlobsKey)) {
   1460     s = MergeDatabaseIntoLiveBlobJournal(transaction.get(), metadata.id);
   1461     if (!s.ok())
   1462       return s;
   1463   } else {
   1464     UpdateBlobJournalWithDatabase(transaction.get(), metadata.id);
   1465     need_cleanup = true;
   1466   }
   1467 
   1468   s = transaction->Commit();
   1469   if (!s.ok()) {
   1470     INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE);
   1471     return s;
   1472   }
   1473 
   1474   if (need_cleanup)
   1475     CleanUpBlobJournal(BlobJournalKey::Encode());
   1476 
   1477   db_->Compact(start_key, stop_key);
   1478   return s;
   1479 }
   1480 
   1481 static bool CheckObjectStoreAndMetaDataType(const LevelDBIterator* it,
   1482                                             const std::string& stop_key,
   1483                                             int64 object_store_id,
   1484                                             int64 meta_data_type) {
   1485   if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0)
   1486     return false;
   1487 
   1488   StringPiece slice(it->Key());
   1489   ObjectStoreMetaDataKey meta_data_key;
   1490   bool ok =
   1491       ObjectStoreMetaDataKey::Decode(&slice, &meta_data_key) && slice.empty();
   1492   DCHECK(ok);
   1493   if (meta_data_key.ObjectStoreId() != object_store_id)
   1494     return false;
   1495   if (meta_data_key.MetaDataType() != meta_data_type)
   1496     return false;
   1497   return ok;
   1498 }
   1499 
   1500 // TODO(jsbell): This should do some error handling rather than
   1501 // plowing ahead when bad data is encountered.
   1502 leveldb::Status IndexedDBBackingStore::GetObjectStores(
   1503     int64 database_id,
   1504     IndexedDBDatabaseMetadata::ObjectStoreMap* object_stores) {
   1505   IDB_TRACE("IndexedDBBackingStore::GetObjectStores");
   1506   if (!KeyPrefix::IsValidDatabaseId(database_id))
   1507     return InvalidDBKeyStatus();
   1508   const std::string start_key =
   1509       ObjectStoreMetaDataKey::Encode(database_id, 1, 0);
   1510   const std::string stop_key =
   1511       ObjectStoreMetaDataKey::EncodeMaxKey(database_id);
   1512 
   1513   DCHECK(object_stores->empty());
   1514 
   1515   scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
   1516   leveldb::Status s = it->Seek(start_key);
   1517   while (s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0) {
   1518     StringPiece slice(it->Key());
   1519     ObjectStoreMetaDataKey meta_data_key;
   1520     bool ok =
   1521         ObjectStoreMetaDataKey::Decode(&slice, &meta_data_key) && slice.empty();
   1522     DCHECK(ok);
   1523     if (!ok || meta_data_key.MetaDataType() != ObjectStoreMetaDataKey::NAME) {
   1524       INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
   1525       // Possible stale metadata, but don't fail the load.
   1526       s = it->Next();
   1527       if (!s.ok())
   1528         break;
   1529       continue;
   1530     }
   1531 
   1532     int64 object_store_id = meta_data_key.ObjectStoreId();
   1533 
   1534     // TODO(jsbell): Do this by direct key lookup rather than iteration, to
   1535     // simplify.
   1536     base::string16 object_store_name;
   1537     {
   1538       StringPiece slice(it->Value());
   1539       if (!DecodeString(&slice, &object_store_name) || !slice.empty())
   1540         INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
   1541     }
   1542 
   1543     s = it->Next();
   1544     if (!s.ok())
   1545       break;
   1546     if (!CheckObjectStoreAndMetaDataType(it.get(),
   1547                                          stop_key,
   1548                                          object_store_id,
   1549                                          ObjectStoreMetaDataKey::KEY_PATH)) {
   1550       INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
   1551       break;
   1552     }
   1553     IndexedDBKeyPath key_path;
   1554     {
   1555       StringPiece slice(it->Value());
   1556       if (!DecodeIDBKeyPath(&slice, &key_path) || !slice.empty())
   1557         INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
   1558     }
   1559 
   1560     s = it->Next();
   1561     if (!s.ok())
   1562       break;
   1563     if (!CheckObjectStoreAndMetaDataType(
   1564              it.get(),
   1565              stop_key,
   1566              object_store_id,
   1567              ObjectStoreMetaDataKey::AUTO_INCREMENT)) {
   1568       INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
   1569       break;
   1570     }
   1571     bool auto_increment;
   1572     {
   1573       StringPiece slice(it->Value());
   1574       if (!DecodeBool(&slice, &auto_increment) || !slice.empty())
   1575         INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
   1576     }
   1577 
   1578     s = it->Next();  // Is evictable.
   1579     if (!s.ok())
   1580       break;
   1581     if (!CheckObjectStoreAndMetaDataType(it.get(),
   1582                                          stop_key,
   1583                                          object_store_id,
   1584                                          ObjectStoreMetaDataKey::EVICTABLE)) {
   1585       INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
   1586       break;
   1587     }
   1588 
   1589     s = it->Next();  // Last version.
   1590     if (!s.ok())
   1591       break;
   1592     if (!CheckObjectStoreAndMetaDataType(
   1593              it.get(),
   1594              stop_key,
   1595              object_store_id,
   1596              ObjectStoreMetaDataKey::LAST_VERSION)) {
   1597       INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
   1598       break;
   1599     }
   1600 
   1601     s = it->Next();  // Maximum index id allocated.
   1602     if (!s.ok())
   1603       break;
   1604     if (!CheckObjectStoreAndMetaDataType(
   1605              it.get(),
   1606              stop_key,
   1607              object_store_id,
   1608              ObjectStoreMetaDataKey::MAX_INDEX_ID)) {
   1609       INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
   1610       break;
   1611     }
   1612     int64 max_index_id;
   1613     {
   1614       StringPiece slice(it->Value());
   1615       if (!DecodeInt(&slice, &max_index_id) || !slice.empty())
   1616         INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
   1617     }
   1618 
   1619     s = it->Next();  // [optional] has key path (is not null)
   1620     if (!s.ok())
   1621       break;
   1622     if (CheckObjectStoreAndMetaDataType(it.get(),
   1623                                         stop_key,
   1624                                         object_store_id,
   1625                                         ObjectStoreMetaDataKey::HAS_KEY_PATH)) {
   1626       bool has_key_path;
   1627       {
   1628         StringPiece slice(it->Value());
   1629         if (!DecodeBool(&slice, &has_key_path))
   1630           INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
   1631       }
   1632       // This check accounts for two layers of legacy coding:
   1633       // (1) Initially, has_key_path was added to distinguish null vs. string.
   1634       // (2) Later, null vs. string vs. array was stored in the key_path itself.
   1635       // So this check is only relevant for string-type key_paths.
   1636       if (!has_key_path &&
   1637           (key_path.type() == blink::WebIDBKeyPathTypeString &&
   1638            !key_path.string().empty())) {
   1639         INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
   1640         break;
   1641       }
   1642       if (!has_key_path)
   1643         key_path = IndexedDBKeyPath();
   1644       s = it->Next();
   1645       if (!s.ok())
   1646         break;
   1647     }
   1648 
   1649     int64 key_generator_current_number = -1;
   1650     if (CheckObjectStoreAndMetaDataType(
   1651             it.get(),
   1652             stop_key,
   1653             object_store_id,
   1654             ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER)) {
   1655       StringPiece slice(it->Value());
   1656       if (!DecodeInt(&slice, &key_generator_current_number) || !slice.empty())
   1657         INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
   1658 
   1659       // TODO(jsbell): Return key_generator_current_number, cache in
   1660       // object store, and write lazily to backing store.  For now,
   1661       // just assert that if it was written it was valid.
   1662       DCHECK_GE(key_generator_current_number, kKeyGeneratorInitialNumber);
   1663       s = it->Next();
   1664       if (!s.ok())
   1665         break;
   1666     }
   1667 
   1668     IndexedDBObjectStoreMetadata metadata(object_store_name,
   1669                                           object_store_id,
   1670                                           key_path,
   1671                                           auto_increment,
   1672                                           max_index_id);
   1673     s = GetIndexes(database_id, object_store_id, &metadata.indexes);
   1674     if (!s.ok())
   1675       break;
   1676     (*object_stores)[object_store_id] = metadata;
   1677   }
   1678 
   1679   if (!s.ok())
   1680     INTERNAL_READ_ERROR_UNTESTED(GET_OBJECT_STORES);
   1681 
   1682   return s;
   1683 }
   1684 
   1685 WARN_UNUSED_RESULT static leveldb::Status SetMaxObjectStoreId(
   1686     LevelDBTransaction* transaction,
   1687     int64 database_id,
   1688     int64 object_store_id) {
   1689   const std::string max_object_store_id_key = DatabaseMetaDataKey::Encode(
   1690       database_id, DatabaseMetaDataKey::MAX_OBJECT_STORE_ID);
   1691   int64 max_object_store_id = -1;
   1692   leveldb::Status s = GetMaxObjectStoreId(
   1693       transaction, max_object_store_id_key, &max_object_store_id);
   1694   if (!s.ok()) {
   1695     INTERNAL_READ_ERROR_UNTESTED(SET_MAX_OBJECT_STORE_ID);
   1696     return s;
   1697   }
   1698 
   1699   if (object_store_id <= max_object_store_id) {
   1700     INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_MAX_OBJECT_STORE_ID);
   1701     return InternalInconsistencyStatus();
   1702   }
   1703   PutInt(transaction, max_object_store_id_key, object_store_id);
   1704   return s;
   1705 }
   1706 
   1707 void IndexedDBBackingStore::Compact() { db_->CompactAll(); }
   1708 
   1709 leveldb::Status IndexedDBBackingStore::CreateObjectStore(
   1710     IndexedDBBackingStore::Transaction* transaction,
   1711     int64 database_id,
   1712     int64 object_store_id,
   1713     const base::string16& name,
   1714     const IndexedDBKeyPath& key_path,
   1715     bool auto_increment) {
   1716   IDB_TRACE("IndexedDBBackingStore::CreateObjectStore");
   1717   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   1718     return InvalidDBKeyStatus();
   1719   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   1720   leveldb::Status s =
   1721       SetMaxObjectStoreId(leveldb_transaction, database_id, object_store_id);
   1722   if (!s.ok())
   1723     return s;
   1724 
   1725   const std::string name_key = ObjectStoreMetaDataKey::Encode(
   1726       database_id, object_store_id, ObjectStoreMetaDataKey::NAME);
   1727   const std::string key_path_key = ObjectStoreMetaDataKey::Encode(
   1728       database_id, object_store_id, ObjectStoreMetaDataKey::KEY_PATH);
   1729   const std::string auto_increment_key = ObjectStoreMetaDataKey::Encode(
   1730       database_id, object_store_id, ObjectStoreMetaDataKey::AUTO_INCREMENT);
   1731   const std::string evictable_key = ObjectStoreMetaDataKey::Encode(
   1732       database_id, object_store_id, ObjectStoreMetaDataKey::EVICTABLE);
   1733   const std::string last_version_key = ObjectStoreMetaDataKey::Encode(
   1734       database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION);
   1735   const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode(
   1736       database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID);
   1737   const std::string has_key_path_key = ObjectStoreMetaDataKey::Encode(
   1738       database_id, object_store_id, ObjectStoreMetaDataKey::HAS_KEY_PATH);
   1739   const std::string key_generator_current_number_key =
   1740       ObjectStoreMetaDataKey::Encode(
   1741           database_id,
   1742           object_store_id,
   1743           ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER);
   1744   const std::string names_key = ObjectStoreNamesKey::Encode(database_id, name);
   1745 
   1746   PutString(leveldb_transaction, name_key, name);
   1747   PutIDBKeyPath(leveldb_transaction, key_path_key, key_path);
   1748   PutInt(leveldb_transaction, auto_increment_key, auto_increment);
   1749   PutInt(leveldb_transaction, evictable_key, false);
   1750   PutInt(leveldb_transaction, last_version_key, 1);
   1751   PutInt(leveldb_transaction, max_index_id_key, kMinimumIndexId);
   1752   PutBool(leveldb_transaction, has_key_path_key, !key_path.IsNull());
   1753   PutInt(leveldb_transaction,
   1754          key_generator_current_number_key,
   1755          kKeyGeneratorInitialNumber);
   1756   PutInt(leveldb_transaction, names_key, object_store_id);
   1757   return s;
   1758 }
   1759 
   1760 leveldb::Status IndexedDBBackingStore::DeleteObjectStore(
   1761     IndexedDBBackingStore::Transaction* transaction,
   1762     int64 database_id,
   1763     int64 object_store_id) {
   1764   IDB_TRACE("IndexedDBBackingStore::DeleteObjectStore");
   1765   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   1766     return InvalidDBKeyStatus();
   1767   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   1768 
   1769   base::string16 object_store_name;
   1770   bool found = false;
   1771   leveldb::Status s =
   1772       GetString(leveldb_transaction,
   1773                 ObjectStoreMetaDataKey::Encode(
   1774                     database_id, object_store_id, ObjectStoreMetaDataKey::NAME),
   1775                 &object_store_name,
   1776                 &found);
   1777   if (!s.ok()) {
   1778     INTERNAL_READ_ERROR_UNTESTED(DELETE_OBJECT_STORE);
   1779     return s;
   1780   }
   1781   if (!found) {
   1782     INTERNAL_CONSISTENCY_ERROR_UNTESTED(DELETE_OBJECT_STORE);
   1783     return InternalInconsistencyStatus();
   1784   }
   1785 
   1786   s = DeleteBlobsInObjectStore(transaction, database_id, object_store_id);
   1787   if (!s.ok()) {
   1788     INTERNAL_CONSISTENCY_ERROR_UNTESTED(DELETE_OBJECT_STORE);
   1789     return s;
   1790   }
   1791 
   1792   s = DeleteRangeBasic(
   1793       leveldb_transaction,
   1794       ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0),
   1795       ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id),
   1796       true);
   1797 
   1798   if (s.ok()) {
   1799     leveldb_transaction->Remove(
   1800         ObjectStoreNamesKey::Encode(database_id, object_store_name));
   1801 
   1802     s = DeleteRangeBasic(
   1803         leveldb_transaction,
   1804         IndexFreeListKey::Encode(database_id, object_store_id, 0),
   1805         IndexFreeListKey::EncodeMaxKey(database_id, object_store_id),
   1806         true);
   1807   }
   1808 
   1809   if (s.ok()) {
   1810     s = DeleteRangeBasic(
   1811         leveldb_transaction,
   1812         IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0),
   1813         IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id),
   1814         true);
   1815   }
   1816 
   1817   if (!s.ok()) {
   1818     INTERNAL_WRITE_ERROR_UNTESTED(DELETE_OBJECT_STORE);
   1819     return s;
   1820   }
   1821 
   1822   return ClearObjectStore(transaction, database_id, object_store_id);
   1823 }
   1824 
   1825 leveldb::Status IndexedDBBackingStore::GetRecord(
   1826     IndexedDBBackingStore::Transaction* transaction,
   1827     int64 database_id,
   1828     int64 object_store_id,
   1829     const IndexedDBKey& key,
   1830     IndexedDBValue* record) {
   1831   IDB_TRACE("IndexedDBBackingStore::GetRecord");
   1832   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   1833     return InvalidDBKeyStatus();
   1834   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   1835 
   1836   const std::string leveldb_key =
   1837       ObjectStoreDataKey::Encode(database_id, object_store_id, key);
   1838   std::string data;
   1839 
   1840   record->clear();
   1841 
   1842   bool found = false;
   1843   leveldb::Status s = leveldb_transaction->Get(leveldb_key, &data, &found);
   1844   if (!s.ok()) {
   1845     INTERNAL_READ_ERROR(GET_RECORD);
   1846     return s;
   1847   }
   1848   if (!found)
   1849     return s;
   1850   if (data.empty()) {
   1851     INTERNAL_READ_ERROR_UNTESTED(GET_RECORD);
   1852     return leveldb::Status::NotFound("Record contained no data");
   1853   }
   1854 
   1855   int64 version;
   1856   StringPiece slice(data);
   1857   if (!DecodeVarInt(&slice, &version)) {
   1858     INTERNAL_READ_ERROR_UNTESTED(GET_RECORD);
   1859     return InternalInconsistencyStatus();
   1860   }
   1861 
   1862   record->bits = slice.as_string();
   1863   return transaction->GetBlobInfoForRecord(database_id, leveldb_key, record);
   1864 }
   1865 
   1866 WARN_UNUSED_RESULT static leveldb::Status GetNewVersionNumber(
   1867     LevelDBTransaction* transaction,
   1868     int64 database_id,
   1869     int64 object_store_id,
   1870     int64* new_version_number) {
   1871   const std::string last_version_key = ObjectStoreMetaDataKey::Encode(
   1872       database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION);
   1873 
   1874   *new_version_number = -1;
   1875   int64 last_version = -1;
   1876   bool found = false;
   1877   leveldb::Status s =
   1878       GetInt(transaction, last_version_key, &last_version, &found);
   1879   if (!s.ok()) {
   1880     INTERNAL_READ_ERROR_UNTESTED(GET_NEW_VERSION_NUMBER);
   1881     return s;
   1882   }
   1883   if (!found)
   1884     last_version = 0;
   1885 
   1886   DCHECK_GE(last_version, 0);
   1887 
   1888   int64 version = last_version + 1;
   1889   PutInt(transaction, last_version_key, version);
   1890 
   1891   // TODO(jsbell): Think about how we want to handle the overflow scenario.
   1892   DCHECK(version > last_version);
   1893 
   1894   *new_version_number = version;
   1895   return s;
   1896 }
   1897 
   1898 leveldb::Status IndexedDBBackingStore::PutRecord(
   1899     IndexedDBBackingStore::Transaction* transaction,
   1900     int64 database_id,
   1901     int64 object_store_id,
   1902     const IndexedDBKey& key,
   1903     IndexedDBValue* value,
   1904     ScopedVector<storage::BlobDataHandle>* handles,
   1905     RecordIdentifier* record_identifier) {
   1906   IDB_TRACE("IndexedDBBackingStore::PutRecord");
   1907   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   1908     return InvalidDBKeyStatus();
   1909   DCHECK(key.IsValid());
   1910 
   1911   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   1912   int64 version = -1;
   1913   leveldb::Status s = GetNewVersionNumber(
   1914       leveldb_transaction, database_id, object_store_id, &version);
   1915   if (!s.ok())
   1916     return s;
   1917   DCHECK_GE(version, 0);
   1918   const std::string object_store_data_key =
   1919       ObjectStoreDataKey::Encode(database_id, object_store_id, key);
   1920 
   1921   std::string v;
   1922   EncodeVarInt(version, &v);
   1923   v.append(value->bits);
   1924 
   1925   leveldb_transaction->Put(object_store_data_key, &v);
   1926   s = transaction->PutBlobInfoIfNeeded(database_id,
   1927                                        object_store_id,
   1928                                        object_store_data_key,
   1929                                        &value->blob_info,
   1930                                        handles);
   1931   if (!s.ok())
   1932     return s;
   1933   DCHECK(!handles->size());
   1934 
   1935   const std::string exists_entry_key =
   1936       ExistsEntryKey::Encode(database_id, object_store_id, key);
   1937   std::string version_encoded;
   1938   EncodeInt(version, &version_encoded);
   1939   leveldb_transaction->Put(exists_entry_key, &version_encoded);
   1940 
   1941   std::string key_encoded;
   1942   EncodeIDBKey(key, &key_encoded);
   1943   record_identifier->Reset(key_encoded, version);
   1944   return s;
   1945 }
   1946 
   1947 leveldb::Status IndexedDBBackingStore::ClearObjectStore(
   1948     IndexedDBBackingStore::Transaction* transaction,
   1949     int64 database_id,
   1950     int64 object_store_id) {
   1951   IDB_TRACE("IndexedDBBackingStore::ClearObjectStore");
   1952   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   1953     return InvalidDBKeyStatus();
   1954   const std::string start_key =
   1955       KeyPrefix(database_id, object_store_id).Encode();
   1956   const std::string stop_key =
   1957       KeyPrefix(database_id, object_store_id + 1).Encode();
   1958 
   1959   leveldb::Status s =
   1960       DeleteRangeBasic(transaction->transaction(), start_key, stop_key, true);
   1961   if (!s.ok()) {
   1962     INTERNAL_WRITE_ERROR(CLEAR_OBJECT_STORE);
   1963     return s;
   1964   }
   1965   return DeleteBlobsInObjectStore(transaction, database_id, object_store_id);
   1966 }
   1967 
   1968 leveldb::Status IndexedDBBackingStore::DeleteRecord(
   1969     IndexedDBBackingStore::Transaction* transaction,
   1970     int64 database_id,
   1971     int64 object_store_id,
   1972     const RecordIdentifier& record_identifier) {
   1973   IDB_TRACE("IndexedDBBackingStore::DeleteRecord");
   1974   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   1975     return InvalidDBKeyStatus();
   1976   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   1977 
   1978   const std::string object_store_data_key = ObjectStoreDataKey::Encode(
   1979       database_id, object_store_id, record_identifier.primary_key());
   1980   leveldb_transaction->Remove(object_store_data_key);
   1981   leveldb::Status s = transaction->PutBlobInfoIfNeeded(
   1982       database_id, object_store_id, object_store_data_key, NULL, NULL);
   1983   if (!s.ok())
   1984     return s;
   1985 
   1986   const std::string exists_entry_key = ExistsEntryKey::Encode(
   1987       database_id, object_store_id, record_identifier.primary_key());
   1988   leveldb_transaction->Remove(exists_entry_key);
   1989   return leveldb::Status::OK();
   1990 }
   1991 
   1992 leveldb::Status IndexedDBBackingStore::DeleteRange(
   1993     IndexedDBBackingStore::Transaction* transaction,
   1994     int64 database_id,
   1995     int64 object_store_id,
   1996     const IndexedDBKeyRange& key_range) {
   1997   leveldb::Status s;
   1998   scoped_ptr<IndexedDBBackingStore::Cursor> start_cursor =
   1999       OpenObjectStoreCursor(transaction,
   2000                             database_id,
   2001                             object_store_id,
   2002                             key_range,
   2003                             blink::WebIDBCursorDirectionNext,
   2004                             &s);
   2005   if (!s.ok())
   2006     return s;
   2007   if (!start_cursor)
   2008     return leveldb::Status::OK();  // Empty range == delete success.
   2009 
   2010   scoped_ptr<IndexedDBBackingStore::Cursor> end_cursor =
   2011       OpenObjectStoreCursor(transaction,
   2012                             database_id,
   2013                             object_store_id,
   2014                             key_range,
   2015                             blink::WebIDBCursorDirectionPrev,
   2016                             &s);
   2017 
   2018   if (!s.ok())
   2019     return s;
   2020   if (!end_cursor)
   2021     return leveldb::Status::OK();  // Empty range == delete success.
   2022 
   2023   BlobEntryKey start_blob_key, end_blob_key;
   2024 
   2025   std::string start_key = ObjectStoreDataKey::Encode(
   2026       database_id, object_store_id, start_cursor->key());
   2027   base::StringPiece start_key_piece(start_key);
   2028   if (!BlobEntryKey::FromObjectStoreDataKey(&start_key_piece, &start_blob_key))
   2029     return InternalInconsistencyStatus();
   2030   std::string stop_key = ObjectStoreDataKey::Encode(
   2031       database_id, object_store_id, end_cursor->key());
   2032   base::StringPiece stop_key_piece(stop_key);
   2033   if (!BlobEntryKey::FromObjectStoreDataKey(&stop_key_piece, &end_blob_key))
   2034     return InternalInconsistencyStatus();
   2035 
   2036   s = DeleteBlobsInRange(transaction,
   2037                          database_id,
   2038                          object_store_id,
   2039                          start_blob_key.Encode(),
   2040                          end_blob_key.Encode(),
   2041                          false);
   2042   if (!s.ok())
   2043     return s;
   2044   s = DeleteRangeBasic(transaction->transaction(), start_key, stop_key, false);
   2045   if (!s.ok())
   2046     return s;
   2047   start_key =
   2048       ExistsEntryKey::Encode(database_id, object_store_id, start_cursor->key());
   2049   stop_key =
   2050       ExistsEntryKey::Encode(database_id, object_store_id, end_cursor->key());
   2051   return DeleteRangeBasic(
   2052       transaction->transaction(), start_key, stop_key, false);
   2053 }
   2054 
   2055 leveldb::Status IndexedDBBackingStore::GetKeyGeneratorCurrentNumber(
   2056     IndexedDBBackingStore::Transaction* transaction,
   2057     int64 database_id,
   2058     int64 object_store_id,
   2059     int64* key_generator_current_number) {
   2060   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   2061     return InvalidDBKeyStatus();
   2062   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   2063 
   2064   const std::string key_generator_current_number_key =
   2065       ObjectStoreMetaDataKey::Encode(
   2066           database_id,
   2067           object_store_id,
   2068           ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER);
   2069 
   2070   *key_generator_current_number = -1;
   2071   std::string data;
   2072 
   2073   bool found = false;
   2074   leveldb::Status s =
   2075       leveldb_transaction->Get(key_generator_current_number_key, &data, &found);
   2076   if (!s.ok()) {
   2077     INTERNAL_READ_ERROR_UNTESTED(GET_KEY_GENERATOR_CURRENT_NUMBER);
   2078     return s;
   2079   }
   2080   if (found && !data.empty()) {
   2081     StringPiece slice(data);
   2082     if (!DecodeInt(&slice, key_generator_current_number) || !slice.empty()) {
   2083       INTERNAL_READ_ERROR_UNTESTED(GET_KEY_GENERATOR_CURRENT_NUMBER);
   2084       return InternalInconsistencyStatus();
   2085     }
   2086     return s;
   2087   }
   2088 
   2089   // Previously, the key generator state was not stored explicitly
   2090   // but derived from the maximum numeric key present in existing
   2091   // data. This violates the spec as the data may be cleared but the
   2092   // key generator state must be preserved.
   2093   // TODO(jsbell): Fix this for all stores on database open?
   2094   const std::string start_key =
   2095       ObjectStoreDataKey::Encode(database_id, object_store_id, MinIDBKey());
   2096   const std::string stop_key =
   2097       ObjectStoreDataKey::Encode(database_id, object_store_id, MaxIDBKey());
   2098 
   2099   scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator();
   2100   int64 max_numeric_key = 0;
   2101 
   2102   for (s = it->Seek(start_key);
   2103        s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
   2104        s = it->Next()) {
   2105     StringPiece slice(it->Key());
   2106     ObjectStoreDataKey data_key;
   2107     if (!ObjectStoreDataKey::Decode(&slice, &data_key) || !slice.empty()) {
   2108       INTERNAL_READ_ERROR_UNTESTED(GET_KEY_GENERATOR_CURRENT_NUMBER);
   2109       return InternalInconsistencyStatus();
   2110     }
   2111     scoped_ptr<IndexedDBKey> user_key = data_key.user_key();
   2112     if (user_key->type() == blink::WebIDBKeyTypeNumber) {
   2113       int64 n = static_cast<int64>(user_key->number());
   2114       if (n > max_numeric_key)
   2115         max_numeric_key = n;
   2116     }
   2117   }
   2118 
   2119   if (s.ok())
   2120     *key_generator_current_number = max_numeric_key + 1;
   2121   else
   2122     INTERNAL_READ_ERROR_UNTESTED(GET_KEY_GENERATOR_CURRENT_NUMBER);
   2123 
   2124   return s;
   2125 }
   2126 
   2127 leveldb::Status IndexedDBBackingStore::MaybeUpdateKeyGeneratorCurrentNumber(
   2128     IndexedDBBackingStore::Transaction* transaction,
   2129     int64 database_id,
   2130     int64 object_store_id,
   2131     int64 new_number,
   2132     bool check_current) {
   2133   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   2134     return InvalidDBKeyStatus();
   2135 
   2136   if (check_current) {
   2137     int64 current_number;
   2138     leveldb::Status s = GetKeyGeneratorCurrentNumber(
   2139         transaction, database_id, object_store_id, &current_number);
   2140     if (!s.ok())
   2141       return s;
   2142     if (new_number <= current_number)
   2143       return s;
   2144   }
   2145 
   2146   const std::string key_generator_current_number_key =
   2147       ObjectStoreMetaDataKey::Encode(
   2148           database_id,
   2149           object_store_id,
   2150           ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER);
   2151   PutInt(
   2152       transaction->transaction(), key_generator_current_number_key, new_number);
   2153   return leveldb::Status::OK();
   2154 }
   2155 
   2156 leveldb::Status IndexedDBBackingStore::KeyExistsInObjectStore(
   2157     IndexedDBBackingStore::Transaction* transaction,
   2158     int64 database_id,
   2159     int64 object_store_id,
   2160     const IndexedDBKey& key,
   2161     RecordIdentifier* found_record_identifier,
   2162     bool* found) {
   2163   IDB_TRACE("IndexedDBBackingStore::KeyExistsInObjectStore");
   2164   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   2165     return InvalidDBKeyStatus();
   2166   *found = false;
   2167   const std::string leveldb_key =
   2168       ObjectStoreDataKey::Encode(database_id, object_store_id, key);
   2169   std::string data;
   2170 
   2171   leveldb::Status s =
   2172       transaction->transaction()->Get(leveldb_key, &data, found);
   2173   if (!s.ok()) {
   2174     INTERNAL_READ_ERROR_UNTESTED(KEY_EXISTS_IN_OBJECT_STORE);
   2175     return s;
   2176   }
   2177   if (!*found)
   2178     return leveldb::Status::OK();
   2179   if (!data.size()) {
   2180     INTERNAL_READ_ERROR_UNTESTED(KEY_EXISTS_IN_OBJECT_STORE);
   2181     return InternalInconsistencyStatus();
   2182   }
   2183 
   2184   int64 version;
   2185   StringPiece slice(data);
   2186   if (!DecodeVarInt(&slice, &version))
   2187     return InternalInconsistencyStatus();
   2188 
   2189   std::string encoded_key;
   2190   EncodeIDBKey(key, &encoded_key);
   2191   found_record_identifier->Reset(encoded_key, version);
   2192   return s;
   2193 }
   2194 
   2195 class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl
   2196     : public IndexedDBBackingStore::Transaction::ChainedBlobWriter {
   2197  public:
   2198   typedef IndexedDBBackingStore::Transaction::WriteDescriptorVec
   2199       WriteDescriptorVec;
   2200   ChainedBlobWriterImpl(
   2201       int64 database_id,
   2202       IndexedDBBackingStore* backing_store,
   2203       WriteDescriptorVec* blobs,
   2204       scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback)
   2205       : waiting_for_callback_(false),
   2206         database_id_(database_id),
   2207         backing_store_(backing_store),
   2208         callback_(callback),
   2209         aborted_(false) {
   2210     blobs_.swap(*blobs);
   2211     iter_ = blobs_.begin();
   2212     backing_store->task_runner()->PostTask(
   2213         FROM_HERE, base::Bind(&ChainedBlobWriterImpl::WriteNextFile, this));
   2214   }
   2215 
   2216   virtual void set_delegate(scoped_ptr<FileWriterDelegate> delegate) OVERRIDE {
   2217     delegate_.reset(delegate.release());
   2218   }
   2219 
   2220   virtual void ReportWriteCompletion(bool succeeded,
   2221                                      int64 bytes_written) OVERRIDE {
   2222     DCHECK(waiting_for_callback_);
   2223     DCHECK(!succeeded || bytes_written >= 0);
   2224     waiting_for_callback_ = false;
   2225     if (delegate_.get())  // Only present for Blob, not File.
   2226       content::BrowserThread::DeleteSoon(
   2227           content::BrowserThread::IO, FROM_HERE, delegate_.release());
   2228     if (aborted_) {
   2229       self_ref_ = NULL;
   2230       return;
   2231     }
   2232     if (iter_->size() != -1 && iter_->size() != bytes_written)
   2233       succeeded = false;
   2234     if (succeeded) {
   2235       ++iter_;
   2236       WriteNextFile();
   2237     } else {
   2238       callback_->Run(false);
   2239     }
   2240   }
   2241 
   2242   virtual void Abort() OVERRIDE {
   2243     if (!waiting_for_callback_)
   2244       return;
   2245     self_ref_ = this;
   2246     aborted_ = true;
   2247   }
   2248 
   2249  private:
   2250   virtual ~ChainedBlobWriterImpl() {}
   2251 
   2252   void WriteNextFile() {
   2253     DCHECK(!waiting_for_callback_);
   2254     DCHECK(!aborted_);
   2255     if (iter_ == blobs_.end()) {
   2256       DCHECK(!self_ref_.get());
   2257       callback_->Run(true);
   2258       return;
   2259     } else {
   2260       if (!backing_store_->WriteBlobFile(database_id_, *iter_, this)) {
   2261         callback_->Run(false);
   2262         return;
   2263       }
   2264       waiting_for_callback_ = true;
   2265     }
   2266   }
   2267 
   2268   bool waiting_for_callback_;
   2269   scoped_refptr<ChainedBlobWriterImpl> self_ref_;
   2270   WriteDescriptorVec blobs_;
   2271   WriteDescriptorVec::const_iterator iter_;
   2272   int64 database_id_;
   2273   IndexedDBBackingStore* backing_store_;
   2274   scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback_;
   2275   scoped_ptr<FileWriterDelegate> delegate_;
   2276   bool aborted_;
   2277 
   2278   DISALLOW_COPY_AND_ASSIGN(ChainedBlobWriterImpl);
   2279 };
   2280 
   2281 class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback,
   2282                           public base::RefCountedThreadSafe<LocalWriteClosure> {
   2283  public:
   2284   LocalWriteClosure(IndexedDBBackingStore::Transaction::ChainedBlobWriter*
   2285                         chained_blob_writer,
   2286                     base::SequencedTaskRunner* task_runner)
   2287       : chained_blob_writer_(chained_blob_writer),
   2288         task_runner_(task_runner),
   2289         bytes_written_(0) {}
   2290 
   2291   void Run(base::File::Error rv,
   2292            int64 bytes,
   2293            FileWriterDelegate::WriteProgressStatus write_status) {
   2294     DCHECK_GE(bytes, 0);
   2295     bytes_written_ += bytes;
   2296     if (write_status == FileWriterDelegate::SUCCESS_IO_PENDING)
   2297       return;  // We don't care about progress events.
   2298     if (rv == base::File::FILE_OK) {
   2299       DCHECK_EQ(write_status, FileWriterDelegate::SUCCESS_COMPLETED);
   2300     } else {
   2301       DCHECK(write_status == FileWriterDelegate::ERROR_WRITE_STARTED ||
   2302              write_status == FileWriterDelegate::ERROR_WRITE_NOT_STARTED);
   2303     }
   2304     task_runner_->PostTask(
   2305         FROM_HERE,
   2306         base::Bind(&IndexedDBBackingStore::Transaction::ChainedBlobWriter::
   2307                        ReportWriteCompletion,
   2308                    chained_blob_writer_,
   2309                    write_status == FileWriterDelegate::SUCCESS_COMPLETED,
   2310                    bytes_written_));
   2311   }
   2312 
   2313   void writeBlobToFileOnIOThread(const FilePath& file_path,
   2314                                  const GURL& blob_url,
   2315                                  net::URLRequestContext* request_context) {
   2316     DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
   2317     scoped_ptr<storage::FileStreamWriter> writer(
   2318         storage::FileStreamWriter::CreateForLocalFile(
   2319             task_runner_.get(),
   2320             file_path,
   2321             0,
   2322             storage::FileStreamWriter::CREATE_NEW_FILE));
   2323     scoped_ptr<FileWriterDelegate> delegate(
   2324         new FileWriterDelegate(writer.Pass(),
   2325                                FileWriterDelegate::FLUSH_ON_COMPLETION));
   2326 
   2327     DCHECK(blob_url.is_valid());
   2328     scoped_ptr<net::URLRequest> blob_request(request_context->CreateRequest(
   2329         blob_url, net::DEFAULT_PRIORITY, delegate.get(), NULL));
   2330 
   2331     delegate->Start(blob_request.Pass(),
   2332                     base::Bind(&LocalWriteClosure::Run, this));
   2333     chained_blob_writer_->set_delegate(delegate.Pass());
   2334   }
   2335 
   2336  private:
   2337   virtual ~LocalWriteClosure() {
   2338     // Make sure the last reference to a ChainedBlobWriter is released (and
   2339     // deleted) on the IDB thread since it owns a transaction which has thread
   2340     // affinity.
   2341     IndexedDBBackingStore::Transaction::ChainedBlobWriter* raw_tmp =
   2342         chained_blob_writer_.get();
   2343     raw_tmp->AddRef();
   2344     chained_blob_writer_ = NULL;
   2345     task_runner_->ReleaseSoon(FROM_HERE, raw_tmp);
   2346   }
   2347   friend class base::RefCountedThreadSafe<LocalWriteClosure>;
   2348 
   2349   scoped_refptr<IndexedDBBackingStore::Transaction::ChainedBlobWriter>
   2350       chained_blob_writer_;
   2351   scoped_refptr<base::SequencedTaskRunner> task_runner_;
   2352   int64 bytes_written_;
   2353 
   2354   DISALLOW_COPY_AND_ASSIGN(LocalWriteClosure);
   2355 };
   2356 
   2357 bool IndexedDBBackingStore::WriteBlobFile(
   2358     int64 database_id,
   2359     const Transaction::WriteDescriptor& descriptor,
   2360     Transaction::ChainedBlobWriter* chained_blob_writer) {
   2361 
   2362   if (!MakeIDBBlobDirectory(blob_path_, database_id, descriptor.key()))
   2363     return false;
   2364 
   2365   FilePath path = GetBlobFileName(database_id, descriptor.key());
   2366 
   2367   if (descriptor.is_file()) {
   2368     DCHECK(!descriptor.file_path().empty());
   2369     if (!base::CopyFile(descriptor.file_path(), path))
   2370       return false;
   2371 
   2372     base::File::Info info;
   2373     if (base::GetFileInfo(descriptor.file_path(), &info)) {
   2374       if (descriptor.size() != -1) {
   2375         if (descriptor.size() != info.size)
   2376           return false;
   2377         // The round-trip can be lossy; round to nearest millisecond.
   2378         int64 delta = (descriptor.last_modified() -
   2379             info.last_modified).InMilliseconds();
   2380         if (std::abs(delta) > 1)
   2381           return false;
   2382       }
   2383       if (!base::TouchFile(path, info.last_accessed, info.last_modified)) {
   2384         // TODO(ericu): Complain quietly; timestamp's probably not vital.
   2385       }
   2386     } else {
   2387       // TODO(ericu): Complain quietly; timestamp's probably not vital.
   2388     }
   2389 
   2390     task_runner_->PostTask(
   2391         FROM_HERE,
   2392         base::Bind(&Transaction::ChainedBlobWriter::ReportWriteCompletion,
   2393                    chained_blob_writer,
   2394                    true,
   2395                    info.size));
   2396   } else {
   2397     DCHECK(descriptor.url().is_valid());
   2398     scoped_refptr<LocalWriteClosure> write_closure(
   2399         new LocalWriteClosure(chained_blob_writer, task_runner_.get()));
   2400     content::BrowserThread::PostTask(
   2401         content::BrowserThread::IO,
   2402         FROM_HERE,
   2403         base::Bind(&LocalWriteClosure::writeBlobToFileOnIOThread,
   2404                    write_closure.get(),
   2405                    path,
   2406                    descriptor.url(),
   2407                    request_context_));
   2408   }
   2409   return true;
   2410 }
   2411 
   2412 void IndexedDBBackingStore::ReportBlobUnused(int64 database_id,
   2413                                              int64 blob_key) {
   2414   DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
   2415   bool all_blobs = blob_key == DatabaseMetaDataKey::kAllBlobsKey;
   2416   DCHECK(all_blobs || DatabaseMetaDataKey::IsValidBlobKey(blob_key));
   2417   scoped_refptr<LevelDBTransaction> transaction =
   2418       IndexedDBClassFactory::Get()->CreateLevelDBTransaction(db_.get());
   2419 
   2420   std::string live_blob_key = LiveBlobJournalKey::Encode();
   2421   BlobJournalType live_blob_journal;
   2422   if (!GetBlobJournal(live_blob_key, transaction.get(), &live_blob_journal)
   2423            .ok())
   2424     return;
   2425   DCHECK(live_blob_journal.size());
   2426 
   2427   std::string primary_key = BlobJournalKey::Encode();
   2428   BlobJournalType primary_journal;
   2429   if (!GetBlobJournal(primary_key, transaction.get(), &primary_journal).ok())
   2430     return;
   2431 
   2432   // There are several cases to handle.  If blob_key is kAllBlobsKey, we want to
   2433   // remove all entries with database_id from the live_blob journal and add only
   2434   // kAllBlobsKey to the primary journal.  Otherwise if IsValidBlobKey(blob_key)
   2435   // and we hit kAllBlobsKey for the right database_id in the journal, we leave
   2436   // the kAllBlobsKey entry in the live_blob journal but add the specific blob
   2437   // to the primary.  Otherwise if IsValidBlobKey(blob_key) and we find a
   2438   // matching (database_id, blob_key) tuple, we should move it to the primary
   2439   // journal.
   2440   BlobJournalType new_live_blob_journal;
   2441   for (BlobJournalType::iterator journal_iter = live_blob_journal.begin();
   2442        journal_iter != live_blob_journal.end();
   2443        ++journal_iter) {
   2444     int64 current_database_id = journal_iter->first;
   2445     int64 current_blob_key = journal_iter->second;
   2446     bool current_all_blobs =
   2447         current_blob_key == DatabaseMetaDataKey::kAllBlobsKey;
   2448     DCHECK(KeyPrefix::IsValidDatabaseId(current_database_id) ||
   2449            current_all_blobs);
   2450     if (current_database_id == database_id &&
   2451         (all_blobs || current_all_blobs || blob_key == current_blob_key)) {
   2452       if (!all_blobs) {
   2453         primary_journal.push_back(
   2454             std::make_pair(database_id, current_blob_key));
   2455         if (current_all_blobs)
   2456           new_live_blob_journal.push_back(*journal_iter);
   2457         new_live_blob_journal.insert(new_live_blob_journal.end(),
   2458                                      ++journal_iter,
   2459                                      live_blob_journal.end());  // All the rest.
   2460         break;
   2461       }
   2462     } else {
   2463       new_live_blob_journal.push_back(*journal_iter);
   2464     }
   2465   }
   2466   if (all_blobs) {
   2467     primary_journal.push_back(
   2468         std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey));
   2469   }
   2470   UpdatePrimaryJournalWithBlobList(transaction.get(), primary_journal);
   2471   UpdateLiveBlobJournalWithBlobList(transaction.get(), new_live_blob_journal);
   2472   transaction->Commit();
   2473   // We could just do the deletions/cleaning here, but if there are a lot of
   2474   // blobs about to be garbage collected, it'd be better to wait and do them all
   2475   // at once.
   2476   StartJournalCleaningTimer();
   2477 }
   2478 
   2479 // The this reference is a raw pointer that's declared Unretained inside the
   2480 // timer code, so this won't confuse IndexedDBFactory's check for
   2481 // HasLastBackingStoreReference.  It's safe because if the backing store is
   2482 // deleted, the timer will automatically be canceled on destruction.
   2483 void IndexedDBBackingStore::StartJournalCleaningTimer() {
   2484   journal_cleaning_timer_.Start(
   2485       FROM_HERE,
   2486       base::TimeDelta::FromSeconds(5),
   2487       this,
   2488       &IndexedDBBackingStore::CleanPrimaryJournalIgnoreReturn);
   2489 }
   2490 
   2491 // This assumes a file path of dbId/second-to-LSB-of-counter/counter.
   2492 FilePath IndexedDBBackingStore::GetBlobFileName(int64 database_id, int64 key) {
   2493   return GetBlobFileNameForKey(blob_path_, database_id, key);
   2494 }
   2495 
   2496 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it,
   2497                                      const std::string& stop_key,
   2498                                      int64 index_id,
   2499                                      unsigned char meta_data_type) {
   2500   if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0)
   2501     return false;
   2502 
   2503   StringPiece slice(it->Key());
   2504   IndexMetaDataKey meta_data_key;
   2505   bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key);
   2506   DCHECK(ok);
   2507   if (meta_data_key.IndexId() != index_id)
   2508     return false;
   2509   if (meta_data_key.meta_data_type() != meta_data_type)
   2510     return false;
   2511   return true;
   2512 }
   2513 
   2514 // TODO(jsbell): This should do some error handling rather than plowing ahead
   2515 // when bad data is encountered.
   2516 leveldb::Status IndexedDBBackingStore::GetIndexes(
   2517     int64 database_id,
   2518     int64 object_store_id,
   2519     IndexedDBObjectStoreMetadata::IndexMap* indexes) {
   2520   IDB_TRACE("IndexedDBBackingStore::GetIndexes");
   2521   if (!KeyPrefix::ValidIds(database_id, object_store_id))
   2522     return InvalidDBKeyStatus();
   2523   const std::string start_key =
   2524       IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0);
   2525   const std::string stop_key =
   2526       IndexMetaDataKey::Encode(database_id, object_store_id + 1, 0, 0);
   2527 
   2528   DCHECK(indexes->empty());
   2529 
   2530   scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
   2531   leveldb::Status s = it->Seek(start_key);
   2532   while (s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0) {
   2533     StringPiece slice(it->Key());
   2534     IndexMetaDataKey meta_data_key;
   2535     bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key);
   2536     DCHECK(ok);
   2537     if (meta_data_key.meta_data_type() != IndexMetaDataKey::NAME) {
   2538       INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
   2539       // Possible stale metadata due to http://webkit.org/b/85557 but don't fail
   2540       // the load.
   2541       s = it->Next();
   2542       if (!s.ok())
   2543         break;
   2544       continue;
   2545     }
   2546 
   2547     // TODO(jsbell): Do this by direct key lookup rather than iteration, to
   2548     // simplify.
   2549     int64 index_id = meta_data_key.IndexId();
   2550     base::string16 index_name;
   2551     {
   2552       StringPiece slice(it->Value());
   2553       if (!DecodeString(&slice, &index_name) || !slice.empty())
   2554         INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
   2555     }
   2556 
   2557     s = it->Next();  // unique flag
   2558     if (!s.ok())
   2559       break;
   2560     if (!CheckIndexAndMetaDataKey(
   2561              it.get(), stop_key, index_id, IndexMetaDataKey::UNIQUE)) {
   2562       INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
   2563       break;
   2564     }
   2565     bool index_unique;
   2566     {
   2567       StringPiece slice(it->Value());
   2568       if (!DecodeBool(&slice, &index_unique) || !slice.empty())
   2569         INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
   2570     }
   2571 
   2572     s = it->Next();  // key_path
   2573     if (!s.ok())
   2574       break;
   2575     if (!CheckIndexAndMetaDataKey(
   2576              it.get(), stop_key, index_id, IndexMetaDataKey::KEY_PATH)) {
   2577       INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
   2578       break;
   2579     }
   2580     IndexedDBKeyPath key_path;
   2581     {
   2582       StringPiece slice(it->Value());
   2583       if (!DecodeIDBKeyPath(&slice, &key_path) || !slice.empty())
   2584         INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
   2585     }
   2586 
   2587     s = it->Next();  // [optional] multi_entry flag
   2588     if (!s.ok())
   2589       break;
   2590     bool index_multi_entry = false;
   2591     if (CheckIndexAndMetaDataKey(
   2592             it.get(), stop_key, index_id, IndexMetaDataKey::MULTI_ENTRY)) {
   2593       StringPiece slice(it->Value());
   2594       if (!DecodeBool(&slice, &index_multi_entry) || !slice.empty())
   2595         INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
   2596 
   2597       s = it->Next();
   2598       if (!s.ok())
   2599         break;
   2600     }
   2601 
   2602     (*indexes)[index_id] = IndexedDBIndexMetadata(
   2603         index_name, index_id, key_path, index_unique, index_multi_entry);
   2604   }
   2605 
   2606   if (!s.ok())
   2607     INTERNAL_READ_ERROR_UNTESTED(GET_INDEXES);
   2608 
   2609   return s;
   2610 }
   2611 
   2612 bool IndexedDBBackingStore::RemoveBlobFile(int64 database_id, int64 key) {
   2613   FilePath fileName = GetBlobFileName(database_id, key);
   2614   return base::DeleteFile(fileName, false);
   2615 }
   2616 
   2617 bool IndexedDBBackingStore::RemoveBlobDirectory(int64 database_id) {
   2618   FilePath dirName = GetBlobDirectoryName(blob_path_, database_id);
   2619   return base::DeleteFile(dirName, true);
   2620 }
   2621 
   2622 leveldb::Status IndexedDBBackingStore::CleanUpBlobJournal(
   2623     const std::string& level_db_key) {
   2624   scoped_refptr<LevelDBTransaction> journal_transaction =
   2625       IndexedDBClassFactory::Get()->CreateLevelDBTransaction(db_.get());
   2626   BlobJournalType journal;
   2627   leveldb::Status s =
   2628       GetBlobJournal(level_db_key, journal_transaction.get(), &journal);
   2629   if (!s.ok())
   2630     return s;
   2631   if (!journal.size())
   2632     return leveldb::Status::OK();
   2633   BlobJournalType::iterator journal_iter;
   2634   for (journal_iter = journal.begin(); journal_iter != journal.end();
   2635        ++journal_iter) {
   2636     int64 database_id = journal_iter->first;
   2637     int64 blob_key = journal_iter->second;
   2638     DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
   2639     if (blob_key == DatabaseMetaDataKey::kAllBlobsKey) {
   2640       if (!RemoveBlobDirectory(database_id))
   2641         return IOErrorStatus();
   2642     } else {
   2643       DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key));
   2644       if (!RemoveBlobFile(database_id, blob_key))
   2645         return IOErrorStatus();
   2646     }
   2647   }
   2648   ClearBlobJournal(journal_transaction.get(), level_db_key);
   2649   return journal_transaction->Commit();
   2650 }
   2651 
   2652 leveldb::Status IndexedDBBackingStore::Transaction::GetBlobInfoForRecord(
   2653     int64 database_id,
   2654     const std::string& object_store_data_key,
   2655     IndexedDBValue* value) {
   2656   BlobChangeRecord* change_record = NULL;
   2657   BlobChangeMap::const_iterator blob_iter =
   2658       blob_change_map_.find(object_store_data_key);
   2659   if (blob_iter != blob_change_map_.end()) {
   2660     change_record = blob_iter->second;
   2661   } else {
   2662     blob_iter = incognito_blob_map_.find(object_store_data_key);
   2663     if (blob_iter != incognito_blob_map_.end())
   2664       change_record = blob_iter->second;
   2665   }
   2666   if (change_record) {
   2667     // Either we haven't written the blob to disk yet or we're in incognito
   2668     // mode, so we have to send back the one they sent us.  This change record
   2669     // includes the original UUID.
   2670     value->blob_info = change_record->blob_info();
   2671     return leveldb::Status::OK();
   2672   }
   2673 
   2674   BlobEntryKey blob_entry_key;
   2675   StringPiece leveldb_key_piece(object_store_data_key);
   2676   if (!BlobEntryKey::FromObjectStoreDataKey(&leveldb_key_piece,
   2677                                             &blob_entry_key)) {
   2678     NOTREACHED();
   2679     return InternalInconsistencyStatus();
   2680   }
   2681   std::string encoded_key = blob_entry_key.Encode();
   2682   bool found;
   2683   std::string encoded_value;
   2684   leveldb::Status s = transaction()->Get(encoded_key, &encoded_value, &found);
   2685   if (!s.ok())
   2686     return s;
   2687   if (found) {
   2688     if (!DecodeBlobData(encoded_value, &value->blob_info)) {
   2689       INTERNAL_READ_ERROR(GET_BLOB_INFO_FOR_RECORD);
   2690       return InternalInconsistencyStatus();
   2691     }
   2692     std::vector<IndexedDBBlobInfo>::iterator iter;
   2693     for (iter = value->blob_info.begin(); iter != value->blob_info.end();
   2694          ++iter) {
   2695       iter->set_file_path(
   2696           backing_store_->GetBlobFileName(database_id, iter->key()));
   2697       iter->set_mark_used_callback(
   2698           backing_store_->active_blob_registry()->GetAddBlobRefCallback(
   2699               database_id, iter->key()));
   2700       iter->set_release_callback(
   2701           backing_store_->active_blob_registry()->GetFinalReleaseCallback(
   2702               database_id, iter->key()));
   2703       if (iter->is_file()) {
   2704         base::File::Info info;
   2705         if (base::GetFileInfo(iter->file_path(), &info)) {
   2706           // This should always work, but it isn't fatal if it doesn't; it just
   2707           // means a potential slow synchronous call from the renderer later.
   2708           iter->set_last_modified(info.last_modified);
   2709           iter->set_size(info.size);
   2710         }
   2711       }
   2712     }
   2713   }
   2714   return leveldb::Status::OK();
   2715 }
   2716 
   2717 void IndexedDBBackingStore::CleanPrimaryJournalIgnoreReturn() {
   2718   CleanUpBlobJournal(BlobJournalKey::Encode());
   2719 }
   2720 
   2721 WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId(
   2722     LevelDBTransaction* transaction,
   2723     int64 database_id,
   2724     int64 object_store_id,
   2725     int64 index_id) {
   2726   int64 max_index_id = -1;
   2727   const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode(
   2728       database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID);
   2729   bool found = false;
   2730   leveldb::Status s =
   2731       GetInt(transaction, max_index_id_key, &max_index_id, &found);
   2732   if (!s.ok()) {
   2733     INTERNAL_READ_ERROR_UNTESTED(SET_MAX_INDEX_ID);
   2734     return s;
   2735   }
   2736   if (!found)
   2737     max_index_id = kMinimumIndexId;
   2738 
   2739   if (index_id <= max_index_id) {
   2740     INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_MAX_INDEX_ID);
   2741     return InternalInconsistencyStatus();
   2742   }
   2743 
   2744   PutInt(transaction, max_index_id_key, index_id);
   2745   return s;
   2746 }
   2747 
   2748 leveldb::Status IndexedDBBackingStore::CreateIndex(
   2749     IndexedDBBackingStore::Transaction* transaction,
   2750     int64 database_id,
   2751     int64 object_store_id,
   2752     int64 index_id,
   2753     const base::string16& name,
   2754     const IndexedDBKeyPath& key_path,
   2755     bool is_unique,
   2756     bool is_multi_entry) {
   2757   IDB_TRACE("IndexedDBBackingStore::CreateIndex");
   2758   if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
   2759     return InvalidDBKeyStatus();
   2760   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   2761   leveldb::Status s = SetMaxIndexId(
   2762       leveldb_transaction, database_id, object_store_id, index_id);
   2763 
   2764   if (!s.ok())
   2765     return s;
   2766 
   2767   const std::string name_key = IndexMetaDataKey::Encode(
   2768       database_id, object_store_id, index_id, IndexMetaDataKey::NAME);
   2769   const std::string unique_key = IndexMetaDataKey::Encode(
   2770       database_id, object_store_id, index_id, IndexMetaDataKey::UNIQUE);
   2771   const std::string key_path_key = IndexMetaDataKey::Encode(
   2772       database_id, object_store_id, index_id, IndexMetaDataKey::KEY_PATH);
   2773   const std::string multi_entry_key = IndexMetaDataKey::Encode(
   2774       database_id, object_store_id, index_id, IndexMetaDataKey::MULTI_ENTRY);
   2775 
   2776   PutString(leveldb_transaction, name_key, name);
   2777   PutBool(leveldb_transaction, unique_key, is_unique);
   2778   PutIDBKeyPath(leveldb_transaction, key_path_key, key_path);
   2779   PutBool(leveldb_transaction, multi_entry_key, is_multi_entry);
   2780   return s;
   2781 }
   2782 
   2783 leveldb::Status IndexedDBBackingStore::DeleteIndex(
   2784     IndexedDBBackingStore::Transaction* transaction,
   2785     int64 database_id,
   2786     int64 object_store_id,
   2787     int64 index_id) {
   2788   IDB_TRACE("IndexedDBBackingStore::DeleteIndex");
   2789   if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
   2790     return InvalidDBKeyStatus();
   2791   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   2792 
   2793   const std::string index_meta_data_start =
   2794       IndexMetaDataKey::Encode(database_id, object_store_id, index_id, 0);
   2795   const std::string index_meta_data_end =
   2796       IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
   2797   leveldb::Status s = DeleteRangeBasic(
   2798       leveldb_transaction, index_meta_data_start, index_meta_data_end, true);
   2799 
   2800   if (s.ok()) {
   2801     const std::string index_data_start =
   2802         IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id);
   2803     const std::string index_data_end =
   2804         IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
   2805     s = DeleteRangeBasic(
   2806         leveldb_transaction, index_data_start, index_data_end, true);
   2807   }
   2808 
   2809   if (!s.ok())
   2810     INTERNAL_WRITE_ERROR_UNTESTED(DELETE_INDEX);
   2811 
   2812   return s;
   2813 }
   2814 
   2815 leveldb::Status IndexedDBBackingStore::PutIndexDataForRecord(
   2816     IndexedDBBackingStore::Transaction* transaction,
   2817     int64 database_id,
   2818     int64 object_store_id,
   2819     int64 index_id,
   2820     const IndexedDBKey& key,
   2821     const RecordIdentifier& record_identifier) {
   2822   IDB_TRACE("IndexedDBBackingStore::PutIndexDataForRecord");
   2823   DCHECK(key.IsValid());
   2824   if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
   2825     return InvalidDBKeyStatus();
   2826 
   2827   std::string encoded_key;
   2828   EncodeIDBKey(key, &encoded_key);
   2829 
   2830   const std::string index_data_key =
   2831       IndexDataKey::Encode(database_id,
   2832                            object_store_id,
   2833                            index_id,
   2834                            encoded_key,
   2835                            record_identifier.primary_key(),
   2836                            0);
   2837 
   2838   std::string data;
   2839   EncodeVarInt(record_identifier.version(), &data);
   2840   data.append(record_identifier.primary_key());
   2841 
   2842   transaction->transaction()->Put(index_data_key, &data);
   2843   return leveldb::Status::OK();
   2844 }
   2845 
   2846 static bool FindGreatestKeyLessThanOrEqual(LevelDBTransaction* transaction,
   2847                                            const std::string& target,
   2848                                            std::string* found_key,
   2849                                            leveldb::Status* s) {
   2850   scoped_ptr<LevelDBIterator> it = transaction->CreateIterator();
   2851   *s = it->Seek(target);
   2852   if (!s->ok())
   2853     return false;
   2854 
   2855   if (!it->IsValid()) {
   2856     *s = it->SeekToLast();
   2857     if (!s->ok() || !it->IsValid())
   2858       return false;
   2859   }
   2860 
   2861   while (CompareIndexKeys(it->Key(), target) > 0) {
   2862     *s = it->Prev();
   2863     if (!s->ok() || !it->IsValid())
   2864       return false;
   2865   }
   2866 
   2867   do {
   2868     *found_key = it->Key().as_string();
   2869 
   2870     // There can be several index keys that compare equal. We want the last one.
   2871     *s = it->Next();
   2872   } while (s->ok() && it->IsValid() && !CompareIndexKeys(it->Key(), target));
   2873 
   2874   return true;
   2875 }
   2876 
   2877 static leveldb::Status VersionExists(LevelDBTransaction* transaction,
   2878                                      int64 database_id,
   2879                                      int64 object_store_id,
   2880                                      int64 version,
   2881                                      const std::string& encoded_primary_key,
   2882                                      bool* exists) {
   2883   const std::string key =
   2884       ExistsEntryKey::Encode(database_id, object_store_id, encoded_primary_key);
   2885   std::string data;
   2886 
   2887   leveldb::Status s = transaction->Get(key, &data, exists);
   2888   if (!s.ok()) {
   2889     INTERNAL_READ_ERROR_UNTESTED(VERSION_EXISTS);
   2890     return s;
   2891   }
   2892   if (!*exists)
   2893     return s;
   2894 
   2895   StringPiece slice(data);
   2896   int64 decoded;
   2897   if (!DecodeInt(&slice, &decoded) || !slice.empty())
   2898     return InternalInconsistencyStatus();
   2899   *exists = (decoded == version);
   2900   return s;
   2901 }
   2902 
   2903 leveldb::Status IndexedDBBackingStore::FindKeyInIndex(
   2904     IndexedDBBackingStore::Transaction* transaction,
   2905     int64 database_id,
   2906     int64 object_store_id,
   2907     int64 index_id,
   2908     const IndexedDBKey& key,
   2909     std::string* found_encoded_primary_key,
   2910     bool* found) {
   2911   IDB_TRACE("IndexedDBBackingStore::FindKeyInIndex");
   2912   DCHECK(KeyPrefix::ValidIds(database_id, object_store_id, index_id));
   2913 
   2914   DCHECK(found_encoded_primary_key->empty());
   2915   *found = false;
   2916 
   2917   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   2918   const std::string leveldb_key =
   2919       IndexDataKey::Encode(database_id, object_store_id, index_id, key);
   2920   scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator();
   2921   leveldb::Status s = it->Seek(leveldb_key);
   2922   if (!s.ok()) {
   2923     INTERNAL_READ_ERROR_UNTESTED(FIND_KEY_IN_INDEX);
   2924     return s;
   2925   }
   2926 
   2927   for (;;) {
   2928     if (!it->IsValid())
   2929       return leveldb::Status::OK();
   2930     if (CompareIndexKeys(it->Key(), leveldb_key) > 0)
   2931       return leveldb::Status::OK();
   2932 
   2933     StringPiece slice(it->Value());
   2934 
   2935     int64 version;
   2936     if (!DecodeVarInt(&slice, &version)) {
   2937       INTERNAL_READ_ERROR_UNTESTED(FIND_KEY_IN_INDEX);
   2938       return InternalInconsistencyStatus();
   2939     }
   2940     *found_encoded_primary_key = slice.as_string();
   2941 
   2942     bool exists = false;
   2943     s = VersionExists(leveldb_transaction,
   2944                       database_id,
   2945                       object_store_id,
   2946                       version,
   2947                       *found_encoded_primary_key,
   2948                       &exists);
   2949     if (!s.ok())
   2950       return s;
   2951     if (!exists) {
   2952       // Delete stale index data entry and continue.
   2953       leveldb_transaction->Remove(it->Key());
   2954       s = it->Next();
   2955       continue;
   2956     }
   2957     *found = true;
   2958     return s;
   2959   }
   2960 }
   2961 
   2962 leveldb::Status IndexedDBBackingStore::GetPrimaryKeyViaIndex(
   2963     IndexedDBBackingStore::Transaction* transaction,
   2964     int64 database_id,
   2965     int64 object_store_id,
   2966     int64 index_id,
   2967     const IndexedDBKey& key,
   2968     scoped_ptr<IndexedDBKey>* primary_key) {
   2969   IDB_TRACE("IndexedDBBackingStore::GetPrimaryKeyViaIndex");
   2970   if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
   2971     return InvalidDBKeyStatus();
   2972 
   2973   bool found = false;
   2974   std::string found_encoded_primary_key;
   2975   leveldb::Status s = FindKeyInIndex(transaction,
   2976                                      database_id,
   2977                                      object_store_id,
   2978                                      index_id,
   2979                                      key,
   2980                                      &found_encoded_primary_key,
   2981                                      &found);
   2982   if (!s.ok()) {
   2983     INTERNAL_READ_ERROR_UNTESTED(GET_PRIMARY_KEY_VIA_INDEX);
   2984     return s;
   2985   }
   2986   if (!found)
   2987     return s;
   2988   if (!found_encoded_primary_key.size()) {
   2989     INTERNAL_READ_ERROR_UNTESTED(GET_PRIMARY_KEY_VIA_INDEX);
   2990     return InvalidDBKeyStatus();
   2991   }
   2992 
   2993   StringPiece slice(found_encoded_primary_key);
   2994   if (DecodeIDBKey(&slice, primary_key) && slice.empty())
   2995     return s;
   2996   else
   2997     return InvalidDBKeyStatus();
   2998 }
   2999 
   3000 leveldb::Status IndexedDBBackingStore::KeyExistsInIndex(
   3001     IndexedDBBackingStore::Transaction* transaction,
   3002     int64 database_id,
   3003     int64 object_store_id,
   3004     int64 index_id,
   3005     const IndexedDBKey& index_key,
   3006     scoped_ptr<IndexedDBKey>* found_primary_key,
   3007     bool* exists) {
   3008   IDB_TRACE("IndexedDBBackingStore::KeyExistsInIndex");
   3009   if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
   3010     return InvalidDBKeyStatus();
   3011 
   3012   *exists = false;
   3013   std::string found_encoded_primary_key;
   3014   leveldb::Status s = FindKeyInIndex(transaction,
   3015                                      database_id,
   3016                                      object_store_id,
   3017                                      index_id,
   3018                                      index_key,
   3019                                      &found_encoded_primary_key,
   3020                                      exists);
   3021   if (!s.ok()) {
   3022     INTERNAL_READ_ERROR_UNTESTED(KEY_EXISTS_IN_INDEX);
   3023     return s;
   3024   }
   3025   if (!*exists)
   3026     return leveldb::Status::OK();
   3027   if (found_encoded_primary_key.empty()) {
   3028     INTERNAL_READ_ERROR_UNTESTED(KEY_EXISTS_IN_INDEX);
   3029     return InvalidDBKeyStatus();
   3030   }
   3031 
   3032   StringPiece slice(found_encoded_primary_key);
   3033   if (DecodeIDBKey(&slice, found_primary_key) && slice.empty())
   3034     return s;
   3035   else
   3036     return InvalidDBKeyStatus();
   3037 }
   3038 
   3039 IndexedDBBackingStore::Cursor::Cursor(
   3040     const IndexedDBBackingStore::Cursor* other)
   3041     : backing_store_(other->backing_store_),
   3042       transaction_(other->transaction_),
   3043       database_id_(other->database_id_),
   3044       cursor_options_(other->cursor_options_),
   3045       current_key_(new IndexedDBKey(*other->current_key_)) {
   3046   if (other->iterator_) {
   3047     iterator_ = transaction_->transaction()->CreateIterator();
   3048 
   3049     if (other->iterator_->IsValid()) {
   3050       leveldb::Status s = iterator_->Seek(other->iterator_->Key());
   3051       // TODO(cmumford): Handle this error (crbug.com/363397)
   3052       DCHECK(iterator_->IsValid());
   3053     }
   3054   }
   3055 }
   3056 
   3057 IndexedDBBackingStore::Cursor::Cursor(
   3058     scoped_refptr<IndexedDBBackingStore> backing_store,
   3059     IndexedDBBackingStore::Transaction* transaction,
   3060     int64 database_id,
   3061     const CursorOptions& cursor_options)
   3062     : backing_store_(backing_store.get()),
   3063       transaction_(transaction),
   3064       database_id_(database_id),
   3065       cursor_options_(cursor_options) {
   3066 }
   3067 IndexedDBBackingStore::Cursor::~Cursor() {}
   3068 
   3069 bool IndexedDBBackingStore::Cursor::FirstSeek(leveldb::Status* s) {
   3070   iterator_ = transaction_->transaction()->CreateIterator();
   3071   if (cursor_options_.forward)
   3072     *s = iterator_->Seek(cursor_options_.low_key);
   3073   else
   3074     *s = iterator_->Seek(cursor_options_.high_key);
   3075   if (!s->ok())
   3076     return false;
   3077 
   3078   return Continue(0, READY, s);
   3079 }
   3080 
   3081 bool IndexedDBBackingStore::Cursor::Advance(uint32 count, leveldb::Status* s) {
   3082   *s = leveldb::Status::OK();
   3083   while (count--) {
   3084     if (!Continue(s))
   3085       return false;
   3086   }
   3087   return true;
   3088 }
   3089 
   3090 bool IndexedDBBackingStore::Cursor::Continue(const IndexedDBKey* key,
   3091                                              const IndexedDBKey* primary_key,
   3092                                              IteratorState next_state,
   3093                                              leveldb::Status* s) {
   3094   DCHECK(!key || key->IsValid());
   3095   DCHECK(!primary_key || primary_key->IsValid());
   3096   *s = leveldb::Status::OK();
   3097 
   3098   // TODO(alecflett): avoid a copy here?
   3099   IndexedDBKey previous_key = current_key_ ? *current_key_ : IndexedDBKey();
   3100 
   3101   // When iterating with PrevNoDuplicate, spec requires that the
   3102   // value we yield for each key is the first duplicate in forwards
   3103   // order.
   3104   IndexedDBKey last_duplicate_key;
   3105 
   3106   bool forward = cursor_options_.forward;
   3107   bool first_iteration_forward = forward;
   3108   bool flipped = false;
   3109 
   3110   for (;;) {
   3111     if (next_state == SEEK) {
   3112       // TODO(jsbell): Optimize seeking for reverse cursors as well.
   3113       if (first_iteration_forward && key) {
   3114         first_iteration_forward = false;
   3115         std::string leveldb_key;
   3116         if (primary_key) {
   3117           leveldb_key = EncodeKey(*key, *primary_key);
   3118         } else {
   3119           leveldb_key = EncodeKey(*key);
   3120         }
   3121         *s = iterator_->Seek(leveldb_key);
   3122       } else if (forward) {
   3123         *s = iterator_->Next();
   3124       } else {
   3125         *s = iterator_->Prev();
   3126       }
   3127       if (!s->ok())
   3128         return false;
   3129     } else {
   3130       next_state = SEEK;  // for subsequent iterations
   3131     }
   3132 
   3133     if (!iterator_->IsValid()) {
   3134       if (!forward && last_duplicate_key.IsValid()) {
   3135         // We need to walk forward because we hit the end of
   3136         // the data.
   3137         forward = true;
   3138         flipped = true;
   3139         continue;
   3140       }
   3141 
   3142       return false;
   3143     }
   3144 
   3145     if (IsPastBounds()) {
   3146       if (!forward && last_duplicate_key.IsValid()) {
   3147         // We need to walk forward because now we're beyond the
   3148         // bounds defined by the cursor.
   3149         forward = true;
   3150         flipped = true;
   3151         continue;
   3152       }
   3153 
   3154       return false;
   3155     }
   3156 
   3157     if (!HaveEnteredRange())
   3158       continue;
   3159 
   3160     // The row may not load because there's a stale entry in the
   3161     // index. This is not fatal.
   3162     if (!LoadCurrentRow())
   3163       continue;
   3164 
   3165     if (key) {
   3166       if (forward) {
   3167         if (primary_key && current_key_->Equals(*key) &&
   3168             this->primary_key().IsLessThan(*primary_key))
   3169           continue;
   3170         if (!flipped && current_key_->IsLessThan(*key))
   3171           continue;
   3172       } else {
   3173         if (primary_key && key->Equals(*current_key_) &&
   3174             primary_key->IsLessThan(this->primary_key()))
   3175           continue;
   3176         if (key->IsLessThan(*current_key_))
   3177           continue;
   3178       }
   3179     }
   3180 
   3181     if (cursor_options_.unique) {
   3182       if (previous_key.IsValid() && current_key_->Equals(previous_key)) {
   3183         // We should never be able to walk forward all the way
   3184         // to the previous key.
   3185         DCHECK(!last_duplicate_key.IsValid());
   3186         continue;
   3187       }
   3188 
   3189       if (!forward) {
   3190         if (!last_duplicate_key.IsValid()) {
   3191           last_duplicate_key = *current_key_;
   3192           continue;
   3193         }
   3194 
   3195         // We need to walk forward because we hit the boundary
   3196         // between key ranges.
   3197         if (!last_duplicate_key.Equals(*current_key_)) {
   3198           forward = true;
   3199           flipped = true;
   3200           continue;
   3201         }
   3202 
   3203         continue;
   3204       }
   3205     }
   3206     break;
   3207   }
   3208 
   3209   DCHECK(!last_duplicate_key.IsValid() ||
   3210          (forward && last_duplicate_key.Equals(*current_key_)));
   3211   return true;
   3212 }
   3213 
   3214 bool IndexedDBBackingStore::Cursor::HaveEnteredRange() const {
   3215   if (cursor_options_.forward) {
   3216     int compare = CompareIndexKeys(iterator_->Key(), cursor_options_.low_key);
   3217     if (cursor_options_.low_open) {
   3218       return compare > 0;
   3219     }
   3220     return compare >= 0;
   3221   }
   3222   int compare = CompareIndexKeys(iterator_->Key(), cursor_options_.high_key);
   3223   if (cursor_options_.high_open) {
   3224     return compare < 0;
   3225   }
   3226   return compare <= 0;
   3227 }
   3228 
   3229 bool IndexedDBBackingStore::Cursor::IsPastBounds() const {
   3230   if (cursor_options_.forward) {
   3231     int compare = CompareIndexKeys(iterator_->Key(), cursor_options_.high_key);
   3232     if (cursor_options_.high_open) {
   3233       return compare >= 0;
   3234     }
   3235     return compare > 0;
   3236   }
   3237   int compare = CompareIndexKeys(iterator_->Key(), cursor_options_.low_key);
   3238   if (cursor_options_.low_open) {
   3239     return compare <= 0;
   3240   }
   3241   return compare < 0;
   3242 }
   3243 
   3244 const IndexedDBKey& IndexedDBBackingStore::Cursor::primary_key() const {
   3245   return *current_key_;
   3246 }
   3247 
   3248 const IndexedDBBackingStore::RecordIdentifier&
   3249 IndexedDBBackingStore::Cursor::record_identifier() const {
   3250   return record_identifier_;
   3251 }
   3252 
   3253 class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor {
   3254  public:
   3255   ObjectStoreKeyCursorImpl(
   3256       scoped_refptr<IndexedDBBackingStore> backing_store,
   3257       IndexedDBBackingStore::Transaction* transaction,
   3258       int64 database_id,
   3259       const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
   3260       : IndexedDBBackingStore::Cursor(backing_store,
   3261                                       transaction,
   3262                                       database_id,
   3263                                       cursor_options) {}
   3264 
   3265   virtual Cursor* Clone() OVERRIDE {
   3266     return new ObjectStoreKeyCursorImpl(this);
   3267   }
   3268 
   3269   // IndexedDBBackingStore::Cursor
   3270   virtual IndexedDBValue* value() OVERRIDE {
   3271     NOTREACHED();
   3272     return NULL;
   3273   }
   3274   virtual bool LoadCurrentRow() OVERRIDE;
   3275 
   3276  protected:
   3277   virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
   3278     return ObjectStoreDataKey::Encode(
   3279         cursor_options_.database_id, cursor_options_.object_store_id, key);
   3280   }
   3281   virtual std::string EncodeKey(const IndexedDBKey& key,
   3282                                 const IndexedDBKey& primary_key) OVERRIDE {
   3283     NOTREACHED();
   3284     return std::string();
   3285   }
   3286 
   3287  private:
   3288   explicit ObjectStoreKeyCursorImpl(const ObjectStoreKeyCursorImpl* other)
   3289       : IndexedDBBackingStore::Cursor(other) {}
   3290 
   3291   DISALLOW_COPY_AND_ASSIGN(ObjectStoreKeyCursorImpl);
   3292 };
   3293 
   3294 bool ObjectStoreKeyCursorImpl::LoadCurrentRow() {
   3295   StringPiece slice(iterator_->Key());
   3296   ObjectStoreDataKey object_store_data_key;
   3297   if (!ObjectStoreDataKey::Decode(&slice, &object_store_data_key)) {
   3298     INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
   3299     return false;
   3300   }
   3301 
   3302   current_key_ = object_store_data_key.user_key();
   3303 
   3304   int64 version;
   3305   slice = StringPiece(iterator_->Value());
   3306   if (!DecodeVarInt(&slice, &version)) {
   3307     INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
   3308     return false;
   3309   }
   3310 
   3311   // TODO(jsbell): This re-encodes what was just decoded; try and optimize.
   3312   std::string encoded_key;
   3313   EncodeIDBKey(*current_key_, &encoded_key);
   3314   record_identifier_.Reset(encoded_key, version);
   3315 
   3316   return true;
   3317 }
   3318 
   3319 class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor {
   3320  public:
   3321   ObjectStoreCursorImpl(
   3322       scoped_refptr<IndexedDBBackingStore> backing_store,
   3323       IndexedDBBackingStore::Transaction* transaction,
   3324       int64 database_id,
   3325       const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
   3326       : IndexedDBBackingStore::Cursor(backing_store,
   3327                                       transaction,
   3328                                       database_id,
   3329                                       cursor_options) {}
   3330 
   3331   virtual Cursor* Clone() OVERRIDE { return new ObjectStoreCursorImpl(this); }
   3332 
   3333   // IndexedDBBackingStore::Cursor
   3334   virtual IndexedDBValue* value() OVERRIDE { return &current_value_; }
   3335   virtual bool LoadCurrentRow() OVERRIDE;
   3336 
   3337  protected:
   3338   virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
   3339     return ObjectStoreDataKey::Encode(
   3340         cursor_options_.database_id, cursor_options_.object_store_id, key);
   3341   }
   3342   virtual std::string EncodeKey(const IndexedDBKey& key,
   3343                                 const IndexedDBKey& primary_key) OVERRIDE {
   3344     NOTREACHED();
   3345     return std::string();
   3346   }
   3347 
   3348  private:
   3349   explicit ObjectStoreCursorImpl(const ObjectStoreCursorImpl* other)
   3350       : IndexedDBBackingStore::Cursor(other),
   3351         current_value_(other->current_value_) {}
   3352 
   3353   IndexedDBValue current_value_;
   3354 
   3355   DISALLOW_COPY_AND_ASSIGN(ObjectStoreCursorImpl);
   3356 };
   3357 
   3358 bool ObjectStoreCursorImpl::LoadCurrentRow() {
   3359   StringPiece key_slice(iterator_->Key());
   3360   ObjectStoreDataKey object_store_data_key;
   3361   if (!ObjectStoreDataKey::Decode(&key_slice, &object_store_data_key)) {
   3362     INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
   3363     return false;
   3364   }
   3365 
   3366   current_key_ = object_store_data_key.user_key();
   3367 
   3368   int64 version;
   3369   StringPiece value_slice = StringPiece(iterator_->Value());
   3370   if (!DecodeVarInt(&value_slice, &version)) {
   3371     INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
   3372     return false;
   3373   }
   3374 
   3375   // TODO(jsbell): This re-encodes what was just decoded; try and optimize.
   3376   std::string encoded_key;
   3377   EncodeIDBKey(*current_key_, &encoded_key);
   3378   record_identifier_.Reset(encoded_key, version);
   3379 
   3380   if (!transaction_->GetBlobInfoForRecord(database_id_,
   3381                                           iterator_->Key().as_string(),
   3382                                           &current_value_).ok()) {
   3383     return false;
   3384   }
   3385   current_value_.bits = value_slice.as_string();
   3386   return true;
   3387 }
   3388 
   3389 class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor {
   3390  public:
   3391   IndexKeyCursorImpl(
   3392       scoped_refptr<IndexedDBBackingStore> backing_store,
   3393       IndexedDBBackingStore::Transaction* transaction,
   3394       int64 database_id,
   3395       const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
   3396       : IndexedDBBackingStore::Cursor(backing_store,
   3397                                       transaction,
   3398                                       database_id,
   3399                                       cursor_options) {}
   3400 
   3401   virtual Cursor* Clone() OVERRIDE { return new IndexKeyCursorImpl(this); }
   3402 
   3403   // IndexedDBBackingStore::Cursor
   3404   virtual IndexedDBValue* value() OVERRIDE {
   3405     NOTREACHED();
   3406     return NULL;
   3407   }
   3408   virtual const IndexedDBKey& primary_key() const OVERRIDE {
   3409     return *primary_key_;
   3410   }
   3411   virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier()
   3412       const OVERRIDE {
   3413     NOTREACHED();
   3414     return record_identifier_;
   3415   }
   3416   virtual bool LoadCurrentRow() OVERRIDE;
   3417 
   3418  protected:
   3419   virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
   3420     return IndexDataKey::Encode(cursor_options_.database_id,
   3421                                 cursor_options_.object_store_id,
   3422                                 cursor_options_.index_id,
   3423                                 key);
   3424   }
   3425   virtual std::string EncodeKey(const IndexedDBKey& key,
   3426                                 const IndexedDBKey& primary_key) OVERRIDE {
   3427     return IndexDataKey::Encode(cursor_options_.database_id,
   3428                                 cursor_options_.object_store_id,
   3429                                 cursor_options_.index_id,
   3430                                 key,
   3431                                 primary_key);
   3432   }
   3433 
   3434  private:
   3435   explicit IndexKeyCursorImpl(const IndexKeyCursorImpl* other)
   3436       : IndexedDBBackingStore::Cursor(other),
   3437         primary_key_(new IndexedDBKey(*other->primary_key_)) {}
   3438 
   3439   scoped_ptr<IndexedDBKey> primary_key_;
   3440 
   3441   DISALLOW_COPY_AND_ASSIGN(IndexKeyCursorImpl);
   3442 };
   3443 
   3444 bool IndexKeyCursorImpl::LoadCurrentRow() {
   3445   StringPiece slice(iterator_->Key());
   3446   IndexDataKey index_data_key;
   3447   if (!IndexDataKey::Decode(&slice, &index_data_key)) {
   3448     INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
   3449     return false;
   3450   }
   3451 
   3452   current_key_ = index_data_key.user_key();
   3453   DCHECK(current_key_);
   3454 
   3455   slice = StringPiece(iterator_->Value());
   3456   int64 index_data_version;
   3457   if (!DecodeVarInt(&slice, &index_data_version)) {
   3458     INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
   3459     return false;
   3460   }
   3461 
   3462   if (!DecodeIDBKey(&slice, &primary_key_) || !slice.empty()) {
   3463     INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
   3464     return false;
   3465   }
   3466 
   3467   std::string primary_leveldb_key =
   3468       ObjectStoreDataKey::Encode(index_data_key.DatabaseId(),
   3469                                  index_data_key.ObjectStoreId(),
   3470                                  *primary_key_);
   3471 
   3472   std::string result;
   3473   bool found = false;
   3474   leveldb::Status s =
   3475       transaction_->transaction()->Get(primary_leveldb_key, &result, &found);
   3476   if (!s.ok()) {
   3477     INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
   3478     return false;
   3479   }
   3480   if (!found) {
   3481     transaction_->transaction()->Remove(iterator_->Key());
   3482     return false;
   3483   }
   3484   if (!result.size()) {
   3485     INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
   3486     return false;
   3487   }
   3488 
   3489   int64 object_store_data_version;
   3490   slice = StringPiece(result);
   3491   if (!DecodeVarInt(&slice, &object_store_data_version)) {
   3492     INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
   3493     return false;
   3494   }
   3495 
   3496   if (object_store_data_version != index_data_version) {
   3497     transaction_->transaction()->Remove(iterator_->Key());
   3498     return false;
   3499   }
   3500 
   3501   return true;
   3502 }
   3503 
   3504 class IndexCursorImpl : public IndexedDBBackingStore::Cursor {
   3505  public:
   3506   IndexCursorImpl(
   3507       scoped_refptr<IndexedDBBackingStore> backing_store,
   3508       IndexedDBBackingStore::Transaction* transaction,
   3509       int64 database_id,
   3510       const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
   3511       : IndexedDBBackingStore::Cursor(backing_store,
   3512                                       transaction,
   3513                                       database_id,
   3514                                       cursor_options) {}
   3515 
   3516   virtual Cursor* Clone() OVERRIDE { return new IndexCursorImpl(this); }
   3517 
   3518   // IndexedDBBackingStore::Cursor
   3519   virtual IndexedDBValue* value() OVERRIDE { return &current_value_; }
   3520   virtual const IndexedDBKey& primary_key() const OVERRIDE {
   3521     return *primary_key_;
   3522   }
   3523   virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier()
   3524       const OVERRIDE {
   3525     NOTREACHED();
   3526     return record_identifier_;
   3527   }
   3528   virtual bool LoadCurrentRow() OVERRIDE;
   3529 
   3530  protected:
   3531   virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
   3532     return IndexDataKey::Encode(cursor_options_.database_id,
   3533                                 cursor_options_.object_store_id,
   3534                                 cursor_options_.index_id,
   3535                                 key);
   3536   }
   3537   virtual std::string EncodeKey(const IndexedDBKey& key,
   3538                                 const IndexedDBKey& primary_key) OVERRIDE {
   3539     return IndexDataKey::Encode(cursor_options_.database_id,
   3540                                 cursor_options_.object_store_id,
   3541                                 cursor_options_.index_id,
   3542                                 key,
   3543                                 primary_key);
   3544   }
   3545 
   3546  private:
   3547   explicit IndexCursorImpl(const IndexCursorImpl* other)
   3548       : IndexedDBBackingStore::Cursor(other),
   3549         primary_key_(new IndexedDBKey(*other->primary_key_)),
   3550         current_value_(other->current_value_),
   3551         primary_leveldb_key_(other->primary_leveldb_key_) {}
   3552 
   3553   scoped_ptr<IndexedDBKey> primary_key_;
   3554   IndexedDBValue current_value_;
   3555   std::string primary_leveldb_key_;
   3556 
   3557   DISALLOW_COPY_AND_ASSIGN(IndexCursorImpl);
   3558 };
   3559 
   3560 bool IndexCursorImpl::LoadCurrentRow() {
   3561   StringPiece slice(iterator_->Key());
   3562   IndexDataKey index_data_key;
   3563   if (!IndexDataKey::Decode(&slice, &index_data_key)) {
   3564     INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
   3565     return false;
   3566   }
   3567 
   3568   current_key_ = index_data_key.user_key();
   3569   DCHECK(current_key_);
   3570 
   3571   slice = StringPiece(iterator_->Value());
   3572   int64 index_data_version;
   3573   if (!DecodeVarInt(&slice, &index_data_version)) {
   3574     INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
   3575     return false;
   3576   }
   3577   if (!DecodeIDBKey(&slice, &primary_key_)) {
   3578     INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
   3579     return false;
   3580   }
   3581 
   3582   DCHECK_EQ(index_data_key.DatabaseId(), database_id_);
   3583   primary_leveldb_key_ =
   3584       ObjectStoreDataKey::Encode(index_data_key.DatabaseId(),
   3585                                  index_data_key.ObjectStoreId(),
   3586                                  *primary_key_);
   3587 
   3588   std::string result;
   3589   bool found = false;
   3590   leveldb::Status s =
   3591       transaction_->transaction()->Get(primary_leveldb_key_, &result, &found);
   3592   if (!s.ok()) {
   3593     INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
   3594     return false;
   3595   }
   3596   if (!found) {
   3597     transaction_->transaction()->Remove(iterator_->Key());
   3598     return false;
   3599   }
   3600   if (!result.size()) {
   3601     INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
   3602     return false;
   3603   }
   3604 
   3605   int64 object_store_data_version;
   3606   slice = StringPiece(result);
   3607   if (!DecodeVarInt(&slice, &object_store_data_version)) {
   3608     INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
   3609     return false;
   3610   }
   3611 
   3612   if (object_store_data_version != index_data_version) {
   3613     transaction_->transaction()->Remove(iterator_->Key());
   3614     return false;
   3615   }
   3616 
   3617   current_value_.bits = slice.as_string();
   3618   return transaction_->GetBlobInfoForRecord(database_id_,
   3619                                             primary_leveldb_key_,
   3620                                             &current_value_).ok();
   3621 }
   3622 
   3623 bool ObjectStoreCursorOptions(
   3624     LevelDBTransaction* transaction,
   3625     int64 database_id,
   3626     int64 object_store_id,
   3627     const IndexedDBKeyRange& range,
   3628     blink::WebIDBCursorDirection direction,
   3629     IndexedDBBackingStore::Cursor::CursorOptions* cursor_options) {
   3630   cursor_options->database_id = database_id;
   3631   cursor_options->object_store_id = object_store_id;
   3632 
   3633   bool lower_bound = range.lower().IsValid();
   3634   bool upper_bound = range.upper().IsValid();
   3635   cursor_options->forward =
   3636       (direction == blink::WebIDBCursorDirectionNextNoDuplicate ||
   3637        direction == blink::WebIDBCursorDirectionNext);
   3638   cursor_options->unique =
   3639       (direction == blink::WebIDBCursorDirectionNextNoDuplicate ||
   3640        direction == blink::WebIDBCursorDirectionPrevNoDuplicate);
   3641 
   3642   if (!lower_bound) {
   3643     cursor_options->low_key =
   3644         ObjectStoreDataKey::Encode(database_id, object_store_id, MinIDBKey());
   3645     cursor_options->low_open = true;  // Not included.
   3646   } else {
   3647     cursor_options->low_key =
   3648         ObjectStoreDataKey::Encode(database_id, object_store_id, range.lower());
   3649     cursor_options->low_open = range.lowerOpen();
   3650   }
   3651 
   3652   leveldb::Status s;
   3653 
   3654   if (!upper_bound) {
   3655     cursor_options->high_key =
   3656         ObjectStoreDataKey::Encode(database_id, object_store_id, MaxIDBKey());
   3657 
   3658     if (cursor_options->forward) {
   3659       cursor_options->high_open = true;  // Not included.
   3660     } else {
   3661       // We need a key that exists.
   3662       // TODO(cmumford): Handle this error (crbug.com/363397)
   3663       if (!FindGreatestKeyLessThanOrEqual(transaction,
   3664                                           cursor_options->high_key,
   3665                                           &cursor_options->high_key,
   3666                                           &s))
   3667         return false;
   3668       cursor_options->high_open = false;
   3669     }
   3670   } else {
   3671     cursor_options->high_key =
   3672         ObjectStoreDataKey::Encode(database_id, object_store_id, range.upper());
   3673     cursor_options->high_open = range.upperOpen();
   3674 
   3675     if (!cursor_options->forward) {
   3676       // For reverse cursors, we need a key that exists.
   3677       std::string found_high_key;
   3678       // TODO(cmumford): Handle this error (crbug.com/363397)
   3679       if (!FindGreatestKeyLessThanOrEqual(
   3680               transaction, cursor_options->high_key, &found_high_key, &s))
   3681         return false;
   3682 
   3683       // If the target key should not be included, but we end up with a smaller
   3684       // key, we should include that.
   3685       if (cursor_options->high_open &&
   3686           CompareIndexKeys(found_high_key, cursor_options->high_key) < 0)
   3687         cursor_options->high_open = false;
   3688 
   3689       cursor_options->high_key = found_high_key;
   3690     }
   3691   }
   3692 
   3693   return true;
   3694 }
   3695 
   3696 bool IndexCursorOptions(
   3697     LevelDBTransaction* transaction,
   3698     int64 database_id,
   3699     int64 object_store_id,
   3700     int64 index_id,
   3701     const IndexedDBKeyRange& range,
   3702     blink::WebIDBCursorDirection direction,
   3703     IndexedDBBackingStore::Cursor::CursorOptions* cursor_options) {
   3704   DCHECK(transaction);
   3705   if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
   3706     return false;
   3707 
   3708   cursor_options->database_id = database_id;
   3709   cursor_options->object_store_id = object_store_id;
   3710   cursor_options->index_id = index_id;
   3711 
   3712   bool lower_bound = range.lower().IsValid();
   3713   bool upper_bound = range.upper().IsValid();
   3714   cursor_options->forward =
   3715       (direction == blink::WebIDBCursorDirectionNextNoDuplicate ||
   3716        direction == blink::WebIDBCursorDirectionNext);
   3717   cursor_options->unique =
   3718       (direction == blink::WebIDBCursorDirectionNextNoDuplicate ||
   3719        direction == blink::WebIDBCursorDirectionPrevNoDuplicate);
   3720 
   3721   if (!lower_bound) {
   3722     cursor_options->low_key =
   3723         IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id);
   3724     cursor_options->low_open = false;  // Included.
   3725   } else {
   3726     cursor_options->low_key = IndexDataKey::Encode(
   3727         database_id, object_store_id, index_id, range.lower());
   3728     cursor_options->low_open = range.lowerOpen();
   3729   }
   3730 
   3731   leveldb::Status s;
   3732 
   3733   if (!upper_bound) {
   3734     cursor_options->high_key =
   3735         IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
   3736     cursor_options->high_open = false;  // Included.
   3737 
   3738     if (!cursor_options->forward) {  // We need a key that exists.
   3739       if (!FindGreatestKeyLessThanOrEqual(transaction,
   3740                                           cursor_options->high_key,
   3741                                           &cursor_options->high_key,
   3742                                           &s))
   3743         return false;
   3744       cursor_options->high_open = false;
   3745     }
   3746   } else {
   3747     cursor_options->high_key = IndexDataKey::Encode(
   3748         database_id, object_store_id, index_id, range.upper());
   3749     cursor_options->high_open = range.upperOpen();
   3750 
   3751     std::string found_high_key;
   3752     // Seek to the *last* key in the set of non-unique keys
   3753     // TODO(cmumford): Handle this error (crbug.com/363397)
   3754     if (!FindGreatestKeyLessThanOrEqual(
   3755             transaction, cursor_options->high_key, &found_high_key, &s))
   3756       return false;
   3757 
   3758     // If the target key should not be included, but we end up with a smaller
   3759     // key, we should include that.
   3760     if (cursor_options->high_open &&
   3761         CompareIndexKeys(found_high_key, cursor_options->high_key) < 0)
   3762       cursor_options->high_open = false;
   3763 
   3764     cursor_options->high_key = found_high_key;
   3765   }
   3766 
   3767   return true;
   3768 }
   3769 
   3770 scoped_ptr<IndexedDBBackingStore::Cursor>
   3771 IndexedDBBackingStore::OpenObjectStoreCursor(
   3772     IndexedDBBackingStore::Transaction* transaction,
   3773     int64 database_id,
   3774     int64 object_store_id,
   3775     const IndexedDBKeyRange& range,
   3776     blink::WebIDBCursorDirection direction,
   3777     leveldb::Status* s) {
   3778   IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreCursor");
   3779   *s = leveldb::Status::OK();
   3780   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   3781   IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
   3782   if (!ObjectStoreCursorOptions(leveldb_transaction,
   3783                                 database_id,
   3784                                 object_store_id,
   3785                                 range,
   3786                                 direction,
   3787                                 &cursor_options))
   3788     return scoped_ptr<IndexedDBBackingStore::Cursor>();
   3789   scoped_ptr<ObjectStoreCursorImpl> cursor(new ObjectStoreCursorImpl(
   3790       this, transaction, database_id, cursor_options));
   3791   if (!cursor->FirstSeek(s))
   3792     return scoped_ptr<IndexedDBBackingStore::Cursor>();
   3793 
   3794   return cursor.PassAs<IndexedDBBackingStore::Cursor>();
   3795 }
   3796 
   3797 scoped_ptr<IndexedDBBackingStore::Cursor>
   3798 IndexedDBBackingStore::OpenObjectStoreKeyCursor(
   3799     IndexedDBBackingStore::Transaction* transaction,
   3800     int64 database_id,
   3801     int64 object_store_id,
   3802     const IndexedDBKeyRange& range,
   3803     blink::WebIDBCursorDirection direction,
   3804     leveldb::Status* s) {
   3805   IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreKeyCursor");
   3806   *s = leveldb::Status::OK();
   3807   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   3808   IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
   3809   if (!ObjectStoreCursorOptions(leveldb_transaction,
   3810                                 database_id,
   3811                                 object_store_id,
   3812                                 range,
   3813                                 direction,
   3814                                 &cursor_options))
   3815     return scoped_ptr<IndexedDBBackingStore::Cursor>();
   3816   scoped_ptr<ObjectStoreKeyCursorImpl> cursor(new ObjectStoreKeyCursorImpl(
   3817       this, transaction, database_id, cursor_options));
   3818   if (!cursor->FirstSeek(s))
   3819     return scoped_ptr<IndexedDBBackingStore::Cursor>();
   3820 
   3821   return cursor.PassAs<IndexedDBBackingStore::Cursor>();
   3822 }
   3823 
   3824 scoped_ptr<IndexedDBBackingStore::Cursor>
   3825 IndexedDBBackingStore::OpenIndexKeyCursor(
   3826     IndexedDBBackingStore::Transaction* transaction,
   3827     int64 database_id,
   3828     int64 object_store_id,
   3829     int64 index_id,
   3830     const IndexedDBKeyRange& range,
   3831     blink::WebIDBCursorDirection direction,
   3832     leveldb::Status* s) {
   3833   IDB_TRACE("IndexedDBBackingStore::OpenIndexKeyCursor");
   3834   *s = leveldb::Status::OK();
   3835   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   3836   IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
   3837   if (!IndexCursorOptions(leveldb_transaction,
   3838                           database_id,
   3839                           object_store_id,
   3840                           index_id,
   3841                           range,
   3842                           direction,
   3843                           &cursor_options))
   3844     return scoped_ptr<IndexedDBBackingStore::Cursor>();
   3845   scoped_ptr<IndexKeyCursorImpl> cursor(
   3846       new IndexKeyCursorImpl(this, transaction, database_id, cursor_options));
   3847   if (!cursor->FirstSeek(s))
   3848     return scoped_ptr<IndexedDBBackingStore::Cursor>();
   3849 
   3850   return cursor.PassAs<IndexedDBBackingStore::Cursor>();
   3851 }
   3852 
   3853 scoped_ptr<IndexedDBBackingStore::Cursor>
   3854 IndexedDBBackingStore::OpenIndexCursor(
   3855     IndexedDBBackingStore::Transaction* transaction,
   3856     int64 database_id,
   3857     int64 object_store_id,
   3858     int64 index_id,
   3859     const IndexedDBKeyRange& range,
   3860     blink::WebIDBCursorDirection direction,
   3861     leveldb::Status* s) {
   3862   IDB_TRACE("IndexedDBBackingStore::OpenIndexCursor");
   3863   LevelDBTransaction* leveldb_transaction = transaction->transaction();
   3864   IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
   3865   if (!IndexCursorOptions(leveldb_transaction,
   3866                           database_id,
   3867                           object_store_id,
   3868                           index_id,
   3869                           range,
   3870                           direction,
   3871                           &cursor_options))
   3872     return scoped_ptr<IndexedDBBackingStore::Cursor>();
   3873   scoped_ptr<IndexCursorImpl> cursor(
   3874       new IndexCursorImpl(this, transaction, database_id, cursor_options));
   3875   if (!cursor->FirstSeek(s))
   3876     return scoped_ptr<IndexedDBBackingStore::Cursor>();
   3877 
   3878   return cursor.PassAs<IndexedDBBackingStore::Cursor>();
   3879 }
   3880 
   3881 IndexedDBBackingStore::Transaction::Transaction(
   3882     IndexedDBBackingStore* backing_store)
   3883     : backing_store_(backing_store), database_id_(-1) {
   3884 }
   3885 
   3886 IndexedDBBackingStore::Transaction::~Transaction() {
   3887   STLDeleteContainerPairSecondPointers(
   3888       blob_change_map_.begin(), blob_change_map_.end());
   3889   STLDeleteContainerPairSecondPointers(incognito_blob_map_.begin(),
   3890                                        incognito_blob_map_.end());
   3891 }
   3892 
   3893 void IndexedDBBackingStore::Transaction::Begin() {
   3894   IDB_TRACE("IndexedDBBackingStore::Transaction::Begin");
   3895   DCHECK(!transaction_.get());
   3896   transaction_ = IndexedDBClassFactory::Get()->CreateLevelDBTransaction(
   3897       backing_store_->db_.get());
   3898 
   3899   // If incognito, this snapshots blobs just as the above transaction_
   3900   // constructor snapshots the leveldb.
   3901   BlobChangeMap::const_iterator iter;
   3902   for (iter = backing_store_->incognito_blob_map_.begin();
   3903        iter != backing_store_->incognito_blob_map_.end();
   3904        ++iter)
   3905     incognito_blob_map_[iter->first] = iter->second->Clone().release();
   3906 }
   3907 
   3908 static GURL getURLFromUUID(const string& uuid) {
   3909   return GURL("blob:uuid/" + uuid);
   3910 }
   3911 
   3912 leveldb::Status IndexedDBBackingStore::Transaction::HandleBlobPreTransaction(
   3913     BlobEntryKeyValuePairVec* new_blob_entries,
   3914     WriteDescriptorVec* new_files_to_write) {
   3915   if (backing_store_->is_incognito())
   3916     return leveldb::Status::OK();
   3917 
   3918   BlobChangeMap::iterator iter = blob_change_map_.begin();
   3919   new_blob_entries->clear();
   3920   new_files_to_write->clear();
   3921   if (iter != blob_change_map_.end()) {
   3922     // Create LevelDBTransaction for the name generator seed and add-journal.
   3923     scoped_refptr<LevelDBTransaction> pre_transaction =
   3924         IndexedDBClassFactory::Get()->CreateLevelDBTransaction(
   3925             backing_store_->db_.get());
   3926     BlobJournalType journal;
   3927     for (; iter != blob_change_map_.end(); ++iter) {
   3928       std::vector<IndexedDBBlobInfo>::iterator info_iter;
   3929       std::vector<IndexedDBBlobInfo*> new_blob_keys;
   3930       for (info_iter = iter->second->mutable_blob_info().begin();
   3931            info_iter != iter->second->mutable_blob_info().end();
   3932            ++info_iter) {
   3933         int64 next_blob_key = -1;
   3934         bool result = GetBlobKeyGeneratorCurrentNumber(
   3935             pre_transaction.get(), database_id_, &next_blob_key);
   3936         if (!result || next_blob_key < 0)
   3937           return InternalInconsistencyStatus();
   3938         BlobJournalEntryType journal_entry =
   3939             std::make_pair(database_id_, next_blob_key);
   3940         journal.push_back(journal_entry);
   3941         if (info_iter->is_file()) {
   3942           new_files_to_write->push_back(
   3943               WriteDescriptor(info_iter->file_path(),
   3944                               next_blob_key,
   3945                               info_iter->size(),
   3946                               info_iter->last_modified()));
   3947         } else {
   3948           new_files_to_write->push_back(
   3949               WriteDescriptor(getURLFromUUID(info_iter->uuid()),
   3950                               next_blob_key,
   3951                               info_iter->size()));
   3952         }
   3953         info_iter->set_key(next_blob_key);
   3954         new_blob_keys.push_back(&*info_iter);
   3955         result = UpdateBlobKeyGeneratorCurrentNumber(
   3956             pre_transaction.get(), database_id_, next_blob_key + 1);
   3957         if (!result)
   3958           return InternalInconsistencyStatus();
   3959       }
   3960       BlobEntryKey blob_entry_key;
   3961       StringPiece key_piece(iter->second->key());
   3962       if (!BlobEntryKey::FromObjectStoreDataKey(&key_piece, &blob_entry_key)) {
   3963         NOTREACHED();
   3964         return InternalInconsistencyStatus();
   3965       }
   3966       new_blob_entries->push_back(
   3967           std::make_pair(blob_entry_key, EncodeBlobData(new_blob_keys)));
   3968     }
   3969     UpdatePrimaryJournalWithBlobList(pre_transaction.get(), journal);
   3970     leveldb::Status s = pre_transaction->Commit();
   3971     if (!s.ok())
   3972       return InternalInconsistencyStatus();
   3973   }
   3974   return leveldb::Status::OK();
   3975 }
   3976 
   3977 bool IndexedDBBackingStore::Transaction::CollectBlobFilesToRemove() {
   3978   if (backing_store_->is_incognito())
   3979     return true;
   3980 
   3981   BlobChangeMap::const_iterator iter = blob_change_map_.begin();
   3982   // Look up all old files to remove as part of the transaction, store their
   3983   // names in blobs_to_remove_, and remove their old blob data entries.
   3984   if (iter != blob_change_map_.end()) {
   3985     for (; iter != blob_change_map_.end(); ++iter) {
   3986       BlobEntryKey blob_entry_key;
   3987       StringPiece key_piece(iter->second->key());
   3988       if (!BlobEntryKey::FromObjectStoreDataKey(&key_piece, &blob_entry_key)) {
   3989         NOTREACHED();
   3990         INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
   3991         transaction_ = NULL;
   3992         return false;
   3993       }
   3994       if (database_id_ < 0)
   3995         database_id_ = blob_entry_key.database_id();
   3996       else
   3997         DCHECK_EQ(database_id_, blob_entry_key.database_id());
   3998       std::string blob_entry_key_bytes = blob_entry_key.Encode();
   3999       bool found;
   4000       std::string blob_entry_value_bytes;
   4001       leveldb::Status s = transaction_->Get(
   4002           blob_entry_key_bytes, &blob_entry_value_bytes, &found);
   4003       if (s.ok() && found) {
   4004         std::vector<IndexedDBBlobInfo> blob_info;
   4005         if (!DecodeBlobData(blob_entry_value_bytes, &blob_info)) {
   4006           INTERNAL_READ_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
   4007           transaction_ = NULL;
   4008           return false;
   4009         }
   4010         std::vector<IndexedDBBlobInfo>::iterator blob_info_iter;
   4011         for (blob_info_iter = blob_info.begin();
   4012              blob_info_iter != blob_info.end();
   4013              ++blob_info_iter)
   4014           blobs_to_remove_.push_back(
   4015               std::make_pair(database_id_, blob_info_iter->key()));
   4016         transaction_->Remove(blob_entry_key_bytes);
   4017       }
   4018     }
   4019   }
   4020   return true;
   4021 }
   4022 
   4023 leveldb::Status IndexedDBBackingStore::Transaction::SortBlobsToRemove() {
   4024   IndexedDBActiveBlobRegistry* registry =
   4025       backing_store_->active_blob_registry();
   4026   BlobJournalType::iterator iter;
   4027   BlobJournalType primary_journal, live_blob_journal;
   4028   for (iter = blobs_to_remove_.begin(); iter != blobs_to_remove_.end();
   4029        ++iter) {
   4030     if (registry->MarkDeletedCheckIfUsed(iter->first, iter->second))
   4031       live_blob_journal.push_back(*iter);
   4032     else
   4033       primary_journal.push_back(*iter);
   4034   }
   4035   UpdatePrimaryJournalWithBlobList(transaction_.get(), primary_journal);
   4036   leveldb::Status s =
   4037       MergeBlobsIntoLiveBlobJournal(transaction_.get(), live_blob_journal);
   4038   if (!s.ok())
   4039     return s;
   4040   // To signal how many blobs need attention right now.
   4041   blobs_to_remove_.swap(primary_journal);
   4042   return leveldb::Status::OK();
   4043 }
   4044 
   4045 leveldb::Status IndexedDBBackingStore::Transaction::CommitPhaseOne(
   4046     scoped_refptr<BlobWriteCallback> callback) {
   4047   IDB_TRACE("IndexedDBBackingStore::Transaction::CommitPhaseOne");
   4048   DCHECK(transaction_.get());
   4049   DCHECK(backing_store_->task_runner()->RunsTasksOnCurrentThread());
   4050 
   4051   leveldb::Status s;
   4052 
   4053   s = backing_store_->CleanUpBlobJournal(BlobJournalKey::Encode());
   4054   if (!s.ok()) {
   4055     INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
   4056     transaction_ = NULL;
   4057     return s;
   4058   }
   4059 
   4060   BlobEntryKeyValuePairVec new_blob_entries;
   4061   WriteDescriptorVec new_files_to_write;
   4062   s = HandleBlobPreTransaction(&new_blob_entries, &new_files_to_write);
   4063   if (!s.ok()) {
   4064     INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
   4065     transaction_ = NULL;
   4066     return s;
   4067   }
   4068 
   4069   DCHECK(!new_files_to_write.size() ||
   4070          KeyPrefix::IsValidDatabaseId(database_id_));
   4071   if (!CollectBlobFilesToRemove()) {
   4072     INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
   4073     transaction_ = NULL;
   4074     return InternalInconsistencyStatus();
   4075   }
   4076 
   4077   if (new_files_to_write.size()) {
   4078     // This kicks off the writes of the new blobs, if any.
   4079     // This call will zero out new_blob_entries and new_files_to_write.
   4080     WriteNewBlobs(&new_blob_entries, &new_files_to_write, callback);
   4081     // Remove the add journal, if any; once the blobs are written, and we
   4082     // commit, this will do the cleanup.
   4083     ClearBlobJournal(transaction_.get(), BlobJournalKey::Encode());
   4084   } else {
   4085     callback->Run(true);
   4086   }
   4087 
   4088   return leveldb::Status::OK();
   4089 }
   4090 
   4091 leveldb::Status IndexedDBBackingStore::Transaction::CommitPhaseTwo() {
   4092   IDB_TRACE("IndexedDBBackingStore::Transaction::CommitPhaseTwo");
   4093   leveldb::Status s;
   4094   if (blobs_to_remove_.size()) {
   4095     s = SortBlobsToRemove();
   4096     if (!s.ok()) {
   4097       INTERNAL_READ_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
   4098       transaction_ = NULL;
   4099       return s;
   4100     }
   4101   }
   4102 
   4103   s = transaction_->Commit();
   4104   transaction_ = NULL;
   4105 
   4106   if (s.ok() && backing_store_->is_incognito() && !blob_change_map_.empty()) {
   4107     BlobChangeMap& target_map = backing_store_->incognito_blob_map_;
   4108     BlobChangeMap::iterator iter;
   4109     for (iter = blob_change_map_.begin(); iter != blob_change_map_.end();
   4110          ++iter) {
   4111       BlobChangeMap::iterator target_record = target_map.find(iter->first);
   4112       if (target_record != target_map.end()) {
   4113         delete target_record->second;
   4114         target_map.erase(target_record);
   4115       }
   4116       if (iter->second) {
   4117         target_map[iter->first] = iter->second;
   4118         iter->second = NULL;
   4119       }
   4120     }
   4121   }
   4122   if (!s.ok())
   4123     INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
   4124   else if (blobs_to_remove_.size())
   4125     s = backing_store_->CleanUpBlobJournal(BlobJournalKey::Encode());
   4126 
   4127   return s;
   4128 }
   4129 
   4130 
   4131 class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper
   4132     : public IndexedDBBackingStore::BlobWriteCallback {
   4133  public:
   4134   BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction,
   4135                            scoped_refptr<BlobWriteCallback> callback)
   4136       : transaction_(transaction), callback_(callback) {}
   4137   virtual void Run(bool succeeded) OVERRIDE {
   4138     callback_->Run(succeeded);
   4139     if (succeeded)  // Else it's already been deleted during rollback.
   4140       transaction_->chained_blob_writer_ = NULL;
   4141   }
   4142 
   4143  private:
   4144   virtual ~BlobWriteCallbackWrapper() {}
   4145   friend class base::RefCounted<IndexedDBBackingStore::BlobWriteCallback>;
   4146 
   4147   IndexedDBBackingStore::Transaction* transaction_;
   4148   scoped_refptr<BlobWriteCallback> callback_;
   4149 
   4150   DISALLOW_COPY_AND_ASSIGN(BlobWriteCallbackWrapper);
   4151 };
   4152 
   4153 void IndexedDBBackingStore::Transaction::WriteNewBlobs(
   4154     BlobEntryKeyValuePairVec* new_blob_entries,
   4155     WriteDescriptorVec* new_files_to_write,
   4156     scoped_refptr<BlobWriteCallback> callback) {
   4157   DCHECK_GT(new_files_to_write->size(), 0UL);
   4158   DCHECK_GT(database_id_, 0);
   4159   BlobEntryKeyValuePairVec::iterator blob_entry_iter;
   4160   for (blob_entry_iter = new_blob_entries->begin();
   4161        blob_entry_iter != new_blob_entries->end();
   4162        ++blob_entry_iter) {
   4163     // Add the new blob-table entry for each blob to the main transaction, or
   4164     // remove any entry that may exist if there's no new one.
   4165     if (!blob_entry_iter->second.size())
   4166       transaction_->Remove(blob_entry_iter->first.Encode());
   4167     else
   4168       transaction_->Put(blob_entry_iter->first.Encode(),
   4169                         &blob_entry_iter->second);
   4170   }
   4171   // Creating the writer will start it going asynchronously.
   4172   chained_blob_writer_ =
   4173       new ChainedBlobWriterImpl(database_id_,
   4174                                 backing_store_,
   4175                                 new_files_to_write,
   4176                                 new BlobWriteCallbackWrapper(this, callback));
   4177 }
   4178 
   4179 void IndexedDBBackingStore::Transaction::Rollback() {
   4180   IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback");
   4181   if (chained_blob_writer_.get()) {
   4182     chained_blob_writer_->Abort();
   4183     chained_blob_writer_ = NULL;
   4184   }
   4185   if (transaction_.get() == NULL)
   4186     return;
   4187   transaction_->Rollback();
   4188   transaction_ = NULL;
   4189 }
   4190 
   4191 IndexedDBBackingStore::BlobChangeRecord::BlobChangeRecord(
   4192     const std::string& key,
   4193     int64 object_store_id)
   4194     : key_(key), object_store_id_(object_store_id) {
   4195 }
   4196 
   4197 IndexedDBBackingStore::BlobChangeRecord::~BlobChangeRecord() {
   4198 }
   4199 
   4200 void IndexedDBBackingStore::BlobChangeRecord::SetBlobInfo(
   4201     std::vector<IndexedDBBlobInfo>* blob_info) {
   4202   blob_info_.clear();
   4203   if (blob_info)
   4204     blob_info_.swap(*blob_info);
   4205 }
   4206 
   4207 void IndexedDBBackingStore::BlobChangeRecord::SetHandles(
   4208     ScopedVector<storage::BlobDataHandle>* handles) {
   4209   handles_.clear();
   4210   if (handles)
   4211     handles_.swap(*handles);
   4212 }
   4213 
   4214 scoped_ptr<IndexedDBBackingStore::BlobChangeRecord>
   4215 IndexedDBBackingStore::BlobChangeRecord::Clone() const {
   4216   scoped_ptr<IndexedDBBackingStore::BlobChangeRecord> record(
   4217       new BlobChangeRecord(key_, object_store_id_));
   4218   record->blob_info_ = blob_info_;
   4219 
   4220   ScopedVector<storage::BlobDataHandle>::const_iterator iter;
   4221   for (iter = handles_.begin(); iter != handles_.end(); ++iter)
   4222     record->handles_.push_back(new storage::BlobDataHandle(**iter));
   4223   return record.Pass();
   4224 }
   4225 
   4226 leveldb::Status IndexedDBBackingStore::Transaction::PutBlobInfoIfNeeded(
   4227     int64 database_id,
   4228     int64 object_store_id,
   4229     const std::string& object_store_data_key,
   4230     std::vector<IndexedDBBlobInfo>* blob_info,
   4231     ScopedVector<storage::BlobDataHandle>* handles) {
   4232   if (!blob_info || blob_info->empty()) {
   4233     blob_change_map_.erase(object_store_data_key);
   4234     incognito_blob_map_.erase(object_store_data_key);
   4235 
   4236     BlobEntryKey blob_entry_key;
   4237     StringPiece leveldb_key_piece(object_store_data_key);
   4238     if (!BlobEntryKey::FromObjectStoreDataKey(&leveldb_key_piece,
   4239                                               &blob_entry_key)) {
   4240       NOTREACHED();
   4241       return InternalInconsistencyStatus();
   4242     }
   4243     std::string value;
   4244     bool found = false;
   4245     leveldb::Status s =
   4246         transaction()->Get(blob_entry_key.Encode(), &value, &found);
   4247     if (!s.ok())
   4248       return s;
   4249     if (!found)
   4250       return leveldb::Status::OK();
   4251   }
   4252   PutBlobInfo(
   4253       database_id, object_store_id, object_store_data_key, blob_info, handles);
   4254   return leveldb::Status::OK();
   4255 }
   4256 
   4257 // This is storing an info, even if empty, even if the previous key had no blob
   4258 // info that we know of.  It duplicates a bunch of information stored in the
   4259 // leveldb transaction, but only w.r.t. the user keys altered--we don't keep the
   4260 // changes to exists or index keys here.
   4261 void IndexedDBBackingStore::Transaction::PutBlobInfo(
   4262     int64 database_id,
   4263     int64 object_store_id,
   4264     const std::string& object_store_data_key,
   4265     std::vector<IndexedDBBlobInfo>* blob_info,
   4266     ScopedVector<storage::BlobDataHandle>* handles) {
   4267   DCHECK_GT(object_store_data_key.size(), 0UL);
   4268   if (database_id_ < 0)
   4269     database_id_ = database_id;
   4270   DCHECK_EQ(database_id_, database_id);
   4271 
   4272   BlobChangeMap::iterator it = blob_change_map_.find(object_store_data_key);
   4273   BlobChangeRecord* record = NULL;
   4274   if (it == blob_change_map_.end()) {
   4275     record = new BlobChangeRecord(object_store_data_key, object_store_id);
   4276     blob_change_map_[object_store_data_key] = record;
   4277   } else {
   4278     record = it->second;
   4279   }
   4280   DCHECK_EQ(record->object_store_id(), object_store_id);
   4281   record->SetBlobInfo(blob_info);
   4282   record->SetHandles(handles);
   4283   DCHECK(!handles || !handles->size());
   4284 }
   4285 
   4286 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
   4287     const GURL& url,
   4288     int64_t key,
   4289     int64_t size)
   4290     : is_file_(false), url_(url), key_(key), size_(size) {
   4291 }
   4292 
   4293 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
   4294     const FilePath& file_path,
   4295     int64_t key,
   4296     int64_t size,
   4297     base::Time last_modified)
   4298     : is_file_(true),
   4299       file_path_(file_path),
   4300       key_(key),
   4301       size_(size),
   4302       last_modified_(last_modified) {
   4303 }
   4304 
   4305 }  // namespace content
   4306