Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/DefaultBrowserInfo.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/DefaultBrowserInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/DefaultBrowserInfo.java |
| index 5477da8e5d919194e7702f6de8d1c44b736d213d..30b0045bf77775ac8f965dbe652c6f079a3bfd9e 100644 |
| --- a/chrome/android/java/src/org/chromium/chrome/browser/DefaultBrowserInfo.java |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/DefaultBrowserInfo.java |
| @@ -6,30 +6,77 @@ package org.chromium.chrome.browser; |
| import android.content.Context; |
| import android.content.Intent; |
| +import android.content.pm.ApplicationInfo; |
| import android.content.pm.PackageManager; |
| import android.content.pm.ResolveInfo; |
| import android.net.Uri; |
| import android.os.AsyncTask; |
| +import android.support.annotation.IntDef; |
| +import android.text.TextUtils; |
| import org.chromium.base.BuildInfo; |
| import org.chromium.base.ContextUtils; |
| +import org.chromium.base.library_loader.LibraryProcessType; |
| +import org.chromium.base.metrics.RecordHistogram; |
| import org.chromium.chrome.R; |
| import org.chromium.chrome.browser.preferences.ChromePreferenceManager; |
| +import org.chromium.content.browser.BrowserStartupController; |
| import java.util.ArrayList; |
| +import java.util.HashSet; |
| +import java.util.List; |
| +import java.util.Set; |
| import java.util.concurrent.ExecutionException; |
| +import java.util.concurrent.RejectedExecutionException; |
| /** |
| * A utility class for querying information about the default browser setting. |
| */ |
| -public class DefaultBrowserInfo { |
| +public final class DefaultBrowserInfo { |
| private static final String SAMPLE_URL = "https://www.madeupdomainforcheck123.com/"; |
| + /** |
| + * A list of potential default browser states. Please keep this in sync with |
| + * MobileDefaultBrowserState in histograms.xml. |
| + */ |
| + @IntDef({ |
| + MobileDefaultBrowserState.NO_DEFAULT, |
| + MobileDefaultBrowserState.CHROME_SYSTEM_DEFAULT, |
| + MobileDefaultBrowserState.CHROME_INSTALLED_DEFAULT, |
| + MobileDefaultBrowserState.OTHER_SYSTEM_DEFAULT, |
| + MobileDefaultBrowserState.OTHER_INSTALLED_DEFAULT, |
| + |
| + MobileDefaultBrowserState.BOUNDARY, |
| + }) |
| + private @interface MobileDefaultBrowserState { |
| + int NO_DEFAULT = 0; |
|
nyquist
2017/04/27 05:20:06
clang-format!! y u no make sense!?
|
| + int CHROME_SYSTEM_DEFAULT = 1; |
| + int CHROME_INSTALLED_DEFAULT = 2; |
| + int OTHER_SYSTEM_DEFAULT = 3; |
| + int OTHER_INSTALLED_DEFAULT = 4; |
| + int BOUNDARY = 5; |
| + } |
| + |
| + /** |
| + * Helper class for passing information about the system's default browser settings back from a |
| + * worker task. |
| + */ |
| + private static class DefaultInfo { |
| + public boolean isChromeDefault; |
| + public boolean isChromeSystem; |
| + public boolean isDefaultSystem; |
| + public boolean hasDefault; |
| + public int browserCount; |
| + } |
| + |
| /** A lock to synchronize background tasks to retrieve browser information. */ |
| private static final Object sDirCreationLock = new Object(); |
| private static AsyncTask<Void, Void, ArrayList<String>> sDefaultBrowserFetcher; |
| + /** Don't instantiate me. */ |
| + private DefaultBrowserInfo() {} |
| + |
| /** |
| * Initialize an AsyncTask for getting menu title of opening a link in default browser. |
| */ |
| @@ -102,4 +149,90 @@ public class DefaultBrowserInfo { |
| R.string.menu_open_in_product_default); |
| } |
| } |
| + |
| + /** |
| + * Log statistics about the current default browser to UMA. |
| + */ |
| + public static void logDefaultBrowserStats() { |
| + assert BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER) |
| + .isStartupSuccessfullyCompleted(); |
| + |
| + try { |
| + new AsyncTask<Context, Void, DefaultInfo>() { |
| + @Override |
| + protected DefaultInfo doInBackground(Context... params) { |
| + Context context = params[0]; |
| + |
| + PackageManager pm = context.getPackageManager(); |
| + |
| + Intent intent = new Intent(Intent.ACTION_VIEW); |
| + intent.setData(Uri.parse(SAMPLE_URL)); |
| + |
| + DefaultInfo info = new DefaultInfo(); |
| + |
| + // Query the default handler first. |
| + ResolveInfo defaultRi = pm.resolveActivity(intent, 0); |
| + if (defaultRi != null && defaultRi.match != 0) { |
| + info.hasDefault = true; |
| + info.isChromeDefault = isSamePackage(context, defaultRi); |
| + info.isDefaultSystem = isSystemPackage(defaultRi); |
| + } |
| + |
| + // Query all other intent handlers. |
| + Set<String> uniquePackages = new HashSet<>(); |
| + List<ResolveInfo> ris = |
| + pm.queryIntentActivities(intent, PackageManager.MATCH_ALL); |
| + for (ResolveInfo ri : ris) { |
| + if (isSamePackage(context, ri)) info.isChromeSystem = isSystemPackage(ri); |
|
nyquist
2017/04/27 05:20:06
Optional nit: Is isChromeSystem really necessary?
David Trainor- moved to gerrit
2017/04/28 01:03:18
Fair point!
|
| + uniquePackages.add(ri.activityInfo.applicationInfo.packageName); |
| + } |
| + |
| + info.browserCount = uniquePackages.size(); |
| + |
| + return info; |
| + } |
| + |
| + @Override |
| + protected void onPostExecute(DefaultInfo info) { |
| + if (info == null) return; |
| + |
| + RecordHistogram.recordCount100Histogram( |
| + getDefaultBrowserCountUmaName(info), info.browserCount); |
| + RecordHistogram.recordEnumeratedHistogram("Mobile.DefaultBrowser.State", |
| + getDefaultBrowserUmaState(info), MobileDefaultBrowserState.BOUNDARY); |
| + } |
| + } |
| + .executeOnExecutor( |
| + AsyncTask.THREAD_POOL_EXECUTOR, ContextUtils.getApplicationContext()); |
| + } catch (RejectedExecutionException ex) { |
| + // Fail silently here since this is not a critical task. |
| + } |
| + } |
| + |
| + private static String getDefaultBrowserCountUmaName(DefaultInfo info) { |
| + if (!info.hasDefault) return "Mobile.DefaultBrowser.BrowserCount.NoDefault"; |
| + if (info.isChromeDefault) return "Mobile.DefaultBrowser.BrowserCount.ChromeDefault"; |
| + return "Mobile.DefaultBrowser.BrowserCount.OtherDefault"; |
| + } |
| + |
| + private static @MobileDefaultBrowserState int getDefaultBrowserUmaState(DefaultInfo info) { |
| + if (!info.hasDefault) return MobileDefaultBrowserState.NO_DEFAULT; |
| + |
| + if (info.isChromeDefault) { |
| + if (info.isChromeSystem) return MobileDefaultBrowserState.CHROME_SYSTEM_DEFAULT; |
| + return MobileDefaultBrowserState.CHROME_INSTALLED_DEFAULT; |
| + } |
| + |
| + if (info.isDefaultSystem) return MobileDefaultBrowserState.OTHER_SYSTEM_DEFAULT; |
| + return MobileDefaultBrowserState.OTHER_INSTALLED_DEFAULT; |
| + } |
| + |
| + private static boolean isSamePackage(Context context, ResolveInfo info) { |
| + return TextUtils.equals( |
| + context.getPackageName(), info.activityInfo.applicationInfo.packageName); |
| + } |
| + |
| + private static boolean isSystemPackage(ResolveInfo info) { |
| + return (info.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; |
| + } |
| } |