Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser.customtabs; | 5 package org.chromium.chrome.browser.customtabs; |
| 6 | 6 |
| 7 import android.app.ActivityManager; | 7 import android.app.ActivityManager; |
| 8 import android.app.Application; | 8 import android.app.Application; |
| 9 import android.app.PendingIntent; | 9 import android.app.PendingIntent; |
| 10 import android.content.Context; | 10 import android.content.Context; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 import android.os.SystemClock; | 21 import android.os.SystemClock; |
| 22 import android.support.customtabs.CustomTabsCallback; | 22 import android.support.customtabs.CustomTabsCallback; |
| 23 import android.support.customtabs.CustomTabsIntent; | 23 import android.support.customtabs.CustomTabsIntent; |
| 24 import android.support.customtabs.CustomTabsService; | 24 import android.support.customtabs.CustomTabsService; |
| 25 import android.support.customtabs.CustomTabsSessionToken; | 25 import android.support.customtabs.CustomTabsSessionToken; |
| 26 import android.text.TextUtils; | 26 import android.text.TextUtils; |
| 27 import android.util.Pair; | 27 import android.util.Pair; |
| 28 import android.widget.RemoteViews; | 28 import android.widget.RemoteViews; |
| 29 | 29 |
| 30 import org.chromium.base.CommandLine; | 30 import org.chromium.base.CommandLine; |
| 31 import org.chromium.base.ContextUtils; | |
| 31 import org.chromium.base.Log; | 32 import org.chromium.base.Log; |
| 32 import org.chromium.base.ThreadUtils; | 33 import org.chromium.base.ThreadUtils; |
| 33 import org.chromium.base.TimeUtils; | 34 import org.chromium.base.TimeUtils; |
| 34 import org.chromium.base.TraceEvent; | 35 import org.chromium.base.TraceEvent; |
| 35 import org.chromium.base.VisibleForTesting; | 36 import org.chromium.base.VisibleForTesting; |
| 36 import org.chromium.base.annotations.SuppressFBWarnings; | 37 import org.chromium.base.annotations.SuppressFBWarnings; |
| 37 import org.chromium.base.library_loader.ProcessInitException; | 38 import org.chromium.base.library_loader.ProcessInitException; |
| 38 import org.chromium.base.metrics.RecordHistogram; | 39 import org.chromium.base.metrics.RecordHistogram; |
| 39 import org.chromium.chrome.R; | 40 import org.chromium.chrome.R; |
| 40 import org.chromium.chrome.browser.AppHooks; | 41 import org.chromium.chrome.browser.AppHooks; |
| 41 import org.chromium.chrome.browser.ChromeApplication; | 42 import org.chromium.chrome.browser.ChromeApplication; |
| 42 import org.chromium.chrome.browser.ChromeFeatureList; | 43 import org.chromium.chrome.browser.ChromeFeatureList; |
| 43 import org.chromium.chrome.browser.IntentHandler; | 44 import org.chromium.chrome.browser.IntentHandler; |
| 44 import org.chromium.chrome.browser.WarmupManager; | 45 import org.chromium.chrome.browser.WarmupManager; |
| 45 import org.chromium.chrome.browser.device.DeviceClassManager; | 46 import org.chromium.chrome.browser.device.DeviceClassManager; |
| 46 import org.chromium.chrome.browser.init.ChromeBrowserInitializer; | 47 import org.chromium.chrome.browser.init.ChromeBrowserInitializer; |
| 47 import org.chromium.chrome.browser.metrics.PageLoadMetrics; | 48 import org.chromium.chrome.browser.metrics.PageLoadMetrics; |
| 48 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; | 49 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; |
| 49 import org.chromium.chrome.browser.preferences.PrefServiceBridge; | 50 import org.chromium.chrome.browser.preferences.PrefServiceBridge; |
| 50 import org.chromium.chrome.browser.prerender.ExternalPrerenderHandler; | 51 import org.chromium.chrome.browser.prerender.ExternalPrerenderHandler; |
| 51 import org.chromium.chrome.browser.profiles.Profile; | 52 import org.chromium.chrome.browser.profiles.Profile; |
| 52 import org.chromium.chrome.browser.tab.Tab; | 53 import org.chromium.chrome.browser.tab.Tab; |
| 53 import org.chromium.chrome.browser.util.IntentUtils; | 54 import org.chromium.chrome.browser.util.IntentUtils; |
| 54 import org.chromium.chrome.browser.util.UrlUtilities; | 55 import org.chromium.chrome.browser.util.UrlUtilities; |
| 55 import org.chromium.content.browser.ChildProcessLauncherHelper; | 56 import org.chromium.content.browser.ChildProcessLauncherHelper; |
| 56 import org.chromium.content_public.browser.LoadUrlParams; | 57 import org.chromium.content_public.browser.LoadUrlParams; |
| 57 import org.chromium.content_public.browser.WebContents; | 58 import org.chromium.content_public.browser.WebContents; |
| 58 import org.chromium.content_public.common.Referrer; | 59 import org.chromium.content_public.common.Referrer; |
| 60 import org.chromium.net.GURLUtils; | |
| 59 | 61 |
| 60 import java.io.BufferedReader; | 62 import java.io.BufferedReader; |
| 61 import java.io.FileReader; | 63 import java.io.FileReader; |
| 62 import java.io.IOException; | 64 import java.io.IOException; |
| 63 import java.util.List; | 65 import java.util.List; |
| 64 import java.util.concurrent.Callable; | 66 import java.util.concurrent.Callable; |
| 65 import java.util.concurrent.ExecutionException; | 67 import java.util.concurrent.ExecutionException; |
| 66 import java.util.concurrent.atomic.AtomicBoolean; | 68 import java.util.concurrent.atomic.AtomicBoolean; |
| 67 import java.util.concurrent.atomic.AtomicReference; | 69 import java.util.concurrent.atomic.AtomicReference; |
| 68 | 70 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 109 static final String DEBUG_OVERRIDE_KEY = | 111 static final String DEBUG_OVERRIDE_KEY = |
| 110 "android.support.customtabs.maylaunchurl.DEBUG_OVERRIDE"; | 112 "android.support.customtabs.maylaunchurl.DEBUG_OVERRIDE"; |
| 111 private static final int NO_OVERRIDE = 0; | 113 private static final int NO_OVERRIDE = 0; |
| 112 @VisibleForTesting | 114 @VisibleForTesting |
| 113 static final int NO_PRERENDERING = 1; | 115 static final int NO_PRERENDERING = 1; |
| 114 @VisibleForTesting | 116 @VisibleForTesting |
| 115 static final int PREFETCH_ONLY = 2; | 117 static final int PREFETCH_ONLY = 2; |
| 116 @VisibleForTesting | 118 @VisibleForTesting |
| 117 static final int HIDDEN_TAB = 3; | 119 static final int HIDDEN_TAB = 3; |
| 118 | 120 |
| 121 @VisibleForTesting | |
| 122 static final String REDIRECT_ENDPOINT_KEY = "android.support.customtabs.REDI RECT_ENDPOINT"; | |
|
Yusuf
2017/07/06 06:34:42
some todo around moving this to support lib?
Benoit L
2017/07/07 11:30:56
Done.
| |
| 123 | |
| 119 private static AtomicReference<CustomTabsConnection> sInstance = new AtomicR eference<>(); | 124 private static AtomicReference<CustomTabsConnection> sInstance = new AtomicR eference<>(); |
| 120 | 125 |
| 121 /** Holds the parameters for the current speculation. */ | 126 /** Holds the parameters for the current speculation. */ |
| 122 @VisibleForTesting | 127 @VisibleForTesting |
| 123 static final class SpeculationParams { | 128 static final class SpeculationParams { |
| 124 @VisibleForTesting | 129 @VisibleForTesting |
| 125 static final int NO_SPECULATION = 0; | 130 static final int NO_SPECULATION = 0; |
| 126 @VisibleForTesting | 131 @VisibleForTesting |
| 127 static final int PREFETCH = 1; | 132 static final int PREFETCH = 1; |
| 128 @VisibleForTesting | 133 @VisibleForTesting |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 339 } | 344 } |
| 340 } finally { | 345 } finally { |
| 341 TraceEvent.end("CustomTabsConnection.warmupInternal"); | 346 TraceEvent.end("CustomTabsConnection.warmupInternal"); |
| 342 } | 347 } |
| 343 mWarmupHasBeenFinished.set(true); | 348 mWarmupHasBeenFinished.set(true); |
| 344 } | 349 } |
| 345 }); | 350 }); |
| 346 return true; | 351 return true; |
| 347 } | 352 } |
| 348 | 353 |
| 349 /** @return the URL converted to string, or null if it's invalid. */ | 354 /** @return the URL or null if it's invalid. */ |
| 350 private static String checkAndConvertUri(Uri uri) { | 355 private boolean isValid(Uri uri) { |
| 351 if (uri == null) return null; | 356 if (uri == null) return false; |
| 352 // Don't do anything for unknown schemes. Not having a scheme is allowed , as we allow | 357 // Don't do anything for unknown schemes. Not having a scheme is allowed , as we allow |
| 353 // "www.example.com". | 358 // "www.example.com". |
| 354 String scheme = uri.normalizeScheme().getScheme(); | 359 String scheme = uri.normalizeScheme().getScheme(); |
| 355 boolean allowedScheme = scheme == null || scheme.equals("http") || schem e.equals("https"); | 360 boolean allowedScheme = scheme == null || scheme.equals("http") || schem e.equals("https"); |
| 356 if (!allowedScheme) return null; | 361 if (!allowedScheme) return false; |
| 357 return uri.toString(); | 362 return true; |
| 358 } | 363 } |
| 359 | 364 |
| 360 /** | 365 /** |
| 361 * High confidence mayLaunchUrl() call, that is: | 366 * High confidence mayLaunchUrl() call, that is: |
| 362 * - Tries to prerender if possible. | 367 * - Tries to prerender if possible. |
| 363 * - An empty URL cancels the current prerender if any. | 368 * - An empty URL cancels the current prerender if any. |
| 364 * - If prerendering is not possible, makes sure that there is a spare rende rer. | 369 * - If prerendering is not possible, makes sure that there is a spare rende rer. |
| 365 */ | 370 */ |
| 366 private void highConfidenceMayLaunchUrl(CustomTabsSessionToken session, | 371 private void highConfidenceMayLaunchUrl(CustomTabsSessionToken session, |
| 367 int uid, String url, Bundle extras, List<Bundle> otherLikelyBundles) { | 372 int uid, String url, Bundle extras, List<Bundle> otherLikelyBundles) { |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 398 if (likelyBundles == null) return false; | 403 if (likelyBundles == null) return false; |
| 399 WarmupManager warmupManager = WarmupManager.getInstance(); | 404 WarmupManager warmupManager = WarmupManager.getInstance(); |
| 400 Profile profile = Profile.getLastUsedProfile(); | 405 Profile profile = Profile.getLastUsedProfile(); |
| 401 for (Bundle bundle : likelyBundles) { | 406 for (Bundle bundle : likelyBundles) { |
| 402 Uri uri; | 407 Uri uri; |
| 403 try { | 408 try { |
| 404 uri = IntentUtils.safeGetParcelable(bundle, CustomTabsService.KE Y_URL); | 409 uri = IntentUtils.safeGetParcelable(bundle, CustomTabsService.KE Y_URL); |
| 405 } catch (ClassCastException e) { | 410 } catch (ClassCastException e) { |
| 406 continue; | 411 continue; |
| 407 } | 412 } |
| 408 String url = checkAndConvertUri(uri); | 413 if (isValid(uri)) { |
| 409 if (url != null) { | 414 warmupManager.maybePreconnectUrlAndSubResources(profile, uri.toS tring()); |
| 410 warmupManager.maybePreconnectUrlAndSubResources(profile, url); | |
| 411 atLeastOneUrl = true; | 415 atLeastOneUrl = true; |
| 412 } | 416 } |
| 413 } | 417 } |
| 414 return atLeastOneUrl; | 418 return atLeastOneUrl; |
| 415 } | 419 } |
| 416 | 420 |
| 417 public boolean mayLaunchUrl(CustomTabsSessionToken session, Uri url, Bundle extras, | 421 public boolean mayLaunchUrl(CustomTabsSessionToken session, Uri url, Bundle extras, |
| 418 List<Bundle> otherLikelyBundles) { | 422 List<Bundle> otherLikelyBundles) { |
| 419 try { | 423 try { |
| 420 TraceEvent.begin("CustomTabsConnection.mayLaunchUrl"); | 424 TraceEvent.begin("CustomTabsConnection.mayLaunchUrl"); |
| 421 boolean success = mayLaunchUrlInternal(session, url, extras, otherLi kelyBundles); | 425 boolean success = mayLaunchUrlInternal(session, url, extras, otherLi kelyBundles); |
| 422 logCall("mayLaunchUrl(" + url + ")", success); | 426 logCall("mayLaunchUrl(" + url + ")", success); |
| 423 return success; | 427 return success; |
| 424 } finally { | 428 } finally { |
| 425 TraceEvent.end("CustomTabsConnection.mayLaunchUrl"); | 429 TraceEvent.end("CustomTabsConnection.mayLaunchUrl"); |
| 426 } | 430 } |
| 427 } | 431 } |
| 428 | 432 |
| 429 private boolean mayLaunchUrlInternal(final CustomTabsSessionToken session, U ri url, | 433 private boolean mayLaunchUrlInternal(final CustomTabsSessionToken session, U ri url, |
| 430 final Bundle extras, final List<Bundle> otherLikelyBundles) { | 434 final Bundle extras, final List<Bundle> otherLikelyBundles) { |
| 431 final boolean lowConfidence = | 435 final boolean lowConfidence = |
| 432 (url == null || TextUtils.isEmpty(url.toString())) && otherLikel yBundles != null; | 436 (url == null || TextUtils.isEmpty(url.toString())) && otherLikel yBundles != null; |
| 433 final String urlString = checkAndConvertUri(url); | 437 final String urlString = isValid(url) ? url.toString() : null; |
| 434 if (url != null && urlString == null && !lowConfidence) return false; | 438 if (url != null && urlString == null && !lowConfidence) return false; |
| 435 | 439 |
| 436 // Things below need the browser process to be initialized. | 440 // Things below need the browser process to be initialized. |
| 437 | 441 |
| 438 // Forbids warmup() from creating a spare renderer, as prerendering woul dn't reuse | 442 // Forbids warmup() from creating a spare renderer, as prerendering woul dn't reuse |
| 439 // it. Checking whether prerendering is enabled requires the native libr ary to be loaded, | 443 // it. Checking whether prerendering is enabled requires the native libr ary to be loaded, |
| 440 // which is not necessarily the case yet. | 444 // which is not necessarily the case yet. |
| 441 if (!warmupInternal(false)) return false; // Also does the foreground ch eck. | 445 if (!warmupInternal(false)) return false; // Also does the foreground ch eck. |
| 442 | 446 |
| 443 final int uid = Binder.getCallingUid(); | 447 final int uid = Binder.getCallingUid(); |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 718 SPECULATION_STATUS_ON_SWAP_BACKGROUND_TAB_NOT_MATCHE D); | 722 SPECULATION_STATUS_ON_SWAP_BACKGROUND_TAB_NOT_MATCHE D); |
| 719 tab.destroy(); | 723 tab.destroy(); |
| 720 } | 724 } |
| 721 } | 725 } |
| 722 } finally { | 726 } finally { |
| 723 TraceEvent.end("CustomTabsConnection.takeHiddenTab"); | 727 TraceEvent.end("CustomTabsConnection.takeHiddenTab"); |
| 724 } | 728 } |
| 725 return null; | 729 return null; |
| 726 } | 730 } |
| 727 | 731 |
| 732 /** | |
| 733 * Called when an intent is handled by either an existing or a new CustomTab Activity. | |
| 734 * | |
| 735 * @param session Session extracted from the intent. | |
| 736 * @param url URL extracted from the intent. | |
| 737 * @param intent incoming intent. | |
| 738 */ | |
| 739 void onHandledIntent(CustomTabsSessionToken session, String url, Intent inte nt) { | |
| 740 // For the preconnection to not be a no-op, we need more than just the n ative library. | |
| 741 Context context = ContextUtils.getApplicationContext(); | |
| 742 if (!ChromeBrowserInitializer.getInstance(context).hasNativeInitializati onCompleted()) { | |
| 743 return; | |
| 744 } | |
| 745 if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_REDIRECT_PRECONNE CT)) return; | |
| 746 | |
| 747 // Conditions: | |
| 748 // - There is a valid redirect endpoint. | |
| 749 // - The URL's origin is first party with respect to the app. | |
| 750 Uri redirectEndpoint = intent.getParcelableExtra(REDIRECT_ENDPOINT_KEY); | |
|
Yusuf
2017/07/06 06:34:41
does it make sense to have this logic be in Custom
Benoit L
2017/07/07 11:30:56
This talks to ClientManager, and also I find it co
| |
| 751 if (redirectEndpoint == null || !isValid(redirectEndpoint)) return; | |
| 752 | |
| 753 String origin = GURLUtils.getOrigin(url); | |
| 754 if (origin == null) return; | |
| 755 if (!mClientManager.isFirstPartyOriginForSession(session, Uri.parse(orig in))) return; | |
|
Yusuf
2017/07/06 06:34:41
Going back all the way to how we handle isValidOri
Benoit L
2017/07/07 11:30:55
That would be a neat solution indeed.
However it
| |
| 756 | |
| 757 WarmupManager.getInstance().maybePreconnectUrlAndSubResources( | |
| 758 Profile.getLastUsedProfile(), redirectEndpoint.toString()); | |
|
Yusuf
2017/07/06 06:34:41
getLastUsedProfile().getOriginalProfile() to avoid
Benoit L
2017/07/07 11:30:56
Thanks!
Done.
| |
| 759 } | |
| 760 | |
| 728 /** See {@link ClientManager#getReferrerForSession(CustomTabsSessionToken)} */ | 761 /** See {@link ClientManager#getReferrerForSession(CustomTabsSessionToken)} */ |
| 729 public Referrer getReferrerForSession(CustomTabsSessionToken session) { | 762 public Referrer getReferrerForSession(CustomTabsSessionToken session) { |
| 730 return mClientManager.getReferrerForSession(session); | 763 return mClientManager.getReferrerForSession(session); |
| 731 } | 764 } |
| 732 | 765 |
| 733 /** @see ClientManager#shouldHideDomainForSession(CustomTabsSessionToken) */ | 766 /** @see ClientManager#shouldHideDomainForSession(CustomTabsSessionToken) */ |
| 734 public boolean shouldHideDomainForSession(CustomTabsSessionToken session) { | 767 public boolean shouldHideDomainForSession(CustomTabsSessionToken session) { |
| 735 return mClientManager.shouldHideDomainForSession(session); | 768 return mClientManager.shouldHideDomainForSession(session); |
| 736 } | 769 } |
| 737 | 770 |
| (...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1234 private static void recordSpeculationStatusOnStart(int status) { | 1267 private static void recordSpeculationStatusOnStart(int status) { |
| 1235 RecordHistogram.recordEnumeratedHistogram( | 1268 RecordHistogram.recordEnumeratedHistogram( |
| 1236 "CustomTabs.SpeculationStatusOnStart", status, SPECULATION_STATU S_ON_START_MAX); | 1269 "CustomTabs.SpeculationStatusOnStart", status, SPECULATION_STATU S_ON_START_MAX); |
| 1237 } | 1270 } |
| 1238 | 1271 |
| 1239 private static void recordSpeculationStatusOnSwap(int status) { | 1272 private static void recordSpeculationStatusOnSwap(int status) { |
| 1240 RecordHistogram.recordEnumeratedHistogram( | 1273 RecordHistogram.recordEnumeratedHistogram( |
| 1241 "CustomTabs.SpeculationStatusOnSwap", status, SPECULATION_STATUS _ON_SWAP_MAX); | 1274 "CustomTabs.SpeculationStatusOnSwap", status, SPECULATION_STATUS _ON_SWAP_MAX); |
| 1242 } | 1275 } |
| 1243 } | 1276 } |
| OLD | NEW |