CloudSearch: Add error message when no source selected

This commit is contained in:
Andrea Torlaschi 2016-07-27 22:05:42 +02:00
parent d947db2569
commit 7b7efa1a73
6 changed files with 58 additions and 46 deletions

View file

@ -17,6 +17,8 @@
package org.sufficientlysecure.keychain.keyimport;
import android.support.annotation.NonNull;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Preferences;
@ -25,8 +27,6 @@ import java.net.Proxy;
import java.util.ArrayList;
import java.util.Vector;
import android.support.annotation.NonNull;
/**
* Search two or more types of server for online keys.
*/
@ -37,8 +37,8 @@ public class CloudSearch {
public static ArrayList<ImportKeysListEntry> search(
@NonNull final String query, Preferences.CloudSearchPrefs cloudPrefs, @NonNull Proxy proxy)
throws Keyserver.CloudSearchFailureException {
final ArrayList<Keyserver> servers = new ArrayList<>();
final ArrayList<Keyserver> servers = new ArrayList<>();
// it's a Vector for sync, multiple threads might report problems
final Vector<Keyserver.CloudSearchFailureException> problems = new Vector<>();
@ -51,46 +51,48 @@ public class CloudSearch {
if (cloudPrefs.searchFacebook) {
servers.add(new FacebookKeyserver(proxy));
}
final ImportKeysList results = new ImportKeysList(servers.size());
ArrayList<Thread> searchThreads = new ArrayList<>();
for (final Keyserver keyserver : servers) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
results.addAll(keyserver.search(query));
} catch (Keyserver.CloudSearchFailureException e) {
problems.add(e);
int numberOfServers = servers.size();
final ImportKeysList results = new ImportKeysList(numberOfServers);
if (numberOfServers > 0) {
ArrayList<Thread> searchThreads = new ArrayList<>();
for (final Keyserver keyserver : servers) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
results.addAll(keyserver.search(query));
} catch (Keyserver.CloudSearchFailureException e) {
problems.add(e);
}
results.finishedAdding(); // notifies if all searchers done
}
results.finishedAdding(); // notifies if all searchers done
}
};
Thread searchThread = new Thread(r);
searchThreads.add(searchThread);
searchThread.start();
}
// wait for either all the searches to come back, or 10 seconds. If using proxy, wait 30 seconds.
synchronized (results) {
try {
if (proxy == Proxy.NO_PROXY) {
results.wait(30 * SECONDS);
} else {
results.wait(10 * SECONDS);
}
for (Thread thread : searchThreads) {
// kill threads that haven't returned yet
thread.interrupt();
}
} catch (InterruptedException ignored) {
};
Thread searchThread = new Thread(r);
searchThreads.add(searchThread);
searchThread.start();
}
}
if (results.outstandingSuppliers() > 0) {
String message = "Launched " + servers.size() + " cloud searchers, but " +
results.outstandingSuppliers() + "failed to complete.";
problems.add(new Keyserver.QueryFailedException(message));
// wait for either all the searches to come back, or 10 seconds. If using proxy, wait 30 seconds.
synchronized (results) {
try {
results.wait((proxy == Proxy.NO_PROXY ? 30 : 10) * SECONDS);
for (Thread thread : searchThreads) {
// kill threads that haven't returned yet
thread.interrupt();
}
} catch (InterruptedException ignored) {
}
}
if (results.outstandingSuppliers() > 0) {
String message = "Launched " + servers.size() + " cloud searchers, but " +
results.outstandingSuppliers() + "failed to complete.";
problems.add(new Keyserver.QueryFailedException(message));
}
} else {
problems.add(new Keyserver.QueryNoEnabledSourceException());
}
if (!problems.isEmpty()) {

View file

@ -64,6 +64,10 @@ public abstract class Keyserver {
private static final long serialVersionUID = 2703768928624654518L;
}
public static class QueryNoEnabledSourceException extends QueryNeedsRepairException {
private static final long serialVersionUID = 2703768928624654519L;
}
public static class AddKeyException extends Exception {
private static final long serialVersionUID = -507574859137295530L;
}

View file

@ -175,6 +175,9 @@ public class ImportKeysListCloudLoader
} else if (e instanceof Keyserver.QueryTooShortOrTooManyResponsesException) {
error = GetKeyResult.RESULT_ERROR_TOO_SHORT_OR_TOO_MANY_RESPONSES;
logType = OperationResult.LogType.MSG_GET_QUERY_TOO_SHORT_OR_TOO_MANY_RESPONSES;
} else if (e instanceof Keyserver.QueryNoEnabledSourceException) {
error = GetKeyResult.RESULT_ERROR_NO_ENABLED_SOURCE;
logType = OperationResult.LogType.MSG_GET_NO_ENABLED_SOURCE;
}
OperationResult.OperationLog log = new OperationResult.OperationLog();
log.add(logType, 0);

