# Copyright 2015 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import("//android_webview/variables.gni")
import("//base/android/resource_exclusions.gni")
import("//build/config/android/abi.gni")
import("//build/config/android/config.gni")
import("//build/config/android/rules.gni")
import("//build/config/chrome_build.gni")
import("//build/config/locales.gni")
import("//chrome/android/trichrome.gni")
import("//chrome/version.gni")
import("//components/crash/android/silent_java_assert_reporting.gni")
import("//device/vr/buildflags/buildflags.gni")
import("//tools/v8_context_snapshot/v8_context_snapshot.gni")
import("//weblayer/variables.gni")
import("//weblayer/weblayer_resource_exclusions.gni")

declare_args() {
  # Android package name to use when compiling the system_webview_apk and
  # trichrome_webview_apk targets. This should be used if the Android build
  # on which you are going to install WebView is configured to load a
  # different package name than the default used in AOSP.
  system_webview_package_name = "com.android.webview"
}

template("system_webview_apk_or_module_tmpl") {
  _is_trichrome = defined(invoker.is_trichrome) && invoker.is_trichrome
  assert(_is_trichrome == defined(invoker.static_library_provider),
         "If trichrome library is used, static_library_provider must be set " +
             "so that a dep can be added on the library APK.")

  _include_32_bit_webview =
      !defined(invoker.include_32_bit_webview) || invoker.include_32_bit_webview
  _include_64_bit_webview =
      android_64bit_target_cpu && (!defined(invoker.include_64_bit_webview) ||
                                   invoker.include_64_bit_webview)
  if (_is_trichrome) {
    _is_64_bit_browser = android_64bit_target_cpu && invoker.is_64_bit_browser
    _version_code = TRICHROME_VERSION_MAP["${android_64bit_target_cpu}_${_is_64_bit_browser}_${_include_64_bit_webview}_${_include_32_bit_webview}"]
  } else {
    _version_code = WEBVIEW_VERSION_MAP["${android_64bit_target_cpu}_${_include_64_bit_webview}_${_include_32_bit_webview}"]
  }

  if (defined(invoker.manifest_package)) {
    _manifest_package = invoker.manifest_package
  } else {
    _manifest_package = system_webview_package_name
  }
  _android_manifest = "$target_gen_dir/$target_name/AndroidManifest.xml"
  _android_manifest_target_name = "${target_name}__android_manifest"
  jinja_template(_android_manifest_target_name) {
    if (!defined(_android_sdk_release)) {
      _android_sdk_release = android_sdk_release
    }
    input = "//android_webview/nonembedded/java/AndroidManifest.xml"
    output = _android_manifest
    _force_32_bit = _include_32_bit_webview && _include_64_bit_webview &&
                    (!_is_trichrome || !_is_64_bit_browser)
    variables = [
      "android_sdk_release=$_android_sdk_release",
      "force_32_bit=$_force_32_bit",
      "manifest_package=$_manifest_package",
    ]
    if (_is_trichrome) {
      variables +=
          trichrome_jinja_variables + [ "trichrome_version=$_version_code" ]
      if (_is_64_bit_browser) {
        variables += [ "library=libmonochrome_64.so" ]
      } else {
        variables += [ "library=libmonochrome.so" ]
      }
    }
    includes = []
    if (defined(invoker.jinja_input)) {
      includes += [ input ]
      input = invoker.jinja_input
    }
    if (defined(invoker.jinja_extra_variables)) {
      variables += invoker.jinja_extra_variables
    }
    if (defined(invoker.jinja_extra_includes)) {
      includes += invoker.jinja_extra_includes
    }
  }
  if (defined(invoker.target_type)) {
    _target_type = invoker.target_type
  } else {
    _target_type = "android_apk"
  }
  target(_target_type, target_name) {
    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)

    # Do not forward variables used only by this template so that code below
    # needs to use "invoker" to make it clear where variables are coming from.
    forward_variables_from(invoker,
                           "*",
                           TESTONLY_AND_VISIBILITY + [
                                 "exclude_weblayer_java",
                                 "is_64_bit_browser",
                                 "is_trichrome",
                                 "include_32_bit_webview",
                                 "include_64_bit_webview",
                                 "manifest_package",
                                 "weblayer_product_config_java_package",
                                 "webview_framework_dep",
                                 "webview_product_config_java_package",
                                 "webview_devui_show_icon",
                                 "use_stable_package_name_for_trichrome",
                               ])

    _is_bundle_module = _target_type == "android_app_bundle_module"
    _exclude_weblayer_java =
        defined(invoker.exclude_weblayer_java) && invoker.exclude_weblayer_java
    _omit_dex = defined(invoker.omit_dex) && invoker.omit_dex

    if (!defined(min_sdk_version) && _is_trichrome) {
      min_sdk_version = 29
    }
    if (defined(expected_android_manifest)) {
      expected_android_manifest_version_code_offset = chrome_version_code
      expected_android_manifest_library_version_offset = chrome_version_code
    }

    android_manifest = _android_manifest
    android_manifest_dep = ":$_android_manifest_target_name"
    manifest_package = _manifest_package
    deps += [
      "//android_webview:locale_pak_assets",
      "//android_webview:pak_file_assets",
    ]

    if (_exclude_weblayer_java) {
      deps += [ "//android_webview:android_webview_no_weblayer_java" ]
    } else {
      if (_is_bundle_module && webview_includes_weblayer) {
        deps += [
          # TODO(crbug.com/1105096): WebLayer resources are added to the base
          # module for now because of bugs with shared resources in splits.
          ":${target_name}__all_weblayer_resources",
          "//android_webview:android_webview_no_weblayer_java",
          "//weblayer/browser/java:base_module_java",
        ]
      } else {
        deps += [ "//android_webview:android_webview_java" ]
      }

      # Resources from this target will be kept in the base bundle module
      # instead of in language splits.
      if (!defined(shared_resources_allowlist_target)) {
        shared_resources_allowlist_target =
            "//android_webview:system_webview_no_weblayer_apk"
      }
    }

    if (!_omit_dex) {
      product_config_java_packages =
          [ invoker.webview_product_config_java_package ]
      if (allow_jni_multiplexing) {
        enable_jni_multiplexing = true
      }
    }

    if (webview_includes_weblayer) {
      if (_is_bundle_module) {
        deps += [ "//weblayer:bundle_locale_pak_assets" ]
      } else {
        deps += [ "//weblayer:locale_pak_assets" ]
      }
      if (!_omit_dex) {
        product_config_java_packages +=
            [ invoker.weblayer_product_config_java_package ]
      }
    }

    if (!defined(alternative_android_sdk_dep)) {
      alternative_android_sdk_dep = invoker.webview_framework_dep
    }

    # We can't include an icon for anything with the Stable channel package name
    # because it confuses work profiles. We check
    # use_stable_package_name_for_trichrome here instead of where
    # webview_devui_show_icon is assigned to avoid a circular dependency
    # between //android_webview/variables.gni and
    # //chrome/android/trichrome.gni.
    if (invoker.webview_devui_show_icon &&
        !invoker.use_stable_package_name_for_trichrome) {
      deps += [ "//android_webview/nonembedded:devui_launcher_icon_resources" ]
    }

    # Flag whether additional deps and libs should be included for each ABI.
    _include_primary_support = false
    _include_secondary_support = false

    if (!_is_trichrome) {
      shared_resources = true

      if ((!android_64bit_target_cpu && _include_32_bit_webview) ||
          (android_64bit_target_cpu && _include_64_bit_webview)) {
        shared_libraries = [ "//android_webview:libwebviewchromium" ]
        _include_primary_support = true
      }
      if (android_64bit_target_cpu && _include_32_bit_webview) {
        secondary_abi_shared_libraries = [ "//android_webview:libwebviewchromium($android_secondary_abi_toolchain)" ]
        _include_secondary_support = true
      }
      deps += [ "//third_party/icu:icu_assets" ]
    } else {
      app_as_shared_lib = true

      # Include placeholder libraries to ensure we are treated as the desired
      # architecture.
      if (android_64bit_target_cpu) {
        if (_is_64_bit_browser) {
          native_lib_placeholders = [ "libdummy.so" ]
          if (_include_32_bit_webview) {
            secondary_abi_shared_libraries = [ "//android_webview:monochrome_64($android_secondary_abi_toolchain)" ]
            _include_secondary_support = true
          }
        } else {
          if (_include_64_bit_webview) {
            shared_libraries = [ "//android_webview:monochrome" ]
            _include_primary_support = true
          }
          secondary_native_lib_placeholders = [ "libdummy.so" ]
          static_library_provider_use_secondary_abi = true
        }

        # http://crbug.com/1042107.
        if (is_component_build) {
          if (_is_64_bit_browser) {
            main_component_library = "libmonochrome_64.cr.so"
          } else {
            main_component_library = "libmonochrome.cr.so"
          }
        }
      } else {
        native_lib_placeholders = [ "libdummy.so" ]
      }
    }

    _include_arcore =
        webview_includes_weblayer && enable_arcore && !_exclude_weblayer_java &&
        (_include_secondary_support || _include_primary_support)

    if (_include_arcore) {
      # Do not add manifest entries because embedders are the ones that will need to add them.
      deps += [ "//third_party/arcore-android-sdk-client:com_google_ar_core_J__unpack_aar" ]
      _libarcore_dir = get_label_info(
                           "//third_party/arcore-android-sdk-client:com_google_ar_core_java($default_toolchain)",
                           "target_out_dir") + "/com_google_ar_core_java/jni"
      if (!_is_bundle_module) {
        deps += [
          "//third_party/arcore-android-sdk-client:arcore_remove_manifest_java",
        ]
      }
    }

    if (_include_primary_support) {
      deps += [
        "//android_webview:webview_primary_abi_assets",
        "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline",
      ]
      loadable_modules = [ "$root_out_dir/libcrashpad_handler_trampoline.so" ]
      if (webview_includes_weblayer) {
        deps += [ "//base/android/linker:chromium_android_linker" ]
        loadable_modules +=
            [ "$root_out_dir/libchromium_android_linker$shlib_extension" ]
      }
      if (_include_arcore) {
        loadable_modules +=
            [ "$_libarcore_dir/$android_app_abi/libarcore_sdk_c.so" ]
      }
    }
    if (_include_secondary_support) {
      _trampoline = "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline($android_secondary_abi_toolchain)"
      deps += [
        "//android_webview:webview_secondary_abi_assets",
        _trampoline,
      ]
      _secondary_out_dir = get_label_info(_trampoline, "root_out_dir")
      secondary_abi_loadable_modules =
          [ "$_secondary_out_dir/libcrashpad_handler_trampoline.so" ]
      if (webview_includes_weblayer) {
        deps += [ "//base/android/linker:chromium_android_linker($android_secondary_abi_toolchain)" ]
        secondary_abi_loadable_modules +=
            [ "$_secondary_out_dir/libchromium_android_linker$shlib_extension" ]
      }
      if (_include_arcore) {
        secondary_abi_loadable_modules +=
            [ "$_libarcore_dir/$android_app_secondary_abi/libarcore_sdk_c.so" ]
      }
    }

    aapt_locale_allowlist = platform_pak_locales

    resource_exclusion_regex = common_resource_exclusion_regex
    resource_exclusion_exceptions = common_resource_exclusion_exceptions

    if (webview_includes_weblayer) {
      resource_values_filter_rules = weblayer_resource_values_filter_rules
      resource_exclusion_exceptions += weblayer_resource_exclusion_exceptions

      # Note: WebLayer's resource exclusion regex deliberately does not start
      # with "|".
      resource_exclusion_regex += "|" + weblayer_resource_exclusion_regex
    }

    # We only optimize resources for bundles since APKs are not shipped.
    # Resources only live in the base module atm as such we only need to set
    # these on the base module
    if (_is_bundle_module) {
      # Removes metadata needed for Resources.getIdentifier("resource_name").
      strip_resource_names = !is_java_debug

      # Shortens resource file names in apk eg: res/drawable/button.xml -> res/a.xml
      short_resource_paths = !is_java_debug

      # Removes unused resources from the apk. Only enabled on official builds
      # since it adds a slow step and serializes the build graph causing fewer
      # expensive tasks (eg: proguarding, resource optimization) to be run in
      # parallel by adding dependencies between them (adds around 10-20
      # seconds on my machine).
      strip_unused_resources = is_official_build
    }

    if (!_is_bundle_module) {
      # Used as an additional apk in test scripts.
      never_incremental = true
      command_line_flags_file = "webview-command-line"
    }

    if (!is_java_debug && !_omit_dex) {
      proguard_enabled = true
      if (!defined(proguard_configs)) {
        proguard_configs = []
      }

      proguard_configs +=
          [ "//android_webview/nonembedded/java/proguard.flags" ]
      png_to_webp = true
    }

    if (enable_silent_java_assert_reporting && !_omit_dex) {
      custom_assertion_handler = crash_reporting_assertion_handler
    }

    version_name = chrome_version_name
    version_code = _version_code
  }
}