4343import android .webkit .WebResourceRequest ;
4444import android .webkit .WebResourceResponse ;
4545import android .webkit .WebView ;
46- import android .widget .LinearLayout ;
4746import android .widget .TextView ;
4847import android .widget .TextView .OnEditorActionListener ;
4948import android .widget .Toast ;
5049
5150import com .blikoon .qrcodescanner .QrCodeActivity ;
52- import com .google .android .material .button .MaterialButton ;
5351import com .google .android .material .snackbar .Snackbar ;
54- import com .google .gson .JsonObject ;
55- import com .google .gson .JsonParser ;
5652import com .nextcloud .android .common .ui .color .ColorUtil ;
5753import com .nextcloud .android .common .ui .theme .utils .ColorRole ;
5854import com .nextcloud .client .account .User ;
5955import com .nextcloud .client .account .UserAccountManager ;
6056import com .nextcloud .client .device .DeviceInfo ;
6157import com .nextcloud .client .di .Injectable ;
62- import com .nextcloud .client .network .ClientFactory ;
6358import com .nextcloud .client .onboarding .FirstRunActivity ;
6459import com .nextcloud .client .onboarding .OnboardingService ;
6560import com .nextcloud .client .preferences .AppPreferences ;
66- import com .nextcloud .common .PlainClient ;
67- import com .nextcloud .operations .PostMethod ;
6861import com .nextcloud .utils .extensions .BundleExtensionsKt ;
6962import com .owncloud .android .MainApp ;
7063import com .owncloud .android .R ;
111104import com .owncloud .android .utils .theme .CapabilityUtils ;
112105import com .owncloud .android .utils .theme .ViewThemeUtils ;
113106
114- import org .json .JSONObject ;
115-
116107import java .io .InputStream ;
117108import java .net .URLDecoder ;
118109import java .util .HashMap ;
119110import java .util .Locale ;
120111import java .util .Map ;
121112import java .util .Optional ;
122113import java .util .concurrent .Executors ;
123- import java .util .concurrent .ScheduledExecutorService ;
124- import java .util .concurrent .TimeUnit ;
125114
126115import javax .inject .Inject ;
127116
137126import androidx .fragment .app .Fragment ;
138127import androidx .fragment .app .FragmentManager ;
139128import androidx .fragment .app .FragmentTransaction ;
140- import androidx .lifecycle .Lifecycle ;
141- import androidx .lifecycle .LifecycleEventObserver ;
142- import androidx .lifecycle .ProcessLifecycleOwner ;
143129import de .cotech .hw .fido .WebViewFidoBridge ;
144130import de .cotech .hw .fido .ui .FidoDialogOptions ;
145131import de .cotech .hw .fido2 .WebViewWebauthnBridge ;
146132import de .cotech .hw .fido2 .ui .WebauthnDialogOptions ;
147133import edu .umd .cs .findbugs .annotations .SuppressFBWarnings ;
148- import okhttp3 .FormBody ;
149- import okhttp3 .RequestBody ;
150134
151135import static com .owncloud .android .utils .PermissionUtil .PERMISSIONS_CAMERA ;
152136
@@ -184,17 +168,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
184168 private static final String KEY_USERNAME = "USERNAME" ;
185169 private static final String KEY_PASSWORD = "PASSWORD" ;
186170 private static final String KEY_ASYNC_TASK_IN_PROGRESS = "AUTH_IN_PROGRESS" ;
187-
188- /**
189- * Login Flow v1
190- */
191- // public static final String WEB_LOGIN = "/index.php/login/flow";
192-
193- /**
194- * Login Flow v2
195- */
196- public static final String WEB_LOGIN = "/index.php/login/v2" ;
197-
171+ public static final String WEB_LOGIN = "/index.php/login/flow" ;
198172 public static final String PROTOCOL_SUFFIX = "://" ;
199173 public static final String LOGIN_URL_DATA_KEY_VALUE_SEPARATOR = ":" ;
200174 public static final String HTTPS_PROTOCOL = "https://" ;
@@ -248,9 +222,6 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
248222 @ Inject PassCodeManager passCodeManager ;
249223 @ Inject ViewThemeUtils .Factory viewThemeUtilsFactory ;
250224 @ Inject ColorUtil colorUtil ;
251- @ Inject ClientFactory clientFactory ;
252-
253- private String token ;
254225
255226 private boolean onlyAdd = false ;
256227 @ SuppressLint ("ResourceAsColor" ) @ ColorInt
@@ -275,7 +246,7 @@ protected void onCreate(Bundle savedInstanceState) {
275246 viewThemeUtils = viewThemeUtilsFactory .withPrimaryAsBackground ();
276247 viewThemeUtils .platform .themeStatusBar (this , ColorRole .PRIMARY );
277248
278- // WebViewUtil webViewUtil = new WebViewUtil(this);
249+ WebViewUtil webViewUtil = new WebViewUtil (this );
279250
280251 Uri data = getIntent ().getData ();
281252 boolean directLogin = data != null && data .toString ().startsWith (getString (R .string .login_data_own_scheme ));
@@ -340,8 +311,7 @@ protected void onCreate(Bundle savedInstanceState) {
340311 if (webViewLoginMethod ) {
341312 accountSetupWebviewBinding = AccountSetupWebviewBinding .inflate (getLayoutInflater ());
342313 setContentView (accountSetupWebviewBinding .getRoot ());
343- anonymouslyPostLoginRequest (webloginUrl );
344- // initWebViewLogin(webloginUrl, false);
314+ initWebViewLogin (webloginUrl , false );
345315 } else {
346316 accountSetupBinding = AccountSetupBinding .inflate (getLayoutInflater ());
347317 setContentView (accountSetupBinding .getRoot ());
@@ -356,18 +326,10 @@ protected void onCreate(Bundle savedInstanceState) {
356326 }
357327
358328 initServerPreFragment (savedInstanceState );
359- ProcessLifecycleOwner .get ().getLifecycle ().addObserver (lifecycleEventObserver );
360329
361- // webViewUtil.checkWebViewVersion();
330+ webViewUtil .checkWebViewVersion ();
362331 }
363332
364- private final LifecycleEventObserver lifecycleEventObserver = ((lifecycleOwner , event ) -> {
365- if (event == Lifecycle .Event .ON_START && token != null ) {
366- Log_OC .d (TAG , "Start poolLogin" );
367- poolLogin ();
368- }
369- });
370-
371333 private void deleteCookies () {
372334 try {
373335 CookieSyncManager .createInstance (this );
@@ -377,72 +339,11 @@ private void deleteCookies() {
377339 }
378340 }
379341
380- private String baseUrl ;
381-
382- /**
383- * This function facilitates the login process by anonymously posting a login request to a specified URL.
384- * After posting the request, it retrieves the login URL for completing the login flow.
385- * The login flow version used is v2.
386- *
387- * @param url The URL where the login request is to be anonymously posted.
388- * This URL should handle the login request and return the login URL.
389- * It's typically the entry point for the login process.
390- * Example: "<a href="https://example.com/index.php/login/v2">...</a>"
391- */
392- private void anonymouslyPostLoginRequest (String url ) {
393- baseUrl = url ;
394-
395- Thread thread = new Thread (() -> {
396- String response = getResponseOfAnonymouslyPostLoginRequest ();
397-
398- try {
399- JsonObject jsonObject = JsonParser .parseString (response ).getAsJsonObject ();
400- String loginUrl = getLoginUrl (jsonObject );
401- runOnUiThread (() -> {
402- initLoginInfoView ();
403- launchDefaultWebBrowser (loginUrl );
404- });
405- token = jsonObject .getAsJsonObject ("poll" ).get ("token" ).getAsString ();
406- } catch (Throwable t ) {
407- Log_OC .d (TAG , "Error caught at anonymouslyPostLoginRequest: " + t );
408- DisplayUtils .showSnackMessage (this , R .string .authenticator_activity_login_error );
409- }
410- });
411-
412- thread .start ();
413- }
414-
415- private String getResponseOfAnonymouslyPostLoginRequest () {
416- PostMethod post = new PostMethod (baseUrl , false , new FormBody .Builder ().build ());
417- PlainClient client = clientFactory .createPlainClient ();
418- post .execute (client );
419- return post .getResponseBodyAsString ();
420- }
421-
422- private String getLoginUrl (JsonObject response ) {
423- String result = response .get ("login" ).getAsString ();
424- if (result == null ) {
425- result = getResources ().getString (R .string .webview_login_url );
426- }
427-
428- return result ;
429- }
430-
431- private void launchDefaultWebBrowser (String url ) {
432- Intent intent = new Intent (Intent .ACTION_VIEW , Uri .parse (url ));
433- intent .setFlags (Intent .FLAG_ACTIVITY_NEW_TASK );
434- startActivity (intent );
435- }
436-
437342 private static String getWebLoginUserAgent () {
438343 return Build .MANUFACTURER .substring (0 , 1 ).toUpperCase (Locale .getDefault ()) +
439344 Build .MANUFACTURER .substring (1 ).toLowerCase (Locale .getDefault ()) + " " + Build .MODEL + " (Android)" ;
440345 }
441346
442- /**
443- * @Deprecated This function is deprecated. Please use the {@link #anonymouslyPostLoginRequest(String)} method instead, which utilizes the improved login flow v2.
444- */
445- @ Deprecated
446347 @ SuppressFBWarnings ("ANDROID_WEB_VIEW_JAVASCRIPT" )
447348 @ SuppressLint ("SetJavaScriptEnabled" )
448349 private void initWebViewLogin (String baseURL , boolean useGenericUserAgent ) {
@@ -802,8 +703,7 @@ protected void onNewIntent(Intent intent) {
802703 if (intent .getBooleanExtra (EXTRA_USE_PROVIDER_AS_WEBLOGIN , false )) {
803704 accountSetupWebviewBinding = AccountSetupWebviewBinding .inflate (getLayoutInflater ());
804705 setContentView (accountSetupWebviewBinding .getRoot ());
805- anonymouslyPostLoginRequest (getString (R .string .provider_registration_server ));
806- // initWebViewLogin(getString(R.string.provider_registration_server), true);
706+ initWebViewLogin (getString (R .string .provider_registration_server ), true );
807707 }
808708 }
809709
@@ -1040,16 +940,7 @@ private void onGetServerInfoFinish(RemoteOperationResult result) {
1040940
1041941 accountSetupWebviewBinding = AccountSetupWebviewBinding .inflate (getLayoutInflater ());
1042942 setContentView (accountSetupWebviewBinding .getRoot ());
1043-
1044- if (!isLoginProcessCompleted ) {
1045- if (!isRedirectedToTheDefaultBrowser ) {
1046- anonymouslyPostLoginRequest (mServerInfo .mBaseUrl + WEB_LOGIN );
1047- isRedirectedToTheDefaultBrowser = true ;
1048- } else {
1049- initLoginInfoView ();
1050- }
1051- // initWebViewLogin(mServerInfo.mBaseUrl + WEB_LOGIN, false);
1052- }
943+ initWebViewLogin (mServerInfo .mBaseUrl + WEB_LOGIN , false );
1053944 }
1054945 } else {
1055946 updateServerStatusIconAndText (result );
@@ -1062,20 +953,6 @@ private void onGetServerInfoFinish(RemoteOperationResult result) {
1062953 }
1063954 }
1064955
1065- // region LoginInfoView
1066- private void initLoginInfoView () {
1067- LinearLayout loginFlowLayout = accountSetupWebviewBinding .loginFlowV2 .getRoot ();
1068- MaterialButton cancelButton = accountSetupWebviewBinding .loginFlowV2 .cancelButton ;
1069- loginFlowLayout .setVisibility (View .VISIBLE );
1070-
1071- cancelButton .setOnClickListener (v -> {
1072- loginFlowExecutorService .shutdown ();
1073- ProcessLifecycleOwner .get ().getLifecycle ().removeObserver (lifecycleEventObserver );
1074- recreate ();
1075- });
1076- }
1077- // endregion
1078-
1079956 /**
1080957 * Chooses the right icon and text to show to the user for the received operation result.
1081958 *
@@ -1317,8 +1194,7 @@ public void onAuthenticatorTaskCallback(RemoteOperationResult<UserInfo> result)
13171194
13181195 } else { // authorization fail due to client side - probably wrong credentials
13191196 if (accountSetupWebviewBinding != null ) {
1320- anonymouslyPostLoginRequest (mServerInfo .mBaseUrl + WEB_LOGIN );
1321- // initWebViewLogin(mServerInfo.mBaseUrl + WEB_LOGIN, false);
1197+ initWebViewLogin (mServerInfo .mBaseUrl + WEB_LOGIN , false );
13221198 DisplayUtils .showSnackMessage (this ,
13231199 accountSetupWebviewBinding .loginWebview , R .string .auth_access_failed ,
13241200 result .getLogMessage ());
@@ -1662,71 +1538,6 @@ public void onServiceDisconnected(ComponentName component) {
16621538 }
16631539 }
16641540
1665- private final ScheduledExecutorService loginFlowExecutorService = Executors .newSingleThreadScheduledExecutor ();
1666- private boolean isLoginProcessCompleted = false ;
1667- private boolean isRedirectedToTheDefaultBrowser = false ;
1668-
1669- private void poolLogin () {
1670- loginFlowExecutorService .scheduleWithFixedDelay (() -> {
1671- if (!isLoginProcessCompleted ) {
1672- performLoginFlowV2 ();
1673- }
1674- }, 0 , 30 , TimeUnit .SECONDS );
1675- }
1676-
1677- private void performLoginFlowV2 () {
1678- String postRequestUrl = baseUrl + "/poll" ;
1679-
1680- RequestBody requestBody = new FormBody .Builder ()
1681- .add ("token" , token )
1682- .build ();
1683-
1684- PlainClient client = clientFactory .createPlainClient ();
1685- PostMethod post = new PostMethod (postRequestUrl , false , requestBody );
1686- int status = post .execute (client );
1687- String response = post .getResponseBodyAsString ();
1688-
1689- Log_OC .d (TAG , "performLoginFlowV2 status: " + status );
1690- Log_OC .d (TAG , "performLoginFlowV2 response: " + response );
1691-
1692- if (!response .isEmpty ()) {
1693- runOnUiThread (() -> completeLoginFlow (response , status ));
1694- }
1695- }
1696-
1697- private void completeLoginFlow (String response , int status ) {
1698- try {
1699- JSONObject jsonObject = new JSONObject (response );
1700-
1701- String server = jsonObject .getString ("server" );
1702- String loginName = jsonObject .getString ("loginName" );
1703- String appPassword = jsonObject .getString ("appPassword" );
1704-
1705- LoginUrlInfo loginUrlInfo = new LoginUrlInfo ();
1706- loginUrlInfo .serverAddress = server ;
1707- loginUrlInfo .username = loginName ;
1708- loginUrlInfo .password = appPassword ;
1709-
1710- isLoginProcessCompleted = (status == 200 && !server .isEmpty () && !loginName .isEmpty () && !appPassword .isEmpty ());
1711-
1712- if (accountSetupBinding != null ) {
1713- accountSetupBinding .hostUrlInput .setText ("" );
1714- }
1715- mServerInfo .mBaseUrl = AuthenticatorUrlUtils .INSTANCE .normalizeUrlSuffix (loginUrlInfo .serverAddress );
1716- webViewUser = loginUrlInfo .username ;
1717- webViewPassword = loginUrlInfo .password ;
1718- } catch (Exception e ) {
1719- Log_OC .d (TAG , "Error caught at completeLoginFlow: " + e );
1720- mServerStatusIcon = R .drawable .ic_alert ;
1721- mServerStatusText = getString (R .string .qr_could_not_be_read );
1722- showServerStatus ();
1723- }
1724-
1725- checkOcServer ();
1726- loginFlowExecutorService .shutdown ();
1727- ProcessLifecycleOwner .get ().getLifecycle ().removeObserver (lifecycleEventObserver );
1728- }
1729-
17301541 /**
17311542 * Called from SslValidatorDialog when a new server certificate was correctly saved.
17321543 */
0 commit comments