From 4d0a686220fc3948b61b7ac0dc223f03c79bee59 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Wed, 6 Sep 2017 03:53:54 +0200 Subject: [PATCH] token-import: show unlock option for locked keys --- .../ui/token/ManageSecurityTokenContract.java | 3 + .../ui/token/ManageSecurityTokenFragment.java | 25 +++++- .../token/ManageSecurityTokenPresenter.java | 40 +++++++++- .../create_security_token_import_fragment.xml | 79 ++++++++++++++++++- OpenKeychain/src/main/res/values/strings.xml | 6 ++ 5 files changed, 149 insertions(+), 4 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/token/ManageSecurityTokenContract.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/token/ManageSecurityTokenContract.java index fcb6db169..7c67e0ad0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/token/ManageSecurityTokenContract.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/token/ManageSecurityTokenContract.java @@ -49,6 +49,8 @@ class ManageSecurityTokenContract { void onClickResetToken(); void onClickConfirmReset(); void onSecurityTokenResetSuccess(); + + void onClickUnlockToken(); } interface ManageSecurityTokenMvpView { @@ -60,6 +62,7 @@ class ManageSecurityTokenContract { void showActionImport(); void showActionViewKey(); void showActionRetryOrFromFile(); + void showActionLocked(int unlockAttempts); void hideAction(); void operationImportKey(byte[] importKeyData); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/token/ManageSecurityTokenFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/token/ManageSecurityTokenFragment.java index 946917a1c..89c9fefc5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/token/ManageSecurityTokenFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/token/ManageSecurityTokenFragment.java @@ -81,6 +81,7 @@ public class ManageSecurityTokenFragment extends Fragment implements ManageSecur ManageSecurityTokenMvpPresenter presenter; private ViewGroup statusLayoutGroup; private ToolableViewAnimator actionAnimator; + private TextView unlockSubtitle; ImportKeyringParcel currentImportKeyringParcel; PromoteKeyringParcel currentPromoteKeyringParcel; @@ -136,6 +137,7 @@ public class ManageSecurityTokenFragment extends Fragment implements ManageSecur statusLayoutGroup = (ViewGroup) view.findViewById(R.id.status_indicator_layout); actionAnimator = (ToolableViewAnimator) view.findViewById(R.id.action_animator); + unlockSubtitle = (TextView) view.findViewById(R.id.button_unlock_subtitle); view.findViewById(R.id.button_import).setOnClickListener(this); view.findViewById(R.id.button_view_key).setOnClickListener(this); @@ -143,6 +145,8 @@ public class ManageSecurityTokenFragment extends Fragment implements ManageSecur view.findViewById(R.id.button_reset_token_1).setOnClickListener(this); view.findViewById(R.id.button_reset_token_2).setOnClickListener(this); view.findViewById(R.id.button_reset_token_3).setOnClickListener(this); + view.findViewById(R.id.button_reset_token_4).setOnClickListener(this); + view.findViewById(R.id.button_unlock).setOnClickListener(this); view.findViewById(R.id.button_load_file).setOnClickListener(this); setHasOptionsMenu(true); @@ -250,6 +254,18 @@ public class ManageSecurityTokenFragment extends Fragment implements ManageSecur actionAnimator.setDisplayedChildId(R.id.token_layout_not_found); } + @Override + public void showActionLocked(int attemptsLeft) { + actionAnimator.setDisplayedChildId(R.id.token_layout_locked); + if (attemptsLeft > 0) { + String unlockAttemptsText = getResources().getQuantityString( + R.plurals.token_unlock_attempts, attemptsLeft, attemptsLeft); + unlockSubtitle.setText(unlockAttemptsText); + } else { + unlockSubtitle.setText(R.string.token_unlock_attempts_none); + } + } + @Override public void hideAction() { actionAnimator.setDisplayedChild(0); @@ -378,10 +394,16 @@ public class ManageSecurityTokenFragment extends Fragment implements ManageSecur } case R.id.button_reset_token_1: case R.id.button_reset_token_2: - case R.id.button_reset_token_3: { + case R.id.button_reset_token_3: + case R.id.button_reset_token_4: { presenter.onClickResetToken(); break; } + + case R.id.button_unlock: { + presenter.onClickUnlockToken(); + break; + } } } @@ -426,6 +448,7 @@ public class ManageSecurityTokenFragment extends Fragment implements ManageSecur }, null); enum StatusLine { + CHECK_KEY (R.string.status_check_key), SEARCH_LOCAL (R.string.status_search_local), SEARCH_URI (R.string.status_search_uri), SEARCH_KEYSERVER (R.string.status_search_keyserver), diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/token/ManageSecurityTokenPresenter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/token/ManageSecurityTokenPresenter.java index 28f52f736..ba2966b31 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/token/ManageSecurityTokenPresenter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/token/ManageSecurityTokenPresenter.java @@ -21,6 +21,7 @@ package org.sufficientlysecure.keychain.ui.token; import android.content.Context; import android.net.Uri; import android.os.Bundle; +import android.os.Handler; import android.support.v4.app.LoaderManager; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.Loader; @@ -55,6 +56,7 @@ class ManageSecurityTokenPresenter implements ManageSecurityTokenMvpPresenter { private ManageSecurityTokenMvpView view; + private boolean checkedKeyStatus; private boolean searchedLocally; private boolean searchedAtUri; private boolean searchedKeyservers; @@ -80,7 +82,7 @@ class ManageSecurityTokenPresenter implements ManageSecurityTokenMvpPresenter { @Override public void onActivityCreated() { - if (!searchedLocally || !searchedAtUri || !searchedKeyservers) { + if (!checkedKeyStatus || !searchedLocally || !searchedAtUri || !searchedKeyservers) { continueSearch(); } } @@ -91,6 +93,12 @@ class ManageSecurityTokenPresenter implements ManageSecurityTokenMvpPresenter { } private void continueSearch() { + if (!checkedKeyStatus) { + view.statusLineAdd(StatusLine.CHECK_KEY); + delayPerformKeyCheck(); + return; + } + if (!searchedLocally) { view.statusLineAdd(StatusLine.SEARCH_LOCAL); loaderManager.restartLoader(LOADER_LOCAL, null, loaderCallbacks); @@ -112,6 +120,36 @@ class ManageSecurityTokenPresenter implements ManageSecurityTokenMvpPresenter { view.showActionRetryOrFromFile(); } + private void delayPerformKeyCheck() { + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + performKeyCheck(); + } + }, 1000); + } + + private void performKeyCheck() { + boolean isLocked = tokenInfo.getVerifyRetries() == 0; + if (!isLocked) { + view.statusLineOk(); + + checkedKeyStatus = true; + continueSearch(); + return; + } + + view.statusLineError(); + + int unlockAttemptsLeft = tokenInfo.getVerifyAdminRetries(); + view.showActionLocked(unlockAttemptsLeft); + } + + @Override + public void onClickUnlockToken() { + // TODO + } + private LoaderCallbacks loaderCallbacks = new LoaderCallbacks() { @Override public Loader onCreateLoader(int id, Bundle args) { diff --git a/OpenKeychain/src/main/res/layout/create_security_token_import_fragment.xml b/OpenKeychain/src/main/res/layout/create_security_token_import_fragment.xml index 4a9f9b2ec..35ab29536 100644 --- a/OpenKeychain/src/main/res/layout/create_security_token_import_fragment.xml +++ b/OpenKeychain/src/main/res/layout/create_security_token_import_fragment.xml @@ -2,7 +2,8 @@ + android:layout_height="match_parent" + xmlns:tools="http://schemas.android.com/tools"> + custom:initialView="04"> + + + + + + + + + + + + + + +