1 /* ownCloud Android client application 
   2  *   Copyright (C) 2012  Bartek Przybylski 
   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. 
   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. 
  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/>. 
  19 package eu
.alefzero
.owncloud
.authenticator
; 
  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
; 
  28 public class AccountAuthenticator 
extends AbstractAccountAuthenticator 
{ 
  30      * Is used by android system to assign accounts to authenticators. Should be 
  31      * used by application and all extensions. 
  33     public static final String ACCOUNT_TYPE 
= "owncloud"; 
  34     public static final String AUTH_TOKEN_TYPE 
= "org.owncloud"; 
  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"; 
  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} 
  48     public static final String KEY_OC_URL 
= "oc_url"; 
  50      * Version should be 3 numbers separated by dot so it can be parsed by 
  51      * {@link eu.alefzero.owncloud.utils.OwnCloudVersion} 
  53     public static final String KEY_OC_VERSION 
= "oc_version"; 
  55      * Base url should point to owncloud installation without trailing / ie: 
  56      * http://server/path or https://owncloud.server 
  58     public static final String KEY_OC_BASE_URL 
= "oc_base_url"; 
  60     private static final String TAG 
= "AccountAuthenticator"; 
  61     private Context mContext
; 
  63     public AccountAuthenticator(Context context
) { 
  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
); 
  79             validateAccountType(accountType
); 
  80         } catch (AuthenticatorException e
) { 
  81             Log
.e(TAG
, "Failed to validate account type " + accountType 
+ ": " 
  84             return e
.getFailureBundle(); 
  86         final Intent intent 
= new Intent(mContext
, AuthenticatorActivity
.class); 
  87         intent
.putExtra(AccountManager
.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE
, 
  89         intent
.putExtra(KEY_AUTH_TOKEN_TYPE
, authTokenType
); 
  90         intent
.putExtra(KEY_REQUIRED_FEATURES
, requiredFeatures
); 
  91         intent
.putExtra(KEY_LOGIN_OPTIONS
, options
); 
  93         setIntentFlags(intent
); 
  94         final Bundle bundle 
= new Bundle(); 
  95         bundle
.putParcelable(AccountManager
.KEY_INTENT
, intent
); 
 103     public Bundle 
confirmCredentials(AccountAuthenticatorResponse response
, 
 104             Account account
, Bundle options
) throws NetworkErrorException 
{ 
 106             validateAccountType(account
.type
); 
 107         } catch (AuthenticatorException e
) { 
 108             Log
.e(TAG
, "Failed to validate account type " + account
.type 
+ ": " 
 111             return e
.getFailureBundle(); 
 113         Intent intent 
= new Intent(mContext
, AuthenticatorActivity
.class); 
 114         intent
.putExtra(AccountManager
.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE
, 
 116         intent
.putExtra(KEY_ACCOUNT
, account
); 
 117         intent
.putExtra(KEY_LOGIN_OPTIONS
, options
); 
 119         setIntentFlags(intent
); 
 121         Bundle resultBundle 
= new Bundle(); 
 122         resultBundle
.putParcelable(AccountManager
.KEY_INTENT
, intent
); 
 127     public Bundle 
editProperties(AccountAuthenticatorResponse response
, 
 128             String accountType
) { 
 133     public Bundle 
getAuthToken(AccountAuthenticatorResponse response
, 
 134             Account account
, String authTokenType
, Bundle options
) 
 135             throws NetworkErrorException 
{ 
 137             validateAccountType(account
.type
); 
 138             validateAuthTokenType(authTokenType
); 
 139         } catch (AuthenticatorException e
) { 
 140             Log
.e(TAG
, "Failed to validate account type " + account
.type 
+ ": " 
 143             return e
.getFailureBundle(); 
 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
); 
 155         final Intent intent 
= new Intent(mContext
, AuthenticatorActivity
.class); 
 156         intent
.putExtra(AccountManager
.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE
, 
 158         intent
.putExtra(KEY_AUTH_TOKEN_TYPE
, authTokenType
); 
 159         intent
.putExtra(KEY_LOGIN_OPTIONS
, options
); 
 160         intent
.putExtra(AuthenticatorActivity
.PARAM_USERNAME
, account
.name
); 
 162         final Bundle bundle 
= new Bundle(); 
 163         bundle
.putParcelable(AccountManager
.KEY_INTENT
, intent
); 
 168     public String 
getAuthTokenLabel(String authTokenType
) { 
 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
); 
 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
, 
 187         intent
.putExtra(KEY_ACCOUNT
, account
); 
 188         intent
.putExtra(KEY_AUTH_TOKEN_TYPE
, authTokenType
); 
 189         intent
.putExtra(KEY_LOGIN_OPTIONS
, options
); 
 190         setIntentFlags(intent
); 
 192         final Bundle bundle 
= new Bundle(); 
 193         bundle
.putParcelable(AccountManager
.KEY_INTENT
, intent
); 
 198     public Bundle 
getAccountRemovalAllowed( 
 199             AccountAuthenticatorResponse response
, Account account
) 
 200             throws NetworkErrorException 
{ 
 201         return super.getAccountRemovalAllowed(response
, account
); 
 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
); 
 212     private void validateAccountType(String type
) 
 213             throws UnsupportedAccountTypeException 
{ 
 214         if (!type
.equals(ACCOUNT_TYPE
)) { 
 215             throw new UnsupportedAccountTypeException(); 
 219     private void validateAuthTokenType(String authTokenType
) 
 220             throws UnsupportedAuthTokenTypeException 
{ 
 221         if (!authTokenType
.equals(AUTH_TOKEN_TYPE
)) { 
 222             throw new UnsupportedAuthTokenTypeException(); 
 226     public static class AuthenticatorException 
extends Exception 
{ 
 227         private static final long serialVersionUID 
= 1L; 
 228         private Bundle mFailureBundle
; 
 230         public AuthenticatorException(int code
, String errorMsg
) { 
 231             mFailureBundle 
= new Bundle(); 
 232             mFailureBundle
.putInt(AccountManager
.KEY_ERROR_CODE
, code
); 
 234                     .putString(AccountManager
.KEY_ERROR_MESSAGE
, errorMsg
); 
 237         public Bundle 
getFailureBundle() { 
 238             return mFailureBundle
; 
 242     public static class UnsupportedAccountTypeException 
extends 
 243             AuthenticatorException 
{ 
 244         private static final long serialVersionUID 
= 1L; 
 246         public UnsupportedAccountTypeException() { 
 247             super(AccountManager
.ERROR_CODE_UNSUPPORTED_OPERATION
, 
 248                     "Unsupported account type"); 
 252     public static class UnsupportedAuthTokenTypeException 
extends 
 253             AuthenticatorException 
{ 
 254         private static final long serialVersionUID 
= 1L; 
 256         public UnsupportedAuthTokenTypeException() { 
 257             super(AccountManager
.ERROR_CODE_UNSUPPORTED_OPERATION
, 
 258                     "Unsupported auth token type"); 
 262     public static class UnsupportedFeaturesException 
extends 
 263             AuthenticatorException 
{ 
 264         public static final long serialVersionUID 
= 1L; 
 266         public UnsupportedFeaturesException() { 
 267             super(AccountManager
.ERROR_CODE_UNSUPPORTED_OPERATION
, 
 268                     "Unsupported features"); 
 272     public static class AccessDeniedException 
extends AuthenticatorException 
{ 
 273         public AccessDeniedException(int code
, String errorMsg
) { 
 274             super(AccountManager
.ERROR_CODE_INVALID_RESPONSE
, "Access Denied"); 
 277         private static final long serialVersionUID 
= 1L;