chromium/chrome/android/webapk/shell_apk/BUILD.gn

# 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("//build/config/android/rules.gni")
import("//build/config/locales.gni")
import("//tools/grit/grit_rule.gni")
import("current_version/current_version.gni")
import("generate_manifest_for_upload_outputs.gni")
import("mustache_pass.gni")

h2o_junit_manifest_output =
    "${target_gen_dir}/junit_manifest/AndroidManifest.xml"

# GN breaks with a mysterious error if the target has the word "junit" in it.
h2o_junit_manifest_target_name = "h2o_j_unit_manifest_target"

# Stamped out copy of the runtime-library, used for fail-safe code in when using an
# old copy of the runtime library.
android_library("compiled_in_runtime_library_java") {
  chromium_code = false
  sources = [ "src/org/chromium/webapk/lib/runtime_library/IWebApkApi.java" ]
}

mustache_pass("generate_chromeos_manifest_for_upload") {
  inputs = [ "AndroidManifest.xml" ]
  output_dir =
      get_path_info(generate_chromeos_manifest_for_upload_output, "dir")
  extra_variables = [
    "shell_apk_version=$current_shell_apk_version",
    "use_new_splash=false",
  ]
}

mustache_pass("generate_manifest_for_upload") {
  inputs = [ "AndroidManifest.xml" ]
  output_dir = get_path_info(generate_manifest_for_upload_output, "dir")
  extra_variables = [
    "shell_apk_version=$current_shell_apk_version",
    "use_new_splash=true",
  ]
}

# |webapk_java| is split from |webapk_with_service_java| for the sake of instrumentation tests.
# |chrome_public_test_apk| cannot depend on |compiled_in_runtime_library_java| due to a class
# name conflict.
template("webapk_java") {
  android_library(target_name) {
    forward_variables_from(invoker,
                           [
                             "deps",
                             "resources_package",
                           ])

    sources = [
      "src/org/chromium/webapk/shell_apk/DexLoader.java",
      "src/org/chromium/webapk/shell_apk/HostBrowserClassLoader.java",
      "src/org/chromium/webapk/shell_apk/HostBrowserLauncher.java",
      "src/org/chromium/webapk/shell_apk/HostBrowserLauncherParams.java",
      "src/org/chromium/webapk/shell_apk/HostBrowserUtils.java",
      "src/org/chromium/webapk/shell_apk/IdentityService.java",
      "src/org/chromium/webapk/shell_apk/InstallHostBrowserDialog.java",
      "src/org/chromium/webapk/shell_apk/LaunchHostBrowserSelector.java",
      "src/org/chromium/webapk/shell_apk/ManageDataLauncherActivity.java",
      "src/org/chromium/webapk/shell_apk/NotificationPermissionRequestActivity.java",
      "src/org/chromium/webapk/shell_apk/PermissionStatus.java",
      "src/org/chromium/webapk/shell_apk/PrefUtils.java",
      "src/org/chromium/webapk/shell_apk/TransparentLauncherActivity.java",
      "src/org/chromium/webapk/shell_apk/WebApkSharedPreferences.java",
      "src/org/chromium/webapk/shell_apk/WebApkUtils.java",
      "src/org/chromium/webapk/shell_apk/h2o/H2OLauncher.java",
      "src/org/chromium/webapk/shell_apk/h2o/H2OMainActivity.java",
      "src/org/chromium/webapk/shell_apk/h2o/H2OOpaqueMainActivity.java",
      "src/org/chromium/webapk/shell_apk/h2o/H2OTransparentLauncherActivity.java",
      "src/org/chromium/webapk/shell_apk/h2o/LaunchTrigger.java",
      "src/org/chromium/webapk/shell_apk/h2o/SplashActivity.java",
      "src/org/chromium/webapk/shell_apk/h2o/SplashContentProvider.java",
      "src/org/chromium/webapk/shell_apk/h2o/SplashUtils.java",
      "src/org/chromium/webapk/shell_apk/h2o/SplashUtilsForS.java",
    ]
    deps += [
      "//chrome/android/webapk/libs/common:common_java",
      "//chrome/android/webapk/libs/common:splash_java",
      "//components/webapk/android/libs/common:java",
      "//third_party/androidx:androidx_annotation_annotation_java",
    ]
  }
}

template("webapk_with_service_java") {
  android_library(target_name) {
    forward_variables_from(invoker, [ "deps" ])

    sources = [
      "src/org/chromium/webapk/shell_apk/WebApkServiceFactory.java",
      "src/org/chromium/webapk/shell_apk/WebApkServiceImplWrapper.java",
    ]
    deps += [
      ":compiled_in_runtime_library_java",
      "//third_party/androidx:androidx_annotation_annotation_java",
    ]
  }
}

