Commit d205c616 authored by Tibor Goldschwendt's avatar Tibor Goldschwendt Committed by Commit Bot

Add native resource to dummy module and test loading in smoke test

* Adds a new PAK file with a dummy resources.
* Refactors the TestDummyModuleProvider to to synchronously load the
  module PAK file when retrieving the impl.
* Adds a friend to ScopedAllowBlocking in order to be able to memory
  map the module PAK file on the main thread.

Change-Id: I0a3b949b83b37a7089aa410a691de6ae28f9a36a
Bug: 989646
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1822847
Auto-Submit: Tibor Goldschwendt <tiborg@chromium.org>
Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Reviewed-by: default avatarChristopher Grant <cjgrant@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarAndrew Grieve <agrieve@chromium.org>
Reviewed-by: default avatarSamuel Huang <huangs@chromium.org>
Reviewed-by: default avatarFred Mello <fredmello@chromium.org>
Commit-Queue: Tibor Goldschwendt <tiborg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#702423}
parent d9b72f3c
......@@ -194,6 +194,9 @@ class OSMetrics;
namespace midi {
class TaskService; // https://crbug.com/796830
}
namespace module_installer {
class ScopedAllowModulePakLoad;
}
namespace mojo {
class CoreLibraryInitializer;
class SyncCallRestrictions;
......@@ -347,6 +350,7 @@ class BASE_EXPORT ScopedAllowBlocking {
friend class cronet::CronetPrefsManager;
friend class cronet::CronetURLRequestContext;
friend class memory_instrumentation::OSMetrics;
friend class module_installer::ScopedAllowModulePakLoad;
friend class mojo::CoreLibraryInitializer;
friend class resource_coordinator::TabManagerDelegate; // crbug.com/778703
friend class ui::MaterialDesignController;
......
......@@ -1745,6 +1745,7 @@ if (is_android) {
]
deps = [
"//chrome/android/modules/test_dummy/provider:native",
"//chrome/browser/ui",
"//chrome/child",
"//chrome/common",
......
include_rules = [
"+chrome/grit",
]
......@@ -5,6 +5,7 @@
import("//build/buildflag_header.gni")
import("//build/config/android/rules.gni")
import("//chrome/android/modules/buildflags.gni")
import("//tools/grit/grit_rule.gni")
android_resources("java_resources") {
resource_dirs = [ "java/res" ]
......@@ -34,7 +35,9 @@ source_set("native") {
deps = [
":jni_headers",
":resources_native",
"//base",
"//ui/base",
]
}
......@@ -46,7 +49,9 @@ source_set("native") {
android_library("base_module_java") {
deps = [
"//base:base_java",
"//chrome/android/features/test_dummy/public:java",
"//chrome/android/modules/test_dummy/provider:java",
"//chrome/android/modules/test_dummy/public:java",
"//third_party/android_deps:android_support_v7_appcompat_java",
]
java_files = [
......@@ -59,3 +64,15 @@ generate_jni("jni_headers") {
"java/src/org/chromium/chrome/features/test_dummy/TestDummyImpl.java",
]
}
# Cannot call this just "resources" since all targets with that name in
# //chrome/android need a build_config, which grit targets don't have.
grit("resources_native") {
source = "resources/resources.grd"
outputs = [
"grit/test_dummy_resources.h",
"test_dummy_resources.pak",
]
output_dir = "$root_gen_dir/chrome"
depfile_dir = target_gen_dir
}
......@@ -20,6 +20,15 @@ public class TestDummyActivity extends AppCompatActivity {
finish();
return;
}
TestDummyModuleProvider.launchTestDummy(getIntent(), this);
if (!TestDummyModuleProvider.isModuleInstalled()) {
TestDummyModuleProvider.installModule(this::onModuleInstalled);
return;
}
onModuleInstalled(true);
}
private void onModuleInstalled(boolean success) {
if (!success) throw new RuntimeException("Failed to install module");
TestDummyModuleProvider.getTestDummyProvider().getTestDummy().launch(getIntent(), this);
}
}
......@@ -29,6 +29,7 @@ public class TestDummyImpl implements TestDummy {
int EXECUTE_JAVA = 0;
int EXECUTE_NATIVE = 1;
int LOAD_JAVA_RESOURCE = 2;
int LOAD_NATIVE_RESOURCE = 3;
}
@Override
......@@ -45,6 +46,9 @@ public class TestDummyImpl implements TestDummy {
case TestCase.LOAD_JAVA_RESOURCE:
loadJavaResource(activity);
break;
case TestCase.LOAD_NATIVE_RESOURCE:
loadNativeResource(activity);
break;
default:
throw new RuntimeException("Unknown test case " + testCase);
}
......@@ -53,6 +57,7 @@ public class TestDummyImpl implements TestDummy {
@NativeMethods
interface Natives {
int execute();
String loadResource();
}
private void showDoneDialog(Activity activity, @TestCase int testCase, boolean pass) {
......@@ -94,4 +99,9 @@ public class TestDummyImpl implements TestDummy {
}
showDoneDialog(activity, TestCase.LOAD_JAVA_RESOURCE, result);
}
private void loadNativeResource(Activity activity) {
boolean result = TestDummyImplJni.get().loadResource().equals("Hello, World!");
showDoneDialog(activity, TestCase.LOAD_NATIVE_RESOURCE, result);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<grit latest_public_release="0"
current_release="1"
output_all_resource_defines="false">
<outputs>
<output filename="grit/test_dummy_resources.h"
type="rc_header">
<emit emit_type='prepend'></emit>
</output>
<output filename="test_dummy_resources.pak"
type="data_package" />
</outputs>
<release seq="1">
<includes>
<include name="IDR_TEST_DUMMY_TEST_RESOURCE"
file="test_resource.txt"
type="BINDATA" />
</includes>
</release>
</grit>
......@@ -2,10 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/android/jni_string.h"
#include "base/logging.h"
#include "chrome/android/features/test_dummy/internal/jni_headers/TestDummyImpl_jni.h"
#include "chrome/grit/test_dummy_resources.h"
#include "ui/base/resource/resource_bundle.h"
static int JNI_TestDummyImpl_Execute(JNIEnv* env) {
LOG(INFO) << "Running test dummy native library";
return 123;
}
static base::android::ScopedJavaLocalRef<jstring>
JNI_TestDummyImpl_LoadResource(JNIEnv* env) {
auto resource = ui::ResourceBundle::GetSharedInstance().GetRawDataResource(
IDR_TEST_DUMMY_TEST_RESOURCE);
LOG(INFO) << "Loading dummy native resource: " << resource;
return base::android::ConvertUTF8ToJavaString(env, resource);
}
......@@ -83,4 +83,9 @@ public class ChromeBundleSmokeTest {
public void testModuleJavaResourceLoading() {
runTestActivity(2); // Test case LOAD_JAVA_RESOURCE.
}
@Test
public void testModuleNativeResourceLoading() {
runTestActivity(3); // Test case LOAD_NATIVE_RESOURCE.
}
}
......@@ -56,3 +56,13 @@ generate_jni_registration("jni_registration") {
header_output = "$target_gen_dir/jni_registration.h"
namespace = "test_dummy"
}
android_assets("pak_assets") {
sources = [
"$root_gen_dir/chrome/test_dummy_resources.pak",
]
deps = [
"//chrome/android/features/test_dummy/internal:resources_native",
]
disable_compression = true
}
......@@ -2,12 +2,34 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/buildflag_header.gni")
import("//build/config/android/rules.gni")
import("//chrome/android/modules/buildflags.gni")
android_library("java") {
deps = [
"//base:base_java",
"//base:jni_java",
"//chrome/android/features/test_dummy/public:java",
"//chrome/android/modules/test_dummy/public:java",
]
java_files = [ "java/src/org/chromium/chrome/modules/test_dummy/TestDummyModuleProvider.java" ]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
}
generate_jni("jni_headers") {
sources = [
"java/src/org/chromium/chrome/modules/test_dummy/TestDummyModuleProvider.java",
]
}
source_set("native") {
deps = [
":jni_headers",
"//base",
"//ui/base",
]
sources = [
"test_dummy_module_provider.cc",
]
}
......@@ -4,31 +4,52 @@
package org.chromium.chrome.modules.test_dummy;
import android.app.Activity;
import android.content.Intent;
import org.chromium.base.ThreadUtils;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods;
import org.chromium.components.module_installer.OnModuleInstallFinishedListener;
/** Installs the test dummy module and launches the test dummy implementation. */
/** Installs and loads the test dummy module. */
@JNINamespace("test_dummy")
public class TestDummyModuleProvider {
private static boolean sIsModuleLoaded;
/** Returns true if the module is installed. */
public static boolean isModuleInstalled() {
ThreadUtils.assertOnUiThread();
return TestDummyModule.isInstalled();
}
/**
* Installs the module.
*
* Can only be called if the module is not installed.
*
* @param onFinished Called when the install has finished.
*/
public static void installModule(OnModuleInstallFinishedListener onFinished) {
ThreadUtils.assertOnUiThread();
TestDummyModule.install(onFinished);
}
/**
* Launches test dummy. Installs test dummy module if necessary.
* Returns the test dummy provider from inside the module.
*
* @param intent A test dummy intent encoding the desired test scenario.
* @param activity The activity the test dummy will run in.
* Can only be called if the module is installed. Maps native resources into memory on first
* call.
*/
public static void launchTestDummy(Intent intent, Activity activity) {
if (!TestDummyModule.isInstalled()) {
installAndLaunchTestDummy(intent, activity);
return;
public static TestDummyProvider getTestDummyProvider() {
ThreadUtils.assertOnUiThread();
assert isModuleInstalled();
if (!sIsModuleLoaded) {
TestDummyModuleProviderJni.get().loadNative();
sIsModuleLoaded = true;
}
TestDummyModule.getImpl().getTestDummy().launch(intent, activity);
return TestDummyModule.getImpl();
}
private static void installAndLaunchTestDummy(Intent intent, Activity activity) {
TestDummyModule.install((success) -> {
if (!success) {
throw new RuntimeException("Failed to install module.");
}
TestDummyModule.getImpl().getTestDummy().launch(intent, activity);
});
@NativeMethods
interface Natives {
void loadNative();
}
}
// Copyright 2019 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.
#include "base/android/apk_assets.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/android/modules/test_dummy/provider/jni_headers/TestDummyModuleProvider_jni.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/resource/scale_factor.h"
// Native partner of the Java TestDummyModuleProvider. Used to load native
// resources of the test dummy module into memory.
// TODO(tiborg): Move to //components/module_installer so that it can be used by
// other modules.
namespace module_installer {
// Allows memory mapping module PAK files on the main thread.
//
// We expect the memory mapping step to be quick. All it does is retrieveing a
// region from the APK file that should already be memory mapped and reading the
// PAK file header. Most of the disk IO is happening when accessing a resource.
// And this traditionally happens synchronously on the main thread.
class ScopedAllowModulePakLoad {
public:
ScopedAllowModulePakLoad() {}
~ScopedAllowModulePakLoad() {}
private:
base::ScopedAllowBlocking allow_blocking_;
};
} // namespace module_installer
namespace test_dummy {
static void JNI_TestDummyModuleProvider_LoadNative(JNIEnv* env) {
module_installer::ScopedAllowModulePakLoad resource_loader;
std::string path = "assets/test_dummy_resources.pak";
base::MemoryMappedFile::Region region;
int fd = base::android::OpenApkAsset(path, &region);
if (fd < 0) {
NOTREACHED() << "Cannot find " << path << " in APK.";
}
ui::ResourceBundle::GetSharedInstance().AddDataPackFromFileRegion(
base::File(fd), region, ui::SCALE_FACTOR_NONE);
}
} // namespace test_dummy
......@@ -11,6 +11,7 @@ test_dummy_module_desc = {
java_deps = [
"//chrome/android/features/test_dummy/internal:java",
"//chrome/android/modules/test_dummy/internal:java",
"//chrome/android/modules/test_dummy/internal:pak_assets",
]
native_deps = [
......
......@@ -172,6 +172,9 @@
# END chrome/ WebUI resources section
# START chrome/ miscellaneous section.
"chrome/android/features/test_dummy/internal/resources/resources.grd": {
"includes": [14070],
},
"chrome/common/common_resources.grd": {
"includes": [14160],
},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment