Merge "Add back auto-completion and auto-fill."

This commit is contained in:
George Mount
2012-03-12 07:10:28 -07:00
committed by Android (Google) Code Review
3 changed files with 472 additions and 16 deletions

View File

@@ -0,0 +1,264 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.webkit;
import android.content.Context;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.AbsoluteLayout;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ListAdapter;
import android.widget.ListPopupWindow;
class AutoCompletePopup implements OnItemClickListener, Filter.FilterListener {
private static class AnchorView extends View {
AnchorView(Context context) {
super(context);
setFocusable(false);
}
}
private static final int AUTOFILL_FORM = 100;
private boolean mIsAutoFillProfileSet;
private Handler mHandler;
private int mQueryId;
private Rect mNodeBounds = new Rect();
private int mNodeLayerId;
private ListPopupWindow mPopup;
private Filter mFilter;
private CharSequence mText;
private ListAdapter mAdapter;
private boolean mIsFocused;
private View mAnchor;
private WebViewClassic.WebViewInputConnection mInputConnection;
private WebViewClassic mWebView;
public AutoCompletePopup(Context context,
WebViewClassic webView,
WebViewClassic.WebViewInputConnection inputConnection) {
mInputConnection = inputConnection;
mWebView = webView;
mPopup = new ListPopupWindow(context);
mAnchor = new AnchorView(context);
mWebView.getWebView().addView(mAnchor);
mPopup.setOnItemClickListener(this);
mPopup.setAnchorView(mAnchor);
mPopup.setPromptPosition(ListPopupWindow.POSITION_PROMPT_BELOW);
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case AUTOFILL_FORM:
mWebView.autoFillForm(mQueryId);
break;
}
}
};
}
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && mPopup.isShowing()) {
// special case for the back key, we do not even try to send it
// to the drop down list but instead, consume it immediately
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
KeyEvent.DispatcherState state = mAnchor.getKeyDispatcherState();
if (state != null) {
state.startTracking(event, this);
}
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
KeyEvent.DispatcherState state = mAnchor.getKeyDispatcherState();
if (state != null) {
state.handleUpEvent(event);
}
if (event.isTracking() && !event.isCanceled()) {
Log.v("AutoCompletePopup", "dismiss popup 2");
mPopup.dismiss();
return true;
}
}
}
if (mPopup.isShowing()) {
return mPopup.onKeyPreIme(keyCode, event);
}
return false;
}
public void setFocused(boolean isFocused) {
mIsFocused = isFocused;
if (!mIsFocused) {
Log.v("AutoCompletePopup", "dismiss popup 3");
mPopup.dismiss();
}
}
public void setText(CharSequence text) {
mText = text;
if (mFilter != null) {
mFilter.filter(text, this);
}
}
public void setAutoFillQueryId(int queryId) {
mQueryId = queryId;
}
public void clearAdapter() {
mAdapter = null;
mFilter = null;
Log.v("AutoCompletePopup", "dismiss popup 4");
mPopup.dismiss();
mPopup.setAdapter(null);
}
public <T extends ListAdapter & Filterable> void setAdapter(T adapter) {
mPopup.setAdapter(adapter);
mAdapter = adapter;
if (adapter != null) {
mFilter = adapter.getFilter();
mFilter.filter(mText, this);
} else {
mFilter = null;
}
resetRect();
}
public void setNodeBounds(Rect nodeBounds, int layerId) {
mNodeBounds.set(nodeBounds);
mNodeLayerId = layerId;
resetRect();
}
public void resetRect() {
Log.v("AutoCompletePopup", "resetRect: " + mNodeBounds);
int left = mWebView.contentToViewX(mNodeBounds.left);
int right = mWebView.contentToViewX(mNodeBounds.right);
int width = right - left;
mPopup.setWidth(width);
int bottom = mWebView.contentToViewY(mNodeBounds.bottom);
int top = mWebView.contentToViewY(mNodeBounds.top);
int height = bottom - top;
AbsoluteLayout.LayoutParams lp =
(AbsoluteLayout.LayoutParams) mAnchor.getLayoutParams();
boolean needsUpdate = false;
if (null == lp) {
lp = new AbsoluteLayout.LayoutParams(width, height, left, top);
} else {
if ((lp.x != left) || (lp.y != top) || (lp.width != width)
|| (lp.height != height)) {
needsUpdate = true;
lp.x = left;
lp.y = top;
lp.width = width;
lp.height = height;
}
}
Log.v("AutoCompletePopup", "resetRect layout " + lp.x + ", " + lp.y +
", " + lp.width + ", " + lp.height);
if (needsUpdate) {
mAnchor.setLayoutParams(lp);
}
if (mPopup.isShowing()) {
Log.v("AutoCompletePopup", "showing popup again");
mPopup.show(); // update its position
}
}
public void scrollDelta(int layerId, int dx, int dy) {
if (layerId == mNodeLayerId) {
mNodeBounds.offset(dx, dy);
resetRect();
}
}
// AdapterView.OnItemClickListener implementation
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (id == 0 && position == 0 && mInputConnection.getIsAutoFillable()) {
mText = "";
pushTextToInputConnection();
// Blank out the text box while we wait for WebCore to fill the form.
if (mIsAutoFillProfileSet) {
// Call a webview method to tell WebCore to autofill the form.
mWebView.autoFillForm(mQueryId);
} else {
// There is no autofill profile setup yet and the user has
// elected to try and set one up. Call through to the
// embedder to action that.
mWebView.getWebChromeClient().setupAutoFill(
mHandler.obtainMessage(AUTOFILL_FORM));
}
} else {
Object selectedItem;
if (position < 0) {
selectedItem = mPopup.getSelectedItem();
} else {
selectedItem = mAdapter.getItem(position);
}
if (selectedItem != null) {
setText(mFilter.convertResultToString(selectedItem));
pushTextToInputConnection();
}
}
Log.v("AutoCompletePopup", "dismiss popup 5");
mPopup.dismiss();
}
public void setIsAutoFillProfileSet(boolean isAutoFillProfileSet) {
mIsAutoFillProfileSet = isAutoFillProfileSet;
}
private void pushTextToInputConnection() {
Editable oldText = mInputConnection.getEditable();
mInputConnection.setSelection(0, oldText.length());
mInputConnection.replaceSelection(mText);
mInputConnection.setSelection(mText.length(), mText.length());
}
@Override
public void onFilterComplete(int count) {
if (!mIsFocused) {
Log.v("AutoCompletePopup", "dismiss popup 1");
mPopup.dismiss();
return;
}
boolean showDropDown = (count > 0) &&
(mInputConnection.getIsAutoFillable() || mText.length() > 0);
if (showDropDown) {
if (!mPopup.isShowing()) {
// Make sure the list does not obscure the IME when shown for the first time.
mPopup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NEEDED);
}
Log.v("AutoCompletePopup", "showing popup");
mPopup.show();
mPopup.getListView().setOverScrollMode(View.OVER_SCROLL_ALWAYS);
} else {
Log.v("AutoCompletePopup", "dismiss popup");
mPopup.dismiss();
}
}
}

