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

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

Issue 1420913007: customtabs: Create a spare WebContents in warmup() on non low-end devices. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Cosmetic changes. Created 5 years, 1 month 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.content.Context; 9 import android.content.Context;
10 import android.content.Intent; 10 import android.content.Intent;
11 import android.content.res.Resources; 11 import android.content.res.Resources;
12 import android.graphics.Bitmap; 12 import android.graphics.Bitmap;
13 import android.graphics.Point; 13 import android.graphics.Point;
14 import android.net.ConnectivityManager; 14 import android.net.ConnectivityManager;
15 import android.net.Uri; 15 import android.net.Uri;
16 import android.os.AsyncTask; 16 import android.os.AsyncTask;
17 import android.os.Binder; 17 import android.os.Binder;
18 import android.os.Build; 18 import android.os.Build;
19 import android.os.Bundle; 19 import android.os.Bundle;
20 import android.os.IBinder; 20 import android.os.IBinder;
21 import android.os.Process; 21 import android.os.Process;
22 import android.support.customtabs.CustomTabsIntent; 22 import android.support.customtabs.CustomTabsIntent;
23 import android.support.customtabs.ICustomTabsCallback; 23 import android.support.customtabs.ICustomTabsCallback;
24 import android.support.customtabs.ICustomTabsService; 24 import android.support.customtabs.ICustomTabsService;
25 import android.text.TextUtils; 25 import android.text.TextUtils;
26 import android.view.WindowManager; 26 import android.view.WindowManager;
27 27
28 import org.chromium.base.FieldTrialList; 28 import org.chromium.base.FieldTrialList;
29 import org.chromium.base.Log; 29 import org.chromium.base.Log;
30 import org.chromium.base.SysUtils;
30 import org.chromium.base.ThreadUtils; 31 import org.chromium.base.ThreadUtils;
31 import org.chromium.base.VisibleForTesting; 32 import org.chromium.base.VisibleForTesting;
32 import org.chromium.base.annotations.SuppressFBWarnings; 33 import org.chromium.base.annotations.SuppressFBWarnings;
33 import org.chromium.base.library_loader.ProcessInitException; 34 import org.chromium.base.library_loader.ProcessInitException;
34 import org.chromium.chrome.R; 35 import org.chromium.chrome.R;
35 import org.chromium.chrome.browser.ChromeApplication; 36 import org.chromium.chrome.browser.ChromeApplication;
36 import org.chromium.chrome.browser.IntentHandler; 37 import org.chromium.chrome.browser.IntentHandler;
37 import org.chromium.chrome.browser.WarmupManager; 38 import org.chromium.chrome.browser.WarmupManager;
38 import org.chromium.chrome.browser.WebContentsFactory; 39 import org.chromium.chrome.browser.WebContentsFactory;
39 import org.chromium.chrome.browser.device.DeviceClassManager; 40 import org.chromium.chrome.browser.device.DeviceClassManager;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 public boolean newSession(ICustomTabsCallback callback) { 122 public boolean newSession(ICustomTabsCallback callback) {
122 ClientManager.DisconnectCallback onDisconnect = new ClientManager.Discon nectCallback() { 123 ClientManager.DisconnectCallback onDisconnect = new ClientManager.Discon nectCallback() {
123 @Override 124 @Override
124 public void run(IBinder session) { 125 public void run(IBinder session) {
125 cancelPrerender(session); 126 cancelPrerender(session);
126 } 127 }
127 }; 128 };
128 return mClientManager.newSession(callback, Binder.getCallingUid(), onDis connect); 129 return mClientManager.newSession(callback, Binder.getCallingUid(), onDis connect);
129 } 130 }
130 131
132 /** Warmup activities that should only happen once. */
133 @SuppressFBWarnings("DM_EXIT")
134 private static void oneTimeInitialization(final ChromeApplication app) {
pasko 2015/10/29 13:38:58 since the one time-ness check is outside this func
Benoit L 2015/10/29 17:12:36 Done.
135 ThreadUtils.assertOnUiThread();
136 try {
137 app.startBrowserProcessesAndLoadLibrariesSync(true);
138 } catch (ProcessInitException e) {
139 Log.e(TAG, "ProcessInitException while starting the browser process. ");
140 // Cannot do anything without the native library, and cannot show a
141 // dialog to the user.
142 System.exit(-1);
143 }
144 final Context context = app.getApplicationContext();
145 new AsyncTask<Void, Void, Void>() {
146 @Override
147 protected Void doInBackground(Void... params) {
148 ChildProcessLauncher.warmUp(context);
149 return null;
150 }
151 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
152 ChromeBrowserInitializer.initNetworkChangeNotifier(context);
153 WarmupManager.getInstance().initializeViewHierarchy(
154 context, R.layout.custom_tabs_control_container);
155 }
156
131 @Override 157 @Override
132 public boolean warmup(long flags) { 158 public boolean warmup(long flags) {
159 return warmup(true);
160 }
161
162 /**
163 * Starts as much as possible in anticipation of a future navigation.
164 *
165 * @param mayCreatesparewebcontents true if warmup() can create a spare rend erer.
166 * @return true for success.
167 */
168 private boolean warmup(final boolean mayCreateSpareWebContents) {
133 // Here and in mayLaunchUrl(), don't do expensive work for background ap plications. 169 // Here and in mayLaunchUrl(), don't do expensive work for background ap plications.
134 if (!isCallerForegroundOrSelf()) return false; 170 if (!isCallerForegroundOrSelf()) return false;
135 mClientManager.recordUidHasCalledWarmup(Binder.getCallingUid()); 171 mClientManager.recordUidHasCalledWarmup(Binder.getCallingUid());
136 if (!mWarmupHasBeenCalled.compareAndSet(false, true)) return true; 172 final boolean firstTime = mWarmupHasBeenCalled.compareAndSet(false, true );
Yusuf 2015/10/29 16:35:27 and lets call this !initialized
Benoit L 2015/10/29 17:12:36 Done.
137 // The call is non-blocking and this must execute on the UI thread, post a task. 173 // The call is non-blocking and this must execute on the UI thread, post a task.
138 ThreadUtils.postOnUiThread(new Runnable() { 174 ThreadUtils.postOnUiThread(new Runnable() {
139 @Override 175 @Override
140 @SuppressFBWarnings("DM_EXIT")
141 public void run() { 176 public void run() {
142 ChromeApplication app = (ChromeApplication) mApplication; 177 if (firstTime) oneTimeInitialization((ChromeApplication) mApplic ation);
143 try { 178 if (mayCreateSpareWebContents && mPrerender == null && !SysUtils .isLowEndDevice()) {
144 app.startBrowserProcessesAndLoadLibrariesSync(true); 179 createSpareWebContents();
145 } catch (ProcessInitException e) {
146 Log.e(TAG, "ProcessInitException while starting the browser process.");
147 // Cannot do anything without the native library, and cannot show a
148 // dialog to the user.
149 System.exit(-1);
150 } 180 }
151 final Context context = app.getApplicationContext();
152 new AsyncTask<Void, Void, Void>() {
153 @Override
154 protected Void doInBackground(Void... params) {
155 ChildProcessLauncher.warmUp(context);
156 return null;
157 }
158 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
159 ChromeBrowserInitializer.initNetworkChangeNotifier(context);
160 WarmupManager.getInstance().initializeViewHierarchy(app.getAppli cationContext(),
161 R.layout.custom_tabs_control_container);
162 } 181 }
163 }); 182 });
164 return true; 183 return true;
165 } 184 }
166 185
167 /** 186 /**
168 * Creates a spare {@link WebContents}, if none exists. 187 * Creates a spare {@link WebContents}, if none exists.
169 * 188 *
170 * Navigating to "about:blank" forces a lot of initialization to take place 189 * Navigating to "about:blank" forces a lot of initialization to take place
171 * here. This improves PLT. This navigation is never registered in the histo ry, as 190 * here. This improves PLT. This navigation is never registered in the histo ry, as
(...skipping 11 matching lines...) Expand all
183 } 202 }
184 203
185 @Override 204 @Override
186 public boolean mayLaunchUrl(ICustomTabsCallback callback, Uri url, final Bun dle extras, 205 public boolean mayLaunchUrl(ICustomTabsCallback callback, Uri url, final Bun dle extras,
187 List<Bundle> otherLikelyBundles) { 206 List<Bundle> otherLikelyBundles) {
188 // Don't do anything for unknown schemes. Not having a scheme is 207 // Don't do anything for unknown schemes. Not having a scheme is
189 // allowed, as we allow "www.example.com". 208 // allowed, as we allow "www.example.com".
190 String scheme = url.normalizeScheme().getScheme(); 209 String scheme = url.normalizeScheme().getScheme();
191 if (scheme != null && !scheme.equals("http") && !scheme.equals("https")) return false; 210 if (scheme != null && !scheme.equals("http") && !scheme.equals("https")) return false;
192 // Things below need the browser process to be initialized. 211 // Things below need the browser process to be initialized.
193 if (!warmup(0)) return false; // Also does the foreground check. 212
213 // Forbids warmup() from creating a spare renderer, as prerendering woul dn't reuse
214 // it. Checking whether prerendering is enabled requires the native libr ary to be loaded,
215 // which is not necessarily the case yet.
216 if (!warmup(false)) return false; // Also does the foreground check.
194 217
195 final IBinder session = callback.asBinder(); 218 final IBinder session = callback.asBinder();
196 final String urlString = url.toString(); 219 final String urlString = url.toString();
197 final boolean noPrerendering = 220 final boolean noPrerendering =
198 extras != null ? extras.getBoolean(NO_PRERENDERING_KEY, false) : false; 221 extras != null ? extras.getBoolean(NO_PRERENDERING_KEY, false) : false;
199 final int uid = Binder.getCallingUid(); 222 final int uid = Binder.getCallingUid();
200 if (!mClientManager.updateStatsAndReturnWhetherAllowed(session, uid, url String)) { 223 if (!mClientManager.updateStatsAndReturnWhetherAllowed(session, uid, url String)) {
201 return false; 224 return false;
202 } 225 }
203 ThreadUtils.postOnUiThread(new Runnable() { 226 ThreadUtils.postOnUiThread(new Runnable() {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 * 259 *
237 * TODO(lizeb): Update this when crbug.com/521729 is fixed. 260 * TODO(lizeb): Update this when crbug.com/521729 is fixed.
238 */ 261 */
239 WebContents takeSpareWebContents() { 262 WebContents takeSpareWebContents() {
240 ThreadUtils.assertOnUiThread(); 263 ThreadUtils.assertOnUiThread();
241 WebContents result = mSpareWebContents; 264 WebContents result = mSpareWebContents;
242 mSpareWebContents = null; 265 mSpareWebContents = null;
243 return result; 266 return result;
244 } 267 }
245 268
269 private void destroySpareWebContents() {
270 ThreadUtils.assertOnUiThread();
271 WebContents webContents = takeSpareWebContents();
272 if (webContents != null) webContents.destroy();
273 }
274
246 @Override 275 @Override
247 public boolean updateVisuals(final ICustomTabsCallback callback, Bundle bund le) { 276 public boolean updateVisuals(final ICustomTabsCallback callback, Bundle bund le) {
248 final Bundle actionButtonBundle = IntentUtils.safeGetBundle(bundle, 277 final Bundle actionButtonBundle = IntentUtils.safeGetBundle(bundle,
249 CustomTabsIntent.EXTRA_ACTION_BUTTON_BUNDLE); 278 CustomTabsIntent.EXTRA_ACTION_BUTTON_BUNDLE);
250 if (actionButtonBundle == null) return false; 279 if (actionButtonBundle == null) return false;
251 280
252 final Bitmap bitmap = ActionButtonParams.tryParseBitmapFromBundle(mAppli cation, 281 final Bitmap bitmap = ActionButtonParams.tryParseBitmapFromBundle(mAppli cation,
253 actionButtonBundle); 282 actionButtonBundle);
254 final String description = ActionButtonParams 283 final String description = ActionButtonParams
255 .tryParseDescriptionFromBundle(actionButtonBundle); 284 .tryParseDescriptionFromBundle(actionButtonBundle);
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 // incompatible with prerendering through this service. Remove this 503 // incompatible with prerendering through this service. Remove this
475 // limitation, or remove ChromePrerenderService. 504 // limitation, or remove ChromePrerenderService.
476 WarmupManager.getInstance().disallowPrerendering(); 505 WarmupManager.getInstance().disallowPrerendering();
477 // Ignores mayPrerender() for an empty URL, since it cancels an existing prerender. 506 // Ignores mayPrerender() for an empty URL, since it cancels an existing prerender.
478 if (!mayPrerender() && !TextUtils.isEmpty(url)) return; 507 if (!mayPrerender() && !TextUtils.isEmpty(url)) return;
479 if (!mWarmupHasBeenCalled.get()) return; 508 if (!mWarmupHasBeenCalled.get()) return;
480 // Last one wins and cancels the previous prerender. 509 // Last one wins and cancels the previous prerender.
481 cancelPrerender(null); 510 cancelPrerender(null);
482 if (TextUtils.isEmpty(url)) return; 511 if (TextUtils.isEmpty(url)) return;
483 if (!mClientManager.isPrerenderingAllowed(uid)) return; 512 if (!mClientManager.isPrerenderingAllowed(uid)) return;
513
514 // A prerender will be requested. Time to destroy the spare WebContents.
515 destroySpareWebContents();
Yusuf 2015/10/29 16:35:27 since it is a spare one, can we just reuse that? i
Benoit L 2015/10/29 17:12:36 Unfortunately, the prerender logic cannot use an e
516
484 Intent extrasIntent = new Intent(); 517 Intent extrasIntent = new Intent();
485 if (extras != null) extrasIntent.putExtras(extras); 518 if (extras != null) extrasIntent.putExtras(extras);
486 if (IntentHandler.getExtraHeadersFromIntent(extrasIntent) != null) retur n; 519 if (IntentHandler.getExtraHeadersFromIntent(extrasIntent) != null) retur n;
487 if (mExternalPrerenderHandler == null) { 520 if (mExternalPrerenderHandler == null) {
488 mExternalPrerenderHandler = new ExternalPrerenderHandler(); 521 mExternalPrerenderHandler = new ExternalPrerenderHandler();
489 } 522 }
490 Point contentSize = estimateContentSize(); 523 Point contentSize = estimateContentSize();
491 Context context = mApplication.getApplicationContext(); 524 Context context = mApplication.getApplicationContext();
492 String referrer = IntentHandler.getReferrerUrlIncludingExtraHeaders(extr asIntent, context); 525 String referrer = IntentHandler.getReferrerUrlIncludingExtraHeaders(extr asIntent, context);
493 if (referrer == null && getReferrerForSession(session) != null) { 526 if (referrer == null && getReferrerForSession(session) != null) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 screenSize.x /= density; 562 screenSize.x /= density;
530 screenSize.y /= density; 563 screenSize.y /= density;
531 return screenSize; 564 return screenSize;
532 } 565 }
533 566
534 @VisibleForTesting 567 @VisibleForTesting
535 void resetThrottling(Context context, int uid) { 568 void resetThrottling(Context context, int uid) {
536 mClientManager.resetThrottling(uid); 569 mClientManager.resetThrottling(uid);
537 } 570 }
538 } 571 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698