Home | History | Annotate | Download | only in autofill
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.service.autofill;
     18 
     19 import static android.view.autofill.Helper.sDebug;
     20 
     21 import android.annotation.NonNull;
     22 import android.annotation.Nullable;
     23 import android.annotation.TestApi;
     24 import android.os.Parcel;
     25 import android.os.Parcelable;
     26 import android.util.Slog;
     27 import android.view.autofill.AutofillValue;
     28 
     29 import com.android.internal.util.Preconditions;
     30 
     31 import java.util.regex.Matcher;
     32 import java.util.regex.Pattern;
     33 
     34 /**
     35  * Sanitizes a text {@link AutofillValue} using a regular expression (regex) substitution.
     36  *
     37  * <p>For example, to remove spaces from groups of 4-digits in a credit card:
     38  *
     39  * <pre class="prettyprint">
     40  * new TextValueSanitizer(Pattern.compile("^(\\d{4})\\s?(\\d{4})\\s?(\\d{4})\\s?(\\d{4})$"),
     41  *     "$1$2$3$4")
     42  * </pre>
     43  */
     44 public final class TextValueSanitizer extends InternalSanitizer implements
     45         Sanitizer, Parcelable {
     46     private static final String TAG = "TextValueSanitizer";
     47 
     48     private final Pattern mRegex;
     49     private final String mSubst;
     50 
     51     /**
     52      * Default constructor.
     53      *
     54      * @param regex regular expression with groups (delimited by {@code (} and {@code (}) that
     55      * are used to substitute parts of the {@link AutofillValue#getTextValue() text value}.
     56      * @param subst the string that substitutes the matched regex, using {@code $} for
     57      * group substitution ({@code $1} for 1st group match, {@code $2} for 2nd, etc).
     58      */
     59     public TextValueSanitizer(@NonNull Pattern regex, @NonNull String subst) {
     60         mRegex = Preconditions.checkNotNull(regex);
     61         mSubst = Preconditions.checkNotNull(subst);
     62     }
     63 
     64     /** @hide */
     65     @Override
     66     @TestApi
     67     @Nullable
     68     public AutofillValue sanitize(@NonNull AutofillValue value) {
     69         if (value == null) {
     70             Slog.w(TAG, "sanitize() called with null value");
     71             return null;
     72         }
     73         if (!value.isText()) {
     74             if (sDebug) Slog.d(TAG, "sanitize() called with non-text value: " + value);
     75             return null;
     76         }
     77 
     78         final CharSequence text = value.getTextValue();
     79 
     80         try {
     81             final Matcher matcher = mRegex.matcher(text);
     82             if (!matcher.matches()) {
     83                 if (sDebug) Slog.d(TAG, "sanitize(): " + mRegex + " failed for " + value);
     84                 return null;
     85             }
     86 
     87             final CharSequence sanitized = matcher.replaceAll(mSubst);
     88             return AutofillValue.forText(sanitized);
     89         } catch (Exception e) {
     90             Slog.w(TAG, "Exception evaluating " + mRegex + "/" + mSubst + ": " + e);
     91             return null;
     92         }
     93     }
     94 
     95     /////////////////////////////////////
     96     // Object "contract" methods. //
     97     /////////////////////////////////////
     98     @Override
     99     public String toString() {
    100         if (!sDebug) return super.toString();
    101 
    102         return "TextValueSanitizer: [regex=" + mRegex + ", subst=" + mSubst + "]";
    103     }
    104 
    105     /////////////////////////////////////
    106     // Parcelable "contract" methods. //
    107     /////////////////////////////////////
    108     @Override
    109     public int describeContents() {
    110         return 0;
    111     }
    112 
    113     @Override
    114     public void writeToParcel(Parcel parcel, int flags) {
    115         parcel.writeSerializable(mRegex);
    116         parcel.writeString(mSubst);
    117     }
    118 
    119     public static final Parcelable.Creator<TextValueSanitizer> CREATOR =
    120             new Parcelable.Creator<TextValueSanitizer>() {
    121         @Override
    122         public TextValueSanitizer createFromParcel(Parcel parcel) {
    123             return new TextValueSanitizer((Pattern) parcel.readSerializable(), parcel.readString());
    124         }
    125 
    126         @Override
    127         public TextValueSanitizer[] newArray(int size) {
    128             return new TextValueSanitizer[size];
    129         }
    130     };
    131 }
    132