Chromium Code Reviews| 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 |