| // Copyright (c) 2011 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 "chrome/browser/webdata/token_service_table.h" |
| |
| #include <map> |
| #include <string> |
| |
| #include "base/logging.h" |
| #include "components/webdata/common/web_database.h" |
| #include "components/webdata/encryptor/encryptor.h" |
| #include "sql/statement.h" |
| |
| namespace { |
| |
| WebDatabaseTable::TypeKey GetKey() { |
| // We just need a unique constant. Use the address of a static that |
| // COMDAT folding won't touch in an optimizing linker. |
| static int table_key = 0; |
| return reinterpret_cast<void*>(&table_key); |
| } |
| |
| } // namespace |
| |
| TokenServiceTable* TokenServiceTable::FromWebDatabase(WebDatabase* db) { |
| return static_cast<TokenServiceTable*>(db->GetTable(GetKey())); |
| |
| } |
| |
| WebDatabaseTable::TypeKey TokenServiceTable::GetTypeKey() const { |
| return GetKey(); |
| } |
| |
| bool TokenServiceTable::Init(sql::Connection* db, sql::MetaTable* meta_table) { |
| WebDatabaseTable::Init(db, meta_table); |
| if (!db_->DoesTableExist("token_service")) { |
| if (!db_->Execute("CREATE TABLE token_service (" |
| "service VARCHAR PRIMARY KEY NOT NULL," |
| "encrypted_token BLOB)")) { |
| NOTREACHED(); |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| bool TokenServiceTable::IsSyncable() { |
| return true; |
| } |
| |
| bool TokenServiceTable::MigrateToVersion(int version, |
| bool* update_compatible_version) { |
| return true; |
| } |
| |
| bool TokenServiceTable::RemoveAllTokens() { |
| sql::Statement s(db_->GetUniqueStatement( |
| "DELETE FROM token_service")); |
| |
| return s.Run(); |
| } |
| |
| bool TokenServiceTable::RemoveTokenForService(const std::string& service) { |
| sql::Statement s(db_->GetUniqueStatement( |
| "DELETE FROM token_service WHERE service = ?")); |
| s.BindString(0, service); |
| |
| return s.Run(); |
| } |
| |
| bool TokenServiceTable::SetTokenForService(const std::string& service, |
| const std::string& token) { |
| std::string encrypted_token; |
| bool encrypted = Encryptor::EncryptString(token, &encrypted_token); |
| if (!encrypted) { |
| return false; |
| } |
| |
| // Don't bother with a cached statement since this will be a relatively |
| // infrequent operation. |
| sql::Statement s(db_->GetUniqueStatement( |
| "INSERT OR REPLACE INTO token_service " |
| "(service, encrypted_token) VALUES (?, ?)")); |
| s.BindString(0, service); |
| s.BindBlob(1, encrypted_token.data(), |
| static_cast<int>(encrypted_token.length())); |
| |
| return s.Run(); |
| } |
| |
| bool TokenServiceTable::GetAllTokens( |
| std::map<std::string, std::string>* tokens) { |
| sql::Statement s(db_->GetUniqueStatement( |
| "SELECT service, encrypted_token FROM token_service")); |
| |
| if (!s.is_valid()) |
| return false; |
| |
| while (s.Step()) { |
| std::string encrypted_token; |
| std::string decrypted_token; |
| std::string service; |
| service = s.ColumnString(0); |
| bool entry_ok = !service.empty() && |
| s.ColumnBlobAsString(1, &encrypted_token); |
| if (entry_ok) { |
| Encryptor::DecryptString(encrypted_token, &decrypted_token); |
| (*tokens)[service] = decrypted_token; |
| } else { |
| NOTREACHED(); |
| return false; |
| } |
| } |
| return true; |
| } |