// 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.browser;

import android.content.Context;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.text.TextUtils;

import org.chromium.base.ContextUtils;
import org.chromium.base.CpuFeatures;
import org.chromium.base.Log;
import org.chromium.base.ThreadUtils;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.SuppressFBWarnings;
import org.chromium.base.library_loader.Linker;
import org.chromium.base.process_launcher.ChildConnectionAllocator;
import org.chromium.base.process_launcher.ChildProcessConnection;
import org.chromium.base.process_launcher.ChildProcessConstants;
import org.chromium.base.process_launcher.ChildProcessCreationParams;
import org.chromium.base.process_launcher.ChildProcessLauncher;
import org.chromium.base.process_launcher.FileDescriptorInfo;
import org.chromium.content.app.ChromiumLinkerParams;
import org.chromium.content.app.SandboxedProcessService;
import org.chromium.content.common.ContentSwitches;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * This is the java counterpart to ChildProcessLauncherHelper. It is owned by native side and
 * has an explicit destroy method.
 * Each public or jni methods should have explicit documentation on what threads they are called.
 */
@JNINamespace("content::internal")
public class ChildProcessLauncherHelper {
    private static final String TAG = "ChildProcLH";

    // Manifest values used to specify the service names.
    private static final String NUM_SANDBOXED_SERVICES_KEY =
            "org.chromium.content.browser.NUM_SANDBOXED_SERVICES";
    private static final String SANDBOXED_SERVICES_NAME_KEY =
            "org.chromium.content.browser.SANDBOXED_SERVICES_NAME";
    private static final String NUM_PRIVILEGED_SERVICES_KEY =
            "org.chromium.content.browser.NUM_PRIVILEGED_SERVICES";
    private static final String PRIVILEGED_SERVICES_NAME_KEY =
            "org.chromium.content.browser.PRIVILEGED_SERVICES_NAME";

    // A warmed-up connection to a sandboxed service.
    private static SpareChildConnection sSpareSandboxedConnection;

    // Map from package name to ChildConnectionAllocator.
    private static final Map<String, ChildConnectionAllocator>
            sSandboxedChildConnectionAllocatorMap = new HashMap<>();

    // Map from PID to ChildProcessLauncherHelper.
    private static final Map<Integer, ChildProcessLauncherHelper> sLauncherByPid = new HashMap<>();

    // Allocator used for non-sandboxed services.
    private static ChildConnectionAllocator sPrivilegedChildConnectionAllocator;

    // Used by tests to override the default sandboxed service allocator settings.
    private static ChildConnectionAllocator.ConnectionFactory sSandboxedServiceFactoryForTesting;
    private static int sSandboxedServicesCountForTesting = -1;
    private static String sSandboxedServicesNameForTesting;

    // Manages OOM bindings used to bind chind services. Lazily initialized by getBindingManager().
    private static BindingManager sBindingManager;

    // Whether the main application is currently brought to the foreground.
    private static boolean sApplicationInForeground = true;

    // Whether the connection is managed by the BindingManager.
    private final boolean mUseBindingManager;

    private final ChildProcessCreationParams mCreationParams;

    // Whether the created process should be sandboxed.
    private final boolean mSandboxed;

    private final ChildProcessLauncher.Delegate mLauncherDelegate =
            new ChildProcessLauncher.Delegate() {
                @Override
                public void onBeforeConnectionAllocated(Bundle bundle) {
                    populateServiceBundle(bundle, mCreationParams);
                }

                @Override
                public void onBeforeConnectionSetup(Bundle connectionBundle) {
                    // Populate the bundle passed to the service setup call with content specific
                    // parameters.
                    connectionBundle.putInt(
                            ContentChildProcessConstants.EXTRA_CPU_COUNT, CpuFeatures.getCount());
                    connectionBundle.putLong(
                            ContentChildProcessConstants.EXTRA_CPU_FEATURES, CpuFeatures.getMask());
                    connectionBundle.putBundle(Linker.EXTRA_LINKER_SHARED_RELROS,
                            Linker.getInstance().getSharedRelros());
                }

                @Override
                public void onConnectionEstablished(ChildProcessConnection connection) {
                    int pid = connection.getPid();
                    assert pid > 0;

                    sLauncherByPid.put(pid, ChildProcessLauncherHelper.this);

                    if (mUseBindingManager) {
                        getBindingManager().addNewConnection(pid, connection);
                    }

                    // If the connection fails and pid == 0, the Java-side cleanup was already
                    // handled by DeathCallback. We still have to call back to native for cleanup
                    // there.
                    if (mNativeChildProcessLauncherHelper != 0) {
                        nativeOnChildProcessStarted(
                                mNativeChildProcessLauncherHelper, connection.getPid());
                    }
                    mNativeChildProcessLauncherHelper = 0;
                }

                @Override
                public void onConnectionLost(ChildProcessConnection connection) {
                    assert connection.getPid() > 0;
                    sLauncherByPid.remove(connection.getPid());
                    if (mUseBindingManager) {
                        getBindingManager().removeConnection(connection.getPid());
                    }
                }
            };

