add override mechanism to ui

This commit is contained in:
Vincent Breitmoser 2017-04-29 02:21:48 +02:00
parent 0e3032a192
commit 11f10cf85f
6 changed files with 167 additions and 79 deletions

View file

@ -30,7 +30,7 @@ import org.bouncycastle.util.encoders.Base64;
public abstract class SecurityProblem implements Serializable { public abstract class SecurityProblem implements Serializable {
String getIdentifier() { public String getIdentifier() {
if (!isIdentifiable()) { if (!isIdentifiable()) {
return null; return null;
} }

View file

@ -84,7 +84,9 @@ public class RemoteSecurityProblemDialogActivity extends FragmentActivity {
public static final int SECONDARY_CHILD_NONE = 0; public static final int SECONDARY_CHILD_NONE = 0;
public static final int SECONDARY_CHILD_RECOMMENDATION = 1; public static final int SECONDARY_CHILD_RECOMMENDATION = 1;
public static final int SECONDARY_CHILD_OVERRIDE = 2; public static final int SECONDARY_CHILD_OVERRIDE = 2;
public static final int SECONDARY_CHILD_OVERRIDE_OK = 3; public static final int BUTTON_BAR_REGULAR = 0;
public static final int BUTTON_BAR_OVERRIDE = 1;
private SecurityProblemPresenter presenter; private SecurityProblemPresenter presenter;
private RemoteSecurityProblemView mvpView; private RemoteSecurityProblemView mvpView;
@ -92,6 +94,8 @@ public class RemoteSecurityProblemDialogActivity extends FragmentActivity {
private Button buttonViewKey; private Button buttonViewKey;
private Button buttonOverride; private Button buttonOverride;
private Button buttonOverrideUndo; private Button buttonOverrideUndo;
private Button buttonOverrideBack;
private Button buttonOverrideConfirm;
@NonNull @NonNull
@Override @Override
@ -109,6 +113,8 @@ public class RemoteSecurityProblemDialogActivity extends FragmentActivity {
buttonViewKey = (Button) view.findViewById(R.id.button_view_key); buttonViewKey = (Button) view.findViewById(R.id.button_view_key);
buttonOverride = (Button) view.findViewById(R.id.button_override); buttonOverride = (Button) view.findViewById(R.id.button_override);
buttonOverrideUndo = (Button) view.findViewById(R.id.button_override_undo); buttonOverrideUndo = (Button) view.findViewById(R.id.button_override_undo);
buttonOverrideBack = (Button) view.findViewById(R.id.button_override_back);
buttonOverrideConfirm = (Button) view.findViewById(R.id.button_override_confirm);
setupListenersForPresenter(); setupListenersForPresenter();
mvpView = createMvpView(view); mvpView = createMvpView(view);
@ -152,6 +158,8 @@ public class RemoteSecurityProblemDialogActivity extends FragmentActivity {
final TextView overrideText = (TextView) insecureWarningLayout.findViewById(R.id.dialog_insecure_override_text); final TextView overrideText = (TextView) insecureWarningLayout.findViewById(R.id.dialog_insecure_override_text);
final ToolableViewAnimator secondaryLayoutAnimator = final ToolableViewAnimator secondaryLayoutAnimator =
(ToolableViewAnimator) insecureWarningLayout.findViewById(R.id.dialog_insecure_secondary_layout); (ToolableViewAnimator) insecureWarningLayout.findViewById(R.id.dialog_insecure_secondary_layout);
final ToolableViewAnimator buttonBarAnimator =
(ToolableViewAnimator) view.findViewById(R.id.dialog_insecure_button_bar);
return new RemoteSecurityProblemView() { return new RemoteSecurityProblemView() {
private boolean layoutInitialized = false; private boolean layoutInitialized = false;
@ -167,6 +175,17 @@ public class RemoteSecurityProblemDialogActivity extends FragmentActivity {
activity.finish(); activity.finish();
} }
@Override
public void finishAsSuppressed() {
FragmentActivity activity = getActivity();
if (activity == null) {
return;
}
activity.setResult(RESULT_OK);
activity.finish();
}
@Override @Override
public void setTitleClientIcon(Drawable drawable) { public void setTitleClientIcon(Drawable drawable) {
iconClientApp.setImageDrawable(drawable); iconClientApp.setImageDrawable(drawable);
@ -182,12 +201,14 @@ public class RemoteSecurityProblemDialogActivity extends FragmentActivity {
private void showGeneric(@StringRes int explanationStringRes) { private void showGeneric(@StringRes int explanationStringRes) {
explanationText.setText(explanationStringRes); explanationText.setText(explanationStringRes);
secondaryLayoutAnimator.setDisplayedChild(SECONDARY_CHILD_NONE, layoutInitialized); secondaryLayoutAnimator.setDisplayedChild(SECONDARY_CHILD_NONE, layoutInitialized);
buttonBarAnimator.setDisplayedChild(BUTTON_BAR_REGULAR, layoutInitialized);
layoutInitialized = true; layoutInitialized = true;
} }
private void showGeneric(String explanationString) { private void showGeneric(String explanationString) {
explanationText.setText(explanationString); explanationText.setText(explanationString);
secondaryLayoutAnimator.setDisplayedChild(SECONDARY_CHILD_NONE, layoutInitialized); secondaryLayoutAnimator.setDisplayedChild(SECONDARY_CHILD_NONE, layoutInitialized);
buttonBarAnimator.setDisplayedChild(BUTTON_BAR_REGULAR, layoutInitialized);
layoutInitialized = true; layoutInitialized = true;
} }
@ -196,6 +217,7 @@ public class RemoteSecurityProblemDialogActivity extends FragmentActivity {
explanationText.setText(explanationStringRes); explanationText.setText(explanationStringRes);
recommendText.setText(recommendationStringRes); recommendText.setText(recommendationStringRes);
secondaryLayoutAnimator.setDisplayedChild(SECONDARY_CHILD_RECOMMENDATION, layoutInitialized); secondaryLayoutAnimator.setDisplayedChild(SECONDARY_CHILD_RECOMMENDATION, layoutInitialized);
buttonBarAnimator.setDisplayedChild(BUTTON_BAR_REGULAR, layoutInitialized);
layoutInitialized = true; layoutInitialized = true;
} }
@ -204,6 +226,7 @@ public class RemoteSecurityProblemDialogActivity extends FragmentActivity {
explanationText.setText(explanationString); explanationText.setText(explanationString);
recommendText.setText(recommendationStringRes); recommendText.setText(recommendationStringRes);
secondaryLayoutAnimator.setDisplayedChild(SECONDARY_CHILD_RECOMMENDATION, layoutInitialized); secondaryLayoutAnimator.setDisplayedChild(SECONDARY_CHILD_RECOMMENDATION, layoutInitialized);
buttonBarAnimator.setDisplayedChild(BUTTON_BAR_REGULAR, layoutInitialized);
layoutInitialized = true; layoutInitialized = true;
} }
@ -267,12 +290,10 @@ public class RemoteSecurityProblemDialogActivity extends FragmentActivity {
@Override @Override
public void showOverrideMessage(int countdown) { public void showOverrideMessage(int countdown) {
secondaryLayoutAnimator.setDisplayedChild(SECONDARY_CHILD_OVERRIDE, true); secondaryLayoutAnimator.setDisplayedChild(SECONDARY_CHILD_OVERRIDE, true);
buttonBarAnimator.setDisplayedChild(BUTTON_BAR_OVERRIDE, true);
overrideText.setText(getString(R.string.dialog_insecure_override, countdown)); overrideText.setText(getString(R.string.dialog_insecure_override, countdown));
} buttonOverrideConfirm.setText(
getString(R.string.dialog_insecure_button_override_confirm, countdown));
@Override
public void showOverrideOk() {
secondaryLayoutAnimator.setDisplayedChild(SECONDARY_CHILD_OVERRIDE_OK, true);
} }
@Override @Override
@ -319,6 +340,18 @@ public class RemoteSecurityProblemDialogActivity extends FragmentActivity {
presenter.onClickOverrideUndo(); presenter.onClickOverrideUndo();
} }
}); });
buttonOverrideBack.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
presenter.onClickOverrideBack();
}
});
buttonOverrideConfirm.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
presenter.onClickOverrideConfirm();
}
});
} }
} }

