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.
5 package org.chromium.android_webview.test;
7 import android.app.Activity;
8 import android.content.pm.ActivityInfo;
9 import android.test.suitebuilder.annotation.SmallTest;
10 import android.view.View;
11 import android.view.ViewConfiguration;
13 import org.chromium.android_webview.AwContents;
14 import org.chromium.android_webview.AwSettings;
15 import org.chromium.base.ThreadUtils;
16 import org.chromium.base.test.util.Feature;
18 import java.util.concurrent.Callable;
21 * A test suite for zooming-related methods and settings.
23 public class AwZoomTest extends AwTestBase {
24 private TestAwContentsClient mContentsClient;
25 private AwContents mAwContents;
28 public void setUp() throws Exception {
30 mContentsClient = new TestAwContentsClient();
31 final AwTestContainerView testContainerView =
32 createAwTestContainerViewOnMainSync(mContentsClient);
33 mAwContents = testContainerView.getAwContents();
36 private String getZoomableHtml() {
37 return "<html><head><meta name=\"viewport\" content=\"" +
38 "width=device-width, minimum-scale=0.5, maximum-scale=2.0, initial-scale=0.5" +
39 "\"/></head><body>Zoomable</body></html>";
42 private String getNonZoomableHtml() {
43 // This page can't be zoomed because its viewport fully occupies
44 // view area and is explicitly made non user-scalable.
45 return "<html><head>" +
46 "<meta name=\"viewport\" " +
47 "content=\"width=device-width,height=device-height," +
48 "initial-scale=1,maximum-scale=1,user-scalable=no\">" +
49 "</head><body>Non-zoomable</body></html>";
52 private boolean isMultiTouchZoomSupportedOnUiThread() throws Throwable {
53 return runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
55 public Boolean call() throws Exception {
56 return mAwContents.isMultiTouchZoomSupported();
61 private int getVisibilityOnUiThread(final View view) throws Throwable {
62 return runTestOnUiThreadAndGetResult(new Callable<Integer>() {
64 public Integer call() throws Exception {
65 return view.getVisibility();
70 private View getZoomControlsOnUiThread() throws Throwable {
71 return runTestOnUiThreadAndGetResult(new Callable<View>() {
73 public View call() throws Exception {
74 return mAwContents.getZoomControlsForTest();
79 private void invokeZoomPickerOnUiThread() throws Throwable {
80 ThreadUtils.runOnUiThreadBlocking(new Runnable() {
83 mAwContents.invokeZoomPicker();
88 private void zoomInOnUiThreadAndWait() throws Throwable {
89 final float previousScale = getPixelScaleOnUiThread(mAwContents);
90 assertTrue(runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
92 public Boolean call() throws Exception {
93 return mAwContents.zoomIn();
96 // The zoom level is updated asynchronously.
97 waitForScaleChange(previousScale);
100 private void zoomOutOnUiThreadAndWait() throws Throwable {
101 final float previousScale = getPixelScaleOnUiThread(mAwContents);
102 assertTrue(runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
104 public Boolean call() throws Exception {
105 return mAwContents.zoomOut();
108 // The zoom level is updated asynchronously.
109 waitForScaleChange(previousScale);
112 private void waitForScaleChange(final float previousScale) throws Throwable {
113 poll(new Callable<Boolean>() {
115 public Boolean call() throws Exception {
116 return previousScale != getPixelScaleOnUiThread(mAwContents);
121 private void waitUntilCanZoomIn() throws Throwable {
122 poll(new Callable<Boolean>() {
124 public Boolean call() throws Exception {
125 return canZoomInOnUiThread(mAwContents);
130 private void waitUntilCanNotZoom() throws Throwable {
131 poll(new Callable<Boolean>() {
133 public Boolean call() throws Exception {
134 return !canZoomInOnUiThread(mAwContents) &&
135 !canZoomOutOnUiThread(mAwContents);
140 private void runMagnificationTest() throws Throwable {
141 getAwSettingsOnUiThread(mAwContents).setUseWideViewPort(true);
142 assertFalse("Should not be able to zoom in", canZoomInOnUiThread(mAwContents));
143 loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
144 getZoomableHtml(), "text/html", false);
145 waitUntilCanZoomIn();
146 assertTrue("Should be able to zoom in", canZoomInOnUiThread(mAwContents));
147 assertFalse("Should not be able to zoom out", canZoomOutOnUiThread(mAwContents));
149 while (canZoomInOnUiThread(mAwContents)) {
150 zoomInOnUiThreadAndWait();
152 assertTrue("Should be able to zoom out", canZoomOutOnUiThread(mAwContents));
154 while (canZoomOutOnUiThread(mAwContents)) {
155 zoomOutOnUiThreadAndWait();
157 assertTrue("Should be able to zoom in", canZoomInOnUiThread(mAwContents));
161 @Feature({"AndroidWebView"})
162 public void testMagnification() throws Throwable {
163 getAwSettingsOnUiThread(mAwContents).setSupportZoom(true);
164 runMagnificationTest();
167 // According to Android CTS test, zoomIn/Out must work
168 // even if supportZoom is turned off.
170 @Feature({"AndroidWebView"})
171 public void testMagnificationWithZoomSupportOff() throws Throwable {
172 getAwSettingsOnUiThread(mAwContents).setSupportZoom(false);
173 runMagnificationTest();
177 @Feature({"AndroidWebView"})
178 public void testZoomUsingMultiTouch() throws Throwable {
179 AwSettings webSettings = getAwSettingsOnUiThread(mAwContents);
180 loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
181 getZoomableHtml(), "text/html", false);
183 assertTrue(webSettings.supportZoom());
184 assertFalse(webSettings.getBuiltInZoomControls());
185 assertFalse(isMultiTouchZoomSupportedOnUiThread());
187 webSettings.setBuiltInZoomControls(true);
188 assertTrue(isMultiTouchZoomSupportedOnUiThread());
190 webSettings.setSupportZoom(false);
191 assertFalse(isMultiTouchZoomSupportedOnUiThread());
195 @Feature({"AndroidWebView"})
196 public void testZoomControls() throws Throwable {
197 AwSettings webSettings = getAwSettingsOnUiThread(mAwContents);
198 webSettings.setUseWideViewPort(true);
199 assertFalse("Should not be able to zoom in", canZoomInOnUiThread(mAwContents));
200 loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
201 getZoomableHtml(), "text/html", false);
202 waitUntilCanZoomIn();
203 // It must be possible to zoom in (or zoom out) for zoom controls to be shown
204 assertTrue("Should be able to zoom in", canZoomInOnUiThread(mAwContents));
206 assertTrue(webSettings.supportZoom());
207 webSettings.setBuiltInZoomControls(true);
208 webSettings.setDisplayZoomControls(false);
210 // With DisplayZoomControls set to false, attempts to display zoom
211 // controls must be ignored.
212 assertNull(getZoomControlsOnUiThread());
213 invokeZoomPickerOnUiThread();
214 assertNull(getZoomControlsOnUiThread());
216 webSettings.setDisplayZoomControls(true);
217 assertNull(getZoomControlsOnUiThread());
218 invokeZoomPickerOnUiThread();
219 View zoomControls = getZoomControlsOnUiThread();
220 assertEquals(View.VISIBLE, getVisibilityOnUiThread(zoomControls));
224 @Feature({"AndroidWebView"})
225 public void testZoomControlsOnNonZoomableContent() throws Throwable {
226 AwSettings webSettings = getAwSettingsOnUiThread(mAwContents);
227 loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
228 getNonZoomableHtml(), "text/html", false);
230 // ContentView must update itself according to the viewport setup.
231 waitUntilCanNotZoom();
233 assertTrue(webSettings.supportZoom());
234 webSettings.setBuiltInZoomControls(true);
235 webSettings.setDisplayZoomControls(true);
236 assertNull(getZoomControlsOnUiThread());
237 invokeZoomPickerOnUiThread();
238 View zoomControls = getZoomControlsOnUiThread();
239 assertEquals(View.GONE, getVisibilityOnUiThread(zoomControls));
243 @Feature({"AndroidWebView"})
244 public void testZoomControlsOnOrientationChange() throws Throwable {
245 AwSettings webSettings = getAwSettingsOnUiThread(mAwContents);
246 loadDataSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
247 getZoomableHtml(), "text/html", false);
249 assertTrue(webSettings.supportZoom());
250 webSettings.setBuiltInZoomControls(true);
251 webSettings.setDisplayZoomControls(true);
252 invokeZoomPickerOnUiThread();
254 // Now force an orientation change, and try to display the zoom picker
255 // again. Make sure that we don't crash when the ZoomPicker registers
258 Activity activity = getActivity();
259 int orientation = activity.getRequestedOrientation();
260 activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
261 activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
262 activity.setRequestedOrientation(orientation);
263 invokeZoomPickerOnUiThread();
265 // We may crash shortly (as the zoom picker has a short delay in it before
266 // it tries to register it's BroadcastReceiver), so sleep to verify we don't.
267 // The delay is encoded in ZoomButtonsController#ZOOM_CONTROLS_TIMEOUT,
268 // if that changes we may need to update this test.
269 Thread.sleep(ViewConfiguration.getZoomControlsTimeout());