    private final ChildProcessLauncher mLauncher;

    // Note native pointer is only guaranteed live until nativeOnChildProcessStarted.
    private long mNativeChildProcessLauncherHelper;

    @CalledByNative
    private static FileDescriptorInfo makeFdInfo(
            int id, int fd, boolean autoClose, long offset, long size) {
        assert LauncherThread.runningOnLauncherThread();
        ParcelFileDescriptor pFd;
        if (autoClose) {
            // Adopt the FD, it will be closed when we close the ParcelFileDescriptor.
            pFd = ParcelFileDescriptor.adoptFd(fd);
        } else {
            try {
                pFd = ParcelFileDescriptor.fromFd(fd);
            } catch (IOException e) {
                Log.e(TAG, "Invalid FD provided for process connection, aborting connection.", e);
                return null;
            }
        }
        return new FileDescriptorInfo(id, pFd, offset, size);
    }

    @VisibleForTesting
    @CalledByNative
    public static ChildProcessLauncherHelper createAndStart(long nativePointer, int paramId,
            String[] commandLine, FileDescriptorInfo[] filesToBeMapped) {
        assert LauncherThread.runningOnLauncherThread();
        ChildProcessCreationParams creationParams = ChildProcessCreationParams.get(paramId);
        if (paramId != ChildProcessCreationParams.DEFAULT_ID && creationParams == null) {
            throw new RuntimeException("CreationParams id " + paramId + " not found");
        }

        String processType =
                ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWITCH_PROCESS_TYPE);

