2012-05-21 15:12:37 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2010-10-15 22:27:57 +04:00
|
|
|
|
2010-10-29 23:22:28 +04:00
|
|
|
/*
|
|
|
|
* This custom library loading code is only meant to be called
|
2017-04-12 12:34:17 +03:00
|
|
|
* during initialization. As a result, it takes no special
|
2010-10-29 23:22:28 +04:00
|
|
|
* precautions to be threadsafe. Any of the library loading functions
|
|
|
|
* like mozload should not be available to other code.
|
|
|
|
*/
|
|
|
|
|
2010-10-15 22:27:57 +04:00
|
|
|
#include <jni.h>
|
|
|
|
#include <android/log.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/mman.h>
|
2010-10-29 23:22:28 +04:00
|
|
|
#include <sys/limits.h>
|
2010-10-15 22:27:57 +04:00
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
2010-10-29 23:22:28 +04:00
|
|
|
#include <stdlib.h>
|
2010-10-15 22:27:57 +04:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <zlib.h>
|
|
|
|
#include "dlfcn.h"
|
2010-10-21 04:44:03 +04:00
|
|
|
#include "APKOpen.h"
|
2011-01-13 00:08:28 +03:00
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/resource.h>
|
2013-05-28 11:44:57 +04:00
|
|
|
#include <sys/prctl.h>
|
2012-01-20 00:19:56 +04:00
|
|
|
#include "sqlite3.h"
|
|
|
|
#include "SQLiteBridge.h"
|
2012-03-08 22:25:44 +04:00
|
|
|
#include "NSSBridge.h"
|
2012-01-20 12:49:07 +04:00
|
|
|
#include "ElfLoader.h"
|
2012-02-22 11:12:15 +04:00
|
|
|
#include "application.ini.h"
|
2010-10-15 22:27:57 +04:00
|
|
|
|
2017-03-01 22:26:12 +03:00
|
|
|
#include "mozilla/arm.h"
|
2016-12-17 00:48:01 +03:00
|
|
|
#include "mozilla/Bootstrap.h"
|
2015-07-06 19:01:09 +03:00
|
|
|
#include "mozilla/TimeStamp.h"
|
2015-10-30 18:16:24 +03:00
|
|
|
#include "mozilla/UniquePtr.h"
|
2016-05-15 18:35:22 +03:00
|
|
|
#include "XREChildData.h"
|
2015-07-06 19:01:09 +03:00
|
|
|
|
2011-11-18 11:54:17 +04:00
|
|
|
/* Android headers don't define RUSAGE_THREAD */
|
|
|
|
#ifndef RUSAGE_THREAD
|
|
|
|
#define RUSAGE_THREAD 1
|
|
|
|
#endif
|
|
|
|
|
2016-10-08 12:14:49 +03:00
|
|
|
#ifndef RELEASE_OR_BETA
|
2013-05-28 11:44:57 +04:00
|
|
|
/* Official builds have the debuggable flag set to false, which disables
|
|
|
|
* the backtrace dumper from bionic. However, as it is useful for native
|
|
|
|
* crashes happening before the crash reporter is registered, re-enable
|
|
|
|
* it on non release builds (i.e. nightly and aurora).
|
|
|
|
* Using a constructor so that it is re-enabled as soon as libmozglue.so
|
|
|
|
* is loaded.
|
|
|
|
*/
|
|
|
|
__attribute__((constructor))
|
|
|
|
void make_dumpable() {
|
|
|
|
prctl(PR_SET_DUMPABLE, 1);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-03-13 12:49:18 +04:00
|
|
|
extern "C" {
|
|
|
|
/*
|
|
|
|
* To work around http://code.google.com/p/android/issues/detail?id=23203
|
|
|
|
* we don't link with the crt objects. In some configurations, this means
|
|
|
|
* a lack of the __dso_handle symbol because it is defined there, and
|
|
|
|
* depending on the android platform and ndk versions used, it may or may
|
|
|
|
* not be defined in libc.so. In the latter case, we fail to link. Defining
|
|
|
|
* it here as weak makes us provide the symbol when it's not provided by
|
|
|
|
* the crt objects, making the change transparent for future NDKs that
|
|
|
|
* would fix the original problem. On older NDKs, it is not a problem
|
|
|
|
* either because the way __dso_handle was used was already broken (and
|
|
|
|
* the custom linker works around it).
|
|
|
|
*/
|
2016-11-29 22:27:30 +03:00
|
|
|
APKOPEN_EXPORT __attribute__((weak)) void *__dso_handle;
|
2012-03-13 12:49:18 +04:00
|
|
|
}
|
|
|
|
|
2012-03-08 22:25:44 +04:00
|
|
|
typedef int mozglueresult;
|
|
|
|
|
2011-11-18 11:54:37 +04:00
|
|
|
enum StartupEvent {
|
|
|
|
#define mozilla_StartupTimeline_Event(ev, z) ev,
|
|
|
|
#include "StartupTimeline.h"
|
|
|
|
#undef mozilla_StartupTimeline_Event
|
2012-06-18 20:06:59 +04:00
|
|
|
MAX_STARTUP_EVENT_ID
|
2011-11-18 11:54:37 +04:00
|
|
|
};
|
|
|
|
|
2012-02-13 18:49:45 +04:00
|
|
|
using namespace mozilla;
|
|
|
|
|
2016-09-09 15:32:48 +03:00
|
|
|
static const int MAX_MAPPING_INFO = 32;
|
|
|
|
static mapping_info lib_mapping[MAX_MAPPING_INFO];
|
2010-10-29 23:22:28 +04:00
|
|
|
|
2016-11-29 22:27:30 +03:00
|
|
|
APKOPEN_EXPORT const struct mapping_info *
|
2010-10-29 23:22:28 +04:00
|
|
|
getLibraryMapping()
|
|
|
|
{
|
|
|
|
return lib_mapping;
|
|
|
|
}
|
|
|
|
|
2012-03-08 22:25:44 +04:00
|
|
|
void
|
|
|
|
JNI_Throw(JNIEnv* jenv, const char* classname, const char* msg)
|
|
|
|
{
|
|
|
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Throw\n");
|
|
|
|
jclass cls = jenv->FindClass(classname);
|
2013-11-11 23:14:45 +04:00
|
|
|
if (cls == nullptr) {
|
2012-03-08 22:25:44 +04:00
|
|
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't find exception class (or exception pending) %s\n", classname);
|
|
|
|
exit(FAILURE);
|
|
|
|
}
|
|
|
|
int rc = jenv->ThrowNew(cls, msg);
|
|
|
|
if (rc < 0) {
|
|
|
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Error throwing exception %s\n", msg);
|
|
|
|
exit(FAILURE);
|
|
|
|
}
|
|
|
|
jenv->DeleteLocalRef(cls);
|
|
|
|
}
|
|
|
|
|
2014-09-24 22:12:54 +04:00
|
|
|
namespace {
|
|
|
|
JavaVM* sJavaVM;
|
2016-08-13 06:15:52 +03:00
|
|
|
pthread_t sJavaUiThread;
|
2014-09-24 22:12:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
abortThroughJava(const char* msg)
|
|
|
|
{
|
|
|
|
struct sigaction sigact = {};
|
|
|
|
if (SEGVHandler::__wrap_sigaction(SIGSEGV, nullptr, &sigact)) {
|
|
|
|
return; // sigaction call failed.
|
|
|
|
}
|
|
|
|
|
|
|
|
Dl_info info = {};
|
|
|
|
if ((sigact.sa_flags & SA_SIGINFO) &&
|
|
|
|
__wrap_dladdr(reinterpret_cast<void*>(sigact.sa_sigaction), &info) &&
|
|
|
|
info.dli_fname && strstr(info.dli_fname, "libxul.so")) {
|
|
|
|
|
|
|
|
return; // Existing signal handler is in libxul (i.e. we have crash reporter).
|
|
|
|
}
|
|
|
|
|
|
|
|
JNIEnv* env = nullptr;
|
|
|
|
if (!sJavaVM || sJavaVM->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!env || env->PushLocalFrame(2) != JNI_OK) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
jclass loader = env->FindClass("org/mozilla/gecko/mozglue/GeckoLoader");
|
|
|
|
if (!loader) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
jmethodID method = env->GetStaticMethodID(loader, "abort", "(Ljava/lang/String;)V");
|
|
|
|
jstring str = env->NewStringUTF(msg);
|
|
|
|
|
|
|
|
if (method && str) {
|
|
|
|
env->CallStaticVoidMethod(loader, method, str);
|
|
|
|
}
|
|
|
|
|
|
|
|
env->PopLocalFrame(nullptr);
|
|
|
|
}
|
|
|
|
|
2016-11-29 22:27:30 +03:00
|
|
|
APKOPEN_EXPORT pthread_t
|
2016-08-13 06:15:52 +03:00
|
|
|
getJavaUiThread()
|
|
|
|
{
|
|
|
|
return sJavaUiThread;
|
|
|
|
}
|
|
|
|
|
2016-11-29 22:27:30 +03:00
|
|
|
extern "C" APKOPEN_EXPORT void MOZ_JNICALL
|
2016-08-13 06:15:52 +03:00
|
|
|
Java_org_mozilla_gecko_GeckoThread_registerUiThread(JNIEnv*, jclass)
|
|
|
|
{
|
|
|
|
sJavaUiThread = pthread_self();
|
|
|
|
}
|
|
|
|
|
2016-12-17 00:48:01 +03:00
|
|
|
Bootstrap::UniquePtr gBootstrap;
|
2013-03-17 11:02:35 +04:00
|
|
|
#ifndef MOZ_FOLD_LIBS
|
2013-11-11 23:14:45 +04:00
|
|
|
static void * sqlite_handle = nullptr;
|
|
|
|
static void * nspr_handle = nullptr;
|
|
|
|
static void * plc_handle = nullptr;
|
2013-03-17 11:02:35 +04:00
|
|
|
#else
|
|
|
|
#define sqlite_handle nss_handle
|
|
|
|
#define nspr_handle nss_handle
|
|
|
|
#define plc_handle nss_handle
|
|
|
|
#endif
|
2013-11-11 23:14:45 +04:00
|
|
|
static void * nss_handle = nullptr;
|
2010-10-15 22:27:57 +04:00
|
|
|
|
2010-10-21 04:44:03 +04:00
|
|
|
static int mapping_count = 0;
|
|
|
|
|
|
|
|
extern "C" void
|
|
|
|
report_mapping(char *name, void *base, uint32_t len, uint32_t offset)
|
|
|
|
{
|
2013-04-09 16:05:07 +04:00
|
|
|
if (mapping_count >= MAX_MAPPING_INFO)
|
2010-10-21 04:44:03 +04:00
|
|
|
return;
|
|
|
|
|
|
|
|
struct mapping_info *info = &lib_mapping[mapping_count++];
|
|
|
|
info->name = strdup(name);
|
|
|
|
info->base = (uintptr_t)base;
|
|
|
|
info->len = len;
|
|
|
|
info->offset = offset;
|
|
|
|
}
|
|
|
|
|
2016-11-10 03:32:16 +03:00
|
|
|
extern "C" void
|
|
|
|
delete_mapping(const char *name)
|
|
|
|
{
|
|
|
|
for (int pos = 0; pos < mapping_count; ++pos) {
|
|
|
|
struct mapping_info *info = &lib_mapping[pos];
|
|
|
|
if (!strcmp(info->name, name)) {
|
|
|
|
struct mapping_info *last = &lib_mapping[mapping_count - 1];
|
|
|
|
free(info->name);
|
|
|
|
*info = *last;
|
|
|
|
--mapping_count;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-17 00:48:01 +03:00
|
|
|
static UniquePtr<char[]>
|
|
|
|
getAPKLibraryName(const char* apkName, const char* libraryName)
|
2015-10-30 18:16:24 +03:00
|
|
|
{
|
|
|
|
#define APK_ASSETS_PATH "!/assets/" ANDROID_CPU_ARCH "/"
|
|
|
|
size_t filenameLength = strlen(apkName) +
|
|
|
|
sizeof(APK_ASSETS_PATH) + // includes \0 terminator
|
|
|
|
strlen(libraryName);
|
|
|
|
auto file = MakeUnique<char[]>(filenameLength);
|
|
|
|
snprintf(file.get(), filenameLength, "%s" APK_ASSETS_PATH "%s",
|
|
|
|
apkName, libraryName);
|
2016-12-17 00:48:01 +03:00
|
|
|
return file;
|
2015-10-30 18:16:24 +03:00
|
|
|
#undef APK_ASSETS_PATH
|
|
|
|
}
|
2016-12-17 00:48:01 +03:00
|
|
|
|
|
|
|
static void*
|
|
|
|
dlopenAPKLibrary(const char* apkName, const char* libraryName)
|
|
|
|
{
|
|
|
|
return __wrap_dlopen(getAPKLibraryName(apkName, libraryName).get(), RTLD_GLOBAL | RTLD_LAZY);
|
|
|
|
}
|
|
|
|
|
2012-03-08 22:25:44 +04:00
|
|
|
static mozglueresult
|
2012-01-20 00:19:56 +04:00
|
|
|
loadGeckoLibs(const char *apkName)
|
2010-10-15 22:27:57 +04:00
|
|
|
{
|
2015-07-06 19:01:09 +03:00
|
|
|
TimeStamp t0 = TimeStamp::Now();
|
2013-05-28 11:44:39 +04:00
|
|
|
struct rusage usage1_thread, usage1;
|
|
|
|
getrusage(RUSAGE_THREAD, &usage1_thread);
|
|
|
|
getrusage(RUSAGE_SELF, &usage1);
|
2010-10-15 22:27:57 +04:00
|
|
|
|
2016-12-17 00:48:01 +03:00
|
|
|
gBootstrap = GetBootstrap(getAPKLibraryName(apkName, "libxul.so").get());
|
|
|
|
if (!gBootstrap) {
|
2010-10-15 22:27:57 +04:00
|
|
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libxul!");
|
2012-03-08 22:25:44 +04:00
|
|
|
return FAILURE;
|
|
|
|
}
|
2010-10-15 22:27:57 +04:00
|
|
|
|
2015-07-06 19:01:09 +03:00
|
|
|
TimeStamp t1 = TimeStamp::Now();
|
2013-05-28 11:44:39 +04:00
|
|
|
struct rusage usage2_thread, usage2;
|
|
|
|
getrusage(RUSAGE_THREAD, &usage2_thread);
|
|
|
|
getrusage(RUSAGE_SELF, &usage2);
|
|
|
|
|
|
|
|
#define RUSAGE_TIMEDIFF(u1, u2, field) \
|
|
|
|
((u2.ru_ ## field.tv_sec - u1.ru_ ## field.tv_sec) * 1000 + \
|
|
|
|
(u2.ru_ ## field.tv_usec - u1.ru_ ## field.tv_usec) / 1000)
|
|
|
|
|
2015-07-06 19:01:09 +03:00
|
|
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Loaded libs in %fms total, %ldms(%ldms) user, %ldms(%ldms) system, %ld(%ld) faults",
|
|
|
|
(t1 - t0).ToMilliseconds(),
|
2013-05-28 11:44:39 +04:00
|
|
|
RUSAGE_TIMEDIFF(usage1_thread, usage2_thread, utime),
|
|
|
|
RUSAGE_TIMEDIFF(usage1, usage2, utime),
|
|
|
|
RUSAGE_TIMEDIFF(usage1_thread, usage2_thread, stime),
|
|
|
|
RUSAGE_TIMEDIFF(usage1, usage2, stime),
|
|
|
|
usage2_thread.ru_majflt - usage1_thread.ru_majflt,
|
|
|
|
usage2.ru_majflt - usage1.ru_majflt);
|
2011-11-18 11:54:37 +04:00
|
|
|
|
2016-12-17 00:48:01 +03:00
|
|
|
gBootstrap->XRE_StartupTimelineRecord(LINKER_INITIALIZED, t0);
|
|
|
|
gBootstrap->XRE_StartupTimelineRecord(LIBRARIES_LOADED, t1);
|
2012-03-08 22:25:44 +04:00
|
|
|
return SUCCESS;
|
2010-10-15 22:27:57 +04:00
|
|
|
}
|
|
|
|
|
2013-03-17 11:02:35 +04:00
|
|
|
static mozglueresult loadNSSLibs(const char *apkName);
|
|
|
|
|
|
|
|
static mozglueresult
|
|
|
|
loadSQLiteLibs(const char *apkName)
|
2012-01-20 00:19:56 +04:00
|
|
|
{
|
2013-03-17 11:02:35 +04:00
|
|
|
if (sqlite_handle)
|
|
|
|
return SUCCESS;
|
|
|
|
|
|
|
|
#ifdef MOZ_FOLD_LIBS
|
|
|
|
if (loadNSSLibs(apkName) != SUCCESS)
|
|
|
|
return FAILURE;
|
|
|
|
#else
|
2012-01-20 00:19:56 +04:00
|
|
|
|
2015-10-30 18:16:24 +03:00
|
|
|
sqlite_handle = dlopenAPKLibrary(apkName, "libmozsqlite3.so");
|
2012-03-08 22:25:44 +04:00
|
|
|
if (!sqlite_handle) {
|
2012-01-20 00:19:56 +04:00
|
|
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libmozsqlite3!");
|
2012-03-08 22:25:44 +04:00
|
|
|
return FAILURE;
|
|
|
|
}
|
2013-03-17 11:02:35 +04:00
|
|
|
#endif
|
2012-01-20 00:19:56 +04:00
|
|
|
|
|
|
|
setup_sqlite_functions(sqlite_handle);
|
2012-03-08 22:25:44 +04:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static mozglueresult
|
|
|
|
loadNSSLibs(const char *apkName)
|
|
|
|
{
|
2013-03-17 11:02:35 +04:00
|
|
|
if (nss_handle && nspr_handle && plc_handle)
|
|
|
|
return SUCCESS;
|
|
|
|
|
2015-10-30 18:16:24 +03:00
|
|
|
nss_handle = dlopenAPKLibrary(apkName, "libnss3.so");
|
2012-03-08 22:25:44 +04:00
|
|
|
|
2013-03-17 11:02:35 +04:00
|
|
|
#ifndef MOZ_FOLD_LIBS
|
2015-10-30 18:16:24 +03:00
|
|
|
nspr_handle = dlopenAPKLibrary(apkName, "libnspr4.so");
|
|
|
|
|
|
|
|
plc_handle = dlopenAPKLibrary(apkName, "libplc4.so");
|
2013-03-17 11:02:35 +04:00
|
|
|
#endif
|
2012-03-08 22:25:44 +04:00
|
|
|
|
|
|
|
if (!nss_handle) {
|
|
|
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libnss3!");
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
2013-03-17 11:02:35 +04:00
|
|
|
#ifndef MOZ_FOLD_LIBS
|
2012-03-08 22:25:44 +04:00
|
|
|
if (!nspr_handle) {
|
|
|
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libnspr4!");
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!plc_handle) {
|
|
|
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libplc4!");
|
|
|
|
return FAILURE;
|
|
|
|
}
|
2013-03-17 11:02:35 +04:00
|
|
|
#endif
|
2012-03-08 22:25:44 +04:00
|
|
|
|
|
|
|
return setup_nss_functions(nss_handle, nspr_handle, plc_handle);
|
2012-01-20 00:19:56 +04:00
|
|
|
}
|
|
|
|
|
2016-11-29 22:27:30 +03:00
|
|
|
extern "C" APKOPEN_EXPORT void MOZ_JNICALL
|
2013-02-07 18:37:06 +04:00
|
|
|
Java_org_mozilla_gecko_mozglue_GeckoLoader_loadGeckoLibsNative(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName)
|
2010-10-15 22:27:57 +04:00
|
|
|
{
|
2014-09-24 22:12:54 +04:00
|
|
|
jenv->GetJavaVM(&sJavaVM);
|
|
|
|
|
2012-01-20 00:19:56 +04:00
|
|
|
const char* str;
|
|
|
|
// XXX: java doesn't give us true UTF8, we should figure out something
|
|
|
|
// better to do here
|
2013-11-11 23:14:45 +04:00
|
|
|
str = jenv->GetStringUTFChars(jApkName, nullptr);
|
|
|
|
if (str == nullptr)
|
2012-01-20 00:19:56 +04:00
|
|
|
return;
|
|
|
|
|
2012-03-08 22:25:44 +04:00
|
|
|
int res = loadGeckoLibs(str);
|
|
|
|
if (res != SUCCESS) {
|
|
|
|
JNI_Throw(jenv, "java/lang/Exception", "Error loading gecko libraries");
|
|
|
|
}
|
2012-01-20 00:19:56 +04:00
|
|
|
jenv->ReleaseStringUTFChars(jApkName, str);
|
|
|
|
}
|
|
|
|
|
2016-11-29 22:27:30 +03:00
|
|
|
extern "C" APKOPEN_EXPORT void MOZ_JNICALL
|
2014-08-26 23:08:00 +04:00
|
|
|
Java_org_mozilla_gecko_mozglue_GeckoLoader_loadSQLiteLibsNative(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName) {
|
2012-03-08 22:25:44 +04:00
|
|
|
const char* str;
|
|
|
|
// XXX: java doesn't give us true UTF8, we should figure out something
|
|
|
|
// better to do here
|
2013-11-11 23:14:45 +04:00
|
|
|
str = jenv->GetStringUTFChars(jApkName, nullptr);
|
|
|
|
if (str == nullptr)
|
2012-03-08 22:25:44 +04:00
|
|
|
return;
|
|
|
|
|
2012-03-08 22:25:44 +04:00
|
|
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Load sqlite start\n");
|
|
|
|
mozglueresult rv = loadSQLiteLibs(str);
|
|
|
|
if (rv != SUCCESS) {
|
|
|
|
JNI_Throw(jenv, "java/lang/Exception", "Error loading sqlite libraries");
|
2012-01-20 12:49:07 +04:00
|
|
|
}
|
2012-03-08 22:25:44 +04:00
|
|
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Load sqlite done\n");
|
|
|
|
jenv->ReleaseStringUTFChars(jApkName, str);
|
|
|
|
}
|
2011-01-07 05:02:07 +03:00
|
|
|
|
2016-11-29 22:27:30 +03:00
|
|
|
extern "C" APKOPEN_EXPORT void MOZ_JNICALL
|
2014-08-26 23:08:00 +04:00
|
|
|
Java_org_mozilla_gecko_mozglue_GeckoLoader_loadNSSLibsNative(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName) {
|
2010-10-15 22:27:57 +04:00
|
|
|
const char* str;
|
2012-01-20 00:19:56 +04:00
|
|
|
// XXX: java doesn't give us true UTF8, we should figure out something
|
2010-10-15 22:27:57 +04:00
|
|
|
// better to do here
|
2013-11-11 23:14:45 +04:00
|
|
|
str = jenv->GetStringUTFChars(jApkName, nullptr);
|
|
|
|
if (str == nullptr)
|
2010-10-15 22:27:57 +04:00
|
|
|
return;
|
|
|
|
|
2012-03-08 22:25:44 +04:00
|
|
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Load nss start\n");
|
|
|
|
mozglueresult rv = loadNSSLibs(str);
|
|
|
|
if (rv != SUCCESS) {
|
|
|
|
JNI_Throw(jenv, "java/lang/Exception", "Error loading nss libraries");
|
|
|
|
}
|
|
|
|
__android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Load nss done\n");
|
2010-10-15 22:27:57 +04:00
|
|
|
jenv->ReleaseStringUTFChars(jApkName, str);
|
|
|
|
}
|
|
|
|
|
2016-10-06 02:46:53 +03:00
|
|
|
static char**
|
|
|
|
CreateArgvFromObjectArray(JNIEnv *jenv, jobjectArray jargs, int* length)
|
|
|
|
{
|
|
|
|
size_t stringCount = jenv->GetArrayLength(jargs);
|
2012-02-22 11:12:15 +04:00
|
|
|
|
2016-10-06 02:46:53 +03:00
|
|
|
if (length) {
|
|
|
|
*length = stringCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!stringCount) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
char** argv = new char*[stringCount + 1];
|
|
|
|
|
|
|
|
argv[stringCount] = nullptr;
|
|
|
|
|
|
|
|
for (size_t ix = 0; ix < stringCount; ix++) {
|
|
|
|
jstring string = (jstring) (jenv->GetObjectArrayElement(jargs, ix));
|
|
|
|
const char* rawString = jenv->GetStringUTFChars(string, nullptr);
|
|
|
|
const int strLength = jenv->GetStringUTFLength(string);
|
|
|
|
argv[ix] = strndup(rawString, strLength);
|
|
|
|
jenv->ReleaseStringUTFChars(string, rawString);
|
|
|
|
jenv->DeleteLocalRef(string);
|
|
|
|
}
|
|
|
|
|
|
|
|
return argv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FreeArgv(char** argv, int argc)
|
2012-02-22 11:12:15 +04:00
|
|
|
{
|
2016-10-06 02:46:53 +03:00
|
|
|
for (int ix=0; ix < argc; ix++) {
|
|
|
|
// String was allocated with strndup, so need to use free to deallocate.
|
|
|
|
free(argv[ix]);
|
|
|
|
}
|
|
|
|
delete[](argv);
|
2012-02-22 11:12:15 +04:00
|
|
|
}
|
|
|
|
|
2016-11-29 22:27:30 +03:00
|
|
|
extern "C" APKOPEN_EXPORT void MOZ_JNICALL
|
2016-10-06 02:46:53 +03:00
|
|
|
Java_org_mozilla_gecko_mozglue_GeckoLoader_nativeRun(JNIEnv *jenv, jclass jc, jobjectArray jargs, int crashFd, int ipcFd)
|
|
|
|
{
|
|
|
|
int argc = 0;
|
|
|
|
char** argv = CreateArgvFromObjectArray(jenv, jargs, &argc);
|
|
|
|
|
|
|
|
if (ipcFd < 0) {
|
2016-12-17 00:48:01 +03:00
|
|
|
if (gBootstrap == nullptr) {
|
2016-10-06 02:46:53 +03:00
|
|
|
FreeArgv(argv, argc);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ElfLoader::Singleton.ExpectShutdown(false);
|
2016-12-17 00:48:01 +03:00
|
|
|
gBootstrap->GeckoStart(jenv, argv, argc, sAppData);
|
2016-10-06 02:46:53 +03:00
|
|
|
ElfLoader::Singleton.ExpectShutdown(true);
|
|
|
|
} else {
|
Bug 1343075 - Use GeckoEditableSupport from PuppetWidget; r=masayuki r=rbarker r=snorp r=esawin
Bug 1343075 - 1a. Add TextEventDispatcherListener::GetIMEUpdatePreference; r=masayuki
Add a GetIMEUpdatePreference method to TextEventDispatcherListener to
optionally control which IME notifications are received by NotifyIME.
This patch also makes nsBaseWidget forward its GetIMEUpdatePreference
call to the widget's native TextEventDispatcherListener.
Bug 1343075 - 1b. Implement GetIMEUpdatePreference for all TextEventDispatcherListener; r=masayuki
This patch implements GetIMEUpdatePreference for all
TextEventDispatcherListener implementations, by moving previous
implementations of nsIWidget::GetIMEUpdatePreference.
Bug 1343075 - 2. Allow setting a PuppetWidget's native TextEventDispatcherListener; r=masayuki
In PuppetWidget, add getter and setter for the widget's native
TextEventDispatcherListener. This allows overriding of PuppetWidget's
default IME handling. For example, on Android, the PuppetWidget's native
TextEventDispatcherListener will communicate directly with Java IME code
in the main process.
Bug 1343075 - 3. Add AIDL interface for main process; r=rbarker
Add AIDL definition and implementation for an interface for the main
process that child processes can access.
Bug 1343075 - 4. Set Gecko thread JNIEnv for child process; r=snorp
Add a JNIEnv* parameter to XRE_SetAndroidChildFds, which is used to set
the Gecko thread JNIEnv for child processes. XRE_SetAndroidChildFds is
the only Android-specific entry point for child processes, so I think
it's the most logical place to initialize JNI.
Bug 1343075 - 5. Support multiple remote GeckoEditableChild; r=esawin
Support remote GeckoEditableChild instances that are created in the
content processes and connect to the parent process GeckoEditableParent
through binders.
Support having multiple GeckoEditableChild instances in GeckoEditable by
keeping track of which child is currently focused, and only allow
calls to/from the focused child by using access tokens.
Bug 1343075 - 6. Add method to get GeckoEditableParent instance; r=esawin
Add IProcessManager.getEditableParent, which a content process can call
to get the GeckoEditableParent instance that corresponds to a given
content process tab, from the main process.
Bug 1343075 - 7. Support GeckoEditableSupport in content processes; r=esawin
Support creating and running GeckoEditableSupport attached to a
PuppetWidget in content processes.
Because we don't know PuppetWidget's lifetime as well as nsWindow's,
when attached to PuppetWidget, we need to attach/detach our native
object on focus/blur, respectively.
Bug 1343075 - 8. Connect GeckoEditableSupport on PuppetWidget creation; r=esawin
Listen to the "tab-child-created" notification and attach our content
process GeckoEditableSupport to the new PuppetWidget.
Bug 1343075 - 9. Update auto-generated bindings; r=me
2017-03-08 06:34:39 +03:00
|
|
|
gBootstrap->XRE_SetAndroidChildFds(jenv, crashFd, ipcFd);
|
2016-12-17 00:48:01 +03:00
|
|
|
gBootstrap->XRE_SetProcessType(argv[argc - 1]);
|
2016-10-06 02:46:53 +03:00
|
|
|
|
|
|
|
XREChildData childData;
|
2016-12-17 00:48:01 +03:00
|
|
|
gBootstrap->XRE_InitChildProcess(argc - 1, argv, &childData);
|
2016-10-06 02:46:53 +03:00
|
|
|
}
|
|
|
|
|
2016-12-17 00:48:01 +03:00
|
|
|
gBootstrap.reset();
|
2016-10-06 02:46:53 +03:00
|
|
|
FreeArgv(argv, argc);
|
|
|
|
}
|
|
|
|
|
2016-11-29 22:27:30 +03:00
|
|
|
extern "C" APKOPEN_EXPORT mozglueresult
|
2010-10-15 22:27:57 +04:00
|
|
|
ChildProcessInit(int argc, char* argv[])
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < (argc - 1); i++) {
|
2011-02-25 14:53:36 +03:00
|
|
|
if (strcmp(argv[i], "-greomni"))
|
2010-10-15 22:27:57 +04:00
|
|
|
continue;
|
|
|
|
|
|
|
|
i = i + 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-03-08 22:25:44 +04:00
|
|
|
if (loadNSSLibs(argv[i]) != SUCCESS) {
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
if (loadSQLiteLibs(argv[i]) != SUCCESS) {
|
|
|
|
return FAILURE;
|
|
|
|
}
|
|
|
|
if (loadGeckoLibs(argv[i]) != SUCCESS) {
|
|
|
|
return FAILURE;
|
|
|
|
}
|
2010-10-15 22:27:57 +04:00
|
|
|
|
2016-12-17 00:48:01 +03:00
|
|
|
gBootstrap->XRE_SetProcessType(argv[--argc]);
|
2010-10-15 22:27:57 +04:00
|
|
|
|
2016-05-15 18:35:22 +03:00
|
|
|
XREChildData childData;
|
2016-12-17 00:48:01 +03:00
|
|
|
return NS_FAILED(gBootstrap->XRE_InitChildProcess(argc, argv, &childData));
|
2010-10-15 22:27:57 +04:00
|
|
|
}
|
|
|
|
|
2017-03-01 22:26:12 +03:00
|
|
|
extern "C" APKOPEN_EXPORT jboolean MOZ_JNICALL
|
|
|
|
Java_org_mozilla_gecko_mozglue_GeckoLoader_neonCompatible(JNIEnv *jenv, jclass jc)
|
|
|
|
{
|
2017-03-13 18:25:12 +03:00
|
|
|
#ifdef __ARM_EABI__
|
2017-03-01 22:26:12 +03:00
|
|
|
return mozilla::supports_neon();
|
2017-03-13 18:25:12 +03:00
|
|
|
#else
|
|
|
|
return true;
|
|
|
|
#endif // __ARM_EABI__
|
2017-03-01 22:26:12 +03:00
|
|
|
}
|
2017-04-12 12:34:17 +03:00
|
|
|
|
|
|
|
// Does current process name end with ':media'?
|
|
|
|
static bool
|
|
|
|
IsMediaProcess()
|
|
|
|
{
|
|
|
|
pid_t pid = getpid();
|
|
|
|
char str[256];
|
|
|
|
snprintf(str, sizeof(str), "/proc/%d/cmdline", pid);
|
|
|
|
FILE* f = fopen(str, "r");
|
|
|
|
if (f) {
|
|
|
|
fgets(str, sizeof(str), f);
|
|
|
|
fclose(f);
|
|
|
|
const size_t strLen = strlen(str);
|
|
|
|
const char suffix[] = ":media";
|
|
|
|
const size_t suffixLen = sizeof(suffix) - 1;
|
|
|
|
if (strLen >= suffixLen &&
|
|
|
|
!strncmp(str + strLen - suffixLen, suffix, suffixLen)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" APKOPEN_EXPORT void MOZ_JNICALL
|
|
|
|
Java_org_mozilla_gecko_mozglue_GeckoLoader_suppressCrashDialog(JNIEnv *jenv, jclass jc)
|
|
|
|
{
|
|
|
|
MOZ_RELEASE_ASSERT(IsMediaProcess(), "Suppress crash dialog only for media process");
|
|
|
|
// Restore all signal actions changed by Android debugger.
|
|
|
|
// See http://androidxref.com/7.1.1_r6/xref/bionic/linker/debugger.cpp#312
|
|
|
|
struct sigaction dfl = {};
|
|
|
|
dfl.sa_handler = SIG_DFL;
|
|
|
|
sigaction(SIGABRT, &dfl, nullptr);
|
|
|
|
sigaction(SIGBUS, &dfl, nullptr);
|
|
|
|
sigaction(SIGILL, &dfl, nullptr);
|
|
|
|
sigaction(SIGFPE, &dfl, nullptr);
|
|
|
|
sigaction(SIGSEGV, &dfl, nullptr);
|
|
|
|
#if defined(SIGSTKFLT)
|
|
|
|
sigaction(SIGSTKFLT, &dfl, nullptr);
|
|
|
|
#endif
|
|
|
|
sigaction(SIGTRAP, &dfl, nullptr);
|
|
|
|
}
|