blob: 3c78b9389bec404f18363fad9a4ff7933c58891a [file] [log] [blame]
// 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 <dlfcn.h>
#include "base/android/bundle_utils.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "components/module_installer/android/jni_headers/Module_jni.h"
using base::android::BundleUtils;
#if defined(LOAD_FROM_BASE_LIBRARY)
extern "C" {
// These methods are forward-declared here for the build case where
// partitioned libraries are disabled, and module code is pulled into the main
// library. In that case, there is no current way of dlsym()'ing for this
// JNI registration method, and hence it's referred to directly.
// This list could be auto-generated in the future.
extern bool JNI_OnLoad_test_dummy(JNIEnv* env) __attribute__((weak_import));
} // extern "C"
#endif // LOAD_FROM_BASE_LIBRARY
namespace module_installer {
typedef bool JniRegistrationFunction(JNIEnv* env);
static void JNI_Module_LoadNativeLibrary(
JNIEnv* env,
const base::android::JavaParamRef<jstring>& jtext) {
std::string library_name;
base::android::ConvertJavaStringToUTF8(env, jtext, &library_name);
JniRegistrationFunction* registration_function = nullptr;
#if defined(LOAD_FROM_PARTITIONS) || defined(LOAD_FROM_COMPONENTS)
#if defined(LOAD_FROM_PARTITIONS)
// The partition library must be opened via native code (using
// android_dlopen_ext() under the hood). There is no need to repeat the
// operation on the Java side, because JNI registration is done explicitly
// (hence there is no reason for the Java ClassLoader to be aware of the
// library, for lazy JNI registration).
void* library_handle =
BundleUtils::DlOpenModuleLibraryPartition(library_name);
#else // defined(LOAD_FROM_PARTITIONS)
const std::string lib_name = "lib" + library_name + ".cr.so";
void* library_handle = dlopen(lib_name.c_str(), RTLD_LOCAL);
#endif // defined(LOAD_FROM_PARTITIONS)
CHECK(library_handle != nullptr)
<< "Could not open feature library:" << dlerror();
const std::string registration_name = "JNI_OnLoad_" + library_name;
// Find the module's JNI registration method from the feature library.
void* symbol = dlsym(library_handle, registration_name.c_str());
CHECK(symbol != nullptr) << "Could not find JNI registration method: "
<< dlerror();
registration_function = reinterpret_cast<JniRegistrationFunction*>(symbol);
#else // defined(LOAD_FROM_PARTITIONS) || defined(LOAD_FROM_COMPONENTS)
// TODO(https://crbug.com/870055): Similar to the declarations above, this map
// could be auto-generated.
const std::map<std::string, JniRegistrationFunction*> modules = {
{"test_dummy", JNI_OnLoad_test_dummy}};
registration_function = modules.at(library_name);
#endif // defined(LOAD_FROM_PARTITIONS) || defined(LOAD_FROM_COMPONENTS)
CHECK(registration_function(env))
<< "JNI registration failed: " << library_name;
}
} // namespace module_installer