39 lines
4.0 KiB
Java
39 lines
4.0 KiB
Java
package ru.kusoft.qsafe;
|
|
|
|
import android.app.*;
|
|
import android.content.*;
|
|
import android.graphics.Bitmap;
|
|
import android.view.*;
|
|
import android.widget.*;
|
|
import junit.framework.TestCase;
|
|
import org.json.*;
|
|
import java.lang.reflect.Field;
|
|
|
|
public class ScreenSecurityTests extends TestCase {
|
|
private final Instrumentation instrument=androidx.test.platform.app.InstrumentationRegistry.getInstrumentation();
|
|
private MainActivity activity;
|
|
private void main(Runnable work){instrument.runOnMainSync(work);instrument.waitForIdleSync();}
|
|
private AlertDialog dialog()throws Exception{Field f=MainActivity.class.getDeclaredField("dialog");f.setAccessible(true);return (AlertDialog)f.get(activity);}
|
|
private void secure(Window w){assertTrue((w.getAttributes().flags&WindowManager.LayoutParams.FLAG_SECURE)!=0);}
|
|
private View text(View v,String target){if(v instanceof TextView&&((TextView)v).getText().toString().equals(target))return v;if(v instanceof ViewGroup){ViewGroup g=(ViewGroup)v;for(int i=0;i<g.getChildCount();i++){View found=text(g.getChildAt(i),target);if(found!=null)return found;}}return null;}
|
|
private void open()throws Exception {
|
|
main(()->{((EditText)activity.findViewById(R.id.master_password)).setText("synthetic screenshot password!");activity.findViewById(R.id.open_vault).performClick();});
|
|
long end=System.currentTimeMillis()+20000;while(System.currentTimeMillis()<end){instrument.waitForIdleSync();if(text(activity.getWindow().getDecorView(),"Security synthetic")!=null||text(activity.getWindow().getDecorView(),"Security synthetic\nsecurity@example.test")!=null)return;Thread.sleep(100);}fail("Unlock timed out");
|
|
}
|
|
public void testProtectedScreenshotDeleteDialogAndAutofillConfirmation()throws Exception {
|
|
assertTrue(android.os.Build.MODEL.contains("sdk_gphone"));Context c=instrument.getTargetContext();Repository r=Repository.get(c);r.setAutoSync(false);r.setHomeWifi(false,"");r.fingerprintOffered(true);
|
|
try(VaultCrypto.Key key=VaultCrypto.create("synthetic screenshot password!".toCharArray())){
|
|
JSONObject data=Vault.empty(),e=CardTemplates.create("login").put("title","Security synthetic");e.getJSONArray("fields").getJSONObject(0).put("value","security@example.test");e.getJSONArray("fields").getJSONObject(1).put("value","SYNTHETIC_SCREEN_SECRET");e.getJSONArray("fields").getJSONObject(2).put("value","https://example.test");Vault.update(data,e);r.save(data,key);
|
|
}
|
|
activity=(MainActivity)instrument.startActivitySync(new Intent(c,MainActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));secure(activity.getWindow());
|
|
Thread.sleep(200);Bitmap capture=instrument.getUiAutomation().takeScreenshot();if(capture!=null){int color=capture.getPixel(capture.getWidth()/2,capture.getHeight()/2);assertEquals("Secure app content must be black in capture",0,color&0x00ffffff);capture.recycle();}
|
|
open();View card=text(activity.getWindow().getDecorView(),"Security synthetic");main(()->((View)card.getParent().getParent()).performClick());secure(activity.getWindow());
|
|
View remove=text(activity.getWindow().getDecorView(),"Удалить карточку");assertNotNull(remove);main(remove::performClick);secure(dialog().getWindow());main(activity::finish);
|
|
Intent autofill=new Intent(c,AutofillActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).putExtra("domain","example.test").putExtra("targetPackage","example.browser");activity=(MainActivity)instrument.startActivitySync(autofill);secure(activity.getWindow());open();
|
|
View choice=text(activity.getWindow().getDecorView(),"Security synthetic\nsecurity@example.test");assertNotNull(choice);main(choice::performClick);secure(dialog().getWindow());
|
|
main(()->activity.moveTaskToBack(true));long end=System.currentTimeMillis()+10000;
|
|
while(dialog()!=null&&System.currentTimeMillis()<end){Thread.sleep(100);instrument.waitForIdleSync();}
|
|
assertNull("Leaving autofill must dismiss its confirmation",dialog());main(activity::finish);
|
|
}
|
|
}
|