1// Copyright 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package org.chromium.chrome.browser.autofill;
6
7import android.test.suitebuilder.annotation.SmallTest;
8
9import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
10
11import org.chromium.base.test.util.Feature;
12import org.chromium.chrome.shell.ChromeShellActivity;
13import org.chromium.chrome.shell.ChromeShellTestBase;
14import org.chromium.content.browser.test.util.Criteria;
15import org.chromium.content.browser.test.util.CriteriaHelper;
16import org.chromium.content.browser.test.util.TouchCommon;
17import org.chromium.content.browser.test.util.UiUtils;
18import org.chromium.ui.autofill.AutofillPopup;
19import org.chromium.ui.autofill.AutofillPopup.AutofillPopupDelegate;
20import org.chromium.ui.autofill.AutofillSuggestion;
21import org.chromium.ui.base.ActivityWindowAndroid;
22import org.chromium.ui.base.ViewAndroidDelegate;
23import org.chromium.ui.base.WindowAndroid;
24
25import java.util.concurrent.atomic.AtomicBoolean;
26
27/**
28 * Tests the Autofill's java code for creating the AutofillPopup object, opening and selecting
29 * popups.
30 */
31public class AutofillTest extends ChromeShellTestBase {
32
33    private AutofillPopup mAutofillPopup;
34    private WindowAndroid mWindowAndroid;
35    private MockAutofillCallback mMockAutofillCallback;
36
37    @Override
38    public void setUp() throws Exception {
39        super.setUp();
40        ChromeShellActivity activity = launchChromeShellWithBlankPage();
41        assertNotNull(activity);
42        waitForActiveShellToBeDoneLoading();
43
44        mMockAutofillCallback = new MockAutofillCallback();
45        mWindowAndroid = new ActivityWindowAndroid(activity);
46        final ViewAndroidDelegate viewDelegate =
47                activity.getActiveContentViewCore().getViewAndroidDelegate();
48
49        UiUtils.runOnUiThread(getActivity(), new Runnable() {
50            @Override
51            public void run() {
52                mAutofillPopup = new AutofillPopup(mWindowAndroid.getActivity().get(),
53                        viewDelegate,
54                        mMockAutofillCallback);
55                mAutofillPopup.setAnchorRect(50, 500, 500, 50);
56            }
57        });
58
59    }
60
61    private static final long CALLBACK_TIMEOUT_MS = scaleTimeout(4000);
62    private static final int CHECK_INTERVAL_MS = 100;
63
64    private class MockAutofillCallback implements AutofillPopupDelegate{
65        private final AtomicBoolean mGotPopupSelection = new AtomicBoolean(false);
66        public int mListIndex = -1;
67
68        @Override
69        public void suggestionSelected(int listIndex) {
70            mListIndex = listIndex;
71            mAutofillPopup.dismiss();
72            mGotPopupSelection.set(true);
73        }
74
75        public boolean waitForCallback() throws InterruptedException {
76            return CriteriaHelper.pollForCriteria(new Criteria() {
77                @Override
78                public boolean isSatisfied() {
79                    return mGotPopupSelection.get();
80                }
81            }, CALLBACK_TIMEOUT_MS, CHECK_INTERVAL_MS);
82        }
83
84        @Override
85        public void dismissed() {
86        }
87    }
88
89    private AutofillSuggestion[] createTwoAutofillSuggestionArray() {
90        return new AutofillSuggestion[] {
91            new AutofillSuggestion("Sherlock Holmes", "221B Baker Street", 42),
92            new AutofillSuggestion("Arthur Dent", "West Country", 43),
93        };
94    }
95
96    private AutofillSuggestion[] createFiveAutofillSuggestionArray() {
97        return new AutofillSuggestion[] {
98            new AutofillSuggestion("Sherlock Holmes", "221B Baker Street", 42),
99            new AutofillSuggestion("Arthur Dent", "West Country", 43),
100            new AutofillSuggestion("Arthos", "France", 44),
101            new AutofillSuggestion("Porthos", "France", 45),
102            new AutofillSuggestion("Aramis", "France", 46),
103        };
104    }
105
106    public boolean openAutofillPopupAndWaitUntilReady(final AutofillSuggestion[] suggestions)
107            throws InterruptedException {
108        UiUtils.runOnUiThread(getActivity(), new Runnable() {
109            @Override
110            public void run() {
111                mAutofillPopup.filterAndShow(suggestions, false);
112            }
113        });
114        return CriteriaHelper.pollForCriteria(new Criteria() {
115            @Override
116            public boolean isSatisfied() {
117                return mAutofillPopup.getListView().getChildCount() > 0;
118            }
119        });
120    }
121
122    @SmallTest
123    @Feature({"autofill"})
124    public void testAutofillWithDifferentNumberSuggestions() throws Exception {
125        assertTrue(openAutofillPopupAndWaitUntilReady(createTwoAutofillSuggestionArray()));
126        assertEquals(2, mAutofillPopup.getListView().getCount());
127
128        assertTrue(openAutofillPopupAndWaitUntilReady(createFiveAutofillSuggestionArray()));
129        assertEquals(5, mAutofillPopup.getListView().getCount());
130    }
131
132    @SmallTest
133    @Feature({"autofill"})
134    public void testAutofillClickFirstSuggestion() throws Exception {
135        AutofillSuggestion[] suggestions = createTwoAutofillSuggestionArray();
136        assertTrue(openAutofillPopupAndWaitUntilReady(suggestions));
137        assertEquals(2, mAutofillPopup.getListView().getCount());
138
139        TouchCommon touchCommon = new TouchCommon(this);
140        touchCommon.singleClickViewRelative(mAutofillPopup.getListView(), 10, 10);
141        assertTrue(mMockAutofillCallback.waitForCallback());
142
143        assertEquals(0, mMockAutofillCallback.mListIndex);
144    }
145}
146