/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.webkit;

import android.annotation.NonNull;
import android.app.ActivityManagerInternal;
import android.app.ActivityThread;
import android.app.LoadedApk;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.os.Build;
import android.os.Process;
import android.util.Log;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;

import dalvik.system.VMRuntime;

import java.util.Arrays;

/**
 * @hide
 */
@VisibleForTesting
public class WebViewLibraryLoader {
    private static final String LOGTAG = WebViewLibraryLoader.class.getSimpleName();

    private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_32 =
            "/data/misc/shared_relro/libwebviewchromium32.relro";
    private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_64 =
            "/data/misc/shared_relro/libwebviewchromium64.relro";

    private static final boolean DEBUG = false;

    private static boolean sAddressSpaceReserved = false;

    /**
     * Private class for running the actual relro creation in an unprivileged child process.
     * RelroFileCreator is a static class (without access to the outer class) to avoid accidentally
     * using any static members from the outer class. Those members will in reality differ between
     * the child process in which RelroFileCreator operates, and the app process in which the static
     * members of this class are used.
     */
    private static class RelroFileCreator {
        // Called in an unprivileged child process to create the relro file.
        public static void main(String[] args) {
            boolean result = false;
            boolean is64Bit = VMRuntime.getRuntime().is64Bit();
            try {
                if (args.length != 2 || args[0] == null || args[1] == null) {
                    Log.e(LOGTAG, "Invalid RelroFileCreator args: " + Arrays.toString(args));
                    return;
                }
                String packageName = args[0];
                String libraryFileName = args[1];
                Log.v(LOGTAG, "RelroFileCreator (64bit = " + is64Bit + "), package: "
                        + packageName + " library: " + libraryFileName);
                if (!sAddressSpaceReserved) {
                    Log.e(LOGTAG, "can't create relro file; address space not reserved");
                    return;
                }
                LoadedApk apk = ActivityThread.currentActivityThread().getPackageInfo(
                        packageName,
                        null,
                        Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
                result = nativeCreateRelroFile(libraryFileName,
                                               is64Bit ? CHROMIUM_WEBVIEW_NATIVE_RELRO_64 :
                                                         CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
                                               apk.getClassLoader());
                if (result && DEBUG) Log.v(LOGTAG, "created relro file");
            } finally {
                // We must do our best to always notify the update service, even if something fails.
                try {
                    if (Flags.updateServiceIpcWrapper()) {
                        WebViewUpdateManager.getInstance().notifyRelroCreationCompleted();
                    } else {
                        WebViewFactory.getUpdateServiceUnchecked().notifyRelroCreationCompleted();
                    }
                } catch (Exception e) {
                    Log.e(LOGTAG, "error notifying update service", e);
                }

                if (!result) Log.e(LOGTAG, "failed to create relro file");

                // Must explicitly exit or else this process will just sit around after we return.
                System.exit(0);
            }
        }
    }

    /**
     * Create a single relro file by invoking an isolated process that to do the actual work.
     */
    static void createRelroFile(final boolean is64Bit, @NonNull String packageName,
            @NonNull String libraryFileName) {
        final String abi =
                is64Bit ? Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0];

        // crashHandler is invoked by the ActivityManagerService when the isolated process crashes.
        Runnable crashHandler = new Runnable() {
            @Override
            public void run() {
                try {
                    Log.e(LOGTAG, "relro file creator for " + abi + " crashed. Proceeding without");
                    if (Flags.updateServiceIpcWrapper()) {
                        WebViewUpdateManager.getInstance().notifyRelroCreationCompleted();
                    } else {
                        WebViewFactory.getUpdateService().notifyRelroCreationCompleted();
                    }
                } catch (Exception e) {
                    Log.e(LOGTAG, "Cannot reach WebViewUpdateService. " + e.getMessage());
                }
            }
        };

        try {
            boolean success = LocalServices.getService(ActivityManagerInternal.class)
                    .startIsolatedProcess(
                            RelroFileCreator.class.getName(),
                            new String[] { packageName, libraryFileName },
                            "WebViewLoader-" + abi, abi, Process.SHARED_RELRO_UID, crashHandler);
            if (!success) throw new Exception("Failed to start the relro file creator process");
        } catch (Throwable t) {
            // Log and discard errors as we must not crash the system server.
            Slog.wtf(LOGTAG, "error starting relro file creator for abi " + abi, t);
            crashHandler.run();
        }
    }

