supports retype phone login challenge

This commit is contained in:
Mariotaku Lee 2016-02-14 16:24:39 +08:00
parent bb7cdf1b53
commit 76645a6ecd
20 changed files with 89 additions and 35 deletions

View File

@ -34,8 +34,13 @@ import com.squareup.leakcanary.ServiceHeapDumpListener;
import org.mariotaku.twidere.BuildConfig;
import org.mariotaku.twidere.activity.support.ComposeActivity;
import org.mariotaku.twidere.util.net.NoIntercept;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Response;
/**
* Created by mariotaku on 15/5/27.
@ -45,7 +50,17 @@ public class DebugModeUtils {
private static RefWatcher sRefWatcher;
public static void initForOkHttpClient(final OkHttpClient.Builder builder) {
builder.addNetworkInterceptor(new StethoInterceptor());
final StethoInterceptor interceptor = new StethoInterceptor();
builder.addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
if (chain.request().tag() == NoIntercept.INSTANCE) {
return chain.proceed(chain.request());
}
return interceptor.intercept(chain);
}
});
}
public static void initForApplication(final Application application) {

View File

@ -92,7 +92,6 @@ import org.mariotaku.twidere.util.ParseUtils;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.TwidereActionModeForChildListener;
import org.mariotaku.twidere.util.TwidereColorUtils;
import org.mariotaku.twidere.util.TwitterAPIFactory;
import org.mariotaku.twidere.util.UserAgentUtils;
import org.mariotaku.twidere.util.Utils;
@ -942,6 +941,9 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
if ("Push".equalsIgnoreCase(challengeType)) {
verificationHint.setText(R.string.login_verification_push_hint);
editVerification.setVisibility(View.GONE);
} else if ("RetypePhoneNumber".equalsIgnoreCase(challengeType)) {
verificationHint.setText(R.string.login_challenge_retype_phone_hint);
editVerification.setVisibility(View.VISIBLE);
} else {
verificationHint.setText(R.string.login_verification_pin_hint);
editVerification.setVisibility(View.VISIBLE);

View File

@ -129,6 +129,8 @@ abstract class AbsUsersFragment<Data> extends AbsContentListRecyclerViewFragment
protected abstract boolean hasMoreData(Data data);
protected abstract Loader<Data> onCreateUsersLoader(Context context, Bundle args, boolean fromUser);
protected abstract Loader<Data> onCreateUsersLoader(final Context context,
@NonNull final Bundle args,
final boolean fromUser);
}

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.fragment.support;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.content.Loader;
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition;
@ -95,5 +96,5 @@ public abstract class CursorSupportUsersListFragment extends ParcelableUsersFrag
}
@Override
protected abstract BaseCursorSupportUsersLoader onCreateUsersLoader(final Context context, final Bundle args, boolean fromUser);
protected abstract BaseCursorSupportUsersLoader onCreateUsersLoader(final Context context, @NonNull final Bundle args, boolean fromUser);
}

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.fragment.support;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.loader.support.IDsUsersLoader;
import org.mariotaku.twidere.loader.support.IncomingFriendshipsLoader;
@ -28,8 +29,7 @@ import org.mariotaku.twidere.loader.support.IncomingFriendshipsLoader;
public class IncomingFriendshipsFragment extends CursorSupportUsersListFragment {
@Override
public IDsUsersLoader onCreateUsersLoader(final Context context, final Bundle args, boolean fromUser) {
if (args == null) return null;
public IDsUsersLoader onCreateUsersLoader(final Context context, @NonNull final Bundle args, boolean fromUser) {
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
return new IncomingFriendshipsLoader(context, accountId, getNextCursor(), getData(), fromUser);
}

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.fragment.support;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.loader.support.CursorSupportUsersLoader;
import org.mariotaku.twidere.loader.support.MutesUsersLoader;
@ -28,7 +29,7 @@ import org.mariotaku.twidere.loader.support.MutesUsersLoader;
public class MutesUsersListFragment extends CursorSupportUsersListFragment {
@Override
public CursorSupportUsersLoader onCreateUsersLoader(final Context context, final Bundle args, boolean fromUser) {
public CursorSupportUsersLoader onCreateUsersLoader(final Context context, @NonNull final Bundle args, boolean fromUser) {
if (args == null) return null;
final long account_id = args.getLong(EXTRA_ACCOUNT_ID, -1);
return new MutesUsersLoader(context, account_id, getNextCursor(), getData(), fromUser);

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.fragment.support;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.content.Loader;
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition;
@ -42,7 +43,7 @@ public class SearchUsersFragment extends ParcelableUsersFragment {
}
@Override
public Loader<List<ParcelableUser>> onCreateUsersLoader(final Context context, final Bundle args, boolean fromUser) {
public Loader<List<ParcelableUser>> onCreateUsersLoader(final Context context, @NonNull final Bundle args, boolean fromUser) {
if (args == null) return null;
final long account_id = args.getLong(EXTRA_ACCOUNT_ID);
final String query = args.getString(EXTRA_QUERY);

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.fragment.support;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.loader.support.IDsUsersLoader;
import org.mariotaku.twidere.loader.support.StatusFavoritersLoader;
@ -28,7 +29,7 @@ import org.mariotaku.twidere.loader.support.StatusFavoritersLoader;
public class StatusFavoritersListFragment extends CursorSupportUsersListFragment {
@Override
public IDsUsersLoader onCreateUsersLoader(final Context context, final Bundle args, boolean fromUser) {
public IDsUsersLoader onCreateUsersLoader(final Context context, @NonNull final Bundle args, boolean fromUser) {
if (args == null) return null;
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
final long statusId = args.getLong(EXTRA_STATUS_ID, -1);

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.fragment.support;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.loader.support.IDsUsersLoader;
import org.mariotaku.twidere.loader.support.StatusRetweetersLoader;
@ -28,7 +29,7 @@ import org.mariotaku.twidere.loader.support.StatusRetweetersLoader;
public class StatusRetweetersListFragment extends CursorSupportUsersListFragment {
@Override
public IDsUsersLoader onCreateUsersLoader(final Context context, final Bundle args, boolean fromUser) {
public IDsUsersLoader onCreateUsersLoader(final Context context, @NonNull final Bundle args, boolean fromUser) {
if (args == null) return null;
final long account_id = args.getLong(EXTRA_ACCOUNT_ID, -1);
final long status_id = args.getLong(EXTRA_STATUS_ID, -1);

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.fragment.support;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.loader.support.CursorSupportUsersLoader;
import org.mariotaku.twidere.loader.support.UserBlocksLoader;
@ -28,7 +29,7 @@ import org.mariotaku.twidere.loader.support.UserBlocksLoader;
public class UserBlocksListFragment extends CursorSupportUsersListFragment {
@Override
public CursorSupportUsersLoader onCreateUsersLoader(final Context context, final Bundle args, boolean fromUser) {
public CursorSupportUsersLoader onCreateUsersLoader(final Context context, @NonNull final Bundle args, boolean fromUser) {
if (args == null) return null;
final long account_id = args.getLong(EXTRA_ACCOUNT_ID, -1);
return new UserBlocksLoader(context, account_id, getNextCursor(), getData(), fromUser);

View File

@ -24,6 +24,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.loader.support.CursorSupportUsersLoader;
import org.mariotaku.twidere.loader.support.UserFollowersLoader;
@ -53,7 +54,7 @@ public class UserFollowersFragment extends CursorSupportUsersListFragment {
};
@Override
public CursorSupportUsersLoader onCreateUsersLoader(final Context context, final Bundle args, boolean fromUser) {
public CursorSupportUsersLoader onCreateUsersLoader(final Context context, @NonNull final Bundle args, boolean fromUser) {
if (args == null) return null;
final long account_id = args.getLong(EXTRA_ACCOUNT_ID, -1);
final long user_id = args.getLong(EXTRA_USER_ID, -1);

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.fragment.support;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.loader.support.CursorSupportUsersLoader;
import org.mariotaku.twidere.loader.support.UserFriendsLoader;
@ -28,7 +29,7 @@ import org.mariotaku.twidere.loader.support.UserFriendsLoader;
public class UserFriendsFragment extends CursorSupportUsersListFragment {
@Override
public CursorSupportUsersLoader onCreateUsersLoader(final Context context, final Bundle args, boolean fromUser) {
public CursorSupportUsersLoader onCreateUsersLoader(final Context context, @NonNull final Bundle args, boolean fromUser) {
if (args == null) return null;
final long account_id = args.getLong(EXTRA_ACCOUNT_ID, -1);
final long user_id = args.getLong(EXTRA_USER_ID, -1);

View File

@ -57,7 +57,7 @@ public class UserListMembersFragment extends CursorSupportUsersListFragment {
};
@Override
public CursorSupportUsersLoader onCreateUsersLoader(final Context context, final Bundle args, boolean fromUser) {
public CursorSupportUsersLoader onCreateUsersLoader(final Context context, @NonNull final Bundle args, boolean fromUser) {
if (args == null) return null;
final long listId = args.getLong(EXTRA_LIST_ID, -1);
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.fragment.support;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.loader.support.CursorSupportUsersLoader;
import org.mariotaku.twidere.loader.support.UserListSubscribersLoader;
@ -28,7 +29,7 @@ import org.mariotaku.twidere.loader.support.UserListSubscribersLoader;
public class UserListSubscribersFragment extends CursorSupportUsersListFragment {
@Override
public CursorSupportUsersLoader onCreateUsersLoader(final Context context, final Bundle args, boolean fromUser) {
public CursorSupportUsersLoader onCreateUsersLoader(final Context context, @NonNull final Bundle args, boolean fromUser) {
if (args == null) return null;
final long listId = args.getLong(EXTRA_LIST_ID, -1);
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.fragment.support;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.Loader;
@ -54,7 +55,7 @@ public class UsersListFragment extends ParcelableUsersFragment {
}
@Override
public Loader<List<ParcelableUser>> onCreateUsersLoader(final Context context, final Bundle args, boolean fromUser) {
public Loader<List<ParcelableUser>> onCreateUsersLoader(final Context context, @NonNull final Bundle args, boolean fromUser) {
if (args == null) return null;
if (args.containsKey(EXTRA_USERS))
return new IntentExtrasUsersLoader(context, args, getData(), fromUser);

View File

@ -302,6 +302,8 @@ public class DataImportExportUtils implements Constants {
}
} catch (JSONException e) {
return false;
} catch (ClassCastException e) {
return false;
}
return true;
}

View File

@ -98,12 +98,12 @@ public class OAuthPasswordAuthenticator implements Constants {
if (!TextUtils.isEmpty(authorizeResponseData.oauthPin)) {
// Here we got OAuth PIN, just get access token directly
return oauth.getAccessToken(requestToken, authorizeResponseData.oauthPin);
} else if (authorizeResponseData.verification == null) {
} else if (authorizeResponseData.challenge == null) {
// No OAuth pin, or verification challenge, so treat as wrong password
throw new WrongUserPassException();
}
// Go to password verification flow
final String challengeType = authorizeResponseData.verification.challengeType;
final String challengeType = authorizeResponseData.challenge.challengeType;
final String loginVerification = loginVerificationCallback.getLoginVerification(challengeType);
final AuthorizeRequestData verificationData = getVerificationData(authorizeResponseData,
loginVerification);
@ -124,7 +124,7 @@ public class OAuthPasswordAuthenticator implements Constants {
try {
final AuthorizeRequestData data = new AuthorizeRequestData();
final MultiValueMap<String> params = new MultiValueMap<>();
final AuthorizeResponseData.Verification verification = authorizeResponseData.verification;
final AuthorizeResponseData.Verification verification = authorizeResponseData.challenge;
params.add("authenticity_token", verification.authenticityToken);
params.add("user_id", verification.userId);
params.add("challenge_id", verification.challengeId);
@ -234,7 +234,7 @@ public class OAuthPasswordAuthenticator implements Constants {
final HtmlParsingConfiguration conf = new HtmlParsingConfiguration();
final IAttoHandler handler = new AbstractStandardNonValidatingHtmlAttoHandler(conf) {
boolean isOAuthPinDivOpened;
boolean isLoginVerificationFormOpened;
boolean isChallengeFormOpened;
@Override
public void handleHtmlStandaloneElement(IHtmlElement element, boolean minimized,
@ -252,7 +252,7 @@ public class OAuthPasswordAuthenticator implements Constants {
break;
}
case "form": {
isLoginVerificationFormOpened = false;
isChallengeFormOpened = false;
break;
}
}
@ -263,51 +263,61 @@ public class OAuthPasswordAuthenticator implements Constants {
Map<String, String> attributes, int line, int col) {
switch (elementName) {
case "div": {
if (attributes != null && "oauth_pin".equals(attributes.get("id"))) {
if (attributes == null) break;
if ("oauth_pin".equals(attributes.get("id"))) {
isOAuthPinDivOpened = true;
}
break;
}
case "form": {
if (attributes != null && "login-verification-form".equals(attributes.get("id"))) {
isLoginVerificationFormOpened = true;
if (attributes == null) break;
final String id = attributes.get("id");
if (id == null) break;
switch (id) {
case "login-verification-form":
case "login-challenge-form": {
isChallengeFormOpened = true;
break;
}
}
break;
}
case "input":
if (isLoginVerificationFormOpened && attributes != null) {
if (attributes == null) break;
if (isChallengeFormOpened) {
final String name = attributes.get("name");
if (TextUtils.isEmpty(name)) break;
final String value = attributes.get("value");
switch (name) {
case "authenticity_token": {
ensureVerification();
data.verification.authenticityToken = value;
data.challenge.authenticityToken = value;
break;
}
case "challenge_id": {
ensureVerification();
data.verification.challengeId = value;
data.challenge.challengeId = value;
break;
}
case "challenge_type": {
ensureVerification();
data.verification.challengeType = value;
data.challenge.challengeType = value;
break;
}
case "platform": {
ensureVerification();
data.verification.platform = value;
data.challenge.platform = value;
break;
}
case "user_id": {
ensureVerification();
data.verification.userId = value;
data.challenge.userId = value;
break;
}
case "redirect_after_login": {
ensureVerification();
data.verification.redirectAfterLogin = value;
data.challenge.redirectAfterLogin = value;
break;
}
}
@ -317,8 +327,8 @@ public class OAuthPasswordAuthenticator implements Constants {
}
private void ensureVerification() {
if (data.verification == null) {
data.verification = new AuthorizeResponseData.Verification();
if (data.challenge == null) {
data.challenge = new AuthorizeResponseData.Verification();
}
}
@ -484,7 +494,7 @@ public class OAuthPasswordAuthenticator implements Constants {
String referer;
public String oauthPin;
public Verification verification;
public Verification challenge;
static class Verification {

View File

@ -32,6 +32,7 @@ import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.TwitterAPIFactory;
import org.mariotaku.twidere.util.UserAgentUtils;
import org.mariotaku.twidere.util.media.preview.PreviewMediaExtractor;
import org.mariotaku.twidere.util.net.NoIntercept;
import java.io.IOException;
@ -130,8 +131,11 @@ public class TwidereMediaDownloader implements MediaDownloader, Constants {
builder.method(method);
builder.url(requestUri);
builder.headers(additionalHeaders);
builder.tag(NoIntercept.INSTANCE);
final HttpResponse resp = mClient.newCall(builder.build()).execute();
if (!resp.isSuccessful()) throw new IOException("Unable to get media, response code: " + resp.getStatus());
if (!resp.isSuccessful()) {
throw new IOException("Unable to get media, response code: " + resp.getStatus());
}
final Body body = resp.getBody();
return new CacheDownloadLoader.DownloadResult(body.length(), body.stream());
}

View File

@ -0,0 +1,8 @@
package org.mariotaku.twidere.util.net;
/**
* Created by mariotaku on 16/2/14.
*/
public class NoIntercept {
public static final NoIntercept INSTANCE = new NoIntercept();
}

View File

@ -827,6 +827,7 @@
<string name="link_copied_to_clipboard">Link copied to clipboard</string>
<string name="login_verification">Login verification</string>
<string name="login_verification_pin_hint">Check your phone for a PIN code and enter it to log in.</string>
<string name="login_challenge_retype_phone_hint">Retype the phone number associated with your Twitter account.</string>
<string name="login_verification_push_hint">Accept login verification request from Twitter app, once you approved the request, click OK.</string>
<string name="login_verification_failed">Login verification failed.</string>
<string name="saved_searches_already_saved_hint">Perhaps you already saved this search</string>