diff --git a/app/src/main/java/com/keepassdroid/AutoFillAuthActivity.java b/app/src/main/java/com/keepassdroid/AutoFillAuthActivity.java index 30a04325e..673b231fb 100644 --- a/app/src/main/java/com/keepassdroid/AutoFillAuthActivity.java +++ b/app/src/main/java/com/keepassdroid/AutoFillAuthActivity.java @@ -23,12 +23,26 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.IntentSender; +import android.os.Build; +import android.support.annotation.RequiresApi; -public class AutoFillAuthActivity extends PasswordActivity { +import com.keepassdroid.fileselect.FileSelectActivity; +import com.kunzisoft.keepass.KeePass; + +import static com.keepassdroid.PasswordActivity.KEY_AUTOFILL_RESPONSE; + +@RequiresApi(api = Build.VERSION_CODES.O) +public class AutoFillAuthActivity extends KeePass { public static IntentSender getAuthIntentSenderForResponse(Context context) { - final Intent intent = new Intent(context, PasswordActivity.class); + final Intent intent = new Intent(context, AutoFillAuthActivity.class); return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT) .getIntentSender(); } + + protected void startFileSelectActivity() { + Intent intent = new Intent(this, FileSelectActivity.class); + intent.putExtra(KEY_AUTOFILL_RESPONSE, true); + startActivityForResult(intent, 0); + } } diff --git a/app/src/main/java/com/keepassdroid/PasswordActivity.java b/app/src/main/java/com/keepassdroid/PasswordActivity.java index 482780905..505b118d0 100644 --- a/app/src/main/java/com/keepassdroid/PasswordActivity.java +++ b/app/src/main/java/com/keepassdroid/PasswordActivity.java @@ -20,11 +20,13 @@ package com.keepassdroid; import android.app.Activity; +import android.app.PendingIntent; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; +import android.content.IntentSender; import android.content.SharedPreferences; import android.net.Uri; import android.os.AsyncTask; @@ -37,6 +39,7 @@ import android.support.v4.hardware.fingerprint.FingerprintManagerCompat; import android.support.v7.widget.Toolbar; import android.text.Editable; import android.text.TextWatcher; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -47,8 +50,6 @@ import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; -import com.kunzisoft.keepass.KeePass; -import com.kunzisoft.keepass.R; import com.keepassdroid.app.App; import com.keepassdroid.compat.BackupManagerCompat; import com.keepassdroid.compat.ClipDataCompat; @@ -65,6 +66,8 @@ import com.keepassdroid.utils.Interaction; import com.keepassdroid.utils.MenuUtil; import com.keepassdroid.utils.UriUtil; import com.keepassdroid.utils.Util; +import com.kunzisoft.keepass.KeePass; +import com.kunzisoft.keepass.R; import java.io.File; import java.io.FileNotFoundException; @@ -77,6 +80,7 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp private static final String KEY_FILENAME = "fileName"; private static final String KEY_KEYFILE = "keyFile"; private static final String KEY_PASSWORD = "password"; + public static final String KEY_AUTOFILL_RESPONSE = "KEY_AUTOFILL_RESPONSE"; private static final String KEY_LAUNCH_IMMEDIATELY = "launchImmediately"; private static final String VIEW_INTENT = "android.intent.action.VIEW"; @@ -101,16 +105,20 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp private EditText passwordView; private Button confirmButton; + private Intent mReplyIntent; + public static void Launch( Activity act, - String fileName) throws FileNotFoundException { - Launch(act, fileName, ""); + String fileName, + boolean autoFillResponse) throws FileNotFoundException { + Launch(act, fileName, "", autoFillResponse); } public static void Launch( Activity act, String fileName, - String keyFile) throws FileNotFoundException { + String keyFile, + boolean autoFillResponse) throws FileNotFoundException { if (EmptyUtils.isNullOrEmpty(fileName)) { throw new FileNotFoundException(); } @@ -128,9 +136,13 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp Intent i = new Intent(act, PasswordActivity.class); i.putExtra(KEY_FILENAME, fileName); i.putExtra(KEY_KEYFILE, keyFile); + i.putExtra(KEY_AUTOFILL_RESPONSE, autoFillResponse); act.startActivityForResult(i, 0); + if(autoFillResponse) + act.finish(); + } @Override @@ -391,9 +403,7 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp else if (!fingerPrintHelper.hasEnrolledFingerprints()) { setFingerPrintVisibility(View.VISIBLE); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - fingerprintView.setAlpha(0.3f); - } + fingerprintView.setAlpha(0.3f); // This happens when no fingerprints are registered. Listening won't start confirmationView.setText(R.string.configure_fingerprint); } @@ -401,9 +411,7 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp else { fingerprintMustBeConfigured = false; setFingerPrintVisibility(View.VISIBLE); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - fingerprintView.setAlpha(1f); - } + fingerprintView.setAlpha(1f); // fingerprint available but no stored password found yet for this DB so show info don't listen if (prefsNoBackup.getString(getPreferenceKeyValue(), null) == null) { confirmationView.setText(R.string.no_password_stored); @@ -510,7 +518,17 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp App.clearShutdown(); Handler handler = new Handler(); - LoadDB task = new LoadDB(db, PasswordActivity.this, mDbUri, pass, keyfile, new AfterLoad(handler, db)); + AfterLoad afterLoad; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O + && getIntent().getExtras() != null + && getIntent().getExtras().containsKey(KEY_AUTOFILL_RESPONSE) + && getIntent().getBooleanExtra(KEY_AUTOFILL_RESPONSE, false)) { + afterLoad = new AfterLoadAutofill(handler, db); + } else { + afterLoad = new AfterLoad(handler, db); + } + + LoadDB task = new LoadDB(db, PasswordActivity.this, mDbUri, pass, keyfile, afterLoad); ProgressTask pt = new ProgressTask(PasswordActivity.this, task, R.string.loading_database); pt.run(); } @@ -550,9 +568,9 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp return super.onOptionsItemSelected(item); } - private final class AfterLoad extends OnFinish { + private class AfterLoad extends OnFinish { - private Database db; + protected Database db; public AfterLoad( Handler handler, @@ -584,6 +602,24 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp } } + @RequiresApi(api = Build.VERSION_CODES.O) + private class AfterLoadAutofill extends AfterLoad { + + public AfterLoadAutofill(Handler handler, Database db) { + super(handler, db); + } + + @Override + public void run() { + if (mSuccess) { + onAutofillResponseSuccess(); + } else { + onAutofillResponseFailure(); + } + finish(); + } + } + private class InitTask extends AsyncTask { String password = ""; @@ -725,4 +761,51 @@ public class PasswordActivity extends LockingActivity implements FingerPrintHelp } } } + + @RequiresApi(api = Build.VERSION_CODES.O) + public static IntentSender getAuthIntentSenderForResponse(Context context) { + final Intent intent = new Intent(context, AutoFillAuthActivity.class); + return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT) + .getIntentSender(); + } + + + @Override + public void finish() { + if (mReplyIntent != null) { + setResult(RESULT_OK, mReplyIntent); + } else { + setResult(RESULT_CANCELED); + } + super.finish(); + } + + @RequiresApi(api = Build.VERSION_CODES.O) + private void onAutofillResponseFailure() { + Log.w(getClass().getName(), "Failed Autofill auth."); + mReplyIntent = null; + } + + @RequiresApi(api = Build.VERSION_CODES.O) + private void onAutofillResponseSuccess() { + /* + Intent intent = getIntent(); + Bundle clientState = intent.getBundleExtra(AutofillManager.EXTRA_CLIENT_STATE); + AssistStructure structure = intent.getParcelableExtra(EXTRA_ASSIST_STRUCTURE); + StructureParser parser = new StructureParser(getApplicationContext(), structure); + parser.parseForFill(); + AutofillFieldMetadataCollection autofillFields = parser.getAutofillFields(); + */ + mReplyIntent = new Intent(); + /* + HashMap clientFormDataMap = + SharedPrefsAutofillRepository.getInstance().getFilledAutofillFieldCollection + (this, autofillFields.getFocusedHints(), autofillFields.getAllHints()); + + // TODO Add success results + mReplyIntent.putExtra(EXTRA_AUTHENTICATION_RESULT, AutofillHelper.newResponse + (this, clientState, false, autofillFields, clientFormDataMap)); + */ + mReplyIntent.putExtra(android.view.autofill.AutofillManager.EXTRA_AUTHENTICATION_RESULT, ""); + } } diff --git a/app/src/main/java/com/keepassdroid/autofill/AutofillFieldMetadataCollection.java b/app/src/main/java/com/keepassdroid/autofill/AutofillFieldMetadataCollection.java index 7540cc5df..b051db487 100644 --- a/app/src/main/java/com/keepassdroid/autofill/AutofillFieldMetadataCollection.java +++ b/app/src/main/java/com/keepassdroid/autofill/AutofillFieldMetadataCollection.java @@ -15,6 +15,8 @@ */ package com.keepassdroid.autofill; +import android.os.Build; +import android.support.annotation.RequiresApi; import android.view.autofill.AutofillId; import java.util.ArrayList; @@ -26,6 +28,7 @@ import java.util.List; * Data structure that stores a collection of {@code AutofillFieldMetadata}s. Contains all of the * client's {@code View} hierarchy autofill-relevant metadata. */ +@RequiresApi(api = Build.VERSION_CODES.O) public final class AutofillFieldMetadataCollection { private final List mAutofillIds = new ArrayList<>(); diff --git a/app/src/main/java/com/keepassdroid/autofill/KeeAutofillService.java b/app/src/main/java/com/keepassdroid/autofill/KeeAutofillService.java index 08d9e240d..4641216ec 100644 --- a/app/src/main/java/com/keepassdroid/autofill/KeeAutofillService.java +++ b/app/src/main/java/com/keepassdroid/autofill/KeeAutofillService.java @@ -22,7 +22,6 @@ package com.keepassdroid.autofill; import android.app.assist.AssistStructure; import android.content.IntentSender; import android.os.Build; -import android.os.Bundle; import android.os.CancellationSignal; import android.service.autofill.AutofillService; import android.service.autofill.FillCallback; @@ -51,8 +50,6 @@ public class KeeAutofillService extends AutofillService { AssistStructure structure = request.getFillContexts() .get(request.getFillContexts().size() - 1).getStructure(); - final Bundle clientState = request.getClientState(); - cancellationSignal.setOnCancelListener(() -> Log.e(TAG, "Cancel autofill not implemented in this sample.") ); @@ -77,11 +74,8 @@ public class KeeAutofillService extends AutofillService { // If the entire Autofill Response is authenticated, AuthActivity is used // to generate Response. IntentSender sender = AutoFillAuthActivity.getAuthIntentSenderForResponse(this); - RemoteViews presentation = new RemoteViews(getPackageName(), R.layout.autofill_service_unlock); - presentation.setTextViewText(R.id.text, getString(R.string.autofill_sign_in_prompt)); - responseBuilder .setAuthentication(autofillIds, sender, presentation); callback.onSuccess(responseBuilder.build()); diff --git a/app/src/main/java/com/keepassdroid/autofill/StructureParser.java b/app/src/main/java/com/keepassdroid/autofill/StructureParser.java index 953107996..eabeaa459 100644 --- a/app/src/main/java/com/keepassdroid/autofill/StructureParser.java +++ b/app/src/main/java/com/keepassdroid/autofill/StructureParser.java @@ -33,14 +33,14 @@ import com.kunzisoft.keepass.R; * parses the hierarchy and collects autofill metadata from {@link ViewNode}s along the way. */ @RequiresApi(api = Build.VERSION_CODES.O) -final class StructureParser { +final public class StructureParser { private final AutofillFieldMetadataCollection mAutofillFields = new AutofillFieldMetadataCollection(); private final Context mContext; private final AssistStructure mStructure; private FilledAutofillFieldCollection mFilledAutofillFieldCollection; - StructureParser(Context context, AssistStructure structure) { + public StructureParser(Context context, AssistStructure structure) { mContext = context; mStructure = structure; } diff --git a/app/src/main/java/com/keepassdroid/fileselect/FileSelectActivity.java b/app/src/main/java/com/keepassdroid/fileselect/FileSelectActivity.java index 96c502ee4..a89cffcb7 100644 --- a/app/src/main/java/com/keepassdroid/fileselect/FileSelectActivity.java +++ b/app/src/main/java/com/keepassdroid/fileselect/FileSelectActivity.java @@ -91,11 +91,17 @@ public class FileSelectActivity extends StylishActivity { private RecentFileHistory fileHistory; private boolean recentMode = false; + private boolean autofillResponse = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - + + if(getIntent().getExtras() != null) { + autofillResponse = getIntent().getExtras(). + getBoolean(PasswordActivity.KEY_AUTOFILL_RESPONSE, autofillResponse); + } + fileHistory = App.getFileHistory(); if (fileHistory.hasRecentFiles()) { @@ -129,7 +135,7 @@ public class FileSelectActivity extends StylishActivity { R.id.file_filename); try { - PasswordActivity.Launch(FileSelectActivity.this, fileName); + PasswordActivity.Launch(FileSelectActivity.this, fileName, autofillResponse); } catch (ContentFileNotFoundException e) { Toast.makeText(FileSelectActivity.this, @@ -286,7 +292,7 @@ public class FileSelectActivity extends StylishActivity { if (db.exists()) { try { - PasswordActivity.Launch(FileSelectActivity.this, path); + PasswordActivity.Launch(FileSelectActivity.this, path, autofillResponse); } catch (Exception e) { // Ignore exception } @@ -294,7 +300,7 @@ public class FileSelectActivity extends StylishActivity { } else { try { - PasswordActivity.Launch(FileSelectActivity.this, dbUri.toString()); + PasswordActivity.Launch(FileSelectActivity.this, dbUri.toString(), autofillResponse); } catch (Exception e) { // Ignore exception } @@ -359,7 +365,7 @@ public class FileSelectActivity extends StylishActivity { protected void onPostExecute(Void v) { try { - PasswordActivity.Launch(FileSelectActivity.this, fileName, keyFile); + PasswordActivity.Launch(FileSelectActivity.this, fileName, keyFile, autofillResponse); } catch (ContentFileNotFoundException e) { Toast.makeText(FileSelectActivity.this, R.string.file_not_found_content, Toast.LENGTH_LONG) diff --git a/app/src/main/java/com/kunzisoft/keepass/KeePass.java b/app/src/main/java/com/kunzisoft/keepass/KeePass.java index 93da807d1..9f4bd4bfb 100644 --- a/app/src/main/java/com/kunzisoft/keepass/KeePass.java +++ b/app/src/main/java/com/kunzisoft/keepass/KeePass.java @@ -40,10 +40,10 @@ public class KeePass extends Activity { @Override protected void onStart() { super.onStart(); - startFileSelect(); + startFileSelectActivity(); } - private void startFileSelect() { + protected void startFileSelectActivity() { Intent intent = new Intent(this, FileSelectActivity.class); startActivityForResult(intent, 0); } diff --git a/app/src/main/res/layout/autofill_service_unlock.xml b/app/src/main/res/layout/autofill_service_unlock.xml index 4869ccf7d..d430c78ce 100644 --- a/app/src/main/res/layout/autofill_service_unlock.xml +++ b/app/src/main/res/layout/autofill_service_unlock.xml @@ -24,7 +24,9 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_vertical" + android:text="@string/autofill_sign_in_prompt" android:minHeight="?android:attr/listPreferredItemHeightSmall" + android:layout_gravity="center" android:paddingRight="12dp" android:paddingEnd="12dp" android:paddingLeft="12dp" @@ -33,11 +35,10 @@ + android:src="@mipmap/ic_launcher"/> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 495786abe..020b2d522 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -205,7 +205,7 @@ General Autofill KeepassDX Autofill Service - Tap to sign in. + Sign in with KeepassDX Set default Autofill service Could not associate web domain %1$s with app %2$s