View file

@ -20,6 +20,7 @@ import org.sufficientlysecure.keychain.pgp.SecurityProblem.NotWhitelistedCurve;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.EncryptionAlgorithmProblem; import org.sufficientlysecure.keychain.pgp.SecurityProblem.EncryptionAlgorithmProblem;
import org.sufficientlysecure.keychain.pgp.SecurityProblem.UnidentifiedKeyProblem; import org.sufficientlysecure.keychain.pgp.SecurityProblem.UnidentifiedKeyProblem;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.OverriddenWarningsRepository;
import org.sufficientlysecure.keychain.ui.ViewKeyActivity; import org.sufficientlysecure.keychain.ui.ViewKeyActivity;
@ -29,11 +30,14 @@ class SecurityProblemPresenter {
private final Context context; private final Context context;
private final PackageManager packageManager; private final PackageManager packageManager;
private final OverriddenWarningsRepository overriddenWarningsRepository;
private RemoteSecurityProblemView view; private RemoteSecurityProblemView view;
private Long viewKeyMasterKeyId; private Long viewKeyMasterKeyId;
private int overrideCounter; private int overrideCounter;
private String securityProblemIdentifier;
private String packageName; private String packageName;
private Serializable securityProblem; private Serializable securityProblem;
@ -41,6 +45,7 @@ class SecurityProblemPresenter {
SecurityProblemPresenter(Context context) { SecurityProblemPresenter(Context context) {
this.context = context; this.context = context;
packageManager = context.getPackageManager(); packageManager = context.getPackageManager();
overriddenWarningsRepository = OverriddenWarningsRepository.createOverriddenWarningsRepository(context);
} }
public void setView(RemoteSecurityProblemView view) { public void setView(RemoteSecurityProblemView view) {
@ -79,10 +84,6 @@ class SecurityProblemPresenter {
viewKeyMasterKeyId = keySecurityProblem.masterKeyId; viewKeyMasterKeyId = keySecurityProblem.masterKeyId;
view.showViewKeyButton(); view.showViewKeyButton();
if (keySecurityProblem.isIdentifiable()) {
view.showOverrideButton();
}
if (keySecurityProblem instanceof InsecureBitStrength) { if (keySecurityProblem instanceof InsecureBitStrength) {
InsecureBitStrength problem = (InsecureBitStrength) keySecurityProblem; InsecureBitStrength problem = (InsecureBitStrength) keySecurityProblem;
view.showLayoutEncryptInsecureBitsize(problem.algorithm, problem.bitStrength); view.showLayoutEncryptInsecureBitsize(problem.algorithm, problem.bitStrength);
@ -94,6 +95,11 @@ class SecurityProblemPresenter {
} else { } else {
throw new IllegalArgumentException("Unhandled key security problem type!"); throw new IllegalArgumentException("Unhandled key security problem type!");
} }
if (keySecurityProblem.isIdentifiable()) {
securityProblemIdentifier = keySecurityProblem.getIdentifier();
refreshOverrideStatusView();
}
} }
private void setupFromSigningKeySecurityProblem(KeySecurityProblem keySecurityProblem) { private void setupFromSigningKeySecurityProblem(KeySecurityProblem keySecurityProblem) {
@ -111,6 +117,11 @@ class SecurityProblemPresenter {
} else { } else {
throw new IllegalArgumentException("Unhandled key security problem type!"); throw new IllegalArgumentException("Unhandled key security problem type!");
} }
if (keySecurityProblem.isIdentifiable()) {
securityProblemIdentifier = keySecurityProblem.getIdentifier();
refreshOverrideStatusView();
}
} }
private void setupFromEncryptionAlgorithmSecurityProblem(EncryptionAlgorithmProblem securityProblem) { private void setupFromEncryptionAlgorithmSecurityProblem(EncryptionAlgorithmProblem securityProblem) {
@ -122,6 +133,19 @@ class SecurityProblemPresenter {
} else { } else {
throw new IllegalArgumentException("Unhandled symmetric algorithm problem type!"); throw new IllegalArgumentException("Unhandled symmetric algorithm problem type!");
} }
if (securityProblem.isIdentifiable()) {
securityProblemIdentifier = securityProblem.getIdentifier();
refreshOverrideStatusView();
}
}
private void refreshOverrideStatusView() {
if (overriddenWarningsRepository.isWarningOverridden(securityProblemIdentifier)) {
view.showOverrideUndoButton();
} else {
view.showOverrideButton();
}
} }
private void setupFromSignatureSecurityProblem(InsecureSigningAlgorithm signatureSecurityProblem) { private void setupFromSignatureSecurityProblem(InsecureSigningAlgorithm signatureSecurityProblem) {
@ -147,11 +171,16 @@ class SecurityProblemPresenter {
overrideCounter++; overrideCounter++;
view.showOverrideMessage(overrideCountLeft); view.showOverrideMessage(overrideCountLeft);
} else { } else {
view.showOverrideOk(); overriddenWarningsRepository.putOverride(securityProblemIdentifier);
view.showOverrideUndoButton(); view.finishAsSuppressed();
} }
} }
private void resetOverrideStatus() {
overrideCounter = 0;
overriddenWarningsRepository.deleteOverride(securityProblemIdentifier);
}
void onClickGotIt() { void onClickGotIt() {
view.finishAsCancelled(); view.finishAsCancelled();
} }
@ -167,16 +196,26 @@ class SecurityProblemPresenter {
} }
void onClickOverrideUndo() { void onClickOverrideUndo() {
overrideCounter = 0; resetOverrideStatus();
refreshSecurityProblemDisplay(); refreshSecurityProblemDisplay();
} }
void onClickOverrideBack() {
resetOverrideStatus();
refreshSecurityProblemDisplay();
}
void onClickOverrideConfirm() {
incrementOverrideAndDisplayOrTrigger();
}
void onCancel() { void onCancel() {
view.finishAsCancelled(); view.finishAsCancelled();
} }
interface RemoteSecurityProblemView { interface RemoteSecurityProblemView {
void finishAsCancelled(); void finishAsCancelled();
void finishAsSuppressed();
void setTitleClientIcon(Drawable drawable); void setTitleClientIcon(Drawable drawable);
void showLayoutEncryptInsecureBitsize(int algorithmId, int bitStrength); void showLayoutEncryptInsecureBitsize(int algorithmId, int bitStrength);
@ -192,7 +231,6 @@ class SecurityProblemPresenter {
void showLayoutInsecureHashAlgorithm(int hashAlgorithm); void showLayoutInsecureHashAlgorithm(int hashAlgorithm);
void showOverrideMessage(int countdown); void showOverrideMessage(int countdown);
void showOverrideOk();
void showViewKeyButton(); void showViewKeyButton();
void showOverrideButton(); void showOverrideButton();

View file

@ -30,7 +30,7 @@
android:inAnimation="@anim/fade_in" android:inAnimation="@anim/fade_in"
android:outAnimation="@anim/fade_out" android:outAnimation="@anim/fade_out"
android:measureAllChildren="true" android:measureAllChildren="true"
custom:initialView="3"> custom:initialView="1">
<android.support.v4.widget.Space <android.support.v4.widget.Space
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -88,30 +88,6 @@
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textAppearance="?android:textAppearanceMedium"
android:text="@string/dialog_insecure_override_ok_title"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@string/dialog_insecure_override_ok"
/>
</LinearLayout>
</org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator> </org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator>

View file

@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:orientation="vertical"
tools:layout_marginTop="24dp" tools:layout_marginTop="24dp"
> >
@ -71,55 +72,94 @@
</LinearLayout> </LinearLayout>
<LinearLayout <org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:id="@+id/dialog_insecure_button_bar"
android:gravity="end" android:inAnimation="@anim/fade_in"
android:padding="8dp" android:outAnimation="@anim/fade_out"
tools:layout_marginBottom="50dp" tools:layout_marginBottom="50dp"
style="?buttonBarStyle"> custom:initialView="0">
<Button <LinearLayout
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/dialog_insecure_button_override" android:orientation="horizontal"
android:id="@+id/button_override" android:gravity="end"
android:visibility="gone" android:padding="8dp"
tools:visibility="visible" style="?buttonBarStyle">
style="?buttonBarButtonStyle" />
<Button <Button
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/dialog_insecure_button_override"
android:id="@+id/button_override"
android:visibility="gone"
tools:visibility="visible"
style="?buttonBarButtonStyle" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/dialog_insecure_button_undo"
android:id="@+id/button_override_undo"
android:visibility="gone"
style="?buttonBarButtonStyle" />
<android.support.v4.widget.Space
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/dialog_insecure_button_view_key"
android:id="@+id/button_view_key"
android:visibility="gone"
tools:visibility="visible"
style="?buttonBarButtonStyle" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/dialog_insecure_button_ok"
android:id="@+id/button_allow"
style="?buttonBarButtonStyle" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/dialog_insecure_button_undo" android:orientation="horizontal"
android:id="@+id/button_override_undo" android:gravity="end"
android:visibility="gone" android:padding="8dp"
style="?buttonBarButtonStyle" /> style="?buttonBarStyle">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Back"
android:id="@+id/button_override_back"
style="?buttonBarButtonStyle" />
<android.support.v4.widget.Space <android.support.v4.widget.Space
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
/> />
<Button <Button
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/dialog_insecure_button_view_key" android:text="@string/dialog_insecure_button_override_confirm"
android:id="@+id/button_view_key" android:id="@+id/button_override_confirm"
android:visibility="gone" style="?buttonBarButtonStyle" />
tools:visibility="visible"
style="?buttonBarButtonStyle" />
<Button </LinearLayout>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/dialog_insecure_button_ok"
android:id="@+id/button_allow"
style="?buttonBarButtonStyle" />
</LinearLayout> </org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator>
</LinearLayout> </LinearLayout>

View file

@ -1874,7 +1874,8 @@
<string name="dialog_insecure_override_ok_title">Warning suppressed</string> <string name="dialog_insecure_override_ok_title">Warning suppressed</string>
<string name="dialog_insecure_override_ok">The security warning (for this key/message) will not be shown again in the future.</string> <string name="dialog_insecure_override_ok">The security warning (for this key/message) will not be shown again in the future.</string>
<string name="dialog_insecure_button_override">Suppress</string> <string name="dialog_insecure_button_override">Suppress</string>
<string name="dialog_insecure_button_undo">Undo</string> <string name="dialog_insecure_button_override_confirm">Suppress (%d)</string>
<string name="dialog_insecure_button_undo">Un-Suppress</string>
<string name="dialog_insecure_button_view_key">View Key</string> <string name="dialog_insecure_button_view_key">View Key</string>
<string name="dialog_insecure_button_ok">Got it</string> <string name="dialog_insecure_button_ok">Got it</string>