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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java

Issue 2970003003: customtabs: Extract a redirect endpoint, and maybe connect to it. (Closed)
Patch Set: . Created 3 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 unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698