template("webapk_tmpl") {
  _manifest_to_upload_dep = invoker.manifest_to_upload_dep
  _manifest_target_name = "${target_name}_generate_manifest"
  _manifest_output =
      "${target_gen_dir}/${_manifest_target_name}/AndroidManifest.xml"
  _java_without_services_target_name = "${target_name}_generated_webapk_java"
  _java_with_services_target_name =
      "${target_name}_generated_webapk_with_service_java"
  _generate_res_background_xml_target_name =
      "${target_name}_generate_res_background_xml"
  _generated_res_background_dir =
      "${target_gen_dir}/${_generate_res_background_xml_target_name}/res"
  _resources_target_name = "${target_name}_resources"
  _generated_icons_target_name = "${target_name}_generated_icons"

  if (defined(invoker.manifest_output)) {
    _manifest_output = invoker.manifest_output
  }
  if (defined(invoker.manifest_target_name)) {
    _manifest_target_name = invoker.manifest_target_name
  }

  # Generate manifest with test values.
  mustache_pass(_manifest_target_name) {
    forward_variables_from(invoker,
                           [
                             "apk_package_name",
                             "config_file",
                             "delta_config_file",
                           ])

    inputs = get_target_outputs(_manifest_to_upload_dep)
    output_dir = get_path_info(_manifest_output, "dir")
    extra_variables = [ "manifest_package=$apk_package_name" ]
    deps = [ _manifest_to_upload_dep ]
  }

  # Populate background color in values/background_color.xml
  mustache_pass(_generate_res_background_xml_target_name) {
    forward_variables_from(invoker, [ "config_file" ])
    inputs = [ "res_template/values/background_color.xml" ]
    output_dir = "${_generated_res_background_dir}/values"
  }

  mustache_pass(_generated_icons_target_name) {
    forward_variables_from(invoker, [ "config_file" ])
    icon_density = "hdpi"
    extra_variables = [ "icon_density=$icon_density" ]
    inputs = [
      "res_template/mipmap-nodpi/app_icon.xml",
      "res_template/mipmap-nodpi/maskable_app_icon.xml",
    ]
    output_dir = "${target_gen_dir}/${_generated_icons_target_name}/res/mipmap-${icon_density}"
  }

  android_resources(_resources_target_name) {
    sources = [
      "res/drawable-hdpi/ic_site_settings.png",
      "res/drawable-hdpi/last_resort_runtime_host_logo.png",
      "res/drawable-hdpi/notification_badge.png",
      "res/drawable-hdpi/shortcut_1_icon.png",
      "res/drawable-hdpi/shortcut_2_icon.png",
      "res/drawable-hdpi/shortcut_3_icon.png",
      "res/drawable-hdpi/shortcut_4_icon.png",
      "res/drawable-hdpi/splash_icon.xml",
      "res/drawable-mdpi/ic_site_settings.png",
      "res/drawable-mdpi/notification_badge.png",
      "res/drawable-mdpi/shortcut_1_icon.png",
      "res/drawable-mdpi/shortcut_2_icon.png",
      "res/drawable-mdpi/shortcut_3_icon.png",
      "res/drawable-mdpi/shortcut_4_icon.png",
      "res/drawable-mdpi/splash_icon.xml",
      "res/drawable-xhdpi/ic_site_settings.png",
      "res/drawable-xhdpi/notification_badge.png",
      "res/drawable-xhdpi/shortcut_1_icon.png",
      "res/drawable-xhdpi/shortcut_2_icon.png",
      "res/drawable-xhdpi/shortcut_3_icon.png",
      "res/drawable-xhdpi/shortcut_4_icon.png",
      "res/drawable-xhdpi/splash_icon.xml",
      "res/drawable-xxhdpi/ic_site_settings.png",
      "res/drawable-xxhdpi/notification_badge.png",
      "res/drawable-xxhdpi/shortcut_1_icon.png",
      "res/drawable-xxhdpi/shortcut_2_icon.png",
      "res/drawable-xxhdpi/shortcut_3_icon.png",
      "res/drawable-xxhdpi/shortcut_4_icon.png",
      "res/drawable-xxhdpi/splash_icon.xml",
      "res/drawable-xxxhdpi/ic_site_settings.png",
      "res/drawable-xxxhdpi/notification_badge.png",
      "res/drawable-xxxhdpi/shortcut_1_icon.png",
      "res/drawable-xxxhdpi/shortcut_2_icon.png",
      "res/drawable-xxxhdpi/shortcut_3_icon.png",
      "res/drawable-xxxhdpi/shortcut_4_icon.png",
      "res/drawable-xxxhdpi/splash_icon.xml",
      "res/layout-night-v31/splash_screen_view.xml",
      "res/layout-v31/splash_screen_view.xml",
      "res/layout/host_browser_list_item.xml",
      "res/mipmap-anydpi-v26/ic_launcher.xml",
      "res/mipmap-hdpi/ic_launcher.xml",
      "res/mipmap-mdpi/ic_launcher.xml",
      "res/mipmap-mdpi/ic_launcher_background.png",
      "res/mipmap-mdpi/ic_launcher_foreground.png",
      "res/mipmap-nodpi/app_icon_hdpi.png",
      "res/mipmap-nodpi/app_icon_mdpi.png",
      "res/mipmap-nodpi/app_icon_xhdpi.png",
      "res/mipmap-nodpi/app_icon_xxhdpi.png",
      "res/mipmap-nodpi/app_icon_xxxhdpi.png",
      "res/mipmap-nodpi/maskable_app_icon_hdpi.png",
      "res/mipmap-nodpi/maskable_app_icon_mdpi.png",
      "res/mipmap-nodpi/maskable_app_icon_xhdpi.png",
      "res/mipmap-nodpi/maskable_app_icon_xxhdpi.png",
      "res/mipmap-nodpi/maskable_app_icon_xxxhdpi.png",
      "res/mipmap-nodpi/maskable_splash_icon_xxhdpi.png",
      "res/mipmap-nodpi/maskable_splash_icon_xxxhdpi.png",
      "res/mipmap-nodpi/splash_icon_xxhdpi.png",
      "res/mipmap-nodpi/splash_icon_xxxhdpi.png",
      "res/mipmap-xhdpi/ic_launcher.xml",
      "res/mipmap-xxhdpi/ic_launcher.xml",
      "res/mipmap-xxxhdpi/ic_launcher.xml",
      "res/values-hdpi/is_splash_icon_maskable_bool.xml",
      "res/values-mdpi/is_splash_icon_maskable_bool.xml",
      "res/values-night-v17/styles.xml",
      "res/values-night-v31/dimens.xml",
      "res/values-night-v31/styles.xml",
      "res/values-v17/styles.xml",
      "res/values-v24/default_enabled_activity.xml",
      "res/values-v31/dimens.xml",
      "res/values-v31/styles.xml",
      "res/values-xhdpi/is_splash_icon_maskable_bool.xml",
      "res/values-xxhdpi/is_splash_icon_maskable_bool.xml",
      "res/values-xxxhdpi/is_splash_icon_maskable_bool.xml",
      "res/values/colors.xml",
      "res/values/default_enabled_activity.xml",
      "res/values/dimens.xml",
      "res/xml/shortcuts.xml",
    ]
    sources += get_target_outputs(":$_generate_res_background_xml_target_name")
    sources += get_target_outputs(":$_generated_icons_target_name")
    deps = [
      ":$_generate_res_background_xml_target_name",
      ":$_generated_icons_target_name",
      ":webapk_strings_grd",
    ]
  }

  webapk_java(_java_without_services_target_name) {
    resources_package = "org.chromium.webapk.shell_apk"
    deps = [
      ":$_manifest_target_name",
      ":$_resources_target_name",
    ]
  }

  webapk_with_service_java(_java_with_services_target_name) {
    deps = [
      ":$_java_without_services_target_name",
      ":$_manifest_target_name",
    ]
  }

  android_apk(target_name) {
    forward_variables_from(invoker,
                           [
                             "apk_name",
                             "testonly",
                           ])
    deps = [ ":$_java_with_services_target_name" ]

    android_manifest = _manifest_output
    android_manifest_dep = ":$_manifest_target_name"
    target_sdk_version = 33
    never_incremental = true

    # Force 32 bit mode on 64 bit devices.
    native_lib_placeholders = [ "libfoo.so" ]

    if (!is_java_debug) {
      proguard_enabled = true
      proguard_configs = [ "//chrome/android/webapk/shell_apk/proguard.flags" ]
    }
  }
}

