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