15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/webdata/token_service_table.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "components/webdata/common/web_database.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/webdata/encryptor/encryptor.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/statement.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebDatabaseTable::TypeKey GetKey() {
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We just need a unique constant. Use the address of a static that
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // COMDAT folding won't touch in an optimizing linker.
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  static int table_key = 0;
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return reinterpret_cast<void*>(&table_key);
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TokenServiceTable* TokenServiceTable::FromWebDatabase(WebDatabase* db) {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return static_cast<TokenServiceTable*>(db->GetTable(GetKey()));
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebDatabaseTable::TypeKey TokenServiceTable::GetTypeKey() const {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return GetKey();
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TokenServiceTable::Init(sql::Connection* db, sql::MetaTable* meta_table) {
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WebDatabaseTable::Init(db, meta_table);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!db_->DoesTableExist("token_service")) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!db_->Execute("CREATE TABLE token_service ("
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "service VARCHAR PRIMARY KEY NOT NULL,"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "encrypted_token BLOB)")) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TokenServiceTable::IsSyncable() {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TokenServiceTable::MigrateToVersion(int version,
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         bool* update_compatible_version) {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TokenServiceTable::RemoveAllTokens() {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement s(db_->GetUniqueStatement(
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "DELETE FROM token_service"));
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return s.Run();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool TokenServiceTable::RemoveTokenForService(const std::string& service) {
65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  sql::Statement s(db_->GetUniqueStatement(
66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      "DELETE FROM token_service WHERE service = ?"));
67a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  s.BindString(0, service);
68a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
69a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return s.Run();
70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TokenServiceTable::SetTokenForService(const std::string& service,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const std::string& token) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string encrypted_token;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool encrypted = Encryptor::EncryptString(token, &encrypted_token);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!encrypted) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't bother with a cached statement since this will be a relatively
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // infrequent operation.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement s(db_->GetUniqueStatement(
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "INSERT OR REPLACE INTO token_service "
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "(service, encrypted_token) VALUES (?, ?)"));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s.BindString(0, service);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s.BindBlob(1, encrypted_token.data(),
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             static_cast<int>(encrypted_token.length()));
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return s.Run();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TokenServiceTable::GetAllTokens(
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::map<std::string, std::string>* tokens) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sql::Statement s(db_->GetUniqueStatement(
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "SELECT service, encrypted_token FROM token_service"));
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!s.is_valid())
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (s.Step()) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string encrypted_token;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string decrypted_token;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string service;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service = s.ColumnString(0);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool entry_ok = !service.empty() &&
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    s.ColumnBlobAsString(1, &encrypted_token);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (entry_ok) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Encryptor::DecryptString(encrypted_token, &decrypted_token);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (*tokens)[service] = decrypted_token;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
117