View File

@@ -375,7 +375,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
* InputConnection used for ContentEditable. This captures changes
* to the text and sends them either as key strokes or text changes.
*/
private class WebViewInputConnection extends BaseInputConnection {
class WebViewInputConnection extends BaseInputConnection {
// Used for mapping characters to keys typed.
private KeyCharacterMap mKeyCharacterMap;
private boolean mIsKeySentByMe;
@@ -383,11 +383,31 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
private int mImeOptions;
private String mHint;
private int mMaxLength;
private boolean mIsAutoFillable;
private boolean mIsAutoCompleteEnabled;
private String mName;
public WebViewInputConnection() {
super(mWebView, true);
}
public void setAutoFillable(int queryId) {
mIsAutoFillable = getSettings().getAutoFillEnabled()
&& (queryId != WebTextView.FORM_NOT_AUTOFILLABLE);
int variation = mInputType & EditorInfo.TYPE_MASK_VARIATION;
if (variation != EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD
&& (mIsAutoFillable || mIsAutoCompleteEnabled)) {
if (mName != null && mName.length() > 0) {
requestFormData(mName, mFieldPointer, mIsAutoFillable,
mIsAutoCompleteEnabled);
}
}
}
public boolean getIsAutoFillable() {
return mIsAutoFillable;
}
@Override
public boolean sendKeyEvent(KeyEvent event) {
// Some IMEs send key events directly using sendKeyEvents.
@@ -582,6 +602,9 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
mInputType = inputType;
mImeOptions = imeOptions;
mMaxLength = initData.mMaxLength;
mIsAutoCompleteEnabled = initData.mIsAutoCompleteEnabled;
mName = initData.mName;
mAutoCompletePopup.clearAdapter();
}
public void setupEditorInfo(EditorInfo outAttrs) {
@@ -629,6 +652,13 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
REPLACE_TEXT, start, end, text.toString());
mPrivateHandler.sendMessage(replaceMessage);
}
if (mAutoCompletePopup != null) {
StringBuilder newText = new StringBuilder();
newText.append(editable.subSequence(0, start));
newText.append(text);
newText.append(editable.subSequence(end, editable.length()));
mAutoCompletePopup.setText(newText.toString());
}
mIsKeySentByMe = false;
}
@@ -795,6 +825,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
WebViewInputConnection mInputConnection = null;
private int mFieldPointer;
private PastePopupWindow mPasteWindow;
AutoCompletePopup mAutoCompletePopup;
private static class OnTrimMemoryListener implements ComponentCallbacks2 {
private static OnTrimMemoryListener sInstance = null;
@@ -1104,6 +1135,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
private static final int SWITCH_TO_SHORTPRESS = 3;
private static final int SWITCH_TO_LONGPRESS = 4;
private static final int RELEASE_SINGLE_TAP = 5;
private static final int REQUEST_FORM_DATA = 6;
private static final int DRAG_HELD_MOTIONLESS = 8;
private static final int AWAKEN_SCROLL_BARS = 9;
private static final int PREVENT_DEFAULT_TIMEOUT = 10;
@@ -1156,6 +1188,9 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
static final int REPLACE_TEXT = 143;
static final int CLEAR_CARET_HANDLE = 144;
static final int KEY_PRESS = 145;
static final int RELOCATE_AUTO_COMPLETE_POPUP = 146;
static final int FOCUS_NODE_CHANGED = 147;
static final int AUTOFILL_FORM = 148;
private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID;
private static final int LAST_PACKAGE_MSG_ID = HIT_TEST_RESULT;
@@ -3560,7 +3595,9 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
@Override
public void clearFormData() {
checkThread();
// TODO: Implement b/6083041
if (mAutoCompletePopup != null) {
mAutoCompletePopup.clearAdapter();
}
}
/**
@@ -3861,12 +3898,12 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
private void scrollLayerTo(int x, int y) {
if (x == mScrollingLayerRect.left && y == mScrollingLayerRect.top) {
int dx = mScrollingLayerRect.left - x;
int dy = mScrollingLayerRect.top - y;
if (dx == 0 && y == 0) {
return;
}
if (mSelectingText) {
int dx = mScrollingLayerRect.left - x;
int dy = mScrollingLayerRect.top - y;
if (mSelectCursorBaseLayerId == mCurrentScrollingLayerId) {
mSelectCursorBase.offset(dx, dy);
}
@@ -3874,6 +3911,9 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
mSelectCursorExtent.offset(dx, dy);
}
}
if (mAutoCompletePopup != null) {
mAutoCompletePopup.scrollDelta(mCurrentScrollingLayerId, dx, dy);
}
nativeScrollLayer(mCurrentScrollingLayerId, x, y);
mScrollingLayerRect.left = x;
mScrollingLayerRect.top = y;
@@ -4726,6 +4766,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
private void onZoomAnimationEnd() {
mPrivateHandler.sendEmptyMessage(RELOCATE_AUTO_COMPLETE_POPUP);
}
void onFixedLengthZoomAnimationStart() {
@@ -4880,11 +4921,20 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
if (mInputConnection == null) {
mInputConnection = new WebViewInputConnection();
mAutoCompletePopup = new AutoCompletePopup(mContext, this,
mInputConnection);
}
mInputConnection.setupEditorInfo(outAttrs);
return mInputConnection;
}
private void relocateAutoCompletePopup() {
if (mAutoCompletePopup != null) {
mAutoCompletePopup.resetRect();
mAutoCompletePopup.setText(mInputConnection.getEditable());
}
}
/**
* Called in response to a message from webkit telling us that the soft
* keyboard should be launched.
@@ -4915,6 +4965,91 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
}
/**
* Called by AutoCompletePopup to find saved form data associated with the
* textfield
* @param name Name of the textfield.
* @param nodePointer Pointer to the node of the textfield, so it can be
* compared to the currently focused textfield when the data is
* retrieved.
* @param autoFillable true if WebKit has determined this field is part of
* a form that can be auto filled.
* @param autoComplete true if the attribute "autocomplete" is set to true
* on the textfield.
*/
/* package */ void requestFormData(String name, int nodePointer,
boolean autoFillable, boolean autoComplete) {
if (mWebViewCore.getSettings().getSaveFormData()) {
Message update = mPrivateHandler.obtainMessage(REQUEST_FORM_DATA);
update.arg1 = nodePointer;
RequestFormData updater = new RequestFormData(name, getUrl(),
update, autoFillable, autoComplete);
Thread t = new Thread(updater);
t.start();
}
}
/*
* This class requests an Adapter for the AutoCompletePopup which shows past
* entries stored in the database. It is a Runnable so that it can be done
* in its own thread, without slowing down the UI.
*/
private class RequestFormData implements Runnable {
private String mName;
private String mUrl;
private Message mUpdateMessage;
private boolean mAutoFillable;
private boolean mAutoComplete;
private WebSettingsClassic mWebSettings;
public RequestFormData(String name, String url, Message msg,
boolean autoFillable, boolean autoComplete) {
mName = name;
mUrl = WebTextView.urlForAutoCompleteData(url);
mUpdateMessage = msg;
mAutoFillable = autoFillable;
mAutoComplete = autoComplete;
mWebSettings = getSettings();
}
@Override
public void run() {
ArrayList<String> pastEntries = new ArrayList<String>();
if (mAutoFillable) {
// Note that code inside the adapter click handler in AutoCompletePopup depends
// on the AutoFill item being at the top of the drop down list. If you change
// the order, make sure to do it there too!
if (mWebSettings != null && mWebSettings.getAutoFillProfile() != null) {
pastEntries.add(mWebView.getResources().getText(
com.android.internal.R.string.autofill_this_form).toString() +
" " +
mAutoFillData.getPreviewString());
mAutoCompletePopup.setIsAutoFillProfileSet(true);
} else {
// There is no autofill profile set up yet, so add an option that
// will invite the user to set their profile up.
pastEntries.add(mWebView.getResources().getText(
com.android.internal.R.string.setup_autofill).toString());
mAutoCompletePopup.setIsAutoFillProfileSet(false);
}
}
if (mAutoComplete) {
pastEntries.addAll(mDatabase.getFormData(mUrl, mName));
}
if (pastEntries.size() > 0) {
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
mContext,
com.android.internal.R.layout.web_text_view_dropdown,
pastEntries);
mUpdateMessage.obj = adapter;
mUpdateMessage.sendToTarget();
}
}
}
/**
* Dump the display tree to "/sdcard/displayTree.txt"
*
@@ -4990,6 +5125,13 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
|| keyCode == KeyEvent.KEYCODE_NUMPAD_ENTER;
}
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (mAutoCompletePopup != null) {
return mAutoCompletePopup.onKeyPreIme(keyCode, event);
}
return false;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (DebugFlags.WEB_VIEW) {
@@ -5593,6 +5735,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
// However, do not update the base layer as that hasn't changed
setNewPicture(mLoadedPicture, false);
}
relocateAutoCompletePopup();
}
@Override
@@ -8020,6 +8163,12 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
break;
}
case REQUEST_FORM_DATA:
if (mFieldPointer == msg.arg1) {
ArrayAdapter<String> adapter = (ArrayAdapter<String>)msg.obj;
mAutoCompletePopup.setAdapter(adapter);
}
break;
case LONG_PRESS_CENTER:
// as this is shared by keydown and trackballdown, reset all
@@ -8174,6 +8323,11 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
break;
case FOCUS_NODE_CHANGED:
if (mAutoCompletePopup != null) {
mAutoCompletePopup.setFocused(msg.arg1 == mFieldPointer);
}
// fall through to HIT_TEST_RESULT
case HIT_TEST_RESULT:
WebKitHitTest hit = (WebKitHitTest) msg.obj;
mFocusedNode = hit;
@@ -8190,11 +8344,20 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
case SET_AUTOFILLABLE:
mAutoFillData = (WebViewCore.AutoFillData) msg.obj;
// TODO: Support (b/6083041)
if (mInputConnection != null) {
mInputConnection.setAutoFillable(mAutoFillData.getQueryId());
mAutoCompletePopup.setAutoFillQueryId(mAutoFillData.getQueryId());
}
break;
case AUTOFILL_COMPLETE:
// TODO: Support (b/6083041)
if (mAutoCompletePopup != null) {
ArrayList<String> pastEntries = new ArrayList<String>();
mAutoCompletePopup.setAdapter(new ArrayAdapter<String>(
mContext,
com.android.internal.R.layout.web_text_view_dropdown,
pastEntries));
}
break;
case COPY_TO_CLIPBOARD:
@@ -8208,6 +8371,11 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
mFieldPointer = initData.mFieldPointer;
mInputConnection.initEditorInfo(initData);
mInputConnection.setTextAndKeepSelection(initData.mText);
nativeMapLayerRect(mNativeClass, initData.mNodeLayerId,
initData.mNodeBounds);
mAutoCompletePopup.setNodeBounds(initData.mNodeBounds,
initData.mNodeLayerId);
mAutoCompletePopup.setText(mInputConnection.getEditable());
}
break;
@@ -8236,6 +8404,15 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
mWebViewCore.sendMessage(EventHub.KEY_PRESS, msg.arg1);
break;
case RELOCATE_AUTO_COMPLETE_POPUP:
relocateAutoCompletePopup();
break;
case AUTOFILL_FORM:
mWebViewCore.sendMessage(EventHub.AUTOFILL_FORM,
msg.arg1, /* unused */0);
break;
default:
super.handleMessage(msg);
break;
@@ -9019,7 +9196,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
/*package*/ void autoFillForm(int autoFillQueryId) {
mWebViewCore.sendMessage(EventHub.AUTOFILL_FORM, autoFillQueryId, /* unused */0);
mPrivateHandler.obtainMessage(AUTOFILL_FORM, autoFillQueryId, 0)
.sendToTarget();
}
/* package */ ViewManager getViewManager() {
@@ -9169,4 +9347,6 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
private static native int nativeGetHandleLayerId(int instance, int handle,
Rect cursorLocation);
private static native boolean nativeIsBaseFirst(int instance);
private static native void nativeMapLayerRect(int instance, int layerId,
Rect rect);
}

