Refresh authorization token on failed synchronizations when notification error is...
authorDavid A. Velasco <dvelasco@solidgear.es>
Mon, 18 Mar 2013 13:05:34 +0000 (14:05 +0100)
committerDavid A. Velasco <dvelasco@solidgear.es>
Mon, 18 Mar 2013 13:05:34 +0000 (14:05 +0100)
res/values/oauth.xml
res/values/strings.xml
src/com/owncloud/android/operations/RemoteOperation.java
src/com/owncloud/android/syncadapter/FileSyncAdapter.java
src/com/owncloud/android/ui/activity/AuthenticatorActivity.java

index b12b648..66bb225 100644 (file)
@@ -1,5 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-    <string name="oauth_url_endpoint_auth">https://frko.surfnetlabs.nl/workshop/php-oauth/authorize.php</string>
-    <string name="oauth_url_endpoint_access">https://frko.surfnetlabs.nl/workshop/php-oauth/token.php</string>
+    <!-- string name="oauth_url_endpoint_auth">https://frko.surfnetlabs.nl/workshop/php-oauth/authorize.php</string>
+    <string name="oauth_url_endpoint_access">https://frko.surfnetlabs.nl/workshop/php-oauth/token.php</string -->
+    <string name="oauth_url_endpoint_auth">http://owncloud.tuxed.net/oauth/php-oauth/authorize.php</string>
+    <string name="oauth_url_endpoint_access">http://owncloud.tuxed.net/oauth/php-oauth/token.php</string>
 </resources>
index bc35032..21938f0 100644 (file)
     <string name="sync_string_contacts">Contacts</string>
        <string name="sync_fail_ticker">Synchronization failed</string>
     <string name="sync_fail_content">Synchronization of %1$s could not be completed</string>
+    <string name="sync_fail_content_unauthorized">Invalid credentials for %1$s</string>
        <string name="sync_conflicts_in_favourites_ticker">Conflicts found</string>
        <string name="sync_conflicts_in_favourites_content">%1$d kept-in-sync files could not be sync\'ed</string>
     <string name="sync_fail_in_favourites_ticker">Kept-in-sync files failed</string>
index bf635a8..06a70f7 100644 (file)
@@ -244,6 +244,7 @@ public abstract class RemoteOperation implements Runnable {
         
             repeat = false;
             if (mCallerActivity != null && mAccount != null && mContext != null && !result.isSuccess() && result.getCode() == ResultCode.UNAUTHORIZED) {
+                /// fail due to lack of authorization in an operation performed in foreground
                 AccountManager am = AccountManager.get(mContext);
                 Credentials cred = mClient.getCredentials();
                 if (cred instanceof BearerCredentials) {
@@ -252,7 +253,7 @@ public abstract class RemoteOperation implements Runnable {
                     am.clearPassword(mAccount);
                 }
                 mClient = null;
-                repeat = true;
+                repeat = true;  // when repeated, the creation of a new OwnCloudClient after erasing the saved credentials will trigger the login activity
                 result = null;
             }
         } while (repeat);
index 46c088b..4eafeac 100644 (file)
@@ -19,7 +19,6 @@
 package com.owncloud.android.syncadapter;\r
 \r
 import java.io.IOException;\r
-import java.net.UnknownHostException;\r
 import java.util.ArrayList;\r
 import java.util.HashMap;\r
 import java.util.List;\r
@@ -35,11 +34,11 @@ import com.owncloud.android.operations.RemoteOperationResult;
 import com.owncloud.android.operations.SynchronizeFolderOperation;\r
 import com.owncloud.android.operations.UpdateOCVersionOperation;\r
 import com.owncloud.android.operations.RemoteOperationResult.ResultCode;\r
+import com.owncloud.android.ui.activity.AuthenticatorActivity;\r
 import com.owncloud.android.ui.activity.ErrorsWhileCopyingHandlerActivity;\r
+\r
 import android.accounts.Account;\r
 import android.accounts.AccountsException;\r
-import android.accounts.AuthenticatorException;\r
-import android.accounts.OperationCanceledException;\r
 import android.app.Notification;\r
 import android.app.NotificationManager;\r
 import android.app.PendingIntent;\r
@@ -249,6 +248,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
             RemoteOperationResult.ResultCode code = failedResult.getCode();\r
             return (code.equals(RemoteOperationResult.ResultCode.SSL_ERROR) ||\r
                     code.equals(RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) ||\r
+                    code.equals(RemoteOperationResult.ResultCode.UNAUTHORIZED) ||\r
                     code.equals(RemoteOperationResult.ResultCode.BAD_OC_VERSION) ||\r
                     code.equals(RemoteOperationResult.ResultCode.INSTANCE_NOT_CONFIGURED));\r
         }\r
