Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 62275a46 authored by Ben Murdoch's avatar Ben Murdoch Committed by Steve Block
Browse files

Make WebTextView display an "AutoFill this form" option

When the user clicks to AutoFill the form, we propogate a message
to WebCore through WebViewCore to actually perform the action.

Corresponding change in external/webkit needed to implement the
native method that gets called to execute

Change-Id: I6c75ab9b2c5404580de549b69102ab9374493c34
parent 1115d0da
Loading
Loading
Loading
Loading
+32 −2
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputConnection;
import android.widget.AbsoluteLayout.LayoutParams;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.TextView;
@@ -116,15 +117,28 @@ import java.util.ArrayList;
    private int mDelSelStart;
    private int mDelSelEnd;

    // Keep in sync with native constant in
    // external/webkit/WebKit/android/WebCoreSupport/autofill/WebAutoFill.cpp
    /* package */ static final int FORM_NOT_AUTOFILLABLE = -1;

    private boolean mAutoFillable; // Is this textview part of an autofillable form?
    private int mQueryId;

    /**
     * Create a new WebTextView.
     * @param   context The Context for this WebTextView.
     * @param   webView The WebView that created this.
     */
    /* package */ WebTextView(Context context, WebView webView) {
    /* package */ WebTextView(Context context, WebView webView, int autoFillQueryId) {
        super(context, null, com.android.internal.R.attr.webTextViewStyle);
        mWebView = webView;
        mMaxLength = -1;
        setAutoFillable(autoFillQueryId);
    }

    public void setAutoFillable(int queryId) {
        mAutoFillable = (queryId != FORM_NOT_AUTOFILLABLE);
        mQueryId = queryId;
    }

    @Override
@@ -673,6 +687,22 @@ import java.util.ArrayList;
            adapter.setTextView(this);
        }
        super.setAdapter(adapter);
        if (mAutoFillable) {
            setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    if (id == 0 && position == 0) {
                        // Blank out the text box while we wait for WebCore to fill the form.
                        replaceText("");
                        // Call a webview method to tell WebCore to autofill the form.
                        mWebView.autoFillForm(mQueryId);
                    }
                }
            });
        } else {
            setOnItemClickListener(null);
        }
        showDropDown();
    }

    /**
@@ -964,7 +994,7 @@ import java.util.ArrayList;
            if (type != 2 /* PASSWORD */) {
                String name = mWebView.nativeFocusCandidateName();
                if (name != null && name.length() > 0) {
                    mWebView.requestFormData(name, mNodePointer);
                    mWebView.requestFormData(name, mNodePointer, mAutoFillable);
                }
            }
        }
+38 −6
Original line number Diff line number Diff line
@@ -614,6 +614,8 @@ public class WebView extends AbsoluteLayout
    static final int SET_TOUCH_HIGHLIGHT_RECTS          = 131;
    static final int SAVE_WEBARCHIVE_FINISHED           = 132;

    static final int SET_AUTOFILLABLE                   = 133;

    private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID;
    private static final int LAST_PACKAGE_MSG_ID = SET_TOUCH_HIGHLIGHT_RECTS;

@@ -662,7 +664,8 @@ public class WebView extends AbsoluteLayout
        "SET_SCROLLBAR_MODES", //            = 129;
        "SELECTION_STRING_CHANGED", //       = 130;
        "SET_TOUCH_HIGHLIGHT_RECTS", //      = 131;
        "SAVE_WEBARCHIVE_FINISHED" //        = 132;
        "SAVE_WEBARCHIVE_FINISHED", //       = 132;
        "SET_AUTOFILLABLE" //                = 133;
    };

    // If the site doesn't use the viewport meta tag to specify the viewport,
@@ -735,6 +738,8 @@ public class WebView extends AbsoluteLayout
    // for event log
    private long mLastTouchUpTime = 0;

    private int mAutoFillQueryId = WebTextView.FORM_NOT_AUTOFILLABLE;

    /**
     * URI scheme for telephone number
     */
@@ -3868,7 +3873,7 @@ public class WebView extends AbsoluteLayout
        // At this point, we know we have found an input field, so go ahead
        // and create the WebTextView if necessary.
        if (mWebTextView == null) {
            mWebTextView = new WebTextView(mContext, WebView.this);
            mWebTextView = new WebTextView(mContext, WebView.this, mAutoFillQueryId);
            // Initialize our generation number.
            mTextGeneration = 0;
        }
