1 /*
2  * Copyright (C) 2015 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.applications;
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.Handler;
25 import android.os.UserHandle;
26 import android.text.TextUtils;
27 import android.util.AttributeSet;
28 import android.util.Log;
29 import com.android.internal.content.PackageMonitor;
30 import com.android.settings.AppListPreference;
31 import com.android.settings.R;
32 
33 import java.util.ArrayList;
34 import java.util.List;
35 
36 public class DefaultBrowserPreference extends AppListPreference {
37 
38     private static final String TAG = "DefaultBrowserPref";
39 
40     private static final long DELAY_UPDATE_BROWSER_MILLIS = 500;
41 
42     private final Handler mHandler = new Handler();
43 
44     final private PackageManager mPm;
45 
DefaultBrowserPreference(Context context, AttributeSet attrs)46     public DefaultBrowserPreference(Context context, AttributeSet attrs) {
47         super(context, attrs);
48 
49         mPm = context.getPackageManager();
50         refreshBrowserApps();
51     }
52 
53     @Override
onAttached()54     public void onAttached() {
55         super.onAttached();
56         updateDefaultBrowserPreference();
57         mPackageMonitor.register(getContext(), getContext().getMainLooper(), false);
58     }
59 
60     @Override
onDetached()61     public void onDetached() {
62         mPackageMonitor.unregister();
63         super.onDetached();
64     }
65 
66     @Override
persistString(String newValue)67     protected boolean persistString(String newValue) {
68 
69         if (newValue == null) {
70             return false;
71         }
72         final CharSequence packageName = (CharSequence) newValue;
73         if (TextUtils.isEmpty(packageName)) {
74             return false;
75         }
76         boolean result = mPm.setDefaultBrowserPackageNameAsUser(
77                 packageName.toString(), mUserId);
78         if (result) {
79             setSummary("%s");
80         }
81         return result && super.persistString(newValue);
82     }
83 
refreshBrowserApps()84     public void refreshBrowserApps() {
85         List<String> browsers = resolveBrowserApps();
86 
87         setPackageNames(browsers.toArray(new String[browsers.size()]), null);
88     }
89 
updateDefaultBrowserPreference()90     private void updateDefaultBrowserPreference() {
91         refreshBrowserApps();
92 
93         final PackageManager pm = getContext().getPackageManager();
94 
95         String packageName = pm.getDefaultBrowserPackageNameAsUser(mUserId);
96         if (!TextUtils.isEmpty(packageName)) {
97             // Check if the default Browser package is still there
98             Intent intent = new Intent();
99             intent.setPackage(packageName);
100             intent.setAction(Intent.ACTION_VIEW);
101             intent.addCategory(Intent.CATEGORY_BROWSABLE);
102             intent.setData(Uri.parse("http:"));
103 
104             ResolveInfo info = mPm.resolveActivityAsUser(intent, 0, mUserId);
105             if (info != null) {
106                 setValue(packageName);
107                 setSummary("%s");
108             } else {
109                 setSummary(R.string.default_browser_title_none);
110             }
111         } else {
112             setSummary(R.string.default_browser_title_none);
113             Log.d(TAG, "Cannot set empty default Browser value!");
114         }
115     }
116 
resolveBrowserApps()117     private List<String> resolveBrowserApps() {
118         List<String> result = new ArrayList<>();
119 
120         // Create an Intent that will match ALL Browser Apps
121         Intent intent = new Intent();
122         intent.setAction(Intent.ACTION_VIEW);
123         intent.addCategory(Intent.CATEGORY_BROWSABLE);
124         intent.setData(Uri.parse("http:"));
125 
126         // Resolve that intent and check that the handleAllWebDataURI boolean is set
127         List<ResolveInfo> list = mPm.queryIntentActivitiesAsUser(intent, PackageManager.MATCH_ALL,
128                 mUserId);
129 
130         final int count = list.size();
131         for (int i=0; i<count; i++) {
132             ResolveInfo info = list.get(i);
133             if (info.activityInfo == null || result.contains(info.activityInfo.packageName)
134                     || !info.handleAllWebDataURI) {
135                 continue;
136             }
137 
138             result.add(info.activityInfo.packageName);
139         }
140 
141         return result;
142     }
143 
144     private final Runnable mUpdateRunnable = new Runnable() {
145         @Override
146         public void run() {
147             updateDefaultBrowserPreference();
148         }
149     };
150 
151     private final PackageMonitor mPackageMonitor = new PackageMonitor() {
152         @Override
153         public void onPackageAdded(String packageName, int uid) {
154             sendUpdate();
155         }
156 
157         @Override
158         public void onPackageAppeared(String packageName, int reason) {
159             sendUpdate();
160         }
161 
162         @Override
163         public void onPackageDisappeared(String packageName, int reason) {
164             sendUpdate();
165         }
166 
167         @Override
168         public void onPackageRemoved(String packageName, int uid) {
169             sendUpdate();
170         }
171 
172         private void sendUpdate() {
173             mHandler.postDelayed(mUpdateRunnable, DELAY_UPDATE_BROWSER_MILLIS);
174         }
175     };
176 
hasBrowserPreference(String pkg, Context context)177     public static boolean hasBrowserPreference(String pkg, Context context) {
178         Intent intent = new Intent();
179         intent.setAction(Intent.ACTION_VIEW);
180         intent.addCategory(Intent.CATEGORY_BROWSABLE);
181         intent.setData(Uri.parse("http:"));
182         intent.setPackage(pkg);
183         final List<ResolveInfo> resolveInfos =
184                 context.getPackageManager().queryIntentActivities(intent, 0);
185         return resolveInfos != null && resolveInfos.size() != 0;
186     }
187 
isBrowserDefault(String pkg, Context context)188     public static boolean isBrowserDefault(String pkg, Context context) {
189         String defaultPackage = context.getPackageManager()
190                 .getDefaultBrowserPackageNameAsUser(UserHandle.myUserId());
191         return defaultPackage != null && defaultPackage.equals(pkg);
192     }
193 }
194