Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/InstantAppsHandler.java

Issue 2123393002: Rename AppLinkHandler to InstantAppsHandler. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Make test inner class static Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/InstantAppsHandler.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/InstantAppsHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/InstantAppsHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..3515dc84b7f0f7743c628bdbea66fdeba6a102f9
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/InstantAppsHandler.java
@@ -0,0 +1,225 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.StrictMode;
+import android.os.SystemClock;
+import android.provider.Browser;
+
+import org.chromium.base.CommandLine;
+import org.chromium.base.FieldTrialList;
+import org.chromium.base.Log;
+import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl;
+import org.chromium.chrome.browser.metrics.LaunchMetrics.TimesHistogramSample;
+import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
+import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
+import org.chromium.chrome.browser.util.IntentUtils;
+
+import java.util.concurrent.TimeUnit;
+
+/** A launcher for Instant Apps. */
+public class InstantAppsHandler {
+ private static final String TAG = "InstantAppsHandler";
+
+ private static final Object INSTANCE_LOCK = new Object();
+ private static InstantAppsHandler sInstance;
+
+ private static final String DO_NOT_LAUNCH_EXTRA =
+ "com.google.android.gms.instantapps.DO_NOT_LAUNCH_INSTANT_APP";
+
+ private static final String CUSTOM_APPS_INSTANT_APP_EXTRA =
+ "android.support.customtabs.extra.EXTRA_ENABLE_INSTANT_APPS";
+
+ private static final String INSTANT_APP_START_TIME_EXTRA =
+ "org.chromium.chrome.INSTANT_APP_START_TIME";
+
+ /** Finch experiment name. */
+ private static final String INSTANT_APPS_EXPERIMENT_NAME = "InstantApps";
+
+ /** Finch experiment group which is enabled for instant apps. */
+ private static final String INSTANT_APPS_ENABLED_ARM = "InstantAppsEnabled";
+
+ /** Finch experiment group which is disabled for instant apps. */
+ private static final String INSTANT_APPS_DISABLED_ARM = "InstantAppsDisabled";
+
+ /** A histogram to record how long each handleIntent() call took. */
+ private static final TimesHistogramSample sHandleIntentDuration = new TimesHistogramSample(
+ "Android.InstantApps.HandleIntentDuration", TimeUnit.MILLISECONDS);
+
+ /** A histogram to record how long the fallback intent roundtrip was. */
+ private static final TimesHistogramSample sFallbackIntentTimes = new TimesHistogramSample(
+ "Android.InstantApps.FallbackDuration", TimeUnit.MILLISECONDS);
+
+ /** A histogram to record how long the GMS Core API call took. */
+ private static final TimesHistogramSample sInstantAppsApiCallTimes = new TimesHistogramSample(
+ "Android.InstantApps.ApiCallDuration", TimeUnit.MILLISECONDS);
+
+
+ /** @return The singleton instance of {@link InstantAppsHandler}. */
+ public static InstantAppsHandler getInstance(ChromeApplication application) {
+ synchronized (INSTANCE_LOCK) {
+ if (sInstance == null) {
+ sInstance = application.createInstantAppsHandler();
+ }
+ }
+ return sInstance;
+ }
+
+ /**
+ * Check the cached value to figure out if the feature is enabled. We have to use the cached
+ * value because native library hasn't yet been loaded.
+ * @param context The application context.
+ * @return Whether the feature is enabled.
+ */
+ private boolean isEnabled(Context context) {
+ // Will go away once the feature is enabled for everyone by default.
+ StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+ try {
+ return ChromePreferenceManager.getInstance(context).getCachedInstantAppsEnabled();
+ } finally {
+ StrictMode.setThreadPolicy(oldPolicy);
+ }
+ }
+
+ /**
+ * Record how long the handleIntent() method took.
+ * @param startTime The timestamp for handleIntent start time.
+ */
+ private void recordHandleIntentDuration(long startTime) {
+ sHandleIntentDuration.record(SystemClock.elapsedRealtime() - startTime);
+ }
+
+ /**
+ * Record the amount of time spent in the instant apps API call.
+ * @param startTime The time at which we started doing computations.
+ */
+ protected void recordInstantAppsApiCallTime(long startTime) {
+ sInstantAppsApiCallTimes.record(SystemClock.elapsedRealtime() - startTime);
+ }
+
+ /**
+ * In the case Chrome is called through the fallback mechanism from Instant Apps, record the
+ * amount of time the whole trip took.
+ * @param intent The current intent.
+ */
+ private void maybeRecordFallbackDuration(Intent intent) {
+ if (intent.hasExtra(INSTANT_APP_START_TIME_EXTRA)) {
+ Long startTime = intent.getLongExtra(INSTANT_APP_START_TIME_EXTRA, 0);
+ if (startTime != 0) {
+ sFallbackIntentTimes.record(SystemClock.elapsedRealtime() - startTime);
+ }
+ }
+ }
+
+ /**
+ * Cache whether the Instant Apps feature is enabled.
+ * This should only be called with the native library loaded.
+ */
+ public void cacheInstantAppsEnabled(Context context) {
+ boolean isEnabled = false;
+ boolean wasEnabled = isEnabled(context);
+ CommandLine instance = CommandLine.getInstance();
+ if (instance.hasSwitch(ChromeSwitches.DISABLE_APP_LINK)) {
+ isEnabled = false;
+ } else if (instance.hasSwitch(ChromeSwitches.ENABLE_APP_LINK)) {
+ isEnabled = true;
+ } else {
+ String experiment = FieldTrialList.findFullName(INSTANT_APPS_EXPERIMENT_NAME);
+ if (INSTANT_APPS_DISABLED_ARM.equals(experiment)) {
+ isEnabled = false;
+ } else if (INSTANT_APPS_ENABLED_ARM.equals(experiment)) {
+ isEnabled = true;
+ }
+ }
+
+ if (isEnabled != wasEnabled) {
+ ChromePreferenceManager.getInstance(context).setCachedInstantAppsEnabled(isEnabled);
+ }
+ }
+
+ /** Handle incoming intent. */
+ public boolean handleIncomingIntent(Context context, Intent intent,
+ boolean isCustomTabsIntent) {
+ long startTimeStamp = SystemClock.elapsedRealtime();
+ boolean result = handleIncomingIntentInternal(context, intent, isCustomTabsIntent,
+ startTimeStamp);
+ recordHandleIntentDuration(startTimeStamp);
+ return result;
+ }
+
+ private boolean handleIncomingIntentInternal(
+ Context context, Intent intent, boolean isCustomTabsIntent, long startTime) {
+ if (!isEnabled(context)
+ || IntentUtils.safeGetBooleanExtra(intent, DO_NOT_LAUNCH_EXTRA, false)
+ || IntentUtils.safeGetBooleanExtra(
+ intent, IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, false)
+ || (isCustomTabsIntent && !IntentUtils.safeGetBooleanExtra(
+ intent, CUSTOM_APPS_INSTANT_APP_EXTRA, false))
+ || DataReductionProxySettings.isEnabledBeforeNativeLoad(context)
+ || isIntentFromChrome(context, intent)
+ || (intent.getAction() != Intent.ACTION_VIEW)) {
+ Log.i(TAG, "Not handling with Instant Apps");
+ return false;
+ }
+
+ maybeRecordFallbackDuration(intent);
+
+ // Used to search for the intent handlers. Needs null component to return correct results.
+ Intent intentCopy = new Intent(intent);
+ intentCopy.setComponent(null);
+
+ if (!(isCustomTabsIntent || isChromeDefaultHandler(context))
+ || ExternalNavigationDelegateImpl.isPackageSpecializedHandler(
+ context, null, intentCopy)) {
+ // Chrome is not the default browser or a specialized handler exists.
+ Log.i(TAG, "Not handling with Instant Apps because Chrome is not default or "
+ + "there's a specialized handler");
+ return false;
+ }
+
+ Intent callbackIntent = new Intent(intent);
+ callbackIntent.putExtra(DO_NOT_LAUNCH_EXTRA, true);
+ callbackIntent.putExtra(INSTANT_APP_START_TIME_EXTRA, startTime);
+
+ return tryLaunchingInstantApp(context, intent, isCustomTabsIntent, callbackIntent);
+ }
+
+ /**
+ * Attempts to launch an Instant App, if possible.
+ * @param context The activity context.
+ * @param intent The incoming intent.
+ * @param isCustomTabsIntent Whether the intent is for a CustomTab.
+ * @param fallbackIntent The intent that will be launched by Instant Apps in case of failure to
+ * load.
+ * @return Whether an Instant App was launched.
+ */
+ protected boolean tryLaunchingInstantApp(
+ Context context, Intent intent, boolean isCustomTabsIntent, Intent fallbackIntent) {
+ return false;
+ }
+
+ /**
+ * @return Whether the intent was fired from Chrome. This happens when the user gets a
+ * disambiguation dialog and chooses to stay in Chrome.
+ */
+ private boolean isIntentFromChrome(Context context, Intent intent) {
+ return context.getPackageName().equals(IntentUtils.safeGetStringExtra(
+ intent, Browser.EXTRA_APPLICATION_ID))
+ // We shouldn't leak internal intents with authentication tokens
+ || IntentHandler.wasIntentSenderChrome(intent, context);
+ }
+
+ /** @return Whether Chrome is the default browser on the device. */
+ private boolean isChromeDefaultHandler(Context context) {
+ StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+ try {
+ return ChromePreferenceManager.getInstance(context).getCachedChromeDefaultBrowser();
+ } finally {
+ StrictMode.setThreadPolicy(oldPolicy);
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698