Update WebView implementation Dev Setting - new looks + descriptions.
Now that we are changing the WebView package mechanism so that a package can only be used as WebView implementation if that package is enabled for all users of the device we need to tell the user why a package can't be chosen as WebView implementation. With this CL we do so in the 'Set WebView Implementation' Developer Setting. We code for the WebView implementation Developer Setting is now based on the same code as that of the Debug App Developer Setting. Bug: 32894154 Test: Ensure WebView Implementation setting shows correct packages. Test: Ensure WebView Implementation setting shows correct descriptions for why a package is not usable - including the case where packages are disabled/uninstalled for a second user. Test: Ensure the summary for the WebView Implmentation setting is updated after changing WebView package. Test: Ensure the WebView package Activity (Settings.ACTION_WEBVIEW_SETTINGS) is similar to the Dev Setting. Test: ensure non-admin user cannot start WV-picker activity through 'adb shell am start -n com.android.settings/.WebViewImplementation' Change-Id: Ia6e6e9e12ce8f8f45ec539807cd0c6479acb8ecb
This commit is contained in:
@@ -2005,6 +2005,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"
|
||||||
|
android:theme="@android:style/Theme.DeviceDefault.Light.Dialog" />
|
||||||
|
|
||||||
<!-- Keep compatibility with old shortcuts. -->
|
<!-- Keep compatibility with old shortcuts. -->
|
||||||
<activity-alias android:name="UsbSettings"
|
<activity-alias android:name="UsbSettings"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
@@ -2940,7 +2943,9 @@
|
|||||||
android:value="true" />
|
android:value="true" />
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name=".WebViewImplementation"
|
<!-- Keep compatibility with old WebView-picker implementation -->
|
||||||
|
<activity-alias android:name=".WebViewImplementation"
|
||||||
|
android:targetActivity=".webview.WebViewAppPicker"
|
||||||
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">
|
||||||
@@ -2950,7 +2955,7 @@
|
|||||||
</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" />
|
||||||
</activity>
|
</activity-alias>
|
||||||
|
|
||||||
<!-- activity for gesture settings -->
|
<!-- activity for gesture settings -->
|
||||||
<activity android:name="Settings$GestureSettingsActivity"
|
<activity android:name="Settings$GestureSettingsActivity"
|
||||||
|
@@ -8098,4 +8098,9 @@
|
|||||||
<!-- On status for the automatic storage manager. [CHAR_LIMIT=10] -->
|
<!-- On status for the automatic storage manager. [CHAR_LIMIT=10] -->
|
||||||
<string name="storage_manager_indicator_on">On</string>
|
<string name="storage_manager_indicator_on">On</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>
|
||||||
|
<!-- 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>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@@ -74,11 +74,9 @@
|
|||||||
android:title="@string/picture_color_mode"
|
android:title="@string/picture_color_mode"
|
||||||
android:summary="@string/picture_color_mode_desc" />
|
android:summary="@string/picture_color_mode_desc" />
|
||||||
|
|
||||||
<ListPreference
|
<Preference android:key="select_webview_provider"
|
||||||
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:summary="%s" />
|
|
||||||
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:key="enable_webview_multiprocess"
|
android:key="enable_webview_multiprocess"
|
||||||
|
@@ -78,7 +78,7 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.accessibility.AccessibilityManager;
|
import android.view.accessibility.AccessibilityManager;
|
||||||
import android.webkit.IWebViewUpdateService;
|
import android.webkit.IWebViewUpdateService;
|
||||||
import android.webkit.WebViewProviderInfo;
|
import android.webkit.WebViewFactory;
|
||||||
import android.widget.Switch;
|
import android.widget.Switch;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
@@ -92,6 +92,7 @@ import com.android.settings.fuelgauge.InactiveApps;
|
|||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
import com.android.settings.search.BaseSearchIndexProvider;
|
import com.android.settings.search.BaseSearchIndexProvider;
|
||||||
import com.android.settings.search.Indexable;
|
import com.android.settings.search.Indexable;
|
||||||
|
import com.android.settings.webview.WebViewAppPreferenceController;
|
||||||
import com.android.settings.widget.SwitchBar;
|
import com.android.settings.widget.SwitchBar;
|
||||||
import com.android.settingslib.RestrictedLockUtils;
|
import com.android.settingslib.RestrictedLockUtils;
|
||||||
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||||
@@ -126,7 +127,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
|||||||
private static final String ENABLE_TERMINAL = "enable_terminal";
|
private static final String ENABLE_TERMINAL = "enable_terminal";
|
||||||
private static final String KEEP_SCREEN_ON = "keep_screen_on";
|
private static final String KEEP_SCREEN_ON = "keep_screen_on";
|
||||||
private static final String BT_HCI_SNOOP_LOG = "bt_hci_snoop_log";
|
private static final String BT_HCI_SNOOP_LOG = "bt_hci_snoop_log";
|
||||||
private static final String WEBVIEW_PROVIDER_KEY = "select_webview_provider";
|
|
||||||
private static final String WEBVIEW_MULTIPROCESS_KEY = "enable_webview_multiprocess";
|
private static final String WEBVIEW_MULTIPROCESS_KEY = "enable_webview_multiprocess";
|
||||||
private static final String ENABLE_OEM_UNLOCK = "oem_unlock_enable";
|
private static final String ENABLE_OEM_UNLOCK = "oem_unlock_enable";
|
||||||
private static final String HDCP_CHECKING_KEY = "hdcp_checking";
|
private static final String HDCP_CHECKING_KEY = "hdcp_checking";
|
||||||
@@ -230,6 +230,7 @@ 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";
|
||||||
@@ -310,8 +311,8 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
|||||||
private ListPreference mAnimatorDurationScale;
|
private ListPreference mAnimatorDurationScale;
|
||||||
private ListPreference mOverlayDisplayDevices;
|
private ListPreference mOverlayDisplayDevices;
|
||||||
|
|
||||||
|
private WebViewAppPreferenceController mWebViewAppPrefController;
|
||||||
private SwitchPreference mWebViewMultiprocess;
|
private SwitchPreference mWebViewMultiprocess;
|
||||||
private ListPreference mWebViewProvider;
|
|
||||||
|
|
||||||
private ListPreference mSimulateColorSpace;
|
private ListPreference mSimulateColorSpace;
|
||||||
|
|
||||||
@@ -371,8 +372,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
|||||||
mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
|
mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
|
||||||
mBackupManager = IBackupManager.Stub.asInterface(
|
mBackupManager = IBackupManager.Stub.asInterface(
|
||||||
ServiceManager.getService(Context.BACKUP_SERVICE));
|
ServiceManager.getService(Context.BACKUP_SERVICE));
|
||||||
mWebViewUpdateService =
|
mWebViewUpdateService = WebViewFactory.getUpdateService();
|
||||||
IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
|
|
||||||
mOemUnlockManager = (PersistentDataBlockManager) getActivity()
|
mOemUnlockManager = (PersistentDataBlockManager) getActivity()
|
||||||
.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
|
.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
|
||||||
mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
|
mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
|
||||||
@@ -384,6 +384,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
|||||||
|
|
||||||
mBugReportController = new BugReportPreferenceController(getActivity());
|
mBugReportController = new BugReportPreferenceController(getActivity());
|
||||||
mBugReportInPowerController = new BugReportInPowerPreferenceController(getActivity());
|
mBugReportInPowerController = new BugReportInPowerPreferenceController(getActivity());
|
||||||
|
mWebViewAppPrefController = new WebViewAppPreferenceController(getActivity());
|
||||||
|
|
||||||
setIfOnlyAvailableForAdmins(true);
|
setIfOnlyAvailableForAdmins(true);
|
||||||
if (isUiRestricted() || !Utils.isDeviceProvisioned(getActivity())) {
|
if (isUiRestricted() || !Utils.isDeviceProvisioned(getActivity())) {
|
||||||
@@ -414,6 +415,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
|||||||
|
|
||||||
mBugReportController.displayPreference(getPreferenceScreen());
|
mBugReportController.displayPreference(getPreferenceScreen());
|
||||||
mBugReportInPowerController.displayPreference(getPreferenceScreen());
|
mBugReportInPowerController.displayPreference(getPreferenceScreen());
|
||||||
|
mWebViewAppPrefController.displayPreference(getPreferenceScreen());
|
||||||
|
|
||||||
mKeepScreenOn = (RestrictedSwitchPreference) findAndInitSwitchPref(KEEP_SCREEN_ON);
|
mKeepScreenOn = (RestrictedSwitchPreference) findAndInitSwitchPref(KEEP_SCREEN_ON);
|
||||||
mBtHciSnoopLog = findAndInitSwitchPref(BT_HCI_SNOOP_LOG);
|
mBtHciSnoopLog = findAndInitSwitchPref(BT_HCI_SNOOP_LOG);
|
||||||
@@ -483,7 +485,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
|||||||
mLogpersist = null;
|
mLogpersist = null;
|
||||||
}
|
}
|
||||||
mUsbConfiguration = addListPreference(USB_CONFIGURATION_KEY);
|
mUsbConfiguration = addListPreference(USB_CONFIGURATION_KEY);
|
||||||
mWebViewProvider = addListPreference(WEBVIEW_PROVIDER_KEY);
|
|
||||||
mWebViewMultiprocess = findAndInitSwitchPref(WEBVIEW_MULTIPROCESS_KEY);
|
mWebViewMultiprocess = findAndInitSwitchPref(WEBVIEW_MULTIPROCESS_KEY);
|
||||||
mBluetoothDisableAbsVolume = findAndInitSwitchPref(BLUETOOTH_DISABLE_ABSOLUTE_VOLUME_KEY);
|
mBluetoothDisableAbsVolume = findAndInitSwitchPref(BLUETOOTH_DISABLE_ABSOLUTE_VOLUME_KEY);
|
||||||
|
|
||||||
@@ -544,7 +545,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
|||||||
removePreference(KEY_COLOR_MODE);
|
removePreference(KEY_COLOR_MODE);
|
||||||
mColorModePreference = null;
|
mColorModePreference = null;
|
||||||
}
|
}
|
||||||
updateWebViewProviderOptions();
|
|
||||||
|
|
||||||
mColorTemperaturePreference = (SwitchPreference) findPreference(COLOR_TEMPERATURE_KEY);
|
mColorTemperaturePreference = (SwitchPreference) findPreference(COLOR_TEMPERATURE_KEY);
|
||||||
if (getResources().getBoolean(R.bool.config_enableColorTemperature)) {
|
if (getResources().getBoolean(R.bool.config_enableColorTemperature)) {
|
||||||
@@ -629,6 +629,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
|||||||
pref.setEnabled(enabled && !mDisabledPrefs.contains(pref));
|
pref.setEnabled(enabled && !mDisabledPrefs.contains(pref));
|
||||||
}
|
}
|
||||||
mBugReportInPowerController.enablePreference(enabled);
|
mBugReportInPowerController.enablePreference(enabled);
|
||||||
|
mWebViewAppPrefController.enablePreference(enabled);
|
||||||
updateAllOptions();
|
updateAllOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -793,8 +794,8 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
|||||||
updateSimulateColorSpace();
|
updateSimulateColorSpace();
|
||||||
updateUSBAudioOptions();
|
updateUSBAudioOptions();
|
||||||
updateForceResizableOptions();
|
updateForceResizableOptions();
|
||||||
|
mWebViewAppPrefController.updateState(null);
|
||||||
updateWebViewMultiprocessOptions();
|
updateWebViewMultiprocessOptions();
|
||||||
updateWebViewProviderOptions();
|
|
||||||
updateOemUnlockOptions();
|
updateOemUnlockOptions();
|
||||||
if (mColorTemperaturePreference != null) {
|
if (mColorTemperaturePreference != null) {
|
||||||
updateColorTemperature();
|
updateColorTemperature();
|
||||||
@@ -831,39 +832,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
|||||||
pokeSystemProperties();
|
pokeSystemProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateWebViewProviderOptions() {
|
|
||||||
try {
|
|
||||||
WebViewProviderInfo[] providers = mWebViewUpdateService.getValidWebViewPackages();
|
|
||||||
if (providers == null) {
|
|
||||||
Log.e(TAG, "No WebView providers available");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ArrayList<String> options = new ArrayList<String>();
|
|
||||||
ArrayList<String> values = new ArrayList<String>();
|
|
||||||
for (int n = 0; n < providers.length; n++) {
|
|
||||||
if (Utils.isPackageEnabled(getActivity(), providers[n].packageName)) {
|
|
||||||
options.add(providers[n].description);
|
|
||||||
values.add(providers[n].packageName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mWebViewProvider.setEntries(options.toArray(new String[options.size()]));
|
|
||||||
mWebViewProvider.setEntryValues(values.toArray(new String[values.size()]));
|
|
||||||
|
|
||||||
String value = mWebViewUpdateService.getCurrentWebViewPackageName();
|
|
||||||
if (value == null) {
|
|
||||||
value = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < values.size(); i++) {
|
|
||||||
if (value.contentEquals(values.get(i))) {
|
|
||||||
mWebViewProvider.setValueIndex(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateWebViewMultiprocessOptions() {
|
private void updateWebViewMultiprocessOptions() {
|
||||||
try {
|
try {
|
||||||
updateSwitchPreference(mWebViewMultiprocess,
|
updateSwitchPreference(mWebViewMultiprocess,
|
||||||
@@ -918,17 +886,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
|||||||
mBtHciSnoopLog.isChecked() ? 1 : 0);
|
mBtHciSnoopLog.isChecked() ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean writeWebViewProviderOptions(Object newValue) {
|
|
||||||
try {
|
|
||||||
String updatedProvider = mWebViewUpdateService.changeProviderAndSetting(
|
|
||||||
newValue == null ? "" : newValue.toString());
|
|
||||||
updateWebViewProviderOptions();
|
|
||||||
return newValue != null && newValue.equals(updatedProvider);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeDebuggerOptions() {
|
private void writeDebuggerOptions() {
|
||||||
try {
|
try {
|
||||||
ActivityManager.getService().setDebugApp(
|
ActivityManager.getService().setDebugApp(
|
||||||
@@ -2327,6 +2284,8 @@ 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()) {
|
||||||
@@ -2349,6 +2308,10 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
|||||||
if (mBugReportInPowerController.handlePreferenceTreeClick(preference)) {
|
if (mBugReportInPowerController.handlePreferenceTreeClick(preference)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (mWebViewAppPrefController.handlePreferenceTreeClick(preference)) {
|
||||||
|
startActivityForResult(
|
||||||
|
mWebViewAppPrefController.getActivityIntent(), RESULT_WEBVIEW_APP);
|
||||||
|
}
|
||||||
|
|
||||||
if (preference == mEnableAdb) {
|
if (preference == mEnableAdb) {
|
||||||
if (mEnableAdb.isChecked()) {
|
if (mEnableAdb.isChecked()) {
|
||||||
@@ -2502,21 +2465,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
|
|||||||
updateHdcpValues();
|
updateHdcpValues();
|
||||||
pokeSystemProperties();
|
pokeSystemProperties();
|
||||||
return true;
|
return true;
|
||||||
} else if (preference == mWebViewProvider) {
|
|
||||||
if (newValue == null) {
|
|
||||||
Log.e(TAG, "Tried to set a null WebView provider");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (writeWebViewProviderOptions(newValue)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// The user chose a package that became invalid since the list was last updated,
|
|
||||||
// show a Toast to explain the situation.
|
|
||||||
Toast toast = Toast.makeText(getActivity(),
|
|
||||||
R.string.select_webview_provider_toast_text, Toast.LENGTH_SHORT);
|
|
||||||
toast.show();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} else if ((preference == mBluetoothSelectA2dpCodec) ||
|
} else if ((preference == mBluetoothSelectA2dpCodec) ||
|
||||||
(preference == mBluetoothSelectA2dpSampleRate) ||
|
(preference == mBluetoothSelectA2dpSampleRate) ||
|
||||||
(preference == mBluetoothSelectA2dpBitsPerSample) ||
|
(preference == mBluetoothSelectA2dpBitsPerSample) ||
|
||||||
|
@@ -44,6 +44,8 @@ public class SettingsInitialize extends BroadcastReceiver {
|
|||||||
private static final String TAG = "Settings";
|
private static final String TAG = "Settings";
|
||||||
private static final String PRIMARY_PROFILE_SETTING =
|
private static final String PRIMARY_PROFILE_SETTING =
|
||||||
"com.android.settings.PRIMARY_PROFILE_CONTROLLED";
|
"com.android.settings.PRIMARY_PROFILE_CONTROLLED";
|
||||||
|
private static final String SETTINGS_PACKAGE = "com.android.settings";
|
||||||
|
private static final String WEBVIEW_IMPLEMENTATION_ACTIVITY = ".WebViewImplementation";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent broadcast) {
|
public void onReceive(Context context, Intent broadcast) {
|
||||||
@@ -100,7 +102,7 @@ public class SettingsInitialize extends BroadcastReceiver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ComponentName settingsComponentName =
|
ComponentName settingsComponentName =
|
||||||
new ComponentName(context, WebViewImplementation.class);
|
new ComponentName(SETTINGS_PACKAGE, SETTINGS_PACKAGE + WEBVIEW_IMPLEMENTATION_ACTIVITY);
|
||||||
pm.setComponentEnabledSetting(settingsComponentName,
|
pm.setComponentEnabledSetting(settingsComponentName,
|
||||||
userInfo.isAdmin() ?
|
userInfo.isAdmin() ?
|
||||||
PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
|
PackageManager.COMPONENT_ENABLED_STATE_ENABLED :
|
||||||
|
@@ -1,114 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 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;
|
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.DialogInterface.OnCancelListener;
|
|
||||||
import android.content.DialogInterface.OnClickListener;
|
|
||||||
import android.content.DialogInterface.OnDismissListener;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.os.ServiceManager;
|
|
||||||
import android.os.UserManager;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.webkit.IWebViewUpdateService;
|
|
||||||
import android.webkit.WebViewProviderInfo;
|
|
||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
|
||||||
import com.android.settings.core.InstrumentedActivity;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
public class WebViewImplementation extends InstrumentedActivity implements
|
|
||||||
OnCancelListener, OnDismissListener {
|
|
||||||
|
|
||||||
private static final String TAG = "WebViewImplementation";
|
|
||||||
|
|
||||||
private IWebViewUpdateService mWebViewUpdateService;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
if (!UserManager.get(this).isAdminUser()) {
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mWebViewUpdateService =
|
|
||||||
IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
|
|
||||||
try {
|
|
||||||
WebViewProviderInfo[] providers = mWebViewUpdateService.getValidWebViewPackages();
|
|
||||||
if (providers == null) {
|
|
||||||
Log.e(TAG, "No WebView providers available");
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String currentValue = mWebViewUpdateService.getCurrentWebViewPackageName();
|
|
||||||
if (currentValue == null) {
|
|
||||||
currentValue = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
int currentIndex = -1;
|
|
||||||
ArrayList<String> options = new ArrayList<>();
|
|
||||||
final ArrayList<String> values = new ArrayList<>();
|
|
||||||
for (WebViewProviderInfo provider : providers) {
|
|
||||||
if (Utils.isPackageEnabled(this, provider.packageName)) {
|
|
||||||
options.add(provider.description);
|
|
||||||
values.add(provider.packageName);
|
|
||||||
if (currentValue.contentEquals(provider.packageName)) {
|
|
||||||
currentIndex = values.size() - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
new AlertDialog.Builder(this)
|
|
||||||
.setTitle(R.string.select_webview_provider_dialog_title)
|
|
||||||
.setSingleChoiceItems(options.toArray(new String[0]), currentIndex,
|
|
||||||
new OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
try {
|
|
||||||
mWebViewUpdateService.changeProviderAndSetting(values.get(which));
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
Log.w(TAG, "Problem reaching webviewupdate service", e);
|
|
||||||
}
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}).setNegativeButton(android.R.string.cancel, null)
|
|
||||||
.setOnCancelListener(this)
|
|
||||||
.setOnDismissListener(this)
|
|
||||||
.show();
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
Log.w(TAG, "Problem reaching webviewupdate service", e);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMetricsCategory() {
|
|
||||||
return MetricsEvent.WEBVIEW_IMPLEMENTATION;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCancel(DialogInterface dialog) {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDismiss(DialogInterface dialog) {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
33
src/com/android/settings/webview/UserPackageWrapper.java
Normal file
33
src/com/android/settings/webview/UserPackageWrapper.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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.PackageInfo;
|
||||||
|
import android.content.pm.UserInfo;
|
||||||
|
import android.webkit.UserPackage;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper class around android.webkit.UserPackage - to be able to use UserPackage in Robolectric
|
||||||
|
* tests (such tests currently don't support mocking hidden classes).
|
||||||
|
*/
|
||||||
|
interface UserPackageWrapper {
|
||||||
|
UserInfo getUserInfo();
|
||||||
|
PackageInfo getPackageInfo();
|
||||||
|
boolean isEnabledPackage();
|
||||||
|
boolean isInstalledPackage();
|
||||||
|
}
|
50
src/com/android/settings/webview/UserPackageWrapperImpl.java
Normal file
50
src/com/android/settings/webview/UserPackageWrapperImpl.java
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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.PackageInfo;
|
||||||
|
import android.content.pm.UserInfo;
|
||||||
|
import android.webkit.UserPackage;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation of UserPackageWrapper.
|
||||||
|
*/
|
||||||
|
class UserPackageWrapperImpl implements UserPackageWrapper {
|
||||||
|
private final UserPackage mUserPackage;
|
||||||
|
|
||||||
|
UserPackageWrapperImpl(UserPackage userPackage) {
|
||||||
|
mUserPackage = userPackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserInfo getUserInfo() {
|
||||||
|
return mUserPackage.getUserInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PackageInfo getPackageInfo() {
|
||||||
|
return mUserPackage.getPackageInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabledPackage() {
|
||||||
|
return mUserPackage.isEnabledPackage();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInstalledPackage() {
|
||||||
|
return mUserPackage.isInstalledPackage();
|
||||||
|
}
|
||||||
|
}
|
126
src/com/android/settings/webview/WebViewAppListAdapter.java
Normal file
126
src/com/android/settings/webview/WebViewAppListAdapter.java
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* 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.PackageManager;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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));
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
95
src/com/android/settings/webview/WebViewAppPicker.java
Normal file
95
src/com/android/settings/webview/WebViewAppPicker.java
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* 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.app.ListActivity;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class WebViewAppPicker extends ListActivity implements Instrumentable {
|
||||||
|
private static final String TAG = WebViewAppPicker.class.getSimpleName();
|
||||||
|
private WebViewAppListAdapter mAdapter;
|
||||||
|
private WebViewUpdateServiceWrapper mWebViewUpdateServiceWrapper;
|
||||||
|
|
||||||
|
private final VisibilityLoggerMixin mVisibilityLoggerMixin =
|
||||||
|
new VisibilityLoggerMixin(getMetricsCategory());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle icicle) {
|
||||||
|
super.onCreate(icicle);
|
||||||
|
|
||||||
|
if (mWebViewUpdateServiceWrapper == null) {
|
||||||
|
setWebViewUpdateServiceWrapper(createDefaultWebViewUpdateServiceWrapper());
|
||||||
|
}
|
||||||
|
mAdapter = new WebViewAppListAdapter(this, mWebViewUpdateServiceWrapper);
|
||||||
|
setListAdapter(mAdapter);
|
||||||
|
|
||||||
|
mVisibilityLoggerMixin.onAttach(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||||
|
WebViewApplicationInfo app = mAdapter.getItem(position);
|
||||||
|
|
||||||
|
if (mWebViewUpdateServiceWrapper.setWebViewProvider(app.info.packageName)) {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.setAction(app.info.packageName);
|
||||||
|
setResult(RESULT_OK, intent);
|
||||||
|
} else {
|
||||||
|
mWebViewUpdateServiceWrapper.showInvalidChoiceToast(this);
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
private WebViewUpdateServiceWrapper createDefaultWebViewUpdateServiceWrapper() {
|
||||||
|
return new WebViewUpdateServiceWrapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void setWebViewUpdateServiceWrapper(WebViewUpdateServiceWrapper wvusWrapper) {
|
||||||
|
mWebViewUpdateServiceWrapper = wvusWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
mVisibilityLoggerMixin.onResume();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
mVisibilityLoggerMixin.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMetricsCategory() {
|
||||||
|
return MetricsEvent.WEBVIEW_IMPLEMENTATION;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* 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.app.Activity;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.support.annotation.VisibleForTesting;
|
||||||
|
import android.support.v7.preference.Preference;
|
||||||
|
import android.support.v7.preference.PreferenceScreen;
|
||||||
|
|
||||||
|
import com.android.settings.DevelopmentSettings;
|
||||||
|
import com.android.settings.core.PreferenceController;
|
||||||
|
|
||||||
|
public class WebViewAppPreferenceController extends PreferenceController {
|
||||||
|
|
||||||
|
private static final String WEBVIEW_APP_KEY = "select_webview_provider";
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
private Preference mPreference;
|
||||||
|
private final WebViewUpdateServiceWrapper mWebViewUpdateServiceWrapper;
|
||||||
|
|
||||||
|
public WebViewAppPreferenceController(Context context) {
|
||||||
|
this(context, new WebViewUpdateServiceWrapper());
|
||||||
|
}
|
||||||
|
|
||||||
|
public WebViewAppPreferenceController(Context context,
|
||||||
|
WebViewUpdateServiceWrapper webviewUpdateServiceWrapper) {
|
||||||
|
super(context);
|
||||||
|
mContext = context;
|
||||||
|
mWebViewUpdateServiceWrapper = webviewUpdateServiceWrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void displayPreference(PreferenceScreen screen) {
|
||||||
|
super.displayPreference(screen);
|
||||||
|
if (isAvailable()) {
|
||||||
|
mPreference = screen.findPreference(WEBVIEW_APP_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the return-value from the WebViewAppPicker Activity.
|
||||||
|
*/
|
||||||
|
public void onActivityResult(int resultCode, Intent data) {
|
||||||
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enablePreference(boolean enabled) {
|
||||||
|
if (isAvailable()) {
|
||||||
|
mPreference.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
src/com/android/settings/webview/WebViewApplicationInfo.java
Normal file
29
src/com/android/settings/webview/WebViewApplicationInfo.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.Log;
|
||||||
|
import android.webkit.UserPackage;
|
||||||
|
import android.webkit.WebViewFactory;
|
||||||
|
import android.webkit.WebViewProviderInfo;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class WebViewUpdateServiceWrapper {
|
||||||
|
private static final String TAG = "WVUSWrapper";
|
||||||
|
|
||||||
|
public WebViewUpdateServiceWrapper() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the package currently used as WebView implementation.
|
||||||
|
*/
|
||||||
|
public PackageInfo getCurrentWebViewPackage() {
|
||||||
|
try {
|
||||||
|
return WebViewFactory.getUpdateService().getCurrentWebViewPackage();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches ApplicationInfo objects for all currently valid WebView packages.
|
||||||
|
* A WebView package is considered valid if it can be used as a WebView implementation. The
|
||||||
|
* validity of a package is not dependent on whether the package is installed/enabled.
|
||||||
|
*/
|
||||||
|
public List<ApplicationInfo> getValidWebViewApplicationInfos(Context context) {
|
||||||
|
WebViewProviderInfo[] providers = null;
|
||||||
|
try {
|
||||||
|
providers = WebViewFactory.getUpdateService().getValidWebViewPackages();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
}
|
||||||
|
List<ApplicationInfo> pkgs = new ArrayList<>();
|
||||||
|
for (WebViewProviderInfo provider : providers) {
|
||||||
|
try {
|
||||||
|
pkgs.add(context.getPackageManager().getApplicationInfo(
|
||||||
|
provider.packageName, PACKAGE_FLAGS));
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pkgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change WebView provider to {@param packageName}.
|
||||||
|
* @return whether the change succeeded.
|
||||||
|
*/
|
||||||
|
public boolean setWebViewProvider(String packageName) {
|
||||||
|
try {
|
||||||
|
return packageName.equals(
|
||||||
|
WebViewFactory.getUpdateService().changeProviderAndSetting(packageName));
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "RemoteException when trying to change provider to " + packageName, e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch PackageInfos for the package named {@param packageName} for all users on the device.
|
||||||
|
*/
|
||||||
|
public List<UserPackageWrapper> getPackageInfosAllUsers(Context context, String packageName) {
|
||||||
|
List<UserPackageWrapper> userPackageWrappers = new ArrayList<>();
|
||||||
|
List<UserPackage> userPackages =
|
||||||
|
UserPackage.getPackageInfosAllUsers(context, packageName, PACKAGE_FLAGS);
|
||||||
|
for (UserPackage userPackage : userPackages) {
|
||||||
|
userPackageWrappers.add(new UserPackageWrapperImpl(userPackage));
|
||||||
|
}
|
||||||
|
return userPackageWrappers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a toast to explain the chosen package can no longer be chosen.
|
||||||
|
*/
|
||||||
|
public void showInvalidChoiceToast(Context context) {
|
||||||
|
// The user chose a package that became invalid since the list was last updated,
|
||||||
|
// show a Toast to explain the situation.
|
||||||
|
Toast toast = Toast.makeText(context,
|
||||||
|
R.string.select_webview_provider_toast_text, Toast.LENGTH_SHORT);
|
||||||
|
toast.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
static final int PACKAGE_FLAGS = PackageManager.MATCH_ANY_USER;
|
||||||
|
}
|
@@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* 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.junit.Assert.assertEquals;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.eq;
|
||||||
|
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.pm.ApplicationInfo;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
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.Robolectric;
|
||||||
|
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 static final String DEFAULT_PACKAGE_NAME = "DEFAULT_PACKAGE_NAME";
|
||||||
|
|
||||||
|
private static ApplicationInfo createApplicationInfo(String packageName) {
|
||||||
|
ApplicationInfo ai = new ApplicationInfo();
|
||||||
|
ai.packageName = packageName;
|
||||||
|
return ai;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClickingItemChangesProvider() {
|
||||||
|
ActivityController<WebViewAppPicker> controller =
|
||||||
|
Robolectric.buildActivity(WebViewAppPicker.class);
|
||||||
|
WebViewAppPicker webviewAppPicker = controller.get();
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
webviewAppPicker.setWebViewUpdateServiceWrapper(wvusWrapper);
|
||||||
|
|
||||||
|
controller.create().start().postCreate(null).resume().visible();
|
||||||
|
WebViewApplicationInfo firstItem =
|
||||||
|
(WebViewApplicationInfo) webviewAppPicker.getListView().getItemAtPosition(0);
|
||||||
|
assertThat(firstItem.info.packageName).isEqualTo(DEFAULT_PACKAGE_NAME);
|
||||||
|
|
||||||
|
webviewAppPicker.onListItemClick(webviewAppPicker.getListView(), null, 0, 0);
|
||||||
|
|
||||||
|
verify(wvusWrapper, times(1)).setWebViewProvider(eq(DEFAULT_PACKAGE_NAME));
|
||||||
|
assertThat(shadowOf(webviewAppPicker).getResultCode()).isEqualTo(Activity.RESULT_OK);
|
||||||
|
verify(wvusWrapper, never()).showInvalidChoiceToast(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailingPackageChangeReturnsCancelled() {
|
||||||
|
ActivityController<WebViewAppPicker> controller =
|
||||||
|
Robolectric.buildActivity(WebViewAppPicker.class);
|
||||||
|
WebViewAppPicker webviewAppPicker = controller.get();
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
webviewAppPicker.setWebViewUpdateServiceWrapper(wvusWrapper);
|
||||||
|
|
||||||
|
controller.create().start().postCreate(null).resume().visible();
|
||||||
|
WebViewApplicationInfo firstItem =
|
||||||
|
(WebViewApplicationInfo) webviewAppPicker.getListView().getItemAtPosition(0);
|
||||||
|
assertThat(firstItem.info.packageName).isEqualTo(DEFAULT_PACKAGE_NAME);
|
||||||
|
|
||||||
|
webviewAppPicker.onListItemClick(webviewAppPicker.getListView(), null, 0, 0);
|
||||||
|
|
||||||
|
verify(wvusWrapper, times(1)).setWebViewProvider(eq(DEFAULT_PACKAGE_NAME));
|
||||||
|
assertThat(shadowOf(webviewAppPicker).getResultCode()).isEqualTo(Activity.RESULT_CANCELED);
|
||||||
|
verify(wvusWrapper, times(1)).showInvalidChoiceToast(any());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* 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 org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Mockito.doNothing;
|
||||||
|
import static org.mockito.Mockito.eq;
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||||
|
public class WebViewAppPreferenceControllerTest {
|
||||||
|
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private PreferenceScreen mPreferenceScreen;
|
||||||
|
@Mock
|
||||||
|
private Preference mPreference;
|
||||||
|
|
||||||
|
private static final String DEFAULT_PACKAGE_NAME = "DEFAULT_PACKAGE_NAME";
|
||||||
|
|
||||||
|
@Before public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
when(mPreferenceScreen.findPreference(any())).thenReturn(mPreference);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 testOnActivityResultWithFailureDoesNothing() {
|
||||||
|
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, never()).updateState(any());
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user