|
@@ -1,4 +1,4 @@
|
|
|
-/**
|
|
|
+/*
|
|
|
* ownCloud Android client application
|
|
|
*
|
|
|
* @author Bartek Przybylski
|
|
@@ -53,11 +53,13 @@ import android.graphics.Rect;
|
|
|
import android.graphics.drawable.Drawable;
|
|
|
import android.net.Uri;
|
|
|
import android.net.http.SslError;
|
|
|
+import android.os.Build;
|
|
|
import android.os.Bundle;
|
|
|
import android.os.Handler;
|
|
|
import android.os.IBinder;
|
|
|
import android.preference.PreferenceManager;
|
|
|
import android.support.annotation.Nullable;
|
|
|
+import android.support.design.widget.TextInputLayout;
|
|
|
import android.support.v4.app.DialogFragment;
|
|
|
import android.support.v4.app.Fragment;
|
|
|
import android.support.v4.app.FragmentManager;
|
|
@@ -72,6 +74,8 @@ import android.view.View;
|
|
|
import android.view.View.OnFocusChangeListener;
|
|
|
import android.view.View.OnTouchListener;
|
|
|
import android.view.inputmethod.EditorInfo;
|
|
|
+import android.webkit.CookieManager;
|
|
|
+import android.webkit.CookieSyncManager;
|
|
|
import android.webkit.HttpAuthHandler;
|
|
|
import android.webkit.SslErrorHandler;
|
|
|
import android.webkit.WebView;
|
|
@@ -79,6 +83,7 @@ import android.webkit.WebViewClient;
|
|
|
import android.widget.Button;
|
|
|
import android.widget.CheckBox;
|
|
|
import android.widget.EditText;
|
|
|
+import android.widget.ProgressBar;
|
|
|
import android.widget.TextView;
|
|
|
import android.widget.TextView.OnEditorActionListener;
|
|
|
import android.widget.Toast;
|
|
@@ -117,6 +122,7 @@ import com.owncloud.android.utils.AnalyticsUtils;
|
|
|
import com.owncloud.android.utils.DisplayUtils;
|
|
|
|
|
|
import java.security.cert.X509Certificate;
|
|
|
+import java.util.HashMap;
|
|
|
import java.util.Map;
|
|
|
|
|
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
|
@@ -168,6 +174,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|
|
private static final String KEY_USERNAME = "USERNAME";
|
|
|
private static final String KEY_PASSWORD = "PASSWORD";
|
|
|
private static final String KEY_ASYNC_TASK_IN_PROGRESS = "AUTH_IN_PROGRESS";
|
|
|
+ private static final String WEB_LOGIN = "/index.php/login/flow";
|
|
|
public static final String PROTOCOL_SUFFIX = "://";
|
|
|
public static final String LOGIN_URL_DATA_KEY_VALUE_SEPARATOR = ":";
|
|
|
public static final String HTTPS_PROTOCOL = "https://";
|
|
@@ -233,6 +240,8 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|
|
private boolean webViewLoginMethod;
|
|
|
private String webViewUser;
|
|
|
private String webViewPassword;
|
|
|
+ private TextInputLayout mUsernameInputLayout;
|
|
|
+ private TextInputLayout mPasswordInputLayout;
|
|
|
|
|
|
/**
|
|
|
* {@inheritDoc}
|
|
@@ -244,6 +253,9 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|
|
//Log_OC.e(TAG, "onCreate init");
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
|
|
+ // delete cookies for webView
|
|
|
+ deleteCookies();
|
|
|
+
|
|
|
// Workaround, for fixing a problem with Android Library Suppor v7 19
|
|
|
//getWindow().requestFeature(Window.FEATURE_NO_TITLE);
|
|
|
if (getSupportActionBar() != null) {
|
|
@@ -284,6 +296,9 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|
|
/// initialize general UI elements
|
|
|
initOverallUi();
|
|
|
|
|
|
+ mUsernameInputLayout = (TextInputLayout) findViewById(R.id.input_layout_account_username);
|
|
|
+ mPasswordInputLayout = (TextInputLayout) findViewById(R.id.input_layout_account_password);
|
|
|
+
|
|
|
mOkButton = findViewById(R.id.buttonOK);
|
|
|
mOkButton.setOnClickListener(new View.OnClickListener() {
|
|
|
|
|
@@ -317,17 +332,47 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|
|
} else {
|
|
|
setContentView(R.layout.account_setup_webview);
|
|
|
mLoginWebView = (WebView) findViewById(R.id.login_webview);
|
|
|
- initWebViewLogin();
|
|
|
+ initWebViewLogin(null);
|
|
|
}
|
|
|
|
|
|
initServerPreFragment(savedInstanceState);
|
|
|
}
|
|
|
|
|
|
- private void initWebViewLogin() {
|
|
|
+ private void deleteCookies() {
|
|
|
+ CookieSyncManager.createInstance(this);
|
|
|
+ CookieManager cookieManager = CookieManager.getInstance();
|
|
|
+
|
|
|
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
|
+ cookieManager.removeAllCookies(null);
|
|
|
+ } else {
|
|
|
+ cookieManager.removeAllCookie();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String getWebLoginUserAgent() {
|
|
|
+ return Build.MANUFACTURER.substring(0, 1).toUpperCase() +
|
|
|
+ Build.MANUFACTURER.substring(1).toLowerCase() + " " + Build.MODEL;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void initWebViewLogin(String baseURL) {
|
|
|
+ mLoginWebView.setVisibility(View.GONE);
|
|
|
+
|
|
|
+ final ProgressBar progressBar = (ProgressBar) findViewById(R.id.login_webview_progress_bar);
|
|
|
+
|
|
|
mLoginWebView.getSettings().setAllowFileAccess(false);
|
|
|
mLoginWebView.getSettings().setJavaScriptEnabled(true);
|
|
|
- mLoginWebView.getSettings().setUserAgentString(MainApp.getUserAgent());
|
|
|
- mLoginWebView.loadUrl(getResources().getString(R.string.webview_login_url));
|
|
|
+ mLoginWebView.getSettings().setUserAgentString(getWebLoginUserAgent());
|
|
|
+ mLoginWebView.getSettings().setSaveFormData(false);
|
|
|
+ mLoginWebView.getSettings().setSavePassword(false);
|
|
|
+
|
|
|
+ if (baseURL != null && !baseURL.isEmpty()){
|
|
|
+ Map<String, String> headers = new HashMap<>();
|
|
|
+ headers.put(RemoteOperation.OCS_API_HEADER, RemoteOperation.OCS_API_HEADER_VALUE);
|
|
|
+ mLoginWebView.loadUrl(baseURL + WEB_LOGIN, headers);
|
|
|
+ } else {
|
|
|
+ mLoginWebView.loadUrl(getResources().getString(R.string.webview_login_url));
|
|
|
+ }
|
|
|
+
|
|
|
mLoginWebView.setWebViewClient(new WebViewClient() {
|
|
|
@Override
|
|
|
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
|
@@ -338,8 +383,17 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
|
|
|
+ @Override
|
|
|
+ public void onPageFinished(WebView view, String url) {
|
|
|
+ super.onPageFinished(view, url);
|
|
|
|
|
|
+ progressBar.setVisibility(View.GONE);
|
|
|
+ mLoginWebView.setVisibility(View.VISIBLE);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
|
|
|
+ progressBar.setVisibility(View.GONE);
|
|
|
+ mLoginWebView.setVisibility(View.VISIBLE);
|
|
|
mLoginWebView.loadData(DisplayUtils.getData(getResources().openRawResource(R.raw.custom_error)),"text/html; charset=UTF-8", null);
|
|
|
}
|
|
|
});
|
|
@@ -483,6 +537,10 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public void onTestServerConnectionClick(View v) {
|
|
|
+ checkOcServer();
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* @param savedInstanceState Saved activity state, as in {{@link #onCreate(Bundle)}
|
|
@@ -987,10 +1045,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|
|
|
|
|
Intent getServerInfoIntent = new Intent();
|
|
|
getServerInfoIntent.setAction(OperationsService.ACTION_GET_SERVER_INFO);
|
|
|
- getServerInfoIntent.putExtra(
|
|
|
- OperationsService.EXTRA_SERVER_URL,
|
|
|
- normalizeUrlSuffix(uri)
|
|
|
- );
|
|
|
+ getServerInfoIntent.putExtra(OperationsService.EXTRA_SERVER_URL, normalizeUrlSuffix(uri));
|
|
|
|
|
|
if (mOperationsServiceBinder != null) {
|
|
|
mWaitingForOpId = mOperationsServiceBinder.queueNewOperation(getServerInfoIntent);
|
|
@@ -1283,8 +1338,25 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|
|
// 4. we got the authentication method required by the server
|
|
|
mServerInfo = (GetServerInfoOperation.ServerInfo) (result.getData().get(0));
|
|
|
|
|
|
- if (webViewLoginMethod) {
|
|
|
+ webViewLoginMethod = mServerInfo.mVersion.isWebLoginSupported();
|
|
|
+
|
|
|
+ if (webViewUser != null && !webViewUser.isEmpty() &&
|
|
|
+ webViewPassword != null && !webViewPassword.isEmpty()) {
|
|
|
checkBasicAuthorization(webViewUser, webViewPassword);
|
|
|
+ } else if (webViewLoginMethod) {
|
|
|
+ // hide old login
|
|
|
+ mOkButton.setVisibility(View.GONE);
|
|
|
+ mUsernameInputLayout.setVisibility(View.GONE);
|
|
|
+ mPasswordInputLayout.setVisibility(View.GONE);
|
|
|
+
|
|
|
+ setContentView(R.layout.account_setup_webview);
|
|
|
+ mLoginWebView = (WebView) findViewById(R.id.login_webview);
|
|
|
+ initWebViewLogin(mServerInfo.mBaseUrl);
|
|
|
+ } else {
|
|
|
+ // show old login
|
|
|
+ mOkButton.setVisibility(View.VISIBLE);
|
|
|
+ mUsernameInputLayout.setVisibility(View.VISIBLE);
|
|
|
+ mPasswordInputLayout.setVisibility(View.VISIBLE);
|
|
|
}
|
|
|
|
|
|
if (!authSupported(mServerInfo.mAuthMethod)) {
|
|
@@ -1310,6 +1382,14 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|
|
mOkButton.setEnabled(mServerIsValid);
|
|
|
}
|
|
|
|
|
|
+ if (!mServerIsValid) {
|
|
|
+ // hide old login
|
|
|
+ mOkButton.setVisibility(View.GONE);
|
|
|
+ mUsernameInputLayout.setVisibility(View.GONE);
|
|
|
+ mPasswordInputLayout.setVisibility(View.GONE);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
/// very special case (TODO: move to a common place for all the remote operations)
|
|
|
if (result.getCode() == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED) {
|
|
|
showUntrustedCertDialog(result);
|
|
@@ -1623,8 +1703,26 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // Reset webView
|
|
|
+ webViewPassword = null;
|
|
|
+ webViewUser = null;
|
|
|
+ deleteCookies();
|
|
|
+
|
|
|
if (success) {
|
|
|
finish();
|
|
|
+ } else {
|
|
|
+ // init webView again
|
|
|
+ mLoginWebView.setVisibility(View.GONE);
|
|
|
+ setContentView(R.layout.account_setup);
|
|
|
+
|
|
|
+ CustomEditText serverAddressField = (CustomEditText) findViewById(R.id.hostUrlInput);
|
|
|
+ serverAddressField.setText(mServerInfo.mBaseUrl);
|
|
|
+
|
|
|
+ findViewById(R.id.oauth_onOff_check).setVisibility(View.GONE);
|
|
|
+ findViewById(R.id.server_status_text).setVisibility(View.GONE);
|
|
|
+ mAuthStatusView = (TextView) findViewById(R.id.auth_status_text);
|
|
|
+
|
|
|
+ showAuthStatus();
|
|
|
}
|
|
|
|
|
|
} else if (result.isServerFail() || result.isException()) {
|
|
@@ -1751,10 +1849,10 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|
|
if (AccountUtils.exists(newAccount, getApplicationContext())) {
|
|
|
// fail - not a new account, but an existing one; disallow
|
|
|
RemoteOperationResult result = new RemoteOperationResult(ResultCode.ACCOUNT_NOT_NEW);
|
|
|
- if (!webViewLoginMethod) {
|
|
|
- updateAuthStatusIconAndText(result);
|
|
|
- showAuthStatus();
|
|
|
- }
|
|
|
+
|
|
|
+ updateAuthStatusIconAndText(result);
|
|
|
+ showAuthStatus();
|
|
|
+
|
|
|
Log_OC.d(TAG, result.getLogMessage());
|
|
|
return false;
|
|
|
|
|
@@ -1856,15 +1954,12 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|
|
* to the last check on the ownCloud server.
|
|
|
*/
|
|
|
private void showServerStatus() {
|
|
|
- if (!webViewLoginMethod) {
|
|
|
- if (mServerStatusIcon == 0 && mServerStatusText == 0) {
|
|
|
- mServerStatusView.setVisibility(View.INVISIBLE);
|
|
|
-
|
|
|
- } else {
|
|
|
- mServerStatusView.setText(mServerStatusText);
|
|
|
- mServerStatusView.setCompoundDrawablesWithIntrinsicBounds(mServerStatusIcon, 0, 0, 0);
|
|
|
- mServerStatusView.setVisibility(View.VISIBLE);
|
|
|
- }
|
|
|
+ if (mServerStatusIcon == 0 && mServerStatusText == 0) {
|
|
|
+ mServerStatusView.setVisibility(View.INVISIBLE);
|
|
|
+ } else {
|
|
|
+ mServerStatusView.setText(mServerStatusText);
|
|
|
+ mServerStatusView.setCompoundDrawablesWithIntrinsicBounds(mServerStatusIcon, 0, 0, 0);
|
|
|
+ mServerStatusView.setVisibility(View.VISIBLE);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1874,15 +1969,12 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|
|
* to the interactions with the OAuth authorization server.
|
|
|
*/
|
|
|
private void showAuthStatus() {
|
|
|
- if (!webViewLoginMethod) {
|
|
|
- if (mAuthStatusIcon == 0 && mAuthStatusText == 0) {
|
|
|
- mAuthStatusView.setVisibility(View.INVISIBLE);
|
|
|
-
|
|
|
- } else {
|
|
|
- mAuthStatusView.setText(mAuthStatusText);
|
|
|
- mAuthStatusView.setCompoundDrawablesWithIntrinsicBounds(mAuthStatusIcon, 0, 0, 0);
|
|
|
- mAuthStatusView.setVisibility(View.VISIBLE);
|
|
|
- }
|
|
|
+ if (mAuthStatusIcon == 0 && mAuthStatusText == 0) {
|
|
|
+ mAuthStatusView.setVisibility(View.INVISIBLE);
|
|
|
+ } else {
|
|
|
+ mAuthStatusView.setText(mAuthStatusText);
|
|
|
+ mAuthStatusView.setCompoundDrawablesWithIntrinsicBounds(mAuthStatusIcon, 0, 0, 0);
|
|
|
+ mAuthStatusView.setVisibility(View.VISIBLE);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -2154,7 +2246,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
|
|
|
/**
|
|
|
* Create and show dialog for request authentication to the user
|
|
|
*
|
|
|
- * @param webView Web view to emebd into the authentication dialog.
|
|
|
+ * @param webView Web view to embed into the authentication dialog.
|
|
|
* @param handler Object responsible for catching and recovering HTTP authentication fails.
|
|
|
*/
|
|
|
public void createAuthenticationDialog(WebView webView, HttpAuthHandler handler) {
|