1// Copyright 2014 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.graphics.Picture;
8import android.os.Handler;
9import android.os.Looper;
10import android.test.suitebuilder.annotation.SmallTest;
11
12import org.chromium.android_webview.AwContentsClientCallbackHelper;
13import org.chromium.android_webview.test.TestAwContentsClient.OnDownloadStartHelper;
14import org.chromium.android_webview.test.TestAwContentsClient.OnReceivedLoginRequestHelper;
15import org.chromium.android_webview.test.TestAwContentsClient.PictureListenerHelper;
16import org.chromium.base.test.util.Feature;
17import org.chromium.content.browser.test.util.CallbackHelper;
18import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPageStartedHelper;
19import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnReceivedErrorHelper;
20
21import java.util.concurrent.Callable;
22
23/**
24 * Test suite for AwContentsClientCallbackHelper.
25 */
26public class AwContentsClientCallbackHelperTest extends AwTestBase {
27    /**
28     * Callback helper for OnLoadedResource.
29     */
30    public static class OnLoadResourceHelper extends CallbackHelper {
31        private String mLastLoadedResource;
32
33        public String getLastLoadedResource() {
34            assert getCallCount() > 0;
35            return mLastLoadedResource;
36        }
37
38        public void notifyCalled(String url) {
39            mLastLoadedResource = url;
40            notifyCalled();
41        }
42    }
43
44    /**
45     * TestAwContentsClient extended with OnLoadResourceHelper.
46     */
47    public static class TestAwContentsClient
48            extends org.chromium.android_webview.test.TestAwContentsClient {
49
50        private final OnLoadResourceHelper mOnLoadResourceHelper;
51
52        public TestAwContentsClient() {
53            super();
54            mOnLoadResourceHelper = new OnLoadResourceHelper();
55        }
56
57        public OnLoadResourceHelper getOnLoadResourceHelper() {
58            return mOnLoadResourceHelper;
59        }
60
61        @Override
62        public void onLoadResource(String url) {
63            mOnLoadResourceHelper.notifyCalled(url);
64        }
65    }
66
67    static final int PICTURE_TIMEOUT = 5000;
68    static final String TEST_URL = "www.example.com";
69    static final String REALM = "www.example.com";
70    static final String ACCOUNT = "account";
71    static final String ARGS = "args";
72    static final String USER_AGENT = "userAgent";
73    static final String CONTENT_DISPOSITION = "contentDisposition";
74    static final String MIME_TYPE = "mimeType";
75    static final int CONTENT_LENGTH = 42;
76
77    static final float NEW_SCALE = 1.0f;
78    static final float OLD_SCALE = 2.0f;
79    static final int ERROR_CODE = 2;
80    static final String ERROR_MESSAGE = "A horrible thing has occurred!";
81
82    private TestAwContentsClient mContentsClient;
83    private AwContentsClientCallbackHelper mClientHelper;
84    private Looper mLooper;
85
86    @Override
87    protected void setUp() throws Exception {
88        super.setUp();
89        mLooper = Looper.getMainLooper();
90        mContentsClient = new TestAwContentsClient();
91        mClientHelper = new AwContentsClientCallbackHelper(mLooper, mContentsClient);
92    }
93
94    @Feature({"AndroidWebView"})
95    @SmallTest
96    public void testOnLoadResource() throws Exception {
97        OnLoadResourceHelper loadResourceHelper = mContentsClient.getOnLoadResourceHelper();
98
99        int onLoadResourceCount = loadResourceHelper.getCallCount();
100        mClientHelper.postOnLoadResource(TEST_URL);
101        loadResourceHelper.waitForCallback(onLoadResourceCount);
102        assertEquals(TEST_URL, loadResourceHelper.getLastLoadedResource());
103    }
104
105    @Feature({"AndroidWebView"})
106    @SmallTest
107    public void testOnPageStarted() throws Exception {
108        OnPageStartedHelper pageStartedHelper = mContentsClient.getOnPageStartedHelper();
109
110        int onPageStartedCount = pageStartedHelper.getCallCount();
111        mClientHelper.postOnPageStarted(TEST_URL);
112        pageStartedHelper.waitForCallback(onPageStartedCount);
113        assertEquals(TEST_URL, pageStartedHelper.getUrl());
114    }
115
116    @Feature({"AndroidWebView"})
117    @SmallTest
118    public void testOnDownloadStart() throws Exception {
119        OnDownloadStartHelper downloadStartHelper = mContentsClient.getOnDownloadStartHelper();
120
121        int onDownloadStartCount = downloadStartHelper.getCallCount();
122        mClientHelper.postOnDownloadStart(TEST_URL, USER_AGENT, CONTENT_DISPOSITION,
123                MIME_TYPE, CONTENT_LENGTH);
124        downloadStartHelper.waitForCallback(onDownloadStartCount);
125        assertEquals(TEST_URL, downloadStartHelper.getUrl());
126        assertEquals(USER_AGENT, downloadStartHelper.getUserAgent());
127        assertEquals(CONTENT_DISPOSITION, downloadStartHelper.getContentDisposition());
128        assertEquals(MIME_TYPE, downloadStartHelper.getMimeType());
129        assertEquals(CONTENT_LENGTH, downloadStartHelper.getContentLength());
130    }
131
132    @Feature({"AndroidWebView"})
133    @SmallTest
134    public void testOnNewPicture() throws Exception {
135        final PictureListenerHelper pictureListenerHelper =
136            mContentsClient.getPictureListenerHelper();
137
138        final Picture thePicture = new Picture();
139
140        final Callable<Picture> pictureProvider = new Callable<Picture>() {
141            @Override
142            public Picture call() {
143                return thePicture;
144            }
145        };
146
147        // AwContentsClientCallbackHelper rate limits photo callbacks so two posts in close
148        // succession should only result in one callback.
149        final int onNewPictureCount = pictureListenerHelper.getCallCount();
150        // To trip the rate limiting the second postNewPicture call needs to happen
151        // before mLooper processes the first. To do this we run both posts as a single block
152        // and we do it in the thread that is processes the callbacks (mLooper).
153        Handler mainHandler = new Handler(mLooper);
154        Runnable postPictures = new Runnable() {
155            @Override
156            public void run() {
157                mClientHelper.postOnNewPicture(pictureProvider);
158                mClientHelper.postOnNewPicture(pictureProvider);
159            }
160        };
161        mainHandler.post(postPictures);
162
163        // We want to check that one and only one callback is fired,
164        // First we wait for the first call back to complete, this ensures that both posts have
165        // finished.
166        pictureListenerHelper.waitForCallback(onNewPictureCount);
167
168        // Then we post a runnable on the callback handler thread. Since both posts have happened
169        // and the first callback has happened a second callback (if it exists) must be
170        // in the queue before this runnable.
171        getInstrumentation().runOnMainSync(new Runnable() {
172            @Override
173            public void run() {
174            }
175        });
176
177        // When that runnable has finished we assert that one and only on callback happened.
178        assertEquals(thePicture, pictureListenerHelper.getPicture());
179        assertEquals(onNewPictureCount + 1, pictureListenerHelper.getCallCount());
180    }
181
182    @Feature({"AndroidWebView"})
183    @SmallTest
184    public void testOnReceivedLoginRequest() throws Exception {
185        OnReceivedLoginRequestHelper receivedLoginRequestHelper =
186            mContentsClient.getOnReceivedLoginRequestHelper();
187
188        int onReceivedLoginRequestCount = receivedLoginRequestHelper.getCallCount();
189        mClientHelper.postOnReceivedLoginRequest(REALM, ACCOUNT, ARGS);
190        receivedLoginRequestHelper.waitForCallback(onReceivedLoginRequestCount);
191        assertEquals(REALM, receivedLoginRequestHelper.getRealm());
192        assertEquals(ACCOUNT, receivedLoginRequestHelper.getAccount());
193        assertEquals(ARGS, receivedLoginRequestHelper.getArgs());
194    }
195
196    @Feature({"AndroidWebView"})
197    @SmallTest
198    public void testOnReceivedError() throws Exception {
199        OnReceivedErrorHelper receivedErrorHelper =
200            mContentsClient.getOnReceivedErrorHelper();
201
202        int onReceivedErrorCount = receivedErrorHelper.getCallCount();
203        mClientHelper.postOnReceivedError(ERROR_CODE, ERROR_MESSAGE, TEST_URL);
204        receivedErrorHelper.waitForCallback(onReceivedErrorCount);
205        assertEquals(ERROR_CODE, receivedErrorHelper.getErrorCode());
206        assertEquals(ERROR_MESSAGE, receivedErrorHelper.getDescription());
207        assertEquals(TEST_URL, receivedErrorHelper.getFailingUrl());
208    }
209
210    @Feature({"AndroidWebView"})
211    @SmallTest
212    public void testOnScaleChangedScaled() throws Exception {
213        TestAwContentsClient.OnScaleChangedHelper scaleChangedHelper =
214            mContentsClient.getOnScaleChangedHelper();
215
216        int onScaleChangeCount = scaleChangedHelper.getCallCount();
217        mClientHelper.postOnScaleChangedScaled(OLD_SCALE, NEW_SCALE);
218        scaleChangedHelper.waitForCallback(onScaleChangeCount);
219        assertEquals(OLD_SCALE, scaleChangedHelper.getOldScale());
220        assertEquals(NEW_SCALE, scaleChangedHelper.getNewScale());
221    }
222}
223