- // KeyChainAliasCallback implementation
- @Override
- public void alias(final String alias) {
- // This is called by KeyChainActivity in a background thread. Post task to handle the
- // certificate selection on the UI thread.
- ThreadUtils.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if (alias == null) {
- // No certificate was selected.
- onPostExecute(null);
- } else {
- mAlias = alias;
- // Launch background thread.
- execute();
+ /**
+ * Common implementation for anynchronous task of handling the certificate request. This
+ * AsyncTask uses the abstract methods to retrieve the authentication material from a
+ * generalized key store. The key store is accessed in background, as the APIs being exercised
+ * may be blocking. The results are posted back to native on the UI thread.
+ */
+ abstract static class CertAsyncTask extends AsyncTask<Void, Void, Void> {
+ // These fields will store the results computed in doInBackground so that they can be posted
+ // back in onPostExecute.
+ private byte[][] mEncodedChain;
+ private AndroidPrivateKey mAndroidPrivateKey;
+
+ // Pointer to the native certificate request needed to return the results.
+ private final int mNativePtr;
+
+ CertAsyncTask(int nativePtr) {
+ mNativePtr = nativePtr;
+ }
+
+ // These overriden methods will be used to access the key store.
+ abstract String getAlias();
+ abstract AndroidPrivateKey getPrivateKey(String alias);
+ abstract X509Certificate[] getCertificateChain(String alias);
+
+ @Override
+ protected Void doInBackground(Void... params) {
+ String alias = getAlias();
+ if (alias == null) return null;
+
+ AndroidPrivateKey key = getPrivateKey(alias);
+ X509Certificate[] chain = getCertificateChain(alias);
+
+ if (key == null || chain == null || chain.length == 0) {
+ Log.w(TAG, "Empty client certificate chain?");
+ return null;
+ }
+
+ // Encode the certificate chain.
+ byte[][] encodedChain = new byte[chain.length][];
+ try {
+ for (int i = 0; i < chain.length; ++i) {
+ encodedChain[i] = chain[i].getEncoded();