Merge branch 'master' into oauth_login
[pub/Android/ownCloud.git] / src / com / owncloud / android / ui / activity / AuthenticatorActivity.java
index bd36ed1..fc84df6 100644 (file)
@@ -20,16 +20,29 @@ package com.owncloud.android.ui.activity;
 \r
 import java.net.MalformedURLException;\r
 import java.net.URL;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.json.JSONException;\r
+import org.json.JSONObject;\r
 \r
 import com.owncloud.android.AccountUtils;\r
 import com.owncloud.android.authenticator.AccountAuthenticator;\r
 import com.owncloud.android.authenticator.AuthenticationRunnable;\r
 import com.owncloud.android.authenticator.OnAuthenticationResultListener;\r
 import com.owncloud.android.authenticator.OnConnectCheckListener;\r
+import com.owncloud.android.authenticator.oauth2.OAuth2Context;\r
+import com.owncloud.android.authenticator.oauth2.OAuth2GetCodeRunnable;\r
+import com.owncloud.android.authenticator.oauth2.OnOAuth2GetCodeResultListener;\r
+import com.owncloud.android.authenticator.oauth2.connection.ConnectorOAuth2;\r
+import com.owncloud.android.authenticator.oauth2.services.OAuth2GetTokenService;\r
 import com.owncloud.android.ui.dialog.SslValidatorDialog;\r
 import com.owncloud.android.ui.dialog.SslValidatorDialog.OnSslValidatorListener;\r
+import com.owncloud.android.utils.OwnCloudVersion;\r
 import com.owncloud.android.network.OwnCloudClientUtils;\r
 import com.owncloud.android.operations.ConnectionCheckOperation;\r
+import com.owncloud.android.operations.ExistenceCheckOperation;\r
+import com.owncloud.android.operations.GetOAuth2AccessToken;\r
 import com.owncloud.android.operations.OnRemoteOperationListener;\r
 import com.owncloud.android.operations.RemoteOperation;\r
 import com.owncloud.android.operations.RemoteOperationResult;\r
@@ -40,9 +53,12 @@ import android.accounts.AccountManager;
 import android.app.AlertDialog;\r
 import android.app.Dialog;\r
 import android.app.ProgressDialog;\r
+import android.content.BroadcastReceiver;\r
 import android.content.ContentResolver;\r
+import android.content.Context;\r
 import android.content.DialogInterface;\r
 import android.content.Intent;\r
+import android.content.IntentFilter;\r
 import android.content.SharedPreferences;\r
 import android.net.Uri;\r
 import android.os.Bundle;\r
@@ -54,8 +70,9 @@ import android.view.View;
 import android.view.View.OnClickListener;\r
 import android.view.View.OnFocusChangeListener;\r
 import android.view.Window;\r
-import android.widget.Button;\r
+import android.widget.CheckBox;\r
 import android.widget.EditText;\r
+import android.widget.Button;\r
 import android.widget.ImageView;\r
 import android.widget.TextView;\r
 import com.owncloud.android.R;\r
@@ -70,7 +87,7 @@ import eu.alefzero.webdav.WebdavClient;
  */\r
 public class AuthenticatorActivity extends AccountAuthenticatorActivity\r
         implements OnAuthenticationResultListener, OnConnectCheckListener, OnRemoteOperationListener, OnSslValidatorListener, \r
