Merge "Have WebView Implementation Dev Setting use DefaultAppPickerFragment."

This commit is contained in:
Gustav Sennton
2017-02-09 17:36:32 +00:00
committed by Android (Google) Code Review
15 changed files with 365 additions and 512 deletions

View File

@@ -1980,8 +1980,9 @@
<activity android:name=".AppPicker" android:label="@string/select_application" <activity android:name=".AppPicker" android:label="@string/select_application"
android:theme="@android:style/Theme.DeviceDefault.Light.Dialog" /> android:theme="@android:style/Theme.DeviceDefault.Light.Dialog" />
<activity android:name=".webview.WebViewAppPicker" android:label="@string/select_webview_provider_dialog_title" <activity android:name="Settings$WebViewAppPickerActivity"
android:theme="@android:style/Theme.DeviceDefault.Light.Dialog" /> android:label="@string/select_webview_provider_dialog_title">
</activity>
<!-- Keep compatibility with old shortcuts. --> <!-- Keep compatibility with old shortcuts. -->
<activity-alias android:name="UsbSettings" <activity-alias android:name="UsbSettings"
@@ -2945,7 +2946,7 @@
<!-- Keep compatibility with old WebView-picker implementation --> <!-- Keep compatibility with old WebView-picker implementation -->
<activity-alias android:name=".WebViewImplementation" <activity-alias android:name=".WebViewImplementation"
android:targetActivity=".webview.WebViewAppPicker" android:targetActivity="Settings$WebViewAppPickerActivity"
android:exported="true" android:exported="true"
android:excludeFromRecents="true" android:excludeFromRecents="true"
android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"> android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert">
@@ -2955,6 +2956,8 @@
</intent-filter> </intent-filter>
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED" <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" /> android:value="true" />
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.webview.WebViewAppPicker" />
</activity-alias> </activity-alias>
<!-- activity for gesture settings --> <!-- activity for gesture settings -->

View File

@@ -8180,9 +8180,9 @@
<string name="audio_storage_title">Music</string> <string name="audio_storage_title">Music</string>
<!-- UI webview setting: WebView uninstalled-for-user explanatory text [CHAR LIMIT=30] --> <!-- 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] --> <!-- 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 --> <!-- AutoFill strings -->
<!-- Preference label for the auto-fill app. [CHAR LIMIT=60] --> <!-- Preference label for the auto-fill app. [CHAR LIMIT=60] -->

View File

@@ -76,7 +76,8 @@
<Preference android:key="select_webview_provider" <Preference android:key="select_webview_provider"
android:title="@string/select_webview_provider_title" 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 <SwitchPreference
android:key="enable_webview_multiprocess" android:key="enable_webview_multiprocess"

View File