@@ -299,12 +299,29 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
     private void notifyFailedSynchronization() {\r
         Notification notification = new Notification(R.drawable.icon, getContext().getString(R.string.sync_fail_ticker), System.currentTimeMillis());\r
         notification.flags |= Notification.FLAG_AUTO_CANCEL;\r
-        // TODO put something smart in the contentIntent below\r
+        boolean needsToUpdateCredentials = (mLastFailedResult != null && mLastFailedResult.getCode() == ResultCode.UNAUTHORIZED);\r
+        // TODO put something smart in the contentIntent below for all the possible errors\r
         notification.contentIntent = PendingIntent.getActivity(getContext().getApplicationContext(), (int)System.currentTimeMillis(), new Intent(), 0);\r
-        notification.setLatestEventInfo(getContext().getApplicationContext(), \r
-                                        getContext().getString(R.string.sync_fail_ticker), \r
-                                        String.format(getContext().getString(R.string.sync_fail_content), getAccount().name), \r
-                                        notification.contentIntent);\r
+        if (needsToUpdateCredentials) {\r
+            // let the user update credentials with one click\r
+            Intent updateAccountCredentials = new Intent(getContext(), AuthenticatorActivity.class);\r
+            updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, getAccount());\r
+            updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACTION, AuthenticatorActivity.ACTION_UPDATE_TOKEN);\r
+            updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);\r
+            updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);\r
+            updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND);\r
+            notification.contentIntent = PendingIntent.getActivity(getContext(), (int)System.currentTimeMillis(), updateAccountCredentials, PendingIntent.FLAG_ONE_SHOT);\r
+            notification.setLatestEventInfo(getContext().getApplicationContext(), \r
+                    getContext().getString(R.string.sync_fail_ticker), \r
+                    String.format(getContext().getString(R.string.sync_fail_content_unauthorized), getAccount().name), \r
+                    notification.contentIntent);\r
+            Log.e(TAG, "NEEDS TO UPDATE CREDENTIALS");\r
+        } else {\r
+            notification.setLatestEventInfo(getContext().getApplicationContext(), \r
+                    getContext().getString(R.string.sync_fail_ticker), \r
+                    String.format(getContext().getString(R.string.sync_fail_content), getAccount().name), \r
+                    notification.contentIntent);\r
+        }\r
         ((NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE)).notify(R.string.sync_fail_ticker, notification);\r
     }\r
 \r
index 8c8798c..8dce3bc 100644 (file)
@@ -186,8 +186,6 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             /// retrieve extras from intent\r
             String tokenType = getIntent().getExtras().getString(AccountAuthenticator.KEY_AUTH_TOKEN_TYPE);\r
             boolean oAuthRequired = AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN.equals(tokenType);\r
-            mOAuth2Check.setChecked(oAuthRequired);\r
-            changeViewByOAuth2Check(oAuthRequired);\r
             \r
             mAccount = getIntent().getExtras().getParcelable(EXTRA_ACCOUNT);\r
             if (mAccount != null) {\r
@@ -199,7 +197,11 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
                 mHostUrlInput.setText(mHostBaseUrl);\r
                 String userName = mAccount.name.substring(0, mAccount.name.lastIndexOf('@'));\r
                 mUsernameInput.setText(userName);\r
+                oAuthRequired = (mAccountMgr.getUserData(mAccount, AccountAuthenticator.KEY_SUPPORTS_OAUTH2) != null);\r
             }\r
+            mOAuth2Check.setChecked(oAuthRequired);\r
+            changeViewByOAuth2Check(oAuthRequired);\r
+            \r
 \r
         } else {\r
             loadSavedInstanceState(savedInstanceState);\r
@@ -826,11 +828,10 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
         boolean isOAuth = mOAuth2Check.isChecked();\r
         if (isOAuth) {\r
             response.putString(AccountManager.KEY_AUTHTOKEN, mOAuthAccessToken);\r
-            // the next line is unnecessary; the AccountManager does it when receives the response Bundle\r
-            // mAccountMgr.setAuthToken(mAccount, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, mOAuthAccessToken);\r
+            // the next line is necessary; by now, notifications are calling directly to the AuthenticatorActivity to update, without AccountManager intervention\r
+            mAccountMgr.setAuthToken(mAccount, AccountAuthenticator.AUTH_TOKEN_TYPE_ACCESS_TOKEN, mOAuthAccessToken);\r
         } else {\r
             response.putString(AccountManager.KEY_AUTHTOKEN, mPasswordInput.getText().toString());\r
-            // the next line is not really necessary, because we are using the password as if it was an auth token; but let's keep it there by now\r
             mAccountMgr.setPassword(mAccount, mPasswordInput.getText().toString());\r
         }\r
         setAccountAuthenticatorResult(response);\r