| Index: content/browser/media/webrtc/webrtc_identity_store_backend.cc
|
| diff --git a/content/browser/media/webrtc/webrtc_identity_store_backend.cc b/content/browser/media/webrtc/webrtc_identity_store_backend.cc
|
| deleted file mode 100644
|
| index dc247b7a3a7dda0c6687d6ab0f82e91a55e8053d..0000000000000000000000000000000000000000
|
| --- a/content/browser/media/webrtc/webrtc_identity_store_backend.cc
|
| +++ /dev/null
|
| @@ -1,610 +0,0 @@
|
| -// Copyright 2013 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 "content/browser/media/webrtc/webrtc_identity_store_backend.h"
|
| -
|
| -#include <stddef.h>
|
| -#include <stdint.h>
|
| -
|
| -#include <tuple>
|
| -
|
| -#include "base/files/file_path.h"
|
| -#include "base/files/file_util.h"
|
| -#include "base/macros.h"
|
| -#include "base/memory/scoped_vector.h"
|
| -#include "base/strings/string_util.h"
|
| -#include "content/public/browser/browser_thread.h"
|
| -#include "net/base/net_errors.h"
|
| -#include "sql/statement.h"
|
| -#include "sql/transaction.h"
|
| -#include "storage/browser/quota/special_storage_policy.h"
|
| -#include "url/gurl.h"
|
| -
|
| -namespace content {
|
| -
|
| -static const char kWebRTCIdentityStoreDBName[] = "webrtc_identity_store";
|
| -
|
| -static const base::FilePath::CharType kWebRTCIdentityStoreDirectory[] =
|
| - FILE_PATH_LITERAL("WebRTCIdentityStore");
|
| -
|
| -// Initializes the identity table, returning true on success.
|
| -static bool InitDB(sql::Connection* db) {
|
| - if (db->DoesTableExist(kWebRTCIdentityStoreDBName)) {
|
| - if (db->DoesColumnExist(kWebRTCIdentityStoreDBName, "origin") &&
|
| - db->DoesColumnExist(kWebRTCIdentityStoreDBName, "identity_name") &&
|
| - db->DoesColumnExist(kWebRTCIdentityStoreDBName, "common_name") &&
|
| - db->DoesColumnExist(kWebRTCIdentityStoreDBName, "certificate") &&
|
| - db->DoesColumnExist(kWebRTCIdentityStoreDBName, "private_key") &&
|
| - db->DoesColumnExist(kWebRTCIdentityStoreDBName, "creation_time"))
|
| - return true;
|
| -
|
| - if (!db->Execute("DROP TABLE webrtc_identity_store"))
|
| - return false;
|
| - }
|
| -
|
| - return db->Execute(
|
| - "CREATE TABLE webrtc_identity_store"
|
| - " ("
|
| - "origin TEXT NOT NULL,"
|
| - "identity_name TEXT NOT NULL,"
|
| - "common_name TEXT NOT NULL,"
|
| - "certificate BLOB NOT NULL,"
|
| - "private_key BLOB NOT NULL,"
|
| - "creation_time INTEGER)");
|
| -}
|
| -
|
| -struct WebRTCIdentityStoreBackend::IdentityKey {
|
| - IdentityKey(const GURL& origin, const std::string& identity_name)
|
| - : origin(origin), identity_name(identity_name) {}
|
| -
|
| - bool operator<(const IdentityKey& other) const {
|
| - return std::tie(origin, identity_name) <
|
| - std::tie(other.origin, other.identity_name);
|
| - }
|
| -
|
| - GURL origin;
|
| - std::string identity_name;
|
| -};
|
| -
|
| -struct WebRTCIdentityStoreBackend::Identity {
|
| - Identity(const std::string& common_name,
|
| - const std::string& certificate,
|
| - const std::string& private_key)
|
| - : common_name(common_name),
|
| - certificate(certificate),
|
| - private_key(private_key),
|
| - creation_time(base::Time::Now().ToInternalValue()) {}
|
| -
|
| - Identity(const std::string& common_name,
|
| - const std::string& certificate,
|
| - const std::string& private_key,
|
| - int64_t creation_time)
|
| - : common_name(common_name),
|
| - certificate(certificate),
|
| - private_key(private_key),
|
| - creation_time(creation_time) {}
|
| -
|
| - std::string common_name;
|
| - std::string certificate;
|
| - std::string private_key;
|
| - int64_t creation_time;
|
| -};
|
| -
|
| -struct WebRTCIdentityStoreBackend::PendingFindRequest {
|
| - PendingFindRequest(const GURL& origin,
|
| - const std::string& identity_name,
|
| - const std::string& common_name,
|
| - const FindIdentityCallback& callback)
|
| - : origin(origin),
|
| - identity_name(identity_name),
|
| - common_name(common_name),
|
| - callback(callback) {}
|
| -
|
| - ~PendingFindRequest() {}
|
| -
|
| - GURL origin;
|
| - std::string identity_name;
|
| - std::string common_name;
|
| - FindIdentityCallback callback;
|
| -};
|
| -
|
| -// The class encapsulates the database operations. All members except ctor and
|
| -// dtor should be accessed on the DB thread.
|
| -// It can be created/destroyed on any thread.
|
| -class WebRTCIdentityStoreBackend::SqlLiteStorage
|
| - : public base::RefCountedThreadSafe<SqlLiteStorage> {
|
| - public:
|
| - SqlLiteStorage(base::TimeDelta validity_period,
|
| - const base::FilePath& path,
|
| - storage::SpecialStoragePolicy* policy)
|
| - : validity_period_(validity_period), special_storage_policy_(policy) {
|
| - if (!path.empty())
|
| - path_ = path.Append(kWebRTCIdentityStoreDirectory);
|
| - }
|
| -
|
| - void Load(IdentityMap* out_map);
|
| - void Close();
|
| - void AddIdentity(const GURL& origin,
|
| - const std::string& identity_name,
|
| - const Identity& identity);
|
| - void DeleteIdentity(const GURL& origin,
|
| - const std::string& identity_name,
|
| - const Identity& identity);
|
| - void DeleteBetween(base::Time delete_begin, base::Time delete_end);
|
| -
|
| - void SetValidityPeriodForTesting(base::TimeDelta validity_period) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::DB);
|
| - DCHECK(!db_.get());
|
| - validity_period_ = validity_period;
|
| - }
|
| -
|
| - private:
|
| - friend class base::RefCountedThreadSafe<SqlLiteStorage>;
|
| -
|
| - enum OperationType {
|
| - ADD_IDENTITY,
|
| - DELETE_IDENTITY
|
| - };
|
| - struct PendingOperation {
|
| - PendingOperation(OperationType type,
|
| - const GURL& origin,
|
| - const std::string& identity_name,
|
| - const Identity& identity)
|
| - : type(type),
|
| - origin(origin),
|
| - identity_name(identity_name),
|
| - identity(identity) {}
|
| -
|
| - OperationType type;
|
| - GURL origin;
|
| - std::string identity_name;
|
| - Identity identity;
|
| - };
|
| - typedef ScopedVector<PendingOperation> PendingOperationList;
|
| -
|
| - virtual ~SqlLiteStorage() {}
|
| - void OnDatabaseError(int error, sql::Statement* stmt);
|
| - void BatchOperation(OperationType type,
|
| - const GURL& origin,
|
| - const std::string& identity_name,
|
| - const Identity& identity);
|
| - void Commit();
|
| -
|
| - base::TimeDelta validity_period_;
|
| - // The file path of the DB. Empty if temporary.
|
| - base::FilePath path_;
|
| - scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
|
| - std::unique_ptr<sql::Connection> db_;
|
| - // Batched DB operations pending to commit.
|
| - PendingOperationList pending_operations_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(SqlLiteStorage);
|
| -};
|
| -
|
| -WebRTCIdentityStoreBackend::WebRTCIdentityStoreBackend(
|
| - const base::FilePath& path,
|
| - storage::SpecialStoragePolicy* policy,
|
| - base::TimeDelta validity_period)
|
| - : validity_period_(validity_period),
|
| - state_(NOT_STARTED),
|
| - sql_lite_storage_(new SqlLiteStorage(validity_period, path, policy)) {
|
| -}
|
| -
|
| -bool WebRTCIdentityStoreBackend::FindIdentity(
|
| - const GURL& origin,
|
| - const std::string& identity_name,
|
| - const std::string& common_name,
|
| - const FindIdentityCallback& callback) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - if (state_ == CLOSED)
|
| - return false;
|
| -
|
| - if (state_ != LOADED) {
|
| - // Queues the request to wait for the DB to load.
|
| - pending_find_requests_.push_back(
|
| - new PendingFindRequest(origin, identity_name, common_name, callback));
|
| - if (state_ == LOADING)
|
| - return true;
|
| -
|
| - DCHECK_EQ(state_, NOT_STARTED);
|
| -
|
| - // Kick off loading the DB.
|
| - std::unique_ptr<IdentityMap> out_map(new IdentityMap());
|
| - base::Closure task(
|
| - base::Bind(&SqlLiteStorage::Load, sql_lite_storage_, out_map.get()));
|
| - // |out_map| will be NULL after this call.
|
| - if (BrowserThread::PostTaskAndReply(
|
| - BrowserThread::DB,
|
| - FROM_HERE,
|
| - task,
|
| - base::Bind(&WebRTCIdentityStoreBackend::OnLoaded,
|
| - this,
|
| - base::Passed(&out_map)))) {
|
| - state_ = LOADING;
|
| - return true;
|
| - }
|
| - // If it fails to post task, falls back to ERR_FILE_NOT_FOUND.
|
| - }
|
| -
|
| - IdentityKey key(origin, identity_name);
|
| - IdentityMap::iterator iter = identities_.find(key);
|
| - if (iter != identities_.end() && iter->second.common_name == common_name) {
|
| - base::TimeDelta age = base::Time::Now() - base::Time::FromInternalValue(
|
| - iter->second.creation_time);
|
| - if (age < validity_period_) {
|
| - // Identity found.
|
| - return BrowserThread::PostTask(BrowserThread::IO,
|
| - FROM_HERE,
|
| - base::Bind(callback,
|
| - net::OK,
|
| - iter->second.certificate,
|
| - iter->second.private_key));
|
| - }
|
| - // Removes the expired identity from the in-memory cache. The copy in the
|
| - // database will be removed on the next load.
|
| - identities_.erase(iter);
|
| - }
|
| -
|
| - return BrowserThread::PostTask(
|
| - BrowserThread::IO,
|
| - FROM_HERE,
|
| - base::Bind(callback, net::ERR_FILE_NOT_FOUND, "", ""));
|
| -}
|
| -
|
| -void WebRTCIdentityStoreBackend::AddIdentity(const GURL& origin,
|
| - const std::string& identity_name,
|
| - const std::string& common_name,
|
| - const std::string& certificate,
|
| - const std::string& private_key) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - if (state_ == CLOSED)
|
| - return;
|
| -
|
| - // If there is an existing identity for the same origin and identity_name,
|
| - // delete it.
|
| - IdentityKey key(origin, identity_name);
|
| - Identity identity(common_name, certificate, private_key);
|
| -
|
| - if (identities_.find(key) != identities_.end()) {
|
| - if (!BrowserThread::PostTask(BrowserThread::DB,
|
| - FROM_HERE,
|
| - base::Bind(&SqlLiteStorage::DeleteIdentity,
|
| - sql_lite_storage_,
|
| - origin,
|
| - identity_name,
|
| - identities_.find(key)->second)))
|
| - return;
|
| - }
|
| - identities_.insert(std::pair<IdentityKey, Identity>(key, identity));
|
| -
|
| - BrowserThread::PostTask(BrowserThread::DB,
|
| - FROM_HERE,
|
| - base::Bind(&SqlLiteStorage::AddIdentity,
|
| - sql_lite_storage_,
|
| - origin,
|
| - identity_name,
|
| - identity));
|
| -}
|
| -
|
| -void WebRTCIdentityStoreBackend::Close() {
|
| - if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
|
| - BrowserThread::PostTask(
|
| - BrowserThread::IO,
|
| - FROM_HERE,
|
| - base::Bind(&WebRTCIdentityStoreBackend::Close, this));
|
| - return;
|
| - }
|
| -
|
| - if (state_ == CLOSED)
|
| - return;
|
| -
|
| - state_ = CLOSED;
|
| - BrowserThread::PostTask(
|
| - BrowserThread::DB,
|
| - FROM_HERE,
|
| - base::Bind(&SqlLiteStorage::Close, sql_lite_storage_));
|
| -}
|
| -
|
| -void WebRTCIdentityStoreBackend::DeleteBetween(base::Time delete_begin,
|
| - base::Time delete_end,
|
| - const base::Closure& callback) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - if (state_ == CLOSED)
|
| - return;
|
| -
|
| - // Delete the in-memory cache.
|
| - IdentityMap::iterator it = identities_.begin();
|
| - while (it != identities_.end()) {
|
| - if (it->second.creation_time >= delete_begin.ToInternalValue() &&
|
| - it->second.creation_time <= delete_end.ToInternalValue()) {
|
| - identities_.erase(it++);
|
| - } else {
|
| - ++it;
|
| - }
|
| - }
|
| - BrowserThread::PostTaskAndReply(BrowserThread::DB,
|
| - FROM_HERE,
|
| - base::Bind(&SqlLiteStorage::DeleteBetween,
|
| - sql_lite_storage_,
|
| - delete_begin,
|
| - delete_end),
|
| - callback);
|
| -}
|
| -
|
| -void WebRTCIdentityStoreBackend::SetValidityPeriodForTesting(
|
| - base::TimeDelta validity_period) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - validity_period_ = validity_period;
|
| - BrowserThread::PostTask(
|
| - BrowserThread::DB,
|
| - FROM_HERE,
|
| - base::Bind(&SqlLiteStorage::SetValidityPeriodForTesting,
|
| - sql_lite_storage_,
|
| - validity_period));
|
| -}
|
| -
|
| -WebRTCIdentityStoreBackend::~WebRTCIdentityStoreBackend() {}
|
| -
|
| -void WebRTCIdentityStoreBackend::OnLoaded(
|
| - std::unique_ptr<IdentityMap> out_map) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| -
|
| - if (state_ != LOADING)
|
| - return;
|
| -
|
| - DVLOG(3) << "WebRTC identity store has loaded.";
|
| -
|
| - state_ = LOADED;
|
| - identities_.swap(*out_map);
|
| -
|
| - for (size_t i = 0; i < pending_find_requests_.size(); ++i) {
|
| - FindIdentity(pending_find_requests_[i]->origin,
|
| - pending_find_requests_[i]->identity_name,
|
| - pending_find_requests_[i]->common_name,
|
| - pending_find_requests_[i]->callback);
|
| - delete pending_find_requests_[i];
|
| - }
|
| - pending_find_requests_.clear();
|
| -}
|
| -
|
| -//
|
| -// Implementation of SqlLiteStorage.
|
| -//
|
| -
|
| -void WebRTCIdentityStoreBackend::SqlLiteStorage::Load(IdentityMap* out_map) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::DB);
|
| - DCHECK(!db_.get());
|
| -
|
| - // Ensure the parent directory for storing certs is created before reading
|
| - // from it.
|
| - const base::FilePath dir = path_.DirName();
|
| - if (!base::PathExists(dir) && !base::CreateDirectory(dir)) {
|
| - DVLOG(2) << "Unable to open DB file path.";
|
| - return;
|
| - }
|
| -
|
| - db_.reset(new sql::Connection());
|
| -
|
| - db_->set_error_callback(base::Bind(&SqlLiteStorage::OnDatabaseError, this));
|
| -
|
| - if (!db_->Open(path_)) {
|
| - DVLOG(2) << "Unable to open DB.";
|
| - db_.reset();
|
| - return;
|
| - }
|
| -
|
| - if (!InitDB(db_.get())) {
|
| - DVLOG(2) << "Unable to init DB.";
|
| - db_.reset();
|
| - return;
|
| - }
|
| -
|
| - db_->Preload();
|
| -
|
| - // Delete expired identities.
|
| - DeleteBetween(base::Time(), base::Time::Now() - validity_period_);
|
| -
|
| - // Slurp all the identities into the out_map.
|
| - sql::Statement stmt(db_->GetUniqueStatement(
|
| - "SELECT origin, identity_name, common_name, "
|
| - "certificate, private_key, creation_time "
|
| - "FROM webrtc_identity_store"));
|
| - CHECK(stmt.is_valid());
|
| -
|
| - while (stmt.Step()) {
|
| - IdentityKey key(GURL(stmt.ColumnString(0)), stmt.ColumnString(1));
|
| - std::string common_name(stmt.ColumnString(2));
|
| - std::string cert, private_key;
|
| - stmt.ColumnBlobAsString(3, &cert);
|
| - stmt.ColumnBlobAsString(4, &private_key);
|
| - int64_t creation_time = stmt.ColumnInt64(5);
|
| - std::pair<IdentityMap::iterator, bool> result =
|
| - out_map->insert(std::pair<IdentityKey, Identity>(
|
| - key, Identity(common_name, cert, private_key, creation_time)));
|
| - DCHECK(result.second);
|
| - }
|
| -}
|
| -
|
| -void WebRTCIdentityStoreBackend::SqlLiteStorage::Close() {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::DB);
|
| - Commit();
|
| - db_.reset();
|
| -}
|
| -
|
| -void WebRTCIdentityStoreBackend::SqlLiteStorage::AddIdentity(
|
| - const GURL& origin,
|
| - const std::string& identity_name,
|
| - const Identity& identity) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::DB);
|
| - if (!db_.get())
|
| - return;
|
| -
|
| - // Do not add for session only origins.
|
| - if (special_storage_policy_.get() &&
|
| - !special_storage_policy_->IsStorageProtected(origin) &&
|
| - special_storage_policy_->IsStorageSessionOnly(origin)) {
|
| - return;
|
| - }
|
| - BatchOperation(ADD_IDENTITY, origin, identity_name, identity);
|
| -}
|
| -
|
| -void WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteIdentity(
|
| - const GURL& origin,
|
| - const std::string& identity_name,
|
| - const Identity& identity) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::DB);
|
| - if (!db_.get())
|
| - return;
|
| - BatchOperation(DELETE_IDENTITY, origin, identity_name, identity);
|
| -}
|
| -
|
| -void WebRTCIdentityStoreBackend::SqlLiteStorage::DeleteBetween(
|
| - base::Time delete_begin,
|
| - base::Time delete_end) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::DB);
|
| - if (!db_.get())
|
| - return;
|
| -
|
| - // Commit pending operations first.
|
| - Commit();
|
| -
|
| - sql::Statement del_stmt(db_->GetCachedStatement(
|
| - SQL_FROM_HERE,
|
| - "DELETE FROM webrtc_identity_store"
|
| - " WHERE creation_time >= ? AND creation_time <= ?"));
|
| - CHECK(del_stmt.is_valid());
|
| -
|
| - del_stmt.BindInt64(0, delete_begin.ToInternalValue());
|
| - del_stmt.BindInt64(1, delete_end.ToInternalValue());
|
| -
|
| - sql::Transaction transaction(db_.get());
|
| - if (!transaction.Begin()) {
|
| - DVLOG(2) << "Failed to begin the transaction.";
|
| - return;
|
| - }
|
| -
|
| - if (!del_stmt.Run()) {
|
| - DVLOG(2) << "Failed to run the delete statement.";
|
| - return;
|
| - }
|
| -
|
| - if (!transaction.Commit())
|
| - DVLOG(2) << "Failed to commit the transaction.";
|
| -}
|
| -
|
| -void WebRTCIdentityStoreBackend::SqlLiteStorage::OnDatabaseError(
|
| - int error,
|
| - sql::Statement* stmt) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::DB);
|
| -
|
| - db_->RazeAndClose();
|
| - // It's not safe to reset |db_| here.
|
| -}
|
| -
|
| -void WebRTCIdentityStoreBackend::SqlLiteStorage::BatchOperation(
|
| - OperationType type,
|
| - const GURL& origin,
|
| - const std::string& identity_name,
|
| - const Identity& identity) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::DB);
|
| - // Commit every 30 seconds.
|
| - static const base::TimeDelta kCommitInterval(
|
| - base::TimeDelta::FromSeconds(30));
|
| - // Commit right away if we have more than 512 outstanding operations.
|
| - static const size_t kCommitAfterBatchSize = 512;
|
| -
|
| - // We do a full copy of the cert here, and hopefully just here.
|
| - std::unique_ptr<PendingOperation> operation(
|
| - new PendingOperation(type, origin, identity_name, identity));
|
| -
|
| - pending_operations_.push_back(operation.release());
|
| -
|
| - if (pending_operations_.size() == 1) {
|
| - // We've gotten our first entry for this batch, fire off the timer.
|
| - BrowserThread::PostDelayedTask(BrowserThread::DB,
|
| - FROM_HERE,
|
| - base::Bind(&SqlLiteStorage::Commit, this),
|
| - kCommitInterval);
|
| - } else if (pending_operations_.size() >= kCommitAfterBatchSize) {
|
| - // We've reached a big enough batch, fire off a commit now.
|
| - BrowserThread::PostTask(BrowserThread::DB,
|
| - FROM_HERE,
|
| - base::Bind(&SqlLiteStorage::Commit, this));
|
| - }
|
| -}
|
| -
|
| -void WebRTCIdentityStoreBackend::SqlLiteStorage::Commit() {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::DB);
|
| - // Maybe an old timer fired or we are already Close()'ed.
|
| - if (!db_.get() || pending_operations_.empty())
|
| - return;
|
| -
|
| - sql::Statement add_stmt(db_->GetCachedStatement(
|
| - SQL_FROM_HERE,
|
| - "INSERT INTO webrtc_identity_store "
|
| - "(origin, identity_name, common_name, certificate,"
|
| - " private_key, creation_time) VALUES"
|
| - " (?,?,?,?,?,?)"));
|
| -
|
| - CHECK(add_stmt.is_valid());
|
| -
|
| - sql::Statement del_stmt(db_->GetCachedStatement(
|
| - SQL_FROM_HERE,
|
| - "DELETE FROM webrtc_identity_store WHERE origin=? AND identity_name=?"));
|
| -
|
| - CHECK(del_stmt.is_valid());
|
| -
|
| - sql::Transaction transaction(db_.get());
|
| - if (!transaction.Begin()) {
|
| - DVLOG(2) << "Failed to begin the transaction.";
|
| - return;
|
| - }
|
| -
|
| - // Swaps |pending_operations_| into a temporary list to make sure
|
| - // |pending_operations_| is always cleared in case of DB errors.
|
| - PendingOperationList pending_operations_copy;
|
| - pending_operations_.swap(pending_operations_copy);
|
| -
|
| - for (PendingOperationList::const_iterator it =
|
| - pending_operations_copy.begin();
|
| - it != pending_operations_copy.end();
|
| - ++it) {
|
| - switch ((*it)->type) {
|
| - case ADD_IDENTITY: {
|
| - add_stmt.Reset(true);
|
| - add_stmt.BindString(0, (*it)->origin.spec());
|
| - add_stmt.BindString(1, (*it)->identity_name);
|
| - add_stmt.BindString(2, (*it)->identity.common_name);
|
| - const std::string& cert = (*it)->identity.certificate;
|
| - add_stmt.BindBlob(3, cert.data(), cert.size());
|
| - const std::string& private_key = (*it)->identity.private_key;
|
| - add_stmt.BindBlob(4, private_key.data(), private_key.size());
|
| - add_stmt.BindInt64(5, (*it)->identity.creation_time);
|
| - if (!add_stmt.Run()) {
|
| - DVLOG(2) << "Failed to add the identity to DB.";
|
| - return;
|
| - }
|
| - break;
|
| - }
|
| - case DELETE_IDENTITY:
|
| - del_stmt.Reset(true);
|
| - del_stmt.BindString(0, (*it)->origin.spec());
|
| - del_stmt.BindString(1, (*it)->identity_name);
|
| - if (!del_stmt.Run()) {
|
| - DVLOG(2) << "Failed to delete the identity from DB.";
|
| - return;
|
| - }
|
| - break;
|
| -
|
| - default:
|
| - NOTREACHED();
|
| - break;
|
| - }
|
| - }
|
| -
|
| - if (!transaction.Commit())
|
| - DVLOG(2) << "Failed to commit the transaction.";
|
| -}
|
| -
|
| -} // namespace content
|
|
|