ImportKeys: Refactoring

This commit is contained in:
Andrea Torlaschi
2016-08-21 17:19:42 +02:00
parent 4e661886b1
commit f5e5a70d21
7 changed files with 49 additions and 115 deletions

View File

@@ -41,9 +41,7 @@ public class ImportKeysListCloudLoader
extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> { extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
private Context mContext; private Context mContext;
private CloudLoaderState mState;
private String mServerQuery;
private Preferences.CloudSearchPrefs mCloudPrefs;
private ParcelableProxy mParcelableProxy; private ParcelableProxy mParcelableProxy;
private ArrayList<ImportKeysListEntry> mEntryList = new ArrayList<>(); private ArrayList<ImportKeysListEntry> mEntryList = new ArrayList<>();
@@ -52,20 +50,18 @@ public class ImportKeysListCloudLoader
/** /**
* Searches a keyserver as specified in cloudPrefs, using an explicit proxy if passed * Searches a keyserver as specified in cloudPrefs, using an explicit proxy if passed
* *
* @param serverQuery string to search on servers for. If is a fingerprint, * @param loaderState state containing the string to search on servers for (if it is a
* will enforce fingerprint check * fingerprint, will enforce fingerprint check) and the keyserver to
* @param cloudPrefs contains keyserver to search on, whether to search on the keyserver, * search on (whether to search on the keyserver, and whether to search
* and whether to search keybase.io * keybase.io)
* @param parcelableProxy explicit proxy to use. If null, will retrieve from preferences * @param parcelableProxy explicit proxy to use. If null, will retrieve from preferences
*/ */
public ImportKeysListCloudLoader(Context context, String serverQuery, public ImportKeysListCloudLoader(Context context, CloudLoaderState loaderState,
Preferences.CloudSearchPrefs cloudPrefs,
@Nullable ParcelableProxy parcelableProxy) { @Nullable ParcelableProxy parcelableProxy) {
super(context); super(context);
mContext = context; mContext = context;
mServerQuery = serverQuery; mState = loaderState;
mCloudPrefs = cloudPrefs;
mParcelableProxy = parcelableProxy; mParcelableProxy = parcelableProxy;
} }
@@ -73,12 +69,12 @@ public class ImportKeysListCloudLoader
public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() { public AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> loadInBackground() {
mEntryListWrapper = new AsyncTaskResultWrapper<>(mEntryList, null); mEntryListWrapper = new AsyncTaskResultWrapper<>(mEntryList, null);
if (mServerQuery == null) { if (mState.mServerQuery == null) {
Log.e(Constants.TAG, "mServerQuery is null!"); Log.e(Constants.TAG, "mServerQuery is null!");
return mEntryListWrapper; return mEntryListWrapper;
} }
if (mServerQuery.startsWith("0x") && mServerQuery.length() == 42) { if (mState.mServerQuery.startsWith("0x") && mState.mServerQuery.length() == 42) {
Log.d(Constants.TAG, "This search is based on a unique fingerprint. Enforce a fingerprint check!"); Log.d(Constants.TAG, "This search is based on a unique fingerprint. Enforce a fingerprint check!");
queryServer(true); queryServer(true);
} else { } else {
@@ -143,15 +139,15 @@ public class ImportKeysListCloudLoader
try { try {
ArrayList<ImportKeysListEntry> searchResult = CloudSearch.search( ArrayList<ImportKeysListEntry> searchResult = CloudSearch.search(
mServerQuery, mState.mServerQuery,
mCloudPrefs, mState.mCloudPrefs,
parcelableProxy.getProxy() parcelableProxy.getProxy()
); );
mEntryList.clear(); mEntryList.clear();
// add result to data // add result to data
if (enforceFingerprint) { if (enforceFingerprint) {
String fingerprint = mServerQuery.substring(2); String fingerprint = mState.mServerQuery.substring(2);
Log.d(Constants.TAG, "fingerprint: " + fingerprint); Log.d(Constants.TAG, "fingerprint: " + fingerprint);
// query must return only one result! // query must return only one result!
if (searchResult.size() == 1) { if (searchResult.size() == 1) {

View File

@@ -24,7 +24,6 @@ import android.support.v4.content.AsyncTaskLoader;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.operations.results.GetKeyResult; import org.sufficientlysecure.keychain.operations.results.GetKeyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType; import org.sufficientlysecure.keychain.operations.results.OperationResult.LogType;
@@ -42,22 +41,20 @@ import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
public class ImportKeysListLoader public class ImportKeysListLoader
extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> { extends AsyncTaskLoader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
private final Context mContext; private Context mContext;
private final BytesLoaderState mLoaderState; private BytesLoaderState mState;
private ArrayList<ImportKeysListEntry> mData = new ArrayList<>(); private ArrayList<ImportKeysListEntry> mData = new ArrayList<>();
private ArrayList<ParcelableKeyRing> mParcelableRings = new ArrayList<>();
private AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> mEntryListWrapper; private AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> mEntryListWrapper;
public ImportKeysListLoader(Context context, BytesLoaderState inputData) { public ImportKeysListLoader(Context context, BytesLoaderState loaderState) {
super(context); super(context);
this.mContext = context; mContext = context;
this.mLoaderState = inputData; mState = loaderState;
} }
@Override @Override
@@ -72,13 +69,13 @@ public class ImportKeysListLoader
mEntryListWrapper = new AsyncTaskResultWrapper<>(mData, getKeyResult); mEntryListWrapper = new AsyncTaskResultWrapper<>(mData, getKeyResult);
} }
if (mLoaderState == null) { if (mState == null) {
Log.e(Constants.TAG, "Input data is null!"); Log.e(Constants.TAG, "Input data is null!");
return mEntryListWrapper; return mEntryListWrapper;
} }
try { try {
InputData inputData = getInputData(mLoaderState); InputData inputData = getInputData(mState);
generateListOfKeyrings(inputData); generateListOfKeyrings(inputData);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
OperationLog log = new OperationLog(); OperationLog log = new OperationLog();
@@ -108,15 +105,6 @@ public class ImportKeysListLoader
super.cancelLoad(); super.cancelLoad();
} }
@Override
public void deliverResult(AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> data) {
super.deliverResult(data);
}
public List<ParcelableKeyRing> getParcelableRings() {
return mParcelableRings;
}
/** /**
* Reads all PGPKeyRing objects from the bytes of an InputData object. * Reads all PGPKeyRing objects from the bytes of an InputData object.
*/ */
@@ -132,10 +120,7 @@ public class ImportKeysListLoader
// parse all keyrings // parse all keyrings
IteratorWithIOThrow<UncachedKeyRing> it = UncachedKeyRing.fromStream(bufferedInput); IteratorWithIOThrow<UncachedKeyRing> it = UncachedKeyRing.fromStream(bufferedInput);
while (it.hasNext()) { while (it.hasNext()) {
UncachedKeyRing ring = it.next(); mData.add(new ImportKeysListEntry(mContext, it.next()));
ImportKeysListEntry item = new ImportKeysListEntry(mContext, ring);
mData.add(item);
mParcelableRings.add(item.getParcelableKeyRing());
} }
} catch (IOException e) { } catch (IOException e) {
Log.e(Constants.TAG, "IOException on parsing key file! Return NoValidKeysException!", e); Log.e(Constants.TAG, "IOException on parsing key file! Return NoValidKeysException!", e);

View File

@@ -1,9 +1,13 @@
package org.sufficientlysecure.keychain.keyimport.processing; package org.sufficientlysecure.keychain.keyimport.processing;
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import java.util.List;
public interface ImportKeysListener extends ImportKeysResultListener { public interface ImportKeysListener extends ImportKeysResultListener {
void loadKeys(LoaderState loaderState); void loadKeys(LoaderState loaderState);
void importKeys(); void importKeys(List<ImportKeysListEntry> entries);
} }

View File

@@ -30,6 +30,7 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.intents.OpenKeychainIntents; import org.sufficientlysecure.keychain.intents.OpenKeychainIntents;
import org.sufficientlysecure.keychain.keyimport.FacebookKeyserver; import org.sufficientlysecure.keychain.keyimport.FacebookKeyserver;
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.keyimport.processing.ImportKeysListener; import org.sufficientlysecure.keychain.keyimport.processing.ImportKeysListener;
import org.sufficientlysecure.keychain.keyimport.processing.ImportKeysOperationCallback; import org.sufficientlysecure.keychain.keyimport.processing.ImportKeysOperationCallback;
@@ -46,6 +47,8 @@ import org.sufficientlysecure.keychain.util.ParcelableFileCache;
import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.util.Preferences;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class ImportKeysActivity extends BaseActivity implements ImportKeysListener { public class ImportKeysActivity extends BaseActivity implements ImportKeysListener {
@@ -317,11 +320,11 @@ public class ImportKeysActivity extends BaseActivity implements ImportKeysListen
} }
@Override @Override
public void importKeys() { public void importKeys(List<ImportKeysListEntry> entries) {
FragmentManager fM = getSupportFragmentManager(); List<ParcelableKeyRing> keyRings = new ArrayList<>();
ImportKeysListFragment listFragment = (ImportKeysListFragment) fM.findFragmentByTag(TAG_FRAG_LIST); for (ImportKeysListEntry e : entries) {
keyRings.add(e.getParcelableKeyRing());
Log.d(Constants.TAG, "importKeys started"); }
// instead of giving the entries by Intent extra, cache them into a // instead of giving the entries by Intent extra, cache them into a
// file to prevent Java Binder problems on heavy imports // file to prevent Java Binder problems on heavy imports
// read FileImportCache for more info. // read FileImportCache for more info.
@@ -330,7 +333,7 @@ public class ImportKeysActivity extends BaseActivity implements ImportKeysListen
// display here, we should be able to import. // display here, we should be able to import.
ParcelableFileCache<ParcelableKeyRing> cache = ParcelableFileCache<ParcelableKeyRing> cache =
new ParcelableFileCache<>(this, ImportOperation.CACHE_FILE_NAME); new ParcelableFileCache<>(this, ImportOperation.CACHE_FILE_NAME);
cache.writeCache(listFragment.getData()); cache.writeCache(entries.size(), keyRings.iterator());
} catch (IOException e) { } catch (IOException e) {
Log.e(Constants.TAG, "Problem writing cache file", e); Log.e(Constants.TAG, "Problem writing cache file", e);
Notify.create(this, "Problem writing cache file!", Notify.Style.ERROR).show(); Notify.create(this, "Problem writing cache file!", Notify.Style.ERROR).show();

View File

@@ -31,13 +31,13 @@ import android.support.v4.content.Loader;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.databinding.ImportKeysListFragmentBinding; import org.sufficientlysecure.keychain.databinding.ImportKeysListFragmentBinding;
import org.sufficientlysecure.keychain.databinding.ImportKeysListItemBasicBinding; import org.sufficientlysecure.keychain.databinding.ImportKeysListItemBasicBinding;
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.keyimport.processing.AsyncTaskResultWrapper; import org.sufficientlysecure.keychain.keyimport.processing.AsyncTaskResultWrapper;
import org.sufficientlysecure.keychain.keyimport.processing.BytesLoaderState; import org.sufficientlysecure.keychain.keyimport.processing.BytesLoaderState;
import org.sufficientlysecure.keychain.keyimport.processing.CloudLoaderState; import org.sufficientlysecure.keychain.keyimport.processing.CloudLoaderState;
@@ -49,15 +49,12 @@ import org.sufficientlysecure.keychain.operations.results.GetKeyResult;
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter;
import org.sufficientlysecure.keychain.ui.util.PermissionsUtil; import org.sufficientlysecure.keychain.ui.util.PermissionsUtil;
import org.sufficientlysecure.keychain.util.IteratorWithSize;
import org.sufficientlysecure.keychain.util.ParcelableProxy; import org.sufficientlysecure.keychain.util.ParcelableProxy;
import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.util.Preferences;
import org.sufficientlysecure.keychain.util.Preferences.CloudSearchPrefs; import org.sufficientlysecure.keychain.util.Preferences.CloudSearchPrefs;
import org.sufficientlysecure.keychain.util.orbot.OrbotHelper; import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ImportKeysListFragment extends Fragment implements public class ImportKeysListFragment extends Fragment implements
LoaderManager.LoaderCallbacks<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> { LoaderManager.LoaderCallbacks<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> {
@@ -69,13 +66,12 @@ public class ImportKeysListFragment extends Fragment implements
public static final String ARG_CLOUD_SEARCH_PREFS = "cloud_search_prefs"; public static final String ARG_CLOUD_SEARCH_PREFS = "cloud_search_prefs";
private FragmentActivity mActivity; private FragmentActivity mActivity;
private ImportKeysListener mCallback; private ImportKeysListener mListener;
private ImportKeysListFragmentBinding mBinding; private ImportKeysListFragmentBinding mBinding;
private ImportKeysListItemBasicBinding mBindingBasic; private ImportKeysListItemBasicBinding mBindingBasic;
private ParcelableProxy mParcelableProxy; private ParcelableProxy mParcelableProxy;
private List<ParcelableKeyRing> mKeyData;
private ImportKeysAdapter mAdapter; private ImportKeysAdapter mAdapter;
private LoaderState mLoaderState; private LoaderState mLoaderState;
@@ -154,7 +150,7 @@ public class ImportKeysListFragment extends Fragment implements
mBindingBasic.setNonInteractive(nonInteractive); mBindingBasic.setNonInteractive(nonInteractive);
// Create an empty adapter we will use to display the loaded data. // Create an empty adapter we will use to display the loaded data.
mAdapter = new ImportKeysAdapter(mActivity, mCallback, nonInteractive); mAdapter = new ImportKeysAdapter(mActivity, mListener, nonInteractive);
mBinding.recyclerView.setAdapter(mAdapter); mBinding.recyclerView.setAdapter(mAdapter);
mBinding.recyclerView.setLayoutManager(new LinearLayoutManager(mActivity)); mBinding.recyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
@@ -173,13 +169,13 @@ public class ImportKeysListFragment extends Fragment implements
restartLoaders(); restartLoaders();
} }
mBinding.basic.importKeys.setOnClickListener(new View.OnClickListener() { mBinding.basic.importKeys.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
mCallback.importKeys(); mListener.importKeys(mAdapter.getEntries());
} }
}); });
mBinding.basic.listKeys.setOnClickListener(new View.OnClickListener() { mBinding.basic.listKeys.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
mBinding.setAdvanced(true); mBinding.setAdvanced(true);
@@ -194,7 +190,7 @@ public class ImportKeysListFragment extends Fragment implements
super.onAttach(activity); super.onAttach(activity);
try { try {
mCallback = (ImportKeysListener) activity; mListener = (ImportKeysListener) activity;
} catch (ClassCastException e) { } catch (ClassCastException e) {
throw new ClassCastException(activity.toString() throw new ClassCastException(activity.toString()
+ " must implement ImportKeysListener"); + " must implement ImportKeysListener");
@@ -214,10 +210,6 @@ public class ImportKeysListFragment extends Fragment implements
} }
} }
public LoaderState getState() {
return mLoaderState;
}
public void loadState(LoaderState loaderState) { public void loadState(LoaderState loaderState) {
mLoaderState = loaderState; mLoaderState = loaderState;
@@ -255,9 +247,8 @@ public class ImportKeysListFragment extends Fragment implements
break; break;
} }
case LOADER_ID_CLOUD: { case LOADER_ID_CLOUD: {
CloudLoaderState ls = (CloudLoaderState) mLoaderState; loader = new ImportKeysListCloudLoader(mActivity, (CloudLoaderState) mLoaderState,
loader = new ImportKeysListCloudLoader(mActivity, ls.mServerQuery, mParcelableProxy);
ls.mCloudPrefs, mParcelableProxy);
break; break;
} }
} }
@@ -274,30 +265,22 @@ public class ImportKeysListFragment extends Fragment implements
Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> loader, Loader<AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>>> loader,
AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> data AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> data
) { ) {
ArrayList<ImportKeysListEntry> result = data.getResult();
mKeyData = null; mAdapter.setData(data.getResult());
mAdapter.setData(result); int size = mAdapter.getItemCount();
int size = result.size();
mBindingBasic.setNumber(size); mBindingBasic.setNumber(size);
mBinding.setStatus(size > 0 ? STATUS_LOADED : STATUS_EMPTY); mBinding.setStatus(size > 0 ? STATUS_LOADED : STATUS_EMPTY);
GetKeyResult getKeyResult = (GetKeyResult) data.getOperationResult(); GetKeyResult getKeyResult = (GetKeyResult) data.getOperationResult();
switch (loader.getId()) { switch (loader.getId()) {
case LOADER_ID_BYTES: case LOADER_ID_BYTES:
if (getKeyResult.success()) { if (!getKeyResult.success()) {
// No error
mKeyData = ((ImportKeysListLoader) loader).getParcelableRings();
} else {
getKeyResult.createNotify(mActivity).show(); getKeyResult.createNotify(mActivity).show();
} }
break; break;
case LOADER_ID_CLOUD: case LOADER_ID_CLOUD:
if (getKeyResult.success()) { if (getKeyResult.isPending()) {
// No error
} else if (getKeyResult.isPending()) {
if (getKeyResult.getRequiredInputParcel().mType == if (getKeyResult.getRequiredInputParcel().mType ==
RequiredInputParcel.RequiredInputType.ENABLE_ORBOT) { RequiredInputParcel.RequiredInputType.ENABLE_ORBOT) {
if (mShowingOrbotDialog) { if (mShowingOrbotDialog) {
@@ -342,11 +325,10 @@ public class ImportKeysListFragment extends Fragment implements
new Handler().post(showOrbotDialog); new Handler().post(showOrbotDialog);
mShowingOrbotDialog = true; mShowingOrbotDialog = true;
} }
} else { } else if (!getKeyResult.success()) {
getKeyResult.createNotify(mActivity).show(); getKeyResult.createNotify(mActivity).show();
} }
break; break;
default: default:
break; break;
} }
@@ -359,36 +341,4 @@ public class ImportKeysListFragment extends Fragment implements
mAdapter.clearData(); mAdapter.clearData();
} }
/**
* Returns an Iterator (with size) of the selected data items.
* This iterator is sort of a tradeoff, it's slightly more complex than an
* ArrayList would have been, but we save some memory by just returning
* relevant elements on demand.
*/
public IteratorWithSize<ParcelableKeyRing> getData() {
final Iterator<ParcelableKeyRing> it = mKeyData.iterator();
return new IteratorWithSize<ParcelableKeyRing>() {
@Override
public int getSize() {
return mKeyData.size();
}
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
public ParcelableKeyRing next() {
return it.next();
}
@Override
public void remove() {
it.remove();
}
};
}
} }

View File

@@ -117,7 +117,7 @@ public class ImportKeysAdapter extends RecyclerView.Adapter<ImportKeysAdapter.Vi
} }
@Override @Override
public void onBindViewHolder(final ViewHolder holder, final int position) { public void onBindViewHolder(ViewHolder holder, final int position) {
final ImportKeysListItemBinding b = holder.b; final ImportKeysListItemBinding b = holder.b;
final ImportKeysListEntry entry = mData.get(position); final ImportKeysListEntry entry = mData.get(position);
b.setEntry(entry); b.setEntry(entry);

View File

@@ -52,10 +52,6 @@ public class ParcelableFileCache<E extends Parcelable> {
mFilename = filename; mFilename = filename;
} }
public void writeCache(IteratorWithSize<E> it) throws IOException {
writeCache(it.getSize(), it);
}
public void writeCache(int numEntries, Iterator<E> it) throws IOException { public void writeCache(int numEntries, Iterator<E> it) throws IOException {
DataOutputStream oos = getOutputStream(); DataOutputStream oos = getOutputStream();