    /**
     * Perform preparations needed to allow loading WebView from an application. This method should
     * be called whenever we change WebView provider.
     * @return the number of relro processes started.
     */
    static int prepareNativeLibraries(@NonNull PackageInfo webViewPackageInfo) {
        // TODO(torne): new way of calculating VM size
        // updateWebViewZygoteVmSize(nativeLib32bit, nativeLib64bit);
        String libraryFileName = WebViewFactory.getWebViewLibrary(
                webViewPackageInfo.applicationInfo);
        if (libraryFileName == null) {
            // Can't do anything with no filename, don't spawn any processes.
            return 0;
        }
        return createRelros(webViewPackageInfo.packageName, libraryFileName);
    }

    /**
     * @return the number of relro processes started.
     */
    private static int createRelros(@NonNull String packageName, @NonNull String libraryFileName) {
        if (DEBUG) Log.v(LOGTAG, "creating relro files");
        int numRelros = 0;

        if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
            if (DEBUG) Log.v(LOGTAG, "Create 32 bit relro");
            createRelroFile(false /* is64Bit */, packageName, libraryFileName);
            numRelros++;
        }

        if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
            if (DEBUG) Log.v(LOGTAG, "Create 64 bit relro");
            createRelroFile(true /* is64Bit */, packageName, libraryFileName);
            numRelros++;
        }
        return numRelros;
    }

    /**
     * Reserve space for the native library to be loaded into.
     */
    static void reserveAddressSpaceInZygote() {
        System.loadLibrary("webviewchromium_loader");
        long addressSpaceToReserve;
        if (VMRuntime.getRuntime().is64Bit()) {
            // On 64-bit address space is really cheap and we can reserve 1GB which is plenty.
            addressSpaceToReserve = 1 * 1024 * 1024 * 1024;
        } else if (VMRuntime.getRuntime().vmInstructionSet().equals("arm")) {
            // On 32-bit the address space is fairly scarce, hence we should keep it to a realistic
            // number that permits some future growth but doesn't hog space. For ARM we use 130MB
            // which is roughly what was calculated on older OS versions. The size has been
            // growing gradually, but a few efforts have offset it back to the size close to the
            // original.
            addressSpaceToReserve = 130 * 1024 * 1024;
        } else {
            // The number below was obtained for a binary used for x86 emulators, allowing some
            // natural growth.
            addressSpaceToReserve = 190 * 1024 * 1024;
        }

        sAddressSpaceReserved = nativeReserveAddressSpace(addressSpaceToReserve);

        if (sAddressSpaceReserved) {
            if (DEBUG) {
                Log.v(LOGTAG, "address space reserved: " + addressSpaceToReserve + " bytes");
            }
        } else {
            Log.e(LOGTAG, "reserving " + addressSpaceToReserve + " bytes of address space failed");
        }
    }

    /**
     * Load WebView's native library into the current process.
     *
     * <p class="note"><b>Note:</b> Assumes that we have waited for relro creation.
     *
     * @param clazzLoader class loader used to find the linker namespace to load the library into.
     * @param libraryFileName the filename of the library to load.
     */
    public static int loadNativeLibrary(ClassLoader clazzLoader, String libraryFileName) {
        if (!sAddressSpaceReserved) {
            Log.e(LOGTAG, "can't load with relro file; address space not reserved");
            return WebViewFactory.LIBLOAD_ADDRESS_SPACE_NOT_RESERVED;
        }

        String relroPath = VMRuntime.getRuntime().is64Bit() ? CHROMIUM_WEBVIEW_NATIVE_RELRO_64 :
                                                              CHROMIUM_WEBVIEW_NATIVE_RELRO_32;
        int result = nativeLoadWithRelroFile(libraryFileName, relroPath, clazzLoader);
        if (result != WebViewFactory.LIBLOAD_SUCCESS) {
            Log.w(LOGTAG, "failed to load with relro file, proceeding without");
        } else if (DEBUG) {
            Log.v(LOGTAG, "loaded with relro file");
        }
        return result;
    }

    static native boolean nativeReserveAddressSpace(long addressSpaceToReserve);
    static native boolean nativeCreateRelroFile(String lib, String relro, ClassLoader clazzLoader);
    static native int nativeLoadWithRelroFile(String lib, String relro, ClassLoader clazzLoader);
}