View File

@@ -339,10 +339,10 @@ public final class WebViewCore {
/**
* Called by JNI when the focus node changed.
*/
private void focusNodeChanged(WebKitHitTest hitTest) {
private void focusNodeChanged(int nodePointer, WebKitHitTest hitTest) {
if (mWebView == null) return;
mWebView.mPrivateHandler.obtainMessage(WebViewClassic.HIT_TEST_RESULT, hitTest)
.sendToTarget();
mWebView.mPrivateHandler.obtainMessage(WebViewClassic.FOCUS_NODE_CHANGED,
nodePointer, 0, hitTest).sendToTarget();
}
/**
@@ -953,22 +953,32 @@ public final class WebViewCore {
static class TextFieldInitData {
public TextFieldInitData(int fieldPointer,
String text, int type, boolean isSpellCheckEnabled,
boolean isTextFieldNext, String label, int maxLength) {
boolean autoComplete, boolean isTextFieldNext,
String name, String label, int maxLength,
Rect nodeBounds, int nodeLayerId) {
mFieldPointer = fieldPointer;
mText = text;
mType = type;
mIsAutoCompleteEnabled = autoComplete;
mIsSpellCheckEnabled = isSpellCheckEnabled;
mIsTextFieldNext = isTextFieldNext;
mName = name;
mLabel = label;
mMaxLength = maxLength;
mNodeBounds = nodeBounds;
mNodeLayerId = nodeLayerId;
}
int mFieldPointer;
String mText;
int mType;
boolean mIsSpellCheckEnabled;
boolean mIsTextFieldNext;
boolean mIsAutoCompleteEnabled;
String mName;
String mLabel;
int mMaxLength;
Rect mNodeBounds;
int mNodeLayerId;
}
// mAction of TouchEventData can be MotionEvent.getAction() which uses the
@@ -2787,14 +2797,16 @@ public final class WebViewCore {
// called by JNI
private void initEditField(int pointer, String text, int inputType,
boolean isSpellCheckEnabled, boolean nextFieldIsText,
String label, int start, int end, int selectionPtr, int maxLength) {
boolean isSpellCheckEnabled, boolean isAutoCompleteEnabled,
boolean nextFieldIsText, String name,
String label, int start, int end, int selectionPtr, int maxLength,
Rect nodeRect, int nodeLayer) {
if (mWebView == null) {
return;
}
TextFieldInitData initData = new TextFieldInitData(pointer,
text, inputType, isSpellCheckEnabled, nextFieldIsText, label,
maxLength);
text, inputType, isSpellCheckEnabled, isAutoCompleteEnabled,
nextFieldIsText, name, label, maxLength, nodeRect, nodeLayer);
Message.obtain(mWebView.mPrivateHandler,
WebViewClassic.INIT_EDIT_FIELD, initData).sendToTarget();
Message.obtain(mWebView.mPrivateHandler,