-        OnFocusChangeListener, OnClickListener {\r
+        OnFocusChangeListener, OnClickListener, OnOAuth2GetCodeResultListener {\r
 \r
     private static final int DIALOG_LOGIN_PROGRESS = 0;\r
     private static final int DIALOG_SSL_VALIDATOR = 1;\r
@@ -80,22 +97,50 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
 \r
     private Thread mAuthThread;\r
     private AuthenticationRunnable mAuthRunnable;\r
-    //private ConnectionCheckerRunnable mConnChkRunnable = null;\r
     private ConnectionCheckOperation mConnChkRunnable;\r
+    private ExistenceCheckOperation mAuthChkOperation;\r
     private final Handler mHandler = new Handler();\r
     private String mBaseUrl;\r
+    private OwnCloudVersion mDiscoveredVersion;\r
     \r
     private static final String STATUS_TEXT = "STATUS_TEXT";\r
     private static final String STATUS_ICON = "STATUS_ICON";\r
     private static final String STATUS_CORRECT = "STATUS_CORRECT";\r
     private static final String IS_SSL_CONN = "IS_SSL_CONN";\r
+    private static final String OC_VERSION = "OC_VERSION";\r
     private int mStatusText, mStatusIcon;\r
     private boolean mStatusCorrect, mIsSslConn;\r
     private RemoteOperationResult mLastSslUntrustedServerResult;\r
 \r
+    public static final String PARAM_ACCOUNTNAME = "param_Accountname";\r
+    \r
     public static final String PARAM_USERNAME = "param_Username";\r
     public static final String PARAM_HOSTNAME = "param_Hostname";\r
 \r
+    // oAuth2 variables.\r
+    private static final int OAUTH2_LOGIN_PROGRESS = 3;\r
+    private static final String OAUTH2_STATUS_TEXT = "OAUTH2_STATUS_TEXT";\r
+    private static final String OAUTH2_STATUS_ICON = "OAUTH2_STATUS_ICON";\r
+    private static final String OAUTH2_CODE_RESULT = "CODE_RESULT";\r
+    private static final String OAUTH2_IS_CHECKED = "OAUTH2_IS_CHECKED";    \r
+    private Thread mOAuth2GetCodeThread;\r
+    private OAuth2GetCodeRunnable mOAuth2GetCodeRunnable;     \r
+    private TokenReceiver tokenReceiver;\r
+    private JSONObject codeResponseJson; \r
+    private int mOAuth2StatusText, mOAuth2StatusIcon;    \r
+    \r
+    public ConnectorOAuth2 connectorOAuth2;\r
+    \r
+    // Variables used to save the on the state the contents of all fields.\r
+    private static final String HOST_URL_TEXT = "HOST_URL_TEXT";\r
+    private static final String ACCOUNT_USERNAME = "ACCOUNT_USERNAME";\r
+    private static final String ACCOUNT_PASSWORD = "ACCOUNT_PASSWORD";\r
+    \r
+    //private boolean mNewRedirectUriCaptured;\r
+    private Uri mNewCapturedUriFromOAuth2Redirection;\r
+\r
+    // END of oAuth2 variables.\r
+    \r
     @Override\r
     protected void onCreate(Bundle savedInstanceState) {\r
         super.onCreate(savedInstanceState);\r
@@ -105,6 +150,8 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
         ImageView iv2 = (ImageView) findViewById(R.id.viewPassword);\r
         TextView tv = (TextView) findViewById(R.id.host_URL);\r
         TextView tv2 = (TextView) findViewById(R.id.account_password);\r
+        EditText oauth2Url = (EditText)findViewById(R.id.oAuth_URL);\r
+        oauth2Url.setText("OWNCLOUD AUTHORIZATION PROVIDER IN TEST");\r
 \r
         if (savedInstanceState != null) {\r
             mStatusIcon = savedInstanceState.getInt(STATUS_ICON);\r
@@ -116,29 +163,104 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             if (!mStatusCorrect)\r
                 iv.setVisibility(View.VISIBLE);\r
             else\r
-                iv.setVisibility(View.INVISIBLE);\r
+                iv.setVisibility(View.INVISIBLE);        \r
+            \r
+            String ocVersion = savedInstanceState.getString(OC_VERSION, null);\r
+            if (ocVersion != null)\r
+                mDiscoveredVersion = new OwnCloudVersion(ocVersion);\r
+            \r
+            // Getting the state of oAuth2 components.\r
+            mOAuth2StatusIcon = savedInstanceState.getInt(OAUTH2_STATUS_ICON);\r
+            mOAuth2StatusText = savedInstanceState.getInt(OAUTH2_STATUS_TEXT);\r
+                // We set this to true if the rotation happens when the user is validating oAuth2 user_code.\r
+            changeViewByOAuth2Check(savedInstanceState.getBoolean(OAUTH2_IS_CHECKED));\r
+                // We store a JSon object with all the data returned from oAuth2 server when we get user_code.\r
+                // Is better than store variable by variable. We use String object to serialize from/to it.\r
+            try {\r
+                if (savedInstanceState.containsKey(OAUTH2_CODE_RESULT)) {\r
+                    codeResponseJson = new JSONObject(savedInstanceState.getString(OAUTH2_CODE_RESULT));\r
+                }\r
+            } catch (JSONException e) {\r
+                Log.e(TAG, "onCreate->JSONException: " + e.toString());\r
+            }\r
+            // END of getting the state of oAuth2 components.\r
+            \r
+            // Getting contents of each field.\r
+            EditText hostUrl = (EditText)findViewById(R.id.host_URL);\r
+            hostUrl.setText(savedInstanceState.getString(HOST_URL_TEXT), TextView.BufferType.EDITABLE);\r
+            EditText accountUsername = (EditText)findViewById(R.id.account_username);\r
+            accountUsername.setText(savedInstanceState.getString(ACCOUNT_USERNAME), TextView.BufferType.EDITABLE);\r
+            EditText accountPassword = (EditText)findViewById(R.id.account_password);\r
+            accountPassword.setText(savedInstanceState.getString(ACCOUNT_PASSWORD), TextView.BufferType.EDITABLE);\r
+            // END of getting contents of each field\r
 \r
         } else {\r
             mStatusText = mStatusIcon = 0;\r
             mStatusCorrect = false;\r
             mIsSslConn = false;\r
+            \r
+            String accountName = getIntent().getExtras().getString(PARAM_ACCOUNTNAME);\r
+            String tokenType = getIntent().getExtras().getString(AccountAuthenticator.KEY_AUTH_TOKEN_TYPE);\r
+            if (AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN.equals(tokenType)) {\r
+                CheckBox oAuth2Check = (CheckBox) findViewById(R.id.oauth_onOff_check);\r
+                oAuth2Check.setChecked(true);\r
+                changeViewByOAuth2Check(true);\r
+            } \r
+            \r
+            if (accountName != null) {\r
+                ((TextView) findViewById(R.id.account_username)).setText(accountName.substring(0, accountName.lastIndexOf('@')));\r
+                tv.setText(accountName.substring(accountName.lastIndexOf('@') + 1));\r
+            }\r
         }\r
         iv.setOnClickListener(this);\r
         iv2.setOnClickListener(this);\r
         tv.setOnFocusChangeListener(this);\r
         tv2.setOnFocusChangeListener(this);\r
-\r
+        \r
         Button b = (Button) findViewById(R.id.account_register);\r
         if (b != null) {\r
             b.setText(String.format(getString(R.string.auth_register), getString(R.string.app_name)));\r
         }\r
+\r
+        mNewCapturedUriFromOAuth2Redirection = null;\r
     }\r
 \r
+    \r
+    @Override\r
+    protected void onNewIntent (Intent intent) {\r
+        Uri data = intent.getData();\r
+        //mNewRedirectUriCaptured = (data != null && data.toString().startsWith(OAuth2Context.MY_REDIRECT_URI));\r
+        if (data != null && data.toString().startsWith(OAuth2Context.MY_REDIRECT_URI)) {\r
+            mNewCapturedUriFromOAuth2Redirection = data;\r
+        }\r
+        Log.d(TAG, "onNewIntent()");\r
+    \r
+    }\r
+    \r
+    \r
     @Override\r
     protected void onSaveInstanceState(Bundle outState) {\r
         outState.putInt(STATUS_ICON, mStatusIcon);\r
         outState.putInt(STATUS_TEXT, mStatusText);\r
         outState.putBoolean(STATUS_CORRECT, mStatusCorrect);\r
+        if (mDiscoveredVersion != null) \r
+            outState.putString(OC_VERSION, mDiscoveredVersion.toString());\r
+        \r
+        // Saving the state of oAuth2 components.\r
+        outState.putInt(OAUTH2_STATUS_ICON, mOAuth2StatusIcon);\r
+        outState.putInt(OAUTH2_STATUS_TEXT, mOAuth2StatusText);\r
+        CheckBox oAuth2Check = (CheckBox) findViewById(R.id.oauth_onOff_check);\r
+        outState.putBoolean(OAUTH2_IS_CHECKED, oAuth2Check.isChecked());\r
+        if (codeResponseJson != null){\r
+            outState.putString(OAUTH2_CODE_RESULT, codeResponseJson.toString());\r
+        }\r
+        // END of saving the state of oAuth2 components.\r
+        \r
+        // Saving contents of each field.\r
+        outState.putString(HOST_URL_TEXT,((TextView) findViewById(R.id.host_URL)).getText().toString().trim());\r
+        outState.putString(ACCOUNT_USERNAME,((TextView) findViewById(R.id.account_username)).getText().toString().trim());\r
+        outState.putString(ACCOUNT_PASSWORD,((TextView) findViewById(R.id.account_password)).getText().toString().trim());\r
+        \r
         super.onSaveInstanceState(outState);\r
     }\r
 \r
@@ -166,6 +288,41 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             dialog = working_dialog;\r
             break;\r
         }\r
+        // oAuth2 dialog. We show here to the user the URL and user_code that the user must validate in a web browser.\r
+        case OAUTH2_LOGIN_PROGRESS: {\r
+            ProgressDialog working_dialog = new ProgressDialog(this);\r
+            try {\r
+                if (codeResponseJson != null && codeResponseJson.has(OAuth2GetCodeRunnable.CODE_VERIFICATION_URL)) {\r
+                    working_dialog.setMessage(String.format(getString(R.string.oauth_code_validation_message), \r
+                            codeResponseJson.getString(OAuth2GetCodeRunnable.CODE_VERIFICATION_URL), \r
+                            codeResponseJson.getString(OAuth2GetCodeRunnable.CODE_USER_CODE)));\r
+                } else {\r
+                    working_dialog.setMessage(String.format("Getting authorization"));\r
+                }\r
+            } catch (JSONException e) {\r
+                Log.e(TAG, "onCreateDialog->JSONException: " + e.toString());\r
+            }\r
+            working_dialog.setIndeterminate(true);\r
+            working_dialog.setCancelable(true);\r
+            working_dialog\r
+            .setOnCancelListener(new DialogInterface.OnCancelListener() {\r
+                @Override\r
+                public void onCancel(DialogInterface dialog) {\r
+                    Log.i(TAG, "Login canceled");\r
+                    if (mOAuth2GetCodeThread != null) {\r
+                        mOAuth2GetCodeThread.interrupt();\r
+                        finish();\r
+                    } \r
+                    if (tokenReceiver != null) {\r
+                        unregisterReceiver(tokenReceiver);\r
+                        tokenReceiver = null;\r
+                        finish();\r
+                    }\r
+                }\r
+            });\r
+            dialog = working_dialog;\r
+            break;\r
+        }\r
         case DIALOG_SSL_VALIDATOR: {\r
             dialog = SslValidatorDialog.newInstance(this, mLastSslUntrustedServerResult, this);\r
             break;\r
@@ -194,6 +351,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
         switch (id) {\r
         case DIALOG_LOGIN_PROGRESS:\r
         case DIALOG_CERT_NOT_SAVED:\r
+        case OAUTH2_LOGIN_PROGRESS:\r
             break;\r
         case DIALOG_SSL_VALIDATOR: {\r
             ((SslValidatorDialog)dialog).updateResult(mLastSslUntrustedServerResult);\r
@@ -203,6 +361,32 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             Log.e(TAG, "Incorrect dialog called with id = " + id);\r
         }\r
     }\r
+    \r
+    @Override\r
+    protected void onResume() {\r
+        Log.d(TAG, "onResume() start");\r
+        // (old oauth code) Registering token receiver. We must listening to the service that is pooling to the oAuth server for a token.\r
+        if (tokenReceiver == null) {\r
+            IntentFilter tokenFilter = new IntentFilter(OAuth2GetTokenService.TOKEN_RECEIVED_MESSAGE);                \r
+            tokenReceiver = new TokenReceiver();\r
+            this.registerReceiver(tokenReceiver,tokenFilter);\r
+        }\r
+        // (new oauth code)\r
+        /*if (mNewRedirectUriCaptured) {\r
+            mNewRedirectUriCaptured = false;*/\r
+        if (mNewCapturedUriFromOAuth2Redirection != null) {\r
+            getOAuth2AccessTokenFromCapturedRedirection();            \r
+            \r
+        }\r
+        super.onResume();\r
+    }\r
+\r
+    @Override\r
+    protected void onPause() {\r
+        Log.d(TAG, "onPause() start");\r
+        super.onPause();\r
+    }    \r
+    \r
 \r
     public void onAuthenticationResult(boolean success, String message) {\r
         if (success) {\r
@@ -247,9 +431,10 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
                     AccountAuthenticator.ACCOUNT_TYPE);\r
             intent.putExtra(AccountManager.KEY_USERDATA, username);\r
 \r
+            accManager.setUserData(account, AccountAuthenticator.KEY_OC_URL,\r
+                    url.toString());\r
             accManager.setUserData(account,\r
-                    AccountAuthenticator.KEY_OC_VERSION, mConnChkRunnable\r
-                            .getDiscoveredVersion().toString());\r
+                    AccountAuthenticator.KEY_OC_VERSION, mDiscoveredVersion.toString());\r
             \r
             accManager.setUserData(account,\r
                     AccountAuthenticator.KEY_OC_BASE_URL, mBaseUrl);\r
@@ -302,9 +487,25 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
                 || url.toLowerCase().startsWith("https://")) {\r
             prefix = "";\r
         }\r
-        continueConnection(prefix);\r
+        CheckBox oAuth2Check = (CheckBox) findViewById(R.id.oauth_onOff_check);\r
+        if (oAuth2Check != null && oAuth2Check.isChecked()) {\r
+            startOauthorization();\r
+            \r
+        } else {\r
+            continueConnection(prefix);\r
+        }\r
     }\r
     \r
