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.content.Context; 23 import android.content.Intent; 24 import android.content.pm.ApplicationInfo; 25 import android.content.pm.PackageInfo; 26 import android.content.pm.PackageItemInfo; 27 import android.content.pm.PackageManager; 28 import android.support.annotation.VisibleForTesting; 29 import android.text.TextUtils; 30 31 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 32 import com.android.settings.R; 33 import com.android.settings.applications.PackageManagerWrapper; 34 import com.android.settings.applications.defaultapps.DefaultAppInfo; 35 import com.android.settings.applications.defaultapps.DefaultAppPickerFragment; 36 37 import java.util.ArrayList; 38 import java.util.List; 39 40 public class WebViewAppPicker extends DefaultAppPickerFragment { 41 private WebViewUpdateServiceWrapper mWebViewUpdateServiceWrapper; 42 43 private WebViewUpdateServiceWrapper getWebViewUpdateServiceWrapper() { 44 if (mWebViewUpdateServiceWrapper == null) { 45 setWebViewUpdateServiceWrapper(createDefaultWebViewUpdateServiceWrapper()); 46 } 47 return mWebViewUpdateServiceWrapper; 48 } 49 50 @Override 51 public void onAttach(Context context) { 52 super.onAttach(context); 53 54 if (!mUserManager.isAdminUser()) { 55 getActivity().finish(); 56 } 57 } 58 59 @Override 60 protected List<DefaultAppInfo> getCandidates() { 61 final List<DefaultAppInfo> packageInfoList = new ArrayList<DefaultAppInfo>(); 62 List<ApplicationInfo> pkgs = 63 getWebViewUpdateServiceWrapper().getValidWebViewApplicationInfos(getContext()); 64 for (ApplicationInfo ai : pkgs) { 65 packageInfoList.add(createDefaultAppInfo(mPm, ai, 66 getDisabledReason(getWebViewUpdateServiceWrapper(), 67 getContext(), ai.packageName))); 68 } 69 return packageInfoList; 70 } 71 72 @Override 73 protected String getDefaultKey() { 74 PackageInfo currentPackage = getWebViewUpdateServiceWrapper().getCurrentWebViewPackage(); 75 return currentPackage == null ? null : currentPackage.packageName; 76 } 77 78 protected boolean setDefaultKey(String key) { 79 boolean success = getWebViewUpdateServiceWrapper().setWebViewProvider(key); 80 return success; 81 } 82 83 @Override 84 protected void onSelectionPerformed(boolean success) { 85 if (success) { 86 Activity activity = getActivity(); 87 Intent intent = activity == null ? null : activity.getIntent(); 88 if (intent != null && ACTION_WEBVIEW_SETTINGS.equals(intent.getAction())) { 89 // If this was started through ACTION_WEBVIEW_SETTINGS then return once we have 90 // chosen a new package. 91 getActivity().finish(); 92 } 93 } else { 94 getWebViewUpdateServiceWrapper().showInvalidChoiceToast(getActivity()); 95 updateCandidates(); 96 } 97 } 98 99 private WebViewUpdateServiceWrapper createDefaultWebViewUpdateServiceWrapper() { 100 return new WebViewUpdateServiceWrapper(); 101 } 102 103 @VisibleForTesting 104 void setWebViewUpdateServiceWrapper(WebViewUpdateServiceWrapper wvusWrapper) { 105 mWebViewUpdateServiceWrapper = wvusWrapper; 106 } 107 108 @Override 109 public int getMetricsCategory() { 110 return MetricsEvent.WEBVIEW_IMPLEMENTATION; 111 } 112 113 private static class WebViewAppInfo extends DefaultAppInfo { 114 public WebViewAppInfo(PackageManagerWrapper pm, PackageItemInfo packageItemInfo, 115 String summary, boolean enabled) { 116 super(pm, packageItemInfo, summary, enabled); 117 } 118 119 @Override 120 public CharSequence loadLabel() { 121 String versionName = ""; 122 try { 123 versionName = mPm.getPackageManager(). 124 getPackageInfo(packageItemInfo.packageName, 0).versionName; 125 } catch (PackageManager.NameNotFoundException e) { 126 } 127 return String.format("%s %s", super.loadLabel(), versionName); 128 } 129 } 130 131 132 @VisibleForTesting 133 DefaultAppInfo createDefaultAppInfo(PackageManagerWrapper pm, PackageItemInfo packageItemInfo, 134 String disabledReason) { 135 return new WebViewAppInfo(pm, packageItemInfo, disabledReason, 136 TextUtils.isEmpty(disabledReason) /* enabled */); 137 } 138 139 /** 140 * Returns the reason why a package cannot be used as WebView implementation. 141 * This is either because of it being disabled, uninstalled, or hidden for any user. 142 */ 143 @VisibleForTesting 144 String getDisabledReason(WebViewUpdateServiceWrapper webviewUpdateServiceWrapper, 145 Context context, String packageName) { 146 List<UserPackageWrapper> userPackages = 147 webviewUpdateServiceWrapper.getPackageInfosAllUsers(context, packageName); 148 for (UserPackageWrapper userPackage : userPackages) { 149 if (!userPackage.isInstalledPackage()) { 150 // Package uninstalled/hidden 151 return context.getString( 152 R.string.webview_uninstalled_for_user, userPackage.getUserInfo().name); 153 } else if (!userPackage.isEnabledPackage()) { 154 // Package disabled 155 return context.getString( 156 R.string.webview_disabled_for_user, userPackage.getUserInfo().name); 157 } 158 } 159 return null; 160 } 161 } 162