1// Copyright (c) 2013 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;
6
7import android.graphics.Bitmap;
8import android.test.suitebuilder.annotation.MediumTest;
9import android.test.suitebuilder.annotation.SmallTest;
10
11import org.chromium.base.ThreadUtils;
12import org.chromium.base.test.util.Feature;
13import org.chromium.base.test.util.UrlUtils;
14import org.chromium.chrome.testshell.ChromiumTestShellActivity;
15import org.chromium.chrome.testshell.ChromiumTestShellTestBase;
16import org.chromium.content.browser.NavigationClient;
17import org.chromium.content.browser.NavigationEntry;
18import org.chromium.content.browser.NavigationHistory;
19import org.chromium.content.browser.test.util.Criteria;
20import org.chromium.content.browser.test.util.CriteriaHelper;
21
22import java.util.concurrent.Callable;
23import java.util.concurrent.ExecutionException;
24
25/**
26 * Tests for the navigation popup.
27 */
28public class NavigationPopupTest extends ChromiumTestShellTestBase {
29
30    private static final int INVALID_NAVIGATION_INDEX = -1;
31
32    private ChromiumTestShellActivity mActivity;
33
34    @Override
35    public void setUp() throws Exception {
36        super.setUp();
37
38        mActivity = launchChromiumTestShellWithBlankPage();
39    }
40
41    // Exists solely to expose protected methods to this test.
42    private static class TestNavigationHistory extends NavigationHistory {
43        @Override
44        protected void addEntry(NavigationEntry entry) {
45            super.addEntry(entry);
46        }
47    }
48
49    // Exists solely to expose protected methods to this test.
50    private static class TestNavigationEntry extends NavigationEntry {
51        public TestNavigationEntry(int index, String url, String virtualUrl, String originalUrl,
52                String title, Bitmap favicon) {
53            super(index, url, virtualUrl, originalUrl, title, favicon);
54        }
55    }
56
57    private static class TestNavigationClient implements NavigationClient {
58        private TestNavigationHistory mHistory;
59        private int mNavigatedIndex = INVALID_NAVIGATION_INDEX;
60
61        public TestNavigationClient() {
62            mHistory = new TestNavigationHistory();
63            mHistory.addEntry(new TestNavigationEntry(
64                    1, "about:blank", null, null, "About Blank", null));
65            mHistory.addEntry(new TestNavigationEntry(
66                    5, UrlUtils.encodeHtmlDataUri("<html>1</html>"), null, null, null, null));
67        }
68
69        @Override
70        public NavigationHistory getDirectedNavigationHistory(boolean isForward, int itemLimit) {
71            return mHistory;
72        }
73
74        @Override
75        public void goToNavigationIndex(int index) {
76            mNavigatedIndex = index;
77        }
78    }
79
80    @MediumTest
81    @Feature({"Navigation"})
82    public void testFaviconFetching() throws InterruptedException {
83        final TestNavigationClient client = new TestNavigationClient();
84        final NavigationPopup popup = new NavigationPopup(
85                mActivity, client, true);
86        popup.setWidth(300);
87        popup.setAnchorView(mActivity.getActiveContentView());
88        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
89            @Override
90            public void run() {
91                popup.show();
92            }
93        });
94
95        assertTrue("All favicons did not get updated.",
96                CriteriaHelper.pollForCriteria(new Criteria() {
97            @Override
98            public boolean isSatisfied() {
99                try {
100                    return ThreadUtils.runOnUiThreadBlocking(new Callable<Boolean>() {
101                        @Override
102                        public Boolean call() throws Exception {
103                            NavigationHistory history = client.mHistory;
104                            for (int i = 0; i < history.getEntryCount(); i++) {
105                                if (history.getEntryAtIndex(i).getFavicon() == null) return false;
106                            }
107                            return true;
108                        }
109                    });
110                } catch (ExecutionException e) {
111                    return false;
112                }
113            }
114        }));
115
116        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
117            @Override
118            public void run() {
119                popup.dismiss();
120            }
121        });
122    }
123
124    @SmallTest
125    @Feature({"Navigation"})
126    public void testItemSelection() {
127        final TestNavigationClient client = new TestNavigationClient();
128        final NavigationPopup popup = new NavigationPopup(
129                mActivity, client, true);
130        popup.setWidth(300);
131        popup.setAnchorView(mActivity.getActiveContentView());
132        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
133            @Override
134            public void run() {
135                popup.show();
136            }
137        });
138
139        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
140            @Override
141            public void run() {
142                popup.performItemClick(1);
143            }
144        });
145
146        assertFalse("Popup did not hide as expected.", popup.isShowing());
147        assertEquals("Popup attempted to navigate to the wrong index", 5, client.mNavigatedIndex);
148    }
149
150}
151