+    private void startOauthorization() {\r
+        // We start a thread to get an authorization code from the oAuth2 server.\r
+        setOAuth2ResultIconAndText(R.drawable.progress_small, R.string.oauth_login_connection);\r
+        mOAuth2GetCodeRunnable = new OAuth2GetCodeRunnable(OAuth2Context.OAUTH2_F_AUTHORIZATION_ENDPOINT_URL, this);\r
+        //mOAuth2GetCodeRunnable = new OAuth2GetCodeRunnable(OAuth2Context.OAUTH2_G_DEVICE_GETCODE_URL, this);\r
+        mOAuth2GetCodeRunnable.setListener(this, mHandler);\r
+        mOAuth2GetCodeThread = new Thread(mOAuth2GetCodeRunnable);\r
+        mOAuth2GetCodeThread.start();\r
+    }\r
+\r
     public void onRegisterClick(View view) {\r
         Intent register = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.url_account_register)));\r
         setResult(RESULT_CANCELED);\r
@@ -322,8 +523,8 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             url = url.substring(0, url.length() - 1);\r
 \r
         URL uri = null;\r
-        String webdav_path = AccountUtils.getWebdavPath(mConnChkRunnable\r
-                .getDiscoveredVersion());\r
+        mDiscoveredVersion = mConnChkRunnable.getDiscoveredVersion();\r
+        String webdav_path = AccountUtils.getWebdavPath(mDiscoveredVersion, false);\r
         \r
         if (webdav_path == null) {\r
             onAuthenticationResult(false, getString(R.string.auth_bad_oc_version_title));\r
@@ -427,7 +628,6 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
         findViewById(R.id.buttonOK).setEnabled(mStatusCorrect);\r
     }\r
 \r