        boolean sandboxed = true;
        if (!ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) {
            if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) {
                sandboxed = false;
            } else {
                // We only support sandboxed utility processes now.
                assert ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType);
            }
        }

        IBinder binderCallback = ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)
                ? new GpuProcessCallback()
                : null;

        ChildProcessLauncherHelper processLauncher = new ChildProcessLauncherHelper(nativePointer,
                creationParams, commandLine, filesToBeMapped, sandboxed, binderCallback);
        processLauncher.mLauncher.start(
                true /* doSetupConnection */, true /* queueIfNoFreeConnection */);
        return processLauncher;
    }

    /**
     * Creates a ready to use sandboxed child process. Should be called early during startup so the
     * child process is created while other startup work is happening.
     * @param context the application context used for the connection.
     */
    public static void warmUp(final Context context) {
        assert ThreadUtils.runningOnUiThread();
        LauncherThread.post(new Runnable() {
            @Override
            public void run() {
                warmUpOnLauncherThread(context);
            }
        });
    }

    private static void warmUpOnLauncherThread(Context context) {
        if (sSpareSandboxedConnection != null && !sSpareSandboxedConnection.isEmpty()) {
            return;
        }

        ChildProcessCreationParams creationParams = ChildProcessCreationParams.getDefault();
        Bundle serviceBundle = populateServiceBundle(new Bundle(), creationParams);
        ChildConnectionAllocator allocator =
                getConnectionAllocator(context, creationParams, true /* sandboxed */);
        sSpareSandboxedConnection = new SpareChildConnection(context, allocator, serviceBundle);
    }

    public static String getPackageNameFromCreationParams(
            Context context, ChildProcessCreationParams params, boolean sandboxed) {
        return (sandboxed && params != null) ? params.getPackageNameForSandboxedService()
                                             : context.getPackageName();
    }

    public static boolean isServiceExternalFromCreationParams(
            ChildProcessCreationParams params, boolean sandboxed) {
        return sandboxed && params != null && params.getIsSandboxedServiceExternal();
    }

    /**
     * Starts the moderate binding management that adjust a process priority in response to various
     * signals (app sent to background/foreground for example).
     * Note: WebAPKs and non WebAPKs share the same moderate binding pool, so the size of the
     * shared moderate binding pool is always set based on the number of sandboxes processes
     * used by Chrome.
     * @param context Android's context.
     */
    public static void startModerateBindingManagement(final Context context) {
        assert ThreadUtils.runningOnUiThread();
        LauncherThread.post(new Runnable() {
            @Override
            public void run() {
                ChildConnectionAllocator allocator = getConnectionAllocator(
                        context, ChildProcessCreationParams.getDefault(), true /* sandboxed */);
                getBindingManager().startModerateBindingManagement(
                        context, allocator.getNumberOfServices());
            }
        });
    }

    // Lazy initialize sBindingManager
    // TODO(boliu): This should be internal to content.
    @SuppressFBWarnings("LI_LAZY_INIT_STATIC") // Method is single thread.
    public static BindingManager getBindingManager() {
        assert LauncherThread.runningOnLauncherThread();
        if (sBindingManager == null) {
            sBindingManager = BindingManagerImpl.createBindingManager();
        }
        return sBindingManager;
    }

    /**
     * Called when the embedding application is sent to background.
     */
    public static void onSentToBackground() {
        assert ThreadUtils.runningOnUiThread();
        sApplicationInForeground = false;
        LauncherThread.post(new Runnable() {
            @Override
            public void run() {
                getBindingManager().onSentToBackground();
            }
        });
    }

    /**
     * Called when the embedding application is brought to foreground.
     */
    public static void onBroughtToForeground() {
        assert ThreadUtils.runningOnUiThread();
        sApplicationInForeground = true;
        LauncherThread.post(new Runnable() {
            @Override
            public void run() {
                getBindingManager().onBroughtToForeground();
            }
        });
    }

    @VisibleForTesting
    public static void setSandboxServicesSettingsForTesting(
            ChildConnectionAllocator.ConnectionFactory factory, int serviceCount,
            String serviceName) {
        sSandboxedServiceFactoryForTesting = factory;
        sSandboxedServicesCountForTesting = serviceCount;
        sSandboxedServicesNameForTesting = serviceName;
    }

    @VisibleForTesting
    public static void setBindingManagerForTesting(BindingManager manager) {
        sBindingManager = manager;
    }

    @VisibleForTesting
    static ChildConnectionAllocator getConnectionAllocator(
            Context context, ChildProcessCreationParams creationParams, boolean sandboxed) {
        assert LauncherThread.runningOnLauncherThread();
        final String packageName =
                getPackageNameFromCreationParams(context, creationParams, sandboxed);
        boolean bindAsExternalService =
                isServiceExternalFromCreationParams(creationParams, sandboxed);

        if (!sandboxed) {
            if (sPrivilegedChildConnectionAllocator == null) {
                sPrivilegedChildConnectionAllocator = ChildConnectionAllocator.create(context,
                        LauncherThread.getHandler(), creationParams, packageName,
                        PRIVILEGED_SERVICES_NAME_KEY, NUM_PRIVILEGED_SERVICES_KEY,
                        bindAsExternalService, true /* useStrongBinding */);
            }
            return sPrivilegedChildConnectionAllocator;
        }

        if (!sSandboxedChildConnectionAllocatorMap.containsKey(packageName)) {
            Log.w(TAG,
                    "Create a new ChildConnectionAllocator with package name = %s,"
                            + " sandboxed = true",
                    packageName);
            ChildConnectionAllocator connectionAllocator = null;
            if (sSandboxedServicesCountForTesting != -1) {
                // Testing case where allocator settings are overriden.
                String serviceName = !TextUtils.isEmpty(sSandboxedServicesNameForTesting)
                        ? sSandboxedServicesNameForTesting
                        : SandboxedProcessService.class.getName();
                connectionAllocator = ChildConnectionAllocator.createForTest(creationParams,
                        packageName, serviceName, sSandboxedServicesCountForTesting,
                        bindAsExternalService, false /* useStrongBinding */);
            } else {
                connectionAllocator = ChildConnectionAllocator.create(context,
                        LauncherThread.getHandler(), creationParams, packageName,
                        SANDBOXED_SERVICES_NAME_KEY, NUM_SANDBOXED_SERVICES_KEY,
                        bindAsExternalService, false /* useStrongBinding */);
            }
            if (sSandboxedServiceFactoryForTesting != null) {
                connectionAllocator.setConnectionFactoryForTesting(
                        sSandboxedServiceFactoryForTesting);
            }
            sSandboxedChildConnectionAllocatorMap.put(packageName, connectionAllocator);

            final ChildConnectionAllocator finalConnectionAllocator = connectionAllocator;
            // Tracks connections removal so the allocator can be freed when no longer used.
            connectionAllocator.addListener(new ChildConnectionAllocator.Listener() {
                @Override
                public void onConnectionAllocated(
                        ChildConnectionAllocator allocator, ChildProcessConnection connection) {
                    assert connection != null;
                    assert allocator == finalConnectionAllocator;
                    if (!allocator.isFreeConnectionAvailable()) {
                        // Proactively releases all the moderate bindings once all the sandboxed
                        // services are allocated, which will be very likely to have some of them
                        // killed by OOM killer.
                        getBindingManager().releaseAllModerateBindings();
                    }
                }

                @Override
                public void onConnectionFreed(
                        ChildConnectionAllocator allocator, ChildProcessConnection connection) {
                    assert allocator == finalConnectionAllocator;
                    if (!allocator.anyConnectionAllocated()) {
                        // Last connection was freed, the allocator is going aways, remove the
                        // listener.
                        allocator.removeListener(this);
                        ChildConnectionAllocator removedAllocator =
                                sSandboxedChildConnectionAllocatorMap.remove(packageName);
                        assert removedAllocator == allocator;
                    }
                }
            });
        }
        return sSandboxedChildConnectionAllocatorMap.get(packageName);
    }

    private ChildProcessLauncherHelper(long nativePointer,
            ChildProcessCreationParams creationParams, String[] commandLine,
            FileDescriptorInfo[] filesToBeMapped, boolean sandboxed, IBinder binderCallback) {
        assert LauncherThread.runningOnLauncherThread();

        mNativeChildProcessLauncherHelper = nativePointer;
        mCreationParams = creationParams;
        mUseBindingManager = sandboxed;
        mSandboxed = sandboxed;

        final ChildConnectionAllocator connectionAllocator = getConnectionAllocator(
                ContextUtils.getApplicationContext(), mCreationParams, sandboxed);
        if (sSpareSandboxedConnection != null && !sSpareSandboxedConnection.isEmpty()
                && sSpareSandboxedConnection.isForAllocator(connectionAllocator)) {
            // Use the warmed-up connection.
            ChildProcessLauncher.BoundConnectionProvider connectionProvider =
                    new ChildProcessLauncher.BoundConnectionProvider() {
                        @Override
                        public ChildProcessConnection getConnection(
                                ChildProcessConnection.ServiceCallback serviceCallback) {
                            return sSpareSandboxedConnection.getConnection(
                                    connectionAllocator, serviceCallback);
                        }
                    };
            mLauncher = ChildProcessLauncher.createWithBoundConnectionProvider(
                    LauncherThread.getHandler(), mLauncherDelegate, commandLine, filesToBeMapped,
                    connectionProvider, binderCallback);
        } else {
            mLauncher = ChildProcessLauncher.createWithConnectionAllocator(
                    LauncherThread.getHandler(), mLauncherDelegate, commandLine, filesToBeMapped,
                    connectionAllocator, binderCallback);
        }
    }

    public int getPid() {
        assert LauncherThread.runningOnLauncherThread();
        return mLauncher.getPid();
    }

    // Called on client (UI or IO) thread.
    @CalledByNative
    private boolean isOomProtected() {
        ChildProcessConnection connection = mLauncher.getConnection();
        // Here we are accessing the connection from a thread other than the launcher thread, but it
        // does not change once it's been set. So it is safe to test whether it's null here and
        // access it afterwards.
        if (connection == null) {
            return false;
        }

        // We consider the process to be child protected if it has a strong or moderate binding and
        // the app is in the foreground.
        return sApplicationInForeground && !connection.isWaivedBoundOnlyOrWasWhenDied();
    }

    @CalledByNative
    private void setInForeground(int pid, boolean foreground, boolean boostForPendingViews) {
        assert LauncherThread.runningOnLauncherThread();
        assert mLauncher.getPid() == pid;
        getBindingManager().setPriority(pid, foreground, boostForPendingViews);
    }

    @CalledByNative
    static void stop(int pid) {
        assert LauncherThread.runningOnLauncherThread();
        Log.d(TAG, "stopping child connection: pid=%d", pid);
        ChildProcessLauncherHelper launcher = getByPid(pid);
        // launcher can be null for single process.
        if (launcher != null) {
            // Can happen for single process.
            launcher.mLauncher.stop();
        }
    }

    @CalledByNative
    private static int getNumberOfRendererSlots() {
        assert ThreadUtils.runningOnUiThread();
        if (sSandboxedServicesCountForTesting != -1) {
            return sSandboxedServicesCountForTesting;
        }

        final ChildProcessCreationParams params = ChildProcessCreationParams.getDefault();
        final Context context = ContextUtils.getApplicationContext();
        final String packageName = ChildProcessLauncherHelper.getPackageNameFromCreationParams(
                context, params, true /* inSandbox */);
        try {
            return ChildConnectionAllocator.getNumberOfServices(
                    context, packageName, NUM_SANDBOXED_SERVICES_KEY);
        } catch (RuntimeException e) {
            // Unittest packages do not declare services. Some tests require a realistic number
            // to test child process policies, so pick a high-ish number here.
            return 65535;
        }
    }

    // Can be called on a number of threads, including launcher, and binder.
    private static native void nativeOnChildProcessStarted(
            long nativeChildProcessLauncherHelper, int pid);

    private static boolean sLinkerInitialized;
    private static long sLinkerLoadAddress;
    private static void initLinker() {
        assert LauncherThread.runningOnLauncherThread();
        if (sLinkerInitialized) return;
        if (Linker.isUsed()) {
            sLinkerLoadAddress = Linker.getInstance().getBaseLoadAddress();
            if (sLinkerLoadAddress == 0) {
                Log.i(TAG, "Shared RELRO support disabled!");
            }
        }
        sLinkerInitialized = true;
    }

    private static ChromiumLinkerParams getLinkerParamsForNewConnection() {
        assert LauncherThread.runningOnLauncherThread();

        initLinker();
        assert sLinkerInitialized;
        if (sLinkerLoadAddress == 0) return null;

        // Always wait for the shared RELROs in service processes.
        final boolean waitForSharedRelros = true;
        if (Linker.areTestsEnabled()) {
            Linker linker = Linker.getInstance();
            return new ChromiumLinkerParams(sLinkerLoadAddress, waitForSharedRelros,
                    linker.getTestRunnerClassNameForTesting(),
                    linker.getImplementationForTesting());
        } else {
            return new ChromiumLinkerParams(sLinkerLoadAddress, waitForSharedRelros);
        }
    }

    private static Bundle populateServiceBundle(
            Bundle bundle, ChildProcessCreationParams creationParams) {
        boolean bindToCallerCheck =
                creationParams == null ? false : creationParams.getBindToCallerCheck();
        bundle.putBoolean(ChildProcessConstants.EXTRA_BIND_TO_CALLER, bindToCallerCheck);
        ChromiumLinkerParams linkerParams = getLinkerParamsForNewConnection();
        if (linkerParams != null) linkerParams.populateBundle(bundle);
        return bundle;
    }

    public static ChildProcessLauncherHelper getByPid(int pid) {
        return sLauncherByPid.get(pid);
    }

    // Testing only related methods.
    @VisibleForTesting
    public static ChildProcessLauncherHelper createAndStartForTesting(
            ChildProcessCreationParams creationParams, String[] commandLine,
            FileDescriptorInfo[] filesToBeMapped, boolean sandboxed, IBinder binderCallback,
            boolean doSetupConnection) {
        ChildProcessLauncherHelper launcherHelper = new ChildProcessLauncherHelper(
                0L, creationParams, commandLine, filesToBeMapped, sandboxed, binderCallback);
        launcherHelper.mLauncher.start(doSetupConnection, true /* queueIfNoFreeConnection */);
        return launcherHelper;
    }

    /** @return the count of services set-up and working. */
    @VisibleForTesting
    static int getConnectedServicesCountForTesting() {
        int count = sPrivilegedChildConnectionAllocator == null
                ? 0
                : sPrivilegedChildConnectionAllocator.allocatedConnectionsCountForTesting();
        return count + getConnectedSandboxedServicesCountForTesting(null /* packageName */);
    }

    @VisibleForTesting
    public static int getConnectedSandboxedServicesCountForTesting(String packageName) {
        int count = 0;
        for (ChildConnectionAllocator allocator : sSandboxedChildConnectionAllocatorMap.values()) {
            if (packageName == null || packageName.equals(allocator.getPackageName())) {
                count += allocator.allocatedConnectionsCountForTesting();
            }
        }
        return count;
    }

    @VisibleForTesting
    static boolean hasSandboxedConnectionAllocatorForPackage(String packageName) {
        return sSandboxedChildConnectionAllocatorMap.containsKey(packageName);
    }

    @VisibleForTesting
    public ChildProcessConnection getChildProcessConnection() {
        return mLauncher.getConnection();
    }

    @VisibleForTesting
    public ChildConnectionAllocator getChildConnectionAllocatorForTesting() {
        return mLauncher.getConnectionAllocator();
    }

    @VisibleForTesting
    public static ChildProcessConnection getWarmUpConnectionForTesting() {
        return sSpareSandboxedConnection == null ? null : sSpareSandboxedConnection.getConnection();
    }

    @VisibleForTesting
    public static boolean crashProcessForTesting(int pid) {
        if (sLauncherByPid.get(pid) == null) return false;

        ChildProcessConnection connection = sLauncherByPid.get(pid).mLauncher.getConnection();
        if (connection == null) return false;
        try {
            connection.crashServiceForTesting();
            return true;
        } catch (RemoteException ex) {
            return false;
        }
    }
}