java_strings_grd("webapk_strings_grd") {
  grd_file = "//chrome/android/webapk/strings/android_webapk_strings.grd"

  outputs = [ "values/android_webapk_strings.xml" ] +
            process_file_template(
                android_bundle_locales_as_resources,
                [ "values-{{source_name_part}}/android_webapk_strings.xml" ])
}

# Template for WebAPK. When a WebAPK is generated:
# - Android manifest is customized to the website.
# - App icon is extracted from the website and added to the APK's resources.
webapk_tmpl("webapk_chromeos") {
  config_file = "manifest/bound_manifest_config.json"
  manifest_to_upload_dep = ":generate_chromeos_manifest_for_upload"
  apk_name = "WebApkChromeos"
  apk_package_name = "org.chromium.webapk.chromeos"
}

webapk_tmpl("unbound_webapk") {
  config_file = "manifest/unbound_manifest_config.json"
  manifest_to_upload_dep = ":generate_manifest_for_upload"
  apk_name = "UnboundWebApk"
  apk_package_name = "org.chromium.arbitrarypackage"
}

webapk_tmpl("webapk") {
  config_file = "manifest/bound_manifest_config.json"
  manifest_to_upload_dep = ":generate_manifest_for_upload"
  apk_name = "WebApk"
  apk_package_name = "org.chromium.webapk"
}

