зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1566583
- Bridge GeckoResult to MozPromise and return a GeckoResult from GeckoProcessManager::start. r=snorp
Differential Revision: https://phabricator.services.mozilla.com/D38436 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
59bcd549ee
Коммит
5d23efb2eb
|
@ -265,10 +265,9 @@ class AndroidProcessLauncher : public PosixProcessLauncher {
|
|||
|
||||
protected:
|
||||
virtual RefPtr<ProcessHandlePromise> DoLaunch() override;
|
||||
void LaunchAndroidService(
|
||||
RefPtr<ProcessHandlePromise> LaunchAndroidService(
|
||||
const char* type, const std::vector<std::string>& argv,
|
||||
const base::file_handle_mapping_vector& fds_to_remap,
|
||||
base::ProcessHandle* process_handle);
|
||||
const base::file_handle_mapping_vector& fds_to_remap);
|
||||
};
|
||||
typedef AndroidProcessLauncher ProcessLauncher;
|
||||
// NB: Technically Android is linux (i.e. XP_LINUX is defined), but we want
|
||||
|
@ -1136,12 +1135,8 @@ bool PosixProcessLauncher::DoSetup() {
|
|||
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
RefPtr<ProcessHandlePromise> AndroidProcessLauncher::DoLaunch() {
|
||||
ProcessHandle handle = 0;
|
||||
LaunchAndroidService(ChildProcessType(), mChildArgv,
|
||||
mLaunchOptions->fds_to_remap, &handle);
|
||||
return handle != 0
|
||||
? ProcessHandlePromise::CreateAndResolve(handle, __func__)
|
||||
: ProcessHandlePromise::CreateAndReject(LaunchError{}, __func__);
|
||||
return LaunchAndroidService(ChildProcessType(), mChildArgv,
|
||||
mLaunchOptions->fds_to_remap);
|
||||
}
|
||||
#endif // MOZ_WIDGET_ANDROID
|
||||
|
||||
|
@ -1553,10 +1548,9 @@ void GeckoChildProcessHost::GetQueuedMessages(std::queue<IPC::Message>& queue) {
|
|||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
void AndroidProcessLauncher::LaunchAndroidService(
|
||||
RefPtr<ProcessHandlePromise> AndroidProcessLauncher::LaunchAndroidService(
|
||||
const char* type, const std::vector<std::string>& argv,
|
||||
const base::file_handle_mapping_vector& fds_to_remap,
|
||||
base::ProcessHandle* process_handle) {
|
||||
const base::file_handle_mapping_vector& fds_to_remap) {
|
||||
MOZ_RELEASE_ASSERT((2 <= fds_to_remap.size()) && (fds_to_remap.size() <= 5));
|
||||
JNIEnv* const env = mozilla::jni::GetEnvForThread();
|
||||
MOZ_ASSERT(env);
|
||||
|
@ -1586,12 +1580,10 @@ void AndroidProcessLauncher::LaunchAndroidService(
|
|||
crashAnnotationFd = fds_to_remap[4].first;
|
||||
}
|
||||
|
||||
int32_t handle = java::GeckoProcessManager::Start(
|
||||
auto genericResult = java::GeckoProcessManager::Start(
|
||||
type, jargs, prefsFd, prefMapFd, ipcFd, crashFd, crashAnnotationFd);
|
||||
|
||||
if (process_handle) {
|
||||
*process_handle = handle;
|
||||
}
|
||||
auto typedResult = java::GeckoResult::LocalRef(std::move(genericResult));
|
||||
return ProcessHandlePromise::FromGeckoResult(typedResult);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@ import org.mozilla.gecko.IGeckoEditableParent;
|
|||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import org.mozilla.geckoview.GeckoResult;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
@ -207,11 +209,18 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
|
|||
}
|
||||
|
||||
@WrapForJNI
|
||||
private static int start(final String type, final String[] args,
|
||||
private static GeckoResult<Integer> start(final String type, final String[] args,
|
||||
final int prefsFd, final int prefMapFd,
|
||||
final int ipcFd,
|
||||
final int crashFd, final int crashAnnotationFd) {
|
||||
return INSTANCE.start(type, args, prefsFd, prefMapFd, ipcFd, crashFd, crashAnnotationFd, /* retry */ false);
|
||||
int pid = INSTANCE.start(type, args, prefsFd, prefMapFd, ipcFd, crashFd, crashAnnotationFd, /* retry */ false);
|
||||
GeckoResult<Integer> result = new GeckoResult<>();
|
||||
if (pid == 0) {
|
||||
result.completeExceptionally(new RuntimeException("Failed to start process"));
|
||||
} else {
|
||||
result.complete(pid);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int filterFlagsForChild(final int flags) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.mozilla.geckoview;
|
||||
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.mozglue.JNIObject;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import android.os.Handler;
|
||||
|
@ -463,6 +464,25 @@ public class GeckoResult<T> {
|
|||
}
|
||||
}
|
||||
|
||||
@WrapForJNI
|
||||
private void nativeThen(@NonNull final GeckoCallback accept, @NonNull final GeckoCallback reject) {
|
||||
// NB: We could use the lambda syntax here, but given all the layers
|
||||
// of abstraction it's helpful to see the types written explicitly.
|
||||
thenInternal(DirectDispatcher.sInstance, new OnValueListener<T, Void>() {
|
||||
@Override
|
||||
public GeckoResult<Void> onValue(final T value) {
|
||||
accept.call(value);
|
||||
return null;
|
||||
}
|
||||
}, new OnExceptionListener<Void>() {
|
||||
@Override
|
||||
public GeckoResult<Void> onException(final Throwable exception) {
|
||||
reject.call(exception);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Get the {@link Looper} that will be used to schedule listeners registered via
|
||||
* {@link #then(OnValueListener, OnExceptionListener)}.
|
||||
|
@ -683,6 +703,15 @@ public class GeckoResult<T> {
|
|||
@Nullable GeckoResult<V> onException(@NonNull Throwable exception) throws Throwable;
|
||||
}
|
||||
|
||||
@WrapForJNI
|
||||
private static class GeckoCallback extends JNIObject {
|
||||
private native void call(Object arg);
|
||||
|
||||
@Override
|
||||
protected native void disposeNative();
|
||||
}
|
||||
|
||||
|
||||
private boolean haveValue() {
|
||||
return mComplete && mError == null;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include "Conversions.h"
|
||||
#include "JavaBuiltins.h"
|
||||
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace jni {
|
||||
|
||||
|
@ -87,5 +89,10 @@ double Java2Native(mozilla::jni::Object::Param aData, JNIEnv* aEnv) {
|
|||
return result;
|
||||
}
|
||||
|
||||
template <>
|
||||
ipc::LaunchError Java2Native(mozilla::jni::Object::Param aData, JNIEnv* aEnv) {
|
||||
return ipc::LaunchError{};
|
||||
}
|
||||
|
||||
} // namespace jni
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_jni_GeckoResultUtils_h
|
||||
#define mozilla_jni_GeckoResultUtils_h
|
||||
|
||||
#include "mozilla/jni/Conversions.h"
|
||||
#include "GeneratedJNIWrappers.h"
|
||||
#include "GeneratedJNINatives.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace jni {
|
||||
|
||||
// C++-side object bound to Java's GeckoResult.GeckoCallback.
|
||||
//
|
||||
// Note that we can't template this class because that breaks JNI dispatch
|
||||
// (surprisingly: it compiles, but selects the wrong method specialization
|
||||
// during dispatch). So instead we use a templated factory function, which
|
||||
// bundles the per-ArgType conversion logic into the callback.
|
||||
class GeckoResultCallback final
|
||||
: public java::GeckoResult::GeckoCallback::Natives<GeckoResultCallback> {
|
||||
public:
|
||||
typedef java::GeckoResult::GeckoCallback::Natives<GeckoResultCallback> Base;
|
||||
typedef std::function<void(mozilla::jni::Object::Param)> OuterCallback;
|
||||
|
||||
void Call(mozilla::jni::Object::Param aArg) { mCallback(aArg); }
|
||||
|
||||
template <typename ArgType>
|
||||
static java::GeckoResult::GeckoCallback::LocalRef CreateAndAttach(
|
||||
std::function<void(ArgType)>&& aInnerCallback) {
|
||||
auto java = java::GeckoResult::GeckoCallback::New();
|
||||
OuterCallback outerCallback =
|
||||
[inner{std::move(aInnerCallback)}](mozilla::jni::Object::Param aParam) {
|
||||
ArgType converted = Java2Native<ArgType>(aParam);
|
||||
inner(converted);
|
||||
};
|
||||
auto native = MakeUnique<GeckoResultCallback>(std::move(outerCallback));
|
||||
Base::AttachNative(java, std::move(native));
|
||||
return java;
|
||||
}
|
||||
|
||||
explicit GeckoResultCallback(OuterCallback&& aCallback)
|
||||
: mCallback(std::move(aCallback)) {}
|
||||
|
||||
private:
|
||||
OuterCallback mCallback;
|
||||
};
|
||||
|
||||
} // namespace jni
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_jni_GeckoResultUtils_h
|
|
@ -11,6 +11,7 @@ EXPORTS.mozilla.jni += [
|
|||
'Accessors.h',
|
||||
'Conversions.h',
|
||||
'GeckoBundleUtils.h',
|
||||
'GeckoResultUtils.h',
|
||||
'Natives.h',
|
||||
'Refs.h',
|
||||
'Types.h',
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
# include "nsTArray.h"
|
||||
# include "nsThreadUtils.h"
|
||||
|
||||
# ifdef MOZ_WIDGET_ANDROID
|
||||
# include "mozilla/jni/GeckoResultUtils.h"
|
||||
# endif
|
||||
|
||||
# if MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
# define PROMISE_DEBUG
|
||||
# endif
|
||||
|
@ -934,6 +938,21 @@ class MozPromise : public MozPromiseBase {
|
|||
}
|
||||
}
|
||||
|
||||
# ifdef MOZ_WIDGET_ANDROID
|
||||
// Creates a C++ MozPromise from its Java counterpart, GeckoResult.
|
||||
static RefPtr<MozPromise> FromGeckoResult(
|
||||
java::GeckoResult::Param aGeckoResult) {
|
||||
using jni::GeckoResultCallback;
|
||||
RefPtr<Private> p = new Private("GeckoResult Glue", false);
|
||||
auto resolve = GeckoResultCallback::CreateAndAttach<ResolveValueType>(
|
||||
[p](ResolveValueType aArg) { p->Resolve(aArg, __func__); });
|
||||
auto reject = GeckoResultCallback::CreateAndAttach<RejectValueType>(
|
||||
[p](RejectValueType aArg) { p->Reject(aArg, __func__); });
|
||||
aGeckoResult->NativeThen(resolve, reject);
|
||||
return p;
|
||||
}
|
||||
# endif
|
||||
|
||||
// Note we expose the function AssertIsDead() instead of IsDead() since
|
||||
// checking IsDead() is a data race in the situation where the request is not
|
||||
// dead. Therefore we enforce the form |Assert(IsDead())| by exposing
|
||||
|
|
Загрузка…
Ссылка в новой задаче