| 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..ade647d7071acb690a9af43f7001d2414ec7e9f5 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,78 @@ 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. To add a type to this list please update
|
| + * MobileDefaultBrowserState in histograms.xml and make sure to keep this list in sync.
|
| + * Additions should be treated as APPEND ONLY to keep the UMA metric semantics the same over
|
| + * time.
|
| + */
|
| + @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;
|
| + 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 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 +150,89 @@ 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) {
|
| + 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.isDefaultSystem) 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;
|
| + }
|
| }
|
|
|