Commit 475d0979 authored by lizeb's avatar lizeb Committed by Commit bot

customtabs: Refactor CustomTabsConnection to simplify locking.

This refactoring of CustomTabsConnection has two benefits:
- Move the client and session handling logic away from CustomTabsConnection.
- Simplify locking in CustomTabsConnection, as it is all handled by
  ClientManager.

Some methods in CustomTabsConnection are now simple pass-through. These
will be removed in a subsequent CL. Leaving these here means that no
test code is affected.

Review URL: https://codereview.chromium.org/1370473002

Cr-Commit-Position: refs/heads/master@{#351146}
parent 70e884bc
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.customtabs;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
import android.support.customtabs.ICustomTabsCallback;
import android.text.TextUtils;
import org.chromium.base.ThreadUtils;
import org.chromium.base.annotations.SuppressFBWarnings;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.browser.IntentHandler;
import org.chromium.content_public.common.Referrer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/** Manages the clients' state for Custom Tabs. This class is threadsafe. */
class ClientManager {
// Values for the "CustomTabs.PredictionStatus" UMA histogram. Append-only.
private static final int NO_PREDICTION = 0;
private static final int GOOD_PREDICTION = 1;
private static final int BAD_PREDICTION = 2;
private static final int PREDICTION_STATUS_COUNT = 3;
/** Per-session values. */
private static class SessionParams {
public final int uid;
public final Referrer referrer;
public final ICustomTabsCallback callback;
public final IBinder.DeathRecipient deathRecipient;
private ServiceConnection mKeepAliveConnection = null;
private String mPredictedUrl = null;
private long mLastMayLaunchUrlTimestamp = 0;
public SessionParams(Context context, int uid, ICustomTabsCallback callback,
IBinder.DeathRecipient deathRecipient) {
this.uid = uid;
referrer = constructReferrer(context, uid);
this.callback = callback;
this.deathRecipient = deathRecipient;
}
private static Referrer constructReferrer(Context context, int uid) {
PackageManager packageManager = context.getPackageManager();
String[] packageList = packageManager.getPackagesForUid(uid);
if (packageList.length != 1 || TextUtils.isEmpty(packageList[0])) return null;
return IntentHandler.constructValidReferrerForAuthority(packageList[0]);
}
public ServiceConnection getKeepAliveConnection() {
return mKeepAliveConnection;
}
public void setKeepAliveConnection(ServiceConnection serviceConnection) {
mKeepAliveConnection = serviceConnection;
}
public void setPredictionMetrics(String predictedUrl, long lastMayLaunchUrlTimestamp) {
mPredictedUrl = predictedUrl;
mLastMayLaunchUrlTimestamp = lastMayLaunchUrlTimestamp;
}
public String getPredictedUrl() {
return mPredictedUrl;
}
public long getLastMayLaunchUrlTimestamp() {
return mLastMayLaunchUrlTimestamp;
}
}
/** To be called when a client gets disconnected. */
public interface DisconnectCallback { public void run(IBinder session); }
private final Context mContext;
private final Map<IBinder, SessionParams> mSessionParams = new HashMap<>();
public ClientManager(Context context) {
mContext = context.getApplicationContext();
RequestThrottler.purgeOldEntries(mContext);
}
/** Creates a new session.
*
* @param cb Callback provided by the client.
* @param uid Client UID, as returned by Binder.getCallingUid(),
* @param onDisconnect To be called on the UI thread when a client gets disconnected.
* @return true for success.
*/
public boolean newSession(
ICustomTabsCallback cb, int uid, final DisconnectCallback onDisconnect) {
if (cb == null) return false;
final IBinder session = cb.asBinder();
IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
ThreadUtils.postOnUiThread(new Runnable() {
@Override
public void run() {
cleanupSession(session);
onDisconnect.run(session);
}
});
}
};
SessionParams params = new SessionParams(mContext, uid, cb, deathRecipient);
synchronized (this) {
if (mSessionParams.containsKey(session)) return false;
try {
session.linkToDeath(deathRecipient, 0);
} catch (RemoteException e) {
// The return code doesn't matter, because this executes when
// the caller has died.
return false;
}
mSessionParams.put(session, params);
}
return true;
}
/** Updates the client behavior stats and returns whether speculation is allowed.
*
* @param session Client session.
* @param uid As returned by Binder.getCallingUid().
* @param url Predicted URL.
* @return true if speculation is allowed.
*/
@SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
public synchronized boolean updateStatsAndReturnWhetherAllowed(
IBinder session, int uid, String url) {
SessionParams params = mSessionParams.get(session);
if (params == null || params.uid != uid) return false;
params.setPredictionMetrics(url, SystemClock.elapsedRealtime());
RequestThrottler throttler = RequestThrottler.getForUid(mContext, uid);
return throttler.updateStatsAndReturnWhetherAllowed();
}
/**
* Registers that a client has launched a URL inside a Custom Tab.
*/
@SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
public synchronized void registerLaunch(IBinder session, String url) {
int outcome = NO_PREDICTION;
long elapsedTimeMs = -1;
SessionParams params = mSessionParams.get(session);
if (params != null) {
String predictedUrl = params.getPredictedUrl();
outcome = predictedUrl == null ? NO_PREDICTION : predictedUrl.equals(url)
? GOOD_PREDICTION
: BAD_PREDICTION;
long now = SystemClock.elapsedRealtime();
elapsedTimeMs = now - params.getLastMayLaunchUrlTimestamp();
params.setPredictionMetrics(null, 0);
if (outcome == GOOD_PREDICTION) {
RequestThrottler.getForUid(mContext, params.uid).registerSuccess(url);
}
}
RecordHistogram.recordEnumeratedHistogram(
"CustomTabs.PredictionStatus", outcome, PREDICTION_STATUS_COUNT);
if (outcome == GOOD_PREDICTION) {
RecordHistogram.recordCustomTimesHistogram("CustomTabs.PredictionToLaunch",
elapsedTimeMs, 1, TimeUnit.MINUTES.toMillis(3), TimeUnit.MILLISECONDS, 100);
}
}
@SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
public synchronized Referrer getReferrerForSession(IBinder session) {
SessionParams params = mSessionParams.get(session);
return params != null ? params.referrer : null;
}
@SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
public synchronized ICustomTabsCallback getCallbackForSession(IBinder session) {
SessionParams params = mSessionParams.get(session);
return params != null ? params.callback : null;
}
/** Tries to bind to a client to keep it alive, and returns true for success. */
@SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
public synchronized boolean keepAliveForSession(IBinder session, Intent intent) {
// When an application is bound to a service, its priority is raised to
// be at least equal to the application's one. This binds to a dummy
// service (no calls to this service are made).
if (intent == null || intent.getComponent() == null) return false;
SessionParams params = mSessionParams.get(session);
if (params == null) return false;
String packageName = intent.getComponent().getPackageName();
PackageManager pm = mContext.getApplicationContext().getPackageManager();
// Only binds to the application associated to this session.
if (!Arrays.asList(pm.getPackagesForUid(params.uid)).contains(packageName)) return false;
Intent serviceIntent = new Intent().setComponent(intent.getComponent());
// This ServiceConnection doesn't handle disconnects. This is on
// purpose, as it occurs when the remote process has died. Since the
// only use of this connection is to keep the application alive,
// re-connecting would just re-create the process, but the application
// state has been lost at that point, the callbacks invalidated, etc.
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {}
@Override
public void onServiceDisconnected(ComponentName name) {}
};
boolean ok;
try {
ok = mContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE);
} catch (SecurityException e) {
return false;
}
if (ok) params.setKeepAliveConnection(connection);
return ok;
}
/** Unbind from the KeepAlive service for a client. */
@SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
public synchronized void dontKeepAliveForSession(IBinder session) {
SessionParams params = mSessionParams.get(session);
if (params == null || params.getKeepAliveConnection() == null) return;
ServiceConnection connection = params.getKeepAliveConnection();
params.setKeepAliveConnection(null);
mContext.unbindService(connection);
}
@SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
public synchronized boolean isPrerenderingAllowed(int uid) {
return RequestThrottler.getForUid(mContext, uid).isPrerenderingAllowed();
}
@SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
public synchronized void registerPrerenderRequest(int uid, String url) {
RequestThrottler.getForUid(mContext, uid).registerPrerenderRequest(url);
}
@SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
public synchronized void resetThrottling(int uid) {
RequestThrottler.getForUid(mContext, uid).reset();
}
@SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
public synchronized void cleanupAll() {
List<IBinder> sessions = new ArrayList<>(mSessionParams.keySet());
for (IBinder session : sessions) cleanupSession(session);
}
@SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD")
private synchronized void cleanupSession(IBinder session) {
SessionParams params = mSessionParams.get(session);
if (params == null) return;
mSessionParams.remove(session);
IBinder binder = params.callback.asBinder();
binder.unlinkToDeath(params.deathRecipient, 0);
}
}
...@@ -6,11 +6,8 @@ package org.chromium.chrome.browser.customtabs; ...@@ -6,11 +6,8 @@ package org.chromium.chrome.browser.customtabs;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.Application; import android.app.Application;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Point; import android.graphics.Point;
...@@ -22,8 +19,6 @@ import android.os.Build; ...@@ -22,8 +19,6 @@ import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.Process; import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.support.customtabs.CustomTabsIntent; import android.support.customtabs.CustomTabsIntent;
import android.support.customtabs.ICustomTabsCallback; import android.support.customtabs.ICustomTabsCallback;
import android.support.customtabs.ICustomTabsService; import android.support.customtabs.ICustomTabsService;
...@@ -36,7 +31,6 @@ import org.chromium.base.ThreadUtils; ...@@ -36,7 +31,6 @@ import org.chromium.base.ThreadUtils;
import org.chromium.base.VisibleForTesting; import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.SuppressFBWarnings; import org.chromium.base.annotations.SuppressFBWarnings;
import org.chromium.base.library_loader.ProcessInitException; import org.chromium.base.library_loader.ProcessInitException;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeApplication; import org.chromium.chrome.browser.ChromeApplication;
import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.IntentHandler;
...@@ -55,14 +49,9 @@ import org.chromium.content_public.common.Referrer; ...@@ -55,14 +49,9 @@ import org.chromium.content_public.common.Referrer;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
...@@ -78,12 +67,6 @@ public class CustomTabsConnection extends ICustomTabsService.Stub { ...@@ -78,12 +67,6 @@ public class CustomTabsConnection extends ICustomTabsService.Stub {
static final String NO_PRERENDERING_KEY = static final String NO_PRERENDERING_KEY =
"android.support.customtabs.maylaunchurl.NO_PRERENDERING"; "android.support.customtabs.maylaunchurl.NO_PRERENDERING";
// Values for the "CustomTabs.PredictionStatus" UMA histogram. Append-only.
private static final int NO_PREDICTION = 0;
private static final int GOOD_PREDICTION = 1;
private static final int BAD_PREDICTION = 2;
private static final int PREDICTION_STATUS_COUNT = 3;
private static AtomicReference<CustomTabsConnection> sInstance = private static AtomicReference<CustomTabsConnection> sInstance =
new AtomicReference<CustomTabsConnection>(); new AtomicReference<CustomTabsConnection>();
...@@ -106,63 +89,11 @@ public class CustomTabsConnection extends ICustomTabsService.Stub { ...@@ -106,63 +89,11 @@ public class CustomTabsConnection extends ICustomTabsService.Stub {
protected final Application mApplication; protected final Application mApplication;
private final AtomicBoolean mWarmupHasBeenCalled = new AtomicBoolean(); private final AtomicBoolean mWarmupHasBeenCalled = new AtomicBoolean();
private final ClientManager mClientManager;
private ExternalPrerenderHandler mExternalPrerenderHandler; private ExternalPrerenderHandler mExternalPrerenderHandler;
private PrerenderedUrlParams mPrerender; private PrerenderedUrlParams mPrerender;
private WebContents mSpareWebContents; private WebContents mSpareWebContents;
/** Per-session values. */
private static class SessionParams {
public final int mUid;
public final Referrer mReferrer;
public final ICustomTabsCallback mCallback;
public final IBinder.DeathRecipient mDeathRecipient;
private ServiceConnection mServiceConnection;
private String mPredictedUrl;
private long mLastMayLaunchUrlTimestamp;
public SessionParams(Context context, int uid, ICustomTabsCallback callback,
IBinder.DeathRecipient deathRecipient) {
mUid = uid;
mCallback = callback;
mDeathRecipient = deathRecipient;
mServiceConnection = null;
mPredictedUrl = null;
mLastMayLaunchUrlTimestamp = 0;
mReferrer = constructReferrer(context);
}
private Referrer constructReferrer(Context context) {
PackageManager packageManager = context.getPackageManager();
String[] packageList = packageManager.getPackagesForUid(mUid);
if (packageList.length != 1 || TextUtils.isEmpty(packageList[0])) return null;
return IntentHandler.constructValidReferrerForAuthority(packageList[0]);
}
public ServiceConnection getServiceConnection() {
return mServiceConnection;
}
public void setServiceConnection(ServiceConnection serviceConnection) {
mServiceConnection = serviceConnection;
}
public void setPredictionMetrics(String predictedUrl, long lastMayLaunchUrlTimestamp) {
mPredictedUrl = predictedUrl;
mLastMayLaunchUrlTimestamp = lastMayLaunchUrlTimestamp;
}
public String getPredictedUrl() {
return mPredictedUrl;
}
public long getLastMayLaunchUrlTimestamp() {
return mLastMayLaunchUrlTimestamp;
}
}
private final Object mLock = new Object();
private final Map<IBinder, SessionParams> mSessionParams = new HashMap<>();
/** /**
* <strong>DO NOT CALL</strong> * <strong>DO NOT CALL</strong>
* Public to be instanciable from {@link ChromeApplication}. This is however * Public to be instanciable from {@link ChromeApplication}. This is however
...@@ -171,9 +102,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub { ...@@ -171,9 +102,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub {
public CustomTabsConnection(Application application) { public CustomTabsConnection(Application application) {
super(); super();
mApplication = application; mApplication = application;
synchronized (mLock) { mClientManager = new ClientManager(mApplication);
RequestThrottler.purgeOldEntries(application);
}
} }
/** /**
...@@ -190,37 +119,13 @@ public class CustomTabsConnection extends ICustomTabsService.Stub { ...@@ -190,37 +119,13 @@ public class CustomTabsConnection extends ICustomTabsService.Stub {
@Override @Override
public boolean newSession(ICustomTabsCallback callback) { public boolean newSession(ICustomTabsCallback callback) {
if (callback == null) return false; ClientManager.DisconnectCallback onDisconnect = new ClientManager.DisconnectCallback() {
final int uid = Binder.getCallingUid();
final IBinder session = callback.asBinder();
IBinder.DeathRecipient deathRecipient =
new IBinder.DeathRecipient() {
@Override @Override
public void binderDied() { public void run(IBinder session) {
ThreadUtils.postOnUiThread(new Runnable() { cancelPrerender(session);
@Override
public void run() {
synchronized (mLock) {
cleanupAlreadyLocked(session);
}
}
});
} }
}; };
SessionParams sessionParams = return mClientManager.newSession(callback, Binder.getCallingUid(), onDisconnect);
new SessionParams(mApplication, uid, callback, deathRecipient);
synchronized (mLock) {
if (mSessionParams.containsKey(session)) return false;
try {
callback.asBinder().linkToDeath(deathRecipient, 0);
} catch (RemoteException e) {
// The return code doesn't matter, because this executes when
// the caller has died.
return false;
}
mSessionParams.put(session, sessionParams);
}
return true;
} }
@Override @Override
...@@ -292,12 +197,8 @@ public class CustomTabsConnection extends ICustomTabsService.Stub { ...@@ -292,12 +197,8 @@ public class CustomTabsConnection extends ICustomTabsService.Stub {
final boolean noPrerendering = final boolean noPrerendering =
extras != null ? extras.getBoolean(NO_PRERENDERING_KEY, false) : false; extras != null ? extras.getBoolean(NO_PRERENDERING_KEY, false) : false;
final int uid = Binder.getCallingUid(); final int uid = Binder.getCallingUid();
synchronized (mLock) { if (!mClientManager.updateStatsAndReturnWhetherAllowed(session, uid, urlString)) {
SessionParams sessionParams = mSessionParams.get(session); return false;
if (sessionParams == null || sessionParams.mUid != uid) return false;
sessionParams.setPredictionMetrics(urlString, SystemClock.elapsedRealtime());
RequestThrottler throttler = RequestThrottler.getForUid(mApplication, uid);
if (!throttler.updateStatsAndReturnWhetherAllowed()) return false;
} }
ThreadUtils.postOnUiThread(new Runnable() { ThreadUtils.postOnUiThread(new Runnable() {
@Override @Override
...@@ -373,31 +274,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub { ...@@ -373,31 +274,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub {
* This is used for accounting. * This is used for accounting.
*/ */
void registerLaunch(IBinder session, String url) { void registerLaunch(IBinder session, String url) {
int outcome; mClientManager.registerLaunch(session, url);
long elapsedTimeMs = -1;
synchronized (mLock) {
SessionParams sessionParams = mSessionParams.get(session);
if (sessionParams == null) {
outcome = NO_PREDICTION;
} else {
String predictedUrl = sessionParams.getPredictedUrl();
outcome = predictedUrl == null ? NO_PREDICTION
: predictedUrl.equals(url) ? GOOD_PREDICTION : BAD_PREDICTION;
elapsedTimeMs = SystemClock.elapsedRealtime()
- sessionParams.getLastMayLaunchUrlTimestamp();
sessionParams.setPredictionMetrics(null, 0);
if (outcome == GOOD_PREDICTION) {
RequestThrottler.getForUid(mApplication, sessionParams.mUid)
.registerSuccess(url);
}
}
}
RecordHistogram.recordEnumeratedHistogram(
"CustomTabs.PredictionStatus", outcome, PREDICTION_STATUS_COUNT);
if (outcome == GOOD_PREDICTION) {
RecordHistogram.recordCustomTimesHistogram("CustomTabs.PredictionToLaunch",
elapsedTimeMs, 1, TimeUnit.MINUTES.toMillis(3), TimeUnit.MILLISECONDS, 100);
}
} }
/** /**
...@@ -446,16 +323,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub { ...@@ -446,16 +323,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub {
} }
public Referrer getReferrerForSession(IBinder session) { public Referrer getReferrerForSession(IBinder session) {
if (!mSessionParams.containsKey(session)) return null; return mClientManager.getReferrerForSession(session);
return mSessionParams.get(session).mReferrer;
}
private ICustomTabsCallback getCallbackForSession(IBinder session) {
synchronized (mLock) {
SessionParams sessionParams = mSessionParams.get(session);
if (sessionParams == null) return null;
return sessionParams.mCallback;
}
} }
/** /**
...@@ -469,7 +337,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub { ...@@ -469,7 +337,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub {
* @return true for success. * @return true for success.
*/ */
boolean notifyNavigationEvent(IBinder session, int navigationEvent) { boolean notifyNavigationEvent(IBinder session, int navigationEvent) {
ICustomTabsCallback callback = getCallbackForSession(session); ICustomTabsCallback callback = mClientManager.getCallbackForSession(session);
if (callback == null) return false; if (callback == null) return false;
try { try {
callback.onNavigationEvent(navigationEvent, null); callback.onNavigationEvent(navigationEvent, null);
...@@ -494,41 +362,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub { ...@@ -494,41 +362,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub {
* @return true for success. * @return true for success.
*/ */
boolean keepAliveForSession(IBinder session, Intent intent) { boolean keepAliveForSession(IBinder session, Intent intent) {
// When an application is bound to a service, its priority is raised to return mClientManager.keepAliveForSession(session, intent);
// be at least equal to the application's one. This binds to a dummy
// service (no calls to this service are made).
if (intent == null || intent.getComponent() == null) return false;
SessionParams sessionParams;
synchronized (mLock) {
sessionParams = mSessionParams.get(session);
if (sessionParams == null) return false;
}
String packageName = intent.getComponent().getPackageName();
PackageManager pm = mApplication.getApplicationContext().getPackageManager();
// Only binds to the application associated to this session.
int uid = sessionParams.mUid;
if (!Arrays.asList(pm.getPackagesForUid(uid)).contains(packageName)) return false;
Intent serviceIntent = new Intent().setComponent(intent.getComponent());
// This ServiceConnection doesn't handle disconnects. This is on
// purpose, as it occurs when the remote process has died. Since the
// only use of this connection is to keep the application alive,
// re-connecting would just re-create the process, but the application
// state has been lost at that point, the callbacks invalidated, etc.
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {}
@Override
public void onServiceDisconnected(ComponentName name) {}
};
boolean ok;
try {
ok = mApplication.getApplicationContext().bindService(
serviceIntent, connection, Context.BIND_AUTO_CREATE);
} catch (SecurityException e) {
return false;
}
if (ok) sessionParams.setServiceConnection(connection);
return ok;
} }
/** /**
...@@ -539,14 +373,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub { ...@@ -539,14 +373,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub {
* @param session The Binder object identifying the session. * @param session The Binder object identifying the session.
*/ */
void dontKeepAliveForSession(IBinder session) { void dontKeepAliveForSession(IBinder session) {
SessionParams sessionParams; mClientManager.dontKeepAliveForSession(session);
synchronized (mLock) {
sessionParams = mSessionParams.get(session);
if (sessionParams == null || sessionParams.getServiceConnection() == null) return;
}
ServiceConnection serviceConnection = sessionParams.getServiceConnection();
sessionParams.setServiceConnection(null);
mApplication.getApplicationContext().unbindService(serviceConnection);
} }
/** /**
...@@ -613,23 +440,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub { ...@@ -613,23 +440,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub {
@VisibleForTesting @VisibleForTesting
void cleanupAll() { void cleanupAll() {
ThreadUtils.assertOnUiThread(); ThreadUtils.assertOnUiThread();
synchronized (mLock) { mClientManager.cleanupAll();
List<IBinder> sessions = new ArrayList<>(mSessionParams.keySet());
for (IBinder session : sessions) cleanupAlreadyLocked(session);
}
}
/**
* Called when a remote client has died.
*/
private void cleanupAlreadyLocked(IBinder session) {
ThreadUtils.assertOnUiThread();
SessionParams params = mSessionParams.get(session);
if (params == null) return;
mSessionParams.remove(session);
IBinder binder = params.mCallback.asBinder();
binder.unlinkToDeath(params.mDeathRecipient, 0);
cancelPrerender(session);
} }
private boolean mayPrerender() { private boolean mayPrerender() {
...@@ -663,9 +474,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub { ...@@ -663,9 +474,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub {
// Last one wins and cancels the previous prerender. // Last one wins and cancels the previous prerender.
cancelPrerender(null); cancelPrerender(null);
if (TextUtils.isEmpty(url)) return; if (TextUtils.isEmpty(url)) return;
synchronized (mLock) { if (!mClientManager.isPrerenderingAllowed(uid)) return;
if (!RequestThrottler.getForUid(mApplication, uid).isPrerenderingAllowed()) return;
}
Intent extrasIntent = new Intent(); Intent extrasIntent = new Intent();
if (extras != null) extrasIntent.putExtras(extras); if (extras != null) extrasIntent.putExtras(extras);
if (IntentHandler.getExtraHeadersFromIntent(extrasIntent) != null) return; if (IntentHandler.getExtraHeadersFromIntent(extrasIntent) != null) return;
...@@ -682,9 +491,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub { ...@@ -682,9 +491,7 @@ public class CustomTabsConnection extends ICustomTabsService.Stub {
WebContents webContents = mExternalPrerenderHandler.addPrerender( WebContents webContents = mExternalPrerenderHandler.addPrerender(
Profile.getLastUsedProfile(), url, referrer, contentSize.x, contentSize.y); Profile.getLastUsedProfile(), url, referrer, contentSize.x, contentSize.y);
if (webContents != null) { if (webContents != null) {
synchronized (mLock) { mClientManager.registerPrerenderRequest(uid, url);
RequestThrottler.getForUid(mApplication, uid).registerPrerenderRequest(url);
}
mPrerender = new PrerenderedUrlParams(session, webContents, url, referrer, extras); mPrerender = new PrerenderedUrlParams(session, webContents, url, referrer, extras);
} }
} }
...@@ -720,8 +527,6 @@ public class CustomTabsConnection extends ICustomTabsService.Stub { ...@@ -720,8 +527,6 @@ public class CustomTabsConnection extends ICustomTabsService.Stub {
@VisibleForTesting @VisibleForTesting
void resetThrottling(Context context, int uid) { void resetThrottling(Context context, int uid) {
synchronized (mLock) { mClientManager.resetThrottling(uid);
RequestThrottler.getForUid(context, uid).reset();
}
} }
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment