1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.webview; 18 19 import static android.provider.Settings.ACTION_WEBVIEW_SETTINGS; 20 21 import android.app.Activity; 22 import android.app.settings.SettingsEnums; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.pm.ApplicationInfo; 26 import android.content.pm.PackageInfo; 27 import android.content.pm.PackageItemInfo; 28 import android.content.pm.PackageManager; 29 import android.os.UserManager; 30 import android.text.TextUtils; 31 import android.webkit.UserPackage; 32 33 import androidx.annotation.VisibleForTesting; 34 35 import com.android.settings.R; 36 import com.android.settings.applications.defaultapps.DefaultAppPickerFragment; 37 import com.android.settingslib.applications.DefaultAppInfo; 38 39 import java.util.ArrayList; 40 import java.util.List; 41 42 public class WebViewAppPicker extends DefaultAppPickerFragment { 43 private WebViewUpdateServiceWrapper mWebViewUpdateServiceWrapper; 44 getWebViewUpdateServiceWrapper()45 private WebViewUpdateServiceWrapper getWebViewUpdateServiceWrapper() { 46 if (mWebViewUpdateServiceWrapper == null) { 47 setWebViewUpdateServiceWrapper(createDefaultWebViewUpdateServiceWrapper()); 48 } 49 return mWebViewUpdateServiceWrapper; 50 } 51 52 @Override onAttach(Context context)53 public void onAttach(Context context) { 54 super.onAttach(context); 55 56 if (!mUserManager.isAdminUser()) { 57 getActivity().finish(); 58 } 59 } 60 61 @Override getPreferenceScreenResId()62 protected int getPreferenceScreenResId() { 63 return R.xml.webview_app_settings; 64 } 65 66 @Override getCandidates()67 protected List<DefaultAppInfo> getCandidates() { 68 final List<DefaultAppInfo> packageInfoList = new ArrayList<DefaultAppInfo>(); 69 final Context context = getContext(); 70 final WebViewUpdateServiceWrapper webViewUpdateService = getWebViewUpdateServiceWrapper(); 71 final List<ApplicationInfo> pkgs = 72 webViewUpdateService.getValidWebViewApplicationInfos(context); 73 for (ApplicationInfo ai : pkgs) { 74 packageInfoList.add(createDefaultAppInfo(context, mPm, ai, 75 getDisabledReason(webViewUpdateService, context, ai.packageName))); 76 } 77 return packageInfoList; 78 } 79 80 @Override getDefaultKey()81 protected String getDefaultKey() { 82 PackageInfo currentPackage = getWebViewUpdateServiceWrapper().getCurrentWebViewPackage(); 83 return currentPackage == null ? null : currentPackage.packageName; 84 } 85 setDefaultKey(String key)86 protected boolean setDefaultKey(String key) { 87 boolean success = getWebViewUpdateServiceWrapper().setWebViewProvider(key); 88 return success; 89 } 90 91 @Override onSelectionPerformed(boolean success)92 protected void onSelectionPerformed(boolean success) { 93 if (success) { 94 Activity activity = getActivity(); 95 Intent intent = activity == null ? null : activity.getIntent(); 96 if (intent != null && ACTION_WEBVIEW_SETTINGS.equals(intent.getAction())) { 97 // If this was started through ACTION_WEBVIEW_SETTINGS then return once we have 98 // chosen a new package. 99 getActivity().finish(); 100 } 101 } else { 102 getWebViewUpdateServiceWrapper().showInvalidChoiceToast(getActivity()); 103 updateCandidates(); 104 } 105 } 106 createDefaultWebViewUpdateServiceWrapper()107 private WebViewUpdateServiceWrapper createDefaultWebViewUpdateServiceWrapper() { 108 return new WebViewUpdateServiceWrapper(); 109 } 110 111 @VisibleForTesting setWebViewUpdateServiceWrapper(WebViewUpdateServiceWrapper wvusWrapper)112 void setWebViewUpdateServiceWrapper(WebViewUpdateServiceWrapper wvusWrapper) { 113 mWebViewUpdateServiceWrapper = wvusWrapper; 114 } 115 116 @Override getMetricsCategory()117 public int getMetricsCategory() { 118 return SettingsEnums.WEBVIEW_IMPLEMENTATION; 119 } 120 121 private static class WebViewAppInfo extends DefaultAppInfo { WebViewAppInfo(Context context, PackageManager pm, int userId, PackageItemInfo packageItemInfo, String summary, boolean enabled)122 public WebViewAppInfo(Context context, PackageManager pm, int userId, 123 PackageItemInfo packageItemInfo, String summary, boolean enabled) { 124 super(context, pm, userId, packageItemInfo, summary, enabled); 125 } 126 127 @Override loadLabel()128 public CharSequence loadLabel() { 129 String versionName = ""; 130 try { 131 versionName = mPm.getPackageInfo(packageItemInfo.packageName, 0).versionName; 132 } catch (PackageManager.NameNotFoundException e) { 133 } 134 return String.format("%s %s", super.loadLabel(), versionName); 135 } 136 } 137 138 139 @VisibleForTesting createDefaultAppInfo(Context context, PackageManager pm, PackageItemInfo packageItemInfo, String disabledReason)140 DefaultAppInfo createDefaultAppInfo(Context context, PackageManager pm, 141 PackageItemInfo packageItemInfo, String disabledReason) { 142 return new WebViewAppInfo(context, pm, mUserId, packageItemInfo, disabledReason, 143 TextUtils.isEmpty(disabledReason) /* enabled */); 144 } 145 146 /** 147 * Returns the reason why a package cannot be used as WebView implementation. 148 * This is either because of it being disabled, uninstalled, or hidden for any user. 149 */ 150 @VisibleForTesting getDisabledReason(WebViewUpdateServiceWrapper webviewUpdateServiceWrapper, Context context, String packageName)151 String getDisabledReason(WebViewUpdateServiceWrapper webviewUpdateServiceWrapper, 152 Context context, String packageName) { 153 UserManager userManager = context.getSystemService(UserManager.class); 154 List<UserPackage> userPackages = 155 webviewUpdateServiceWrapper.getPackageInfosAllUsers(context, packageName); 156 for (UserPackage userPackage : userPackages) { 157 if (!userPackage.isInstalledPackage()) { 158 // Package uninstalled/hidden 159 return context.getString( 160 R.string.webview_uninstalled_for_user, 161 userManager.getUserInfo(userPackage.getUser().getIdentifier()).name); 162 } else if (!userPackage.isEnabledPackage()) { 163 // Package disabled 164 return context.getString( 165 R.string.webview_disabled_for_user, 166 userManager.getUserInfo(userPackage.getUser().getIdentifier()).name); 167 } 168 } 169 return null; 170 } 171 } 172