Have WebView Implementation Dev Setting use DefaultAppPickerFragment.
Make the WebView Implementation Dev Setting look like the fullscreen settings deriving from DefaultAppPickerFragment. Point the Activity opened through Settings.ACTION_WEBVIEW_SETTINGS to the class WebViewAppPicker which is our new implementation of the WebView Implementation setting. Ensure the new setting closes if it is reached from a user that isn't an admin of the device. Bug: 34806477 Bug: 34966439 Test: Ensure WebView implementation Dev Setting looks ok (disabled packages should have a text showing why they cannot be chosen). Test: Start Intent with action Settings.ACTION_WEBVIEW_SETTINGS and ensure the started Activity looks similar to the WebView Implementation Dev Setting. Test: Ensure picking a package that is no longer active, updates the setting (so that package isn't visible anymore). Change-Id: I08007c515193739ad61dfd735bb5130fc07bd6e6
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -16,57 +16,83 @@
|
||||
|
||||
package com.android.settings.webview;
|
||||
|
||||
import android.app.ListActivity;
|
||||
import static android.provider.Settings.ACTION_WEBVIEW_SETTINGS;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.webkit.WebViewFactory;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.core.instrumentation.Instrumentable;
|
||||
import com.android.settings.core.instrumentation.VisibilityLoggerMixin;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.defaultapps.DefaultAppInfo;
|
||||
import com.android.settings.applications.defaultapps.DefaultAppPickerFragment;
|
||||
|
||||
public class WebViewAppPicker extends ListActivity implements Instrumentable {
|
||||
private static final String TAG = WebViewAppPicker.class.getSimpleName();
|
||||
private WebViewAppListAdapter mAdapter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class WebViewAppPicker extends DefaultAppPickerFragment {
|
||||
private WebViewUpdateServiceWrapper mWebViewUpdateServiceWrapper;
|
||||
|
||||
private final VisibilityLoggerMixin mVisibilityLoggerMixin =
|
||||
new VisibilityLoggerMixin(getMetricsCategory());
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
private WebViewUpdateServiceWrapper getWebViewUpdateServiceWrapper() {
|
||||
if (mWebViewUpdateServiceWrapper == null) {
|
||||
setWebViewUpdateServiceWrapper(createDefaultWebViewUpdateServiceWrapper());
|
||||
}
|
||||
mAdapter = new WebViewAppListAdapter(this, mWebViewUpdateServiceWrapper);
|
||||
setListAdapter(mAdapter);
|
||||
|
||||
mVisibilityLoggerMixin.onAttach(this);
|
||||
return mWebViewUpdateServiceWrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
WebViewApplicationInfo app = mAdapter.getItem(position);
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
|
||||
if (mWebViewUpdateServiceWrapper.setWebViewProvider(app.info.packageName)) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(app.info.packageName);
|
||||
setResult(RESULT_OK, intent);
|
||||
} else {
|
||||
mWebViewUpdateServiceWrapper.showInvalidChoiceToast(this);
|
||||
if (!mUserManager.isAdminUser()) {
|
||||
getActivity().finish();
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<DefaultAppInfo> getCandidates() {
|
||||
final List<DefaultAppInfo> packageInfoList = new ArrayList<DefaultAppInfo>();
|
||||
List<ApplicationInfo> pkgs =
|
||||
getWebViewUpdateServiceWrapper().getValidWebViewApplicationInfos(getContext());
|
||||
for (ApplicationInfo ai : pkgs) {
|
||||
packageInfoList.add(new DefaultAppInfo(ai,
|
||||
getDisabledReason(getWebViewUpdateServiceWrapper(),
|
||||
getContext(), ai.packageName)));
|
||||
}
|
||||
return packageInfoList;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultAppKey() {
|
||||
PackageInfo currentPackage = getWebViewUpdateServiceWrapper().getCurrentWebViewPackage();
|
||||
return currentPackage == null ? null : currentPackage.packageName;
|
||||
}
|
||||
|
||||
protected boolean setDefaultAppKey(String key) {
|
||||
boolean success = getWebViewUpdateServiceWrapper().setWebViewProvider(key);
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSelectionPerformed(boolean success) {
|
||||
if (success) {
|
||||
Activity activity = getActivity();
|
||||
Intent intent = activity == null ? null : activity.getIntent();
|
||||
if (intent != null && ACTION_WEBVIEW_SETTINGS.equals(intent.getAction())) {
|
||||
// If this was started through ACTION_WEBVIEW_SETTINGS then return once we have
|
||||
// chosen a new package.
|
||||
getActivity().finish();
|
||||
}
|
||||
} else {
|
||||
getWebViewUpdateServiceWrapper().showInvalidChoiceToast(getActivity());
|
||||
updateCandidates();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private WebViewUpdateServiceWrapper createDefaultWebViewUpdateServiceWrapper() {
|
||||
return new WebViewUpdateServiceWrapper();
|
||||
}
|
||||
@@ -76,20 +102,32 @@ public class WebViewAppPicker extends ListActivity implements Instrumentable {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
@@ -14,18 +14,15 @@
|
||||
|
||||
package com.android.settings.webview;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.DevelopmentSettings;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.applications.defaultapps.DefaultAppInfo;
|
||||
import com.android.settings.applications.defaultapps.DefaultAppPreferenceController;
|
||||
|
||||
public class WebViewAppPreferenceController extends PreferenceController {
|
||||
public class WebViewAppPreferenceController extends DefaultAppPreferenceController {
|
||||
|
||||
private static final String WEBVIEW_APP_KEY = "select_webview_provider";
|
||||
|
||||
@@ -45,20 +42,9 @@ public class WebViewAppPreferenceController extends PreferenceController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handlePreferenceTreeClick(Preference preference) {
|
||||
if (getPreferenceKey().equals(preference.getKey())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Intent getActivityIntent() {
|
||||
return new Intent(mContext, WebViewAppPicker.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
mPreference.setSummary(getCurrentWebViewPackageLabel(mContext));
|
||||
public DefaultAppInfo getDefaultAppInfo() {
|
||||
PackageInfo currentPackage = mWebViewUpdateServiceWrapper.getCurrentWebViewPackage();
|
||||
return new DefaultAppInfo(currentPackage == null ? null : currentPackage.applicationInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,23 +55,6 @@ 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
|
||||
public String getPreferenceKey() {
|
||||
return WEBVIEW_APP_KEY;
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user