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
-// GetCertDatabaseOnIOThread.
-void DidGetCertDBOnIOThread(const GetCertDBCallback& callback,
+// Used by GetCertDatabaseOnIOThread and called back with the requested
+// NSSCertDatabase.
+// If |token_id| is not empty, sets |slot_| of |state| accordingly and calls
+// |callback| if the database was successfully retrieved.
+void DidGetCertDBOnIOThread(const std::string& token_id,
+ const GetCertDBCallback& callback,
NSSOperationState* state,
net::NSSCertDatabase* cert_db) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
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)
+ 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_id| is not empty, the slot for |token_id|. Stores the slot in |state|
+// 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));
}
const unsigned int modulus_length_bits_;
private:
- // Must be called on origin thread, use CallBack() therefore.
+ // Must be called on origin thread, therefore use CallBack().
subtle::GenerateKeyCallback callback_;
};
const std::string data_;
private:
- // Must be called on origin thread, use CallBack() therefore.
+ // Must be called on origin thread, therefore use CallBack().
subtle::SignCallback callback_;
};
scoped_ptr<net::CertificateList> certs_;
private:
- // Must be called on origin thread, use CallBack() therefore.
+ // Must be called on origin thread, therefore use CallBack().
GetCertificatesCallback callback_;
};
scoped_refptr<net::X509Certificate> certificate_;
private:
- // Must be called on origin thread, use CallBack() therefore.
+ // Must be called on origin thread, therefore use CallBack().
ImportCertificateCallback callback_;
};
scoped_refptr<net::X509Certificate> certificate_;
private:
- // Must be called on origin thread, use CallBack() therefore.
+ // Must be called on origin thread, therefore use CallBack().
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, therefore use CallBack().
+ GetTokensCallback callback_;
+};
+
NSSOperationState::NSSOperationState()
: origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
}
: 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) {
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) {
&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);
+
+ state->CallBack(FROM_HERE, token_ids.Pass(), std::string() /* no error */);
+}
+
} // namespace
namespace subtle {
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