Index: chrome/browser/chromeos/platform_keys/platform_keys_nss.cc |
diff --git a/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc b/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc |
index f3a02087d69096dbc8923449d4fcb26acf01f42d..5b0f6b800476125f66a751fb80377ef6b43ecd8a 100644 |
--- a/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc |
+++ b/chrome/browser/chromeos/platform_keys/platform_keys_nss.cc |
@@ -72,10 +72,12 @@ class NSSOperationState { |
typedef base::Callback<void(net::NSSCertDatabase* cert_db)> GetCertDBCallback; |
-// Called back with the NSSCertDatabase associated to the given |token_id|. |
-// Calls |callback| if the database was successfully retrieved. Used by |
+// Called back with the NSSCertDatabase associated to the given |context|. |
Joao da Silva
2014/07/30 08:46:38
There is no |context| here
pneubeck (no reviews)
2014/07/30 13:53:45
Done.
|
+// If |token_id| is not empty, sets |slot_| of the state accordingly and calls |
+// |callback| if the database was successfully retrieved. Used by |
// GetCertDatabaseOnIOThread. |
-void DidGetCertDBOnIOThread(const GetCertDBCallback& callback, |
+void DidGetCertDBOnIOThread(const std::string& token_id, |
+ const GetCertDBCallback& callback, |
NSSOperationState* state, |
net::NSSCertDatabase* cert_db) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
@@ -85,42 +87,50 @@ void DidGetCertDBOnIOThread(const GetCertDBCallback& callback, |
return; |
} |
- state->slot_ = cert_db->GetPrivateSlot(); |
- if (!state->slot_) { |
- LOG(ERROR) << "No private slot"; |
- state->OnError(FROM_HERE, kErrorInternal); |
- return; |
+ if (!token_id.empty()) { |
+ if (token_id == kTokenIdUser) |
+ state->slot_ = cert_db->GetPrivateSlot(); |
+ else if (token_id == kTokenIdSystem) |
Joao da Silva
2014/07/30 08:46:38
Why isn't kTokenIdUser and kTokenIdSystem an enum?
pneubeck (no reviews)
2014/07/30 13:53:45
Explained now at the declaration comment.
|
+ state->slot_ = cert_db->GetSystemSlot(); |
+ |
+ if (!state->slot_) { |
+ LOG(ERROR) << "Slot for token id '" << token_id << "' not available."; |
+ state->OnError(FROM_HERE, kErrorInternal); |
+ return; |
+ } |
} |
callback.Run(cert_db); |
} |
-// Retrieves the NSSCertDatabase from |context|. Must be called on the IO |
-// thread. |
-void GetCertDatabaseOnIOThread(content::ResourceContext* context, |
+// Retrieves the NSSCertDatabase from |context| and, if |token_id| is not empty, |
+// the slot for |token_id|. |
+// Must be called on the IO thread. |
+void GetCertDatabaseOnIOThread(const std::string& token_id, |
const GetCertDBCallback& callback, |
+ content::ResourceContext* context, |
NSSOperationState* state) { |
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
net::NSSCertDatabase* cert_db = GetNSSCertDatabaseForResourceContext( |
- context, base::Bind(&DidGetCertDBOnIOThread, callback, state)); |
+ context, base::Bind(&DidGetCertDBOnIOThread, token_id, callback, state)); |
if (cert_db) |
- DidGetCertDBOnIOThread(callback, state, cert_db); |
+ DidGetCertDBOnIOThread(token_id, callback, state, cert_db); |
} |
-// Asynchronously fetches the NSSCertDatabase and PK11Slot for |token_id|. |
-// Stores the slot in |state| and passes the database to |callback|. Will run |
-// |callback| on the IO thread. |
+// Asynchronously fetches the NSSCertDatabase for |browser_context| and, if |
+// |token| is not empty, the slot for |token_id|. Stores the slot in |state| |
Joao da Silva
2014/07/30 08:46:39
|token| -> |token_id|
pneubeck (no reviews)
2014/07/30 13:53:45
Done.
|
+// and passes the database to |callback|. Will run |callback| on the IO thread. |
void GetCertDatabase(const std::string& token_id, |
const GetCertDBCallback& callback, |
BrowserContext* browser_context, |
NSSOperationState* state) { |
- // TODO(pneubeck): Decide which DB to retrieve depending on |token_id|. |
BrowserThread::PostTask(BrowserThread::IO, |
FROM_HERE, |
base::Bind(&GetCertDatabaseOnIOThread, |
- browser_context->GetResourceContext(), |
+ token_id, |
callback, |
+ browser_context->GetResourceContext(), |
state)); |
} |
@@ -250,6 +260,30 @@ class RemoveCertificateState : public NSSOperationState { |
RemoveCertificateCallback callback_; |
}; |
+class GetTokensState : public NSSOperationState { |
+ public: |
+ explicit GetTokensState(const GetTokensCallback& callback); |
+ virtual ~GetTokensState() {} |
+ |
+ virtual void OnError(const tracked_objects::Location& from, |
+ const std::string& error_message) OVERRIDE { |
+ CallBack(from, |
+ scoped_ptr<std::vector<std::string> >() /* no token ids */, |
+ error_message); |
+ } |
+ |
+ void CallBack(const tracked_objects::Location& from, |
+ scoped_ptr<std::vector<std::string> > token_ids, |
+ const std::string& error_message) { |
+ origin_task_runner_->PostTask( |
+ from, base::Bind(callback_, base::Passed(&token_ids), error_message)); |
+ } |
+ |
+ private: |
+ // Must be called on origin thread, use CallBack() therefore. |
Joao da Silva
2014/07/30 08:46:38
, therefore use Callback().
pneubeck (no reviews)
2014/07/30 13:53:45
Done.
|
+ GetTokensCallback callback_; |
+}; |
+ |
NSSOperationState::NSSOperationState() |
: origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) { |
} |
@@ -287,6 +321,10 @@ RemoveCertificateState::RemoveCertificateState( |
: certificate_(certificate), callback_(callback) { |
} |
+GetTokensState::GetTokensState(const GetTokensCallback& callback) |
+ : callback_(callback) { |
+} |
+ |
// Does the actual key generation on a worker thread. Used by |
// GenerateRSAKeyWithDB(). |
void GenerateRSAKeyOnWorkerThread(scoped_ptr<GenerateRSAKeyState> state) { |
@@ -447,6 +485,14 @@ void ImportCertificateWithDB(scoped_ptr<ImportCertificateState> state, |
return; |
} |
+ // Check that the private key is in the correct slot. |
+ PK11SlotInfo* slot = |
+ PK11_KeyForCertExists(state->certificate_->os_cert_handle(), NULL, NULL); |
+ if (slot != state->slot_) { |
+ state->OnError(FROM_HERE, kErrorKeyNotFound); |
+ return; |
+ } |
+ |
const net::Error import_status = |
static_cast<net::Error>(db->AddUserCert(state->certificate_.get())); |
if (import_status != net::OK) { |
@@ -490,6 +536,20 @@ void RemoveCertificateWithDB(scoped_ptr<RemoveCertificateState> state, |
&DidRemoveCertificate, base::Passed(&state), certificate_found)); |
} |
+// Does the actual work to determine which tokens are available. |
+void GetTokensWithDB(scoped_ptr<GetTokensState> state, |
+ net::NSSCertDatabase* cert_db) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ scoped_ptr<std::vector<std::string> > token_ids(new std::vector<std::string>); |
+ |
+ // The user's token is always available. |
+ token_ids->push_back(kTokenIdUser); |
+ if (cert_db->GetSystemSlot()) |
+ token_ids->push_back(kTokenIdSystem); |
Joao da Silva
2014/07/30 08:46:39
Doesn't this depend on state->slot_, based on what
pneubeck (no reviews)
2014/07/30 13:53:45
GetCertDatabase always gets the DB for the browser
|
+ |
+ state->CallBack(FROM_HERE, token_ids.Pass(), std::string() /* no error */); |
+} |
+ |
} // namespace |
namespace subtle { |
@@ -588,6 +648,18 @@ void RemoveCertificate(const std::string& token_id, |
state_ptr); |
} |
+void GetTokens(const GetTokensCallback& callback, |
+ content::BrowserContext* browser_context) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ scoped_ptr<GetTokensState> state(new GetTokensState(callback)); |
+ // Get the pointer to |state| before base::Passed releases |state|. |
+ NSSOperationState* state_ptr = state.get(); |
+ GetCertDatabase(std::string() /* don't get any specific slot */, |
+ base::Bind(&GetTokensWithDB, base::Passed(&state)), |
+ browser_context, |
+ state_ptr); |
+} |
+ |
} // namespace platform_keys |
} // namespace chromeos |