View file

@ -44,13 +44,14 @@ public class GetKeyResult extends InputPendingResult {
super(log, requiredInput, cryptoInputParcel);
}
public static final int RESULT_ERROR_NO_VALID_KEYS = RESULT_ERROR + (1<<4);
public static final int RESULT_ERROR_NO_PGP_PARTS = RESULT_ERROR + (2<<4);
public static final int RESULT_ERROR_QUERY_TOO_SHORT = RESULT_ERROR + (3<<4);
public static final int RESULT_ERROR_TOO_MANY_RESPONSES = RESULT_ERROR + (4<<4);
public static final int RESULT_ERROR_TOO_SHORT_OR_TOO_MANY_RESPONSES = RESULT_ERROR + (5<<4);
public static final int RESULT_ERROR_QUERY_FAILED = RESULT_ERROR + (6<<4);
public static final int RESULT_ERROR_FILE_NOT_FOUND = RESULT_ERROR + (7<<4);
public static final int RESULT_ERROR_NO_VALID_KEYS = RESULT_ERROR + (1 << 4);
public static final int RESULT_ERROR_NO_PGP_PARTS = RESULT_ERROR + (2 << 4);
public static final int RESULT_ERROR_QUERY_TOO_SHORT = RESULT_ERROR + (3 << 4);
public static final int RESULT_ERROR_TOO_MANY_RESPONSES = RESULT_ERROR + (4 << 4);
public static final int RESULT_ERROR_TOO_SHORT_OR_TOO_MANY_RESPONSES = RESULT_ERROR + (5 << 4);
public static final int RESULT_ERROR_QUERY_FAILED = RESULT_ERROR + (6 << 4);
public static final int RESULT_ERROR_FILE_NOT_FOUND = RESULT_ERROR + (7 << 4);
public static final int RESULT_ERROR_NO_ENABLED_SOURCE = RESULT_ERROR + (8 << 4);
public GetKeyResult(Parcel source) {
super(source);

View file

@ -818,6 +818,7 @@ public abstract class OperationResult implements Parcelable {
MSG_GET_QUERY_TOO_SHORT_OR_TOO_MANY_RESPONSES (LogLevel.ERROR, R.string.msg_get_query_too_short_or_too_many_responses),
MSG_GET_QUERY_FAILED (LogLevel.ERROR, R.string.msg_download_query_failed),
MSG_GET_FILE_NOT_FOUND (LogLevel.ERROR, R.string.msg_get_file_not_found),
MSG_GET_NO_ENABLED_SOURCE (LogLevel.ERROR, R.string.msg_get_no_enabled_source),
MSG_DEL_ERROR_EMPTY (LogLevel.ERROR, R.string.msg_del_error_empty),
MSG_DEL_ERROR_MULTI_SECRET (LogLevel.ERROR, R.string.msg_del_error_multi_secret),

View file

@ -1440,6 +1440,7 @@
<string name="msg_get_too_many_responses">"Key search query returned too many candidates. Please refine your query!"</string>
<string name="msg_get_query_too_short">"Search query too short. Please refine your query!"</string>
<string name="msg_get_query_too_short_or_too_many_responses">"Either no keys or too many have been found. Please improve your query!"</string>
<string name="msg_get_no_enabled_source">"Enable at least one source for downloading!"</string>
<string name="msg_download_query_failed">"An error occurred when searching for keys."</string>