diff options
author | Nick Bradbury <nick.bradbury@gmail.com> | 2015-02-27 07:33:08 -0500 |
---|---|---|
committer | Nick Bradbury <nick.bradbury@gmail.com> | 2015-02-27 07:33:08 -0500 |
commit | cd65b32e7391e4ae05d9696221c0d16be89e5850 (patch) | |
tree | b6c32d70a17ef97b399888455fd2167c11e13fcb /WordPress/src/main/java/org/wordpress | |
parent | 7688755b35679c661f6528b59a1b7e0ded464d02 (diff) | |
parent | 1bbcedd1d052907ae37a6e7f8124cf14ad10fcf3 (diff) | |
download | gradle-perf-android-medium-cd65b32e7391e4ae05d9696221c0d16be89e5850.tar.gz |
Merge branch 'develop' of https://github.com/wordpress-mobile/WordPress-Android into issue/2367-reader-new-posts
Diffstat (limited to 'WordPress/src/main/java/org/wordpress')
44 files changed, 562 insertions, 980 deletions
diff --git a/WordPress/src/main/java/org/wordpress/android/GCMIntentService.java b/WordPress/src/main/java/org/wordpress/android/GCMIntentService.java index 3f08f64c9..d53ba2dfd 100644 --- a/WordPress/src/main/java/org/wordpress/android/GCMIntentService.java +++ b/WordPress/src/main/java/org/wordpress/android/GCMIntentService.java @@ -273,7 +273,7 @@ public class GCMIntentService extends GCMBaseIntentService { return; } - if (!WordPress.hasValidWPComCredentials(context)) { + if (!WordPress.hasDotComToken(context)) { return; } diff --git a/WordPress/src/main/java/org/wordpress/android/WordPress.java b/WordPress/src/main/java/org/wordpress/android/WordPress.java index e7ad44ff5..4edad2973 100644 --- a/WordPress/src/main/java/org/wordpress/android/WordPress.java +++ b/WordPress/src/main/java/org/wordpress/android/WordPress.java @@ -27,6 +27,7 @@ import com.google.android.gcm.GCMRegistrar; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.wordpress.rest.RestClient; +import com.wordpress.rest.RestRequest; import org.wordpress.android.WordPress.SignOutAsync.SignOutCallback; import org.wordpress.android.analytics.AnalyticsTracker; @@ -76,7 +77,6 @@ import de.greenrobot.event.EventBus; public class WordPress extends Application { public static final String ACCESS_TOKEN_PREFERENCE="wp_pref_wpcom_access_token"; public static final String WPCOM_USERNAME_PREFERENCE="wp_pref_wpcom_username"; - public static final String WPCOM_PASSWORD_PREFERENCE="wp_pref_wpcom_password"; public static String versionName; public static Blog currentBlog; @@ -94,6 +94,7 @@ public class WordPress extends Application { public static final String BROADCAST_ACTION_XMLRPC_INVALID_SSL_CERTIFICATE = "INVALID_SSL_CERTIFICATE"; public static final String BROADCAST_ACTION_XMLRPC_TWO_FA_AUTH = "TWO_FA_AUTH"; public static final String BROADCAST_ACTION_XMLRPC_LOGIN_LIMIT = "LOGIN_LIMIT"; + public static final String BROADCAST_ACTION_REST_API_UNAUTHORIZED = "REST_API_UNAUTHORIZED"; public static final String BROADCAST_ACTION_BLOG_LIST_CHANGED = "BLOG_LIST_CHANGED"; private static final int SECONDS_BETWEEN_STATS_UPDATE = 30 * 60; @@ -125,7 +126,9 @@ public class WordPress extends Application { */ public static RateLimitedTask sUpdateWordPressComBlogList = new RateLimitedTask(SECONDS_BETWEEN_BLOGLIST_UPDATE) { protected boolean run() { - new GenericUpdateBlogListTask(getContext()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + if (getContext() != null && isSignedIn(getContext())) { + new GenericUpdateBlogListTask(getContext()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } return true; } }; @@ -218,7 +221,6 @@ public class WordPress extends Application { SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit(); currentBlog = null; editor.remove(WordPress.WPCOM_USERNAME_PREFERENCE); - editor.remove(WordPress.WPCOM_PASSWORD_PREFERENCE); editor.remove(WordPress.ACCESS_TOKEN_PREFERENCE); editor.commit(); if (wpDB != null) { @@ -257,15 +259,24 @@ public class WordPress extends Application { public static RestClientUtils getRestClientUtils() { if (mRestClientUtils == null) { OAuthAuthenticator authenticator = OAuthAuthenticatorFactory.instantiate(); - mRestClientUtils = new RestClientUtils(requestQueue, authenticator); + mRestClientUtils = new RestClientUtils(requestQueue, authenticator, mOnAuthFailedListener); } return mRestClientUtils; } + private static RestRequest.OnAuthFailedListener mOnAuthFailedListener = new RestRequest.OnAuthFailedListener() { + @Override + public void onAuthFailed() { + if (getContext() == null) return; + // If this is called, it means the WP.com token is no longer valid. + sendLocalBroadcast(getContext(), BROADCAST_ACTION_REST_API_UNAUTHORIZED); + } + }; + public static RestClientUtils getRestClientUtilsV1_1() { if (mRestClientUtilsVersion1_1 == null) { OAuthAuthenticator authenticator = OAuthAuthenticatorFactory.instantiate(); - mRestClientUtilsVersion1_1 = new RestClientUtils(requestQueue, authenticator, RestClient.REST_CLIENT_VERSIONS.V1_1); + mRestClientUtilsVersion1_1 = new RestClientUtils(requestQueue, authenticator, mOnAuthFailedListener, RestClient.REST_CLIENT_VERSIONS.V1_1); } return mRestClientUtilsVersion1_1; } @@ -335,7 +346,7 @@ public class WordPress extends Application { String regId = gcmRegisterIfNot(context); // Register to WordPress.com notifications - if (WordPress.hasValidWPComCredentials(context)) { + if (WordPress.hasDotComToken(context)) { if (!TextUtils.isEmpty(regId)) { // Send the token to WP.com in case it was invalidated NotificationsUtils.registerDeviceForPushNotifications(context, regId); @@ -418,8 +429,7 @@ public class WordPress extends Application { */ public static Blog getBlog(int id) { try { - Blog blog = wpDB.instantiateBlogByLocalId(id); - return blog; + return wpDB.instantiateBlogByLocalId(id); } catch (Exception e) { return null; } @@ -475,22 +485,29 @@ public class WordPress extends Application { * * @return true if we have credentials or false if not */ - public static boolean hasValidWPComCredentials(Context context) { + public static boolean hasDotComToken(Context context) { + if (context == null) return false; + + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); + return !TextUtils.isEmpty(settings.getString(ACCESS_TOKEN_PREFERENCE, null)); + } + + public static String getDotComToken(Context context) { + if (context == null) return null; + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); - String username = settings.getString(WPCOM_USERNAME_PREFERENCE, null); - String password = settings.getString(WPCOM_PASSWORD_PREFERENCE, null); - return username != null && password != null; + return settings.getString(ACCESS_TOKEN_PREFERENCE, null); } public static boolean isSignedIn(Context context) { - if (WordPress.hasValidWPComCredentials(context)) { + if (WordPress.hasDotComToken(context)) { return true; } return WordPress.wpDB.getNumVisibleAccounts() != 0; } public static String getLoggedInUsername(Context context, Blog blog) { - if (hasValidWPComCredentials(context)) { + if (hasDotComToken(context)) { SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); return settings.getString(WPCOM_USERNAME_PREFERENCE, null); } else if (blog != null) { @@ -607,7 +624,6 @@ public class WordPress extends Application { SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit(); editor.remove(WordPress.WPCOM_USERNAME_PREFERENCE); - editor.remove(WordPress.WPCOM_PASSWORD_PREFERENCE); editor.remove(WordPress.ACCESS_TOKEN_PREFERENCE); editor.commit(); @@ -755,7 +771,7 @@ public class WordPress extends Application { */ private void updatePushNotificationTokenIfNotLimited() { // Synch Push Notifications settings - if (isPushNotificationPingNeeded() && WordPress.hasValidWPComCredentials(mContext)) { + if (isPushNotificationPingNeeded() && WordPress.hasDotComToken(mContext)) { String token = null; try { // Register for Google Cloud Messaging diff --git a/WordPress/src/main/java/org/wordpress/android/WordPressDB.java b/WordPress/src/main/java/org/wordpress/android/WordPressDB.java index 36d653d00..502ca1119 100644 --- a/WordPress/src/main/java/org/wordpress/android/WordPressDB.java +++ b/WordPress/src/main/java/org/wordpress/android/WordPressDB.java @@ -51,7 +51,7 @@ import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; public class WordPressDB { - private static final int DATABASE_VERSION = 28; + private static final int DATABASE_VERSION = 29; private static final String CREATE_TABLE_SETTINGS = "create table if not exists accounts (id integer primary key autoincrement, " + "url text, blogName text, username text, password text, imagePlacement text, centerThumbnail boolean, fullSizeImage boolean, maxImageWidth text, maxImageWidthId integer);"; @@ -253,7 +253,12 @@ public class WordPressDB { // Add isUploading column to POSTS db.execSQL(ADD_IS_UPLOADING); currentVersion++; + case 28: + // Remove WordPress.com credentials + removeDotComCredentials(); + currentVersion++; } + db.setVersion(DATABASE_VERSION); } @@ -266,17 +271,15 @@ public class WordPressDB { } private void migrateWPComAccount() { - Cursor c = db.query(SETTINGS_TABLE, new String[] { "username", "password" }, "dotcomFlag=1", null, null, + Cursor c = db.query(SETTINGS_TABLE, new String[] { "username" }, "dotcomFlag=1", null, null, null, null); if (c.getCount() > 0) { c.moveToFirst(); String username = c.getString(0); - String password = c.getString(1); SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this.context); SharedPreferences.Editor editor = settings.edit(); editor.putString(WordPress.WPCOM_USERNAME_PREFERENCE, username); - editor.putString(WordPress.WPCOM_PASSWORD_PREFERENCE, password); editor.commit(); } @@ -336,7 +339,7 @@ public class WordPressDB { if (limit != 0) { limitStr = String.valueOf(limit); } - String[] baseFields = new String[]{"id", "blogName", "username", "blogId", "url", "password"}; + String[] baseFields = new String[]{"id", "blogName", "username", "blogId", "url"}; String[] allFields = baseFields; if (extraFields != null) { allFields = (String[]) ArrayUtils.addAll(baseFields, extraFields); @@ -351,17 +354,17 @@ public class WordPressDB { String username = c.getString(2); int blogId = c.getInt(3); String url = c.getString(4); - String password = c.getString(5); - if (password != null && !password.equals("") && id > 0) { + if (id > 0) { Map<String, Object> thisHash = new HashMap<String, Object>(); thisHash.put("id", id); thisHash.put("blogName", blogName); thisHash.put("username", username); thisHash.put("blogId", blogId); thisHash.put("url", url); + int extraFieldsIndex = baseFields.length; if (extraFields != null) { for (int j = 0; j < extraFields.length; ++j) { - thisHash.put(extraFields[j], c.getString(6 + j)); + thisHash.put(extraFields[j], c.getString(extraFieldsIndex + j)); } } accounts.add(thisHash); @@ -389,6 +392,28 @@ public class WordPressDB { return SqlUtils.intForQuery(db, "SELECT COUNT(*) FROM " + SETTINGS_TABLE + " WHERE dotcomFlag = 1", null); } + // Removes stored DotCom credentials. As of March 2015 only the OAuth token is used + private void removeDotComCredentials() { + // First clear out the password for all WP.com sites + ContentValues dotComValues = new ContentValues(); + dotComValues.put("password", ""); + db.update(SETTINGS_TABLE, dotComValues, "dotcomFlag=1", null); + + // Next, we'll clear out the credentials stored for Jetpack sites + ContentValues jetPackValues = new ContentValues(); + jetPackValues.put("dotcom_username", ""); + jetPackValues.put("dotcom_password", ""); + db.update(SETTINGS_TABLE, jetPackValues, null, null); + + // Lastly we'll remove the preference that previously stored the WP.com password + if (this.context != null) { + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this.context); + SharedPreferences.Editor editor = settings.edit(); + editor.remove("wp_pref_wpcom_password"); + editor.apply(); + } + } + public List<Map<String, Object>> getAllAccounts() { return getAccountsBy(null, null); } @@ -396,7 +421,7 @@ public class WordPressDB { public int setAllDotComAccountsVisibility(boolean visible) { ContentValues values = new ContentValues(); values.put("isHidden", !visible); - return db.update(SETTINGS_TABLE, values, "dotcomFlag = 1", null); + return db.update(SETTINGS_TABLE, values, "dotcomFlag=1", null); } public int setDotComAccountsVisibility(int id, boolean visible) { diff --git a/WordPress/src/main/java/org/wordpress/android/analytics/AnalyticsTrackerMixpanel.java b/WordPress/src/main/java/org/wordpress/android/analytics/AnalyticsTrackerMixpanel.java index a7b0c29f5..6213ae6ba 100644 --- a/WordPress/src/main/java/org/wordpress/android/analytics/AnalyticsTrackerMixpanel.java +++ b/WordPress/src/main/java/org/wordpress/android/analytics/AnalyticsTrackerMixpanel.java @@ -207,7 +207,7 @@ public class AnalyticsTrackerMixpanel implements AnalyticsTracker.Tracker { // Register super properties SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(WordPress.getContext()); int sessionCount = preferences.getInt(SESSION_COUNT, 0); - boolean connected = WordPress.hasValidWPComCredentials(WordPress.getContext()); + boolean connected = WordPress.hasDotComToken(WordPress.getContext()); boolean jetpackUser = WordPress.wpDB.hasAnyJetpackBlogs(); int numBlogs = WordPress.wpDB.getVisibleAccounts().size(); try { diff --git a/WordPress/src/main/java/org/wordpress/android/models/Blog.java b/WordPress/src/main/java/org/wordpress/android/models/Blog.java index c9832227d..05a071f36 100644 --- a/WordPress/src/main/java/org/wordpress/android/models/Blog.java +++ b/WordPress/src/main/java/org/wordpress/android/models/Blog.java @@ -132,7 +132,7 @@ public class Blog { } public String getUsername() { - return username; + return StringUtils.notNullStr(username); } public void setUsername(String username) { @@ -140,7 +140,7 @@ public class Blog { } public String getPassword() { - return password; + return StringUtils.notNullStr(password); } public void setPassword(String password) { diff --git a/WordPress/src/main/java/org/wordpress/android/networking/OAuthAuthenticator.java b/WordPress/src/main/java/org/wordpress/android/networking/OAuthAuthenticator.java index 7144f3117..4dbe7475b 100644 --- a/WordPress/src/main/java/org/wordpress/android/networking/OAuthAuthenticator.java +++ b/WordPress/src/main/java/org/wordpress/android/networking/OAuthAuthenticator.java @@ -1,134 +1,34 @@ package org.wordpress.android.networking; -import android.annotation.SuppressLint; import android.content.SharedPreferences; import android.preference.PreferenceManager; -import com.android.volley.Request; -import com.android.volley.VolleyError; -import com.wordpress.rest.Oauth; - -import org.wordpress.android.BuildConfig; import org.wordpress.android.WordPress; -import org.wordpress.android.WordPressDB; import org.wordpress.android.models.Blog; -import org.wordpress.android.ui.notifications.utils.SimperiumUtils; +import org.wordpress.android.util.StringUtils; public class OAuthAuthenticator implements Authenticator { @Override public void authenticate(final AuthenticatorRequest request) { String siteId = request.getSiteId(); - String token = null; - Blog blog = null; SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(WordPress.getContext()); - if (siteId == null) { - // Use the global access token - token = settings.getString(WordPress.ACCESS_TOKEN_PREFERENCE, null); - } else { - blog = WordPress.wpDB.getBlogForDotComBlogId(siteId); + String token = settings.getString(WordPress.ACCESS_TOKEN_PREFERENCE, null); - if (blog != null) { - // get the access token from api key field. Jetpack blogs linked with a different wpcom - // account have the token stored here. - token = blog.getApi_key(); + if (siteId != null) { + // Get the token for a Jetpack site if needed + Blog blog = WordPress.wpDB.getBlogForDotComBlogId(siteId); - // valid oauth tokens are 64 chars - if (token != null && token.length() < 64 && !blog.isDotcomFlag()) { - token = null; - } + if (blog != null) { + String jetpackToken = blog.getApi_key(); - // if there is no access token, we need to check if it is a dotcom blog, or a jetpack - // blog linked with the main wpcom account. - if (token == null) { - if (blog.isDotcomFlag() && blog.getUsername().equals(settings.getString( - WordPress.WPCOM_USERNAME_PREFERENCE, ""))) { - token = settings.getString(WordPress.ACCESS_TOKEN_PREFERENCE, null); - } else if (blog.isJetpackPowered()) { - if (blog.getDotcom_username() == null || blog.getDotcom_username().equals(settings.getString( - WordPress.WPCOM_USERNAME_PREFERENCE, ""))) { - token = settings.getString(WordPress.ACCESS_TOKEN_PREFERENCE, null); - } - } + // valid OAuth tokens are 64 chars + if (jetpackToken != null && jetpackToken.length() == 64 && !blog.isDotcomFlag()) { + token = jetpackToken; } } } - if (token != null) { - // we have an access token, set the request and send it - request.sendWithAccessToken(token); - } else { - // we don't have an access token, let's request one - requestAccessToken(request, blog); - } - } - /** - * Create an OAuth Request with default listeners - * - * @param username must be set - * @param password must be set - * @param request request that will be sent after authentication, can be null if we just want to authenticate - * @param blog concerned blog associated with a wpcom account, can be null - * @return a com.android.volley.Request that can be sent to a REST queue - */ - private Request makeRequest(final String username, final String password, final AuthenticatorRequest request, - final Blog blog) { - final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(WordPress.getContext()); - Oauth oauth = new Oauth(BuildConfig.OAUTH_APP_ID, BuildConfig.OAUTH_APP_SECRET, BuildConfig.OAUTH_REDIRECT_URI); - Request oauthRequest; - oauthRequest = oauth.makeRequest(username, password, new Oauth.Listener() { - @SuppressLint("CommitPrefEdits") - @Override - public void onResponse(Oauth.Token token) { - if (blog == null) { - settings.edit().putString(WordPress.ACCESS_TOKEN_PREFERENCE, token.toString()).commit(); - } else { - blog.setApi_key(token.toString()); - WordPress.wpDB.saveBlog(blog); - } - - // Once we have a token, start up Simperium - SimperiumUtils.configureSimperium(WordPress.getContext(), token.toString()); - if (request != null) { - request.sendWithAccessToken(token); - } - } - }, - - new Oauth.ErrorListener() { - @Override - public void onErrorResponse(VolleyError error) { - if (request != null) { - request.abort(error); - } - } - }); - return oauthRequest; - } - - public void requestAccessToken(final AuthenticatorRequest request, final Blog blog) { - String username; - String password; - final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(WordPress.getContext()); - if (blog == null) { - // We weren't give a specific blog, so we're going to user the username/password - // from the "global" dotcom user account - username = settings.getString(WordPress.WPCOM_USERNAME_PREFERENCE, null); - password = WordPressDB.decryptPassword(settings.getString(WordPress.WPCOM_PASSWORD_PREFERENCE, null)); - } else { - // use the requested blog's username password, if it's a dotcom blog, use the - // username and password for the blog. If it's a jetpack blog (not isDotcomFlag) - // then use the getDotcom_* methods for username/password - if (blog.isDotcomFlag()) { - username = blog.getUsername(); - password = blog.getPassword(); - } else { - username = blog.getDotcom_username(); - password = blog.getDotcom_password(); - } - } - Request oauthRequest = makeRequest(username, password, request, blog); - // add oauth request to the request queue - WordPress.requestQueue.add(oauthRequest); + request.sendWithAccessToken(StringUtils.notNullStr(token)); } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/DashboardActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/DashboardActivity.java deleted file mode 100644 index fbe0eefce..000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/DashboardActivity.java +++ /dev/null @@ -1,175 +0,0 @@ - -package org.wordpress.android.ui; - -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.support.v7.app.ActionBar; -import android.support.v7.app.ActionBarActivity; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.webkit.WebSettings; -import android.webkit.WebView; -import android.widget.ProgressBar; -import android.widget.Toast; - -import org.wordpress.android.R; -import org.wordpress.android.WordPress; -import org.wordpress.android.models.Blog; -import org.wordpress.android.util.AppLog; -import org.wordpress.android.util.AppLog.T; -import org.wordpress.android.util.WPWebChromeClient; -import org.wordpress.android.util.WPWebViewClient; -import org.wordpress.passcodelock.AppLockManager; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; - -/** - * Basic activity for displaying a WebView. - */ -public class DashboardActivity extends ActionBarActivity { - /** Primary webview used to display content. */ - private WebView mWebView; - - /** - * Blog for which this activity is loading content. - */ - private Blog mBlog; - - @Override - public void onCreate(Bundle savedInstanceState) { - supportRequestWindowFeature(Window.FEATURE_PROGRESS); - - super.onCreate(savedInstanceState); - - setContentView(R.layout.webview); - - ActionBar actionBar = getSupportActionBar(); - setTitle(R.string.view_admin); - if (actionBar != null) { - actionBar.setDisplayHomeAsUpEnabled(true); - actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); - actionBar.setDisplayShowTitleEnabled(true); - } - - mWebView = (WebView) findViewById(R.id.webView); - mWebView.getSettings().setUserAgentString(WordPress.getUserAgent()); - mWebView.getSettings().setJavaScriptEnabled(true); - mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY); - - Bundle extras = getIntent().getExtras(); - if (extras != null && extras.containsKey("blogID")) { - mBlog = WordPress.wpDB.instantiateBlogByLocalId(extras.getInt("blogID", -1)); - if (mBlog == null) { - mBlog = WordPress.getCurrentBlog(); - } - } - - if (mBlog == null) { - Toast.makeText(this, getResources().getText(R.string.blog_not_found), - Toast.LENGTH_SHORT).show(); - finish(); - } - - mWebView.setWebViewClient(new WPWebViewClient(mBlog)); - mWebView.setWebChromeClient(new WPWebChromeClient(this, (ProgressBar) findViewById(R.id.progress_bar))); - - mWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE); - mWebView.getSettings().setSavePassword(false); - - loadDashboard(); - } - - - private void loadDashboard() { - String dashboardUrl = mBlog.getAdminUrl(); - loadAuthenticatedUrl(dashboardUrl); - } - - /** - * Load the specified URL in the webview. - * - * @param url URL to load in the webview. - */ - protected void loadUrl(String url) { - mWebView.loadUrl(url); - } - - @Override - public void onBackPressed() { - if (mWebView != null && mWebView.canGoBack()) - mWebView.goBack(); - else - super.onBackPressed(); - } - - /** - * Get the URL of the WordPress login page. - * - * @return URL of the login page. - */ - String getLoginUrl() { - if (mBlog.getUrl().lastIndexOf("/") != -1) { - return mBlog.getUrl().substring(0, mBlog.getUrl().lastIndexOf("/")) - + "/wp-login.php"; - } else { - return mBlog.getUrl().replace("xmlrpc.php", "wp-login.php"); - } - } - - /** - * Login to the WordPress blog and load the specified URL. - * - * @param url URL to be loaded in the webview. - */ - void loadAuthenticatedUrl(String url) { - try { - String postData = String.format("log=%s&pwd=%s&redirect_to=%s", - URLEncoder.encode(mBlog.getUsername(), "UTF-8"), URLEncoder.encode(mBlog.getPassword(), "UTF-8"), - URLEncoder.encode(url, "UTF-8")); - mWebView.postUrl(getLoginUrl(), postData.getBytes()); - } catch (UnsupportedEncodingException e) { - AppLog.e(T.POSTS, e); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.dashboard, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(final MenuItem item) { - if (mWebView == null) - return false; - - int itemID = item.getItemId(); - if (itemID == R.id.menu_refresh) { - mWebView.reload(); - return true; - } else if (itemID == R.id.menu_browser) { - String url = mWebView.getUrl(); - if (url != null) { - Uri uri = Uri.parse(url); - if (uri != null) { - Intent i = new Intent(Intent.ACTION_VIEW); - i.setData(uri); - startActivity(i); - AppLockManager.getInstance().setExtendedTimeout(); - } - } - return true; - } else if (itemID == android.R.id.home) { - finish(); - } - - return super.onOptionsItemSelected(item); - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/DeepLinkingIntentReceiverActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/DeepLinkingIntentReceiverActivity.java index 9be19e626..fec14fa53 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/DeepLinkingIntentReceiverActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/DeepLinkingIntentReceiverActivity.java @@ -41,7 +41,7 @@ public class DeepLinkingIntentReceiverActivity extends ActionBarActivity { // if user is logged in, show the post right away - otherwise show welcome activity // and then show the post once the user has logged in - if (WordPress.hasValidWPComCredentials(this)) { + if (WordPress.hasDotComToken(this)) { showPost(); } else { Intent intent = new Intent(this, SignInActivity.class); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/DrawerItems.java b/WordPress/src/main/java/org/wordpress/android/ui/DrawerItems.java index 595f22dca..e99215fb6 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/DrawerItems.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/DrawerItems.java @@ -224,9 +224,9 @@ public class DrawerItems { boolean isVisible() { switch (mItemId) { case READER: - return WordPress.hasValidWPComCredentials(WordPress.getContext()); + return WordPress.hasDotComToken(WordPress.getContext()); case NOTIFICATIONS: - return WordPress.hasValidWPComCredentials(WordPress.getContext()); + return WordPress.hasDotComToken(WordPress.getContext()); case POSTS: return WordPress.wpDB.getNumVisibleAccounts() != 0; case MEDIA: diff --git a/WordPress/src/main/java/org/wordpress/android/ui/ViewSiteActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/ViewSiteActivity.java index 2567cb33d..b6002385e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/ViewSiteActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/ViewSiteActivity.java @@ -79,14 +79,14 @@ public class ViewSiteActivity extends WPDrawerActivity { } // Login to the blog and load the specified URL. - try { - String postData = String.format("log=%s&pwd=%s&redirect_to=%s", - URLEncoder.encode(mBlog.getUsername(), "UTF-8"), URLEncoder.encode(mBlog.getPassword(), "UTF-8"), - URLEncoder.encode(siteURL, "UTF-8")); - mWebView.postUrl(WPWebViewActivity.getBlogLoginUrl(mBlog), postData.getBytes()); - } catch (UnsupportedEncodingException e) { - AppLog.e(AppLog.T.UTILS, e); - } + String authenticationUrl = WPWebViewActivity.getBlogLoginUrl(mBlog); + + String postData = WPWebViewActivity.getAuthenticationPostData( + authenticationUrl, siteURL, mBlog.getUsername(), mBlog.getPassword(), + WordPress.getDotComToken(this) + ); + + mWebView.postUrl(authenticationUrl, postData.getBytes()); } @Override diff --git a/WordPress/src/main/java/org/wordpress/android/ui/WPDrawerActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/WPDrawerActivity.java index c9dcc88a2..aae0b5572 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/WPDrawerActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/WPDrawerActivity.java @@ -780,6 +780,7 @@ public abstract class WPDrawerActivity extends ActionBarActivity { filter.addAction(WordPress.BROADCAST_ACTION_XMLRPC_INVALID_CREDENTIALS); filter.addAction(WordPress.BROADCAST_ACTION_XMLRPC_INVALID_SSL_CERTIFICATE); filter.addAction(WordPress.BROADCAST_ACTION_XMLRPC_LOGIN_LIMIT); + filter.addAction(WordPress.BROADCAST_ACTION_REST_API_UNAUTHORIZED); filter.addAction(WordPress.BROADCAST_ACTION_BLOG_LIST_CHANGED); LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); lbm.registerReceiver(mReceiver, filter); @@ -799,27 +800,36 @@ public abstract class WPDrawerActivity extends ActionBarActivity { public void onReceive(Context context, Intent intent) { if (intent == null || intent.getAction() == null) return; + if (intent.getAction().equals(WordPress.BROADCAST_ACTION_SIGNOUT)) { onSignout(); + return; } - if (intent.getAction().equals(WordPress.BROADCAST_ACTION_XMLRPC_INVALID_CREDENTIALS)) { - AuthenticationDialogUtils.showAuthErrorDialog(WPDrawerActivity.this); + + if (intent.getAction().equals(WordPress.BROADCAST_ACTION_XMLRPC_INVALID_CREDENTIALS) + || intent.getAction().equals(WordPress.BROADCAST_ACTION_REST_API_UNAUTHORIZED) + || intent.getAction().equals(WordPress.BROADCAST_ACTION_XMLRPC_TWO_FA_AUTH)) { + AuthenticationDialogUtils.showAuthErrorView(WPDrawerActivity.this); + return; } + if (intent.getAction().equals(SimperiumUtils.BROADCAST_ACTION_SIMPERIUM_NOT_AUTHORIZED) && WPDrawerActivity.this instanceof NotificationsActivity) { - AuthenticationDialogUtils.showAuthErrorDialog(WPDrawerActivity.this, R.string.sign_in_again, + AuthenticationDialogUtils.showAuthErrorView(WPDrawerActivity.this, R.string.sign_in_again, R.string.simperium_connection_error); + return; } - if (intent.getAction().equals(WordPress.BROADCAST_ACTION_XMLRPC_TWO_FA_AUTH)) { - // TODO: add a specific message like "you must use a specific app password" - AuthenticationDialogUtils.showAuthErrorDialog(WPDrawerActivity.this); - } + if (intent.getAction().equals(WordPress.BROADCAST_ACTION_XMLRPC_INVALID_SSL_CERTIFICATE)) { SelfSignedSSLCertsManager.askForSslTrust(WPDrawerActivity.this, null); + return; } + if (intent.getAction().equals(WordPress.BROADCAST_ACTION_XMLRPC_LOGIN_LIMIT)) { ToastUtils.showToast(context, R.string.limit_reached, Duration.LONG); + return; } + if (intent.getAction().equals(WordPress.BROADCAST_ACTION_BLOG_LIST_CHANGED)) { initBlogSpinner(); } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/WPWebViewActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/WPWebViewActivity.java index ac2b98334..648917d00 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/WPWebViewActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/WPWebViewActivity.java @@ -18,11 +18,13 @@ import android.widget.Toast; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import org.w3c.dom.Text; import org.wordpress.android.R; import org.wordpress.android.WordPress; import org.wordpress.android.WordPressDB; import org.wordpress.android.models.Blog; import org.wordpress.android.util.AppLog; +import org.wordpress.android.util.StringUtils; import org.wordpress.android.util.UrlUtils; import org.wordpress.android.util.WPWebChromeClient; import org.wordpress.android.util.WPWebViewClient; @@ -73,23 +75,10 @@ public class WPWebViewActivity extends WebViewActivity { public static final String WPCOM_LOGIN_URL = "https://wordpress.com/wp-login.php"; public static final String LOCAL_BLOG_ID = "local_blog_id"; - public static void openUrlByUsingMainWPCOMCredentials(Context context, String url) { - if (context == null) { - AppLog.e(AppLog.T.UTILS, "Context is null in openUrlByUsingMainWPCOMCredentials!"); - return; - } - - SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); - String authenticatedUser = settings.getString(WordPress.WPCOM_USERNAME_PREFERENCE, null); - String authenticatedPassword = WordPressDB.decryptPassword( - settings.getString(WordPress.WPCOM_PASSWORD_PREFERENCE, null) - ); + private static final String ENCODING_UTF8 = "UTF-8"; - openWPCOMURL(context, url, authenticatedUser, authenticatedPassword); - } - - public static void openUrlByUsingWPCOMCredentials(Context context, String url, String user, String password) { - openWPCOMURL(context, url, user, password); + public static void openUrlByUsingWPCOMCredentials(Context context, String url, String user) { + openWPCOMURL(context, url, user); } public static void openUrlByUsingBlogCredentials(Context context, Blog blog, String url) { @@ -138,7 +127,7 @@ public class WPWebViewActivity extends WebViewActivity { context.startActivity(intent); } - private static void openWPCOMURL(Context context, String url, String user, String password) { + private static void openWPCOMURL(Context context, String url, String user) { if (context == null) { AppLog.e(AppLog.T.UTILS, "Context is null!!!"); return; @@ -151,14 +140,13 @@ public class WPWebViewActivity extends WebViewActivity { return; } - if (TextUtils.isEmpty(user) || TextUtils.isEmpty(password)) { - AppLog.e(AppLog.T.UTILS, "Username and/or password empty/null!!!"); + if (TextUtils.isEmpty(user)) { + AppLog.e(AppLog.T.UTILS, "Username empty/null!!!"); return; } Intent intent = new Intent(context, WPWebViewActivity.class); intent.putExtra(WPWebViewActivity.AUTHENTICATION_USER, user); - intent.putExtra(WPWebViewActivity.AUTHENTICATION_PASSWD, password); intent.putExtra(WPWebViewActivity.URL_TO_LOAD, url); intent.putExtra(WPWebViewActivity.AUTHENTICATION_URL, WPCOM_LOGIN_URL); context.startActivity(intent); @@ -213,12 +201,12 @@ public class WPWebViewActivity extends WebViewActivity { finish(); } - if (TextUtils.isEmpty(username) || TextUtils.isEmpty(password)) { - AppLog.e(AppLog.T.UTILS, "Username and/or password empty/null!!!"); - Toast.makeText(this, getText(R.string.incorrect_credentials), - Toast.LENGTH_SHORT).show(); + if (TextUtils.isEmpty(username)) { + AppLog.e(AppLog.T.UTILS, "Username empty/null!!!"); + Toast.makeText(this, getText(R.string.incorrect_credentials), Toast.LENGTH_SHORT).show(); finish(); } + this.loadAuthenticatedUrl(authURL, addressToLoad, username, password); } } @@ -227,15 +215,33 @@ public class WPWebViewActivity extends WebViewActivity { * Login to the WordPress.com and load the specified URL. * */ - protected void loadAuthenticatedUrl(String authenticationURL, String urlToLoad, String username, String passwd) { + protected void loadAuthenticatedUrl(String authenticationURL, String urlToLoad, String username, String password) { + String postData = getAuthenticationPostData(authenticationURL, urlToLoad, username, password, WordPress.getDotComToken(this)); + + mWebView.postUrl(authenticationURL, postData.getBytes()); + } + + public static String getAuthenticationPostData(String authenticationUrl, String urlToLoad, String username, String password, String token) { + if (TextUtils.isEmpty(authenticationUrl)) return ""; + try { String postData = String.format("log=%s&pwd=%s&redirect_to=%s", - URLEncoder.encode(username, "UTF-8"), URLEncoder.encode(passwd, "UTF-8"), - URLEncoder.encode(urlToLoad, "UTF-8")); - mWebView.postUrl(authenticationURL, postData.getBytes()); + URLEncoder.encode(StringUtils.notNullStr(username), ENCODING_UTF8), + URLEncoder.encode(StringUtils.notNullStr(password), ENCODING_UTF8), + URLEncoder.encode(StringUtils.notNullStr(urlToLoad), ENCODING_UTF8) + ); + + // Add token authorization when signing in to WP.com + if (authenticationUrl.contains("wordpress.com/wp-login.php") && !TextUtils.isEmpty(token)) { + postData += "&authorization=Bearer " + URLEncoder.encode(token, ENCODING_UTF8); + } + + return postData; } catch (UnsupportedEncodingException e) { AppLog.e(AppLog.T.UTILS, e); } + + return ""; } /** diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/AbstractFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/AbstractFragment.java index dafd4260d..8e5523a7e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/AbstractFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/AbstractFragment.java @@ -49,7 +49,7 @@ public abstract class AbstractFragment extends Fragment { protected RestClientUtils getRestClientUtils() { if (mRestClientUtils == null) { - mRestClientUtils = new RestClientUtils(requestQueue, null); + mRestClientUtils = new RestClientUtils(requestQueue, null, null); } return mRestClientUtils; } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/BlogUtils.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/BlogUtils.java index 9ba35adbf..eb4195405 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/BlogUtils.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/BlogUtils.java @@ -26,14 +26,13 @@ public class BlogUtils { * * @return true if a change has been made (new blog added, old blog updated, blog deleted). */ - public static boolean syncBlogs(Context context, List<Map<String, Object>> newBlogList, String username, - String password, String httpUsername, String httpPassword) { + public static boolean syncBlogs(Context context, List<Map<String, Object>> newBlogList, String username) { boolean retValue; // Add all blogs from blogList - retValue = addBlogs(newBlogList, username, password, httpUsername, httpPassword); + retValue = addBlogs(newBlogList, username); - // Delete blogs if not in bloegList + // Delete blogs if not in blogList List<Map<String, Object>> allBlogs = WordPress.wpDB.getAccountsBy("dotcomFlag=1", null); Set<String> newBlogURLs = new HashSet<String>(); for (Map<String, Object> blog : newBlogList) { @@ -76,7 +75,6 @@ public class BlogUtils { * Check xmlrpc urls validity * * @param blogList blog list - * @param xmlrpcUrl forced xmlrpc url * @return true if there is at least one invalid xmlrpc url */ public static boolean isAnyInvalidXmlrpcUrl(List<Map<String, Object>> blogList) { @@ -137,4 +135,8 @@ public class BlogUtils { return false; } } + + public static boolean addBlogs(List<Map<String, Object>> userBlogList, String username) { + return addBlogs(userBlogList, username, null, null, null); + } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/NewAccountActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/NewAccountActivity.java index 1ca052fbd..9fdb6ae38 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/NewAccountActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/NewAccountActivity.java @@ -2,7 +2,6 @@ package org.wordpress.android.ui.accounts; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; -import android.view.Window; import org.wordpress.android.R; diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/NewBlogFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/NewBlogFragment.java index 1c034a108..f8e2fac1c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/NewBlogFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/NewBlogFragment.java @@ -201,9 +201,7 @@ public class NewBlogFragment extends AbstractFragment implements TextWatcher { String blogId = details.getString("blogid"); final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getActivity()); String username = settings.getString(WordPress.WPCOM_USERNAME_PREFERENCE, ""); - String password = WordPressDB.decryptPassword(settings.getString( - WordPress.WPCOM_PASSWORD_PREFERENCE, null)); - BlogUtils.addOrUpdateBlog(blogName, xmlRpcUrl, homeUrl, blogId, username, password, null, null, + BlogUtils.addOrUpdateBlog(blogName, xmlRpcUrl, homeUrl, blogId, username, null, null, null, true, true); ToastUtils.showToast(getActivity(), R.string.new_blog_wpcom_created); } catch (JSONException e) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/NewUserFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/NewUserFragment.java index da894d0a6..e054d3704 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/NewUserFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/NewUserFragment.java @@ -175,11 +175,12 @@ public class NewUserFragment extends AbstractFragment implements TextWatcher { return siteUrl; } - private void finishThisStuff(String username) { + private void finishThisStuff(String username, String password) { final Activity activity = getActivity(); if (activity != null) { Intent intent = new Intent(); intent.putExtra("username", username); + intent.putExtra("password", password); activity.setResult(NewAccountActivity.RESULT_OK, intent); activity.finish(); PersistentEditTextHelper persistentEditTextHelper = new PersistentEditTextHelper(getActivity()); @@ -283,7 +284,7 @@ public class NewUserFragment extends AbstractFragment implements TextWatcher { AnalyticsTracker.track(AnalyticsTracker.Stat.CREATED_ACCOUNT); endProgress(); if (isAdded()) { - finishThisStuff(username); + finishThisStuff(username, password); } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/SignInActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/SignInActivity.java index 0b5425615..e8de57293 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/SignInActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/SignInActivity.java @@ -8,14 +8,19 @@ import android.support.v7.app.ActionBarActivity; import android.view.Window; import org.wordpress.android.R; +import org.wordpress.android.WordPress; +import org.wordpress.android.models.Blog; import org.wordpress.android.ui.ActivityId; public class SignInActivity extends Activity { public static final int SIGN_IN_REQUEST = 1; + public static final int REQUEST_CODE = 5000; public static final int ADD_SELF_HOSTED_BLOG = 2; public static final int CREATE_ACCOUNT_REQUEST = 3; public static final int SHOW_CERT_DETAILS = 4; public static String START_FRAGMENT_KEY = "start-fragment"; + public static final String ARG_JETPACK_SITE_AUTH = "ARG_JETPACK_SITE_AUTH"; + public static final String ARG_IS_AUTH_ERROR = "ARG_IS_AUTH_ERROR"; private SignInFragment mSignInFragment; @@ -27,6 +32,7 @@ public class SignInActivity extends Activity { FragmentManager fragmentManager = getFragmentManager(); mSignInFragment = (SignInFragment) fragmentManager.findFragmentById(R.id.sign_in_fragment); actionMode(getIntent().getExtras()); + ActivityId.trackLastActivity(ActivityId.LOGIN); } @@ -34,6 +40,15 @@ public class SignInActivity extends Activity { int actionMode = SIGN_IN_REQUEST; if (extras != null) { actionMode = extras.getInt(START_FRAGMENT_KEY, -1); + + if (extras.containsKey(ARG_JETPACK_SITE_AUTH)) { + Blog jetpackBlog = WordPress.getBlog(extras.getInt(ARG_JETPACK_SITE_AUTH)); + if (jetpackBlog != null) { + mSignInFragment.setBlog(jetpackBlog); + } + } else if (extras.containsKey(ARG_IS_AUTH_ERROR)) { + mSignInFragment.showAuthErrorMessage(); + } } switch (actionMode) { case ADD_SELF_HOSTED_BLOG: @@ -42,6 +57,8 @@ public class SignInActivity extends Activity { default: break; } + + } @Override @@ -52,8 +69,9 @@ public class SignInActivity extends Activity { mSignInFragment.askForSslTrust(); } else if (resultCode == RESULT_OK && data != null) { String username = data.getStringExtra("username"); + String password = data.getStringExtra("password"); if (username != null) { - mSignInFragment.signInDotComUser(); + mSignInFragment.signInDotComUser(username, password); } } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/SignInFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/SignInFragment.java index f80b6821b..46c616fcc 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/SignInFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/SignInFragment.java @@ -5,13 +5,12 @@ import android.app.AlertDialog; import android.app.FragmentTransaction; import android.content.DialogInterface; import android.content.Intent; -import android.content.SharedPreferences; import android.content.res.Configuration; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; -import android.preference.PreferenceManager; import android.text.Editable; +import android.text.Html; import android.text.TextUtils; import android.text.TextWatcher; import android.util.Patterns; @@ -20,6 +19,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; +import android.view.inputmethod.EditorInfo; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; @@ -32,7 +32,6 @@ import org.json.JSONException; import org.json.JSONObject; import org.wordpress.android.R; import org.wordpress.android.WordPress; -import org.wordpress.android.WordPressDB; import org.wordpress.android.analytics.AnalyticsTracker; import org.wordpress.android.analytics.AnalyticsTracker.Stat; import org.wordpress.android.models.Blog; @@ -53,6 +52,7 @@ import org.wordpress.android.util.EditTextUtils; import org.wordpress.android.util.GenericCallback; import org.wordpress.android.util.NetworkUtils; import org.wordpress.android.util.StringUtils; +import org.wordpress.android.util.ToastUtils; import org.wordpress.android.widgets.WPTextView; import org.wordpress.emailchecker.EmailChecker; import org.xmlrpc.android.ApiHelper; @@ -69,30 +69,46 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { private static final String DOT_COM_BASE_URL = "https://wordpress.com"; private static final String FORGOT_PASSWORD_RELATIVE_URL = "/wp-login.php?action=lostpassword"; private static final int WPCOM_ERRONEOUS_LOGIN_THRESHOLD = 3; + private static final String FROM_LOGIN_SCREEN_KEY = "FROM_LOGIN_SCREEN_KEY"; + public static final String ENTERED_URL_KEY = "ENTERED_URL_KEY"; public static final String ENTERED_USERNAME_KEY = "ENTERED_USERNAME_KEY"; - public static final String FROM_LOGIN_SCREEN_KEY = "FROM_LOGIN_SCREEN_KEY"; + private EditText mUsernameEditText; private EditText mPasswordEditText; private EditText mUrlEditText; - private boolean mSelfHosted; + private EditText mTwoStepEditText; + private WPTextView mSignInButton; private WPTextView mCreateAccountButton; private WPTextView mAddSelfHostedButton; private WPTextView mProgressTextSignIn; private WPTextView mForgotPassword; + private WPTextView mJetpackAuthLabel; + private LinearLayout mBottomButtonsLayout; + private RelativeLayout mUsernameLayout; + private RelativeLayout mPasswordLayout; private RelativeLayout mProgressBarSignIn; private RelativeLayout mUrlButtonLayout; + private RelativeLayout mTwoStepLayout; + private LinearLayout mTwoStepFooter; + private ImageView mInfoButton; private ImageView mInfoButtonSecondary; - private EmailChecker mEmailChecker; + + private final EmailChecker mEmailChecker; + + private boolean mSelfHosted; private boolean mEmailAutoCorrected; + private boolean mShouldSendTwoStepSMS; private int mErroneousLogInCount; private String mUsername; private String mPassword; + private String mTwoStepCode; private String mHttpUsername; private String mHttpPassword; + private Blog mJetpackBlog; public SignInFragment() { mEmailChecker = new EmailChecker(); @@ -102,10 +118,20 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.signin_fragment, container, false); mUrlButtonLayout = (RelativeLayout) rootView.findViewById(R.id.url_button_layout); + mTwoStepLayout = (RelativeLayout) rootView.findViewById(R.id.two_factor_layout); + mTwoStepFooter = (LinearLayout) rootView.findViewById(R.id.two_step_footer); + mUsernameLayout = (RelativeLayout) rootView.findViewById(R.id.nux_username_layout); + mUsernameLayout.setOnClickListener(mOnLoginFormClickListener); + mPasswordLayout = (RelativeLayout) rootView.findViewById(R.id.nux_password_layout); + mPasswordLayout.setOnClickListener(mOnLoginFormClickListener); + mUsernameEditText = (EditText) rootView.findViewById(R.id.nux_username); mUsernameEditText.addTextChangedListener(this); + mUsernameEditText.setOnClickListener(mOnLoginFormClickListener); mPasswordEditText = (EditText) rootView.findViewById(R.id.nux_password); mPasswordEditText.addTextChangedListener(this); + mPasswordEditText.setOnClickListener(mOnLoginFormClickListener); + mJetpackAuthLabel = (WPTextView) rootView.findViewById(R.id.nux_jetpack_auth_label); mUrlEditText = (EditText) rootView.findViewById(R.id.nux_url); mSignInButton = (WPTextView) rootView.findViewById(R.id.nux_sign_in_button); mSignInButton.setOnClickListener(mSignInClickListener); @@ -128,6 +154,7 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { } } }); + mForgotPassword = (WPTextView) rootView.findViewById(R.id.forgot_password); mForgotPassword.setOnClickListener(mForgotPasswordListener); mUsernameEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() { @@ -137,8 +164,34 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { } } }); + mPasswordEditText.setOnEditorActionListener(mEditorAction); mUrlEditText.setOnEditorActionListener(mEditorAction); + + mTwoStepEditText = (EditText) rootView.findViewById(R.id.nux_two_step); + mTwoStepEditText.addTextChangedListener(this); + mTwoStepEditText.setOnKeyListener(new View.OnKeyListener() { + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || (keyCode == EditorInfo.IME_ACTION_DONE)) { + if (fieldsFilled()) { + signIn(); + } + } + + return false; + } + }); + + WPTextView twoStepFooterButton = (WPTextView) rootView.findViewById(R.id.two_step_footer_button); + twoStepFooterButton.setText(Html.fromHtml("<u>" + getString(R.string.two_step_footer_button) + "</u>")); + twoStepFooterButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + requestSMSTwoStepCode(); + } + }); + mBottomButtonsLayout = (LinearLayout) rootView.findViewById(R.id.nux_bottom_buttons); initPasswordVisibilityButton(rootView, mPasswordEditText); initInfoButtons(rootView); @@ -147,6 +200,16 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { return rootView; } + @Override + public void onResume() { + super.onResume(); + + // Ensure two-step form is shown if needed + if (!TextUtils.isEmpty(mTwoStepEditText.getText()) && mTwoStepLayout.getVisibility() == View.GONE) { + setTwoStepAuthVisibility(true); + } + } + /** * Hide toggle button "add self hosted / sign in with WordPress.com" and show self hosted URL * edit box @@ -201,6 +264,18 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { } } + private final OnClickListener mOnLoginFormClickListener = new OnClickListener() { + @Override + public void onClick(View v) { + // Don't change layout if we are performing a network operation + if (mProgressBarSignIn.getVisibility() == View.VISIBLE) return; + + if (mTwoStepLayout.getVisibility() == View.VISIBLE) { + setTwoStepAuthVisibility(false); + } + } + }; + private void autocorrectUsername() { if (mEmailAutoCorrected) { return; @@ -222,11 +297,27 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { } private boolean isWPComLogin() { - String selfHosteUrl = EditTextUtils.getText(mUrlEditText).trim(); - return !mSelfHosted || TextUtils.isEmpty(selfHosteUrl) || selfHosteUrl.contains("wordpress.com"); + String selfHostedUrl = EditTextUtils.getText(mUrlEditText).trim(); + return !mSelfHosted || TextUtils.isEmpty(selfHostedUrl) || selfHostedUrl.contains("wordpress.com"); } - private View.OnClickListener mCreateAccountListener = new View.OnClickListener() { + private boolean isJetpackAuth() { + return mJetpackBlog != null; + } + + // Set blog for Jetpack auth + public void setBlog(Blog blog) { + mJetpackBlog = blog; + + if (mAddSelfHostedButton != null) { + mJetpackAuthLabel.setVisibility(View.VISIBLE); + mAddSelfHostedButton.setVisibility(View.GONE); + mCreateAccountButton.setVisibility(View.GONE); + mUsernameEditText.setText(""); + } + } + + private final View.OnClickListener mCreateAccountListener = new View.OnClickListener() { @Override public void onClick(View v) { Intent newAccountIntent = new Intent(getActivity(), NewAccountActivity.class); @@ -249,7 +340,7 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { return baseUrl + FORGOT_PASSWORD_RELATIVE_URL; } - private View.OnClickListener mForgotPasswordListener = new View.OnClickListener() { + private final View.OnClickListener mForgotPasswordListener = new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(getForgotPasswordURL())); @@ -261,7 +352,7 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { signIn(); } - private TextView.OnEditorActionListener mEditorAction = new TextView.OnEditorActionListener() { + private final TextView.OnEditorActionListener mEditorAction = new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (mPasswordEditText == v) { @@ -327,11 +418,16 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { }); } - private Callback mFecthBlogListCallback = new Callback() { + private final Callback mFetchBlogListCallback = new Callback() { @Override public void onSuccess(final List<Map<String, Object>> userBlogList) { if (userBlogList != null) { - BlogUtils.addBlogs(userBlogList, mUsername, mPassword, mHttpUsername, mHttpPassword); + if (isWPComLogin()) { + BlogUtils.addBlogs(userBlogList, mUsername); + } else { + BlogUtils.addBlogs(userBlogList, mUsername, mPassword, mHttpUsername, mHttpPassword); + } + // refresh first blog refreshFirstBlogContent(); } @@ -358,7 +454,7 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { } @Override - public void onError(final int messageId, final boolean httpAuthRequired, + public void onError(final int messageId, final boolean twoStepCodeRequired, final boolean httpAuthRequired, final boolean erroneousSslCertificate, final String clientResponse) { if (!isAdded()) { return; @@ -366,6 +462,12 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { getActivity().runOnUiThread(new Runnable() { @Override public void run() { + if (twoStepCodeRequired) { + setTwoStepAuthVisibility(true); + endProgress(); + return; + } + if (erroneousSslCertificate) { askForSslTrust(); return; @@ -378,24 +480,64 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { signInError(messageId, clientResponse); return; } + endProgress(); } }); + + AnalyticsTracker.track(Stat.LOGIN_FAILED); } }; + public void showAuthErrorMessage() { + if (mJetpackAuthLabel != null) { + mJetpackAuthLabel.setVisibility(View.VISIBLE); + mJetpackAuthLabel.setText(getResources().getString(R.string.auth_required)); + } + } + + private void setTwoStepAuthVisibility(boolean isVisible) { + mTwoStepLayout.setVisibility(isVisible ? View.VISIBLE : View.GONE); + mTwoStepFooter.setVisibility(isVisible ? View.VISIBLE : View.GONE); + mSignInButton.setText(isVisible ? getString(R.string.verify) : getString(R.string.sign_in)); + mForgotPassword.setVisibility(isVisible ? View.GONE : View.VISIBLE); + mBottomButtonsLayout.setVisibility(isVisible ? View.GONE : View.VISIBLE); + mUsernameEditText.setFocusableInTouchMode(!isVisible); + mUsernameLayout.setAlpha(isVisible ? 0.6f : 1.0f); + mPasswordEditText.setFocusableInTouchMode(!isVisible); + mPasswordLayout.setAlpha(isVisible ? 0.6f : 1.0f); + + if (isVisible) { + mTwoStepEditText.requestFocus(); + mTwoStepEditText.setText(""); + } else { + mTwoStepEditText.setText(""); + mTwoStepEditText.clearFocus(); + } + } + private void signInAndFetchBlogListWPCom() { - LoginWPCom login = new LoginWPCom(mUsername, mPassword); + LoginWPCom login = new LoginWPCom(mUsername, mPassword, mTwoStepCode, mShouldSendTwoStepSMS, mJetpackBlog); login.execute(new LoginAbstract.Callback() { @Override public void onSuccess() { + mShouldSendTwoStepSMS = false; + + // Finish this activity if we've authenticated to a Jetpack site + if (isJetpackAuth() && getActivity() != null) { + getActivity().setResult(Activity.RESULT_OK); + getActivity().finish(); + return; + } + FetchBlogListWPCom fetchBlogListWPCom = new FetchBlogListWPCom(); - fetchBlogListWPCom.execute(mFecthBlogListCallback); + fetchBlogListWPCom.execute(mFetchBlogListCallback); } @Override - public void onError(int errorMessageId, boolean httpAuthRequired, boolean erroneousSslCertificate) { - mFecthBlogListCallback.onError(errorMessageId, httpAuthRequired, erroneousSslCertificate, ""); + public void onError(int errorMessageId, boolean twoStepCodeRequired, boolean httpAuthRequired, boolean erroneousSslCertificate) { + mFetchBlogListCallback.onError(errorMessageId, twoStepCodeRequired, httpAuthRequired, erroneousSslCertificate, ""); + mShouldSendTwoStepSMS = false; } }); } @@ -406,7 +548,7 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { if (mHttpUsername != null && mHttpPassword != null) { fetchBlogListWPOrg.setHttpCredentials(mHttpUsername, mHttpPassword); } - fetchBlogListWPOrg.execute(mFecthBlogListCallback); + fetchBlogListWPOrg.execute(mFetchBlogListCallback); } private boolean checkNetworkConnectivity() { @@ -435,6 +577,7 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { mUsername = EditTextUtils.getText(mUsernameEditText).trim(); mPassword = EditTextUtils.getText(mPasswordEditText).trim(); + mTwoStepCode = EditTextUtils.getText(mTwoStepEditText).trim(); if (isWPComLogin()) { startProgress(getString(R.string.connecting_wpcom)); signInAndFetchBlogListWPCom(); @@ -444,7 +587,17 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { } } - private OnClickListener mSignInClickListener = new OnClickListener() { + private void requestSMSTwoStepCode() { + if (!isAdded()) return; + + ToastUtils.showToast(getActivity(), R.string.two_step_sms_sent); + mTwoStepEditText.setText(""); + mShouldSendTwoStepSMS = true; + + signIn(); + } + + private final OnClickListener mSignInClickListener = new OnClickListener() { @Override public void onClick(View v) { signIn(); @@ -468,11 +621,13 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { } mPasswordEditText.setError(null); mUsernameEditText.setError(null); + mTwoStepEditText.setError(null); } private boolean fieldsFilled() { return EditTextUtils.getText(mUsernameEditText).trim().length() > 0 - && EditTextUtils.getText(mPasswordEditText).trim().length() > 0; + && EditTextUtils.getText(mPasswordEditText).trim().length() > 0 + && (mTwoStepLayout.getVisibility() == View.GONE || EditTextUtils.getText(mTwoStepEditText).trim().length() > 0); } protected boolean isUserDataValid() { @@ -494,10 +649,6 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { return retValue; } - private boolean selfHostedFieldsFilled() { - return fieldsFilled() && EditTextUtils.getText(mUrlEditText).trim().length() > 0; - } - private void showPasswordError(int messageId) { mPasswordEditText.setError(getString(messageId)); mPasswordEditText.requestFocus(); @@ -513,6 +664,11 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { mUrlEditText.requestFocus(); } + private void showTwoStepCodeError(int messageId) { + mTwoStepEditText.setError(getString(messageId)); + mTwoStepEditText.requestFocus(); + } + protected boolean specificShowError(int messageId) { switch (getErrorType(messageId)) { case USERNAME: @@ -525,11 +681,7 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { } } - public void signInDotComUser() { - SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences( - getActivity().getApplicationContext()); - String username = settings.getString(WordPress.WPCOM_USERNAME_PREFERENCE, null); - String password = WordPressDB.decryptPassword(settings.getString(WordPress.WPCOM_PASSWORD_PREFERENCE, null)); + public void signInDotComUser(String username, String password) { if (username != null && password != null) { mUsernameEditText.setText(username); mPasswordEditText.setText(password); @@ -545,6 +697,7 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { mProgressTextSignIn.setText(message); mUsernameEditText.setEnabled(false); mPasswordEditText.setEnabled(false); + mTwoStepEditText.setEnabled(false); mUrlEditText.setEnabled(false); mAddSelfHostedButton.setEnabled(false); mCreateAccountButton.setEnabled(false); @@ -557,6 +710,7 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { mSignInButton.setVisibility(View.VISIBLE); mUsernameEditText.setEnabled(true); mPasswordEditText.setEnabled(true); + mTwoStepEditText.setEnabled(true); mUrlEditText.setEnabled(true); mAddSelfHostedButton.setEnabled(true); mCreateAccountButton.setEnabled(true); @@ -649,22 +803,15 @@ public class SignInFragment extends AbstractFragment implements TextWatcher { } protected void signInError(int messageId, String clientResponse) { - AnalyticsTracker.track(Stat.LOGIN_FAILED); FragmentTransaction ft = getFragmentManager().beginTransaction(); SignInDialogFragment nuxAlert; - if (messageId == org.wordpress.android.R.string.account_two_step_auth_enabled) { - nuxAlert = SignInDialogFragment.newInstance(getString(org.wordpress.android.R.string.nux_cannot_log_in), - getString(messageId), org.wordpress.android.R.drawable.noticon_alert_big, 2, getString( - org.wordpress.android.R.string.cancel), getString( - org.wordpress.android.R.string.visit_security_settings), "", - SignInDialogFragment.ACTION_OPEN_URL, 0); - Bundle bundle = nuxAlert.getArguments(); - bundle.putString(SignInDialogFragment.ARG_OPEN_URL_PARAM, - "https://wordpress.com/settings/security/?ssl=forced"); - nuxAlert.setArguments(bundle); - } else if (messageId == org.wordpress.android.R.string.username_or_password_incorrect) { + if (messageId == org.wordpress.android.R.string.username_or_password_incorrect) { handleInvalidUsernameOrPassword(messageId); return; + } else if (messageId == R.string.invalid_verification_code) { + endProgress(); + showTwoStepCodeError(messageId); + return; } else if (messageId == org.wordpress.android.R.string.invalid_url_message) { showUrlError(messageId); endProgress(); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/WPComLoginActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/WPComLoginActivity.java deleted file mode 100644 index cca3c079c..000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/WPComLoginActivity.java +++ /dev/null @@ -1,268 +0,0 @@ -package org.wordpress.android.ui.accounts; - -import android.app.Activity; -import android.content.Intent; -import android.content.SharedPreferences.Editor; -import android.net.Uri; -import android.os.AsyncTask; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.support.v7.app.ActionBarActivity; -import android.text.Editable; -import android.text.TextWatcher; -import android.text.method.PasswordTransformationMethod; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.EditText; -import android.widget.ImageView; -import android.widget.TextView; -import android.widget.Toast; - -import com.wordpress.rest.RestRequest; - -import org.json.JSONObject; -import org.wordpress.android.Constants; -import org.wordpress.android.R; -import org.wordpress.android.WordPress; -import org.wordpress.android.WordPressDB; -import org.wordpress.android.models.Blog; -import org.wordpress.android.ui.reader.actions.ReaderUserActions; -import org.wordpress.android.util.AppLog; -import org.wordpress.android.util.AppLog.T; -import org.wordpress.android.util.EditTextUtils; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlrpc.android.XMLRPCClientInterface; -import org.xmlrpc.android.XMLRPCException; -import org.xmlrpc.android.XMLRPCFactory; -import org.xmlrpc.android.XMLRPCFault; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; - - -/** - * An activity to let the user specify their WordPress.com credentials. - * Should be used to get WordPress.com credentials for JetPack integration in self-hosted sites. - */ -public class WPComLoginActivity extends ActionBarActivity implements TextWatcher { - public static final int REQUEST_CODE = 5000; - public static final String JETPACK_AUTH_REQUEST = "jetpackAuthRequest"; - private static final String NEED_HELP_URL = "http://android.wordpress.org/faq"; - private String mUsername; - private String mPassword; - private Button mSignInButton; - private boolean mIsJetpackAuthRequest; - private boolean mIsWpcomAccountWith2FA; - private boolean mIsInvalidUsernameOrPassword; - private EditText mUsernameEditText; - private EditText mPasswordEditText; - private boolean mPasswordVisible; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.wp_dot_com_login_activity); - setTitle(getString(R.string.wpcom_signin_dialog_title)); - - if (getIntent().hasExtra(JETPACK_AUTH_REQUEST)) { - mIsJetpackAuthRequest = true; - } - - mSignInButton = (Button) findViewById(R.id.saveDotcom); - mSignInButton.setOnClickListener(new Button.OnClickListener() { - public void onClick(View v) { - signIn(); - } - }); - - TextView wpcomHelp = (TextView) findViewById(R.id.wpcomHelp); - wpcomHelp.setOnClickListener(new TextView.OnClickListener() { - public void onClick(View v) { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse(NEED_HELP_URL)); - startActivity(intent); - } - }); - - mUsernameEditText = (EditText) findViewById(R.id.dotcomUsername); - mUsernameEditText.addTextChangedListener(this); - mPasswordEditText = (EditText) findViewById(R.id.dotcomPassword); - mPasswordEditText.addTextChangedListener(this); - initPasswordVisibilityButton((ImageView) findViewById(R.id.password_visibility), mPasswordEditText); - } - - private void signIn() { - mUsername = EditTextUtils.getText(mUsernameEditText); - mPassword = EditTextUtils.getText(mPasswordEditText); - boolean validUsernameAndPassword = true; - - if (mUsername.equals("")) { - mUsernameEditText.setError(getString(R.string.required_field)); - mUsernameEditText.requestFocus(); - validUsernameAndPassword = false; - } - if (mPassword.equals("")) { - mPasswordEditText.setError(getString(R.string.required_field)); - mPasswordEditText.requestFocus(); - validUsernameAndPassword = false; - } - if (validUsernameAndPassword) { - new SignInTask().execute(); - } - } - - protected void initPasswordVisibilityButton(final ImageView passwordVisibilityToggleView, - final EditText passwordEditText) { - passwordVisibilityToggleView.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mPasswordVisible = !mPasswordVisible; - if (mPasswordVisible) { - passwordVisibilityToggleView.setImageResource(R.drawable.dashicon_eye_open); - passwordVisibilityToggleView.setColorFilter(v.getContext().getResources().getColor(R.color.nux_eye_icon_color_open)); - passwordEditText.setTransformationMethod(null); - } else { - passwordVisibilityToggleView.setImageResource(R.drawable.dashicon_eye_closed); - passwordVisibilityToggleView.setColorFilter(v.getContext().getResources().getColor(R.color.nux_eye_icon_color_closed)); - passwordEditText.setTransformationMethod(PasswordTransformationMethod.getInstance()); - } - passwordEditText.setSelection(passwordEditText.length()); - } - }); - } - - @Override - public void afterTextChanged(Editable s) { - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - mPasswordEditText.setError(null); - mUsernameEditText.setError(null); - } - - @Override - public void onBackPressed() { - super.onBackPressed(); - setResult(Activity.RESULT_CANCELED); - } - - private void setEditTextAndButtonEnabled(boolean enable) { - mUsernameEditText.setEnabled(enable); - mPasswordEditText.setEnabled(enable); - mSignInButton.setEnabled(enable); - } - - private class SignInTask extends AsyncTask<Void, Void, Boolean> { - @Override - protected void onPreExecute() { - mSignInButton.setText(getString(R.string.signing_in)); - setEditTextAndButtonEnabled(false); - mIsWpcomAccountWith2FA = false; - mIsInvalidUsernameOrPassword = false; - } - - @Override - protected Boolean doInBackground(Void... params) { - URI uri; - try { - uri = new URI(Constants.wpcomXMLRPCURL); - } catch (URISyntaxException e) { - AppLog.e(T.API, "Invalid URI syntax: " + Constants.wpcomXMLRPCURL); - return false; - } - XMLRPCClientInterface client = XMLRPCFactory.instantiate(uri, "", ""); - Object[] signInParams = {mUsername, mPassword}; - try { - client.call("wp.getUsersBlogs", signInParams); - Blog blog = WordPress.getCurrentBlog(); - if (blog != null) { - blog.setDotcom_username(mUsername); - blog.setDotcom_password(mPassword); - } - - // Don't change global WP.com settings if this is Jetpack auth request from stats - if (!mIsJetpackAuthRequest) { - // New wpcom credetials inserted here. Reset the app state: there is the possibility a different - // username/password is inserted here - WordPress.removeWpComUserRelatedData(WPComLoginActivity.this); - WordPress.sendLocalBroadcast(WPComLoginActivity.this, WordPress.BROADCAST_ACTION_SIGNOUT); - - Editor settings = PreferenceManager.getDefaultSharedPreferences(WPComLoginActivity.this).edit(); - settings.putString(WordPress.WPCOM_USERNAME_PREFERENCE, mUsername); - settings.putString(WordPress.WPCOM_PASSWORD_PREFERENCE, WordPressDB.encryptPassword(mPassword)); - settings.commit(); - - // Make sure to update credentials for .wpcom blog even if currentBlog is null - WordPress.wpDB.updateWPComCredentials(mUsername, mPassword); - - // Update regular blog credentials for WP.com auth requests - if (blog != null) { - blog.setUsername(mUsername); - blog.setPassword(mPassword); - } - } - if (blog != null) { - WordPress.wpDB.saveBlog(blog); - } - return true; - } catch (XMLRPCFault xmlRpcFault) { - AppLog.e(T.NUX, "XMLRPCFault received from XMLRPC call wp.getUsersBlogs", xmlRpcFault); - if (xmlRpcFault.getFaultCode() == 403) { - mIsInvalidUsernameOrPassword = true; - } - if (xmlRpcFault.getFaultCode() == 425) { - mIsWpcomAccountWith2FA = true; - return false; - } - } catch (XMLRPCException e) { - AppLog.e(T.NUX, "Exception received from XMLRPC call wp.getUsersBlogs", e); - } catch (IOException e) { - AppLog.e(T.NUX, "Exception received from XMLRPC call wp.getUsersBlogs", e); - } catch (XmlPullParserException e) { - AppLog.e(T.NUX, "Exception received from XMLRPC call wp.getUsersBlogs", e); - } - - mIsWpcomAccountWith2FA = false; - return false; - } - - @Override - protected void onPostExecute(Boolean isSignedIn) { - if (isSignedIn && !isFinishing()) { - if (!mIsJetpackAuthRequest) { - WordPress.getRestClientUtils().get("me", new RestRequest.Listener() { - @Override - public void onResponse(JSONObject jsonObject) { - WPComLoginActivity.this.setResult(RESULT_OK); - // Register the device again for Push Notifications - WordPress.registerForCloudMessaging(WPComLoginActivity.this); - ReaderUserActions.setCurrentUser(jsonObject); - finish(); - } - }, null); - } else { - WPComLoginActivity.this.setResult(RESULT_OK); - finish(); - } - } else { - if (mIsInvalidUsernameOrPassword) { - mUsernameEditText.setError(getString(R.string.username_or_password_incorrect)); - mPasswordEditText.setError(getString(R.string.username_or_password_incorrect)); - } else { - String errorMessage = mIsWpcomAccountWith2FA ? getString(R.string.account_two_step_auth_enabled) - : getString(R.string.nux_cannot_log_in); - Toast.makeText(getBaseContext(), errorMessage, Toast.LENGTH_LONG).show(); - } - setEditTextAndButtonEnabled(true); - mSignInButton.setText(R.string.sign_in); - } - } - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/CreateUserAndBlog.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/CreateUserAndBlog.java index 2c77bf977..b8bed82b0 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/CreateUserAndBlog.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/CreateUserAndBlog.java @@ -1,11 +1,13 @@ package org.wordpress.android.ui.accounts.helpers; +import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.preference.PreferenceManager; +import com.android.volley.VolleyError; import com.wordpress.rest.RestRequest; import org.json.JSONException; @@ -153,14 +155,24 @@ public class CreateUserAndBlog { } private void authenticateUser() { - SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(mContext); - SharedPreferences.Editor editor = settings.edit(); - editor.putString(WordPress.WPCOM_USERNAME_PREFERENCE, mUsername); - editor.putString(WordPress.WPCOM_PASSWORD_PREFERENCE, WordPressDB.encryptPassword(mPassword)); - editor.commit(); + LoginWPCom login = new LoginWPCom(mUsername, mPassword, null, false, null); + login.execute(new LoginAbstract.Callback() { + @Override + public void onSuccess() { + try { + mResponseHandler.nextStep(new JSONObject("{\"success\":true}")); + } catch (JSONException e) { + AppLog.e(T.API, "Could not parse JSON in new user setup"); + } + } + + @Override + public void onError(int errorMessageId, boolean twoStepCodeRequired, boolean httpAuthRequired, boolean erroneousSslCertificate) { + mErrorListener.onErrorResponse(new VolleyError("Sign in failed.")); + } + }); + mResponseHandler.setStep(Step.AUTHENTICATE_USER); - // fire off a request to get an access token - WordPress.getRestClientUtils().get("me", mResponseHandler, mErrorListener); } private void createBlog() { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/FetchBlogListAbstract.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/FetchBlogListAbstract.java index 684b26395..7ba8d7a0d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/FetchBlogListAbstract.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/FetchBlogListAbstract.java @@ -10,7 +10,7 @@ public abstract class FetchBlogListAbstract { public interface Callback { void onSuccess(List<Map<String, Object>> userBlogList); - void onError(int errorMessageId, boolean httpAuthRequired, boolean erroneousSslCertificate, + void onError(int errorMessageId, boolean twoStepCodeRequired, boolean httpAuthRequired, boolean erroneousSslCertificate, String clientResponse); } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/FetchBlogListWPCom.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/FetchBlogListWPCom.java index c025b59cc..a52a8fa67 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/FetchBlogListWPCom.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/FetchBlogListWPCom.java @@ -73,7 +73,7 @@ public class FetchBlogListWPCom extends FetchBlogListAbstract { @Override public void onErrorResponse(VolleyError volleyError) { JSONObject errorObject = VolleyUtils.volleyErrorToJSON(volleyError); - callback.onError(LoginWPCom.restLoginErrorToMsgId(errorObject), false, false, ""); + callback.onError(LoginWPCom.restLoginErrorToMsgId(errorObject), false, false, false, ""); } }); } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/FetchBlogListWPOrg.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/FetchBlogListWPOrg.java index 4ed767d42..b0e7c69aa 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/FetchBlogListWPOrg.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/FetchBlogListWPOrg.java @@ -72,7 +72,7 @@ public class FetchBlogListWPOrg extends FetchBlogListAbstract { if (userBlogs == null) { // Could happen if the returned server response is truncated mErrorMsgId = org.wordpress.android.R.string.xmlrpc_error; - callback.onError(mErrorMsgId, false, false, client.getResponse()); + callback.onError(mErrorMsgId, false, false, false, client.getResponse()); return; } Arrays.sort(userBlogs, BlogUtils.BlogNameComparator); @@ -103,7 +103,7 @@ public class FetchBlogListWPOrg extends FetchBlogListAbstract { AppLog.e(T.NUX, "Exception received from XMLRPC call wp.getUsersBlogs", e); mErrorMsgId = org.wordpress.android.R.string.no_site_error; } - callback.onError(mErrorMsgId, mHttpAuthRequired, mErroneousSslCertificate, client.getResponse()); + callback.onError(mErrorMsgId, false, mHttpAuthRequired, mErroneousSslCertificate, client.getResponse()); } public void fetchBlogList(Callback callback) { @@ -116,7 +116,7 @@ public class FetchBlogListWPOrg extends FetchBlogListAbstract { if (!mHttpAuthRequired && mErrorMsgId == 0) { mErrorMsgId = org.wordpress.android.R.string.no_site_error; } - callback.onError(mErrorMsgId, mHttpAuthRequired, mErroneousSslCertificate, ""); + callback.onError(mErrorMsgId, false, mHttpAuthRequired, mErroneousSslCertificate, ""); return; } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/LoginAbstract.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/LoginAbstract.java index fa31b8efc..0709843df 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/LoginAbstract.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/LoginAbstract.java @@ -7,7 +7,7 @@ public abstract class LoginAbstract { public interface Callback { void onSuccess(); - void onError(int errorMessageId, boolean httpAuthRequired, boolean erroneousSslCertificate); + void onError(int errorMessageId, boolean twoStepCodeRequired, boolean httpAuthRequired, boolean erroneousSslCertificate); } public LoginAbstract(String username, String password) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/LoginWPCom.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/LoginWPCom.java index b69d3f737..cc5bf6507 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/LoginWPCom.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/LoginWPCom.java @@ -3,6 +3,7 @@ package org.wordpress.android.ui.accounts.helpers; import android.annotation.SuppressLint; import android.content.SharedPreferences; import android.preference.PreferenceManager; +import android.text.TextUtils; import com.android.volley.Request; import com.android.volley.VolleyError; @@ -13,14 +14,23 @@ import com.wordpress.rest.Oauth.Listener; import org.json.JSONException; import org.json.JSONObject; import org.wordpress.android.*; +import org.wordpress.android.models.Blog; import org.wordpress.android.ui.notifications.utils.SimperiumUtils; import org.wordpress.android.util.AppLog; import org.wordpress.android.util.AppLog.T; import org.wordpress.android.util.VolleyUtils; public class LoginWPCom extends LoginAbstract { - public LoginWPCom(String username, String password) { + + private String mTwoStepCode; + private boolean mShouldSendTwoStepSMS; + private Blog mJetpackBlog; + + public LoginWPCom(String username, String password, String twoStepCode, boolean shouldSendTwoStepSMS, Blog blog) { super(username, password); + mTwoStepCode = twoStepCode; + mShouldSendTwoStepSMS = shouldSendTwoStepSMS; + mJetpackBlog = blog; } public static int restLoginErrorToMsgId(JSONObject errorObject) { @@ -30,15 +40,16 @@ public class LoginWPCom extends LoginAbstract { // Map REST errors to local error codes if (errorObject != null) { try { - String error = errorObject.getString("error"); + String error = errorObject.optString("error", ""); String errorDescription = errorObject.getString("error_description"); - if (error != null && error.equals("invalid_request")) { + if (error.equals("invalid_request")) { if (errorDescription.contains("Incorrect username or password.")) { errorMsgId = org.wordpress.android.R.string.username_or_password_incorrect; } - if (errorDescription.contains("This account has two step authentication enabled.")) { - errorMsgId = org.wordpress.android.R.string.account_two_step_auth_enabled; - } + } else if (error.equals("needs_2fa")) { + errorMsgId = org.wordpress.android.R.string.account_two_step_auth_enabled; + } else if (error.equals("invalid_otp")) { + errorMsgId = org.wordpress.android.R.string.invalid_verification_code; } } catch (JSONException e) { AppLog.e(T.NUX, e); @@ -53,7 +64,7 @@ public class LoginWPCom extends LoginAbstract { org.wordpress.android.BuildConfig.OAUTH_APP_SECRET, org.wordpress.android.BuildConfig.OAUTH_REDIRECT_URI); Request oauthRequest; - oauthRequest = oauth.makeRequest(username, password, listener, errorListener); + oauthRequest = oauth.makeRequest(username, password, mTwoStepCode, mShouldSendTwoStepSMS, listener, errorListener); return oauthRequest; } @@ -66,13 +77,20 @@ public class LoginWPCom extends LoginAbstract { // Once we have a token, start up Simperium SimperiumUtils.configureSimperium(WordPress.getContext(), token.toString()); - // login successful, store password + if (mJetpackBlog != null) { + // Store token in blog object for Jetpack sites + mJetpackBlog.setApi_key(token.toString()); + WordPress.wpDB.saveBlog(mJetpackBlog); + } + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(WordPress.getContext()); - SharedPreferences.Editor editor = settings.edit(); - editor.putString(WordPress.WPCOM_USERNAME_PREFERENCE, mUsername); - editor.putString(WordPress.WPCOM_PASSWORD_PREFERENCE, mPassword); - editor.putString(WordPress.ACCESS_TOKEN_PREFERENCE, token.toString()); - editor.commit(); + if (mJetpackBlog == null || TextUtils.isEmpty(settings.getString(WordPress.WPCOM_USERNAME_PREFERENCE, null))) { + // Store token in global account + SharedPreferences.Editor editor = settings.edit(); + editor.putString(WordPress.WPCOM_USERNAME_PREFERENCE, mUsername); + editor.putString(WordPress.ACCESS_TOKEN_PREFERENCE, token.toString()); + editor.commit(); + } mCallback.onSuccess(); } @@ -80,7 +98,8 @@ public class LoginWPCom extends LoginAbstract { @Override public void onErrorResponse(VolleyError volleyError) { JSONObject errorObject = VolleyUtils.volleyErrorToJSON(volleyError); - mCallback.onError(restLoginErrorToMsgId(errorObject), false, false); + int errorMsgId = restLoginErrorToMsgId(errorObject); + mCallback.onError(errorMsgId, errorMsgId == R.string.account_two_step_auth_enabled, false, false); } })); } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/UpdateBlogListTask.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/UpdateBlogListTask.java index 9baffec36..091884d81 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/UpdateBlogListTask.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/helpers/UpdateBlogListTask.java @@ -36,7 +36,6 @@ public class UpdateBlogListTask extends AsyncTask<Void, Void, List<Map<String, O protected List<Map<String, Object>> doInBackground(Void... args) { SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(mContext); final String username = settings.getString(WordPress.WPCOM_USERNAME_PREFERENCE, null); - final String password = WordPressDB.decryptPassword(settings.getString(WordPress.WPCOM_PASSWORD_PREFERENCE, null)); final CountDownLatch countDownLatch = new CountDownLatch(1); FetchBlogListWPCom fetchBlogList = new FetchBlogListWPCom(); fetchBlogList.execute(new Callback() { @@ -44,13 +43,13 @@ public class UpdateBlogListTask extends AsyncTask<Void, Void, List<Map<String, O public void onSuccess(List<Map<String, Object>> userBlogList) { mUserBlogList = userBlogList; if (mUserBlogList != null) { - mBlogListChanged = BlogUtils.syncBlogs(mContext, mUserBlogList, username, password, null, null); + mBlogListChanged = BlogUtils.syncBlogs(mContext, mUserBlogList, username); } countDownLatch.countDown(); } @Override - public void onError(int messageId, boolean httpAuthRequired, boolean erroneousSslCertificate, + public void onError(int messageId, boolean twoStepCodeRequired, boolean httpAuthRequired, boolean erroneousSslCertificate, String clientResponse) { mErrorMsgId = messageId; countDownLatch.countDown(); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/comments/CommentDetailFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/comments/CommentDetailFragment.java index 69eed8789..b38c063c2 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/comments/CommentDetailFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/comments/CommentDetailFragment.java @@ -632,7 +632,7 @@ public class CommentDetailFragment extends Fragment implements NotificationFragm // the post this comment is on can only be requested if this is a .com blog or a // jetpack-enabled self-hosted blog, and we have valid .com credentials boolean isDotComOrJetpack = WordPress.wpDB.isRemoteBlogIdDotComOrJetpack(mRemoteBlogId); - boolean canRequestPost = isDotComOrJetpack && WordPress.hasValidWPComCredentials(getActivity()); + boolean canRequestPost = isDotComOrJetpack && WordPress.hasDotComToken(getActivity()); final String title; final boolean hasTitle; diff --git a/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsListFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsListFragment.java index 028f49b7c..d40545a5b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsListFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsListFragment.java @@ -32,7 +32,6 @@ import org.wordpress.android.models.Note; import org.wordpress.android.ui.comments.CommentActions; import org.wordpress.android.ui.notifications.adapters.NotesAdapter; import org.wordpress.android.ui.notifications.utils.SimperiumUtils; -import org.wordpress.android.ui.reader.actions.ReaderAuthActions; import org.wordpress.android.util.AppLog; import org.wordpress.android.util.StringUtils; import org.wordpress.android.util.ToastUtils; @@ -48,7 +47,6 @@ public class NotificationsListFragment extends Fragment implements Bucket.Listen public static final String NOTE_MODERATE_STATUS_EXTRA = "moderateNoteStatus"; private static final int NOTE_DETAIL_REQUEST_CODE = 0; - private static final String KEY_INITIAL_UPDATE = "initialUpdate"; private static final String KEY_LIST_SCROLL_POSITION = "scrollPosition"; private SwipeToRefreshHelper mFauxSwipeToRefreshHelper; @@ -58,7 +56,6 @@ public class NotificationsListFragment extends Fragment implements Bucket.Listen private TextView mEmptyTextView; private int mRestoredScrollPosition; - private boolean mHasPerformedInitialUpdate; private Bucket<Note> mBucket; @@ -118,7 +115,6 @@ public class NotificationsListFragment extends Fragment implements Bucket.Listen initSwipeToRefreshHelper(); if (savedInstanceState != null) { - mHasPerformedInitialUpdate = savedInstanceState.getBoolean(KEY_INITIAL_UPDATE, false); setRestoredListPosition(savedInstanceState.getInt(KEY_LIST_SCROLL_POSITION, RecyclerView.NO_POSITION)); } } @@ -153,15 +149,6 @@ public class NotificationsListFragment extends Fragment implements Bucket.Listen } @Override - public void onStart() { - super.onStart(); - if (isAdded() && !mHasPerformedInitialUpdate) { - mHasPerformedInitialUpdate = true; - ReaderAuthActions.updateCookies(getActivity()); - } - } - - @Override public void onDestroy() { // Close Simperium cursor if (mNotesAdapter != null) { @@ -288,8 +275,6 @@ public class NotificationsListFragment extends Fragment implements Bucket.Listen outState.putBoolean("bug_19917_fix", true); } - outState.putBoolean(KEY_INITIAL_UPDATE, mHasPerformedInitialUpdate); - // Save list view scroll position outState.putInt(KEY_LIST_SCROLL_POSITION, getScrollPosition()); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/notifications/utils/NotificationsUtils.java b/WordPress/src/main/java/org/wordpress/android/ui/notifications/utils/NotificationsUtils.java index 1374200eb..7a02ab25f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/notifications/utils/NotificationsUtils.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/notifications/utils/NotificationsUtils.java @@ -52,7 +52,7 @@ public class NotificationsUtils { public static void getPushNotificationSettings(Context context, RestRequest.Listener listener, RestRequest.ErrorListener errorListener) { - if (!WordPress.hasValidWPComCredentials(context)) { + if (!WordPress.hasDotComToken(context)) { return; } @@ -72,7 +72,7 @@ public class NotificationsUtils { } public static void setPushNotificationSettings(Context context) { - if (!WordPress.hasValidWPComCredentials(context)) { + if (!WordPress.hasDotComToken(context)) { return; } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/BlogPreferencesActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/prefs/BlogPreferencesActivity.java index a680682c4..34ab6d1f6 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/BlogPreferencesActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/BlogPreferencesActivity.java @@ -22,8 +22,8 @@ import android.widget.Toast; import org.wordpress.android.R; import org.wordpress.android.WordPress; import org.wordpress.android.models.Blog; -import org.wordpress.android.ui.DashboardActivity; import org.wordpress.android.analytics.AnalyticsTracker; +import org.wordpress.android.ui.WPWebViewActivity; import org.wordpress.android.util.StringUtils; import java.util.Locale; @@ -305,10 +305,16 @@ public class BlogPreferencesActivity extends ActionBarActivity { * View the blog admin area in the web browser */ public void viewAdmin(View view) { + if (blog == null) return; + AnalyticsTracker.track(AnalyticsTracker.Stat.OPENED_VIEW_ADMIN); mIsViewingAdmin = true; - Intent i = new Intent(this, DashboardActivity.class); - i.putExtra("blogID", blog.getLocalTableBlogId()); - startActivity(i); + Intent intent = new Intent(this, WPWebViewActivity.class); + intent.putExtra(WPWebViewActivity.AUTHENTICATION_USER, blog.getUsername()); + intent.putExtra(WPWebViewActivity.AUTHENTICATION_PASSWD, blog.getPassword()); + intent.putExtra(WPWebViewActivity.URL_TO_LOAD, blog.getAdminUrl()); + intent.putExtra(WPWebViewActivity.AUTHENTICATION_URL, WPWebViewActivity.getBlogLoginUrl(blog)); + intent.putExtra(WPWebViewActivity.LOCAL_BLOG_ID, blog.getLocalTableBlogId()); + startActivity(intent); } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/SettingsFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/prefs/SettingsFragment.java index 432cd3e97..4f11b8236 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/SettingsFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/SettingsFragment.java @@ -111,7 +111,7 @@ public class SettingsFragment extends PreferenceFragment { private void initNotifications() { // AuthenticatorRequest notification settings if needed - if (WordPress.hasValidWPComCredentials(getActivity())) { + if (WordPress.hasDotComToken(getActivity())) { String settingsJson = mSettings.getString(NotificationsUtils.WPCOM_PUSH_DEVICE_NOTIFICATION_SETTINGS, null); if (settingsJson == null) { com.wordpress.rest.RestRequest.Listener listener = new RestRequest.Listener() { @@ -236,7 +236,7 @@ public class SettingsFragment extends PreferenceFragment { } private void addWpComSignIn(PreferenceCategory wpComCategory, int order) { - if (WordPress.hasValidWPComCredentials(getActivity())) { + if (WordPress.hasDotComToken(getActivity())) { String username = mSettings.getString(WordPress.WPCOM_USERNAME_PREFERENCE, null); Preference usernamePref = new Preference(getActivity()); usernamePref.setTitle(getString(R.string.username)); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostDetailFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostDetailFragment.java index 0cc84779c..de006acc6 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostDetailFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostDetailFragment.java @@ -681,6 +681,8 @@ public class ReaderPostDetailFragment extends Fragment return false; } + mReaderWebView.setIsPrivatePost(mPost.isPrivate); + txtTitle = (TextView) container.findViewById(R.id.text_title); txtBlogName = (TextView) container.findViewById(R.id.text_blog_name); txtDateAndAuthor = (TextView) container.findViewById(R.id.text_date_and_author); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListActivity.java index 572a2a510..fa3bc395a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListActivity.java @@ -11,7 +11,7 @@ import org.wordpress.android.analytics.AnalyticsTracker; import org.wordpress.android.datasets.ReaderTagTable; import org.wordpress.android.models.ReaderTag; import org.wordpress.android.ui.WPDrawerActivity; -import org.wordpress.android.ui.accounts.WPComLoginActivity; +import org.wordpress.android.ui.accounts.SignInActivity; import org.wordpress.android.ui.prefs.AppPrefs; import org.wordpress.android.util.AppLog; import org.wordpress.android.util.AppLog.T; @@ -125,7 +125,7 @@ public class ReaderPostListActivity extends WPDrawerActivity { switch (requestCode) { // user just returned from the login dialog, need to perform initial update again // since creds have changed - case WPComLoginActivity.REQUEST_CODE: + case SignInActivity.REQUEST_CODE: if (resultCode == Activity.RESULT_OK) { removeListFragment(); EventBus.getDefault().removeStickyEvent(ReaderEvents.HasPerformedInitialUpdate.class); @@ -212,5 +212,4 @@ public class ReaderPostListActivity extends WPDrawerActivity { } return ((ReaderPostListFragment) fragment); } - } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java index 6db7a5e81..f0993f1dd 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java @@ -50,7 +50,6 @@ import org.wordpress.android.models.ReaderTagType; import org.wordpress.android.ui.prefs.AppPrefs; import org.wordpress.android.ui.reader.ReaderTypes.ReaderPostListType; import org.wordpress.android.ui.reader.actions.ReaderActions; -import org.wordpress.android.ui.reader.actions.ReaderAuthActions; import org.wordpress.android.ui.reader.actions.ReaderBlogActions; import org.wordpress.android.ui.reader.actions.ReaderTagActions; import org.wordpress.android.ui.reader.actions.ReaderUserActions; @@ -1425,10 +1424,6 @@ public class ReaderPostListFragment extends Fragment AppLog.d(T.READER, "reader post list > updating current user"); ReaderUserActions.updateCurrentUser(); - // update cookies so that we can show authenticated images in WebViews - AppLog.d(T.READER, "reader post list > updating cookies"); - ReaderAuthActions.updateCookies(getActivity()); - EventBus.getDefault().postSticky(new ReaderEvents.HasPerformedInitialUpdate()); } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/actions/ReaderAuthActions.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/actions/ReaderAuthActions.java deleted file mode 100644 index 95ac67c15..000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/actions/ReaderAuthActions.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.wordpress.android.ui.reader.actions; - -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; -import android.webkit.CookieManager; -import android.webkit.CookieSyncManager; - -import org.apache.http.HttpResponse; -import org.apache.http.HttpStatus; -import org.apache.http.NameValuePair; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.conn.scheme.Scheme; -import org.apache.http.conn.ssl.SSLSocketFactory; -import org.apache.http.cookie.Cookie; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.protocol.HTTP; -import org.wordpress.android.WordPress; -import org.wordpress.android.WordPressDB; -import org.wordpress.android.util.AppLog; -import org.wordpress.android.util.AppLog.T; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; - -public class ReaderAuthActions { - private static final String URI_LOGIN = "https://wordpress.com/wp-login.php"; - private static final int HTTPS_PORT = 443; - - /* - * login to WP using a DefaultHttpClient so we can capture the response cookies and add them to - * the CookieSyncManager so they'll be available in our webView on post detail - only needs to - * be done once per session - */ - public static void updateCookies(Context context) { - // http://developer.android.com/reference/android/webkit/CookieSyncManager.html - CookieSyncManager.createInstance(context.getApplicationContext()); - final CookieManager cookieManager = CookieManager.getInstance(); - cookieManager.removeAllCookie(); - - // nothing more to do if login doesn't exist yet - if (!WordPress.hasValidWPComCredentials(context)) - return; - - SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); - final String username = settings.getString(WordPress.WPCOM_USERNAME_PREFERENCE, ""); - final String password = WordPressDB.decryptPassword(settings.getString(WordPress.WPCOM_PASSWORD_PREFERENCE, "")); - - new Thread() { - @Override - public void run() { - try { - URI uri = URI.create(URI_LOGIN); - HttpPost postMethod = new HttpPost(uri); - postMethod.addHeader("charset", "UTF-8"); - postMethod.addHeader("User-Agent", WordPress.getUserAgent()); - - UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, password); - - DefaultHttpClient client = getHttpClient(creds); - - List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3); - nameValuePairs.add(new BasicNameValuePair("log", username)); - nameValuePairs.add(new BasicNameValuePair("pwd", password)); - nameValuePairs.add(new BasicNameValuePair("rememberme", "forever")); - nameValuePairs.add(new BasicNameValuePair("wp-submit", "Log In")); - nameValuePairs.add(new BasicNameValuePair("redirect_to", "/")); - postMethod.setEntity(new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8)); - - HttpResponse response = client.execute(postMethod); - - int statusCode = response.getStatusLine().getStatusCode(); - if (statusCode != HttpStatus.SC_OK) { - AppLog.w(T.READER, String.format("failed to retrieve cookies, status %d", statusCode)); - return; - } - - List<Cookie> cookies = client.getCookieStore().getCookies(); - if(!cookies.isEmpty()) { - for (Cookie cookie : cookies){ - String cookieString = cookie.getName() + "=" + cookie.getValue() + "; domain=" + cookie.getDomain(); - cookieManager.setCookie("wordpress.com", cookieString); - } - CookieSyncManager.getInstance().sync(); - } - - } catch (UnsupportedEncodingException e) { - AppLog.e(T.READER, e); - } catch (IOException e) { - AppLog.e(T.READER, e); - } - } - }.start(); - } - - private static DefaultHttpClient getHttpClient(UsernamePasswordCredentials creds) { - DefaultHttpClient client = new DefaultHttpClient(); - - BasicCredentialsProvider cP = new BasicCredentialsProvider(); - cP.setCredentials(AuthScope.ANY, creds); - client.setCredentialsProvider(cP); - client.getConnectionManager().getSchemeRegistry().register(new Scheme("https", SSLSocketFactory.getSocketFactory(), HTTPS_PORT)); - - return client; - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/ReaderWebView.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/ReaderWebView.java index e942c7f5f..34ebb0f52 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/views/ReaderWebView.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/views/ReaderWebView.java @@ -2,18 +2,32 @@ package org.wordpress.android.ui.reader.views; import android.annotation.SuppressLint; import android.content.Context; +import android.content.SharedPreferences; import android.os.Build; +import android.preference.PreferenceManager; +import android.text.TextUtils; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.webkit.CookieManager; import android.webkit.WebChromeClient; +import android.webkit.WebResourceRequest; +import android.webkit.WebResourceResponse; import android.webkit.WebView; import android.webkit.WebViewClient; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.DefaultHttpClient; import org.wordpress.android.WordPress; import org.wordpress.android.util.AppLog; +import org.wordpress.android.util.StringUtils; +import org.wordpress.android.util.UrlUtils; + +import java.io.IOException; +import java.io.InputStream; /* * WebView descendant used by ReaderPostDetailFragment - handles @@ -42,11 +56,15 @@ public class ReaderWebView extends WebView { private ReaderWebViewUrlClickListener mUrlClickListener; private ReaderWebViewPageFinishedListener mPageFinishedListener; + private static String mToken; + private static boolean mIsPrivatePost; + private boolean mIsDestroyed; + public ReaderWebView(Context context) { super(context); - init(); + init(context); } @Override @@ -61,17 +79,20 @@ public class ReaderWebView extends WebView { public ReaderWebView(Context context, AttributeSet attrs) { super(context, attrs); - init(); + init(context); } public ReaderWebView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - init(); + init(context); } @SuppressLint("NewApi") - private void init() { + private void init(Context context) { if (!isInEditMode()) { + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); + mToken = settings.getString(WordPress.ACCESS_TOKEN_PREFERENCE, ""); + mReaderChromeClient = new ReaderWebChromeClient(this); this.setWebChromeClient(mReaderChromeClient); this.setWebViewClient(new ReaderWebViewClient(this)); @@ -120,6 +141,10 @@ public class ReaderWebView extends WebView { return mCustomViewListener; } + public void setIsPrivatePost(boolean isPrivatePost) { + mIsPrivatePost = isPrivatePost; + } + private static boolean isValidClickedUrl(String url) { // only return true for http(s) urls so we avoid file: and data: clicks return (url != null && url.startsWith("http")); @@ -188,6 +213,34 @@ public class ReaderWebView extends WebView { return false; } } + + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, String url) { + // Intercept requests for private images and add the WP.com authorization header + if (mIsPrivatePost && !TextUtils.isEmpty(mToken) && isImageUrl(url)) { + DefaultHttpClient client = new DefaultHttpClient(); + HttpGet httpGet = new HttpGet(url); + httpGet.setHeader("Authorization", "Bearer " + mToken); + try { + HttpResponse httpResponse = client.execute(httpGet); + InputStream responseInputStream = httpResponse.getEntity().getContent(); + return new WebResourceResponse(httpResponse.getEntity().getContentType().toString(), "UTF-8", responseInputStream); + } catch (IOException e) { + AppLog.e(AppLog.T.READER, "Invalid reader detail request: " + e.getMessage()); + } + } + + return super.shouldInterceptRequest(view, url); + } + } + + private static boolean isImageUrl(String url) { + if (TextUtils.isEmpty(url)) return false; + + String cleanedUrl = UrlUtils.removeQuery(url.toLowerCase()); + + return cleanedUrl.endsWith("jpg") || cleanedUrl.endsWith("jpeg") || + cleanedUrl.endsWith("gif") || cleanedUrl.endsWith("png"); } private static class ReaderWebChromeClient extends WebChromeClient { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsActivity.java index 3eb47abbb..1a839a44d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsActivity.java @@ -34,12 +34,11 @@ import com.android.volley.VolleyError; import org.wordpress.android.R; import org.wordpress.android.WordPress; -import org.wordpress.android.WordPressDB; import org.wordpress.android.analytics.AnalyticsTracker; import org.wordpress.android.models.Blog; import org.wordpress.android.ui.WPDrawerActivity; import org.wordpress.android.ui.WPWebViewActivity; -import org.wordpress.android.ui.accounts.WPComLoginActivity; +import org.wordpress.android.ui.accounts.SignInActivity; import org.wordpress.android.ui.stats.service.StatsService; import org.wordpress.android.util.AppLog; import org.wordpress.android.util.AppLog.T; @@ -421,15 +420,15 @@ public class StatsActivity extends WPDrawerActivity implements ScrollViewExt.Scr private void startWPComLoginActivity() { mResultCode = RESULT_CANCELED; - Intent loginIntent = new Intent(this, WPComLoginActivity.class); - loginIntent.putExtra(WPComLoginActivity.JETPACK_AUTH_REQUEST, true); - startActivityForResult(loginIntent, WPComLoginActivity.REQUEST_CODE); + Intent signInIntent = new Intent(this, SignInActivity.class); + signInIntent.putExtra(SignInActivity.ARG_JETPACK_SITE_AUTH, mLocalBlogID); + startActivityForResult(signInIntent, SignInActivity.REQUEST_CODE); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - if (requestCode == WPComLoginActivity.REQUEST_CODE) { + if (requestCode == SignInActivity.REQUEST_CODE) { mResultCode = resultCode; final Blog currentBlog = WordPress.getBlog(mLocalBlogID); if (resultCode == RESULT_OK && currentBlog != null && !currentBlog.isDotcomFlag()) { @@ -571,18 +570,15 @@ public class StatsActivity extends WPDrawerActivity implements ScrollViewExt.Scr return true; } - StatsUtils.StatsCredentials credentials = StatsUtils.getBlogStatsCredentials(mLocalBlogID); - if (credentials == null) { + String statsAuthenticatedUser = StatsUtils.getBlogStatsUsername(mLocalBlogID); + if (statsAuthenticatedUser == null) { Toast.makeText(this, R.string.jetpack_message_not_admin, Toast.LENGTH_LONG).show(); return true; } - String statsAuthenticatedUser = credentials.getUsername(); - String statsAuthenticatedPassword = credentials.getPassword(); String addressToLoad = "https://wordpress.com/my-stats/?no-chrome&blog=" + blogId + "&unit=1"; - WPWebViewActivity.openUrlByUsingWPCOMCredentials(this, addressToLoad, statsAuthenticatedUser, - statsAuthenticatedPassword); + WPWebViewActivity.openUrlByUsingWPCOMCredentials(this, addressToLoad, statsAuthenticatedUser); AnalyticsTracker.track(AnalyticsTracker.Stat.STATS_OPENED_WEB_VERSION); return true; } @@ -654,15 +650,11 @@ public class StatsActivity extends WPDrawerActivity implements ScrollViewExt.Scr // for self-hosted sites; launch the user into an activity where they can provide their credentials if (!currentBlog.isDotcomFlag() && !currentBlog.hasValidJetpackCredentials() && mResultCode != RESULT_CANCELED) { - if (WordPress.hasValidWPComCredentials(this)) { + if (WordPress.hasDotComToken(this)) { // Let's try the global wpcom credentials them first SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); String username = settings.getString(WordPress.WPCOM_USERNAME_PREFERENCE, null); - String password = WordPressDB.decryptPassword( - settings.getString(WordPress.WPCOM_PASSWORD_PREFERENCE, null) - ); currentBlog.setDotcom_username(username); - currentBlog.setDotcom_password(password); WordPress.wpDB.saveBlog(currentBlog); mSwipeToRefreshHelper.setRefreshing(true); } else { @@ -687,7 +679,7 @@ public class StatsActivity extends WPDrawerActivity implements ScrollViewExt.Scr // check again that we've valid credentials for a Jetpack site if (!currentBlog.isDotcomFlag() && !currentBlog.hasValidJetpackCredentials() - && !WordPress.hasValidWPComCredentials(this)) { + && !WordPress.hasDotComToken(this)) { mSwipeToRefreshHelper.setRefreshing(false); AppLog.w(T.STATS, "Jetpack blog with no wpcom credentials"); return; diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsUtils.java b/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsUtils.java index ada427c29..42cfbd852 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsUtils.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsUtils.java @@ -214,7 +214,7 @@ public class StatsUtils { */ public static long getDateDiff(Date date1, Date date2, TimeUnit timeUnit) { long diffInMillies = date2.getTime() - date1.getTime(); - return timeUnit.convert(diffInMillies,TimeUnit.MILLISECONDS); + return timeUnit.convert(diffInMillies, TimeUnit.MILLISECONDS); } public static int getSmallestWidthDP() { @@ -229,49 +229,25 @@ public class StatsUtils { * 3. Check that credentials are not empty before launching the activity * */ - public static StatsCredentials getBlogStatsCredentials(int localTableBlogID) { + public static String getBlogStatsUsername(int localTableBlogID) { Blog currentBlog = WordPress.getBlog(localTableBlogID); if (currentBlog == null) { return null; } String statsAuthenticatedUser = currentBlog.getDotcom_username(); - String statsAuthenticatedPassword = currentBlog.getDotcom_password(); - if (org.apache.commons.lang.StringUtils.isEmpty(statsAuthenticatedPassword) - || org.apache.commons.lang.StringUtils.isEmpty(statsAuthenticatedUser)) { + if (org.apache.commons.lang.StringUtils.isEmpty(statsAuthenticatedUser)) { // Let's try the global wpcom credentials SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(WordPress.getContext()); statsAuthenticatedUser = settings.getString(WordPress.WPCOM_USERNAME_PREFERENCE, null); - statsAuthenticatedPassword = WordPressDB.decryptPassword( - settings.getString(WordPress.WPCOM_PASSWORD_PREFERENCE, null) - ); } - if (org.apache.commons.lang.StringUtils.isEmpty(statsAuthenticatedPassword) - || org.apache.commons.lang.StringUtils.isEmpty(statsAuthenticatedUser)) { + if (org.apache.commons.lang.StringUtils.isEmpty(statsAuthenticatedUser)) { AppLog.e(AppLog.T.STATS, "WPCOM Credentials for the current blog are null!"); return null; } - return new StatsCredentials(statsAuthenticatedUser, statsAuthenticatedPassword); - } - - public static class StatsCredentials { - private final String mUsername; - private final String mPassword; - - public StatsCredentials(String username, String password) { - this.mUsername = username; - this.mPassword = password; - } - - public String getUsername() { - return mUsername; - } - - public String getPassword() { - return mPassword; - } + return statsAuthenticatedUser; } /** diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsViewHolder.java b/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsViewHolder.java index 8422da00c..5a1eeff80 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsViewHolder.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsViewHolder.java @@ -81,16 +81,12 @@ public class StatsViewHolder { // Let's try the global wpcom credentials SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(view.getContext()); String statsAuthenticatedUser = settings.getString(WordPress.WPCOM_USERNAME_PREFERENCE, null); - String statsAuthenticatedPassword = WordPressDB.decryptPassword( - settings.getString(WordPress.WPCOM_PASSWORD_PREFERENCE, null) - ); - if (org.apache.commons.lang.StringUtils.isEmpty(statsAuthenticatedPassword) - || org.apache.commons.lang.StringUtils.isEmpty(statsAuthenticatedUser)) { + if (org.apache.commons.lang.StringUtils.isEmpty(statsAuthenticatedUser)) { // Still empty. Do not eat the event, but let's open the default Web Browser. } WPWebViewActivity.openUrlByUsingWPCOMCredentials(view.getContext(), - url, statsAuthenticatedUser, statsAuthenticatedPassword); + url, statsAuthenticatedUser); } else if (url.startsWith("https") || url.startsWith("http")) { AppLog.d(AppLog.T.UTILS, "Opening the in-app browser: " + url); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsWPLinkMovementMethod.java b/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsWPLinkMovementMethod.java index 485904cff..e77d73daa 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsWPLinkMovementMethod.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/stats/StatsWPLinkMovementMethod.java @@ -64,16 +64,12 @@ public class StatsWPLinkMovementMethod extends WPLinkMovementMethod { // Let's try the global wpcom credentials SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(widget.getContext()); String statsAuthenticatedUser = settings.getString(WordPress.WPCOM_USERNAME_PREFERENCE, null); - String statsAuthenticatedPassword = WordPressDB.decryptPassword( - settings.getString(WordPress.WPCOM_PASSWORD_PREFERENCE, null) - ); - if (org.apache.commons.lang.StringUtils.isEmpty(statsAuthenticatedPassword) - || org.apache.commons.lang.StringUtils.isEmpty(statsAuthenticatedUser)) { + if (org.apache.commons.lang.StringUtils.isEmpty(statsAuthenticatedUser)) { // Still empty. Do not eat the event, but let's open the default Web Browser. return super.onTouchEvent(widget, buffer, event); } WPWebViewActivity.openUrlByUsingWPCOMCredentials(widget.getContext(), - url, statsAuthenticatedUser, statsAuthenticatedPassword); + url, statsAuthenticatedUser); return true; } else if (url.startsWith("https") || url.startsWith("http")) { AppLog.d(AppLog.T.UTILS, "Opening the in-app browser: " + url); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/themes/ThemePreviewFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/themes/ThemePreviewFragment.java index a6c979d1a..d1805866e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/themes/ThemePreviewFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/themes/ThemePreviewFragment.java @@ -16,6 +16,7 @@ import android.widget.ProgressBar; import org.wordpress.android.R; import org.wordpress.android.WordPress; import org.wordpress.android.models.Blog; +import org.wordpress.android.ui.WPWebViewActivity; import org.wordpress.android.util.AppLog; import org.wordpress.android.util.AppLog.T; import org.wordpress.android.util.WPWebChromeClient; @@ -162,18 +163,16 @@ public class ThemePreviewFragment extends Fragment { * @param url URL to be loaded in the webview. */ protected void loadAuthenticatedUrl(String url) { - try { - if (mBlog == null || url == null) { - return; - } - String postData = String.format("log=%s&pwd=%s&redirect_to=%s", - URLEncoder.encode(mBlog.getUsername(), "UTF-8"), - URLEncoder.encode(mBlog.getPassword(), "UTF-8"), - URLEncoder.encode(url, "UTF-8")); - mWebView.postUrl(WordPress.getLoginUrl(mBlog), postData.getBytes()); - } catch (UnsupportedEncodingException e) { - AppLog.e(T.THEMES, e); + if (!isAdded() || mBlog == null || url == null) { + return; } + + String authenticationUrl = WordPress.getLoginUrl(mBlog); + String postData = WPWebViewActivity.getAuthenticationPostData(authenticationUrl, url, + mBlog.getUsername(), mBlog.getPassword(), WordPress.getDotComToken(getActivity()) + ); + + mWebView.postUrl(authenticationUrl, postData.getBytes()); } @Override diff --git a/WordPress/src/main/java/org/wordpress/android/util/AuthenticationDialogUtils.java b/WordPress/src/main/java/org/wordpress/android/util/AuthenticationDialogUtils.java index 89e9550c0..a029f546b 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/AuthenticationDialogUtils.java +++ b/WordPress/src/main/java/org/wordpress/android/util/AuthenticationDialogUtils.java @@ -3,6 +3,7 @@ package org.wordpress.android.util; import android.app.Activity; import android.app.FragmentTransaction; import android.content.Context; +import android.content.Intent; import android.text.TextUtils; import com.android.volley.VolleyError; @@ -11,6 +12,7 @@ import org.json.JSONException; import org.json.JSONObject; import org.wordpress.android.R; import org.wordpress.android.WordPress; +import org.wordpress.android.ui.accounts.SignInActivity; import org.wordpress.android.util.AppLog.T; import org.wordpress.android.util.ToastUtils.Duration; import org.wordpress.android.widgets.AuthErrorDialogFragment; @@ -52,7 +54,7 @@ public class AuthenticationDialogUtils { } if (isInvalidTokenError && (context instanceof Activity)) { - showAuthErrorDialog((Activity) context); + showAuthErrorView((Activity) context); } else { String fallbackErrorMessage = TextUtils.isEmpty(friendlyMessage) ? context.getString( R.string.error_generic) : friendlyMessage; @@ -65,29 +67,33 @@ public class AuthenticationDialogUtils { } - public static void showAuthErrorDialog(Activity activity) { - showAuthErrorDialog(activity, AuthErrorDialogFragment.DEFAULT_RESOURCE_ID, AuthErrorDialogFragment.DEFAULT_RESOURCE_ID); + public static void showAuthErrorView(Activity activity) { + showAuthErrorView(activity, AuthErrorDialogFragment.DEFAULT_RESOURCE_ID, AuthErrorDialogFragment.DEFAULT_RESOURCE_ID); } - public static void showAuthErrorDialog(Activity activity, int titleResId, int messageResId) { + public static void showAuthErrorView(Activity activity, int titleResId, int messageResId) { final String ALERT_TAG = "alert_ask_credentials"; if (activity.isFinishing()) { return; } + + // WP.com errors will show the sign in activity + if (WordPress.getCurrentBlog() == null || (WordPress.getCurrentBlog() != null && WordPress.getCurrentBlog().isDotcomFlag())) { + Intent signInIntent = new Intent(activity, SignInActivity.class); + signInIntent.putExtra(SignInActivity.ARG_IS_AUTH_ERROR, true); + signInIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + activity.startActivityForResult(signInIntent, SignInActivity.REQUEST_CODE); + return; + } + // abort if the dialog is already visible if (activity.getFragmentManager().findFragmentByTag(ALERT_TAG) != null) { return; } + FragmentTransaction ft = activity.getFragmentManager().beginTransaction(); - AuthErrorDialogFragment authAlert; - // Default to isDotCom (If WordPress.getCurrentBlog() == null: no blogs found, - // so the user is logged in wpcom and doesn't own any blog - boolean isDotCom = true; - if (WordPress.getCurrentBlog() != null) { - isDotCom = WordPress.getCurrentBlog().isDotcomFlag(); - } - authAlert = new AuthErrorDialogFragment(); - authAlert.setWPComTitleMessage(isDotCom, titleResId, messageResId); + AuthErrorDialogFragment authAlert = new AuthErrorDialogFragment(); + authAlert.setWPComTitleMessage(titleResId, messageResId); ft.add(authAlert, ALERT_TAG); ft.commitAllowingStateLoss(); } diff --git a/WordPress/src/main/java/org/wordpress/android/widgets/AuthErrorDialogFragment.java b/WordPress/src/main/java/org/wordpress/android/widgets/AuthErrorDialogFragment.java index 9c5fa4500..417810803 100644 --- a/WordPress/src/main/java/org/wordpress/android/widgets/AuthErrorDialogFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/widgets/AuthErrorDialogFragment.java @@ -9,7 +9,6 @@ import android.os.Bundle; import org.wordpress.android.R; import org.wordpress.android.WordPress; -import org.wordpress.android.ui.accounts.WPComLoginActivity; import org.wordpress.android.ui.prefs.BlogPreferencesActivity; /** @@ -18,17 +17,12 @@ import org.wordpress.android.ui.prefs.BlogPreferencesActivity; public class AuthErrorDialogFragment extends DialogFragment { public static int DEFAULT_RESOURCE_ID = -1; - private boolean mIsWPCom; private int mMessageId = R.string.incorrect_credentials; private int mTitleId = R.string.connection_error; - public void setWPComTitleMessage(boolean isWPCom, int titleResourceId, int messageResourceId) { - mIsWPCom = isWPCom; - + public void setWPComTitleMessage(int titleResourceId, int messageResourceId) { if (titleResourceId != DEFAULT_RESOURCE_ID) { mTitleId = titleResourceId; - } else if (mIsWPCom) { - mTitleId = R.string.wpcom_signin_dialog_title; } else { mTitleId = R.string.connection_error; } @@ -53,32 +47,20 @@ public class AuthErrorDialogFragment extends DialogFragment { AlertDialog.Builder b = new AlertDialog.Builder(getActivity()); b.setTitle(mTitleId); b.setMessage(mMessageId); - if (mIsWPCom) { - b.setPositiveButton(R.string.sign_in, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Intent authIntent = new Intent(getActivity(), WPComLoginActivity.class); - authIntent.putExtra("wpcom", true); - authIntent.putExtra("auth-only", true); - getActivity().startActivityForResult(authIntent, WPComLoginActivity.REQUEST_CODE); - } - }); - } else { - b.setCancelable(true); - b.setPositiveButton(R.string.settings, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - Intent settingsIntent = new Intent(getActivity(), BlogPreferencesActivity.class); - settingsIntent.putExtra("id", WordPress.getCurrentBlog().getLocalTableBlogId()); - getActivity().startActivity(settingsIntent); - } - }); - b.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - } - }); - } + b.setCancelable(true); + b.setPositiveButton(R.string.settings, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Intent settingsIntent = new Intent(getActivity(), BlogPreferencesActivity.class); + settingsIntent.putExtra("id", WordPress.getCurrentBlog().getLocalTableBlogId()); + getActivity().startActivity(settingsIntent); + } + }); + b.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + } + }); return b.create(); } }
\ No newline at end of file |