-    @Override\r
     public void onFocusChange(View view, boolean hasFocus) {\r
         if (view.getId() == R.id.host_URL) {\r
             if (!hasFocus) {\r
@@ -437,11 +637,12 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
                     setResultIconAndText(R.drawable.progress_small,\r
                             R.string.auth_testing_connection);\r
                     //mConnChkRunnable = new ConnectionCheckerRunnable(uri, this);\r
-                    mConnChkRunnable = new ConnectionCheckOperation(uri, this);\r
+                    mConnChkRunnable = new  ConnectionCheckOperation(uri, this);\r
                     //mConnChkRunnable.setListener(this, mHandler);\r
                     //mAuthThread = new Thread(mConnChkRunnable);\r
                     //mAuthThread.start();\r
                        WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(uri), this);\r
+                       mDiscoveredVersion = null;\r
                     mAuthThread = mConnChkRunnable.execute(client, this, mHandler);\r
                 } else {\r
                     findViewById(R.id.refreshButton).setVisibility(\r
@@ -501,10 +702,212 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             view.setSelection(selectionStart, selectionEnd);\r
         }\r
     }\r
+    \r
+    @Override protected void onDestroy() {       \r
+        // We must stop the service thats it's pooling to oAuth2 server for a token.\r
+        Intent tokenService = new Intent(this, OAuth2GetTokenService.class);\r
+        stopService(tokenService);\r
+        \r
+        // We stop listening the result of the pooling service.\r
+        if (tokenReceiver != null) {\r
+            unregisterReceiver(tokenReceiver);\r
+            tokenReceiver = null;\r
+            finish();\r
+        }\r
+\r
+        super.onDestroy();\r
+    }    \r
+    \r
+    // Controlling the oAuth2 checkbox on the activity: hide and show widgets.\r
+    public void onOff_check_Click(View view) {\r
+        CheckBox oAuth2Check = (CheckBox)view;      \r
+        changeViewByOAuth2Check(oAuth2Check.isChecked());\r
+\r
+    }\r
+    \r
+    public void changeViewByOAuth2Check(Boolean checked) {\r
+        \r
+        EditText oAuth2Url = (EditText) findViewById(R.id.oAuth_URL);\r
+        EditText accountUsername = (EditText) findViewById(R.id.account_username);\r
+        EditText accountPassword = (EditText) findViewById(R.id.account_password);\r
+        ImageView viewPassword = (ImageView) findViewById(R.id.viewPassword); \r
+        ImageView auth2ActionIndicator = (ImageView) findViewById(R.id.auth2_action_indicator); \r
+        TextView oauth2StatusText = (TextView) findViewById(R.id.oauth2_status_text);         \r
+\r
+        if (checked) {\r
+            oAuth2Url.setVisibility(View.VISIBLE);\r
+            accountUsername.setVisibility(View.GONE);\r
+            accountPassword.setVisibility(View.GONE);\r
+            viewPassword.setVisibility(View.GONE);\r
+            auth2ActionIndicator.setVisibility(View.INVISIBLE);\r
+            oauth2StatusText.setVisibility(View.INVISIBLE);\r
+        } else {\r
+            oAuth2Url.setVisibility(View.GONE);\r
+            accountUsername.setVisibility(View.VISIBLE);\r
+            accountPassword.setVisibility(View.VISIBLE);\r
+            viewPassword.setVisibility(View.INVISIBLE);\r
+            auth2ActionIndicator.setVisibility(View.GONE);\r
+            oauth2StatusText.setVisibility(View.GONE);\r
+        }     \r
+\r
+    }    \r
+    \r
+    // Controlling the oAuth2 result of server connection.\r
+    private void setOAuth2ResultIconAndText(int drawable_id, int text_id) {\r
+        ImageView iv = (ImageView) findViewById(R.id.auth2_action_indicator);\r
+        TextView tv = (TextView) findViewById(R.id.oauth2_status_text);\r
+\r
+        if (drawable_id == 0 && text_id == 0) {\r
+            iv.setVisibility(View.INVISIBLE);\r
+            tv.setVisibility(View.INVISIBLE);\r
+        } else {\r
+            iv.setImageResource(drawable_id);\r
+            tv.setText(text_id);\r
+            iv.setVisibility(View.VISIBLE);\r
+            tv.setVisibility(View.VISIBLE);\r
+        }\r
+    }     \r
+    \r
+    // Results from the first call to oAuth2 server : getting the user_code and verification_url.\r
+    @Override\r
+    public void onOAuth2GetCodeResult(ResultOAuthType type, JSONObject responseJson) {\r
+        if ((type == ResultOAuthType.OK_SSL)||(type == ResultOAuthType.OK_NO_SSL)) {\r
+            codeResponseJson = responseJson;\r
+            if (codeResponseJson != null) {\r
+                getOAuth2AccessTokenFromJsonResponse();\r
+            }  // else - nothing to do here - wait for callback !!!\r
+        \r
+        } else if (type == ResultOAuthType.HOST_NOT_AVAILABLE) {\r
+            setOAuth2ResultIconAndText(R.drawable.common_error, R.string.oauth_connection_url_unavailable);\r
+        }\r
+    }\r
+\r
+    // If the results of getting the user_code and verification_url are OK, we get the received data and we start\r
+    // the polling service to oAuth2 server to get a valid token.\r
+    private void getOAuth2AccessTokenFromJsonResponse() {\r
+        String deviceCode = null;\r
+        String verificationUrl = null;\r
+        String userCode = null;\r
+        int expiresIn = -1;\r
+        int interval = -1;\r
+\r
+        Log.d(TAG, "ResponseOAuth2->" + codeResponseJson.toString());\r
+\r
+        try {\r
+            // We get data that we must show to the user or we will use internally.\r
+            verificationUrl = codeResponseJson.getString(OAuth2GetCodeRunnable.CODE_VERIFICATION_URL);\r
+            userCode = codeResponseJson.getString(OAuth2GetCodeRunnable.CODE_USER_CODE);\r
+            expiresIn = codeResponseJson.getInt(OAuth2GetCodeRunnable.CODE_EXPIRES_IN);                \r
+\r
+            // And we get data that we must use to get a token.\r
+            deviceCode = codeResponseJson.getString(OAuth2GetCodeRunnable.CODE_DEVICE_CODE);\r
+            interval = codeResponseJson.getInt(OAuth2GetCodeRunnable.CODE_INTERVAL);\r
+\r
+        } catch (JSONException e) {\r
+            Log.e(TAG, "Exception accesing data in Json object" + e.toString());\r
+        }\r
+\r
+        // Updating status widget to OK.\r
+        setOAuth2ResultIconAndText(R.drawable.ic_ok, R.string.auth_connection_established);\r
+        \r
+        // Showing the dialog with instructions for the user.\r
+        showDialog(OAUTH2_LOGIN_PROGRESS);\r
+\r
+        // Loggin all the data.\r
+        Log.d(TAG, "verificationUrl->" + verificationUrl);\r
+        Log.d(TAG, "userCode->" + userCode);\r
+        Log.d(TAG, "deviceCode->" + deviceCode);\r
+        Log.d(TAG, "expiresIn->" + expiresIn);\r
+        Log.d(TAG, "interval->" + interval);\r
+\r
+        // Starting the pooling service.\r
+        try {\r
+            Intent tokenService = new Intent(this, OAuth2GetTokenService.class);\r
+            tokenService.putExtra(OAuth2GetTokenService.TOKEN_URI, OAuth2Context.OAUTH2_G_DEVICE_GETTOKEN_URL);\r
+            tokenService.putExtra(OAuth2GetTokenService.TOKEN_DEVICE_CODE, deviceCode);\r
+            tokenService.putExtra(OAuth2GetTokenService.TOKEN_INTERVAL, interval);\r
+\r
+            startService(tokenService);\r
+        }\r
+        catch (Exception e) {\r
+            Log.e(TAG, "tokenService creation problem :", e);\r
+        }\r
+        \r
+    }   \r
+    \r
+    private void getOAuth2AccessTokenFromCapturedRedirection() {\r
+        Map<String, String> responseValues = new HashMap<String, String>();\r
+        //String queryParameters = getIntent().getData().getQuery();\r
+        String queryParameters = mNewCapturedUriFromOAuth2Redirection.getQuery();\r
+        mNewCapturedUriFromOAuth2Redirection = null;\r
+        \r
+        Log.v(TAG, "Queryparameters (Code) = " + queryParameters);\r
+\r
+        String[] pairs = queryParameters.split("&");\r
+        Log.v(TAG, "Pairs (Code) = " + pairs.toString());\r
+\r
+        int i = 0;\r
+        String key = "";\r
+        String value = "";\r
+\r
+        StringBuilder sb = new StringBuilder();\r
+\r
+        while (pairs.length > i) {\r
+            int j = 0;\r
+            String[] part = pairs[i].split("=");\r
+\r
+            while (part.length > j) {\r
+                String p = part[j];\r
+                if (j == 0) {\r
+                    key = p;\r
+                    sb.append(key + " = ");\r
+                } else if (j == 1) {\r
+                    value = p;\r
+                    responseValues.put(key, value);\r
+                    sb.append(value + "\n");\r
+                }\r
+\r
+                Log.v(TAG, "[" + i + "," + j + "] = " + p);\r
+                j++;\r
+            }\r
+            i++;\r
+        }\r
+        \r
+        \r
+        // Updating status widget to OK.\r
+        setOAuth2ResultIconAndText(R.drawable.ic_ok, R.string.auth_connection_established);\r
+        \r
+        // Showing the dialog with instructions for the user.\r
+        showDialog(OAUTH2_LOGIN_PROGRESS);\r
+\r
+        // \r
+        RemoteOperation operation = new GetOAuth2AccessToken(responseValues);\r
+        WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(Uri.parse(OAuth2Context.OAUTH2_F_TOKEN_ENDPOINT_URL), getApplicationContext());\r
+        operation.execute(client, this, mHandler);\r
+    }\r
+\r
+    \r
+\r
+    // We get data from the oAuth2 token service with this broadcast receiver.\r
+    private class TokenReceiver extends BroadcastReceiver {\r
+        /**\r
+         * The token is received.\r
+         *  @author\r
+         * {@link BroadcastReceiver} to enable oAuth2 token receiving.\r
+         */\r
+        @Override\r
+        public void onReceive(Context context, Intent intent) {\r
+            @SuppressWarnings("unchecked")\r
+            HashMap<String, String> tokenResponse = (HashMap<String, String>)intent.getExtras().get(OAuth2GetTokenService.TOKEN_RECEIVED_DATA);\r
+            Log.d(TAG, "TokenReceiver->" + tokenResponse.get(OAuth2GetTokenService.TOKEN_ACCESS_TOKEN));\r
+            dismissDialog(OAUTH2_LOGIN_PROGRESS);\r
+\r
+        }\r
+    }\r
 \r
        @Override\r
        public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {\r
-               if (operation.equals(mConnChkRunnable)) {\r
+               if (operation instanceof ConnectionCheckOperation) {\r
                    \r
                mStatusText = mStatusIcon = 0;\r
                mStatusCorrect = false;\r
@@ -592,6 +995,126 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
                else\r
                    findViewById(R.id.refreshButton).setVisibility(View.INVISIBLE);\r
                findViewById(R.id.buttonOK).setEnabled(mStatusCorrect);\r
+               \r
+               } else if (operation instanceof GetOAuth2AccessToken) {\r
+\r
+            try {\r
+                dismissDialog(OAUTH2_LOGIN_PROGRESS);\r
+            } catch (IllegalArgumentException e) {\r
+                // NOTHING TO DO ; can't find out what situation that leads to the exception in this code, but user logs signal that it happens\r
+            }\r
+\r
+                   if (result.isSuccess()) {\r
+                       \r
+                       /// time to test the retrieved access token on the ownCloud server\r
+                       String url = ((TextView) findViewById(R.id.host_URL)).getText()\r
+                               .toString().trim();\r
+                       if (url.endsWith("/"))\r
+                           url = url.substring(0, url.length() - 1);\r
+\r
+                       Uri uri = null;\r
+                       /*String webdav_path = AccountUtils.getWebdavPath(mDiscoveredVersion);\r
+                       \r
+                       if (webdav_path == null) {\r
+                           onAuthenticationResult(false, getString(R.string.auth_bad_oc_version_title));\r
+                           return;\r
+                       }*/\r
+                       \r
+                       String prefix = "";\r
+                       if (mIsSslConn) {\r
+                           prefix = "https://";\r
+                       } else {\r
+                           prefix = "http://";\r
+                       }\r
+                       if (url.toLowerCase().startsWith("http://")\r
+                               || url.toLowerCase().startsWith("https://")) {\r
+                           prefix = "";\r
+                       }\r
+                       \r
+                       try {\r
+                           mBaseUrl = prefix + url;\r
+                           //String url_str = prefix + url + webdav_path;\r
+                           String url_str = prefix + url + "/remote.php/odav";\r
+                           uri = Uri.parse(url_str);\r
+                           \r
+                       } catch (Exception e) {\r
+                           // should never happen\r
+                           onAuthenticationResult(false, getString(R.string.auth_incorrect_address_title));\r
+                           return;\r
+                       }\r
+\r
+                       showDialog(DIALOG_LOGIN_PROGRESS);\r
+                String accessToken = ((GetOAuth2AccessToken)operation).getResultTokenMap().get(OAuth2Context.KEY_ACCESS_TOKEN);\r
+                Log.d(TAG, "Got ACCESS TOKEN: " + accessToken);\r
+                       mAuthChkOperation = new ExistenceCheckOperation("", this, accessToken);\r
+                       WebdavClient client = OwnCloudClientUtils.createOwnCloudClient(uri, getApplicationContext());\r
+                       mAuthChkOperation.execute(client, this, mHandler);\r
+                       \r
+                \r
+            } else {\r
+                TextView tv = (TextView) findViewById(R.id.oAuth_URL);\r
+                tv.setError("A valid authorization could not be obtained");\r
+\r
+            }\r
+                       \r
+               } else if (operation instanceof ExistenceCheckOperation)  {\r
+                       \r
+                   try {\r
+                       dismissDialog(DIALOG_LOGIN_PROGRESS);\r
+                   } catch (IllegalArgumentException e) {\r
+                       // NOTHING TO DO ; can't find out what situation that leads to the exception in this code, but user logs signal that it happens\r
+                   }\r
+                   \r
+                   if (result.isSuccess()) {\r
+                TextView tv = (TextView) findViewById(R.id.oAuth_URL);\r
+                       Log.d(TAG, "Checked access - time to save the account");\r
+                       \r
+                       Uri uri = Uri.parse(mBaseUrl);\r
+                       String username = "OAuth_user" + (new java.util.Random(System.currentTimeMillis())).nextLong(); \r
+                       String accountName = username + "@" + uri.getHost();\r
+                       if (uri.getPort() >= 0) {\r
+                           accountName += ":" + uri.getPort();\r
+                       }\r
+                       // TODO - check that accountName does not exist\r
+                       Account account = new Account(accountName, AccountAuthenticator.ACCOUNT_TYPE);\r
+                       AccountManager accManager = AccountManager.get(this);\r
+                       accManager.addAccountExplicitly(account, "", null);  // with our implementation, the password is never input in the app\r
+\r
+                       // Add this account as default in the preferences, if there is none\r
+                       Account defaultAccount = AccountUtils.getCurrentOwnCloudAccount(this);\r
+                       if (defaultAccount == null) {\r
+                           SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();\r
+                           editor.putString("select_oc_account", accountName);\r
+                       editor.commit();\r
+                       }\r
+\r
+                       /// account data to save by the AccountManager\r
+                       final Intent intent = new Intent();\r
+                       intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, AccountAuthenticator.ACCOUNT_TYPE);\r
+                       intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, account.name);\r
+                       intent.putExtra(AccountManager.KEY_USERDATA, username);\r
+\r
+                accManager.setAuthToken(account, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, ((ExistenceCheckOperation) operation).getAccessToken());\r
+                \r
+                       accManager.setUserData(account, AccountAuthenticator.KEY_OC_VERSION, mConnChkRunnable.getDiscoveredVersion().toString());\r
+                       accManager.setUserData(account, AccountAuthenticator.KEY_OC_BASE_URL, mBaseUrl);\r
+                       accManager.setUserData(account, AccountAuthenticator.KEY_SUPPORTS_OAUTH2, "TRUE");\r
+\r
+                       setAccountAuthenticatorResult(intent.getExtras());\r
+                       setResult(RESULT_OK, intent);\r
+                       \r
+                       /// enforce the first account synchronization\r
+                       Bundle bundle = new Bundle();\r
+                       bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);\r
+                       ContentResolver.requestSync(account, "org.owncloud", bundle);\r
+\r
+                       finish();\r
+                       \r
+                   } else {      \r
+                       TextView tv = (TextView) findViewById(R.id.oAuth_URL);\r
+                       tv.setError(result.getLogMessage());\r
+                Log.d(TAG, "Access failed: " + result.getLogMessage());\r
+                   }\r
                }\r
        }\r
 \r
@@ -604,5 +1127,5 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
     public void onFailedSavingCertificate() {\r
         showDialog(DIALOG_CERT_NOT_SAVED);\r
     }\r
-    \r
+\r
 }\r