1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.view.inputmethod.cts.util; 18 19 import static org.junit.Assert.assertNotNull; 20 21 import android.content.Context; 22 import android.support.test.uiautomator.By; 23 import android.support.test.uiautomator.BySelector; 24 import android.support.test.uiautomator.UiDevice; 25 import android.support.test.uiautomator.UiObject2; 26 import android.view.inputmethod.EditorInfo; 27 import android.view.inputmethod.InputConnection; 28 import android.webkit.WebView; 29 import android.webkit.WebViewClient; 30 import android.widget.EditText; 31 import android.widget.LinearLayout; 32 33 import androidx.test.platform.app.InstrumentationRegistry; 34 35 import com.android.compatibility.common.util.Timeout; 36 37 import java.util.concurrent.CountDownLatch; 38 import java.util.concurrent.TimeUnit; 39 import java.util.concurrent.atomic.AtomicReference; 40 41 /** 42 * A custom {@link WebView} class which provides a simple web page for verifying IME behavior. 43 */ 44 public class TestWebView { 45 46 private static final class Impl extends WebView { 47 private static final String MY_HTML = 48 "<html><body>Editor: <input type='text' name='testInput'></body></html>"; 49 private UiDevice mUiDevice; 50 private final String mMaker; 51 Impl(Context context, UiDevice uiDevice, String maker)52 Impl(Context context, UiDevice uiDevice, String maker) { 53 super(context); 54 mUiDevice = uiDevice; 55 mMaker = maker; 56 } 57 58 @Override onCreateInputConnection(EditorInfo outAttrs)59 public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 60 final InputConnection original = super.onCreateInputConnection(outAttrs); 61 final int inputType = outAttrs.inputType; 62 if ((inputType & EditorInfo.TYPE_MASK_CLASS) == EditorInfo.TYPE_CLASS_TEXT 63 && (inputType & EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) != 0) { 64 outAttrs.privateImeOptions = mMaker; 65 } 66 return original; 67 } 68 loadEditorPage()69 private void loadEditorPage() { 70 super.loadData(MY_HTML, "text/html", "UTF-8"); 71 } 72 getInput(Timeout timeout)73 private UiObject2 getInput(Timeout timeout) { 74 final BySelector selector = By.text("Editor: "); 75 UiObject2 label = null; 76 try { 77 label = timeout.run("waitForObject(" + selector + ")", 78 () -> mUiDevice.findObject(selector)); 79 } catch (Exception e) { 80 } 81 assertNotNull("Editor label must exists on WebView", label); 82 83 // Then the input is next. 84 final UiObject2 parent = label.getParent(); 85 UiObject2 previous = null; 86 for (UiObject2 child : parent.getChildren()) { 87 if (label.equals(previous)) { 88 if (child.getClassName().equals(EditText.class.getName())) { 89 return child; 90 } 91 } 92 previous = child; 93 } 94 return null; 95 } 96 } 97 98 /** 99 * Not intended to be instantiated. 100 */ TestWebView()101 private TestWebView() { 102 } 103 launchTestWebViewActivity(long timeoutMs, String maker)104 public static UiObject2 launchTestWebViewActivity(long timeoutMs, String maker) 105 throws Exception { 106 final AtomicReference<UiObject2> inputTextFieldRef = new AtomicReference<>(); 107 final AtomicReference<TestWebView.Impl> webViewRef = new AtomicReference<>(); 108 final CountDownLatch latch = new CountDownLatch(1); 109 final Timeout timeoutForFindObj = new Timeout("UIOBJECT_FIND_TIMEOUT", 110 timeoutMs, 2F, timeoutMs); 111 112 TestActivity.startSync(activity -> { 113 final LinearLayout layout = new LinearLayout(activity); 114 final TestWebView.Impl webView = new Impl(activity, UiDevice.getInstance( 115 InstrumentationRegistry.getInstrumentation()), maker); 116 webView.setWebViewClient(new WebViewClient() { 117 @Override 118 public void onPageFinished(WebView view, String url) { 119 latch.countDown(); 120 } 121 }); 122 webViewRef.set(webView); 123 layout.setOrientation(LinearLayout.VERTICAL); 124 layout.addView(webView); 125 webView.loadEditorPage(); 126 return layout; 127 }); 128 129 latch.await(timeoutMs, TimeUnit.MILLISECONDS); 130 inputTextFieldRef.set(webViewRef.get().getInput(timeoutForFindObj)); 131 return inputTextFieldRef.get(); 132 } 133 } 134