1// Copyright 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.android_webview.test;
6
7import android.test.suitebuilder.annotation.SmallTest;
8import android.webkit.ValueCallback;
9
10import org.chromium.android_webview.AwContents;
11import org.chromium.android_webview.test.TestAwContentsClient.DoUpdateVisitedHistoryHelper;
12import org.chromium.base.test.util.Feature;
13import org.chromium.content.browser.test.util.CallbackHelper;
14import org.chromium.net.test.util.TestWebServer;
15
16/**
17 * Tests for AwContentsClient.getVisitedHistory and AwContents.doUpdateVisitedHistory callbacks.
18 */
19public class AwContentsClientVisitedHistoryTest extends AwTestBase {
20    private static class GetVisitedHistoryHelper extends CallbackHelper {
21        private ValueCallback<String[]> mCallback;
22        private boolean mSaveCallback = false;
23
24        public ValueCallback<String[]> getCallback() {
25            assert getCallCount() > 0;
26            return mCallback;
27        }
28
29        public void setSaveCallback(boolean value) {
30            mSaveCallback = value;
31        }
32
33        public void notifyCalled(ValueCallback<String[]> callback) {
34            if (mSaveCallback) {
35                mCallback = callback;
36            }
37            notifyCalled();
38        }
39    }
40
41    private static class VisitedHistoryTestAwContentsClient extends TestAwContentsClient {
42
43        private GetVisitedHistoryHelper mGetVisitedHistoryHelper;
44
45        public VisitedHistoryTestAwContentsClient() {
46            mGetVisitedHistoryHelper = new GetVisitedHistoryHelper();
47        }
48
49        public GetVisitedHistoryHelper getGetVisitedHistoryHelper() {
50            return mGetVisitedHistoryHelper;
51        }
52
53        @Override
54        public void getVisitedHistory(ValueCallback<String[]> callback) {
55            getGetVisitedHistoryHelper().notifyCalled(callback);
56        }
57
58    }
59
60    private VisitedHistoryTestAwContentsClient mContentsClient =
61        new VisitedHistoryTestAwContentsClient();
62
63    @Feature({"AndroidWebView"})
64    @SmallTest
65    public void testUpdateVisitedHistoryCallback() throws Throwable {
66        AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient);
67        AwContents awContents = testView.getAwContents();
68
69        final String path = "/testUpdateVisitedHistoryCallback.html";
70        final String html = "testUpdateVisitedHistoryCallback";
71
72        TestWebServer webServer = null;
73        try {
74            webServer = new TestWebServer(false);
75            final String pageUrl = webServer.setResponse(path, html, null);
76            final DoUpdateVisitedHistoryHelper doUpdateVisitedHistoryHelper =
77                mContentsClient.getDoUpdateVisitedHistoryHelper();
78            int callCount = doUpdateVisitedHistoryHelper.getCallCount();
79            loadUrlAsync(awContents, pageUrl);
80            doUpdateVisitedHistoryHelper.waitForCallback(callCount);
81            assertEquals(pageUrl, doUpdateVisitedHistoryHelper.getUrl());
82            assertEquals(false, doUpdateVisitedHistoryHelper.getIsReload());
83
84            // Reload
85            callCount = doUpdateVisitedHistoryHelper.getCallCount();
86            loadUrlAsync(awContents, pageUrl);
87            doUpdateVisitedHistoryHelper.waitForCallback(callCount);
88            assertEquals(pageUrl, doUpdateVisitedHistoryHelper.getUrl());
89            assertEquals(true, doUpdateVisitedHistoryHelper.getIsReload());
90        } finally {
91            if (webServer != null) webServer.shutdown();
92        }
93    }
94
95    @Feature({"AndroidWebView"})
96    @SmallTest
97    public void testGetVisitedHistoryExerciseCodePath() throws Throwable {
98        // Due to security/privacy restrictions around the :visited css property, it is not
99        // possible test this end to end without using the flaky and brittle capturing picture of
100        // the web page. So we are doing the next best thing, exercising all the code paths.
101        final GetVisitedHistoryHelper visitedHistoryHelper =
102            mContentsClient.getGetVisitedHistoryHelper();
103        final int callCount = visitedHistoryHelper.getCallCount();
104        visitedHistoryHelper.setSaveCallback(true);
105
106        AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient);
107        AwContents awContents = testView.getAwContents();
108
109        final String path = "/testGetVisitedHistoryExerciseCodePath.html";
110        final String visitedLinks[] = {"http://foo.com", "http://bar.com", null};
111        final String html = "<a src=\"http://foo.com\">foo</a><a src=\"http://bar.com\">bar</a>";
112
113        TestWebServer webServer = null;
114        try {
115            webServer = new TestWebServer(false);
116            final String pageUrl = webServer.setResponse(path, html, null);
117            loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl);
118            visitedHistoryHelper.waitForCallback(callCount);
119            assertNotNull(visitedHistoryHelper.getCallback());
120
121            visitedHistoryHelper.getCallback().onReceiveValue(visitedLinks);
122            visitedHistoryHelper.getCallback().onReceiveValue(null);
123
124            loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl);
125        } finally {
126            if (webServer != null) webServer.shutdown();
127        }
128    }
129
130    @Feature({"AndroidWebView"})
131    @SmallTest
132    public void testGetVisitedHistoryCallbackAfterDestroy() throws Throwable {
133        GetVisitedHistoryHelper visitedHistoryHelper =
134            mContentsClient.getGetVisitedHistoryHelper();
135        visitedHistoryHelper.setSaveCallback(true);
136        final int callCount = visitedHistoryHelper.getCallCount();
137        AwTestContainerView testView = createAwTestContainerViewOnMainSync(mContentsClient);
138        AwContents awContents = testView.getAwContents();
139        loadUrlAsync(awContents, "about:blank");
140        visitedHistoryHelper.waitForCallback(callCount);
141        assertNotNull(visitedHistoryHelper.getCallback());
142
143        destroyAwContentsOnMainSync(awContents);
144        visitedHistoryHelper.getCallback().onReceiveValue(new String[] {"abc.def"});
145        visitedHistoryHelper.getCallback().onReceiveValue(null);
146    }
147}
148