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

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: Typo. 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 // TODO(lizeb): Move to the support library.
122 @VisibleForTesting
123 static final String REDIRECT_ENDPOINT_KEY = "android.support.customtabs.REDI RECT_ENDPOINT";
124
119 private static AtomicReference<CustomTabsConnection> sInstance = new AtomicR eference<>(); 125 private static AtomicReference<CustomTabsConnection> sInstance = new AtomicR eference<>();
120 126
121 /** Holds the parameters for the current speculation. */ 127 /** Holds the parameters for the current speculation. */
122 @VisibleForTesting 128 @VisibleForTesting
123 static final class SpeculationParams { 129 static final class SpeculationParams {
124 @VisibleForTesting 130 @VisibleForTesting
125 static final int NO_SPECULATION = 0; 131 static final int NO_SPECULATION = 0;
126 @VisibleForTesting 132 @VisibleForTesting
127 static final int PREFETCH = 1; 133 static final int PREFETCH = 1;
128 @VisibleForTesting 134 @VisibleForTesting
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 } 345 }
340 } finally { 346 } finally {
341 TraceEvent.end("CustomTabsConnection.warmupInternal"); 347 TraceEvent.end("CustomTabsConnection.warmupInternal");
342 } 348 }
343 mWarmupHasBeenFinished.set(true); 349 mWarmupHasBeenFinished.set(true);
344 } 350 }
345 }); 351 });
346 return true; 352 return true;
347 } 353 }
348 354
349 /** @return the URL converted to string, or null if it's invalid. */ 355 /** @return the URL or null if it's invalid. */
350 private static String checkAndConvertUri(Uri uri) { 356 private boolean isValid(Uri uri) {
351 if (uri == null) return null; 357 if (uri == null) return false;
352 // Don't do anything for unknown schemes. Not having a scheme is allowed , as we allow 358 // Don't do anything for unknown schemes. Not having a scheme is allowed , as we allow
353 // "www.example.com". 359 // "www.example.com".
354 String scheme = uri.normalizeScheme().getScheme(); 360 String scheme = uri.normalizeScheme().getScheme();
355 boolean allowedScheme = scheme == null || scheme.equals("http") || schem e.equals("https"); 361 boolean allowedScheme = scheme == null || scheme.equals("http") || schem e.equals("https");
356 if (!allowedScheme) return null; 362 if (!allowedScheme) return false;
357 return uri.toString(); 363 return true;
358 } 364 }
359 365
360 /** 366 /**
361 * High confidence mayLaunchUrl() call, that is: 367 * High confidence mayLaunchUrl() call, that is:
362 * - Tries to prerender if possible. 368 * - Tries to prerender if possible.
363 * - An empty URL cancels the current prerender if any. 369 * - An empty URL cancels the current prerender if any.
364 * - If prerendering is not possible, makes sure that there is a spare rende rer. 370 * - If prerendering is not possible, makes sure that there is a spare rende rer.
365 */ 371 */
366 private void highConfidenceMayLaunchUrl(CustomTabsSessionToken session, 372 private void highConfidenceMayLaunchUrl(CustomTabsSessionToken session,
367 int uid, String url, Bundle extras, List<Bundle> otherLikelyBundles) { 373 int uid, String url, Bundle extras, List<Bundle> otherLikelyBundles) {
(...skipping 22 matching lines...) Expand all
390 ThreadUtils.assertOnUiThread(); 396 ThreadUtils.assertOnUiThread();
391 if (!preconnectUrls(likelyBundles)) return false; 397 if (!preconnectUrls(likelyBundles)) return false;
392 WarmupManager.getInstance().createSpareWebContents(); 398 WarmupManager.getInstance().createSpareWebContents();
393 return true; 399 return true;
394 } 400 }
395 401
396 private boolean preconnectUrls(List<Bundle> likelyBundles) { 402 private boolean preconnectUrls(List<Bundle> likelyBundles) {
397 boolean atLeastOneUrl = false; 403 boolean atLeastOneUrl = false;
398 if (likelyBundles == null) return false; 404 if (likelyBundles == null) return false;
399 WarmupManager warmupManager = WarmupManager.getInstance(); 405 WarmupManager warmupManager = WarmupManager.getInstance();
400 Profile profile = Profile.getLastUsedProfile(); 406 Profile profile = Profile.getLastUsedProfile().getOriginalProfile();
401 for (Bundle bundle : likelyBundles) { 407 for (Bundle bundle : likelyBundles) {
402 Uri uri; 408 Uri uri;
403 try { 409 try {
404 uri = IntentUtils.safeGetParcelable(bundle, CustomTabsService.KE Y_URL); 410 uri = IntentUtils.safeGetParcelable(bundle, CustomTabsService.KE Y_URL);
405 } catch (ClassCastException e) { 411 } catch (ClassCastException e) {
406 continue; 412 continue;
407 } 413 }
408 String url = checkAndConvertUri(uri); 414 if (isValid(uri)) {
409 if (url != null) { 415 warmupManager.maybePreconnectUrlAndSubResources(profile, uri.toS tring());
410 warmupManager.maybePreconnectUrlAndSubResources(profile, url);
411 atLeastOneUrl = true; 416 atLeastOneUrl = true;
412 } 417 }
413 } 418 }
414 return atLeastOneUrl; 419 return atLeastOneUrl;
415 } 420 }
416 421
417 public boolean mayLaunchUrl(CustomTabsSessionToken session, Uri url, Bundle extras, 422 public boolean mayLaunchUrl(CustomTabsSessionToken session, Uri url, Bundle extras,
418 List<Bundle> otherLikelyBundles) { 423 List<Bundle> otherLikelyBundles) {
419 try { 424 try {
420 TraceEvent.begin("CustomTabsConnection.mayLaunchUrl"); 425 TraceEvent.begin("CustomTabsConnection.mayLaunchUrl");
421 boolean success = mayLaunchUrlInternal(session, url, extras, otherLi kelyBundles); 426 boolean success = mayLaunchUrlInternal(session, url, extras, otherLi kelyBundles);
422 logCall("mayLaunchUrl(" + url + ")", success); 427 logCall("mayLaunchUrl(" + url + ")", success);
423 return success; 428 return success;
424 } finally { 429 } finally {
425 TraceEvent.end("CustomTabsConnection.mayLaunchUrl"); 430 TraceEvent.end("CustomTabsConnection.mayLaunchUrl");
426 } 431 }
427 } 432 }
428 433
429 private boolean mayLaunchUrlInternal(final CustomTabsSessionToken session, U ri url, 434 private boolean mayLaunchUrlInternal(final CustomTabsSessionToken session, U ri url,
430 final Bundle extras, final List<Bundle> otherLikelyBundles) { 435 final Bundle extras, final List<Bundle> otherLikelyBundles) {
431 final boolean lowConfidence = 436 final boolean lowConfidence =
432 (url == null || TextUtils.isEmpty(url.toString())) && otherLikel yBundles != null; 437 (url == null || TextUtils.isEmpty(url.toString())) && otherLikel yBundles != null;
433 final String urlString = checkAndConvertUri(url); 438 final String urlString = isValid(url) ? url.toString() : null;
434 if (url != null && urlString == null && !lowConfidence) return false; 439 if (url != null && urlString == null && !lowConfidence) return false;
435 440
436 // Things below need the browser process to be initialized. 441 // Things below need the browser process to be initialized.
437 442
438 // Forbids warmup() from creating a spare renderer, as prerendering woul dn't reuse 443 // 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, 444 // it. Checking whether prerendering is enabled requires the native libr ary to be loaded,
440 // which is not necessarily the case yet. 445 // which is not necessarily the case yet.
441 if (!warmupInternal(false)) return false; // Also does the foreground ch eck. 446 if (!warmupInternal(false)) return false; // Also does the foreground ch eck.
442 447
443 final int uid = Binder.getCallingUid(); 448 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); 723 SPECULATION_STATUS_ON_SWAP_BACKGROUND_TAB_NOT_MATCHE D);
719 tab.destroy(); 724 tab.destroy();
720 } 725 }
721 } 726 }
722 } finally { 727 } finally {
723 TraceEvent.end("CustomTabsConnection.takeHiddenTab"); 728 TraceEvent.end("CustomTabsConnection.takeHiddenTab");
724 } 729 }
725 return null; 730 return null;
726 } 731 }
727 732
733 /**
734 * Called when an intent is handled by either an existing or a new CustomTab Activity.
735 *
736 * @param session Session extracted from the intent.
737 * @param url URL extracted from the intent.
738 * @param intent incoming intent.
739 */
740 void onHandledIntent(CustomTabsSessionToken session, String url, Intent inte nt) {
741 // For the preconnection to not be a no-op, we need more than just the n ative library.
742 Context context = ContextUtils.getApplicationContext();
743 if (!ChromeBrowserInitializer.getInstance(context).hasNativeInitializati onCompleted()) {
744 return;
745 }
746 if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_REDIRECT_PRECONNE CT)) return;
747
748 // Conditions:
749 // - There is a valid redirect endpoint.
750 // - The URL's origin is first party with respect to the app.
751 Uri redirectEndpoint = intent.getParcelableExtra(REDIRECT_ENDPOINT_KEY);
752 if (redirectEndpoint == null || !isValid(redirectEndpoint)) return;
753
754 String origin = GURLUtils.getOrigin(url);
755 if (origin == null) return;
756 if (!mClientManager.isFirstPartyOriginForSession(session, Uri.parse(orig in))) return;
757
758 WarmupManager.getInstance().maybePreconnectUrlAndSubResources(
759 Profile.getLastUsedProfile(), redirectEndpoint.toString());
760 }
761
728 /** See {@link ClientManager#getReferrerForSession(CustomTabsSessionToken)} */ 762 /** See {@link ClientManager#getReferrerForSession(CustomTabsSessionToken)} */
729 public Referrer getReferrerForSession(CustomTabsSessionToken session) { 763 public Referrer getReferrerForSession(CustomTabsSessionToken session) {
730 return mClientManager.getReferrerForSession(session); 764 return mClientManager.getReferrerForSession(session);
731 } 765 }
732 766
733 /** @see ClientManager#shouldHideDomainForSession(CustomTabsSessionToken) */ 767 /** @see ClientManager#shouldHideDomainForSession(CustomTabsSessionToken) */
734 public boolean shouldHideDomainForSession(CustomTabsSessionToken session) { 768 public boolean shouldHideDomainForSession(CustomTabsSessionToken session) {
735 return mClientManager.shouldHideDomainForSession(session); 769 return mClientManager.shouldHideDomainForSession(session);
736 } 770 }
737 771
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after
1234 private static void recordSpeculationStatusOnStart(int status) { 1268 private static void recordSpeculationStatusOnStart(int status) {
1235 RecordHistogram.recordEnumeratedHistogram( 1269 RecordHistogram.recordEnumeratedHistogram(
1236 "CustomTabs.SpeculationStatusOnStart", status, SPECULATION_STATU S_ON_START_MAX); 1270 "CustomTabs.SpeculationStatusOnStart", status, SPECULATION_STATU S_ON_START_MAX);
1237 } 1271 }
1238 1272
1239 private static void recordSpeculationStatusOnSwap(int status) { 1273 private static void recordSpeculationStatusOnSwap(int status) {
1240 RecordHistogram.recordEnumeratedHistogram( 1274 RecordHistogram.recordEnumeratedHistogram(
1241 "CustomTabs.SpeculationStatusOnSwap", status, SPECULATION_STATUS _ON_SWAP_MAX); 1275 "CustomTabs.SpeculationStatusOnSwap", status, SPECULATION_STATUS _ON_SWAP_MAX);
1242 } 1276 }
1243 } 1277 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698