Home | History | Annotate | Download | only in accounts
      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.android.settings.accounts;
     17 
     18 import android.accounts.Account;
     19 import android.accounts.AccountManager;
     20 import android.accounts.AccountManagerCallback;
     21 import android.accounts.AccountManagerFuture;
     22 import android.accounts.AuthenticatorException;
     23 import android.accounts.OperationCanceledException;
     24 import android.app.Activity;
     25 import android.app.AlertDialog;
     26 import android.app.Dialog;
     27 import android.app.Fragment;
     28 import android.content.Context;
     29 import android.content.DialogInterface;
     30 import android.content.Intent;
     31 import android.os.Bundle;
     32 import android.os.Process;
     33 import android.os.UserHandle;
     34 import android.support.v7.preference.PreferenceScreen;
     35 import android.view.View;
     36 import android.view.View.OnClickListener;
     37 import android.widget.Button;
     38 
     39 import com.android.internal.logging.nano.MetricsProto;
     40 import com.android.settings.R;
     41 import com.android.settings.applications.LayoutPreference;
     42 import com.android.settings.core.PreferenceController;
     43 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
     44 
     45 import java.io.IOException;
     46 
     47 public class RemoveAccountPreferenceController extends PreferenceController
     48     implements OnClickListener {
     49 
     50     private static final String KEY_REMOVE_ACCOUNT = "remove_account";
     51 
     52     private Account mAccount;
     53     private Fragment mParentFragment;
     54     private UserHandle mUserHandle;
     55 
     56     public RemoveAccountPreferenceController(Context context, Fragment parent) {
     57         super(context);
     58         mParentFragment = parent;
     59     }
     60 
     61     @Override
     62     public void displayPreference(PreferenceScreen screen) {
     63         super.displayPreference(screen);
     64         final LayoutPreference removeAccountPreference =
     65             (LayoutPreference) screen.findPreference(KEY_REMOVE_ACCOUNT);
     66         Button removeAccountButton = (Button) removeAccountPreference.findViewById(R.id.button);
     67         removeAccountButton.setOnClickListener(this);
     68     }
     69 
     70     @Override
     71     public boolean isAvailable() {
     72         return true;
     73     }
     74 
     75     @Override
     76     public String getPreferenceKey() {
     77         return KEY_REMOVE_ACCOUNT;
     78     }
     79 
     80     @Override
     81     public void onClick(View v) {
     82         ConfirmRemoveAccountDialog.show(mParentFragment, mAccount, mUserHandle);
     83     }
     84 
     85     public void init(Account account, UserHandle userHandle) {
     86         mAccount = account;
     87         mUserHandle = userHandle;
     88     }
     89 
     90     /**
     91      * Dialog to confirm with user about account removal
     92      */
     93     public static class ConfirmRemoveAccountDialog extends InstrumentedDialogFragment implements
     94             DialogInterface.OnClickListener {
     95         private static final String KEY_ACCOUNT = "account";
     96         private static final String REMOVE_ACCOUNT_DIALOG = "confirmRemoveAccount";
     97         private Account mAccount;
     98         private UserHandle mUserHandle;
     99 
    100         public static ConfirmRemoveAccountDialog show(
    101                 Fragment parent, Account account, UserHandle userHandle) {
    102             if (!parent.isAdded()) {
    103                 return null;
    104             }
    105             final ConfirmRemoveAccountDialog dialog = new ConfirmRemoveAccountDialog();
    106             Bundle bundle = new Bundle();
    107             bundle.putParcelable(KEY_ACCOUNT, account);
    108             bundle.putParcelable(Intent.EXTRA_USER, userHandle);
    109             dialog.setArguments(bundle);
    110             dialog.setTargetFragment(parent, 0);
    111             dialog.show(parent.getFragmentManager(), REMOVE_ACCOUNT_DIALOG);
    112             return dialog;
    113         }
    114 
    115         @Override
    116         public void onCreate(Bundle savedInstanceState) {
    117             super.onCreate(savedInstanceState);
    118             final Bundle arguments = getArguments();
    119             mAccount = arguments.getParcelable(KEY_ACCOUNT);
    120             mUserHandle = arguments.getParcelable(Intent.EXTRA_USER);
    121         }
    122 
    123         @Override
    124         public Dialog onCreateDialog(Bundle savedInstanceState) {
    125             final Context context = getActivity();
    126             return new AlertDialog.Builder(context)
    127                 .setTitle(R.string.really_remove_account_title)
    128                 .setMessage(R.string.really_remove_account_message)
    129                 .setNegativeButton(android.R.string.cancel, null)
    130                 .setPositiveButton(R.string.remove_account_label, this)
    131                 .create();
    132         }
    133 
    134         @Override
    135         public int getMetricsCategory() {
    136             return MetricsProto.MetricsEvent.DIALOG_ACCOUNT_SYNC_REMOVE;
    137         }
    138 
    139         @Override
    140         public void onClick(DialogInterface dialog, int which) {
    141             Activity activity = getTargetFragment().getActivity();
    142             AccountManager.get(activity).removeAccountAsUser(mAccount, activity,
    143                     new AccountManagerCallback<Bundle>() {
    144                         @Override
    145                         public void run(AccountManagerFuture<Bundle> future) {
    146                             // If already out of this screen, don't proceed.
    147                             if (!getTargetFragment().isResumed()) {
    148                                 return;
    149                             }
    150                             boolean failed = true;
    151                             try {
    152                                 if (future.getResult()
    153                                     .getBoolean(AccountManager.KEY_BOOLEAN_RESULT)) {
    154                                     failed = false;
    155                                 }
    156                             } catch (OperationCanceledException e) {
    157                                 // handled below
    158                             } catch (IOException e) {
    159                                 // handled below
    160                             } catch (AuthenticatorException e) {
    161                                 // handled below
    162                             }
    163                             final Activity activity = getTargetFragment().getActivity();
    164                             if (failed && activity != null && !activity.isFinishing()) {
    165                                 RemoveAccountFailureDialog.show(getTargetFragment());
    166                             } else {
    167                                 activity.finish();
    168                             }
    169                         }
    170                     }, null, mUserHandle);
    171         }
    172     }
    173 
    174     /**
    175      * Dialog to tell user about account removal failure
    176      */
    177     public static class RemoveAccountFailureDialog extends InstrumentedDialogFragment {
    178 
    179         private static final String FAILED_REMOVAL_DIALOG = "removeAccountFailed";
    180 
    181         public static void show(Fragment parent) {
    182             if (!parent.isAdded()) {
    183                 return;
    184             }
    185             final RemoveAccountFailureDialog dialog = new RemoveAccountFailureDialog();
    186             dialog.setTargetFragment(parent, 0);
    187             dialog.show(parent.getFragmentManager(), FAILED_REMOVAL_DIALOG);
    188         }
    189 
    190         @Override
    191         public Dialog onCreateDialog(Bundle savedInstanceState) {
    192             final Context context = getActivity();
    193 
    194             return new AlertDialog.Builder(context)
    195                 .setTitle(R.string.really_remove_account_title)
    196                 .setMessage(R.string.remove_account_failed)
    197                 .setPositiveButton(android.R.string.ok, null)
    198                 .create();
    199         }
    200 
    201         @Override
    202         public int getMetricsCategory() {
    203             return MetricsProto.MetricsEvent.DIALOG_ACCOUNT_SYNC_FAILED_REMOVAL;
    204         }
    205 
    206     }
    207 }
    208