group("new_splash_webapk") {
  deps = [ ":webapk" ]
}

# Used by javatests
webapk_tmpl("javatests_webapk") {
  testonly = true
  config_file = "manifest/bound_manifest_config.json"
  manifest_to_upload_dep = ":generate_manifest_for_upload"
  delta_config_file = "manifest/javatest_manifest_config_delta.json"
  apk_name = "JavatestsWebApk"
  apk_package_name = "org.chromium.webapk.test"
}

# Used by webapk_shell_apk_h2o_junit_tests
webapk_tmpl("h2o_j_unit_webapk") {
  config_file = "manifest/bound_manifest_config.json"
  manifest_to_upload_dep = ":generate_manifest_for_upload"
  apk_name = "H2OJUnitWebApk"
  apk_package_name = "org.chromium.webapk.h2o.junit_webapk"
  manifest_output = h2o_junit_manifest_output
  manifest_target_name = h2o_junit_manifest_target_name
}

android_library("shell_apk_javatests") {
  testonly = true
  sources = [
    "javatests/src/org/chromium/webapk/shell_apk/DexLoaderTest.java",
    "javatests/src/org/chromium/webapk/shell_apk/h2o/SplashUtilsTest.java",
  ]
  deps = [
    ":webapk_generated_webapk_java",
    "//base:base_java",
    "//base:base_java_test_support",
    "//chrome/android/webapk/libs/common:common_java",
    "//content/public/test/android:content_java_test_support",
    "//third_party/androidx:androidx_test_core_java",
    "//third_party/androidx:androidx_test_monitor_java",
    "//third_party/androidx:androidx_test_runner_java",
    "//third_party/junit",
  ]
}

robolectric_binary("webapk_shell_apk_junit_tests") {
  package_name = "org.chromium.test"
  sources = [
    "junit/src/org/chromium/webapk/shell_apk/HostBrowserClassLoaderTest.java",
    "junit/src/org/chromium/webapk/shell_apk/HostBrowserLauncherParamsTest.java",
    "junit/src/org/chromium/webapk/shell_apk/HostBrowserUtilsTest.java",
    "junit/src/org/chromium/webapk/shell_apk/MainActivityTest.java",
    "junit/src/org/chromium/webapk/shell_apk/TestBrowserInstaller.java",
    "junit/src/org/chromium/webapk/shell_apk/WebApkServiceImplWrapperTest.java",
    "junit/src/org/chromium/webapk/shell_apk/WebApkUtilsTest.java",
  ]
  deps = [
    ":compiled_in_runtime_library_java",
    ":webapk_generated_webapk_java",
    ":webapk_generated_webapk_with_service_java",
    "//chrome/android/webapk/libs/common:common_java",
    "//chrome/android/webapk/libs/runtime_library:runtime_library_for_tests_java",
    "//chrome/android/webapk/test:junit_test_support",
    "//components/webapk/android/libs/common:java",
    "//third_party/androidx:androidx_annotation_annotation_java",
  ]
}

robolectric_binary("webapk_shell_apk_h2o_junit_tests") {
  package_name = "org.chromium.test"
  sources = [
    "junit/src/org/chromium/webapk/shell_apk/CustomAndroidOsShadowAsyncTask.java",
    "junit/src/org/chromium/webapk/shell_apk/TestBrowserInstaller.java",
    "junit/src/org/chromium/webapk/shell_apk/h2o/LaunchTest.java",
    "junit/src/org/chromium/webapk/shell_apk/h2o/SplashActivityTest.java",
    "junit/src/org/chromium/webapk/shell_apk/h2o/SplashUtilsUnitTest.java",
  ]
  deps = [
    ":${h2o_junit_manifest_target_name}",
    ":h2o_j_unit_webapk_generated_webapk_java",
    ":h2o_j_unit_webapk_generated_webapk_with_service_java",
    "//chrome/android/webapk/libs/common:common_java",
    "//chrome/android/webapk/test:junit_test_support",
    "//components/webapk/android/libs/common:java",
  ]
  data_deps = [ ":${h2o_junit_manifest_target_name}" ]
}