blob: 28155004910d5ca8aa37367cc37ea4ee26144582 [file] [log] [blame]
// Copyright 2014 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.
#ifndef NET_SSL_DEFAULT_CHANNEL_ID_STORE_H_
#define NET_SSL_DEFAULT_CHANNEL_ID_STORE_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/callback_forward.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "net/base/net_export.h"
#include "net/ssl/channel_id_store.h"
namespace crypto {
class ECPrivateKey;
} // namespace crypto
namespace net {
// This class is the system for storing and retrieving Channel IDs. Modeled
// after the CookieMonster class, it has an in-memory store and synchronizes
// Channel IDs to an optional permanent storage that implements the
// PersistentStore interface. The use case is described in
// https://tools.ietf.org/html/draft-balfanz-tls-channelid-01
class NET_EXPORT DefaultChannelIDStore : public ChannelIDStore {
public:
class PersistentStore;
// The key for each ChannelID* in ChannelIDMap is the
// corresponding server.
typedef std::map<std::string, ChannelID*> ChannelIDMap;
// The store passed in should not have had Init() called on it yet. This
// class will take care of initializing it. The backing store is NOT owned by
// this class, but it must remain valid for the duration of the
// DefaultChannelIDStore's existence. If |store| is NULL, then no
// backing store will be updated.
explicit DefaultChannelIDStore(PersistentStore* store);
~DefaultChannelIDStore() override;
// ChannelIDStore implementation.
int GetChannelID(const std::string& server_identifier,
std::unique_ptr<crypto::ECPrivateKey>* key_result,
GetChannelIDCallback callback) override;
void SetChannelID(std::unique_ptr<ChannelID> channel_id) override;
void DeleteChannelID(const std::string& server_identifier,
base::OnceClosure callback) override;
void DeleteForDomainsCreatedBetween(
const base::Callback<bool(const std::string&)>& domain_predicate,
base::Time delete_begin,
base::Time delete_end,
base::OnceClosure callback) override;
void DeleteAll(base::OnceClosure callback) override;
void GetAllChannelIDs(GetChannelIDListCallback callback) override;
void Flush() override;
int GetChannelIDCount() override;
void SetForceKeepSessionState() override;
bool IsEphemeral() override;
private:
class Task;
class GetChannelIDTask;
class SetChannelIDTask;
class DeleteChannelIDTask;
class DeleteForDomainsCreatedBetweenTask;
class GetAllChannelIDsTask;
// Deletes all of the certs. Does not delete them from |store_|.
void DeleteAllInMemory();
// Called by all non-static functions to ensure that the cert store has
// been initialized.
// TODO(mattm): since we load asynchronously now, maybe we should start
// loading immediately on construction, or provide some method to initiate
// loading?
void InitIfNecessary() {
if (!initialized_) {
if (store_.get()) {
InitStore();
} else {
loaded_ = true;
}
initialized_ = true;
}
}
// Initializes the backing store and reads existing certs from it.
// Should only be called by InitIfNecessary().
void InitStore();
// Callback for backing store loading completion.
void OnLoaded(std::unique_ptr<std::vector<std::unique_ptr<ChannelID>>> certs);
// Syncronous methods which do the actual work. Can only be called after
// initialization is complete.
void SyncSetChannelID(std::unique_ptr<ChannelID> channel_id);
void SyncDeleteChannelID(const std::string& server_identifier);
void SyncDeleteForDomainsCreatedBetween(
const base::Callback<bool(const std::string&)>& domain_predicate,
base::Time delete_begin,
base::Time delete_end);
void SyncGetAllChannelIDs(ChannelIDList* channel_id_list);
// Add |task| to |waiting_tasks_|.
void EnqueueTask(std::unique_ptr<Task> task);
// If already initialized, run |task| immediately. Otherwise add it to
// |waiting_tasks_|.
void RunOrEnqueueTask(std::unique_ptr<Task> task);
// Deletes the channel id for the specified server, if such a channel id
// exists, from the in-memory store. Deletes it from |store_| if |store_|
// is not NULL.
void InternalDeleteChannelID(const std::string& server);
// Adds the channel id to the in-memory store and adds it to |store_| if
// |store_| is not NULL.
void InternalInsertChannelID(std::unique_ptr<ChannelID> channel_id);
// Indicates whether the channel id store has been initialized. This happens
// lazily in InitIfNecessary().
bool initialized_;
// Indicates whether loading from the backend store is completed and
// calls may be immediately processed.
bool loaded_;
// Tasks that are waiting to be run once we finish loading.
std::vector<std::unique_ptr<Task>> waiting_tasks_;
scoped_refptr<PersistentStore> store_;
ChannelIDMap channel_ids_;
base::WeakPtrFactory<DefaultChannelIDStore> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(DefaultChannelIDStore);
};
typedef base::RefCountedThreadSafe<DefaultChannelIDStore::PersistentStore>
RefcountedPersistentStore;
class NET_EXPORT DefaultChannelIDStore::PersistentStore
: public RefcountedPersistentStore {
public:
typedef base::Callback<void(
std::unique_ptr<std::vector<std::unique_ptr<ChannelID>>>)>
LoadedCallback;
// Initializes the store and retrieves the existing channel_ids. This will be
// called only once at startup. Note that the channel_ids are individually
// allocated and that ownership is transferred to the caller upon return.
// The |loaded_callback| must not be called synchronously.
virtual void Load(const LoadedCallback& loaded_callback) = 0;
virtual void AddChannelID(const ChannelID& channel_id) = 0;
virtual void DeleteChannelID(const ChannelID& channel_id) = 0;
virtual void Flush() = 0;
// When invoked, instructs the store to keep session related data on
// destruction.
virtual void SetForceKeepSessionState() = 0;
protected:
friend class base::RefCountedThreadSafe<PersistentStore>;
PersistentStore();
virtual ~PersistentStore();
private:
DISALLOW_COPY_AND_ASSIGN(PersistentStore);
};
} // namespace net
#endif // NET_SSL_DEFAULT_CHANNEL_ID_STORE_H_