blob: 3cc80ad789305f170794b72b431f450f431f6bdf [file] [log] [blame]
// Copyright 2017 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.content_shell_apk;
import org.chromium.base.process_launcher.ChildProcessCreationParams;
import org.chromium.base.process_launcher.FileDescriptorInfo;
import org.chromium.base.process_launcher.IChildProcessService;
import org.chromium.content.browser.ChildProcessConnection;
import org.chromium.content.browser.ChildProcessLauncherHelper;
import org.chromium.content.browser.LauncherThread;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.Semaphore;
/** An assortment of static methods used in tests that deal with launching child processes. */
public final class ChildProcessLauncherTestUtils {
// Do not instanciate, use static methods instead.
private ChildProcessLauncherTestUtils() {}
public static void runOnLauncherThreadBlocking(final Runnable runnable) {
if (LauncherThread.runningOnLauncherThread()) {
runnable.run();
return;
}
final Semaphore done = new Semaphore(0);
LauncherThread.post(new Runnable() {
@Override
public void run() {
runnable.run();
done.release();
}
});
done.acquireUninterruptibly();
}
public static <R> R runOnLauncherAndGetResult(Callable<R> callable) {
if (LauncherThread.runningOnLauncherThread()) {
try {
return callable.call();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
try {
FutureTask<R> task = new FutureTask<R>(callable);
LauncherThread.post(task);
return task.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static ChildProcessLauncherHelper startForTesting(final boolean sandboxed,
final String[] commandLine, final FileDescriptorInfo[] filesToBeMapped,
final ChildProcessCreationParams params, final boolean doSetupConnection) {
return runOnLauncherAndGetResult(new Callable<ChildProcessLauncherHelper>() {
@Override
public ChildProcessLauncherHelper call() {
return ChildProcessLauncherHelper.createAndStartForTesting(params, commandLine,
filesToBeMapped, sandboxed, null /* binderCallback */, doSetupConnection);
}
});
}
public static ChildProcessConnection getConnection(
final ChildProcessLauncherHelper childProcessLauncher) {
return runOnLauncherAndGetResult(new Callable<ChildProcessConnection>() {
@Override
public ChildProcessConnection call() {
return childProcessLauncher.getChildProcessConnection();
}
});
}
// Retrieves the PID of the passed in connection on the launcher thread as to not assert.
public static int getConnectionPid(final ChildProcessConnection connection) {
return runOnLauncherAndGetResult(new Callable<Integer>() {
@Override
public Integer call() {
return connection.getPid();
}
});
}
// Retrieves the service number of the passed in connection from its service name, or -1 if the
// service number could not be determined.
public static int getConnectionServiceNumber(final ChildProcessConnection connection) {
String serviceName = getConnectionServiceName(connection);
// The service name ends up with the service number.
StringBuilder numberString = new StringBuilder();
for (int i = serviceName.length() - 1; i >= 0; i--) {
char c = serviceName.charAt(i);
if (!Character.isDigit(c)) {
break;
}
numberString.append(c);
}
try {
return Integer.decode(numberString.toString());
} catch (NumberFormatException nfe) {
return -1;
}
}
// Retrieves the service number of the passed in connection on the launcher thread as to not
// assert.
public static String getConnectionServiceName(final ChildProcessConnection connection) {
return runOnLauncherAndGetResult(new Callable<String>() {
@Override
public String call() {
return connection.getServiceName().getClassName();
}
});
}
// Retrieves the service of the passed in connection on the launcher thread as to not assert.
public static IChildProcessService getConnectionService(
final ChildProcessConnection connection) {
return runOnLauncherAndGetResult(new Callable<IChildProcessService>() {
@Override
public IChildProcessService call() {
return connection.getService();
}
});
}
}