OSDN Git Service

Use a framework resource to name a factory-default browser app
authorChristopher Tate <ctate@google.com>
Wed, 24 Jun 2015 23:15:48 +0000 (16:15 -0700)
committerChristopher Tate <ctate@google.com>
Fri, 26 Jun 2015 20:48:33 +0000 (13:48 -0700)
If there is no resource-named default but there is a single factory-
installed browser app, that app is made the titular default.

This also introduces a permission guard on attempts to set the
default browser or the app-link state.  These operations are now
contingent on the existing SET_PREFERRED_APPLICATIONS permission.

Bug 21778406

Change-Id: Id099bb9c4141f28917546492657cd2fba472e6b6

core/res/res/values/config.xml
core/res/res/values/symbols.xml
services/core/java/com/android/server/pm/PackageManagerService.java
services/core/java/com/android/server/pm/Settings.java

index f6cefba..9d79952 100755 (executable)
          application is desired. -->
     <string name="default_sms_application" translatable="false">com.android.mms</string>
 
+    <!-- Default web browser.  This is the package name of the application that will
+         be the default browser when the device first boots.  Afterwards the user
+         can select whatever browser app they wish to use as the default.
+
+         If this string is empty or the specified package does not exist, then
+         the behavior will be as though no app was named as an explicit default. -->
+    <string name="default_browser" translatable="false"></string>
+
     <!-- Enable/disable default bluetooth profiles:
         HSP_AG, ObexObjectPush, Audio, NAP -->
     <bool name="config_bluetooth_default_profiles">true</bool>
index 5c42d04..8bf1aac 100755 (executable)
   <java-symbol type="string" name="sipAddressTypeOther" />
   <java-symbol type="string" name="sipAddressTypeWork" />
   <java-symbol type="string" name="default_sms_application" />
+  <java-symbol type="string" name="default_browser" />
   <java-symbol type="string" name="sms_control_message" />
   <java-symbol type="string" name="sms_control_title" />
   <java-symbol type="string" name="sms_control_no" />
index 40ff3f4..d771085 100644 (file)
@@ -2191,7 +2191,8 @@ public class PackageManagerService extends IPackageManager.Stub {
             // If this is the first boot, and it is a normal boot, then
             // we need to initialize the default preferred apps.
             if (!mRestoredSettings && !onlyCore) {
-                mSettings.readDefaultPreferredAppsLPw(this, 0);
+                mSettings.applyDefaultPreferredAppsLPw(this, UserHandle.USER_OWNER);
+                applyFactoryDefaultBrowserLPw(UserHandle.USER_OWNER);
             }
 
             // If this is first boot after an OTA, and a normal boot, then
@@ -2375,13 +2376,72 @@ public class PackageManagerService extends IPackageManager.Stub {
         if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "End priming domain verifications");
     }
 
