• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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          */
onCheckSettingsErrorDialogEditCertificate()46         void onCheckSettingsErrorDialogEditCertificate();
47 
48         /**
49          * Called to indicate the user wants to resolve the error by editing the server settings
50          */
onCheckSettingsErrorDialogEditSettings()51         void onCheckSettingsErrorDialogEditSettings();
52     }
53 
CheckSettingsErrorDialogFragment()54     public CheckSettingsErrorDialogFragment() {}
55 
56     /**
57      * @param reason see REASON_* constants
58      * @param message from {@link #getErrorString(Context, MessagingException)}
59      * @return new instance
60      */
newInstance(int reason, String message)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
onCreateDialog(Bundle savedInstanceState)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
onCancel(DialogInterface dialog)128     public void onCancel(DialogInterface dialog) {
129         super.onCancel(dialog);
130         final Callback callback = (Callback) getActivity();
131         callback.onCheckSettingsErrorDialogEditSettings();
132     }
133 
getReasonFromException(MessagingException ex)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 
getErrorString(Context context, MessagingException ex)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