be0b8e000f1d8e6fae8dc0215e37603d69a5898e
[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, String authTokenType,
74 String[] requiredFeatures, Bundle options)
75 throws NetworkErrorException {
76 Log.i(TAG, "Adding account with type " + accountType
77 + " and auth token " + authTokenType);
78 try {
79 validateAccountType(accountType);
80 } catch (AuthenticatorException e) {
81 Log.e(TAG, "Failed to validate account type " + accountType + ": "
82 + e.getMessage());
83 e.printStackTrace();
84 return e.getFailureBundle();
85 }
86 final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
87 intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
88 response);
89 intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType);
90 intent.putExtra(KEY_REQUIRED_FEATURES, requiredFeatures);
91 intent.putExtra(KEY_LOGIN_OPTIONS, options);
92
93 setIntentFlags(intent);
94 final Bundle bundle = new Bundle();
95 bundle.putParcelable(AccountManager.KEY_INTENT, intent);
96 return bundle;
97 }
98
99 /**
100 * {@inheritDoc}
101 */
102 @Override
103 public Bundle confirmCredentials(AccountAuthenticatorResponse response,
104 Account account, Bundle options) throws NetworkErrorException {
105 try {
106 validateAccountType(account.type);
107 } catch (AuthenticatorException e) {
108 Log.e(TAG, "Failed to validate account type " + account.type + ": "
109 + e.getMessage());
110 e.printStackTrace();
111 return e.getFailureBundle();
112 }
113 Intent intent = new Intent(mContext, AuthenticatorActivity.class);
114 intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
115 response);
116 intent.putExtra(KEY_ACCOUNT, account);
117 intent.putExtra(KEY_LOGIN_OPTIONS, options);
118
119 setIntentFlags(intent);
120
121 Bundle resultBundle = new Bundle();
122 resultBundle.putParcelable(AccountManager.KEY_INTENT, intent);
123 return resultBundle;
124 }
125
126 @Override
127 public Bundle editProperties(AccountAuthenticatorResponse response,
128 String accountType) {
129 return null;
130 }
131
132 @Override
133 public Bundle getAuthToken(AccountAuthenticatorResponse response,
134 Account account, String authTokenType, Bundle options)
135 throws NetworkErrorException {
136 try {
137 validateAccountType(account.type);
138 validateAuthTokenType(authTokenType);
139 } catch (AuthenticatorException e) {
140 Log.e(TAG, "Failed to validate account type " + account.type + ": "
141 + e.getMessage());
142 e.printStackTrace();
143 return e.getFailureBundle();
144 }
145 final AccountManager am = AccountManager.get(mContext);
146 final String password = am.getPassword(account);
147 if (password != null) {
148 final Bundle result = new Bundle();
149 result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
150 result.putString(AccountManager.KEY_ACCOUNT_TYPE, ACCOUNT_TYPE);
151 result.putString(AccountManager.KEY_AUTHTOKEN, password);
152 return result;
153 }
154
155 final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
156 intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
157 response);
158 intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType);
159 intent.putExtra(KEY_LOGIN_OPTIONS, options);
160 intent.putExtra(AuthenticatorActivity.PARAM_USERNAME, account.name);
161
162 final Bundle bundle = new Bundle();
163 bundle.putParcelable(AccountManager.KEY_INTENT, intent);
164 return bundle;
165 }
166
167 @Override
168 public String getAuthTokenLabel(String authTokenType) {
169 return null;
170 }
171
172 @Override
173 public Bundle hasFeatures(AccountAuthenticatorResponse response,
174 Account account, String[] features) throws NetworkErrorException {
175 final Bundle result = new Bundle();
176 result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
177 return result;
178 }
179
180 @Override
181 public Bundle updateCredentials(AccountAuthenticatorResponse response,
182 Account account, String authTokenType, Bundle options)
183 throws NetworkErrorException {
184 final Intent intent = new Intent(mContext, AuthenticatorActivity.class);
185 intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
186 response);
187 intent.putExtra(KEY_ACCOUNT, account);
188 intent.putExtra(KEY_AUTH_TOKEN_TYPE, authTokenType);
189 intent.putExtra(KEY_LOGIN_OPTIONS, options);
190 setIntentFlags(intent);
191
192 final Bundle bundle = new Bundle();
193 bundle.putParcelable(AccountManager.KEY_INTENT, intent);
194 return bundle;
195 }
196
197 @Override
198 public Bundle getAccountRemovalAllowed(
199 AccountAuthenticatorResponse response, Account account)
200 throws NetworkErrorException {
201 return super.getAccountRemovalAllowed(response, account);
202 }
203
204 private void setIntentFlags(Intent intent) {
205 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
206 intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
207 intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
208 intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
209 intent.addFlags(Intent.FLAG_FROM_BACKGROUND);
210 }
211
212 private void validateAccountType(String type)
213 throws UnsupportedAccountTypeException {
214 if (!type.equals(ACCOUNT_TYPE)) {
215 throw new UnsupportedAccountTypeException();
216 }
217 }
218
219 private void validateAuthTokenType(String authTokenType)
220 throws UnsupportedAuthTokenTypeException {
221 if (!authTokenType.equals(AUTH_TOKEN_TYPE)) {
222 throw new UnsupportedAuthTokenTypeException();
223 }
224 }
225
226 public static class AuthenticatorException extends Exception {
227 private static final long serialVersionUID = 1L;
228 private Bundle mFailureBundle;
229
230 public AuthenticatorException(int code, String errorMsg) {
231 mFailureBundle = new Bundle();
232 mFailureBundle.putInt(AccountManager.KEY_ERROR_CODE, code);
233 mFailureBundle
234 .putString(AccountManager.KEY_ERROR_MESSAGE, errorMsg);
235 }
236
237 public Bundle getFailureBundle() {
238 return mFailureBundle;
239 }
240 }
241
242 public static class UnsupportedAccountTypeException extends
243 AuthenticatorException {
244 private static final long serialVersionUID = 1L;
245
246 public UnsupportedAccountTypeException() {
247 super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
248 "Unsupported account type");
249 }
250 }
251
252 public static class UnsupportedAuthTokenTypeException extends
253 AuthenticatorException {
254 private static final long serialVersionUID = 1L;
255
256 public UnsupportedAuthTokenTypeException() {
257 super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
258 "Unsupported auth token type");
259 }
260 }
261
262 public static class UnsupportedFeaturesException extends
263 AuthenticatorException {
264 public static final long serialVersionUID = 1L;
265
266 public UnsupportedFeaturesException() {
267 super(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
268 "Unsupported features");
269 }
270 }
271
272 public static class AccessDeniedException extends AuthenticatorException {
273 public AccessDeniedException(int code, String errorMsg) {
274 super(AccountManager.ERROR_CODE_INVALID_RESPONSE, "Access Denied");
275 }
276
277 private static final long serialVersionUID = 1L;
278
279 }
280 }