Chromium Code Reviews| Index: webkit/dom_storage/local_storage_database.cc |
| diff --git a/webkit/dom_storage/local_storage_database.cc b/webkit/dom_storage/local_storage_database.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..95717c164d32d968a0cf9dd49c9e1019d3f15a43 |
| --- /dev/null |
| +++ b/webkit/dom_storage/local_storage_database.cc |
| @@ -0,0 +1,154 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "webkit/dom_storage/local_storage_database.h" |
| + |
| +#include <string> |
| + |
| +#include "base/logging.h" |
| +#include "base/utf_string_conversions.h" |
| +#include "sql/statement.h" |
| +#include "sql/transaction.h" |
| + |
| +namespace dom_storage { |
| + |
| +LocalStorageDatabase::LocalStorageDatabase(const FilePath& file_path) |
| + : file_path_(file_path), |
| + db_(NULL) { |
| +} |
| + |
| +LocalStorageDatabase::~LocalStorageDatabase() { |
| + if (IsOpen()) |
| + Close(); |
| +} |
| + |
| +bool LocalStorageDatabase::Open() { |
| + if (IsOpen()) |
| + return true; |
| + |
| + db_.reset(new sql::Connection()); |
| + bool is_open = db_->Open(file_path_); |
|
michaeln
2012/01/24 00:18:16
WebCore uses sqlite3_open16 where as the sql::Conn
benm (inactive)
2012/01/24 10:47:01
Good spot!
|
| + |
| + if (!is_open) |
| + LOG(WARNING) << "Unable to open Database at " << file_path_.value(); |
| + |
| + meta_table_.Init(db_.get(), 1, 1); |
|
michaeln
2012/01/24 00:18:16
... similarly, since this isn't in the current sch
benm (inactive)
2012/01/24 10:47:01
Fair enough, but this won't stop us using a WebCor
|
| + |
| + return is_open; |
| +} |
| + |
| +bool LocalStorageDatabase::Init() { |
| + if (!IsOpen()) |
| + return false; |
| + |
| + if (db_->DoesTableExist("ItemTable")) { |
| + bool success = UpgradeVersion1To2IfNeeded(); |
| + if (success) |
| + meta_table_.SetVersionNumber(2); |
| + return success; |
| + } else |
| + return CreateTable(); |
| +} |
| + |
| +void LocalStorageDatabase::Close() { |
| + if (!IsOpen()) |
| + return; |
| + |
| + DCHECK(db_.get()); |
| + |
| + meta_table_.Reset(); |
| + |
| + db_->Close(); |
| + db_.reset(NULL); |
| +} |
| + |
| +bool LocalStorageDatabase::CreateTable() { |
| + if (!IsOpen()) |
| + return false; |
| + |
| + bool success = db_->Execute( |
| + "CREATE TABLE IF NOT EXISTS ItemTable (" |
| + "key TEXT UNIQUE ON CONFLICT REPLACE, " |
| + "value BLOB NOT NULL ON CONFLICT FAIL)"); |
| + if (success) |
| + meta_table_.SetVersionNumber(2); |
| + return success; |
| +} |
| + |
| +std::map<string16, string16> LocalStorageDatabase::ReadAllValues() const { |
| + std::map<string16, string16> values; |
| + if (!IsOpen()) |
| + return values; |
| + |
| + sql::Statement stmt(db_->GetCachedStatement(SQL_FROM_HERE, |
| + "SELECT * from ItemTable")); |
| + DCHECK(stmt.is_valid()); |
| + if (stmt) { |
| + while (stmt.Step()) { |
| + string16 key = stmt.ColumnString16(0); |
| + |
| + std::string result; |
| + stmt.ColumnBlobAsString(1, &result); |
| + string16 value = UTF8ToUTF16(result); |
| + values[key] = value; |
| + } |
| + } |
| + |
| + return values; |
| +} |
| + |
| +bool LocalStorageDatabase::WriteAllValues( |
| + const std::map<string16, string16>& values) { |
| + if (!IsOpen()) |
| + return false; |
| + |
| + std::map<string16, string16>::const_iterator it = values.begin(); |
| + for(; it != values.end(); ++it) { |
| + sql::Statement stmt(db_->GetCachedStatement(SQL_FROM_HERE, |
| + "INSERT INTO ItemTable VALUES (?,?)")); |
| + string16 key = it->first; |
| + string16 value = it->second; |
| + stmt.BindString16(0, key); |
| + stmt.BindBlob(1, UTF16ToUTF8(value).c_str(), value.size()); |
| + DCHECK(stmt.is_valid()); |
| + stmt.Run(); |
| + } |
| + return true; |
| +} |
| + |
| +bool LocalStorageDatabase::UpgradeVersion1To2IfNeeded() { |
|
michaeln
2012/01/24 00:18:16
Code to utilize the new schema has been in used fo
benm (inactive)
2012/01/24 10:47:01
I wondered about that too, but the upgrade process
|
| + sql::Statement stmt(db_->GetCachedStatement(SQL_FROM_HERE, |
| + "SELECT value FROM ItemTable")); |
| + DCHECK(stmt.is_valid()); |
| + if (!stmt) |
| + return false; |
| + |
| + // Quick check to see if we need to upgrade or not. |
| + if (stmt.DeclaredColumnType(0) == sql::COLUMN_TYPE_BLOB) |
| + return true; |
| + |
| + // Need to migrate from TEXT value column to BLOB. |
| + std::map<string16, string16> values; |
| + while (stmt.Step()) { |
| + string16 key = stmt.ColumnString16(0); |
| + string16 value = stmt.ColumnString16(1); |
| + values[key] = value; |
| + } |
| + |
| + { |
| + sql::Transaction migration(db_.get()); |
| + if (migration.Begin()) { |
| + if (db_->Execute("DROP TABLE ItemTable")) { |
| + CreateTable(); |
| + if (WriteAllValues(values)) { |
| + migration.Commit(); |
| + return true; |
| + } |
| + } |
| + } |
| + } |
| + return false; |
| +} |
| + |
| +} // namespace dom_storage |