aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java139
1 files changed, 74 insertions, 65 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java
index 89575338f..19a05790f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/ImportOperation.java
@@ -28,7 +28,7 @@ import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
-import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -82,6 +82,8 @@ import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
*/
public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
+ public static final int MAX_THREADS = 10;
+
public ImportOperation(Context context, ProviderHelper providerHelper, Progressable
progressable) {
super(context, providerHelper, progressable);
@@ -133,7 +135,7 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
@NonNull
private ImportKeyResult serialKeyRingImport(Iterator<ParcelableKeyRing> entries, int num,
String keyServerUri, Progressable progressable,
- Proxy proxy) {
+ @NonNull Proxy proxy) {
if (progressable != null) {
progressable.setProgress(R.string.progress_importing, 0, 100);
}
@@ -188,7 +190,7 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
// Make sure we have the keyserver instance cached
if (keyServer == null) {
log.add(LogType.MSG_IMPORT_KEYSERVER, 1, keyServerUri);
- keyServer = new HkpKeyserver(keyServerUri);
+ keyServer = new HkpKeyserver(keyServerUri, proxy);
}
try {
@@ -197,11 +199,10 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
if (entry.mExpectedFingerprint != null) {
log.add(LogType.MSG_IMPORT_FETCH_KEYSERVER, 2, "0x" +
entry.mExpectedFingerprint.substring(24));
- data = keyServer.get("0x" + entry.mExpectedFingerprint, proxy)
- .getBytes();
+ data = keyServer.get("0x" + entry.mExpectedFingerprint).getBytes();
} else {
log.add(LogType.MSG_IMPORT_FETCH_KEYSERVER, 2, entry.mKeyIdHex);
- data = keyServer.get(entry.mKeyIdHex, proxy).getBytes();
+ data = keyServer.get(entry.mKeyIdHex).getBytes();
}
key = UncachedKeyRing.decodeFromData(data);
if (key != null) {
@@ -219,12 +220,12 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
if (entry.mKeybaseName != null) {
// Make sure we have this cached
if (keybaseServer == null) {
- keybaseServer = new KeybaseKeyserver();
+ keybaseServer = new KeybaseKeyserver(proxy);
}
try {
log.add(LogType.MSG_IMPORT_FETCH_KEYBASE, 2, entry.mKeybaseName);
- byte[] data = keybaseServer.get(entry.mKeybaseName, proxy).getBytes();
+ byte[] data = keybaseServer.get(entry.mKeybaseName).getBytes();
UncachedKeyRing keybaseKey = UncachedKeyRing.decodeFromData(data);
// If there already is a key, merge the two
@@ -261,12 +262,6 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
continue;
}
- // Another check if we have been cancelled
- if (checkCancelled()) {
- cancelled = true;
- break;
- }
-
SaveKeyringResult result;
// synchronizing prevents https://github.com/open-keychain/open-keychain/issues/1221
// and https://github.com/open-keychain/open-keychain/issues/1480
@@ -365,13 +360,15 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
}
}
- // Final log entry, it's easier to do this individually
- if ((newKeys > 0 || updatedKeys > 0) && badKeys > 0) {
- log.add(LogType.MSG_IMPORT_PARTIAL, 1);
- } else if (newKeys > 0 || updatedKeys > 0) {
- log.add(LogType.MSG_IMPORT_SUCCESS, 1);
- } else {
- log.add(LogType.MSG_IMPORT_ERROR, 1);
+ if (!cancelled) {
+ // Final log entry, it's easier to do this individually
+ if ((newKeys > 0 || updatedKeys > 0) && badKeys > 0) {
+ log.add(LogType.MSG_IMPORT_PARTIAL, 1);
+ } else if (newKeys > 0 || updatedKeys > 0) {
+ log.add(LogType.MSG_IMPORT_SUCCESS, 1);
+ } else {
+ log.add(LogType.MSG_IMPORT_ERROR, 1);
+ }
}
return new ImportKeyResult(resultType, log, newKeys, updatedKeys, badKeys, secret,
@@ -400,8 +397,7 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
return new ImportKeyResult(null,
RequiredInputParcel.createOrbotRequiredOperation(), cryptoInput);
}
- proxy = Preferences.getPreferences(mContext).getProxyPrefs().parcelableProxy
- .getProxy();
+ proxy = Preferences.getPreferences(mContext).getProxyPrefs().getProxy();
} else {
proxy = cryptoInput.getParcelableProxy().getProxy();
}
@@ -414,62 +410,61 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
}
@NonNull
- private ImportKeyResult multiThreadedKeyImport(Iterator<ParcelableKeyRing> keyListIterator,
+ private ImportKeyResult multiThreadedKeyImport(@NonNull Iterator<ParcelableKeyRing> keyListIterator,
int totKeys, final String keyServer,
final Proxy proxy) {
Log.d(Constants.TAG, "Multi-threaded key import starting");
- if (keyListIterator != null) {
- KeyImportAccumulator accumulator = new KeyImportAccumulator(totKeys, mProgressable);
-
- final ProgressScaler ignoreProgressable = new ProgressScaler();
+ KeyImportAccumulator accumulator = new KeyImportAccumulator(totKeys, mProgressable);
- final int maxThreads = 200;
- ExecutorService importExecutor = new ThreadPoolExecutor(0, maxThreads,
- 30L, TimeUnit.SECONDS,
- new SynchronousQueue<Runnable>());
+ final ProgressScaler ignoreProgressable = new ProgressScaler();
- ExecutorCompletionService<ImportKeyResult> importCompletionService =
- new ExecutorCompletionService<>(importExecutor);
+ ExecutorService importExecutor = new ThreadPoolExecutor(0, MAX_THREADS, 30L, TimeUnit.SECONDS,
+ new LinkedBlockingQueue<Runnable>());
- while (keyListIterator.hasNext()) { // submit all key rings to be imported
+ ExecutorCompletionService<ImportKeyResult> importCompletionService =
+ new ExecutorCompletionService<>(importExecutor);
- final ParcelableKeyRing pkRing = keyListIterator.next();
+ while (keyListIterator.hasNext()) { // submit all key rings to be imported
- Callable<ImportKeyResult> importOperationCallable = new Callable<ImportKeyResult>
- () {
+ final ParcelableKeyRing pkRing = keyListIterator.next();
- @Override
- public ImportKeyResult call() {
+ Callable<ImportKeyResult> importOperationCallable = new Callable<ImportKeyResult>
+ () {
- ArrayList<ParcelableKeyRing> list = new ArrayList<>();
- list.add(pkRing);
+ @Override
+ public ImportKeyResult call() {
- return serialKeyRingImport(list.iterator(), 1, keyServer,
- ignoreProgressable, proxy);
+ if (checkCancelled()) {
+ return null;
}
- };
- importCompletionService.submit(importOperationCallable);
- }
+ ArrayList<ParcelableKeyRing> list = new ArrayList<>();
+ list.add(pkRing);
- while (!accumulator.isImportFinished()) { // accumulate the results of each import
- try {
- accumulator.accumulateKeyImport(importCompletionService.take().get());
- } catch (InterruptedException | ExecutionException e) {
- Log.e(Constants.TAG, "A key could not be imported during multi-threaded " +
- "import", e);
- // do nothing?
- if (e instanceof ExecutionException) {
- // Since serialKeyRingImport does not throw any exceptions, this is what
- // would have happened if
- // we were importing the key on this thread
- throw new RuntimeException();
- }
+ return serialKeyRingImport(list.iterator(), 1, keyServer, ignoreProgressable, proxy);
+ }
+ };
+
+ importCompletionService.submit(importOperationCallable);
+ }
+
+ while (!accumulator.isImportFinished()) { // accumulate the results of each import
+ try {
+ accumulator.accumulateKeyImport(importCompletionService.take().get());
+ } catch (InterruptedException | ExecutionException e) {
+ Log.e(Constants.TAG, "A key could not be imported during multi-threaded " +
+ "import", e);
+ // do nothing?
+ if (e instanceof ExecutionException) {
+ // Since serialKeyRingImport does not throw any exceptions, this is what
+ // would have happened if
+ // we were importing the key on this thread
+ throw new RuntimeException();
}
}
- return accumulator.getConsolidatedResult();
}
- return new ImportKeyResult(ImportKeyResult.RESULT_FAIL_NOTHING, new OperationLog());
+ return accumulator.getConsolidatedResult();
+
}
/**
@@ -486,6 +481,7 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
private int mUpdatedKeys = 0;
private int mSecret = 0;
private int mResultType = 0;
+ private boolean mHasCancelledResult;
/**
* Accumulates keyring imports and updates the progressable whenever a new key is imported.
@@ -503,14 +499,25 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
}
}
- public synchronized void accumulateKeyImport(ImportKeyResult result) {
+ public void accumulateKeyImport(ImportKeyResult result) {
mImportedKeys++;
+ if (result == null) {
+ return;
+ }
+
if (mProgressable != null) {
mProgressable.setProgress(mImportedKeys, mTotalKeys);
}
- mImportLog.addAll(result.getLog().toList());//accumulates log
+ boolean notCancelledOrFirstCancelled = !result.cancelled() || !mHasCancelledResult;
+ if (notCancelledOrFirstCancelled) {
+ mImportLog.addAll(result.getLog().toList()); //accumulates log
+ if (result.cancelled()) {
+ mHasCancelledResult = true;
+ }
+ }
+
mBadKeys += result.mBadKeys;
mNewKeys += result.mNewKeys;
mUpdatedKeys += result.mUpdatedKeys;
@@ -533,7 +540,9 @@ public class ImportOperation extends BaseOperation<ImportKeyringParcel> {
// adding required information to mResultType
// special case,no keys requested for import
- if (mBadKeys == 0 && mNewKeys == 0 && mUpdatedKeys == 0) {
+ if (mBadKeys == 0 && mNewKeys == 0 && mUpdatedKeys == 0
+ && (mResultType & ImportKeyResult.RESULT_CANCELLED)
+ != ImportKeyResult.RESULT_CANCELLED) {
mResultType = ImportKeyResult.RESULT_FAIL_NOTHING;
} else {
if (mNewKeys > 0) {