2014-07-03 07:48:39 +02:00
|
|
|
/*
|
|
|
|
* Twidere - Twitter client for Android
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package org.mariotaku.twidere.activity.support;
|
|
|
|
|
|
|
|
import android.annotation.SuppressLint;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.SharedPreferences;
|
|
|
|
import android.graphics.Bitmap;
|
|
|
|
import android.net.Uri;
|
|
|
|
import android.net.http.SslError;
|
2015-03-29 20:19:25 +02:00
|
|
|
import android.os.AsyncTask;
|
2014-07-03 07:48:39 +02:00
|
|
|
import android.os.Bundle;
|
2015-02-03 06:22:02 +01:00
|
|
|
import android.support.annotation.NonNull;
|
2015-12-20 12:54:05 +01:00
|
|
|
import android.util.Log;
|
2014-07-03 07:48:39 +02:00
|
|
|
import android.view.MenuItem;
|
|
|
|
import android.view.View;
|
|
|
|
import android.view.Window;
|
|
|
|
import android.webkit.JavascriptInterface;
|
|
|
|
import android.webkit.SslErrorHandler;
|
|
|
|
import android.webkit.WebSettings;
|
|
|
|
import android.webkit.WebView;
|
|
|
|
import android.webkit.WebViewClient;
|
|
|
|
import android.widget.Toast;
|
|
|
|
|
2015-11-14 13:36:56 +01:00
|
|
|
import org.attoparser.AttoParseException;
|
2015-05-26 13:19:03 +02:00
|
|
|
import org.mariotaku.restfu.http.Authorization;
|
2014-07-03 07:48:39 +02:00
|
|
|
import org.mariotaku.twidere.R;
|
2015-05-13 17:40:56 +02:00
|
|
|
import org.mariotaku.twidere.api.twitter.TwitterOAuth;
|
2015-05-07 15:31:13 +02:00
|
|
|
import org.mariotaku.twidere.api.twitter.auth.OAuthAuthorization;
|
2015-08-28 12:16:41 +02:00
|
|
|
import org.mariotaku.twidere.api.twitter.auth.OAuthEndpoint;
|
2015-05-06 18:15:38 +02:00
|
|
|
import org.mariotaku.twidere.api.twitter.auth.OAuthToken;
|
2014-07-03 07:48:39 +02:00
|
|
|
import org.mariotaku.twidere.app.TwidereApplication;
|
2015-01-11 10:28:45 +01:00
|
|
|
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
2015-03-29 20:19:25 +02:00
|
|
|
import org.mariotaku.twidere.util.AsyncTaskUtils;
|
2014-07-03 07:48:39 +02:00
|
|
|
import org.mariotaku.twidere.util.OAuthPasswordAuthenticator;
|
2015-05-26 13:19:03 +02:00
|
|
|
import org.mariotaku.twidere.util.TwitterAPIFactory;
|
2014-07-03 07:48:39 +02:00
|
|
|
|
2014-11-01 17:57:31 +01:00
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.StringReader;
|
|
|
|
|
|
|
|
import static android.text.TextUtils.isEmpty;
|
|
|
|
import static org.mariotaku.twidere.util.Utils.getNonEmptyString;
|
2014-07-03 07:48:39 +02:00
|
|
|
|
|
|
|
@SuppressLint("SetJavaScriptEnabled")
|
2015-05-13 17:40:56 +02:00
|
|
|
public class BrowserSignInActivity extends BaseSupportDialogActivity {
|
2014-07-03 07:48:39 +02:00
|
|
|
|
2014-11-01 17:57:31 +01:00
|
|
|
private static final String INJECT_CONTENT = "javascript:window.injector.processHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');";
|
|
|
|
|
|
|
|
private SharedPreferences mPreferences;
|
|
|
|
|
|
|
|
private WebView mWebView;
|
|
|
|
private View mProgressContainer;
|
|
|
|
|
|
|
|
private WebSettings mWebSettings;
|
|
|
|
|
2015-05-06 18:15:38 +02:00
|
|
|
private OAuthToken mRequestToken;
|
2014-11-01 17:57:31 +01:00
|
|
|
|
|
|
|
private GetRequestTokenTask mTask;
|
|
|
|
|
|
|
|
@Override
|
2015-01-18 17:15:38 +01:00
|
|
|
public void onContentChanged() {
|
|
|
|
super.onContentChanged();
|
2014-11-01 17:57:31 +01:00
|
|
|
mWebView = (WebView) findViewById(R.id.webview);
|
|
|
|
mProgressContainer = findViewById(R.id.progress_container);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onDestroy() {
|
|
|
|
getLoaderManager().destroyLoader(0);
|
|
|
|
super.onDestroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onOptionsItemSelected(final MenuItem item) {
|
|
|
|
switch (item.getItemId()) {
|
2015-07-17 16:30:41 +02:00
|
|
|
case android.R.id.home: {
|
2014-11-01 17:57:31 +01:00
|
|
|
finish();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return super.onOptionsItemSelected(item);
|
|
|
|
}
|
|
|
|
|
2015-12-20 12:54:05 +01:00
|
|
|
@SuppressLint("AddJavascriptInterface")
|
2014-11-01 17:57:31 +01:00
|
|
|
@Override
|
|
|
|
protected void onCreate(final Bundle savedInstanceState) {
|
|
|
|
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
|
|
|
setContentView(R.layout.activity_browser_sign_in);
|
|
|
|
mWebView.setWebViewClient(new AuthorizationWebViewClient(this));
|
|
|
|
mWebView.setVerticalScrollBarEnabled(false);
|
|
|
|
mWebView.addJavascriptInterface(new InjectorJavaScriptInterface(this), "injector");
|
|
|
|
mWebSettings = mWebView.getSettings();
|
|
|
|
mWebSettings.setLoadsImagesAutomatically(true);
|
|
|
|
mWebSettings.setJavaScriptEnabled(true);
|
|
|
|
mWebSettings.setBlockNetworkImage(false);
|
|
|
|
mWebSettings.setSaveFormData(true);
|
|
|
|
getRequestToken();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void getRequestToken() {
|
2015-03-29 20:19:25 +02:00
|
|
|
if (mRequestToken != null || mTask != null && mTask.getStatus() == AsyncTask.Status.RUNNING)
|
2014-11-01 17:57:31 +01:00
|
|
|
return;
|
|
|
|
mTask = new GetRequestTokenTask(this);
|
2015-03-29 20:19:25 +02:00
|
|
|
AsyncTaskUtils.executeTask(mTask);
|
2014-11-01 17:57:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private void loadUrl(final String url) {
|
|
|
|
if (mWebView == null) return;
|
|
|
|
mWebView.loadUrl(url);
|
|
|
|
}
|
|
|
|
|
|
|
|
private String readOAuthPin(final String html) {
|
|
|
|
try {
|
2015-11-14 13:36:56 +01:00
|
|
|
OAuthPasswordAuthenticator.OAuthPinData data = new OAuthPasswordAuthenticator.OAuthPinData();
|
|
|
|
OAuthPasswordAuthenticator.readOAuthPINFromHtml(new StringReader(html), data);
|
|
|
|
return data.oauthPin;
|
|
|
|
} catch (final AttoParseException | IOException e) {
|
2015-12-20 12:54:05 +01:00
|
|
|
Log.w(LOGTAG, e);
|
2014-11-01 17:57:31 +01:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void setLoadProgressShown(final boolean shown) {
|
|
|
|
mProgressContainer.setVisibility(shown ? View.VISIBLE : View.GONE);
|
|
|
|
}
|
|
|
|
|
2015-05-06 18:15:38 +02:00
|
|
|
private void setRequestToken(final OAuthToken token) {
|
2014-11-01 17:57:31 +01:00
|
|
|
mRequestToken = token;
|
|
|
|
}
|
|
|
|
|
|
|
|
static class AuthorizationWebViewClient extends WebViewClient {
|
|
|
|
private final BrowserSignInActivity mActivity;
|
|
|
|
|
|
|
|
AuthorizationWebViewClient(final BrowserSignInActivity activity) {
|
|
|
|
mActivity = activity;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPageFinished(final WebView view, final String url) {
|
|
|
|
super.onPageFinished(view, url);
|
|
|
|
view.loadUrl(INJECT_CONTENT);
|
|
|
|
mActivity.setLoadProgressShown(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPageStarted(final WebView view, final String url, final Bitmap favicon) {
|
|
|
|
super.onPageStarted(view, url, favicon);
|
|
|
|
mActivity.setLoadProgressShown(true);
|
|
|
|
}
|
|
|
|
|
2015-04-04 16:31:37 +02:00
|
|
|
@Override
|
|
|
|
public void onLoadResource(WebView view, String url) {
|
|
|
|
super.onLoadResource(view, url);
|
|
|
|
}
|
|
|
|
|
2015-12-20 12:54:05 +01:00
|
|
|
@SuppressWarnings("deprecation")
|
2014-11-01 17:57:31 +01:00
|
|
|
@Override
|
|
|
|
public void onReceivedError(final WebView view, final int errorCode, final String description,
|
|
|
|
final String failingUrl) {
|
|
|
|
super.onReceivedError(view, errorCode, description, failingUrl);
|
|
|
|
Toast.makeText(mActivity, R.string.error_occurred, Toast.LENGTH_SHORT).show();
|
|
|
|
mActivity.finish();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2015-02-03 06:22:02 +01:00
|
|
|
public void onReceivedSslError(final WebView view, @NonNull final SslErrorHandler handler, final SslError error) {
|
2014-11-01 17:57:31 +01:00
|
|
|
if (mActivity.mPreferences.getBoolean(KEY_IGNORE_SSL_ERROR, false)) {
|
|
|
|
handler.proceed();
|
|
|
|
} else {
|
|
|
|
handler.cancel();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean shouldOverrideUrlLoading(final WebView view, final String url) {
|
|
|
|
final Uri uri = Uri.parse(url);
|
|
|
|
if (url.startsWith(OAUTH_CALLBACK_URL)) {
|
|
|
|
final String oauth_verifier = uri.getQueryParameter(EXTRA_OAUTH_VERIFIER);
|
2015-05-06 18:15:38 +02:00
|
|
|
final OAuthToken requestToken = mActivity.mRequestToken;
|
|
|
|
if (oauth_verifier != null && requestToken != null) {
|
2014-11-01 17:57:31 +01:00
|
|
|
final Intent intent = new Intent();
|
|
|
|
intent.putExtra(EXTRA_OAUTH_VERIFIER, oauth_verifier);
|
2015-05-06 18:15:38 +02:00
|
|
|
intent.putExtra(EXTRA_REQUEST_TOKEN, requestToken.getOauthToken());
|
|
|
|
intent.putExtra(EXTRA_REQUEST_TOKEN_SECRET, requestToken.getOauthTokenSecret());
|
2014-11-01 17:57:31 +01:00
|
|
|
mActivity.setResult(RESULT_OK, intent);
|
|
|
|
mActivity.finish();
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-05-06 18:15:38 +02:00
|
|
|
static class GetRequestTokenTask extends AsyncTask<Object, Object, OAuthToken> {
|
2014-11-01 17:57:31 +01:00
|
|
|
|
|
|
|
private final String mConsumerKey, mConsumerSecret;
|
|
|
|
private final TwidereApplication mApplication;
|
|
|
|
private final SharedPreferences mPreferences;
|
|
|
|
private final BrowserSignInActivity mActivity;
|
|
|
|
|
|
|
|
public GetRequestTokenTask(final BrowserSignInActivity activity) {
|
|
|
|
mActivity = activity;
|
|
|
|
mApplication = TwidereApplication.getInstance(activity);
|
|
|
|
mPreferences = activity.getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE);
|
|
|
|
final Intent intent = activity.getIntent();
|
|
|
|
mConsumerKey = intent.getStringExtra(Accounts.CONSUMER_KEY);
|
|
|
|
mConsumerSecret = intent.getStringExtra(Accounts.CONSUMER_SECRET);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2015-05-06 18:15:38 +02:00
|
|
|
protected OAuthToken doInBackground(final Object... params) {
|
2015-05-08 20:57:26 +02:00
|
|
|
final String defConsumerKey = getNonEmptyString(mPreferences, KEY_CONSUMER_KEY, TWITTER_CONSUMER_KEY);
|
|
|
|
final String defConsumerSecret = getNonEmptyString(mPreferences, KEY_CONSUMER_SECRET,
|
2015-05-08 09:52:15 +02:00
|
|
|
TWITTER_CONSUMER_SECRET);
|
2015-05-08 20:57:26 +02:00
|
|
|
final String consumerKey, consumerSecret;
|
2014-11-01 17:57:31 +01:00
|
|
|
if (!isEmpty(mConsumerKey) && !isEmpty(mConsumerSecret)) {
|
2015-05-08 20:57:26 +02:00
|
|
|
consumerKey = mConsumerKey;
|
|
|
|
consumerSecret = mConsumerSecret;
|
2014-11-01 17:57:31 +01:00
|
|
|
} else {
|
2015-05-08 20:57:26 +02:00
|
|
|
consumerKey = defConsumerKey;
|
|
|
|
consumerSecret = defConsumerSecret;
|
2014-11-01 17:57:31 +01:00
|
|
|
}
|
|
|
|
try {
|
2015-08-28 12:16:41 +02:00
|
|
|
final OAuthEndpoint endpoint = new OAuthEndpoint(TwitterAPIFactory.getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, "api", null));
|
2015-05-08 20:57:26 +02:00
|
|
|
final Authorization auth = new OAuthAuthorization(consumerKey, consumerSecret);
|
2015-05-26 13:19:03 +02:00
|
|
|
final TwitterOAuth twitter = TwitterAPIFactory.getInstance(mActivity, endpoint, auth, TwitterOAuth.class);
|
2015-05-06 21:47:09 +02:00
|
|
|
return twitter.getRequestToken(OAUTH_CALLBACK_OOB);
|
|
|
|
} catch (final Exception e) {
|
2015-12-20 12:54:05 +01:00
|
|
|
Log.w(LOGTAG, e);
|
2014-11-01 17:57:31 +01:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2015-05-06 18:15:38 +02:00
|
|
|
protected void onPostExecute(final OAuthToken data) {
|
2014-11-01 17:57:31 +01:00
|
|
|
mActivity.setLoadProgressShown(false);
|
|
|
|
mActivity.setRequestToken(data);
|
|
|
|
if (data == null) {
|
2014-11-19 06:06:09 +01:00
|
|
|
if (!mActivity.isFinishing()) {
|
|
|
|
Toast.makeText(mActivity, R.string.error_occurred, Toast.LENGTH_SHORT).show();
|
|
|
|
mActivity.finish();
|
|
|
|
}
|
2014-11-01 17:57:31 +01:00
|
|
|
return;
|
|
|
|
}
|
2015-09-03 09:15:11 +02:00
|
|
|
final OAuthEndpoint endpoint = new OAuthEndpoint(TwitterAPIFactory.getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, "api", null));
|
2016-01-20 04:52:08 +01:00
|
|
|
mActivity.loadUrl(endpoint.construct("/oauth/authorize", new String[]{"oauth_token", data.getOauthToken()}));
|
2014-11-01 17:57:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onPreExecute() {
|
|
|
|
mActivity.setLoadProgressShown(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static class InjectorJavaScriptInterface {
|
|
|
|
|
|
|
|
private final BrowserSignInActivity mActivity;
|
|
|
|
|
|
|
|
InjectorJavaScriptInterface(final BrowserSignInActivity activity) {
|
|
|
|
mActivity = activity;
|
|
|
|
}
|
|
|
|
|
|
|
|
@JavascriptInterface
|
|
|
|
public void processHTML(final String html) {
|
2015-02-03 06:22:02 +01:00
|
|
|
final String oauthVerifier = mActivity.readOAuthPin(html);
|
2015-05-06 18:15:38 +02:00
|
|
|
final OAuthToken requestToken = mActivity.mRequestToken;
|
2015-02-03 06:22:02 +01:00
|
|
|
if (oauthVerifier != null && requestToken != null) {
|
2014-11-01 17:57:31 +01:00
|
|
|
final Intent intent = new Intent();
|
2015-02-03 06:22:02 +01:00
|
|
|
intent.putExtra(EXTRA_OAUTH_VERIFIER, oauthVerifier);
|
2015-05-06 18:15:38 +02:00
|
|
|
intent.putExtra(EXTRA_REQUEST_TOKEN, requestToken.getOauthToken());
|
|
|
|
intent.putExtra(EXTRA_REQUEST_TOKEN_SECRET, requestToken.getOauthTokenSecret());
|
2014-11-01 17:57:31 +01:00
|
|
|
mActivity.setResult(RESULT_OK, intent);
|
|
|
|
mActivity.finish();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-07-03 07:48:39 +02:00
|
|
|
}
|