1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
// Copyright (c) 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 "chrome/browser/net/nss_context.h"
#include <utility>
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/supports_user_data.h"
#include "chrome/browser/profiles/profile_io_data.h"
#include "content/public/browser/browser_thread.h"
#include "crypto/nss_util_internal.h"
#include "net/cert/nss_cert_database_chromeos.h"
namespace {
void* kDatabaseManagerKey = &kDatabaseManagerKey;
class NSSCertDatabaseChromeOSManager : public base::SupportsUserData::Data {
public:
typedef base::Callback<void(net::NSSCertDatabaseChromeOS*)>
GetNSSCertDatabaseCallback;
explicit NSSCertDatabaseChromeOSManager(const std::string& username_hash)
: username_hash_(username_hash), weak_ptr_factory_(this) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
crypto::ScopedPK11Slot private_slot(crypto::GetPrivateSlotForChromeOSUser(
username_hash,
base::Bind(&NSSCertDatabaseChromeOSManager::DidGetPrivateSlot,
weak_ptr_factory_.GetWeakPtr())));
if (private_slot)
DidGetPrivateSlot(std::move(private_slot));
}
~NSSCertDatabaseChromeOSManager() override {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
}
net::NSSCertDatabaseChromeOS* GetNSSCertDatabase(
const GetNSSCertDatabaseCallback& callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (nss_cert_database_)
return nss_cert_database_.get();
ready_callback_list_.push_back(callback);
return NULL;
}
private:
typedef std::vector<GetNSSCertDatabaseCallback> ReadyCallbackList;
void DidGetPrivateSlot(crypto::ScopedPK11Slot private_slot) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
nss_cert_database_.reset(new net::NSSCertDatabaseChromeOS(
crypto::GetPublicSlotForChromeOSUser(username_hash_),
std::move(private_slot)));
ReadyCallbackList callback_list;
callback_list.swap(ready_callback_list_);
for (ReadyCallbackList::iterator i = callback_list.begin();
i != callback_list.end();
++i) {
(*i).Run(nss_cert_database_.get());
}
}
std::string username_hash_;
std::unique_ptr<net::NSSCertDatabaseChromeOS> nss_cert_database_;
ReadyCallbackList ready_callback_list_;
base::WeakPtrFactory<NSSCertDatabaseChromeOSManager> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(NSSCertDatabaseChromeOSManager);
};
std::string GetUsername(content::ResourceContext* context) {
return ProfileIOData::FromResourceContext(context)->username_hash();
}
net::NSSCertDatabaseChromeOS* GetNSSCertDatabaseChromeOS(
content::ResourceContext* context,
const NSSCertDatabaseChromeOSManager::GetNSSCertDatabaseCallback&
callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
NSSCertDatabaseChromeOSManager* manager =
static_cast<NSSCertDatabaseChromeOSManager*>(
context->GetUserData(kDatabaseManagerKey));
if (!manager) {
manager = new NSSCertDatabaseChromeOSManager(GetUsername(context));
context->SetUserData(kDatabaseManagerKey, base::WrapUnique(manager));
}
return manager->GetNSSCertDatabase(callback);
}
void CallWithNSSCertDatabase(
const base::Callback<void(net::NSSCertDatabase*)>& callback,
net::NSSCertDatabaseChromeOS* db) {
callback.Run(db);
}
void SetSystemSlot(crypto::ScopedPK11Slot system_slot,
net::NSSCertDatabaseChromeOS* db) {
db->SetSystemSlot(std::move(system_slot));
}
void SetSystemSlotOfDBForResourceContext(content::ResourceContext* context,
crypto::ScopedPK11Slot system_slot) {
base::Callback<void(net::NSSCertDatabaseChromeOS*)> callback =
base::Bind(&SetSystemSlot, base::Passed(&system_slot));
net::NSSCertDatabaseChromeOS* db =
GetNSSCertDatabaseChromeOS(context, callback);
if (db)
callback.Run(db);
}
} // namespace
net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext(
content::ResourceContext* context,
const base::Callback<void(net::NSSCertDatabase*)>& callback) {
return GetNSSCertDatabaseChromeOS(
context, base::Bind(&CallWithNSSCertDatabase, callback));
}
void EnableNSSSystemKeySlotForResourceContext(
content::ResourceContext* context) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
base::Callback<void(crypto::ScopedPK11Slot)> callback =
base::Bind(&SetSystemSlotOfDBForResourceContext, context);
crypto::ScopedPK11Slot system_slot = crypto::GetSystemNSSKeySlot(callback);
if (system_slot)
callback.Run(std::move(system_slot));
}
|