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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
76 private static final String TAG = "ChromeConnection"; | 76 private static final String TAG = "ChromeConnection"; |
77 private static final String LOG_SERVICE_REQUESTS = "custom-tabs-log-service- requests"; | 77 private static final String LOG_SERVICE_REQUESTS = "custom-tabs-log-service- requests"; |
78 | 78 |
79 @VisibleForTesting | 79 @VisibleForTesting |
80 static final String PAGE_LOAD_METRICS_CALLBACK = "NavigationMetrics"; | 80 static final String PAGE_LOAD_METRICS_CALLBACK = "NavigationMetrics"; |
81 | 81 |
82 // For testing only, DO NOT USE. | 82 // For testing only, DO NOT USE. |
83 @VisibleForTesting | 83 @VisibleForTesting |
84 static final String DEBUG_OVERRIDE_KEY = | 84 static final String DEBUG_OVERRIDE_KEY = |
85 "android.support.customtabs.maylaunchurl.DEBUG_OVERRIDE"; | 85 "android.support.customtabs.maylaunchurl.DEBUG_OVERRIDE"; |
86 private static final int NO_OVERRIDE = 0; | 86 @VisibleForTesting |
87 static final int NO_OVERRIDE = 0; | |
87 @VisibleForTesting | 88 @VisibleForTesting |
88 static final int NO_PRERENDERING = 1; | 89 static final int NO_PRERENDERING = 1; |
89 @VisibleForTesting | 90 @VisibleForTesting |
90 static final int PREFETCH_ONLY = 2; | 91 static final int PREFETCH_ONLY = 2; |
91 | 92 |
92 private static AtomicReference<CustomTabsConnection> sInstance = new AtomicR eference<>(); | 93 private static AtomicReference<CustomTabsConnection> sInstance = new AtomicR eference<>(); |
93 | 94 |
94 /** Holds the parameters for the current speculation. */ | 95 /** Holds the parameters for the current speculation. */ |
95 @VisibleForTesting | 96 @VisibleForTesting |
96 static final class SpeculationParams { | 97 static final class SpeculationParams { |
97 public final CustomTabsSessionToken session; | 98 public final CustomTabsSessionToken session; |
98 public final String url; | 99 public final String url; |
100 public final int debugOverrideValue; | |
ahemery1
2017/03/21 15:15:57
Replaces prefetchOnly to have a record of what the
Benoit L
2017/03/21 15:56:41
I would prefer a name like "mode", or something al
| |
99 | 101 |
100 // Only for prerender. | 102 // Only for prerender. |
101 public final WebContents webContents; | 103 public final WebContents webContents; |
102 public final String referrer; | 104 public final String referrer; |
103 public final Bundle extras; | 105 public final Bundle extras; |
104 | 106 |
105 public final boolean prefetchOnly; | 107 static SpeculationParams forPrefetch(CustomTabsSessionToken session, Str ing url) { |
ahemery1
2017/03/21 15:15:58
Just reordered.
Benoit L
2017/03/21 15:56:41
why?
Not an issue, but why reordering code?
| |
108 return new SpeculationParams(session, url, PREFETCH_ONLY, null, null , null); | |
109 } | |
106 | 110 |
107 static SpeculationParams forPrerender(CustomTabsSessionToken session, St ring url, | 111 static SpeculationParams forPrerender(CustomTabsSessionToken session, St ring url, |
108 WebContents webcontents, String referrer, Bundle extras) { | 112 WebContents webcontents, String referrer, Bundle extras) { |
109 return new SpeculationParams(session, url, webcontents, referrer, ex tras, false); | 113 return new SpeculationParams(session, url, NO_OVERRIDE, webcontents, referrer, extras); |
110 } | |
111 | |
112 static SpeculationParams forPrefetch(CustomTabsSessionToken session, Str ing url) { | |
113 return new SpeculationParams(session, url, null, null, null, true); | |
114 } | 114 } |
115 | 115 |
116 private SpeculationParams(CustomTabsSessionToken session, String url, | 116 private SpeculationParams(CustomTabsSessionToken session, String url, |
117 WebContents webContents, String referrer, Bundle extras, boolean prefetchOnly) { | 117 int debugOverrideValue, WebContents webContents, String referrer , Bundle extras) { |
118 this.session = session; | 118 this.session = session; |
119 this.url = url; | 119 this.url = url; |
120 this.debugOverrideValue = debugOverrideValue; | |
120 this.webContents = webContents; | 121 this.webContents = webContents; |
121 this.referrer = referrer; | 122 this.referrer = referrer; |
122 this.extras = extras; | 123 this.extras = extras; |
123 this.prefetchOnly = prefetchOnly; | |
124 } | 124 } |
125 } | 125 } |
126 | 126 |
127 @VisibleForTesting | 127 @VisibleForTesting |
128 SpeculationParams mSpeculation; | 128 SpeculationParams mSpeculation; |
129 protected final Application mApplication; | 129 protected final Application mApplication; |
130 protected final ClientManager mClientManager; | 130 protected final ClientManager mClientManager; |
131 private final boolean mLogRequests; | 131 private final boolean mLogRequests; |
132 private final AtomicBoolean mWarmupHasBeenCalled = new AtomicBoolean(); | 132 private final AtomicBoolean mWarmupHasBeenCalled = new AtomicBoolean(); |
133 private final AtomicBoolean mWarmupHasBeenFinished = new AtomicBoolean(); | 133 private final AtomicBoolean mWarmupHasBeenFinished = new AtomicBoolean(); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
326 int debugOverrideValue = NO_OVERRIDE; | 326 int debugOverrideValue = NO_OVERRIDE; |
327 if (extras != null) debugOverrideValue = extras.getInt(DEBUG_OVERRIDE_KE Y, NO_OVERRIDE); | 327 if (extras != null) debugOverrideValue = extras.getInt(DEBUG_OVERRIDE_KE Y, NO_OVERRIDE); |
328 | 328 |
329 boolean didStartPrerender = false, didStartPrefetch = false; | 329 boolean didStartPrerender = false, didStartPrefetch = false; |
330 boolean mayPrerender = mayPrerender(session); | 330 boolean mayPrerender = mayPrerender(session); |
331 if (mayPrerender) { | 331 if (mayPrerender) { |
332 if (debugOverrideValue == PREFETCH_ONLY) { | 332 if (debugOverrideValue == PREFETCH_ONLY) { |
333 didStartPrefetch = new ResourcePrefetchPredictor(profile).startP refetching(url); | 333 didStartPrefetch = new ResourcePrefetchPredictor(profile).startP refetching(url); |
334 if (didStartPrefetch) mSpeculation = SpeculationParams.forPrefet ch(session, url); | 334 if (didStartPrefetch) mSpeculation = SpeculationParams.forPrefet ch(session, url); |
335 } else if (debugOverrideValue != NO_PRERENDERING) { | 335 } else if (debugOverrideValue != NO_PRERENDERING) { |
336 // Last one wins and cancels the previous prerender. | |
ahemery1
2017/03/21 15:15:57
This was moved from inside the prerenderUrl() func
Benoit L
2017/03/21 15:56:41
nit: Is it possible to isolate the changes between
| |
337 cancelPrerender(null); | |
336 didStartPrerender = prerenderUrl(session, url, extras, uid); | 338 didStartPrerender = prerenderUrl(session, url, extras, uid); |
337 } | 339 } |
338 } | 340 } |
339 preconnectUrls(otherLikelyBundles); | 341 preconnectUrls(otherLikelyBundles); |
340 if (!didStartPrefetch) warmupManager.maybePreconnectUrlAndSubResources(p rofile, url); | 342 if (!didStartPrefetch) warmupManager.maybePreconnectUrlAndSubResources(p rofile, url); |
341 if (!didStartPrerender) warmupManager.createSpareWebContents(); | 343 if (!didStartPrerender) warmupManager.createSpareWebContents(); |
342 } | 344 } |
343 | 345 |
344 /** | 346 /** |
345 * Low confidence mayLaunchUrl() call, that is: | 347 * Low confidence mayLaunchUrl() call, that is: |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
580 * @param url The URL the WebContents is for. | 582 * @param url The URL the WebContents is for. |
581 * @param referrer The referrer to use for |url|. | 583 * @param referrer The referrer to use for |url|. |
582 * @return The prerendered WebContents, or null. | 584 * @return The prerendered WebContents, or null. |
583 */ | 585 */ |
584 WebContents takePrerenderedUrl(CustomTabsSessionToken session, String url, S tring referrer) { | 586 WebContents takePrerenderedUrl(CustomTabsSessionToken session, String url, S tring referrer) { |
585 ThreadUtils.assertOnUiThread(); | 587 ThreadUtils.assertOnUiThread(); |
586 if (mSpeculation == null || session == null || !session.equals(mSpeculat ion.session)) { | 588 if (mSpeculation == null || session == null || !session.equals(mSpeculat ion.session)) { |
587 return null; | 589 return null; |
588 } | 590 } |
589 | 591 |
590 if (mSpeculation.prefetchOnly) { | 592 if (mSpeculation.debugOverrideValue == PREFETCH_ONLY) { |
591 Profile profile = Profile.getLastUsedProfile(); | 593 Profile profile = Profile.getLastUsedProfile(); |
592 new ResourcePrefetchPredictor(profile).stopPrefetching(mSpeculation. url); | 594 new ResourcePrefetchPredictor(profile).stopPrefetching(mSpeculation. url); |
593 mSpeculation = null; | 595 mSpeculation = null; |
594 return null; | 596 return null; |
595 } | 597 } |
596 | 598 |
597 WebContents webContents = mSpeculation.webContents; | 599 WebContents webContents = mSpeculation.webContents; |
598 String prerenderedUrl = mSpeculation.url; | 600 String prerenderedUrl = mSpeculation.url; |
599 String prerenderReferrer = mSpeculation.referrer; | 601 String prerenderReferrer = mSpeculation.referrer; |
600 if (referrer == null) referrer = ""; | 602 if (referrer == null) referrer = ""; |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
894 // tabs. Then PrivacyManager should be used to make the below check. | 896 // tabs. Then PrivacyManager should be used to make the below check. |
895 if (!PrefServiceBridge.getInstance().getNetworkPredictionEnabled()) retu rn false; | 897 if (!PrefServiceBridge.getInstance().getNetworkPredictionEnabled()) retu rn false; |
896 if (DataReductionProxySettings.getInstance().isDataReductionProxyEnabled ()) return false; | 898 if (DataReductionProxySettings.getInstance().isDataReductionProxyEnabled ()) return false; |
897 ConnectivityManager cm = | 899 ConnectivityManager cm = |
898 (ConnectivityManager) mApplication.getApplicationContext().getSy stemService( | 900 (ConnectivityManager) mApplication.getApplicationContext().getSy stemService( |
899 Context.CONNECTIVITY_SERVICE); | 901 Context.CONNECTIVITY_SERVICE); |
900 return !cm.isActiveNetworkMetered() || shouldPrerenderOnCellularForSessi on(session); | 902 return !cm.isActiveNetworkMetered() || shouldPrerenderOnCellularForSessi on(session); |
901 } | 903 } |
902 | 904 |
903 /** Cancels a prerender for a given session, or any session if null. */ | 905 /** Cancels a prerender for a given session, or any session if null. */ |
906 @VisibleForTesting | |
904 void cancelPrerender(CustomTabsSessionToken session) { | 907 void cancelPrerender(CustomTabsSessionToken session) { |
908 if (mSpeculation == null) return; | |
909 if (session != null && !session.equals(mSpeculation.session)) return; | |
910 switch (mSpeculation.debugOverrideValue) { | |
911 case NO_OVERRIDE: | |
912 cancelNoOverridePrerender(session); | |
913 break; | |
914 default: | |
915 return; | |
916 } | |
917 } | |
918 | |
919 private void cancelNoOverridePrerender(CustomTabsSessionToken session) { | |
905 ThreadUtils.assertOnUiThread(); | 920 ThreadUtils.assertOnUiThread(); |
906 if (mSpeculation != null && (session == null || session.equals(mSpeculat ion.session)) | 921 if (mSpeculation.webContents == null) return; |
907 && mSpeculation.webContents != null) { | 922 mExternalPrerenderHandler.cancelCurrentPrerender(); |
908 mExternalPrerenderHandler.cancelCurrentPrerender(); | 923 mSpeculation.webContents.destroy(); |
909 mSpeculation.webContents.destroy(); | 924 mSpeculation = null; |
910 mSpeculation = null; | |
911 } | |
912 } | 925 } |
913 | 926 |
914 /** | 927 /** |
915 * Tries to request a prerender for a given URL. | 928 * Tries to request a prerender for a given URL. |
916 * | 929 * |
917 * @param session Session the request comes from. | 930 * @param session Session the request comes from. |
918 * @param url URL to prerender. | 931 * @param url URL to prerender. |
919 * @param extras extra parameters. | 932 * @param extras extra parameters. |
920 * @param uid UID of the caller. | 933 * @param uid UID of the caller. |
921 * @return true if a prerender has been initiated. | 934 * @return true if a prerender has been initiated. |
922 */ | 935 */ |
923 private boolean prerenderUrl( | 936 private boolean prerenderUrl( |
924 CustomTabsSessionToken session, String url, Bundle extras, int uid) { | 937 CustomTabsSessionToken session, String url, Bundle extras, int uid) { |
925 ThreadUtils.assertOnUiThread(); | 938 ThreadUtils.assertOnUiThread(); |
926 // Ignores mayPrerender() for an empty URL, since it cancels an existing prerender. | |
927 if (!mayPrerender(session) && !TextUtils.isEmpty(url)) return false; | |
ahemery1
2017/03/21 15:15:57
Unnecessary duplicate.
| |
928 if (!mWarmupHasBeenCalled.get()) return false; | 939 if (!mWarmupHasBeenCalled.get()) return false; |
929 // Last one wins and cancels the previous prerender. | 940 |
930 cancelPrerender(null); | |
931 if (TextUtils.isEmpty(url)) return false; | |
ahemery1
2017/03/21 15:15:57
Extracted because behavior is more general than ju
| |
932 boolean throttle = !shouldPrerenderOnCellularForSession(session); | 941 boolean throttle = !shouldPrerenderOnCellularForSession(session); |
933 if (throttle && !mClientManager.isPrerenderingAllowed(uid)) return false ; | 942 if (throttle && !mClientManager.isPrerenderingAllowed(uid)) return false ; |
934 | 943 |
935 // A prerender will be requested. Time to destroy the spare WebContents. | 944 // A prerender will be requested. Time to destroy the spare WebContents. |
936 WarmupManager.getInstance().destroySpareWebContents(); | 945 WarmupManager.getInstance().destroySpareWebContents(); |
937 | 946 |
938 Intent extrasIntent = new Intent(); | 947 Intent extrasIntent = new Intent(); |
939 if (extras != null) extrasIntent.putExtras(extras); | 948 if (extras != null) extrasIntent.putExtras(extras); |
940 if (IntentHandler.getExtraHeadersFromIntent(extrasIntent) != null) retur n false; | 949 if (IntentHandler.getExtraHeadersFromIntent(extrasIntent) != null) retur n false; |
941 if (mExternalPrerenderHandler == null) { | 950 if (mExternalPrerenderHandler == null) { |
942 mExternalPrerenderHandler = new ExternalPrerenderHandler(); | 951 mExternalPrerenderHandler = new ExternalPrerenderHandler(); |
943 } | 952 } |
944 Rect contentBounds = ExternalPrerenderHandler.estimateContentSize(mAppli cation, true); | 953 Rect contentBounds = ExternalPrerenderHandler.estimateContentSize(mAppli cation, true); |
945 String referrer = IntentHandler.getReferrerUrlIncludingExtraHeaders(extr asIntent); | 954 String referrer = IntentHandler.getReferrerUrlIncludingExtraHeaders(extr asIntent); |
946 if (referrer == null && getReferrerForSession(session) != null) { | 955 if (referrer == null && getReferrerForSession(session) != null) { |
947 referrer = getReferrerForSession(session).getUrl(); | 956 referrer = getReferrerForSession(session).getUrl(); |
948 } | 957 } |
949 if (referrer == null) referrer = ""; | 958 if (referrer == null) referrer = ""; |
950 Pair<WebContents, WebContents> webContentsPair = mExternalPrerenderHandl er.addPrerender( | 959 Pair<WebContents, WebContents> webContentsPair = |
951 Profile.getLastUsedProfile(), url, referrer, | 960 mExternalPrerenderHandler.addPrerender(Profile.getLastUsedProfil e(), url, referrer, |
952 contentBounds, | 961 contentBounds, shouldPrerenderOnCellularForSession(sessi on)); |
953 shouldPrerenderOnCellularForSession(session)); | |
954 if (webContentsPair == null) return false; | 962 if (webContentsPair == null) return false; |
955 WebContents dummyWebContents = webContentsPair.first; | 963 WebContents dummyWebContents = webContentsPair.first; |
956 if (webContentsPair.second != null) { | 964 if (webContentsPair.second != null) { |
957 mClientManager.resetPostMessageHandlerForSession(session, webContent sPair.second); | 965 mClientManager.resetPostMessageHandlerForSession(session, webContent sPair.second); |
958 } | 966 } |
959 if (throttle) mClientManager.registerPrerenderRequest(uid, url); | 967 if (throttle) mClientManager.registerPrerenderRequest(uid, url); |
960 mSpeculation = SpeculationParams.forPrerender( | 968 mSpeculation = |
961 session, url, dummyWebContents, referrer, extras); | 969 SpeculationParams.forPrerender(session, url, dummyWebContents, r eferrer, extras); |
962 | 970 |
963 RecordHistogram.recordBooleanHistogram("CustomTabs.PrerenderSessionUsesD efaultParameters", | 971 RecordHistogram.recordBooleanHistogram("CustomTabs.PrerenderSessionUsesD efaultParameters", |
964 mClientManager.usesDefaultSessionParameters(session)); | 972 mClientManager.usesDefaultSessionParameters(session)); |
965 | 973 |
966 return true; | 974 return true; |
967 } | 975 } |
968 | 976 |
969 @VisibleForTesting | 977 @VisibleForTesting |
970 void resetThrottling(Context context, int uid) { | 978 void resetThrottling(Context context, int uid) { |
971 mClientManager.resetThrottling(uid); | 979 mClientManager.resetThrottling(uid); |
972 } | 980 } |
973 | 981 |
974 @VisibleForTesting | 982 @VisibleForTesting |
975 void ban(Context context, int uid) { | 983 void ban(Context context, int uid) { |
976 mClientManager.ban(uid); | 984 mClientManager.ban(uid); |
977 } | 985 } |
978 | 986 |
979 @VisibleForTesting | 987 @VisibleForTesting |
980 void setForcePrerender(boolean force) { | 988 void setForcePrerender(boolean force) { |
981 mForcePrerenderForTesting = force; | 989 mForcePrerenderForTesting = force; |
982 } | 990 } |
983 } | 991 } |
OLD | NEW |