Home | History | Annotate | Download | only in service
      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 package com.example.android.autofillframework.service;
     17 
     18 import android.app.Activity;
     19 import android.app.PendingIntent;
     20 import android.app.assist.AssistStructure;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.IntentSender;
     24 import android.os.Bundle;
     25 import android.service.autofill.Dataset;
     26 import android.service.autofill.FillResponse;
     27 import android.support.annotation.Nullable;
     28 import android.text.Editable;
     29 import android.util.Log;
     30 import android.view.View;
     31 import android.view.View.OnClickListener;
     32 import android.widget.Button;
     33 import android.widget.EditText;
     34 import android.widget.Toast;
     35 
     36 import com.example.android.autofillframework.R;
     37 import com.example.android.autofillframework.service.datasource.LocalAutofillRepository;
     38 import com.example.android.autofillframework.service.model.AutofillFieldsCollection;
     39 import com.example.android.autofillframework.service.model.ClientFormData;
     40 import com.example.android.autofillframework.service.settings.MyPreferences;
     41 
     42 import java.util.HashMap;
     43 
     44 import static android.view.autofill.AutofillManager.EXTRA_ASSIST_STRUCTURE;
     45 import static android.view.autofill.AutofillManager.EXTRA_AUTHENTICATION_RESULT;
     46 import static com.example.android.autofillframework.CommonUtil.EXTRA_DATASET_NAME;
     47 import static com.example.android.autofillframework.CommonUtil.EXTRA_FOR_RESPONSE;
     48 import static com.example.android.autofillframework.CommonUtil.TAG;
     49 
     50 /**
     51  * This Activity controls the UI for logging in to the Autofill service.
     52  * It is launched when an Autofill Response or specific Dataset within the Response requires
     53  * authentication to access. It bundles the result in an Intent.
     54  */
     55 public class AuthActivity extends Activity {
     56 
     57     // Unique id for dataset intents.
     58     private static int sDatasetPendingIntentId = 0;
     59 
     60     private EditText mMasterPassword;
     61     private Button mCancel;
     62     private Button mLogin;
     63     private Intent mReplyIntent;
     64 
     65     static IntentSender getAuthIntentSenderForResponse(Context context) {
     66         final Intent intent = new Intent(context, AuthActivity.class);
     67         return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT)
     68                 .getIntentSender();
     69     }
     70 
     71     static IntentSender getAuthIntentSenderForDataset(Context context, String datasetName) {
     72         final Intent intent = new Intent(context, AuthActivity.class);
     73         intent.putExtra(EXTRA_DATASET_NAME, datasetName);
     74         intent.putExtra(EXTRA_FOR_RESPONSE, false);
     75         return PendingIntent.getActivity(context, ++sDatasetPendingIntentId, intent,
     76                 PendingIntent.FLAG_CANCEL_CURRENT).getIntentSender();
     77     }
     78 
     79     @Override
     80     protected void onCreate(@Nullable Bundle savedInstanceState) {
     81         super.onCreate(savedInstanceState);
     82 
     83         setContentView(R.layout.auth_activity);
     84         mCancel = findViewById(R.id.cancel);
     85         mLogin = findViewById(R.id.login);
     86         mMasterPassword = findViewById(R.id.master_password);
     87         mLogin.setOnClickListener(new OnClickListener() {
     88             @Override
     89             public void onClick(View v) {
     90                 login();
     91             }
     92 
     93         });
     94 
     95         mCancel.setOnClickListener(new OnClickListener() {
     96             @Override
     97             public void onClick(View v) {
     98                 onFailure();
     99                 AuthActivity.this.finish();
    100             }
    101         });
    102     }
    103 
    104     private void login() {
    105         Editable password = mMasterPassword.getText();
    106         if (password.toString()
    107                 .equals(MyPreferences.getInstance(AuthActivity.this).getMasterPassword())) {
    108             onSuccess();
    109         } else {
    110             Toast.makeText(this, "Password incorrect", Toast.LENGTH_SHORT).show();
    111             onFailure();
    112         }
    113         finish();
    114     }
    115 
    116     @Override
    117     public void finish() {
    118         if (mReplyIntent != null) {
    119             setResult(RESULT_OK, mReplyIntent);
    120         } else {
    121             setResult(RESULT_CANCELED);
    122         }
    123         super.finish();
    124     }
    125 
    126     private void onFailure() {
    127         Log.w(TAG, "Failed auth.");
    128         mReplyIntent = null;
    129     }
    130 
    131     private void onSuccess() {
    132         Intent intent = getIntent();
    133         boolean forResponse = intent.getBooleanExtra(EXTRA_FOR_RESPONSE, true);
    134         AssistStructure structure = intent.getParcelableExtra(EXTRA_ASSIST_STRUCTURE);
    135         StructureParser parser = new StructureParser(structure);
    136         parser.parse();
    137         AutofillFieldsCollection autofillFields = parser.getAutofillFields();
    138         int saveTypes = parser.getSaveTypes();
    139         mReplyIntent = new Intent();
    140         HashMap<String, ClientFormData> clientFormDataMap =
    141                 LocalAutofillRepository.getInstance(this).getClientFormData
    142                         (autofillFields.getFocusedHints(), autofillFields.getAllHints());
    143         if (forResponse) {
    144             setResponseIntent(AutofillHelper.newResponse
    145                     (this, false, autofillFields, saveTypes, clientFormDataMap));
    146         } else {
    147             String datasetName = intent.getStringExtra(EXTRA_DATASET_NAME);
    148             setDatasetIntent(AutofillHelper.newDataset
    149                     (this, autofillFields, clientFormDataMap.get(datasetName)));
    150         }
    151     }
    152 
    153     private void setResponseIntent(FillResponse fillResponse) {
    154         mReplyIntent.putExtra(EXTRA_AUTHENTICATION_RESULT, fillResponse);
    155     }
    156 
    157     private void setDatasetIntent(Dataset dataset) {
    158         mReplyIntent.putExtra(EXTRA_AUTHENTICATION_RESULT, dataset);
    159     }
    160 }
    161