+    private void applyFactoryDefaultBrowserLPw(int userId) {
+        // The default browser app's package name is stored in a string resource,
+        // with a product-specific overlay used for vendor customization.
+        String browserPkg = mContext.getResources().getString(
+                com.android.internal.R.string.default_browser);
+        if (browserPkg != null) {
+            // non-empty string => required to be a known package
+            PackageSetting ps = mSettings.mPackages.get(browserPkg);
+            if (ps == null) {
+                Slog.e(TAG, "Product default browser app does not exist: " + browserPkg);
+                browserPkg = null;
+            } else {
+                mSettings.setDefaultBrowserPackageNameLPw(browserPkg, userId);
+            }
+        }
+
+        // Nothing valid explicitly set? Make the factory-installed browser the explicit
+        // default.  If there's more than one, just leave everything alone.
+        if (browserPkg == null) {
+            calculateDefaultBrowserLPw(userId);
+        }
+    }
+
+    private void calculateDefaultBrowserLPw(int userId) {
+        List<String> allBrowsers = resolveAllBrowserApps(userId);
+        final String browserPkg = (allBrowsers.size() == 1) ? allBrowsers.get(0) : null;
+        mSettings.setDefaultBrowserPackageNameLPw(browserPkg, userId);
+    }
+
+    private List<String> resolveAllBrowserApps(int userId) {
+        // Match all generic http: browser apps
+        Intent intent = new Intent();
+        intent.setAction(Intent.ACTION_VIEW);
+        intent.addCategory(Intent.CATEGORY_BROWSABLE);
+        intent.setData(Uri.parse("http:"));
+
+        // Resolve that intent and check that the handleAllWebDataURI boolean is set
+        List<ResolveInfo> list = queryIntentActivities(intent, null, 0, userId);
+
+        final int count = list.size();
+        List<String> result = new ArrayList<String>(count);
+        for (int i=0; i<count; i++) {
+            ResolveInfo info = list.get(i);
+            if (info.activityInfo == null
+                    || !info.handleAllWebDataURI
+                    || (info.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0
+                    || result.contains(info.activityInfo.packageName)) {
+                continue;
+            }
+            result.add(info.activityInfo.packageName);
+        }
+
+        return result;
+    }
+
     private void checkDefaultBrowser() {
         final int myUserId = UserHandle.myUserId();
         final String packageName = getDefaultBrowserPackageName(myUserId);
-        PackageInfo info = getPackageInfo(packageName, 0, myUserId);
-        if (info == null) {
-            Slog.w(TAG, "Default browser no longer installed: " + packageName);
-            setDefaultBrowserPackageName(null, myUserId);
+        if (packageName != null) {
+            PackageInfo info = getPackageInfo(packageName, 0, myUserId);
+            if (info == null) {
+                Slog.w(TAG, "Default browser no longer installed: " + packageName);
+                synchronized (mPackages) {
+                    applyFactoryDefaultBrowserLPw(myUserId);    // leaves ambiguous when > 1
+                }
+            }
         }
     }
 
@@ -4443,7 +4503,7 @@ public class PackageManagerService extends IPackageManager.Stub {
 
         synchronized (mPackages) {
             final int count = candidates.size();
-            // First, try to use the domain prefered App. Partition the candidates into four lists:
+            // First, try to use the domain preferred app. Partition the candidates into four lists:
             // one for the final results, one for the "do not use ever", one for "undefined status"
             // and finally one for "Browser App type".
             for (int n=0; n<count; n++) {
@@ -9577,6 +9637,9 @@ public class PackageManagerService extends IPackageManager.Stub {
 
     @Override
     public boolean updateIntentVerificationStatus(String packageName, int status, int userId) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
+
         boolean result = false;
         synchronized (mPackages) {
             result = mSettings.updateIntentFilterVerificationStatusLPw(packageName, status, userId);
@@ -9618,8 +9681,11 @@ public class PackageManagerService extends IPackageManager.Stub {
 
     @Override
     public boolean setDefaultBrowserPackageName(String packageName, int userId) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
+
         synchronized (mPackages) {
-            boolean result = mSettings.setDefaultBrowserPackageNameLPr(packageName, userId);
+            boolean result = mSettings.setDefaultBrowserPackageNameLPw(packageName, userId);
             if (packageName != null) {
                 result |= updateIntentVerificationStatus(packageName,
                         PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS,
@@ -13379,15 +13445,15 @@ public class PackageManagerService extends IPackageManager.Stub {
 
     @Override
     public void resetPreferredActivities(int userId) {
-        /* TODO: Actually use userId. Why is it being passed in? */
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
         // writer
         synchronized (mPackages) {
-            int user = UserHandle.getCallingUserId();
-            clearPackagePreferredActivitiesLPw(null, user);
-            mSettings.readDefaultPreferredAppsLPw(this, user);
-            scheduleWritePackageRestrictionsLocked(user);
+            clearPackagePreferredActivitiesLPw(null, userId);
+            mSettings.applyDefaultPreferredAppsLPw(this, userId);
+            applyFactoryDefaultBrowserLPw(userId);
+
+            scheduleWritePackageRestrictionsLocked(userId);
         }
     }
 
@@ -15449,6 +15515,7 @@ public class PackageManagerService extends IPackageManager.Stub {
         if (mInstaller != null) {
             mInstaller.createUserConfig(userHandle);
             mSettings.createNewUserLILPw(this, mInstaller, userHandle, path);
+            applyFactoryDefaultBrowserLPw(userHandle);
         }
     }
 
index dcd7799..58d703a 100644 (file)
@@ -1130,7 +1130,7 @@ final class Settings {
         return result;
     }
 
-    boolean setDefaultBrowserPackageNameLPr(String packageName, int userId) {
+    boolean setDefaultBrowserPackageNameLPw(String packageName, int userId) {
         if (userId == UserHandle.USER_ALL) {
             return false;
         }
@@ -2710,7 +2710,7 @@ final class Settings {
         return true;
     }
 
-    void readDefaultPreferredAppsLPw(PackageManagerService service, int userId) {
+    void applyDefaultPreferredAppsLPw(PackageManagerService service, int userId) {
         // First pull data from any pre-installed apps.
         for (PackageSetting ps : mPackages.values()) {
             if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0 && ps.pkg != null
@@ -3618,7 +3618,7 @@ final class Settings {
                     UserHandle.getUid(userHandle, ps.appId), userHandle,
                     ps.pkg.applicationInfo.seinfo);
         }
-        readDefaultPreferredAppsLPw(service, userHandle);
+        applyDefaultPreferredAppsLPw(service, userHandle);
         writePackageRestrictionsLPr(userHandle);
         writePackageListLPr(userHandle);
     }