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 ));
@@ -344,8 +315,7 @@ protected void onCreate(Bundle savedInstanceState) {
344315 if (webViewLoginMethod ) {
345316 accountSetupWebviewBinding = AccountSetupWebviewBinding .inflate (getLayoutInflater ());
346317 setContentView (accountSetupWebviewBinding .getRoot ());
347- anonymouslyPostLoginRequest (webloginUrl );
348- // initWebViewLogin(webloginUrl, false);
318+ initWebViewLogin (webloginUrl , false );
349319 } else {
350320 accountSetupBinding = AccountSetupBinding .inflate (getLayoutInflater ());
351321 setContentView (accountSetupBinding .getRoot ());
@@ -360,18 +330,10 @@ protected void onCreate(Bundle savedInstanceState) {
360330 }
361331
362332 initServerPreFragment (savedInstanceState );
363- ProcessLifecycleOwner .get ().getLifecycle ().addObserver (lifecycleEventObserver );
364333
365- // webViewUtil.checkWebViewVersion();
334+ webViewUtil .checkWebViewVersion ();
366335 }
367336
368- private final LifecycleEventObserver lifecycleEventObserver = ((lifecycleOwner , event ) -> {
369- if (event == Lifecycle .Event .ON_START && token != null ) {
370- Log_OC .d (TAG , "Start poolLogin" );
371- poolLogin ();
372- }
373- });
374-
375337 private void deleteCookies () {
376338 try {
377339 CookieSyncManager .createInstance (this );
@@ -381,72 +343,11 @@ private void deleteCookies() {
381343 }
382344 }
383345
384- private String baseUrl ;
385-
386- /**
387- * This function facilitates the login process by anonymously posting a login request to a specified URL.
388- * After posting the request, it retrieves the login URL for completing the login flow.
389- * The login flow version used is v2.
390- *
391- * @param url The URL where the login request is to be anonymously posted.
392- * This URL should handle the login request and return the login URL.
393- * It's typically the entry point for the login process.
394- * Example: "<a href="https://example.com/index.php/login/v2">...</a>"
395- */
396- private void anonymouslyPostLoginRequest (String url ) {
397- baseUrl = url ;
398-
399- Thread thread = new Thread (() -> {
400- String response = getResponseOfAnonymouslyPostLoginRequest ();
401-
402- try {
403- JsonObject jsonObject = JsonParser .parseString (response ).getAsJsonObject ();
404- String loginUrl = getLoginUrl (jsonObject );
405- runOnUiThread (() -> {
406- initLoginInfoView ();
407- launchDefaultWebBrowser (loginUrl );
408- });
409- token = jsonObject .getAsJsonObject ("poll" ).get ("token" ).getAsString ();
410- } catch (Throwable t ) {
411- Log_OC .d (TAG , "Error caught at anonymouslyPostLoginRequest: " + t );
412- DisplayUtils .showSnackMessage (this , R .string .authenticator_activity_login_error );
413- }
414- });
415-
416- thread .start ();
417- }
418-
419- private String getResponseOfAnonymouslyPostLoginRequest () {
420- PostMethod post = new PostMethod (baseUrl , false , new FormBody .Builder ().build ());
421- PlainClient client = clientFactory .createPlainClient ();
422- post .execute (client );
423- return post .getResponseBodyAsString ();
424- }
425-
426- private String getLoginUrl (JsonObject response ) {
427- String result = response .get ("login" ).getAsString ();
428- if (result == null ) {
429- result = getResources ().getString (R .string .webview_login_url );
430- }
431-
432- return result ;
433- }
434-
435- private void launchDefaultWebBrowser (String url ) {
436- Intent intent = new Intent (Intent .ACTION_VIEW , Uri .parse (url ));
437- intent .setFlags (Intent .FLAG_ACTIVITY_NEW_TASK );
438- startActivity (intent );
439- }
440-
441346 private static String getWebLoginUserAgent () {
442347 return Build .MANUFACTURER .substring (0 , 1 ).toUpperCase (Locale .getDefault ()) +
443348 Build .MANUFACTURER .substring (1 ).toLowerCase (Locale .getDefault ()) + " " + Build .MODEL + " (Android)" ;
444349 }
445350
446- /**
447- * @Deprecated This function is deprecated. Please use the {@link #anonymouslyPostLoginRequest(String)} method instead, which utilizes the improved login flow v2.
448- */
449- @ Deprecated
450351 @ SuppressFBWarnings ("ANDROID_WEB_VIEW_JAVASCRIPT" )
451352 @ SuppressLint ("SetJavaScriptEnabled" )
452353 private void initWebViewLogin (String baseURL , boolean useGenericUserAgent ) {
@@ -806,8 +707,7 @@ protected void onNewIntent(Intent intent) {
806707 if (intent .getBooleanExtra (EXTRA_USE_PROVIDER_AS_WEBLOGIN , false )) {
807708 accountSetupWebviewBinding = AccountSetupWebviewBinding .inflate (getLayoutInflater ());
808709 setContentView (accountSetupWebviewBinding .getRoot ());
809- anonymouslyPostLoginRequest (getString (R .string .provider_registration_server ));
810- // initWebViewLogin(getString(R.string.provider_registration_server), true);
710+ initWebViewLogin (getString (R .string .provider_registration_server ), true );
811711 }
812712 }
813713
@@ -1044,16 +944,7 @@ private void onGetServerInfoFinish(RemoteOperationResult result) {
1044944
1045945 accountSetupWebviewBinding = AccountSetupWebviewBinding .inflate (getLayoutInflater ());
1046946 setContentView (accountSetupWebviewBinding .getRoot ());
1047-
1048- if (!isLoginProcessCompleted ) {
1049- if (!isRedirectedToTheDefaultBrowser ) {
1050- anonymouslyPostLoginRequest (mServerInfo .mBaseUrl + WEB_LOGIN );
1051- isRedirectedToTheDefaultBrowser = true ;
1052- } else {
1053- initLoginInfoView ();
1054- }
1055- // initWebViewLogin(mServerInfo.mBaseUrl + WEB_LOGIN, false);
1056- }
947+ initWebViewLogin (mServerInfo .mBaseUrl + WEB_LOGIN , false );
1057948 }
1058949 } else {
1059950 updateServerStatusIconAndText (result );
@@ -1066,20 +957,6 @@ private void onGetServerInfoFinish(RemoteOperationResult result) {
1066957 }
1067958 }
1068959
1069- // region LoginInfoView
1070- private void initLoginInfoView () {
1071- LinearLayout loginFlowLayout = accountSetupWebviewBinding .loginFlowV2 .getRoot ();
1072- MaterialButton cancelButton = accountSetupWebviewBinding .loginFlowV2 .cancelButton ;
1073- loginFlowLayout .setVisibility (View .VISIBLE );
1074-
1075- cancelButton .setOnClickListener (v -> {
1076- loginFlowExecutorService .shutdown ();
1077- ProcessLifecycleOwner .get ().getLifecycle ().removeObserver (lifecycleEventObserver );
1078- recreate ();
1079- });
1080- }
1081- // endregion
1082-
1083960 /**
1084961 * Chooses the right icon and text to show to the user for the received operation result.
1085962 *
@@ -1321,8 +1198,7 @@ public void onAuthenticatorTaskCallback(RemoteOperationResult<UserInfo> result)
13211198
13221199 } else { // authorization fail due to client side - probably wrong credentials
13231200 if (accountSetupWebviewBinding != null ) {
1324- anonymouslyPostLoginRequest (mServerInfo .mBaseUrl + WEB_LOGIN );
1325- // initWebViewLogin(mServerInfo.mBaseUrl + WEB_LOGIN, false);
1201+ initWebViewLogin (mServerInfo .mBaseUrl + WEB_LOGIN , false );
13261202 DisplayUtils .showSnackMessage (this ,
13271203 accountSetupWebviewBinding .loginWebview , R .string .auth_access_failed ,
13281204 result .getLogMessage ());
@@ -1666,71 +1542,6 @@ public void onServiceDisconnected(ComponentName component) {
16661542 }
16671543 }
16681544
1669- private final ScheduledExecutorService loginFlowExecutorService = Executors .newSingleThreadScheduledExecutor ();
1670- private boolean isLoginProcessCompleted = false ;
1671- private boolean isRedirectedToTheDefaultBrowser = false ;
1672-
1673- private void poolLogin () {
1674- loginFlowExecutorService .scheduleWithFixedDelay (() -> {
1675- if (!isLoginProcessCompleted ) {
1676- performLoginFlowV2 ();
1677- }
1678- }, 0 , 30 , TimeUnit .SECONDS );
1679- }
1680-
1681- private void performLoginFlowV2 () {
1682- String postRequestUrl = baseUrl + "/poll" ;
1683-
1684- RequestBody requestBody = new FormBody .Builder ()
1685- .add ("token" , token )
1686- .build ();
1687-
1688- PlainClient client = clientFactory .createPlainClient ();
1689- PostMethod post = new PostMethod (postRequestUrl , false , requestBody );
1690- int status = post .execute (client );
1691- String response = post .getResponseBodyAsString ();
1692-
1693- Log_OC .d (TAG , "performLoginFlowV2 status: " + status );
1694- Log_OC .d (TAG , "performLoginFlowV2 response: " + response );
1695-
1696- if (!response .isEmpty ()) {
1697- runOnUiThread (() -> completeLoginFlow (response , status ));
1698- }
1699- }
1700-
1701- private void completeLoginFlow (String response , int status ) {
1702- try {
1703- JSONObject jsonObject = new JSONObject (response );
1704-
1705- String server = jsonObject .getString ("server" );
1706- String loginName = jsonObject .getString ("loginName" );
1707- String appPassword = jsonObject .getString ("appPassword" );
1708-
1709- LoginUrlInfo loginUrlInfo = new LoginUrlInfo ();
1710- loginUrlInfo .serverAddress = server ;
1711- loginUrlInfo .username = loginName ;
1712- loginUrlInfo .password = appPassword ;
1713-
1714- isLoginProcessCompleted = (status == 200 && !server .isEmpty () && !loginName .isEmpty () && !appPassword .isEmpty ());
1715-
1716- if (accountSetupBinding != null ) {
1717- accountSetupBinding .hostUrlInput .setText ("" );
1718- }
1719- mServerInfo .mBaseUrl = AuthenticatorUrlUtils .INSTANCE .normalizeUrlSuffix (loginUrlInfo .serverAddress );
1720- webViewUser = loginUrlInfo .username ;
1721- webViewPassword = loginUrlInfo .password ;
1722- } catch (Exception e ) {
1723- Log_OC .d (TAG , "Error caught at completeLoginFlow: " + e );
1724- mServerStatusIcon = R .drawable .ic_alert ;
1725- mServerStatusText = getString (R .string .qr_could_not_be_read );
1726- showServerStatus ();
1727- }
1728-
1729- checkOcServer ();
1730- loginFlowExecutorService .shutdown ();
1731- ProcessLifecycleOwner .get ().getLifecycle ().removeObserver (lifecycleEventObserver );
1732- }
1733-
17341545 /**
17351546 * Called from SslValidatorDialog when a new server certificate was correctly saved.
17361547 */
0 commit comments