@@ -233,7 +233,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
private static final int RESULT_DEBUG_APP = 1000; private static final int RESULT_DEBUG_APP = 1000;
private static final int RESULT_MOCK_LOCATION_APP = 1001; 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 PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
private static final String FLASH_LOCKED_PROP = "ro.boot.flash.locked"; private static final String FLASH_LOCKED_PROP = "ro.boot.flash.locked";
@@ -801,7 +800,8 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
updateSimulateColorSpace(); updateSimulateColorSpace();
updateUSBAudioOptions(); updateUSBAudioOptions();
updateForceResizableOptions(); updateForceResizableOptions();
mWebViewAppPrefController.updateState(null); Preference webViewAppPref = findPreference(mWebViewAppPrefController.getPreferenceKey());
mWebViewAppPrefController.updateState(webViewAppPref);
updateWebViewMultiprocessOptions(); updateWebViewMultiprocessOptions();
updateOemUnlockOptions(); updateOemUnlockOptions();
if (mColorTemperaturePreference != null) { if (mColorTemperaturePreference != null) {
@@ -2330,8 +2330,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
writeMockLocation(); writeMockLocation();
updateMockLocation(); updateMockLocation();
} }
} else if (requestCode == RESULT_WEBVIEW_APP) {
mWebViewAppPrefController.onActivityResult(resultCode, data);
} else if (requestCode == REQUEST_CODE_ENABLE_OEM_UNLOCK) { } else if (requestCode == REQUEST_CODE_ENABLE_OEM_UNLOCK) {
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
if (mEnableOemUnlock.isChecked()) { if (mEnableOemUnlock.isChecked()) {
@@ -2355,8 +2353,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
return true; return true;
} }
if (mWebViewAppPrefController.handlePreferenceTreeClick(preference)) { if (mWebViewAppPrefController.handlePreferenceTreeClick(preference)) {
startActivityForResult( return true;
mWebViewAppPrefController.getActivityIntent(), RESULT_WEBVIEW_APP);
} }
if (preference == mEnableAdb) { if (preference == mEnableAdb) {

View File

@@ -163,6 +163,7 @@ public class Settings extends SettingsActivity {
public static class WifiAPITestActivity extends SettingsActivity { /* empty */ } public static class WifiAPITestActivity extends SettingsActivity { /* empty */ }
public static class WifiInfoActivity extends SettingsActivity { /* empty */ } public static class WifiInfoActivity extends SettingsActivity { /* empty */ }
public static class EnterprisePrivacySettingsActivity extends SettingsActivity { /* empty */ } public static class EnterprisePrivacySettingsActivity extends SettingsActivity { /* empty */ }
public static class WebViewAppPickerActivity extends SettingsActivity { /* empty */ }
// Categories. // Categories.
public static class WirelessSettings extends SettingsActivity { /* empty */ } public static class WirelessSettings extends SettingsActivity { /* empty */ }

View File

@@ -29,25 +29,33 @@ import android.os.UserHandle;
/** /**
* Data model representing an app in DefaultAppPicker UI. * Data model representing an app in DefaultAppPicker UI.
*/ */
class DefaultAppInfo { public class DefaultAppInfo {
public final int userId; public final int userId;
public final ComponentName componentName; public final ComponentName componentName;
public final PackageItemInfo packageItemInfo; public final PackageItemInfo packageItemInfo;
public final String summary; 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) { public DefaultAppInfo(int uid, ComponentName cn, String summary) {
packageItemInfo = null; packageItemInfo = null;
userId = uid; userId = uid;
componentName = cn; componentName = cn;
this.summary = summary; this.summary = summary;
this.disabledDescription = null;
} }
public DefaultAppInfo(PackageItemInfo info) { public DefaultAppInfo(PackageItemInfo info, String description) {
userId = UserHandle.myUserId(); userId = UserHandle.myUserId();
packageItemInfo = info; packageItemInfo = info;
componentName = null; componentName = null;
summary = null; summary = null;
this.disabledDescription = description;
}
public DefaultAppInfo(PackageItemInfo info) {
this(info, null);
} }
public CharSequence loadLabel(PackageManager pm) { public CharSequence loadLabel(PackageManager pm) {

View File

@@ -91,6 +91,11 @@ public abstract class DefaultAppPickerFragment extends InstrumentedPreferenceFra
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
super.onCreatePreferences(savedInstanceState, rootKey); super.onCreatePreferences(savedInstanceState, rootKey);
addPreferencesFromResource(R.xml.app_picker_prefs); addPreferencesFromResource(R.xml.app_picker_prefs);
updateCandidates();
}
@VisibleForTesting
public void updateCandidates() {
mCandidates.clear(); mCandidates.clear();
final List<DefaultAppInfo> candidateList = getCandidates(); final List<DefaultAppInfo> candidateList = getCandidates();
if (candidateList != null) { if (candidateList != null) {
@@ -123,6 +128,10 @@ public abstract class DefaultAppPickerFragment extends InstrumentedPreferenceFra
if (TextUtils.equals(systemDefaultAppKey, appKey)) { if (TextUtils.equals(systemDefaultAppKey, appKey)) {
pref.setSummary(R.string.system_app); pref.setSummary(R.string.system_app);
} }
if (!TextUtils.isEmpty(app.getValue().disabledDescription)) {
pref.setEnabled(false);
pref.setSummary(app.getValue().disabledDescription);
}
pref.setOnClickListener(this); pref.setOnClickListener(this);
screen.addPreference(pref); screen.addPreference(pref);
} }
@@ -146,18 +155,23 @@ public abstract class DefaultAppPickerFragment extends InstrumentedPreferenceFra
private void onRadioButtonConfirmed(String selectedKey) { private void onRadioButtonConfirmed(String selectedKey) {
final boolean success = setDefaultAppKey(selectedKey); final boolean success = setDefaultAppKey(selectedKey);
if (success) { if (success) {
final PreferenceScreen screen = getPreferenceScreen(); updateCheckedState(selectedKey);
if (screen != null) { }
final int count = screen.getPreferenceCount(); onSelectionPerformed(success);
for (int i = 0; i < count; i++) { }
final Preference pref = screen.getPreference(i);
if (pref instanceof RadioButtonPreference) { @VisibleForTesting
final RadioButtonPreference radioPref = (RadioButtonPreference) pref; public void updateCheckedState(String selectedKey) {
final boolean newCheckedState = final PreferenceScreen screen = getPreferenceScreen();
TextUtils.equals(pref.getKey(), selectedKey); if (screen != null) {
if (radioPref.isChecked() != newCheckedState) { final int count = screen.getPreferenceCount();
radioPref.setChecked(TextUtils.equals(pref.getKey(), selectedKey)); 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));
} }
} }
} }
@@ -190,6 +204,9 @@ public abstract class DefaultAppPickerFragment extends InstrumentedPreferenceFra
protected abstract boolean setDefaultAppKey(String key); 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) { protected String getConfirmationMessage(DefaultAppInfo appInfo) {
return null; return null;
} }

View File

@@ -120,6 +120,7 @@ import com.android.settings.system.SystemDashboardFragment;
import com.android.settings.tts.TextToSpeechSettings; import com.android.settings.tts.TextToSpeechSettings;
import com.android.settings.users.UserSettings; import com.android.settings.users.UserSettings;
import com.android.settings.vpn2.VpnSettings; import com.android.settings.vpn2.VpnSettings;
import com.android.settings.webview.WebViewAppPicker;
import com.android.settings.wfd.WifiDisplaySettings; import com.android.settings.wfd.WifiDisplaySettings;
import com.android.settings.wifi.ConfigureWifiSettings; import com.android.settings.wifi.ConfigureWifiSettings;
import com.android.settings.wifi.SavedAccessPointsWifiSettings; import com.android.settings.wifi.SavedAccessPointsWifiSettings;
@@ -246,6 +247,7 @@ public class SettingsGateway {
AppAndNotificationDashboardFragment.class.getName(), AppAndNotificationDashboardFragment.class.getName(),
UserAndAccountDashboardFragment.class.getName(), UserAndAccountDashboardFragment.class.getName(),
EnterprisePrivacySettings.class.getName(), EnterprisePrivacySettings.class.getName(),
WebViewAppPicker.class.getName(),
}; };
public static final String[] SETTINGS_FOR_RESTRICTED = { public static final String[] SETTINGS_FOR_RESTRICTED = {

View File

@@ -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();
}
}

View File

@@ -16,57 +16,83 @@
package com.android.settings.webview; 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.pm.PackageInfo;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.RemoteException;
import android.support.annotation.VisibleForTesting; 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.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.instrumentation.Instrumentable; import com.android.settings.R;
import com.android.settings.core.instrumentation.VisibilityLoggerMixin; import com.android.settings.applications.defaultapps.DefaultAppInfo;
import com.android.settings.applications.defaultapps.DefaultAppPickerFragment;
public class WebViewAppPicker extends ListActivity implements Instrumentable { import java.util.ArrayList;
private static final String TAG = WebViewAppPicker.class.getSimpleName(); import java.util.List;
private WebViewAppListAdapter mAdapter;
public class WebViewAppPicker extends DefaultAppPickerFragment {
private WebViewUpdateServiceWrapper mWebViewUpdateServiceWrapper; private WebViewUpdateServiceWrapper mWebViewUpdateServiceWrapper;
private final VisibilityLoggerMixin mVisibilityLoggerMixin = private WebViewUpdateServiceWrapper getWebViewUpdateServiceWrapper() {
new VisibilityLoggerMixin(getMetricsCategory());
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (mWebViewUpdateServiceWrapper == null) { if (mWebViewUpdateServiceWrapper == null) {
setWebViewUpdateServiceWrapper(createDefaultWebViewUpdateServiceWrapper()); setWebViewUpdateServiceWrapper(createDefaultWebViewUpdateServiceWrapper());
} }
mAdapter = new WebViewAppListAdapter(this, mWebViewUpdateServiceWrapper); return mWebViewUpdateServiceWrapper;
setListAdapter(mAdapter);
mVisibilityLoggerMixin.onAttach(this);
} }
@Override @Override
protected void onListItemClick(ListView l, View v, int position, long id) { public void onAttach(Context context) {
WebViewApplicationInfo app = mAdapter.getItem(position); super.onAttach(context);
if (mWebViewUpdateServiceWrapper.setWebViewProvider(app.info.packageName)) { if (!mUserManager.isAdminUser()) {
Intent intent = new Intent(); getActivity().finish();
intent.setAction(app.info.packageName);
setResult(RESULT_OK, intent);
} else {
mWebViewUpdateServiceWrapper.showInvalidChoiceToast(this);
} }
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() { private WebViewUpdateServiceWrapper createDefaultWebViewUpdateServiceWrapper() {
return new WebViewUpdateServiceWrapper(); return new WebViewUpdateServiceWrapper();
} }
@@ -76,20 +102,32 @@ public class WebViewAppPicker extends ListActivity implements Instrumentable {
mWebViewUpdateServiceWrapper = wvusWrapper; mWebViewUpdateServiceWrapper = wvusWrapper;
} }
@Override
public void onResume() {
super.onResume();
mVisibilityLoggerMixin.onResume();
}
@Override
public void onPause() {
super.onPause();
mVisibilityLoggerMixin.onPause();
}
@Override @Override
public int getMetricsCategory() { public int getMetricsCategory() {
return MetricsEvent.WEBVIEW_IMPLEMENTATION; 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;
}
} }

View File

@@ -14,18 +14,15 @@
package com.android.settings.webview; package com.android.settings.webview;
import android.app.Activity;
import android.content.pm.PackageInfo;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.pm.PackageInfo;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen; import android.support.v7.preference.PreferenceScreen;
import com.android.settings.DevelopmentSettings; import com.android.settings.applications.defaultapps.DefaultAppInfo;
import com.android.settings.core.PreferenceController; 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"; private static final String WEBVIEW_APP_KEY = "select_webview_provider";
@@ -45,20 +42,9 @@ public class WebViewAppPreferenceController extends PreferenceController {
} }
@Override @Override
public boolean handlePreferenceTreeClick(Preference preference) { public DefaultAppInfo getDefaultAppInfo() {
if (getPreferenceKey().equals(preference.getKey())) { PackageInfo currentPackage = mWebViewUpdateServiceWrapper.getCurrentWebViewPackage();
return true; return new DefaultAppInfo(currentPackage == null ? null : currentPackage.applicationInfo);
}
return false;
}
public Intent getActivityIntent() {
return new Intent(mContext, WebViewAppPicker.class);
}
@Override
public void updateState(Preference preference) {
mPreference.setSummary(getCurrentWebViewPackageLabel(mContext));
} }
@Override @Override
@@ -69,23 +55,6 @@ public class WebViewAppPreferenceController extends PreferenceController {
} }
} }
/**
* 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 @Override
public String getPreferenceKey() { public String getPreferenceKey() {
return WEBVIEW_APP_KEY; return WEBVIEW_APP_KEY;

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -16,94 +16,252 @@
package com.android.settings.webview; package com.android.settings.webview;
import static android.provider.Settings.ACTION_WEBVIEW_SETTINGS;
import static com.google.common.truth.Truth.assertThat; 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.any;
import static org.mockito.Matchers.eq; 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.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; 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.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo; 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.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig; import com.android.settings.TestConfig;
import com.android.settings.widget.RadioButtonPreference;
import com.android.settings.applications.PackageManagerWrapper;
import java.util.Arrays; import java.util.Arrays;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; 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.annotation.Config;
import org.robolectric.util.ActivityController;
@RunWith(SettingsRobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class WebViewAppPickerTest { 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) { private final static String DEFAULT_PACKAGE_NAME = "DEFAULT_PACKAGE_NAME";
ApplicationInfo ai = new ApplicationInfo();
ai.packageName = packageName;
return ai;
}
@Test @Mock(answer = Answers.RETURNS_DEEP_STUBS)
public void testClickingItemChangesProvider() { private Activity mActivity;
ActivityController<WebViewAppPicker> controller = @Mock
Robolectric.buildActivity(WebViewAppPicker.class); private UserManager mUserManager;
WebViewAppPicker webviewAppPicker = controller.get(); @Mock
private PackageManagerWrapper mPackageManager;
WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class); private WebViewAppPicker mPicker;
when(wvusWrapper.getValidWebViewApplicationInfos(any())).thenReturn( private WebViewUpdateServiceWrapper mWvusWrapper;
Arrays.asList(createApplicationInfo(DEFAULT_PACKAGE_NAME)));
when(wvusWrapper.setWebViewProvider(eq(DEFAULT_PACKAGE_NAME))).thenReturn(true);
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(); @Before
WebViewApplicationInfo firstItem = public void setUp() {
(WebViewApplicationInfo) webviewAppPicker.getListView().getItemAtPosition(0); MockitoAnnotations.initMocks(this);
assertThat(firstItem.info.packageName).isEqualTo(DEFAULT_PACKAGE_NAME); 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)); mWvusWrapper = mock(WebViewUpdateServiceWrapper.class);
assertThat(shadowOf(webviewAppPicker).getResultCode()).isEqualTo(Activity.RESULT_OK); mPicker.setWebViewUpdateServiceWrapper(mWvusWrapper);
verify(wvusWrapper, never()).showInvalidChoiceToast(any()); }
}
@Test @Test
public void testFailingPackageChangeReturnsCancelled() { public void testClickingItemChangesProvider() {
ActivityController<WebViewAppPicker> controller = testSuccessfulClickChangesProvider();
Robolectric.buildActivity(WebViewAppPicker.class); }
WebViewAppPicker webviewAppPicker = controller.get();
WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class); @Test
when(wvusWrapper.getValidWebViewApplicationInfos(any())).thenReturn( public void testFailingClick() {
Arrays.asList(createApplicationInfo(DEFAULT_PACKAGE_NAME))); testFailingClickUpdatesSetting();
when(wvusWrapper.setWebViewProvider(eq(DEFAULT_PACKAGE_NAME))).thenReturn(false); }
webviewAppPicker.setWebViewUpdateServiceWrapper(wvusWrapper); @Test
public void testClickingItemInActivityModeChangesProviderAndFinishes() {
useWebViewSettingIntent();
testSuccessfulClickChangesProvider();
verify(mActivity, times(1)).finish();
}
controller.create().start().postCreate(null).resume().visible(); @Test
WebViewApplicationInfo firstItem = public void testFailingClickInActivityMode() {
(WebViewApplicationInfo) webviewAppPicker.getListView().getItemAtPosition(0); useWebViewSettingIntent();
assertThat(firstItem.info.packageName).isEqualTo(DEFAULT_PACKAGE_NAME); 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)); private void testSuccessfulClickChangesProvider() {
assertThat(shadowOf(webviewAppPicker).getResultCode()).isEqualTo(Activity.RESULT_CANCELED); when(mWvusWrapper.getValidWebViewApplicationInfos(any())).thenReturn(
verify(wvusWrapper, times(1)).showInvalidChoiceToast(any()); 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);
}
} }

View File

@@ -14,21 +14,11 @@
package com.android.settings.webview; package com.android.settings.webview;
import static org.mockito.Matchers.any; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock; 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.Context;
import android.content.Intent;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig; import com.android.settings.TestConfig;
@@ -36,8 +26,6 @@ import com.android.settings.TestConfig;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Answers;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
@@ -45,39 +33,26 @@ import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class WebViewAppPreferenceControllerTest { public class WebViewAppPreferenceControllerTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS) @Mock
private Context mContext; private Context mContext;
@Mock private WebViewAppPreferenceController mController;
private PreferenceScreen mPreferenceScreen;
@Mock
private Preference mPreference;
private static final String DEFAULT_PACKAGE_NAME = "DEFAULT_PACKAGE_NAME"; private static final String DEFAULT_PACKAGE_NAME = "DEFAULT_PACKAGE_NAME";
@Before public void setUp() { @Before
public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
when(mPreferenceScreen.findPreference(any())).thenReturn(mPreference); mController = new WebViewAppPreferenceController(mContext);
} }
@Test public void testOnActivityResultUpdatesStateOnSuccess() { @Test
WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class); public void testIsAlwaysAvailable() {
WebViewAppPreferenceController controller = assertThat(mController.isAvailable()).isTrue();
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 testOnActivityResultWithFailure() { @Test
WebViewUpdateServiceWrapper wvusWrapper = mock(WebViewUpdateServiceWrapper.class); public void testNeverHandlesClick() {
assertThat(mController.handlePreferenceTreeClick(mock(Preference.class))).isFalse();
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());
} }
} }