1 /* 2 * Copyright (C) 2019 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.permissioncontroller.role.model; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.content.pm.PackageManager; 22 import android.content.pm.ResolveInfo; 23 import android.net.Uri; 24 import android.os.Process; 25 import android.os.UserHandle; 26 import android.util.ArraySet; 27 28 import androidx.annotation.NonNull; 29 import androidx.annotation.Nullable; 30 31 import com.android.permissioncontroller.R; 32 import com.android.permissioncontroller.role.utils.UserUtils; 33 34 import java.util.ArrayList; 35 import java.util.List; 36 37 /** 38 * Class for behavior of the browser role. 39 * 40 * @see com.android.settings.applications.DefaultAppSettings 41 * @see com.android.settings.applications.defaultapps.DefaultBrowserPreferenceController 42 * @see com.android.settings.applications.defaultapps.DefaultBrowserPicker 43 * @see com.android.server.pm.PackageManagerService#resolveAllBrowserApps(int) 44 */ 45 public class BrowserRoleBehavior implements RoleBehavior { 46 47 private static final Intent BROWSER_INTENT = new Intent() 48 .setAction(Intent.ACTION_VIEW) 49 .addCategory(Intent.CATEGORY_BROWSABLE) 50 .setData(Uri.fromParts("http", "", null)); 51 52 @Nullable 53 @Override getFallbackHolder(@onNull Role role, @NonNull Context context)54 public String getFallbackHolder(@NonNull Role role, @NonNull Context context) { 55 List<String> packageNames = role.getQualifyingPackagesAsUser(Process.myUserHandle(), 56 context); 57 if (packageNames.size() == 1) { 58 return packageNames.get(0); 59 } 60 return null; 61 } 62 63 // PackageManager.queryIntentActivities() will only return the default browser if one was set. 64 // Code in the Settings app passes PackageManager.MATCH_ALL and perform its own filtering, so we 65 // do the same thing here. 66 @Nullable 67 @Override getQualifyingPackagesAsUser(@onNull Role role, @NonNull UserHandle user, @NonNull Context context)68 public List<String> getQualifyingPackagesAsUser(@NonNull Role role, @NonNull UserHandle user, 69 @NonNull Context context) { 70 return getQualifyingPackagesAsUserInternal(null, user, context); 71 } 72 73 @Nullable 74 @Override isPackageQualified(@onNull Role role, @NonNull String packageName, @NonNull Context context)75 public Boolean isPackageQualified(@NonNull Role role, @NonNull String packageName, 76 @NonNull Context context) { 77 List<String> packageNames = getQualifyingPackagesAsUserInternal(packageName, 78 Process.myUserHandle(), context); 79 return !packageNames.isEmpty(); 80 } 81 82 @NonNull getQualifyingPackagesAsUserInternal(@ullable String packageName, @NonNull UserHandle user, @NonNull Context context)83 private List<String> getQualifyingPackagesAsUserInternal(@Nullable String packageName, 84 @NonNull UserHandle user, @NonNull Context context) { 85 Context userContext = UserUtils.getUserContext(context, user); 86 PackageManager userPackageManager = userContext.getPackageManager(); 87 Intent intent = BROWSER_INTENT; 88 if (packageName != null) { 89 intent = new Intent(intent) 90 .setPackage(packageName); 91 } 92 List<ResolveInfo> resolveInfos = userPackageManager.queryIntentActivities(intent, 93 // To one's surprise, MATCH_ALL doesn't include MATCH_DIRECT_BOOT_*. 94 PackageManager.MATCH_ALL | PackageManager.MATCH_DIRECT_BOOT_AWARE 95 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE); 96 ArraySet<String> packageNames = new ArraySet<>(); 97 int resolveInfosSize = resolveInfos.size(); 98 for (int i = 0; i < resolveInfosSize; i++) { 99 ResolveInfo resolveInfo = resolveInfos.get(i); 100 101 if (!resolveInfo.handleAllWebDataURI) { 102 continue; 103 } 104 packageNames.add(resolveInfo.activityInfo.packageName); 105 } 106 return new ArrayList<>(packageNames); 107 } 108 109 @Override isVisibleAsUser(@onNull Role role, @NonNull UserHandle user, @NonNull Context context)110 public boolean isVisibleAsUser(@NonNull Role role, @NonNull UserHandle user, 111 @NonNull Context context) { 112 return context.getResources().getBoolean(R.bool.config_showBrowserRole); 113 } 114 } 115