Commit 347a2a14 authored by Shimi Zhang's avatar Shimi Zhang Committed by Commit Bot

[IME] Remove a reflection in |ThreadedInputConnectionFactory|

Previously we have a reflection check for not delaying
onCreateInputConnection() for |ThreadedInputConnectionProxyView| and
|TestInputMethodeManagerWrapper|.

we replaced this reflection by setting a flag from caller directly
and calls onCreateInputConnection(), and then reset the flag after.

Bug: 636474
Change-Id: I7563f38d333a32ea9ccddec69446d1758275300f
Reviewed-on: https://chromium-review.googlesource.com/1038793
Commit-Queue: Shimi Zhang <ctzsm@chromium.org>
Reviewed-by: default avatarBo <boliu@chromium.org>
Reviewed-by: default avatarChangwan Ryu <changwan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#555597}
parent 8bfa76f8
......@@ -31,6 +31,7 @@ public interface ChromiumBaseInputConnection extends InputConnection {
void onViewFocusChanged(boolean gainFocus);
void onViewAttachedToWindow();
void onViewDetachedFromWindow();
void setTriggerDelayedOnCreateInputConnection(boolean trigger);
}
/**
......
......@@ -375,6 +375,11 @@ public class ImeAdapterImpl implements ImeAdapter, WindowEventObserver {
return mInputConnectionFactory;
}
@VisibleForTesting
public void setTriggerDelayedOnCreateInputConnectionForTest(boolean trigger) {
mInputConnectionFactory.setTriggerDelayedOnCreateInputConnection(trigger);
}
/**
* Get the current input connection for testing purposes.
*/
......
......@@ -38,6 +38,7 @@ public class ThreadedInputConnectionFactory implements ChromiumBaseInputConnecti
private ThreadedInputConnection mThreadedInputConnection;
private CheckInvalidator mCheckInvalidator;
private boolean mReentrantTriggering;
private boolean mTriggerDelayedOnCreateInputConnection;
// Initialization-on-demand holder for Handler.
private static class LazyHandlerHolder {
......@@ -70,6 +71,7 @@ public class ThreadedInputConnectionFactory implements ChromiumBaseInputConnecti
ThreadedInputConnectionFactory(InputMethodManagerWrapper inputMethodManagerWrapper) {
mInputMethodManagerWrapper = inputMethodManagerWrapper;
mInputMethodUma = createInputMethodUma();
mTriggerDelayedOnCreateInputConnection = true;
}
@Override
......@@ -81,7 +83,7 @@ public class ThreadedInputConnectionFactory implements ChromiumBaseInputConnecti
protected ThreadedInputConnectionProxyView createProxyView(
Handler handler, View containerView) {
return new ThreadedInputConnectionProxyView(
containerView.getContext(), handler, containerView);
containerView.getContext(), handler, containerView, this);
}
@VisibleForTesting
......@@ -89,23 +91,20 @@ public class ThreadedInputConnectionFactory implements ChromiumBaseInputConnecti
return new InputMethodUma();
}
@VisibleForTesting
@Override
public void setTriggerDelayedOnCreateInputConnection(boolean trigger) {
mTriggerDelayedOnCreateInputConnection = trigger;
}
// Note that ThreadedInputConnectionProxyView intentionally calls
// View#onCreateInputConnection() and not a separate method in this class.
// There are third party apps that override WebView#onCreateInputConnection(),
// and we still want to call them for consistency.
// We let ThreadedInputConnectionProxyView and TestInputMethodManagerWrapper call
// setTriggerDelayedOnCreateInputConnection(false) explicitly to avoid delayed triggering.
private boolean shouldTriggerDelayedOnCreateInputConnection() {
// Note that ThreadedInputConnectionProxyView intentionally calls
// View#onCreateInputConnection() and not a separate method in this class.
// There are third party apps that override WebView#onCreateInputConnection(),
// and we still want to call them for consistency. The setback here is that the only
// way to distinguish calls from InputMethodManager and from ProxyView is by looking at
// the call stack.
// TODO - avoid using reflection here. See crbug.com/636474
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
String className = ste.getClassName();
if (className != null
&& (className.contains(ThreadedInputConnectionProxyView.class.getName())
|| className.contains("TestInputMethodManagerWrapper"))) {
return false;
}
}
return true;
return mTriggerDelayedOnCreateInputConnection;
}
@Override
......
......@@ -13,16 +13,13 @@ import android.view.inputmethod.InputConnection;
import org.chromium.base.Log;
import org.chromium.base.ThreadUtils;
import org.chromium.base.annotations.UsedByReflection;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
/**
* This is a fake View that is only exposed to InputMethodManager.
*/
@UsedByReflection("ThreadedInputConnectionFactory.java")
public class ThreadedInputConnectionProxyView extends View {
private static final String TAG = "cr_Ime";
private static final boolean DEBUG_LOGS = false;
......@@ -33,9 +30,10 @@ public class ThreadedInputConnectionProxyView extends View {
private final AtomicBoolean mWindowFocused = new AtomicBoolean();
private final AtomicReference<IBinder> mWindowToken = new AtomicReference<>();
private final AtomicReference<View> mRootView = new AtomicReference<>();
private final ThreadedInputConnectionFactory mFactory;
ThreadedInputConnectionProxyView(
Context context, Handler imeThreadHandler, View containerView) {
ThreadedInputConnectionProxyView(Context context, Handler imeThreadHandler, View containerView,
ThreadedInputConnectionFactory factory) {
super(context);
mImeThreadHandler = imeThreadHandler;
mContainerView = containerView;
......@@ -48,6 +46,7 @@ public class ThreadedInputConnectionProxyView extends View {
mWindowFocused.set(mContainerView.hasWindowFocus());
mWindowToken.set(mContainerView.getWindowToken());
mRootView.set(mContainerView.getRootView());
mFactory = factory;
}
public void onOriginalViewFocusChanged(boolean gainFocus) {
......@@ -90,11 +89,11 @@ public class ThreadedInputConnectionProxyView extends View {
@Override
public InputConnection onCreateInputConnection(final EditorInfo outAttrs) {
if (DEBUG_LOGS) Log.w(TAG, "onCreateInputConnection");
return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<InputConnection>() {
@Override
public InputConnection call() throws Exception {
return mContainerView.onCreateInputConnection(outAttrs);
}
return ThreadUtils.runOnUiThreadBlockingNoException(() -> {
mFactory.setTriggerDelayedOnCreateInputConnection(false);
InputConnection connection = mContainerView.onCreateInputConnection(outAttrs);
mFactory.setTriggerDelayedOnCreateInputConnection(true);
return connection;
});
}
......
......@@ -676,5 +676,10 @@ class ImeActivityTestRule extends ContentShellActivityTestRule {
public void onViewDetachedFromWindow() {
mFactory.onViewDetachedFromWindow();
}
@Override
public void setTriggerDelayedOnCreateInputConnection(boolean trigger) {
mFactory.setTriggerDelayedOnCreateInputConnection(trigger);
}
}
}
......@@ -150,12 +150,13 @@ public class ThreadedInputConnectionFactoryTest {
mContainerView, mImeAdapter, 1, 0, 0, 0, 0, mEditorInfo);
}
};
when(mProxyView.onCreateInputConnection(any(EditorInfo.class))).thenAnswer(
new Answer<InputConnection>() {
@Override
public InputConnection answer(InvocationOnMock invocation) throws Throwable {
return ThreadUtils.runOnUiThreadBlockingNoException(callable);
}
when(mProxyView.onCreateInputConnection(any(EditorInfo.class)))
.thenAnswer((InvocationOnMock invocation) -> {
mFactory.setTriggerDelayedOnCreateInputConnection(false);
InputConnection connection =
ThreadUtils.runOnUiThreadBlockingNoException(callable);
mFactory.setTriggerDelayedOnCreateInputConnection(true);
return connection;
});
when(mInputMethodManager.isActive(mContainerView)).thenAnswer(new Answer<Boolean>() {
......
......@@ -13,7 +13,7 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import org.chromium.base.Log;
import org.chromium.base.annotations.UsedByReflection;
import org.chromium.content.browser.input.ImeAdapterImpl;
import org.chromium.content.browser.input.Range;
import org.chromium.content_public.browser.ImeAdapter;
import org.chromium.content_public.browser.InputMethodManagerWrapper;
......@@ -24,7 +24,6 @@ import java.util.List;
/**
* Overrides InputMethodManagerWrapper for testing purposes.
*/
@UsedByReflection("ThreadedInputConnectionFactory.java")
public class TestInputMethodManagerWrapper implements InputMethodManagerWrapper {
private static final String TAG = "cr_Ime";
......@@ -59,11 +58,12 @@ public class TestInputMethodManagerWrapper implements InputMethodManagerWrapper
*/
public static InputConnectionProvider defaultInputConnectionProvider(
final ImeAdapter imeAdapter) {
return new InputConnectionProvider() {
@Override
public InputConnection create(EditorInfo info) {
return imeAdapter.onCreateInputConnection(info);
}
return (EditorInfo info) -> {
ImeAdapterImpl imeAdapterImpl = (ImeAdapterImpl) imeAdapter;
imeAdapterImpl.setTriggerDelayedOnCreateInputConnectionForTest(false);
InputConnection connection = imeAdapter.onCreateInputConnection(info);
imeAdapterImpl.setTriggerDelayedOnCreateInputConnectionForTest(true);
return connection;
};
}
......
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