1 // Copyright (c) 2011 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 "chrome/browser/webdata/token_service_table.h" 6 7 #include <map> 8 #include <string> 9 10 #include "base/logging.h" 11 #include "components/webdata/common/web_database.h" 12 #include "components/webdata/encryptor/encryptor.h" 13 #include "sql/statement.h" 14 15 namespace { 16 17 WebDatabaseTable::TypeKey GetKey() { 18 // We just need a unique constant. Use the address of a static that 19 // COMDAT folding won't touch in an optimizing linker. 20 static int table_key = 0; 21 return reinterpret_cast<void*>(&table_key); 22 } 23 24 } // namespace 25 26 TokenServiceTable* TokenServiceTable::FromWebDatabase(WebDatabase* db) { 27 return static_cast<TokenServiceTable*>(db->GetTable(GetKey())); 28 29 } 30 31 WebDatabaseTable::TypeKey TokenServiceTable::GetTypeKey() const { 32 return GetKey(); 33 } 34 35 bool TokenServiceTable::Init(sql::Connection* db, sql::MetaTable* meta_table) { 36 WebDatabaseTable::Init(db, meta_table); 37 if (!db_->DoesTableExist("token_service")) { 38 if (!db_->Execute("CREATE TABLE token_service (" 39 "service VARCHAR PRIMARY KEY NOT NULL," 40 "encrypted_token BLOB)")) { 41 NOTREACHED(); 42 return false; 43 } 44 } 45 return true; 46 } 47 48 bool TokenServiceTable::IsSyncable() { 49 return true; 50 } 51 52 bool TokenServiceTable::MigrateToVersion(int version, 53 bool* update_compatible_version) { 54 return true; 55 } 56 57 bool TokenServiceTable::RemoveAllTokens() { 58 sql::Statement s(db_->GetUniqueStatement( 59 "DELETE FROM token_service")); 60 61 return s.Run(); 62 } 63 64 bool TokenServiceTable::RemoveTokenForService(const std::string& service) { 65 sql::Statement s(db_->GetUniqueStatement( 66 "DELETE FROM token_service WHERE service = ?")); 67 s.BindString(0, service); 68 69 return s.Run(); 70 } 71 72 bool TokenServiceTable::SetTokenForService(const std::string& service, 73 const std::string& token) { 74 std::string encrypted_token; 75 bool encrypted = Encryptor::EncryptString(token, &encrypted_token); 76 if (!encrypted) { 77 return false; 78 } 79 80 // Don't bother with a cached statement since this will be a relatively 81 // infrequent operation. 82 sql::Statement s(db_->GetUniqueStatement( 83 "INSERT OR REPLACE INTO token_service " 84 "(service, encrypted_token) VALUES (?, ?)")); 85 s.BindString(0, service); 86 s.BindBlob(1, encrypted_token.data(), 87 static_cast<int>(encrypted_token.length())); 88 89 return s.Run(); 90 } 91 92 bool TokenServiceTable::GetAllTokens( 93 std::map<std::string, std::string>* tokens) { 94 sql::Statement s(db_->GetUniqueStatement( 95 "SELECT service, encrypted_token FROM token_service")); 96 97 if (!s.is_valid()) 98 return false; 99 100 while (s.Step()) { 101 std::string encrypted_token; 102 std::string decrypted_token; 103 std::string service; 104 service = s.ColumnString(0); 105 bool entry_ok = !service.empty() && 106 s.ColumnBlobAsString(1, &encrypted_token); 107 if (entry_ok) { 108 Encryptor::DecryptString(encrypted_token, &decrypted_token); 109 (*tokens)[service] = decrypted_token; 110 } else { 111 NOTREACHED(); 112 return false; 113 } 114 } 115 return true; 116 } 117