chromium/chrome/android/modules/chrome_bundle_tmpl.gni

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

import("//base/android/linker/config.gni")
import("//build/config/android/config.gni")
import("//chrome/android/modules/chrome_feature_module_tmpl.gni")
import("//chrome/version.gni")
import("//components/crash/android/silent_java_assert_reporting.gni")
import("//components/module_installer/android/module_desc_java.gni")

# Instantiates a Chrome-specific app bundle.
#
# Supports most variables of chrome_feature_module and android_app_bundle, plus:
#   module_descs: List of descriptors for modules that are part of this bundle.
#     See //chrome/android/modules/chrome_feature_modules.gni for the format of
#     a module descriptor.
#   is_64_bit_browser: (Optional) Whether Chrome (as opposed to WebView) runs in
#     64 bit.
#   include_32_bit_webview: (Optional) Whether to include 32 bit code for
#     WebView.
template("chrome_bundle") {
  _bundle_target_name = target_name
  _package_id = 126  # == 0x7e.
  _extra_modules = []
  _module_descs = invoker.module_descs
  _is_monochrome = defined(invoker.is_monochrome) && invoker.is_monochrome
  _is_trichrome = defined(invoker.is_trichrome) && invoker.is_trichrome

  assert(_is_trichrome == defined(invoker.static_library_provider))

  # Put //chrome Java code and resources into a dedicated split to isolate
  # renderer processes from needing to load it.
  _base_target_gen_dir =
      get_label_info(invoker.base_module_target, "target_gen_dir")
  _base_name = get_label_info(invoker.base_module_target, "name")
  _split_android_manifest =
      "${_base_target_gen_dir}/${_base_name}/AndroidManifest_split.xml"

  _chrome_module_desc = {
    name = "chrome"
    android_manifest = _split_android_manifest
    android_manifest_dep =
        "${invoker.base_module_target}__android_manifest__split"
    java_deps = [ "//chrome/android:chrome_all_java" ]
    if (_is_monochrome) {
      java_deps += [ "//chrome/android:monochrome_java" ]
    }
    if (defined(invoker.chrome_deps)) {
      java_deps += invoker.chrome_deps
    }
  }
  _module_descs += [ _chrome_module_desc ]

  # TODO(crbug.com/40148088): Isolated splits cause various bugs with resource
  # access. For now, move all resources to the base module.
  # TODO(crbug.com/40208153): Macro resource types only work when all resources
  # are in the same split. For now, keep all resources in the base module.
  _base_target_name = get_label_info(invoker.base_module_target, "name")
  android_resources("${_base_target_name}__all_dfm_resources") {
    recursive_resource_deps = true
    deps = []

    # Java library deps are added to this target because the
    # recursive_resource_deps arg allows pulling all the android_resources
    # deps from them. The actual java library targets are not used.
    foreach(_module_desc, _module_descs) {
      if (defined(_module_desc.java_deps)) {
        deps += _module_desc.java_deps
      }
    }
  }

  # Determine whether the bundle has native libraries for both the primary and
  # the secondary ABI. This is the case if we package WebView with the
  # complementary ABI of the browser.
  if (_is_trichrome || _is_monochrome) {
    _is_64_bit_browser = android_64bit_target_cpu && invoker.is_64_bit_browser
    _include_64_bit_webview =
        android_64bit_target_cpu && (!defined(invoker.include_64_bit_webview) ||
                                     invoker.include_64_bit_webview)
    _include_32_bit_webview = !defined(invoker.include_32_bit_webview) ||
                              invoker.include_32_bit_webview
    _is_multi_abi = (_is_64_bit_browser && _include_32_bit_webview) ||
                    (!_is_64_bit_browser && _include_64_bit_webview)
  } else {
    _is_multi_abi = false
  }

  if (defined(invoker.version_code)) {
    _version_code = invoker.version_code
    not_needed([
                 "_include_64_bit_webview",
                 "_include_32_bit_webview",
               ])
  } else {
    if (_is_trichrome) {
      _version_code = TRICHROME_VERSION_MAP["${android_64bit_target_cpu}_${_is_64_bit_browser}_${_include_64_bit_webview}_${_include_32_bit_webview}"]
    } else if (_is_monochrome) {
      _version_code = MONOCHROME_VERSION_MAP["${android_64bit_target_cpu}_${_is_64_bit_browser}_${_include_64_bit_webview}_${_include_32_bit_webview}"]
    } else {
      _version_code = chrome_version_code
    }
  }

  if (defined(invoker.min_sdk_version)) {
    _min_sdk_version = invoker.min_sdk_version
  } else if (_is_trichrome) {
    _min_sdk_version = 29
  } else {
    _min_sdk_version = default_min_sdk_version
  }

  foreach(_module_desc, _module_descs) {
    assert(_package_id > 2, "Too many modules, ran out of package IDs!")

    # Assert that |load_native_on_get_impl| is defined iff native libraries or
    # resources are defined.
    if (defined(_module_desc.native_deps) || defined(_module_desc.paks)) {
      assert(defined(_module_desc.load_native_on_get_impl))
    } else {
      assert(!defined(_module_desc.load_native_on_get_impl))
    }

    chrome_feature_module(
        "${_bundle_target_name}__${_module_desc.name}_bundle_module") {
      forward_variables_from(invoker,
                             [
                               "add_view_trace_events",
                               "base_module_target",
                               "is_64_bit_browser",
                               "manifest_package",
                               "target_sdk_version",
                               "override_target_sdk",
                             ])
      is_monochrome = _is_monochrome
      is_trichrome = _is_trichrome
      module_desc = _module_desc
      version_name = chrome_version_name
      version_code = _version_code
      min_sdk_version = _min_sdk_version

      if (defined(_module_desc.uses_split)) {
        assert(
            _module_desc.uses_split == "chrome",
            "Build logic supports only uses_split=chrome. Found uses_split=${_module_desc.uses_split}")
        parent_module_target = ":${_bundle_target_name}__chrome_bundle_module"
      }

      if (android_64bit_target_cpu) {
        _version_code_offset = chrome_32_version_code
      } else {
        _version_code_offset = chrome_version_code
      }
      not_needed([ _version_code_offset ])

      if (defined(invoker.expected_android_manifest_template)) {
        expected_android_manifest_version_code_offset = _version_code_offset
        expected_android_manifest =
            string_replace(invoker.expected_android_manifest_template,
                           "SPLIT_NAME",
                           _module_desc.name)
      }
      if (defined(invoker.expected_android_manifest_base_template)) {
        expected_android_manifest_version_code_offset = _version_code_offset
        if (defined(_module_desc.ignore_base_manifest_expectations) &&
            _module_desc.ignore_base_manifest_expectations) {
          # Remove ".diff" since it's not actually a diff.
          expected_android_manifest =
              string_replace(expected_android_manifest, ".diff", "")
        } else {
          expected_android_manifest_base =
              string_replace(invoker.expected_android_manifest_base_template,
                             "SPLIT_NAME",
                             _module_desc.name)
        }
      }

      if (enable_silent_java_assert_reporting) {
        custom_assertion_handler = crash_reporting_assertion_handler
      }

      # Each module needs a unique resource package ID so that we don't have ID
      # collisions between feature modules.
      package_id = _package_id
    }
    _module_desc.module_target =
        ":${_bundle_target_name}__${_module_desc.name}_bundle_module"
    _extra_modules += [ _module_desc ]
    _package_id -= 1
  }

  android_app_bundle(target_name) {
    min_sdk_version = _min_sdk_version
    command_line_flags_file = "chrome-command-line"
    proguard_enabled = !is_java_debug
    enable_language_splits = true
    extra_modules = _extra_modules
    system_image_locale_allowlist = platform_pak_locales - extended_locales
    is_multi_abi = _is_multi_abi
    validate_services = true
    if (enable_silent_java_assert_reporting) {
      custom_assertion_handler = crash_reporting_assertion_handler
    }

    # For this to be respected, it must also be set on the base module target.
    strip_unused_resources = is_official_build

    # List of DFMs that are installed by default by wrapper scripts, to make
    # testing easier. This removes the need to manually specify, e.g.,
    # "-m dev_ui" on every install or run.
    default_modules_for_testing = [ "dev_ui" ]

    if (!is_java_debug && _is_monochrome) {
      proguard_android_sdk_dep = webview_framework_dep
    }

    forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
  }

  if (defined(invoker.expected_android_manifest_template)) {
    group("${target_name}_validate_manifests") {
      deps = [
        ":${_bundle_target_name}__base_bundle_module_validate_android_manifest",
      ]
      foreach(_module_desc, _module_descs) {
        deps += [ ":${_bundle_target_name}__${_module_desc.name}_bundle_module_validate_android_manifest" ]
      }
    }
  }
}