Merge "Add back auto-completion and auto-fill."
diff --git a/core/java/android/webkit/AutoCompletePopup.java b/core/java/android/webkit/AutoCompletePopup.java
new file mode 100644
index 0000000..e0e5eca
--- /dev/null
+++ b/core/java/android/webkit/AutoCompletePopup.java
@@ -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();
+        }
+    }
+}
+
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 856f787..812d89a 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -375,7 +375,7 @@
      * 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 @@
         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 @@
             mInputType = inputType;
             mImeOptions = imeOptions;
             mMaxLength = initData.mMaxLength;
+            mIsAutoCompleteEnabled = initData.mIsAutoCompleteEnabled;
+            mName = initData.mName;
+            mAutoCompletePopup.clearAdapter();
         }
 
         public void setupEditorInfo(EditorInfo outAttrs) {
@@ -629,6 +652,13 @@
                         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 @@
     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 @@
     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 @@
     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 @@
     @Override
     public void clearFormData() {
         checkThread();
-        // TODO: Implement b/6083041
+        if (mAutoCompletePopup != null) {
+            mAutoCompletePopup.clearAdapter();
+        }
     }
 
     /**
@@ -3861,12 +3898,12 @@
     }
 
     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 @@
                 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 @@
     }
 
     private void onZoomAnimationEnd() {
+        mPrivateHandler.sendEmptyMessage(RELOCATE_AUTO_COMPLETE_POPUP);
     }
 
     void onFixedLengthZoomAnimationStart() {
@@ -4880,11 +4921,20 @@
     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.
@@ -4916,6 +4966,91 @@
     }
 
     /**
+     * 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"
      *
      * @hide debug only
@@ -4990,6 +5125,13 @@
                 || 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 @@
             // However, do not update the base layer as that hasn't changed
             setNewPicture(mLoadedPicture, false);
         }
+        relocateAutoCompletePopup();
     }
 
     @Override
@@ -8020,6 +8163,12 @@
                     }
                     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 @@
                     }
                     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 @@
 
                 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 @@
                         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 @@
                     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 @@
     }
 
     /*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 @@
     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);
 }
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index de30755..8def74b 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -339,10 +339,10 @@
     /**
      * 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 @@
     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 @@
 
     // 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,