Have WebView Implementation Dev Setting use DefaultAppPickerFragment.

Make the WebView Implementation Dev Setting look like the fullscreen
settings deriving from DefaultAppPickerFragment.
Point the Activity opened through Settings.ACTION_WEBVIEW_SETTINGS to
the class WebViewAppPicker which is our new implementation of the
WebView Implementation setting.

Ensure the new setting closes if it is reached from a user that isn't an
admin of the device.

Bug: 34806477
Bug: 34966439
Test: Ensure WebView implementation Dev Setting looks ok (disabled
packages should have a text showing why they cannot be chosen).
Test: Start Intent with action Settings.ACTION_WEBVIEW_SETTINGS and
ensure the started Activity looks similar to the WebView Implementation
Dev Setting.
Test: Ensure picking a package that is no longer active, updates the
setting (so that package isn't visible anymore).
Change-Id: I08007c515193739ad61dfd735bb5130fc07bd6e6
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index e754d6a..2e99ed3 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1979,8 +1979,9 @@
         <activity android:name=".AppPicker" android:label="@string/select_application"
                 android:theme="@android:style/Theme.DeviceDefault.Light.Dialog" />
 
-        <activity android:name=".webview.WebViewAppPicker" android:label="@string/select_webview_provider_dialog_title"
-                android:theme="@android:style/Theme.DeviceDefault.Light.Dialog" />
+        <activity android:name="Settings$WebViewAppPickerActivity"
+                  android:label="@string/select_webview_provider_dialog_title">
+        </activity>
 
         <!-- Keep compatibility with old shortcuts. -->
         <activity-alias android:name="UsbSettings"
@@ -2940,7 +2941,7 @@
 
         <!-- Keep compatibility with old WebView-picker implementation -->
         <activity-alias android:name=".WebViewImplementation"
-                  android:targetActivity=".webview.WebViewAppPicker"
+                  android:targetActivity="Settings$WebViewAppPickerActivity"
                   android:exported="true"
                   android:excludeFromRecents="true"
                   android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert">
@@ -2950,6 +2951,8 @@
             </intent-filter>
             <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
                 android:value="true" />
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                android:value="com.android.settings.webview.WebViewAppPicker" />
       </activity-alias>
 
         <!-- activity for gesture settings -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 396db4a..e8c82f9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -8163,9 +8163,9 @@
     <string name="game_storage_settings">Games</string>
 
     <!-- UI webview setting: WebView uninstalled-for-user explanatory text [CHAR LIMIT=30] -->
-    <string name="webview_uninstalled_for_user">Uninstalled for user <xliff:g id="user" example="John Doe">%s</xliff:g>\n</string>
+    <string name="webview_uninstalled_for_user">(uninstalled for user <xliff:g id="user" example="John Doe">%s</xliff:g>)</string>
     <!-- UI webview setting: WebView disabled-for-user explanatory text [CHAR LIMIT=30] -->
-    <string name="webview_disabled_for_user">Disabled for user <xliff:g id="user" example="John Doe">%s</xliff:g>\n</string>
+    <string name="webview_disabled_for_user">(disabled for user <xliff:g id="user" example="John Doe">%s</xliff:g>)</string>
 
     <!-- AutoFill strings -->
     <!-- Preference label for the auto-fill app. [CHAR LIMIT=60] -->
diff --git a/res/xml/development_prefs.xml b/res/xml/development_prefs.xml
index b8043c9..e857a0e 100644
--- a/res/xml/development_prefs.xml
+++ b/res/xml/development_prefs.xml
@@ -76,7 +76,8 @@
 
     <Preference android:key="select_webview_provider"
         android:title="@string/select_webview_provider_title"
-        android:dialogTitle="@string/select_webview_provider_dialog_title" />
+        android:dialogTitle="@string/select_webview_provider_dialog_title"
+        android:fragment="com.android.settings.webview.WebViewAppPicker" />
 
     <SwitchPreference
         android:key="enable_webview_multiprocess"
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index 2c50c5f..b1b7fc6 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -232,7 +232,6 @@
 
     private static final int RESULT_DEBUG_APP = 1000;
     private static final int RESULT_MOCK_LOCATION_APP = 1001;
-    private static final int RESULT_WEBVIEW_APP = 1002;
 
     private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
     private static final String FLASH_LOCKED_PROP = "ro.boot.flash.locked";
@@ -800,7 +799,8 @@
         updateSimulateColorSpace();
         updateUSBAudioOptions();
         updateForceResizableOptions();
-        mWebViewAppPrefController.updateState(null);
+        Preference webViewAppPref = findPreference(mWebViewAppPrefController.getPreferenceKey());
+        mWebViewAppPrefController.updateState(webViewAppPref);
         updateWebViewMultiprocessOptions();
         updateOemUnlockOptions();
         if (mColorTemperaturePreference != null) {
@@ -2311,8 +2311,6 @@
                 writeMockLocation();
                 updateMockLocation();
             }
-        } else if (requestCode == RESULT_WEBVIEW_APP) {
-            mWebViewAppPrefController.onActivityResult(resultCode, data);
         } else if (requestCode == REQUEST_CODE_ENABLE_OEM_UNLOCK) {
             if (resultCode == Activity.RESULT_OK) {
                 if (mEnableOemUnlock.isChecked()) {
@@ -2336,8 +2334,7 @@
             return true;
         }
         if (mWebViewAppPrefController.handlePreferenceTreeClick(preference)) {
-            startActivityForResult(
-                    mWebViewAppPrefController.getActivityIntent(), RESULT_WEBVIEW_APP);
+            return true;
         }
 
         if (preference == mEnableAdb) {
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index dfa291c..cd6889b 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -164,6 +164,7 @@
     public static class WifiAPITestActivity extends SettingsActivity { /* empty */ }
     public static class WifiInfoActivity extends SettingsActivity { /* empty */ }
     public static class EnterprisePrivacySettingsActivity extends SettingsActivity { /* empty */ }
+    public static class WebViewAppPickerActivity extends SettingsActivity { /* empty */ }
 
     // Categories.
     public static class WirelessSettings extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/applications/defaultapps/DefaultAppInfo.java b/src/com/android/settings/applications/defaultapps/DefaultAppInfo.java
index 7801591..ea3a27a 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultAppInfo.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultAppInfo.java
@@ -29,25 +29,33 @@
 /**
  * Data model representing an app in DefaultAppPicker UI.
  */
-class DefaultAppInfo {
+public class DefaultAppInfo {
 
     public final int userId;
     public final ComponentName componentName;
     public final PackageItemInfo packageItemInfo;
     public final String summary;
+    // Description for why this item is disabled, if null, the item is enabled.
+    public final String disabledDescription;
 
     public DefaultAppInfo(int uid, ComponentName cn, String summary) {
         packageItemInfo = null;
         userId = uid;
         componentName = cn;
         this.summary = summary;
+        this.disabledDescription = null;
     }
 
-    public DefaultAppInfo(PackageItemInfo info) {
+    public DefaultAppInfo(PackageItemInfo info, String description) {
         userId = UserHandle.myUserId();
         packageItemInfo = info;
         componentName = null;
         summary = null;
+        this.disabledDescription = description;
+    }
+
+    public DefaultAppInfo(PackageItemInfo info) {
+        this(info, null);
     }
 
     public CharSequence loadLabel(PackageManager pm) {
diff --git a/src/com/android/settings/applications/defaultapps/DefaultAppPickerFragment.java b/src/com/android/settings/applications/defaultapps/DefaultAppPickerFragment.java
index b322dab..b458337 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultAppPickerFragment.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultAppPickerFragment.java
@@ -91,6 +91,11 @@
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         super.onCreatePreferences(savedInstanceState, rootKey);
         addPreferencesFromResource(R.xml.app_picker_prefs);
+        updateCandidates();
+    }
+
+    @VisibleForTesting
+    public void updateCandidates() {
         mCandidates.clear();
         final List<DefaultAppInfo> candidateList = getCandidates();
         if (candidateList != null) {
@@ -123,6 +128,10 @@
             if (TextUtils.equals(systemDefaultAppKey, appKey)) {
                 pref.setSummary(R.string.system_app);
             }
+            if (!TextUtils.isEmpty(app.getValue().disabledDescription)) {
+                pref.setEnabled(false);
+                pref.setSummary(app.getValue().disabledDescription);
+            }
             pref.setOnClickListener(this);
             screen.addPreference(pref);
         }
@@ -145,18 +154,23 @@
     private void onRadioButtonConfirmed(String selectedKey) {
         final boolean success = setDefaultAppKey(selectedKey);
         if (success) {
-            final PreferenceScreen screen = getPreferenceScreen();
-            if (screen != null) {
-                final int count = screen.getPreferenceCount();
-                for (int i = 0; i < count; i++) {
-                    final Preference pref = screen.getPreference(i);
-                    if (pref instanceof RadioButtonPreference) {
-                        final RadioButtonPreference radioPref = (RadioButtonPreference) pref;
-                        final boolean newCheckedState =
-                                TextUtils.equals(pref.getKey(), selectedKey);
-                        if (radioPref.isChecked() != newCheckedState) {
-                            radioPref.setChecked(TextUtils.equals(pref.getKey(), selectedKey));
-                        }
+            updateCheckedState(selectedKey);
+        }
+        onSelectionPerformed(success);
+    }
+
+    @VisibleForTesting
+    public void updateCheckedState(String selectedKey) {
+        final PreferenceScreen screen = getPreferenceScreen();
+        if (screen != null) {
+            final int count = screen.getPreferenceCount();
+            for (int i = 0; i < count; i++) {
+                final Preference pref = screen.getPreference(i);
+                if (pref instanceof RadioButtonPreference) {
+                    final RadioButtonPreference radioPref = (RadioButtonPreference) pref;
+                    final boolean newCheckedState = TextUtils.equals(pref.getKey(), selectedKey);
+                    if (radioPref.isChecked() != newCheckedState) {
+                        radioPref.setChecked(TextUtils.equals(pref.getKey(), selectedKey));
                     }
                 }
             }
@@ -177,6 +191,9 @@
 
     protected abstract boolean setDefaultAppKey(String key);
 
+    // Called after the user tries to select an item.
+    protected void onSelectionPerformed(boolean success) {}
+
     protected String getConfirmationMessage(DefaultAppInfo appInfo) {
         return null;
     }
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 2f0dff3..dece26a 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -121,6 +121,7 @@
 import com.android.settings.tts.TextToSpeechSettings;
 import com.android.settings.users.UserSettings;
 import com.android.settings.vpn2.VpnSettings;
+import com.android.settings.webview.WebViewAppPicker;
 import com.android.settings.wfd.WifiDisplaySettings;
 import com.android.settings.wifi.ConfigureWifiSettings;
 import com.android.settings.wifi.SavedAccessPointsWifiSettings;
@@ -248,6 +249,7 @@
             AppAndNotificationDashboardFragment.class.getName(),
             UserAndAccountDashboardFragment.class.getName(),
             EnterprisePrivacySettings.class.getName(),
+            WebViewAppPicker.class.getName(),
     };
 
     public static final String[] SETTINGS_FOR_RESTRICTED = {
diff --git a/src/com/android/settings/webview/WebViewAppListAdapter.java b/src/com/android/settings/webview/WebViewAppListAdapter.java
deleted file mode 100644
index 4c36a47..0000000
--- a/src/com/android/settings/webview/WebViewAppListAdapter.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.settings.webview;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.os.RemoteException;
-import android.graphics.Color;
-import android.support.annotation.VisibleForTesting;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-
-import com.android.settings.applications.AppViewHolder;
-import com.android.settings.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Custom list adapter for Settings to choose WebView package.
- * Note: parts of this class are copied from AppPicker.java.
- */
-class WebViewAppListAdapter extends ArrayAdapter<WebViewApplicationInfo> {
-    private final LayoutInflater mInflater;
-    private final String mCurrentWebViewPackageName;
-
-    public WebViewAppListAdapter(Context context,
-            WebViewUpdateServiceWrapper webviewUpdateServiceWrapper) {
-        super(context, 0);
-        mInflater = LayoutInflater.from(context);
-
-        final List<WebViewApplicationInfo> packageInfoList =
-                new ArrayList<WebViewApplicationInfo>();
-        List<ApplicationInfo> pkgs =
-                webviewUpdateServiceWrapper.getValidWebViewApplicationInfos(getContext());
-        for (ApplicationInfo ai : pkgs) {
-            WebViewApplicationInfo info = new WebViewApplicationInfo(ai,
-                    ai.loadLabel(context.getPackageManager()).toString(),
-                    getDisabledReason(webviewUpdateServiceWrapper, context, ai.packageName));
-            packageInfoList.add(info);
-        }
-        addAll(packageInfoList);
-
-        PackageInfo currentWebViewPackage = webviewUpdateServiceWrapper.getCurrentWebViewPackage();
-        mCurrentWebViewPackageName =
-                currentWebViewPackage == null ? null : currentWebViewPackage.packageName;
-    }
-
-    @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
-        // A ViewHolder keeps references to children views to avoid unnecessary calls
-        // to findViewById() on each row.
-        AppViewHolder holder = AppViewHolder.createOrRecycle(mInflater, convertView);
-        convertView = holder.rootView;
-        WebViewApplicationInfo info = getItem(position);
-        holder.appName.setText(info.label);
-        if (info.info != null) {
-            holder.appIcon.setImageDrawable(info.info.loadIcon(getContext().getPackageManager()));
-            // Allow disable-description to wrap - to be able to show several lines of text in case
-            // a package is disabled/uninstalled for several users.
-            holder.summary.setSingleLine(false);
-            if (!isEnabled(position)) {
-                holder.summary.setText(info.disabledReason);
-            } else {
-                holder.summary.setText("");
-            }
-        } else {
-            holder.appIcon.setImageDrawable(null);
-            holder.summary.setText("");
-        }
-        holder.disabled.setVisibility(View.GONE);
-        // Only allow a package to be chosen if it is enabled and installed for all users.
-        convertView.setEnabled(isEnabled(position));
-        if (info.info.packageName.equals(mCurrentWebViewPackageName)) {
-            convertView.setBackgroundColor(Color.GRAY);
-        } else {
-            convertView.setBackgroundColor(Color.WHITE);
-        }
-        return convertView;
-    }
-
-    @Override
-    public boolean isEnabled (int position) {
-        WebViewApplicationInfo info = getItem(position);
-        return info.disabledReason == null;
-    }
-
-    @Override
-    public boolean areAllItemsEnabled() {
-        int numItems = getCount();
-        for (int n = 0; n < numItems; n++) {
-            if (!isEnabled(n)) return false;
-        }
-        return true;
-    }
-
-    /**
-     * Returns the reason why a package cannot be used as WebView implementation.
-     * This is either because of it being disabled, uninstalled, or hidden for any user.
-     */
-    @VisibleForTesting
-    static String getDisabledReason(WebViewUpdateServiceWrapper webviewUpdateServiceWrapper,
-            Context context, String packageName) {
-        StringBuilder disabledReason = new StringBuilder();
-        List<UserPackageWrapper> userPackages =
-                webviewUpdateServiceWrapper.getPackageInfosAllUsers(context, packageName);
-        for (UserPackageWrapper userPackage : userPackages) {
-            if (!userPackage.isInstalledPackage()) {
-                // Package uninstalled/hidden
-                disabledReason.append(context.getString(
-                        R.string.webview_uninstalled_for_user, userPackage.getUserInfo().name));
-            } else if (!userPackage.isEnabledPackage()) {
-                // Package disabled
-                disabledReason.append(context.getString(
-                    R.string.webview_disabled_for_user, userPackage.getUserInfo().name));
-            }
-        }
-        if (disabledReason.length() == 0) return null;
-        return disabledReason.toString();
-    }
-}
-
diff --git a/src/com/android/settings/webview/WebViewAppPicker.java b/src/com/android/settings/webview/WebViewAppPicker.java
index 2417b00..aa229ac 100644
--- a/src/com/android/settings/webview/WebViewAppPicker.java
+++ b/src/com/android/settings/webview/WebViewAppPicker.java
@@ -16,57 +16,83 @@
 
 package com.android.settings.webview;
 
-import android.app.ListActivity;
+import static android.provider.Settings.ACTION_WEBVIEW_SETTINGS;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.RemoteException;
 import android.support.annotation.VisibleForTesting;
-import android.util.Log;
-import android.view.View;
-import android.webkit.WebViewFactory;
-import android.widget.ListView;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.core.instrumentation.Instrumentable;
-import com.android.settings.core.instrumentation.VisibilityLoggerMixin;
+import com.android.settings.R;
+import com.android.settings.applications.defaultapps.DefaultAppInfo;
+import com.android.settings.applications.defaultapps.DefaultAppPickerFragment;
 
-public class WebViewAppPicker extends ListActivity implements Instrumentable {
-    private static final String TAG = WebViewAppPicker.class.getSimpleName();
-    private WebViewAppListAdapter mAdapter;
+import java.util.ArrayList;
+import java.util.List;
+
+public class WebViewAppPicker extends DefaultAppPickerFragment {
     private WebViewUpdateServiceWrapper mWebViewUpdateServiceWrapper;
 
-    private final VisibilityLoggerMixin mVisibilityLoggerMixin =
-            new VisibilityLoggerMixin(getMetricsCategory());
-
-    @Override
-    protected void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
+    private WebViewUpdateServiceWrapper getWebViewUpdateServiceWrapper() {
         if (mWebViewUpdateServiceWrapper == null) {
             setWebViewUpdateServiceWrapper(createDefaultWebViewUpdateServiceWrapper());
         }
-        mAdapter = new WebViewAppListAdapter(this, mWebViewUpdateServiceWrapper);
-        setListAdapter(mAdapter);
-
-        mVisibilityLoggerMixin.onAttach(this);
+        return mWebViewUpdateServiceWrapper;
     }
 
     @Override
-    protected void onListItemClick(ListView l, View v, int position, long id) {
-        WebViewApplicationInfo app = mAdapter.getItem(position);
+    public void onAttach(Context context) {
+        super.onAttach(context);
 
-        if (mWebViewUpdateServiceWrapper.setWebViewProvider(app.info.packageName)) {
-            Intent intent = new Intent();
-            intent.setAction(app.info.packageName);
-            setResult(RESULT_OK, intent);
-        } else {
-            mWebViewUpdateServiceWrapper.showInvalidChoiceToast(this);
+        if (!mUserManager.isAdminUser()) {
+            getActivity().finish();
         }
-        finish();
     }
 
+    @Override
+    protected List<DefaultAppInfo> getCandidates() {
+        final List<DefaultAppInfo> packageInfoList = new ArrayList<DefaultAppInfo>();
+        List<ApplicationInfo> pkgs =
+                getWebViewUpdateServiceWrapper().getValidWebViewApplicationInfos(getContext());
+        for (ApplicationInfo ai : pkgs) {
+            packageInfoList.add(new DefaultAppInfo(ai,
+                      getDisabledReason(getWebViewUpdateServiceWrapper(),
+                              getContext(), ai.packageName)));
+        }
+        return packageInfoList;
+    }
+
+    @Override
+    protected String getDefaultAppKey() {
+        PackageInfo currentPackage = getWebViewUpdateServiceWrapper().getCurrentWebViewPackage();
+        return currentPackage == null ? null : currentPackage.packageName;
+    }
+
+    protected boolean setDefaultAppKey(String key) {
+        boolean success = getWebViewUpdateServiceWrapper().setWebViewProvider(key);
+        return success;
+    }
+
+    @Override
+    protected void onSelectionPerformed(boolean success) {
+        if (success) {
+            Activity activity = getActivity();
+            Intent intent = activity == null ? null : activity.getIntent();
+            if (intent != null && ACTION_WEBVIEW_SETTINGS.equals(intent.getAction())) {
+                // If this was started through ACTION_WEBVIEW_SETTINGS then return once we have
+                // chosen a new package.
+                getActivity().finish();
+            }
+        } else {
+            getWebViewUpdateServiceWrapper().showInvalidChoiceToast(getActivity());
+            updateCandidates();
+        }
+    }
+
+
     private WebViewUpdateServiceWrapper createDefaultWebViewUpdateServiceWrapper() {
         return new WebViewUpdateServiceWrapper();
     }
@@ -77,19 +103,31 @@
     }
 
     @Override
-    public void onResume() {
-        super.onResume();
-        mVisibilityLoggerMixin.onResume();
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        mVisibilityLoggerMixin.onPause();
-    }
-
-    @Override
     public int getMetricsCategory() {
         return MetricsEvent.WEBVIEW_IMPLEMENTATION;
     }
+
+    /**
+     * Returns the reason why a package cannot be used as WebView implementation.
+     * This is either because of it being disabled, uninstalled, or hidden for any user.
+     */
+    @VisibleForTesting
+    String getDisabledReason(WebViewUpdateServiceWrapper webviewUpdateServiceWrapper,
+            Context context, String packageName) {
+        StringBuilder disabledReason = new StringBuilder();
+        List<UserPackageWrapper> userPackages =
+                webviewUpdateServiceWrapper.getPackageInfosAllUsers(context, packageName);
+        for (UserPackageWrapper userPackage : userPackages) {
+            if (!userPackage.isInstalledPackage()) {
+                // Package uninstalled/hidden
+                return context.getString(
+                        R.string.webview_uninstalled_for_user, userPackage.getUserInfo().name);
+            } else if (!userPackage.isEnabledPackage()) {
+                // Package disabled
+                return context.getString(
+                    R.string.webview_disabled_for_user, userPackage.getUserInfo().name);
+            }
+        }
+        return null;
+    }
 }
diff --git a/src/com/android/settings/webview/WebViewAppPreferenceController.java b/src/com/android/settings/webview/WebViewAppPreferenceController.java
index cfb358e..3a181fe 100644
--- a/src/com/android/settings/webview/WebViewAppPreferenceController.java
+++ b/src/com/android/settings/webview/WebViewAppPreferenceController.java
@@ -14,18 +14,15 @@
 
 package com.android.settings.webview;
 
-import android.app.Activity;
-import android.content.pm.PackageInfo;
 import android.content.Context;
-import android.content.Intent;
-import android.support.annotation.VisibleForTesting;
+import android.content.pm.PackageInfo;
 import android.support.v7.preference.Preference;
 import android.support.v7.preference.PreferenceScreen;
 
-import com.android.settings.DevelopmentSettings;
-import com.android.settings.core.PreferenceController;
+import com.android.settings.applications.defaultapps.DefaultAppInfo;
+import com.android.settings.applications.defaultapps.DefaultAppPreferenceController;
 
-public class WebViewAppPreferenceController extends PreferenceController {
+public class WebViewAppPreferenceController extends DefaultAppPreferenceController {
 
     private static final String WEBVIEW_APP_KEY = "select_webview_provider";
 
@@ -45,20 +42,9 @@
     }
 
     @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        if (getPreferenceKey().equals(preference.getKey())) {
-            return true;
-        }
-        return false;
-    }
-
-    public Intent getActivityIntent() {
-        return new Intent(mContext, WebViewAppPicker.class);
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        mPreference.setSummary(getCurrentWebViewPackageLabel(mContext));
+    public DefaultAppInfo getDefaultAppInfo() {
+        PackageInfo currentPackage = mWebViewUpdateServiceWrapper.getCurrentWebViewPackage();
+        return new DefaultAppInfo(currentPackage == null ? null : currentPackage.applicationInfo);
     }
 
     @Override
@@ -69,23 +55,6 @@
         }
     }
 
-    /**
-     * Handle the return-value from the WebViewAppPicker Activity.
-     */
-    public void onActivityResult(int resultCode, Intent data) {
-        // Update the preference summary no matter whether we succeeded to change the webview
-        // implementation correctly - we might have changed implementation to one the user did not
-        // choose.
-        updateState(null);
-    }
-
-    private String getCurrentWebViewPackageLabel(Context context) {
-        PackageInfo webViewPackage = mWebViewUpdateServiceWrapper.getCurrentWebViewPackage();
-        if (webViewPackage == null) return "";
-        return webViewPackage.applicationInfo.loadLabel(context.getPackageManager()).toString();
-    }
-
-
     @Override
     public String getPreferenceKey() {
         return WEBVIEW_APP_KEY;
diff --git a/src/com/android/settings/webview/WebViewApplicationInfo.java b/src/com/android/settings/webview/WebViewApplicationInfo.java
deleted file mode 100644
index 6879c59..0000000
--- a/src/com/android/settings/webview/WebViewApplicationInfo.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.settings.webview;
-
-import android.content.pm.ApplicationInfo;
-
-final class WebViewApplicationInfo {
-    final ApplicationInfo info;
-    final String label;
-    final String disabledReason;
-
-    public WebViewApplicationInfo(ApplicationInfo info, String label, String disabledReason) {
-        this.info = info;
-        this.label = label;
-        this.disabledReason = disabledReason;
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/webview/WebViewAppListAdapterTest.java b/tests/robotests/src/com/android/settings/webview/WebViewAppListAdapterTest.java
deleted file mode 100644
index a8ab5d4..0000000
--- a/tests/robotests/src/com/android/settings/webview/WebViewAppListAdapterTest.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.webview;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.pm.UserInfo;
-
-import com.android.settings.R;
-import com.android.settings.SettingsRobolectricTestRunner;
-import com.android.settings.TestConfig;
-
-import java.util.Arrays;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class WebViewAppListAdapterTest {
-    private Context mContext = RuntimeEnvironment.application;
-
-    private final static UserInfo FIRST_USER = new UserInfo(0, "FIRST_USER", 0);
-    private final static UserInfo SECOND_USER = new UserInfo(0, "SECOND_USER", 0);
-
-    private final static String DEFAULT_PACKAGE_NAME = "DEFAULT_PACKAGE_NAME";
-
-    @Test
-    public void testDisabledReasonNullIfPackagesOk() {
-        UserPackageWrapper packageForFirstUser = mock(UserPackageWrapper.class);
-        when(packageForFirstUser.isEnabledPackage()).thenReturn(true);
-        when(packageForFirstUser.isInstalledPackage()).thenReturn(true);
-
-        UserPackageWrapper packageForSecondUser = mock(UserPackageWrapper.class);
-        when(packageForSecondUser.isEnabledPackage()).thenReturn(true);
-        when(packageForSecondUser.isInstalledPackage()).thenReturn(true);
-
-        WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
-        when(wvusWrapper.getPackageInfosAllUsers(
-                any(), eq(DEFAULT_PACKAGE_NAME))).thenReturn(
-                        Arrays.asList(packageForFirstUser, packageForSecondUser));
-
-        assertThat(WebViewAppListAdapter.getDisabledReason(
-                wvusWrapper, mContext, DEFAULT_PACKAGE_NAME)).isNull();
-    }
-
-    @Test
-    public void testDisabledReasonForSingleUserDisabledPackage() {
-        UserPackageWrapper packageForFirstUser = mock(UserPackageWrapper.class);
-        when(packageForFirstUser.isEnabledPackage()).thenReturn(false);
-        when(packageForFirstUser.isInstalledPackage()).thenReturn(true);
-        when(packageForFirstUser.getUserInfo()).thenReturn(FIRST_USER);
-
-        WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
-        when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)
-                )).thenReturn(Arrays.asList(packageForFirstUser));
-
-        assertThat(WebViewAppListAdapter.getDisabledReason(wvusWrapper, mContext,
-                DEFAULT_PACKAGE_NAME)).isEqualTo("Disabled for user " + FIRST_USER.name + "\n");
-    }
-
-    @Test
-    public void testDisabledReasonForSingleUserUninstalledPackage() {
-        UserPackageWrapper packageForFirstUser = mock(UserPackageWrapper.class);
-        when(packageForFirstUser.isEnabledPackage()).thenReturn(true);
-        when(packageForFirstUser.isInstalledPackage()).thenReturn(false);
-        when(packageForFirstUser.getUserInfo()).thenReturn(FIRST_USER);
-
-        WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
-        when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)
-                )).thenReturn(Arrays.asList(packageForFirstUser));
-
-        assertThat(WebViewAppListAdapter.getDisabledReason(wvusWrapper, mContext,
-                DEFAULT_PACKAGE_NAME)).isEqualTo("Uninstalled for user " + FIRST_USER.name + "\n");
-    }
-
-    @Test
-    public void testDisabledReasonSeveralUsers() {
-        UserPackageWrapper packageForFirstUser = mock(UserPackageWrapper.class);
-        when(packageForFirstUser.isEnabledPackage()).thenReturn(false);
-        when(packageForFirstUser.isInstalledPackage()).thenReturn(true);
-        when(packageForFirstUser.getUserInfo()).thenReturn(FIRST_USER);
-
-        UserPackageWrapper packageForSecondUser = mock(UserPackageWrapper.class);
-        when(packageForSecondUser.isEnabledPackage()).thenReturn(true);
-        when(packageForSecondUser.isInstalledPackage()).thenReturn(false);
-        when(packageForSecondUser.getUserInfo()).thenReturn(SECOND_USER);
-
-        WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
-        when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)
-                )).thenReturn(Arrays.asList(packageForFirstUser, packageForSecondUser));
-
-        final String EXPECTED_DISABLED_REASON = String.format(
-                "Disabled for user %s\nUninstalled for user %s\n",
-                FIRST_USER.name, SECOND_USER.name);
-        assertThat(WebViewAppListAdapter.getDisabledReason(
-                wvusWrapper, mContext,DEFAULT_PACKAGE_NAME)).isEqualTo(EXPECTED_DISABLED_REASON);
-    }
-
-    /**
-     * Ensure we only proclaim a package as uninstalled for a certain user if it's both uninstalled
-     * and disabled.
-     */
-    @Test
-    public void testDisabledReasonUninstalledAndDisabled() {
-        UserPackageWrapper packageForFirstUser = mock(UserPackageWrapper.class);
-        when(packageForFirstUser.isEnabledPackage()).thenReturn(false);
-        when(packageForFirstUser.isInstalledPackage()).thenReturn(false);
-        when(packageForFirstUser.getUserInfo()).thenReturn(FIRST_USER);
-
-        UserPackageWrapper packageForSecondUser = mock(UserPackageWrapper.class);
-        when(packageForSecondUser.isEnabledPackage()).thenReturn(true);
-        when(packageForSecondUser.isInstalledPackage()).thenReturn(true);
-        when(packageForSecondUser.getUserInfo()).thenReturn(SECOND_USER);
-
-        WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
-        when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)
-                )).thenReturn(Arrays.asList(packageForFirstUser, packageForSecondUser));
-
-        final String EXPECTED_DISABLED_REASON = String.format(
-                "Uninstalled for user %s\n", FIRST_USER.name);
-        assertThat(WebViewAppListAdapter.getDisabledReason(wvusWrapper, mContext,
-                DEFAULT_PACKAGE_NAME)).isEqualTo(EXPECTED_DISABLED_REASON);
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/webview/WebViewAppPickerTest.java b/tests/robotests/src/com/android/settings/webview/WebViewAppPickerTest.java
index 8ace8aa..78839fa 100644
--- a/tests/robotests/src/com/android/settings/webview/WebViewAppPickerTest.java
+++ b/tests/robotests/src/com/android/settings/webview/WebViewAppPickerTest.java
@@ -16,94 +16,252 @@
 
 package com.android.settings.webview;
 
+import static android.provider.Settings.ACTION_WEBVIEW_SETTINGS;
 import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assert.assertEquals;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
-import static org.robolectric.shadows.ShadowView.clickOn;
-import static org.robolectric.Shadows.shadowOf;
 
 import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
 import android.content.pm.ApplicationInfo;
-import android.view.View;
+import android.content.pm.UserInfo;
+import android.os.UserManager;
 
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
+import com.android.settings.widget.RadioButtonPreference;
+import com.android.settings.applications.PackageManagerWrapper;
 
 import java.util.Arrays;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
-import org.robolectric.util.ActivityController;
 
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class WebViewAppPickerTest {
+    private Context mContext = RuntimeEnvironment.application;
 
-  private static final String DEFAULT_PACKAGE_NAME = "DEFAULT_PACKAGE_NAME";
+    private final static UserInfo FIRST_USER = new UserInfo(0, "FIRST_USER", 0);
+    private final static UserInfo SECOND_USER = new UserInfo(0, "SECOND_USER", 0);
 
-  private static ApplicationInfo createApplicationInfo(String packageName) {
-      ApplicationInfo ai = new ApplicationInfo();
-      ai.packageName = packageName;
-      return ai;
-  }
+    private final static String DEFAULT_PACKAGE_NAME = "DEFAULT_PACKAGE_NAME";
 
-  @Test
-  public void testClickingItemChangesProvider() {
-      ActivityController<WebViewAppPicker> controller =
-              Robolectric.buildActivity(WebViewAppPicker.class);
-      WebViewAppPicker webviewAppPicker = controller.get();
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Activity mActivity;
+    @Mock
+    private UserManager mUserManager;
+    @Mock
+    private PackageManagerWrapper mPackageManager;
 
-      WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
-      when(wvusWrapper.getValidWebViewApplicationInfos(any())).thenReturn(
-              Arrays.asList(createApplicationInfo(DEFAULT_PACKAGE_NAME)));
-      when(wvusWrapper.setWebViewProvider(eq(DEFAULT_PACKAGE_NAME))).thenReturn(true);
+    private WebViewAppPicker mPicker;
+    private WebViewUpdateServiceWrapper mWvusWrapper;
 
-      webviewAppPicker.setWebViewUpdateServiceWrapper(wvusWrapper);
+    private static ApplicationInfo createApplicationInfo(String packageName) {
+        ApplicationInfo ai = new ApplicationInfo();
+        ai.packageName = packageName;
+        return ai;
+    }
 
-      controller.create().start().postCreate(null).resume().visible();
-      WebViewApplicationInfo firstItem =
-              (WebViewApplicationInfo) webviewAppPicker.getListView().getItemAtPosition(0);
-      assertThat(firstItem.info.packageName).isEqualTo(DEFAULT_PACKAGE_NAME);
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
 
-      webviewAppPicker.onListItemClick(webviewAppPicker.getListView(), null, 0, 0);
+        mPicker = new WebViewAppPicker();
+        mPicker = spy(mPicker);
+        doNothing().when(mPicker).updateCandidates();
+        doNothing().when(mPicker).updateCheckedState(any());
+        doReturn(mActivity).when(mPicker).getActivity();
 
-      verify(wvusWrapper, times(1)).setWebViewProvider(eq(DEFAULT_PACKAGE_NAME));
-      assertThat(shadowOf(webviewAppPicker).getResultCode()).isEqualTo(Activity.RESULT_OK);
-      verify(wvusWrapper, never()).showInvalidChoiceToast(any());
-  }
+        mWvusWrapper = mock(WebViewUpdateServiceWrapper.class);
+        mPicker.setWebViewUpdateServiceWrapper(mWvusWrapper);
+    }
 
-  @Test
-  public void testFailingPackageChangeReturnsCancelled() {
-      ActivityController<WebViewAppPicker> controller =
-              Robolectric.buildActivity(WebViewAppPicker.class);
-      WebViewAppPicker webviewAppPicker = controller.get();
+    @Test
+    public void testClickingItemChangesProvider() {
+        testSuccessfulClickChangesProvider();
+    }
 
-      WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
-      when(wvusWrapper.getValidWebViewApplicationInfos(any())).thenReturn(
-              Arrays.asList(createApplicationInfo(DEFAULT_PACKAGE_NAME)));
-      when(wvusWrapper.setWebViewProvider(eq(DEFAULT_PACKAGE_NAME))).thenReturn(false);
+    @Test
+    public void testFailingClick() {
+        testFailingClickUpdatesSetting();
+    }
 
-      webviewAppPicker.setWebViewUpdateServiceWrapper(wvusWrapper);
+    @Test
+    public void testClickingItemInActivityModeChangesProviderAndFinishes() {
+        useWebViewSettingIntent();
+        testSuccessfulClickChangesProvider();
+        verify(mActivity, times(1)).finish();
+    }
 
-      controller.create().start().postCreate(null).resume().visible();
-      WebViewApplicationInfo firstItem =
-              (WebViewApplicationInfo) webviewAppPicker.getListView().getItemAtPosition(0);
-      assertThat(firstItem.info.packageName).isEqualTo(DEFAULT_PACKAGE_NAME);
+    @Test
+    public void testFailingClickInActivityMode() {
+        useWebViewSettingIntent();
+        testFailingClick();
+    }
 
-      webviewAppPicker.onListItemClick(webviewAppPicker.getListView(), null, 0, 0);
+    private void useWebViewSettingIntent() {
+        Intent intent = new Intent(ACTION_WEBVIEW_SETTINGS);
+        when(mActivity.getIntent()).thenReturn(intent);
+    }
 
-      verify(wvusWrapper, times(1)).setWebViewProvider(eq(DEFAULT_PACKAGE_NAME));
-      assertThat(shadowOf(webviewAppPicker).getResultCode()).isEqualTo(Activity.RESULT_CANCELED);
-      verify(wvusWrapper, times(1)).showInvalidChoiceToast(any());
-  }
+    private void testSuccessfulClickChangesProvider() {
+        when(mWvusWrapper.getValidWebViewApplicationInfos(any())).thenReturn(
+                Arrays.asList(createApplicationInfo(DEFAULT_PACKAGE_NAME)));
+        when(mWvusWrapper.setWebViewProvider(eq(DEFAULT_PACKAGE_NAME))).thenReturn(true);
+
+        RadioButtonPreference defaultPackagePref = mock(RadioButtonPreference.class);
+        when(defaultPackagePref.getKey()).thenReturn(DEFAULT_PACKAGE_NAME);
+        mPicker.onRadioButtonClicked(defaultPackagePref);
+
+        verify(mWvusWrapper, times(1)).setWebViewProvider(eq(DEFAULT_PACKAGE_NAME));
+        verify(mPicker, times(1)).updateCheckedState(DEFAULT_PACKAGE_NAME);
+        verify(mWvusWrapper, never()).showInvalidChoiceToast(any());
+    }
+
+    private void testFailingClickUpdatesSetting() {
+        when(mWvusWrapper.getValidWebViewApplicationInfos(any())).thenReturn(
+                Arrays.asList(createApplicationInfo(DEFAULT_PACKAGE_NAME)));
+        when(mWvusWrapper.setWebViewProvider(eq(DEFAULT_PACKAGE_NAME))).thenReturn(false);
+
+        RadioButtonPreference defaultPackagePref = mock(RadioButtonPreference.class);
+        when(defaultPackagePref.getKey()).thenReturn(DEFAULT_PACKAGE_NAME);
+        mPicker.onRadioButtonClicked(defaultPackagePref);
+
+        verify(mWvusWrapper, times(1)).setWebViewProvider(eq(DEFAULT_PACKAGE_NAME));
+        // Ensure we update the list of packages when we click a non-valid package - the list must
+        // have changed, otherwise this click wouldn't fail.
+        verify(mPicker, times(1)).updateCandidates();
+        verify(mWvusWrapper, times(1)).showInvalidChoiceToast(any());
+    }
+
+    @Test
+    public void testFinishIfNotAdmin() {
+        doReturn(false).when(mUserManager).isAdminUser();
+        mPicker.onAttach((Context) mActivity);
+        verify(mActivity, times(1)).finish();
+    }
+
+    @Test
+    public void testNotFinishedIfAdmin() {
+        doReturn(true).when(mUserManager).isAdminUser();
+        mPicker.onAttach((Context) mActivity);
+        verify(mActivity, never()).finish();
+    }
+
+    @Test
+    public void testDisabledReasonNullIfPackagesOk() {
+        UserPackageWrapper packageForFirstUser = mock(UserPackageWrapper.class);
+        when(packageForFirstUser.isEnabledPackage()).thenReturn(true);
+        when(packageForFirstUser.isInstalledPackage()).thenReturn(true);
+
+        UserPackageWrapper packageForSecondUser = mock(UserPackageWrapper.class);
+        when(packageForSecondUser.isEnabledPackage()).thenReturn(true);
+        when(packageForSecondUser.isInstalledPackage()).thenReturn(true);
+
+        WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
+        when(wvusWrapper.getPackageInfosAllUsers(
+                any(), eq(DEFAULT_PACKAGE_NAME))).thenReturn(
+                        Arrays.asList(packageForFirstUser, packageForSecondUser));
+
+        assertThat(mPicker.getDisabledReason(wvusWrapper, mContext, DEFAULT_PACKAGE_NAME)).isNull();
+    }
+
+    @Test
+    public void testDisabledReasonForSingleUserDisabledPackage() {
+        UserPackageWrapper packageForFirstUser = mock(UserPackageWrapper.class);
+        when(packageForFirstUser.isEnabledPackage()).thenReturn(false);
+        when(packageForFirstUser.isInstalledPackage()).thenReturn(true);
+        when(packageForFirstUser.getUserInfo()).thenReturn(FIRST_USER);
+
+        WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
+        when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)
+                )).thenReturn(Arrays.asList(packageForFirstUser));
+
+        final String EXPECTED_DISABLED_REASON = String.format(
+                "(disabled for user %s)", FIRST_USER.name);
+        assertThat(mPicker.getDisabledReason(wvusWrapper, mContext,
+                DEFAULT_PACKAGE_NAME)).isEqualTo(EXPECTED_DISABLED_REASON);
+    }
+
+    @Test
+    public void testDisabledReasonForSingleUserUninstalledPackage() {
+        UserPackageWrapper packageForFirstUser = mock(UserPackageWrapper.class);
+        when(packageForFirstUser.isEnabledPackage()).thenReturn(true);
+        when(packageForFirstUser.isInstalledPackage()).thenReturn(false);
+        when(packageForFirstUser.getUserInfo()).thenReturn(FIRST_USER);
+
+        WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
+        when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)
+                )).thenReturn(Arrays.asList(packageForFirstUser));
+
+        final String EXPECTED_DISABLED_REASON = String.format(
+                "(uninstalled for user %s)", FIRST_USER.name);
+        assertThat(mPicker.getDisabledReason(wvusWrapper, mContext,
+                DEFAULT_PACKAGE_NAME)).isEqualTo(EXPECTED_DISABLED_REASON);
+    }
+
+    @Test
+    public void testDisabledReasonSeveralUsers() {
+        UserPackageWrapper packageForFirstUser = mock(UserPackageWrapper.class);
+        when(packageForFirstUser.isEnabledPackage()).thenReturn(false);
+        when(packageForFirstUser.isInstalledPackage()).thenReturn(true);
+        when(packageForFirstUser.getUserInfo()).thenReturn(FIRST_USER);
+
+        UserPackageWrapper packageForSecondUser = mock(UserPackageWrapper.class);
+        when(packageForSecondUser.isEnabledPackage()).thenReturn(true);
+        when(packageForSecondUser.isInstalledPackage()).thenReturn(false);
+        when(packageForSecondUser.getUserInfo()).thenReturn(SECOND_USER);
+
+        WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
+        when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)
+                )).thenReturn(Arrays.asList(packageForFirstUser, packageForSecondUser));
+
+        final String EXPECTED_DISABLED_REASON = String.format(
+                "(disabled for user %s)", FIRST_USER.name);
+        assertThat(mPicker.getDisabledReason(
+                wvusWrapper, mContext,DEFAULT_PACKAGE_NAME)).isEqualTo(EXPECTED_DISABLED_REASON);
+    }
+
+    /**
+     * Ensure we only proclaim a package as uninstalled for a certain user if it's both uninstalled
+     * and disabled.
+     */
+    @Test
+    public void testDisabledReasonUninstalledAndDisabled() {
+        UserPackageWrapper packageForFirstUser = mock(UserPackageWrapper.class);
+        when(packageForFirstUser.isEnabledPackage()).thenReturn(false);
+        when(packageForFirstUser.isInstalledPackage()).thenReturn(false);
+        when(packageForFirstUser.getUserInfo()).thenReturn(FIRST_USER);
+
+        UserPackageWrapper packageForSecondUser = mock(UserPackageWrapper.class);
+        when(packageForSecondUser.isEnabledPackage()).thenReturn(true);
+        when(packageForSecondUser.isInstalledPackage()).thenReturn(true);
+        when(packageForSecondUser.getUserInfo()).thenReturn(SECOND_USER);
+
+        WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
+        when(wvusWrapper.getPackageInfosAllUsers(any(), eq(DEFAULT_PACKAGE_NAME)
+                )).thenReturn(Arrays.asList(packageForFirstUser, packageForSecondUser));
+
+        final String EXPECTED_DISABLED_REASON = String.format(
+                "(uninstalled for user %s)", FIRST_USER.name);
+        assertThat(mPicker.getDisabledReason(wvusWrapper, mContext,
+                DEFAULT_PACKAGE_NAME)).isEqualTo(EXPECTED_DISABLED_REASON);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/webview/WebViewAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/webview/WebViewAppPreferenceControllerTest.java
index e0a32a4..d32f486 100644
--- a/tests/robotests/src/com/android/settings/webview/WebViewAppPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/webview/WebViewAppPreferenceControllerTest.java
@@ -14,21 +14,11 @@
 
 package com.android.settings.webview;
 
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.eq;
+import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
-import android.app.Activity;
 import android.content.Context;
-import android.content.Intent;
 import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
 
 import com.android.settings.SettingsRobolectricTestRunner;
 import com.android.settings.TestConfig;
@@ -36,8 +26,6 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-import org.mockito.Answers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
@@ -45,39 +33,26 @@
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class WebViewAppPreferenceControllerTest {
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    @Mock
     private Context mContext;
 
-    @Mock
-    private PreferenceScreen mPreferenceScreen;
-    @Mock
-    private Preference mPreference;
+    private WebViewAppPreferenceController mController;
 
     private static final String DEFAULT_PACKAGE_NAME = "DEFAULT_PACKAGE_NAME";
 
-    @Before public void setUp() {
+    @Before
+    public void setUp() {
         MockitoAnnotations.initMocks(this);
-        when(mPreferenceScreen.findPreference(any())).thenReturn(mPreference);
+        mController = new WebViewAppPreferenceController(mContext);
     }
 
-    @Test public void testOnActivityResultUpdatesStateOnSuccess() {
-        WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
-        WebViewAppPreferenceController controller =
-                spy(new WebViewAppPreferenceController(mContext, wvusWrapper));
-
-        controller.displayPreference(mPreferenceScreen); // Makes sure Preference is non-null
-        controller.onActivityResult(Activity.RESULT_OK, new Intent(DEFAULT_PACKAGE_NAME));
-        verify(controller, times(1)).updateState(any());
+    @Test
+    public void testIsAlwaysAvailable() {
+        assertThat(mController.isAvailable()).isTrue();
     }
 
-    @Test public void testOnActivityResultWithFailure() {
-        WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class);
-
-        WebViewAppPreferenceController controller =
-                spy(new WebViewAppPreferenceController(mContext, wvusWrapper));
-
-        controller.displayPreference(mPreferenceScreen); // Makes sure Preference is non-null
-        controller.onActivityResult(Activity.RESULT_CANCELED, new Intent(DEFAULT_PACKAGE_NAME));
-        verify(controller, times(1)).updateState(any());
+    @Test
+    public void testNeverHandlesClick() {
+        assertThat(mController.handlePreferenceTreeClick(mock(Preference.class))).isFalse();
     }
 }