@@ -3936,13 +3941,15 @@ public class WebView extends AbsoluteLayout
     * @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.
     */
    /* package */ void requestFormData(String name, int nodePointer) {
    /* package */ void requestFormData(String name, int nodePointer, boolean autoFillable) {
        if (mWebViewCore.getSettings().getSaveFormData()) {
            Message update = mPrivateHandler.obtainMessage(REQUEST_FORM_DATA);
            update.arg1 = nodePointer;
            RequestFormData updater = new RequestFormData(name, getUrl(),
                    update);
                    update, autoFillable);
            Thread t = new Thread(updater);
            t.start();
        }
@@ -3968,15 +3975,28 @@ public class WebView extends AbsoluteLayout
        private String mName;
        private String mUrl;
        private Message mUpdateMessage;
        private boolean mAutoFillable;

        public RequestFormData(String name, String url, Message msg) {
        public RequestFormData(String name, String url, Message msg, boolean autoFillable) {
            mName = name;
            mUrl = url;
            mUpdateMessage = msg;
            mAutoFillable = autoFillable;
        }

        public void run() {
            ArrayList<String> pastEntries = mDatabase.getFormData(mUrl, mName);
            ArrayList<String> pastEntries = new ArrayList();

            if (mAutoFillable) {
                // Note that code inside the adapter click handler in WebTextView 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!
                pastEntries.add(getResources().getText(
                        com.android.internal.R.string.autofill_this_form).toString());
            }

            pastEntries.addAll(mDatabase.getFormData(mUrl, mName));

            if (pastEntries.size() > 0) {
                AutoCompleteAdapter adapter = new
                        AutoCompleteAdapter(mContext, pastEntries);
@@ -6942,6 +6962,14 @@ public class WebView extends AbsoluteLayout
                    }
                    break;

                case SET_AUTOFILLABLE:
                    mAutoFillQueryId = msg.arg1;
                    if (mWebTextView != null) {
                        mWebTextView.setAutoFillable(mAutoFillQueryId);
                        rebuildWebTextView();
                    }
                    break;

                default:
                    super.handleMessage(msg);
                    break;
@@ -7475,6 +7503,10 @@ public class WebView extends AbsoluteLayout
        nativeUpdateCachedTextfield(updatedText, mTextGeneration);
    }

    /*package*/ void autoFillForm(int autoFillQueryId) {
        mWebViewCore.sendMessage(EventHub.AUTOFILL_FORM, autoFillQueryId, /* unused */0);
    }

    private native int nativeCacheHitFramePointer();
    private native Rect nativeCacheHitNodeBounds();
    private native int nativeCacheHitNodePointer();
+15 −0
Original line number Diff line number Diff line
@@ -882,6 +882,8 @@ final class WebViewCore {

        static final int USE_MOCK_DEVICE_ORIENTATION = 191;

        static final int AUTOFILL_FORM = 192;

        // private message ids
        private static final int DESTROY =     200;

@@ -1417,6 +1419,10 @@ final class WebViewCore {
                        case USE_MOCK_DEVICE_ORIENTATION:
                            useMockDeviceOrientation();
                            break;

                        case AUTOFILL_FORM:
                            nativeAutoFillForm(msg.arg1);
                            break;
                    }
                }
            };
@@ -2366,6 +2372,13 @@ final class WebViewCore {
        }
    }

    private void setWebTextViewAutoFillable(int queryId) {
        if (mWebView != null) {
            Message.obtain(mWebView.mPrivateHandler, WebView.SET_AUTOFILLABLE, queryId,
                    /* unused */0).sendToTarget();
        }
    }

    // called by JNI
    private Context getContext() {
        return mContext;
@@ -2533,4 +2546,6 @@ final class WebViewCore {

    private native ArrayList<Rect> nativeGetTouchHighlightRects(int x, int y,
            int slop);

   private native void nativeAutoFillForm(int queryId);
}
+3 −0
Original line number Diff line number Diff line
@@ -1629,6 +1629,9 @@
    <!-- Toast for double-tap -->
    <string name="double_tap_toast">Tip: double-tap to zoom in and out.</string>

    <!-- Text to show in the auto complete drop down list on a text view when the browser can auto fill the entire form -->
    <string name="autofill_this_form">AutoFill this form</string>

    <!-- Title of an application permission, listed so the user can choose whether
        they want to allow the application to do this. -->
    <string name="permlab_readHistoryBookmarks">read Browser\'s history and bookmarks</string>