Merge pull request #306 from danielhass/keyserver-conerror

Show error if keyserver is not reachable
This commit is contained in:
Dominik Schürmann 2014-02-28 23:27:57 +01:00
commit 0c60eea628
5 changed files with 102 additions and 27 deletions

View File

@ -27,11 +27,13 @@ import java.util.List;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.Preferences; import org.sufficientlysecure.keychain.helper.Preferences;
import org.sufficientlysecure.keychain.ui.adapter.AsyncTaskResultWrapper;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListServerLoader; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListServerLoader;
import org.sufficientlysecure.keychain.util.InputData; import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.KeyServer;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import android.app.Activity; import android.app.Activity;
@ -42,10 +44,11 @@ import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader; import android.support.v4.content.Loader;
import android.view.View; import android.view.View;
import android.widget.ListView; import android.widget.ListView;
import android.widget.Toast;
import com.devspark.appmsg.AppMsg;
public class ImportKeysListFragment extends ListFragment implements public class ImportKeysListFragment extends ListFragment implements
LoaderManager.LoaderCallbacks<List<ImportKeysListEntry>> { LoaderManager.LoaderCallbacks<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
private static final String ARG_DATA_URI = "uri"; private static final String ARG_DATA_URI = "uri";
private static final String ARG_BYTES = "bytes"; private static final String ARG_BYTES = "bytes";
private static final String ARG_SERVER_QUERY = "query"; private static final String ARG_SERVER_QUERY = "query";
@ -181,11 +184,10 @@ public class ImportKeysListFragment extends ListFragment implements
} }
@Override @Override
public Loader<List<ImportKeysListEntry>> onCreateLoader(int id, Bundle args) { public Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> onCreateLoader(int id, Bundle args) {
switch (id) { switch (id) {
case LOADER_ID_BYTES: { case LOADER_ID_BYTES: {
InputData inputData = getInputData(mKeyBytes, mDataUri); InputData inputData = getInputData(mKeyBytes, mDataUri);
return new ImportKeysListLoader(mActivity, inputData); return new ImportKeysListLoader(mActivity, inputData);
} }
case LOADER_ID_SERVER_QUERY: { case LOADER_ID_SERVER_QUERY: {
@ -198,15 +200,15 @@ public class ImportKeysListFragment extends ListFragment implements
} }
@Override @Override
public void onLoadFinished(Loader<List<ImportKeysListEntry>> loader, public void onLoadFinished(Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> loader,
List<ImportKeysListEntry> data) { AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> data) {
// Swap the new cursor in. (The framework will take care of closing the // Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.) // old cursor once we return.)
Log.d(Constants.TAG, "data: " + data); Log.d(Constants.TAG, "data: " + data.getResult());
// swap in the real data! // swap in the real data!
mAdapter.setData(data); mAdapter.setData(data.getResult());
mAdapter.notifyDataSetChanged(); mAdapter.notifyDataSetChanged();
setListAdapter(mAdapter); setListAdapter(mAdapter);
@ -222,11 +224,25 @@ public class ImportKeysListFragment extends ListFragment implements
break; break;
case LOADER_ID_SERVER_QUERY: case LOADER_ID_SERVER_QUERY:
Toast.makeText(
Exception error = data.getError();
if(error == null){
AppMsg.makeText(
getActivity(), getResources().getQuantityString(R.plurals.keys_found, getActivity(), getResources().getQuantityString(R.plurals.keys_found,
mAdapter.getCount(), mAdapter.getCount()), mAdapter.getCount(), mAdapter.getCount()),
Toast.LENGTH_SHORT AppMsg.STYLE_INFO
).show(); ).show();
} else if(error instanceof KeyServer.InsufficientQuery){
AppMsg.makeText(getActivity(), R.string.error_keyserver_insufficient_query,
AppMsg.STYLE_ALERT).show();
}else if(error instanceof KeyServer.QueryException){
AppMsg.makeText(getActivity(), R.string.error_keyserver_query,
AppMsg.STYLE_ALERT).show();
}else if(error instanceof KeyServer.TooManyResponses){
AppMsg.makeText(getActivity(), R.string.error_keyserver_too_many_responses,
AppMsg.STYLE_ALERT).show();
}
break; break;
default: default:
@ -235,7 +251,7 @@ public class ImportKeysListFragment extends ListFragment implements
} }
@Override @Override
public void onLoaderReset(Loader<List<ImportKeysListEntry>> loader) { public void onLoaderReset(Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> loader) {
switch (loader.getId()) { switch (loader.getId()) {
case LOADER_ID_BYTES: case LOADER_ID_BYTES:
// Clear the data in the adapter. // Clear the data in the adapter.

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.ui.adapter;
/**
* The AsyncTaskResultWrapper is used to wrap a result from a AsyncTask (for example: Loader).
* You can pass the result and an exception in it if an error occurred.
* Concept found at:
* https://stackoverflow.com/questions/19593577/how-to-handle-errors-in-custom-asynctaskloader
* @param <T> - Typ of the result which is wrapped
*/
public class AsyncTaskResultWrapper <T>{
private final T result;
private final Exception error;
public AsyncTaskResultWrapper(T result, Exception error){
this.result = result;
this.error = error;
}
public T getResult() {
return result;
}
public Exception getError() {
return error;
}
}

View File

@ -33,12 +33,13 @@ import org.sufficientlysecure.keychain.util.PositionAwareInputStream;
import android.content.Context; import android.content.Context;
import android.support.v4.content.AsyncTaskLoader; import android.support.v4.content.AsyncTaskLoader;
public class ImportKeysListLoader extends AsyncTaskLoader<List<ImportKeysListEntry>> { public class ImportKeysListLoader extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
Context mContext; Context mContext;
InputData mInputData; InputData mInputData;
ArrayList<ImportKeysListEntry> data = new ArrayList<ImportKeysListEntry>(); ArrayList<ImportKeysListEntry> data = new ArrayList<ImportKeysListEntry>();
AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> entryListWrapper;
public ImportKeysListLoader(Context context, InputData inputData) { public ImportKeysListLoader(Context context, InputData inputData) {
super(context); super(context);
@ -47,15 +48,18 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<ImportKeysListEnt
} }
@Override @Override
public List<ImportKeysListEntry> loadInBackground() { public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() {
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(data, null);
if (mInputData == null) { if (mInputData == null) {
Log.e(Constants.TAG, "Input data is null!"); Log.e(Constants.TAG, "Input data is null!");
return data; return entryListWrapper;
} }
generateListOfKeyrings(mInputData); generateListOfKeyrings(mInputData);
return data; return entryListWrapper;
} }
@Override @Override
@ -77,7 +81,7 @@ public class ImportKeysListLoader extends AsyncTaskLoader<List<ImportKeysListEnt
} }
@Override @Override
public void deliverResult(List<ImportKeysListEntry> data) { public void deliverResult(AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> data) {
super.deliverResult(data); super.deliverResult(data);
} }

View File

@ -26,15 +26,15 @@ import org.sufficientlysecure.keychain.util.KeyServer;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
public class ImportKeysListServerLoader extends AsyncTaskLoader<List<ImportKeysListEntry>> { public class ImportKeysListServerLoader extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
Context mContext; Context mContext;
String mServerQuery; String mServerQuery;
String mKeyServer; String mKeyServer;
ArrayList<ImportKeysListEntry> data = new ArrayList<ImportKeysListEntry>(); private ArrayList<ImportKeysListEntry> entryList = new ArrayList<ImportKeysListEntry>();
private AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> entryListWrapper;
public ImportKeysListServerLoader(Context context, String serverQuery, String keyServer) { public ImportKeysListServerLoader(Context context, String serverQuery, String keyServer) {
super(context); super(context);
@ -44,15 +44,18 @@ public class ImportKeysListServerLoader extends AsyncTaskLoader<List<ImportKeysL
} }
@Override @Override
public List<ImportKeysListEntry> loadInBackground() { public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() {
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, null);
if (mServerQuery == null) { if (mServerQuery == null) {
Log.e(Constants.TAG, "mServerQuery is null!"); Log.e(Constants.TAG, "mServerQuery is null!");
return data; return entryListWrapper;
} }
queryServer(mServerQuery, mKeyServer); queryServer(mServerQuery, mKeyServer);
return data; return entryListWrapper;
} }
@Override @Override
@ -74,7 +77,7 @@ public class ImportKeysListServerLoader extends AsyncTaskLoader<List<ImportKeysL
} }
@Override @Override
public void deliverResult(List<ImportKeysListEntry> data) { public void deliverResult(AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> data) {
super.deliverResult(data); super.deliverResult(data);
} }
@ -87,13 +90,17 @@ public class ImportKeysListServerLoader extends AsyncTaskLoader<List<ImportKeysL
ArrayList<ImportKeysListEntry> searchResult = server.search(query); ArrayList<ImportKeysListEntry> searchResult = server.search(query);
// add result to data // add result to data
data.addAll(searchResult); entryList.addAll(searchResult);
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, null);
} catch (KeyServer.InsufficientQuery e) { } catch (KeyServer.InsufficientQuery e) {
Log.e(Constants.TAG, "InsufficientQuery", e); Log.e(Constants.TAG, "InsufficientQuery", e);
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, e);
} catch (KeyServer.QueryException e) { } catch (KeyServer.QueryException e) {
Log.e(Constants.TAG, "QueryException", e); Log.e(Constants.TAG, "QueryException", e);
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, e);
} catch (KeyServer.TooManyResponses e) { } catch (KeyServer.TooManyResponses e) {
Log.e(Constants.TAG, "TooManyResponses", e); Log.e(Constants.TAG, "TooManyResponses", e);
entryListWrapper = new AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>(entryList, e);
} }
} }

View File

@ -286,6 +286,9 @@
<string name="error_expiry_must_come_after_creation">expiry date must come after creation date</string> <string name="error_expiry_must_come_after_creation">expiry date must come after creation date</string>
<string name="error_can_not_delete_contact">you can not delete this contact because it is your own.</string> <string name="error_can_not_delete_contact">you can not delete this contact because it is your own.</string>
<string name="error_can_not_delete_contacts">you can not delete the following contacts because they are your own:\n%s</string> <string name="error_can_not_delete_contacts">you can not delete the following contacts because they are your own:\n%s</string>
<string name="error_keyserver_insufficient_query">Insufficient server query</string>
<string name="error_keyserver_query">Querying keyserver failed</string>
<string name="error_keyserver_too_many_responses">Too many responses</string>
<plurals name="error_can_not_delete_info"> <plurals name="error_can_not_delete_info">
<item quantity="one">Please delete it from the \'My Keys\' screen!</item> <item quantity="one">Please delete it from the \'My Keys\' screen!</item>
<item quantity="other">Please delete them from the \'My Keys\' screen!</item> <item quantity="other">Please delete them from the \'My Keys\' screen!</item>