diff --git a/emailcommon/src/com/android/emailcommon/utility/CertificateRequestor.java b/emailcommon/src/com/android/emailcommon/utility/CertificateRequestor.java
new file mode 100644
index 000000000..b78895b3a
--- /dev/null
+++ b/emailcommon/src/com/android/emailcommon/utility/CertificateRequestor.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.emailcommon.utility;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.security.KeyChain;
+import android.security.KeyChainAliasCallback;
+
+/**
+ * A headless Activity which simply calls into the framework {@link KeyChain} service to select
+ * a certificate to use for establishing secure connections in the Email app.
+ */
+public class CertificateRequestor extends Activity implements KeyChainAliasCallback {
+
+ public static final String ACTION_REQUEST_CERT = "com.android.emailcommon.REQUEST_CERT";
+
+ public static final String EXTRA_HOST = "CertificateRequestor.host";
+ public static final String EXTRA_PORT = "CertificateRequestor.port";
+
+ public static final String RESULT_ALIAS = "CertificateRequestor.alias";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Intent i = getIntent();
+ String host = i.getStringExtra(EXTRA_HOST);
+ int port = i.getIntExtra(EXTRA_PORT, -1);
+
+ KeyChain.choosePrivateKeyAlias(
+ this, this,
+ null /* keytypes */, null /* issuers */,
+ host, port,
+ null /* alias */);
+ }
+
+ /**
+ * Callback for the certificate request. Does not happen on the UI thread.
+ */
+ @Override
+ public void alias(String alias) {
+ if (alias == null) {
+ setResult(RESULT_CANCELED);
+ } else {
+ Intent data = new Intent();
+ data.putExtra(RESULT_ALIAS, alias);
+ setResult(RESULT_OK, data);
+ }
+ finish();
+ }
+}
diff --git a/res/layout/client_certificate_selector.xml b/res/layout/client_certificate_selector.xml
index 98e59269a..fcdd36af6 100644
--- a/res/layout/client_certificate_selector.xml
+++ b/res/layout/client_certificate_selector.xml
@@ -20,10 +20,8 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="8dip"
- android:layout_marginBottom="8dip"
- android:layout_marginLeft="32dip"
- android:layout_marginRight="32dip"
+ android:layout_margin="8dip"
+ android:gravity="center_vertical"
android:orientation="horizontal" >
diff --git a/src/com/android/email/activity/setup/AccountSetupExchangeFragment.java b/src/com/android/email/activity/setup/AccountSetupExchangeFragment.java
index 72ae31127..19c6aaf40 100644
--- a/src/com/android/email/activity/setup/AccountSetupExchangeFragment.java
+++ b/src/com/android/email/activity/setup/AccountSetupExchangeFragment.java
@@ -18,6 +18,8 @@ package com.android.email.activity.setup;
import android.app.Activity;
import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.text.Editable;
@@ -38,10 +40,12 @@ import com.android.email.activity.UiUtilities;
import com.android.email.provider.AccountBackupRestore;
import com.android.email.service.EmailServiceUtils;
import com.android.email.view.CertificateSelector;
+import com.android.email.view.CertificateSelector.HostCallback;
import com.android.emailcommon.Device;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.HostAuth;
+import com.android.emailcommon.utility.CertificateRequestor;
import com.android.emailcommon.utility.Utility;
import java.io.IOException;
@@ -53,8 +57,9 @@ import java.io.IOException;
* (for editing existing accounts).
*/
public class AccountSetupExchangeFragment extends AccountServerBaseFragment
- implements OnCheckedChangeListener {
+ implements OnCheckedChangeListener, HostCallback {
+ private static final int CERTIFICATE_REQUEST = 0;
private final static String STATE_KEY_CREDENTIAL = "AccountSetupExchangeFragment.credential";
private final static String STATE_KEY_LOADED = "AccountSetupExchangeFragment.loaded";
@@ -147,7 +152,7 @@ public class AccountSetupExchangeFragment extends AccountServerBaseFragment
Log.d(Logging.LOG_TAG, "AccountSetupExchangeFragment onActivityCreated");
}
super.onActivityCreated(savedInstanceState);
- mClientCertificateSelector.setActivity(getActivity());
+ mClientCertificateSelector.setHostActivity(this);
}
/**
@@ -414,4 +419,21 @@ public class AccountSetupExchangeFragment extends AccountServerBaseFragment
SetupData.CHECK_INCOMING);
}
+ @Override
+ public void onCertificateRequested() {
+ Intent intent = new Intent(CertificateRequestor.ACTION_REQUEST_CERT);
+ intent.setData(Uri.parse("eas://com.android.emailcommon/certrequest"));
+ startActivityForResult(intent, CERTIFICATE_REQUEST);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == CERTIFICATE_REQUEST && resultCode == Activity.RESULT_OK) {
+ String certAlias = data.getStringExtra(CertificateRequestor.RESULT_ALIAS);
+ if (certAlias != null) {
+ mClientCertificateSelector.setCertificate(certAlias);
+ }
+ }
+ }
+
}
diff --git a/src/com/android/email/view/CertificateSelector.java b/src/com/android/email/view/CertificateSelector.java
index e180d11bc..80b56eeef 100644
--- a/src/com/android/email/view/CertificateSelector.java
+++ b/src/com/android/email/view/CertificateSelector.java
@@ -17,16 +17,10 @@
package com.android.email.view;
-import com.android.email.R;
-import com.android.email.activity.UiUtilities;
-
-import android.app.Activity;
import android.content.Context;
-import android.content.Intent;
import android.os.Parcel;
import android.os.Parcelable;
import android.security.KeyChain;
-import android.security.KeyChainAliasCallback;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
@@ -34,22 +28,26 @@ import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.android.email.R;
+import com.android.email.activity.UiUtilities;
+
/**
* A simple view that can be used to select a certificate from the system {@link KeyChain}.
*
- * Host activities must register themselves view {@link #setActivity} for this selector to work,
- * since it requires firing system {@link Intent}s.
+ * Host activities must register themselves view {@link #setHostActivity} for this selector to work.
*/
-public class CertificateSelector extends LinearLayout implements
- OnClickListener, KeyChainAliasCallback {
+public class CertificateSelector extends LinearLayout implements OnClickListener {
/** Button to select or remove the certificate. */
private Button mSelectButton;
private TextView mAliasText;
/** The host activity. */
- private Activity mActivity;
+ private HostCallback mHost;
+ public interface HostCallback {
+ void onCertificateRequested();
+ }
public CertificateSelector(Context context) {
super(context);
@@ -61,8 +59,11 @@ public class CertificateSelector extends LinearLayout implements
super(context, attrs, defStyle);
}
- public void setActivity(Activity activity) {
- mActivity = activity;
+ public void setHostActivity(HostCallback host) {
+ mHost = host;
+ }
+
+ public void setDelegate(String uri) {
}
@Override
@@ -98,31 +99,16 @@ public class CertificateSelector extends LinearLayout implements
@Override
public void onClick(View target) {
- if (target == mSelectButton && mActivity != null) {
+ if (target == mSelectButton && mHost != null) {
if (hasCertificate()) {
// Handle the click on the button when it says "Remove"
setCertificate(null);
-
} else {
- // We don't restrict the chooser for certificate types since 95% of the time the
- // user will probably only have one certificate installed and it'll be the right
- // "type". Just let them fail and select a different one if it doesn't match.
- KeyChain.choosePrivateKeyAlias(
- mActivity, this,
- null /* keytypes */, null /* issuers */,
- null /* host */, -1 /* port */,
- null /* alias */);
+ mHost.onCertificateRequested();
}
}
}
- // KeyChainAliasCallback
- @Override
- public void alias(String alias) {
- if (alias != null) {
- setCertificate(alias);
- }
- }
@Override
protected void onRestoreInstanceState(Parcelable parcel) {
SavedState savedState = (SavedState) parcel;