adjusting design to holo, stability for account setup
[pub/Android/ownCloud.git] / src / eu / alefzero / owncloud / authenticator / AccountAuthenticator.java
1 /* ownCloud Android client application
2 * Copyright (C) 2012 Bartek Przybylski
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19 package eu.alefzero.owncloud.authenticator;
20
21 import eu.alefzero.owncloud.ui.activity.AuthenticatorActivity;
22 import android.accounts.*;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.os.Bundle;
26 import android.util.Log;
27
28 public class AccountAuthenticator extends AbstractAccountAuthenticator {
29 /**
30 * Is used by android system to assign accounts to authenticators. Should be
31 * used by application and all extensions.
32 */
33 public static final String ACCOUNT_TYPE = "owncloud";
34 public static final String AUTH_TOKEN_TYPE = "org.owncloud";
35
36 public static final String KEY_AUTH_TOKEN_TYPE = "authTokenType";
37 public static final String KEY_REQUIRED_FEATURES = "requiredFeatures";
38 public static final String KEY_LOGIN_OPTIONS = "loginOptions";
39 public static final String KEY_ACCOUNT = "account";
40 /**
41 * Value under this key should handle path to webdav php script. Will be
42 * removed and usage should be replaced by combining
43 * {@link eu.alefzero.owncloud.authenticator.KEY_OC_BASE_URL} and
44 * {@link eu.alefzero.owncloud.utils.OwnCloudVersion}
45 *
46 * @deprecated
47 */
48 public static final String KEY_OC_URL = "oc_url";
49 /**
50 * Version should be 3 numbers separated by dot so it can be parsed by
51 * {@link eu.alefzero.owncloud.utils.OwnCloudVersion}
52 */
53 public static final String KEY_OC_VERSION = "oc_version";
54 /**
55 * Base url should point to owncloud installation without trailing / ie:
56 * http://server/path or https://owncloud.server
57 */
58 public static final String KEY_OC_BASE_URL = "oc_base_url";
59
60 private static final String TAG = "AccountAuthenticator";
61 private Context mContext;
62
63 public AccountAuthenticator(Context context) {
64 super(context);
65 mContext = context;
66 }
67
68 /**
69 * {@inheritDoc}
70 */
71 @Override
72 public Bundle addAccount(AccountAuthenticatorResponse response,
73 String accountType,
74 String authTokenType,
75 String[] requiredFeatures,
76 Bundle options) throws NetworkErrorException {
77 Log.i(TAG, "Adding account with type " + accountType + " and auth token " + authTokenType);
78 try {
79 validateAccountType(accountType);
80 } catch (AuthenticatorException e) {
81 Log.e(TAG, "Failed to validate account type "+ accountType +": " + e.getMessage());
82 e.printStackTrace();
83 return e.getFailureBundle();
84 }
85 final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
86 intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
87 intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType);
88 intent.putExtra(KEY_REQUIRED_FEATURES, requiredFeatures);
89 intent.putExtra(KEY_LOGIN_OPTIONS, options);
90
91 setIntentFlags(intent);
92 final Bundle bundle = new Bundle();
93 bundle.putParcelable(AccountManager.KEY_INTENT, intent);
94 return bundle;
95 }
96
97 /**
98 * {@inheritDoc}
99 */
100 @Override
101 public Bundle confirmCredentials(AccountAuthenticatorResponse response,
102 Account account, Bundle options) throws NetworkErrorException {
103 try {
104 validateAccountType(account.type);
105 } catch (AuthenticatorException e) {
106 Log.e(TAG, "Failed to validate account type "+ account.type +": " + e.getMessage());
107 e.printStackTrace();
108 return e.getFailureBundle();
109 }
110 Intent intent = new Intent(mContext, AuthenticatorActivity.class);
111 intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
112 intent.putExtra(KEY_ACCOUNT, account);
113 intent.putExtra(KEY_LOGIN_OPTIONS, options);
114
115 setIntentFlags(intent);
116
117 Bundle resultBundle = new Bundle();
118 resultBundle.putParcelable(AccountManager.KEY_INTENT, intent);
119 return resultBundle;
120 }
121
122 @Override
123 public Bundle editProperties(AccountAuthenticatorResponse response,
124 String accountType) {
125 return null;
126 }
127
128 @Override
129 public Bundle getAuthToken(AccountAuthenticatorResponse response,
130 Account account,
131 String authTokenType,
132 Bundle options) throws NetworkErrorException {
133 try {
134 validateAccountType(account.type);
135 validateAuthTokenType(authTokenType);
136 } catch (AuthenticatorException e) {
137 Log.e(TAG, "Failed to validate account type "+ account.type +": " + e.getMessage());
138 e.printStackTrace();
139 return e.getFailureBundle();
140 }
141 final AccountManager am = AccountManager.get(mContext);
142 final String password = am.getPassword(account);
143 if (password != null) {
144 final Bundle result = new Bundle();
145 result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
146 result.putString(AccountManager.KEY_ACCOUNT_TYPE, ACCOUNT_TYPE);
147 result.putString(AccountManager.KEY_AUTHTOKEN, password);
148 return result;
149 }
150
151 final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
152 intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
153 intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType);
154 intent.putExtra(KEY_LOGIN_OPTIONS, options);
155 intent.putExtra(AuthenticatorActivity.PARAM_USERNAME, account.name);
156
157 final Bundle bundle = new Bundle();
158 bundle.putParcelable(AccountManager.KEY_INTENT, intent);
159 return bundle;
160 }
161
162 @Override
163 public String getAuthTokenLabel(String authTokenType) {
164 return null;
165 }
166
167 @Override
168 public Bundle hasFeatures(AccountAuthenticatorResponse response,
169 Account account,
170 String[] features) throws NetworkErrorException {
171 final Bundle result = new Bundle();
172 result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
173 return result;
174 }
175
176 @Override
177 public Bundle updateCredentials(AccountAuthenticatorResponse response,
178 Account account,
179 String authTokenType,
180 Bundle options) throws NetworkErrorException {
181 final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
182 intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
183 intent.putExtra(KEY_ACCOUNT, account);
184 intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType);
185 intent.putExtra(KEY_LOGIN_OPTIONS, options);
186 setIntentFlags(intent);
187
188 final Bundle bundle = new Bundle();
189 bundle.putParcelable(AccountManager.KEY_INTENT, intent);
190 return bundle;
191 }
192
193 @Override
194 public Bundle getAccountRemovalAllowed(AccountAuthenticatorResponse response,
195 Account account) throws NetworkErrorException {
196 return super.getAccountRemovalAllowed(response, account);
197 }
198
199 private void setIntentFlags(Intent intent) {
200 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
201 intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
202 intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
203 intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
204 intent.addFlags(Intent.FLAG_FROM_BACKGROUND);
205 }
206
207 private void validateAccountType(String type)
208 throws UnsupportedAccountTypeException {
209 if (!type.equals(ACCOUNT_TYPE)) {
210 throw new UnsupportedAccountTypeException();
211 }
212 }
213
214 private void validateAuthTokenType(String authTokenType)
215 throws UnsupportedAuthTokenTypeException {
216 if (!authTokenType.equals(AUTH_TOKEN_TYPE)) {
217 throw new UnsupportedAuthTokenTypeException();
218 }
219 }
220
221 public static class AuthenticatorException extends Exception {
222 private static final long serialVersionUID = 1L;
223 private Bundle mFailureBundle;
224
225 public AuthenticatorException(int code, String errorMsg) {
226 mFailureBundle = new Bundle();
227 mFailureBundle.putInt(AccountManager.KEY_ERROR_CODE, code);
228 mFailureBundle.putString(AccountManager.KEY_ERROR_MESSAGE, errorMsg);
229 }
230
231 public Bundle getFailureBundle() {
232 return mFailureBundle;
233 }
234 }
235
236 public static class UnsupportedAccountTypeException
237 extends
238 AuthenticatorException {
239 private static final long serialVersionUID = 1L;
240
241 public UnsupportedAccountTypeException() {
242 super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
243 "Unsupported account type");
244 }
245 }
246
247 public static class UnsupportedAuthTokenTypeException
248 extends
249 AuthenticatorException {
250 private static final long serialVersionUID = 1L;
251
252 public UnsupportedAuthTokenTypeException() {
253 super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
254 "Unsupported auth token type");
255 }
256 }
257
258 public static class UnsupportedFeaturesException
259 extends
260 AuthenticatorException {
261 public static final long serialVersionUID = 1L;
262
263 public UnsupportedFeaturesException() {
264 super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
265 "Unsupported features");
266 }
267 }
268
269 public static class AccessDeniedException extends AuthenticatorException {
270 public AccessDeniedException(int code, String errorMsg) {
271 super(AccountManager.ERROR_CODE_INVALID_RESPONSE, "Access Denied");
272 }
273
274 private static final long serialVersionUID = 1L;
275
276 }
277 }