Add a reset mechanism into content protection processor
Bug: 275732576 Test: Added tests and manual end to end Change-Id: I72238dae65b634c54cc62a0f2df4dff5816ae1c3
This commit is contained in:
@@ -75,6 +75,8 @@ public class ContentProtectionEventProcessor {
|
||||
ContentCaptureEvent.TYPE_VIEW_DISAPPEARED,
|
||||
ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED)));
|
||||
|
||||
private static final int RESET_LOGIN_TOTAL_EVENTS_TO_PROCESS = 150;
|
||||
|
||||
@NonNull private final RingBuffer<ContentCaptureEvent> mEventBuffer;
|
||||
|
||||
@NonNull private final Handler mHandler;
|
||||
@@ -93,6 +95,8 @@ public class ContentProtectionEventProcessor {
|
||||
@Nullable
|
||||
public Instant mLastFlushTime;
|
||||
|
||||
private int mResetLoginRemainingEventsToProcess;
|
||||
|
||||
public ContentProtectionEventProcessor(
|
||||
@NonNull RingBuffer<ContentCaptureEvent> eventBuffer,
|
||||
@NonNull Handler handler,
|
||||
@@ -130,6 +134,8 @@ public class ContentProtectionEventProcessor {
|
||||
mSuspiciousTextDetected |= isSuspiciousText(event);
|
||||
if (mPasswordFieldDetected && mSuspiciousTextDetected) {
|
||||
loginDetected();
|
||||
} else {
|
||||
maybeResetLoginFlags();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,8 +145,28 @@ public class ContentProtectionEventProcessor {
|
||||
|| Instant.now().isAfter(mLastFlushTime.plus(MIN_DURATION_BETWEEN_FLUSHING))) {
|
||||
flush();
|
||||
}
|
||||
resetLoginFlags();
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void resetLoginFlags() {
|
||||
mPasswordFieldDetected = false;
|
||||
mSuspiciousTextDetected = false;
|
||||
mResetLoginRemainingEventsToProcess = 0;
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void maybeResetLoginFlags() {
|
||||
if (mPasswordFieldDetected || mSuspiciousTextDetected) {
|
||||
if (mResetLoginRemainingEventsToProcess <= 0) {
|
||||
mResetLoginRemainingEventsToProcess = RESET_LOGIN_TOTAL_EVENTS_TO_PROCESS;
|
||||
} else {
|
||||
mResetLoginRemainingEventsToProcess--;
|
||||
if (mResetLoginRemainingEventsToProcess <= 0) {
|
||||
resetLoginFlags();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
|
||||
@@ -91,6 +91,8 @@ public class ContentProtectionEventProcessorTest {
|
||||
private static final Set<Integer> EVENT_TYPES_TO_STORE =
|
||||
ImmutableSet.of(TYPE_VIEW_APPEARED, TYPE_VIEW_DISAPPEARED, TYPE_VIEW_TEXT_CHANGED);
|
||||
|
||||
private static final int RESET_LOGIN_TOTAL_EVENTS_TO_PROCESS = 150;
|
||||
|
||||
@Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
|
||||
@Mock private RingBuffer<ContentCaptureEvent> mMockEventBuffer;
|
||||
@@ -231,6 +233,56 @@ public class ContentProtectionEventProcessorTest {
|
||||
verifyZeroInteractions(mMockContentCaptureManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void processEvent_loginDetected_belowResetLimit() throws Exception {
|
||||
when(mMockEventBuffer.toArray()).thenReturn(BUFFERED_EVENTS);
|
||||
mContentProtectionEventProcessor.mSuspiciousTextDetected = true;
|
||||
ContentCaptureEvent event =
|
||||
createAndroidPasswordFieldEvent(
|
||||
ANDROID_CLASS_NAME, InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
|
||||
for (int i = 0; i < RESET_LOGIN_TOTAL_EVENTS_TO_PROCESS; i++) {
|
||||
mContentProtectionEventProcessor.processEvent(PROCESS_EVENT);
|
||||
}
|
||||
|
||||
assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
|
||||
assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isTrue();
|
||||
verify(mMockEventBuffer, never()).clear();
|
||||
verify(mMockEventBuffer, never()).toArray();
|
||||
|
||||
mContentProtectionEventProcessor.processEvent(event);
|
||||
|
||||
assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
|
||||
assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isFalse();
|
||||
verify(mMockEventBuffer).clear();
|
||||
verify(mMockEventBuffer).toArray();
|
||||
assertOnLoginDetected();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void processEvent_loginDetected_aboveResetLimit() throws Exception {
|
||||
mContentProtectionEventProcessor.mSuspiciousTextDetected = true;
|
||||
ContentCaptureEvent event =
|
||||
createAndroidPasswordFieldEvent(
|
||||
ANDROID_CLASS_NAME, InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
|
||||
for (int i = 0; i < RESET_LOGIN_TOTAL_EVENTS_TO_PROCESS + 1; i++) {
|
||||
mContentProtectionEventProcessor.processEvent(PROCESS_EVENT);
|
||||
}
|
||||
|
||||
assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isFalse();
|
||||
assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isFalse();
|
||||
verify(mMockEventBuffer, never()).clear();
|
||||
verify(mMockEventBuffer, never()).toArray();
|
||||
|
||||
mContentProtectionEventProcessor.processEvent(event);
|
||||
|
||||
assertThat(mContentProtectionEventProcessor.mPasswordFieldDetected).isTrue();
|
||||
assertThat(mContentProtectionEventProcessor.mSuspiciousTextDetected).isFalse();
|
||||
verify(mMockEventBuffer, never()).clear();
|
||||
verify(mMockEventBuffer, never()).toArray();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void processEvent_multipleLoginsDetected_belowFlushThreshold() throws Exception {
|
||||
when(mMockEventBuffer.toArray()).thenReturn(BUFFERED_EVENTS);
|
||||
|
||||
Reference in New Issue
Block a user