mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
200 lines
7.2 KiB
Java
200 lines
7.2 KiB
Java
/* 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/. */
|
|
|
|
package org.mozilla.gecko.tests.components;
|
|
|
|
import static org.mozilla.gecko.tests.helpers.AssertionHelper.*;
|
|
|
|
import org.mozilla.gecko.tests.helpers.*;
|
|
import org.mozilla.gecko.tests.UITestContext;
|
|
import org.mozilla.gecko.R;
|
|
|
|
import com.jayway.android.robotium.solo.Condition;
|
|
|
|
import android.content.Context;
|
|
import android.content.ContextWrapper;
|
|
import android.os.Handler;
|
|
import android.os.Looper;
|
|
import android.view.View;
|
|
import android.view.inputmethod.EditorInfo;
|
|
import android.view.inputmethod.InputConnection;
|
|
import android.view.inputmethod.InputMethodManager;
|
|
|
|
/**
|
|
* A class representing any interactions that take place on GeckoView.
|
|
*/
|
|
public class GeckoViewComponent extends BaseComponent {
|
|
|
|
public interface InputConnectionTest {
|
|
public void test(InputConnection ic, EditorInfo info);
|
|
}
|
|
|
|
public final TextInput mTextInput;
|
|
|
|
public GeckoViewComponent(final UITestContext testContext) {
|
|
super(testContext);
|
|
mTextInput = new TextInput();
|
|
}
|
|
|
|
/**
|
|
* Returns the GeckoView.
|
|
*/
|
|
private View getView() {
|
|
// Solo.getView asserts returning a valid View
|
|
return mSolo.getView(R.id.layer_view);
|
|
}
|
|
|
|
private void setContext(final Context newContext) {
|
|
final View geckoView = getView();
|
|
// Switch to a no-InputMethodManager context to avoid interference
|
|
mTestContext.getInstrumentation().runOnMainSync(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
FrameworkHelper.setViewContext(geckoView, newContext);
|
|
}
|
|
});
|
|
}
|
|
|
|
public class TextInput {
|
|
private TextInput() {
|
|
}
|
|
|
|
private InputMethodManager getInputMethodManager() {
|
|
final InputMethodManager imm = (InputMethodManager)
|
|
mActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
|
|
fAssertNotNull("Must have an InputMethodManager", imm);
|
|
return imm;
|
|
}
|
|
|
|
/**
|
|
* Returns whether text input is being directed to the GeckoView.
|
|
*/
|
|
private boolean isActive() {
|
|
return getInputMethodManager().isActive(getView());
|
|
}
|
|
|
|
public TextInput assertActive() {
|
|
fAssertTrue("Current view should be the active input view", isActive());
|
|
return this;
|
|
}
|
|
|
|
public TextInput waitForActive() {
|
|
WaitHelper.waitFor("current view to become the active input view", new Condition() {
|
|
@Override
|
|
public boolean isSatisfied() {
|
|
return isActive();
|
|
}
|
|
});
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Returns whether an InputConnection is avaiable.
|
|
* An InputConnection is available when text input is being directed to the
|
|
* GeckoView, and a text field (input, textarea, contentEditable, etc.) is
|
|
* currently focused inside the GeckoView.
|
|
*/
|
|
private boolean hasInputConnection() {
|
|
final InputMethodManager imm = getInputMethodManager();
|
|
return imm.isActive(getView()) && imm.isAcceptingText();
|
|
}
|
|
|
|
public TextInput assertInputConnection() {
|
|
fAssertTrue("Current view should have an active InputConnection", hasInputConnection());
|
|
return this;
|
|
}
|
|
|
|
public TextInput waitForInputConnection() {
|
|
WaitHelper.waitFor("current view to have an active InputConnection", new Condition() {
|
|
@Override
|
|
public boolean isSatisfied() {
|
|
return hasInputConnection();
|
|
}
|
|
});
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Starts an InputConnectionTest. An InputConnectionTest must run on the
|
|
* InputConnection thread which may or may not be the main UI thread. Also,
|
|
* during an InputConnectionTest, the system InputMethodManager service must
|
|
* be temporarily disabled to prevent the system IME from interfering with our
|
|
* tests. We disable the service by override the GeckoView's context with one
|
|
* that returns a null InputMethodManager service.
|
|
*
|
|
* @param test Test to run
|
|
*/
|
|
public TextInput testInputConnection(final InputConnectionTest test) {
|
|
|
|
fAssertNotNull("Test must not be null", test);
|
|
assertInputConnection();
|
|
|
|
// GeckoInputConnection can run on another thread than the main thread,
|
|
// so we need to be testing it on that same thread it's running on
|
|
final View geckoView = getView();
|
|
final Handler inputConnectionHandler = geckoView.getHandler();
|
|
final Context oldGeckoViewContext = FrameworkHelper.getViewContext(geckoView);
|
|
|
|
setContext(new ContextWrapper(oldGeckoViewContext) {
|
|
@Override
|
|
public Object getSystemService(String name) {
|
|
if (Context.INPUT_METHOD_SERVICE.equals(name)) {
|
|
return null;
|
|
}
|
|
return super.getSystemService(name);
|
|
}
|
|
});
|
|
|
|
(new InputConnectionTestRunner(test)).runOnHandler(inputConnectionHandler);
|
|
|
|
setContext(oldGeckoViewContext);
|
|
return this;
|
|
}
|
|
|
|
private class InputConnectionTestRunner implements Runnable {
|
|
private final InputConnectionTest mTest;
|
|
private boolean mDone;
|
|
|
|
public InputConnectionTestRunner(final InputConnectionTest test) {
|
|
mTest = test;
|
|
}
|
|
|
|
public synchronized void runOnHandler(final Handler inputConnectionHandler) {
|
|
// Below, we are blocking the instrumentation thread to wait on the
|
|
// InputConnection thread. Therefore, the InputConnection thread must not be
|
|
// the same as the instrumentation thread to avoid a deadlock. This should
|
|
// always be the case and we perform a sanity check to make sure.
|
|
fAssertNotSame("InputConnection should not be running on instrumentation thread",
|
|
Looper.myLooper(), inputConnectionHandler.getLooper());
|
|
|
|
mDone = false;
|
|
inputConnectionHandler.post(this);
|
|
do {
|
|
try {
|
|
wait();
|
|
} catch (InterruptedException e) {
|
|
// Ignore interrupts
|
|
}
|
|
} while (!mDone);
|
|
}
|
|
|
|
@Override
|
|
public void run() {
|
|
final EditorInfo info = new EditorInfo();
|
|
final InputConnection ic = getView().onCreateInputConnection(info);
|
|
fAssertNotNull("Must have an InputConnection", ic);
|
|
// Restore the IC to a clean state
|
|
ic.clearMetaKeyStates(-1);
|
|
ic.finishComposingText();
|
|
mTest.test(ic, info);
|
|
synchronized (this) {
|
|
// Test finished; return from runOnHandler
|
|
mDone = true;
|
|
notify();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|