Home | History | Annotate | Download | only in setup
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.email.activity.setup;
     18 
     19 import android.app.AlertDialog;
     20 import android.app.Dialog;
     21 import android.app.DialogFragment;
     22 import android.content.Context;
     23 import android.content.DialogInterface;
     24 import android.os.Bundle;
     25 import android.text.TextUtils;
     26 
     27 import com.android.email.R;
     28 import com.android.emailcommon.mail.MessagingException;
     29 import com.android.mail.utils.LogUtils;
     30 
     31 public class CheckSettingsErrorDialogFragment extends DialogFragment{
     32     public final static String TAG = "CheckSettingsErrorDialog";
     33 
     34     public final static int REASON_OTHER = 0;
     35     public final static int REASON_AUTHENTICATION_FAILED = 1;
     36     public final static int REASON_CERTIFICATE_REQUIRED = 2;
     37 
     38     // Bundle keys for arguments
     39     private final static String ARGS_MESSAGE = "CheckSettingsErrorDialog.Message";
     40     private final static String ARGS_REASON = "CheckSettingsErrorDialog.ExceptionId";
     41 
     42     public interface Callback {
     43         /**
     44          * Called to indicate the user wants to resolve the error by changing the client certificate
     45          */
     46         void onCheckSettingsErrorDialogEditCertificate();
     47 
     48         /**
     49          * Called to indicate the user wants to resolve the error by editing the server settings
     50          */
     51         void onCheckSettingsErrorDialogEditSettings();
     52     }
     53 
     54     public CheckSettingsErrorDialogFragment() {}
     55 
     56     /**
     57      * @param reason see REASON_* constants
     58      * @param message from {@link #getErrorString(Context, MessagingException)}
     59      * @return new instance
     60      */
     61     public static CheckSettingsErrorDialogFragment newInstance(int reason, String message) {
     62         final CheckSettingsErrorDialogFragment fragment = new CheckSettingsErrorDialogFragment();
     63         final Bundle arguments = new Bundle(2);
     64         arguments.putString(ARGS_MESSAGE, message);
     65         arguments.putInt(ARGS_REASON, reason);
     66         fragment.setArguments(arguments);
     67         return fragment;
     68     }
     69 
     70     @Override
     71     public Dialog onCreateDialog(Bundle savedInstanceState) {
     72         final Context context = getActivity();
     73         final Bundle arguments = getArguments();
     74         final String message = arguments.getString(ARGS_MESSAGE);
     75         final int reason = arguments.getInt(ARGS_REASON);
     76 
     77         setCancelable(true);
     78 
     79         final AlertDialog.Builder builder = new AlertDialog.Builder(context)
     80                 .setMessage(message);
     81 
     82         // Use a different title when we get
     83         // MessagingException.AUTODISCOVER_AUTHENTICATION_FAILED
     84         if (reason == REASON_AUTHENTICATION_FAILED) {
     85             builder.setTitle(R.string.account_setup_autodiscover_dlg_authfail_title);
     86         } else {
     87             builder.setIconAttribute(android.R.attr.alertDialogIcon)
     88                     .setTitle(context.getString(R.string.account_setup_failed_dlg_title));
     89         }
     90 
     91         if (reason == REASON_CERTIFICATE_REQUIRED) {
     92             // Certificate error - show two buttons so the host fragment can auto pop
     93             // into the appropriate flow.
     94             builder.setPositiveButton(
     95                     context.getString(android.R.string.ok),
     96                     new DialogInterface.OnClickListener() {
     97                         @Override
     98                         public void onClick(DialogInterface dialog, int which) {
     99                             dismiss();
    100                             final Callback callback = (Callback) getActivity();
    101                             callback.onCheckSettingsErrorDialogEditCertificate();
    102                         }
    103                     });
    104             builder.setNegativeButton(
    105                     context.getString(android.R.string.cancel),
    106                     new DialogInterface.OnClickListener() {
    107                         @Override
    108                         public void onClick(DialogInterface dialog, int which) {
    109                             dialog.cancel();
    110                         }
    111                     });
    112 
    113         } else {
    114             // "Normal" error - just use a single "Edit details" button.
    115             builder.setPositiveButton(
    116                     context.getString(R.string.account_setup_failed_dlg_edit_details_action),
    117                     new DialogInterface.OnClickListener() {
    118                         @Override
    119                         public void onClick(DialogInterface dialog, int which) {
    120                             dialog.cancel();
    121                         }
    122                     });
    123         }
    124         return builder.create();
    125     }
    126 
    127     @Override
    128     public void onCancel(DialogInterface dialog) {
    129         super.onCancel(dialog);
    130         final Callback callback = (Callback) getActivity();
    131         callback.onCheckSettingsErrorDialogEditSettings();
    132     }
    133 
    134     public static int getReasonFromException (MessagingException ex) {
    135         final int exceptionCode = ex.getExceptionType();
    136         switch (exceptionCode) {
    137             case MessagingException.AUTODISCOVER_AUTHENTICATION_FAILED:
    138             case MessagingException.AUTHENTICATION_FAILED:
    139                 return REASON_AUTHENTICATION_FAILED;
    140             case MessagingException.CLIENT_CERTIFICATE_REQUIRED:
    141                 return REASON_CERTIFICATE_REQUIRED;
    142         }
    143         return REASON_OTHER;
    144     }
    145 
    146     public static String getErrorString(Context context, MessagingException ex) {
    147         final int id;
    148         String message = ex.getMessage();
    149         if (message != null) {
    150             message = message.trim();
    151         }
    152         switch (ex.getExceptionType()) {
    153             // The remaining exception types are handled by setting the state to
    154             // STATE_CHECK_ERROR (above, default) and conversion to specific error strings.
    155             case MessagingException.CERTIFICATE_VALIDATION_ERROR:
    156                 id = TextUtils.isEmpty(message)
    157                         ? R.string.account_setup_failed_dlg_certificate_message
    158                         : R.string.account_setup_failed_dlg_certificate_message_fmt;
    159                 break;
    160             case MessagingException.AUTHENTICATION_FAILED:
    161                 id = R.string.account_setup_failed_dlg_auth_message;
    162                 break;
    163             case MessagingException.AUTODISCOVER_AUTHENTICATION_FAILED:
    164                 id = R.string.account_setup_autodiscover_dlg_authfail_message;
    165                 break;
    166             case MessagingException.AUTHENTICATION_FAILED_OR_SERVER_ERROR:
    167                 id = R.string.account_setup_failed_check_credentials_message;
    168                 break;
    169             case MessagingException.IOERROR:
    170                 id = R.string.account_setup_failed_ioerror;
    171                 break;
    172             case MessagingException.TLS_REQUIRED:
    173                 id = R.string.account_setup_failed_tls_required;
    174                 break;
    175             case MessagingException.AUTH_REQUIRED:
    176                 id = R.string.account_setup_failed_auth_required;
    177                 break;
    178             case MessagingException.SECURITY_POLICIES_UNSUPPORTED:
    179                 id = R.string.account_setup_failed_security_policies_unsupported;
    180                 // Belt and suspenders here; there should always be a non-empty array here
    181                 String[] unsupportedPolicies = (String[]) ex.getExceptionData();
    182                 if (unsupportedPolicies == null) {
    183                     LogUtils.w(LogUtils.TAG, "No data for unsupported policies?");
    184                     break;
    185                 }
    186                 // Build a string, concatenating policies we don't support
    187                 final StringBuilder sb = new StringBuilder();
    188                 boolean first = true;
    189                 for (String policyName: unsupportedPolicies) {
    190                     if (first) {
    191                         first = false;
    192                     } else {
    193                         sb.append(", ");
    194                     }
    195                     sb.append(policyName);
    196                 }
    197                 message = sb.toString();
    198                 break;
    199             case MessagingException.ACCESS_DENIED:
    200                 id = R.string.account_setup_failed_access_denied;
    201                 break;
    202             case MessagingException.PROTOCOL_VERSION_UNSUPPORTED:
    203                 id = R.string.account_setup_failed_protocol_unsupported;
    204                 break;
    205             case MessagingException.GENERAL_SECURITY:
    206                 id = R.string.account_setup_failed_security;
    207                 break;
    208             case MessagingException.CLIENT_CERTIFICATE_REQUIRED:
    209                 id = R.string.account_setup_failed_certificate_required;
    210                 break;
    211             case MessagingException.CLIENT_CERTIFICATE_ERROR:
    212                 id = R.string.account_setup_failed_certificate_inaccessible;
    213                 break;
    214             default:
    215                 id = TextUtils.isEmpty(message)
    216                         ? R.string.account_setup_failed_dlg_server_message
    217                         : R.string.account_setup_failed_dlg_server_message_fmt;
    218                 break;
    219         }
    220         return TextUtils.isEmpty(message)
    221                 ? context.getString(id)
    222                 : context.getString(id, message);
    223     }
    224 }
    225