EMMA Coverage Report (generated Tue Aug 20 10:07:21 PDT 2013)
[all classes][org.chromium.android_webview.test]

COVERAGE SUMMARY FOR SOURCE FILE [AndroidViewIntegrationTest.java]

nameclass, %method, %block, %line, %
AndroidViewIntegrationTest.java100% (9/9)100% (38/38)98%  (570/584)99%  (108.8/110)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class AndroidViewIntegrationTest$OnContentSizeChangedHelper100% (1/1)100% (6/6)79%  (37/47)88%  (8/9)
getHeight (): int 100% (1/1)67%  (8/12)78%  (1.6/2)
getWidth (): int 100% (1/1)67%  (8/12)78%  (1.6/2)
<static initializer> 100% (1/1)75%  (6/8)75%  (0.8/1)
AndroidViewIntegrationTest$OnContentSizeChangedHelper (): void 100% (1/1)100% (3/3)100% (1/1)
AndroidViewIntegrationTest$OnContentSizeChangedHelper (AndroidViewIntegration... 100% (1/1)100% (3/3)100% (1/1)
onContentSizeChanged (int, int): void 100% (1/1)100% (9/9)100% (4/4)
     
class AndroidViewIntegrationTest100% (1/1)100% (16/16)99%  (382/386)100% (80.8/81)
waitForContentSizeToChangeTo (AndroidViewIntegrationTest$OnContentSizeChanged... 100% (1/1)97%  (35/36)98%  (6.9/7)
testDisconnectedViewLoadsContent (): void 100% (1/1)98%  (40/41)100% (10/10)
testZeroByZeroViewLoadsContent (): void 100% (1/1)98%  (41/42)100% (10/10)
testInvisibleViewLoadsContent (): void 100% (1/1)98%  (49/50)100% (11/11)
AndroidViewIntegrationTest (): void 100% (1/1)100% (24/24)100% (5/5)
access$100 (AndroidViewIntegrationTest): AndroidViewIntegrationTest$OnContent... 100% (1/1)100% (3/3)100% (1/1)
access$200 (AndroidViewIntegrationTest): CallbackHelper 100% (1/1)100% (3/3)100% (1/1)
assertZeroHeight (AwTestContainerView): void 100% (1/1)100% (9/9)100% (2/2)
createCustomTestContainerViewOnMainSync (AwContentsClient, int): AwTestContai... 100% (1/1)100% (18/18)100% (3/3)
createDetachedTestContainerViewOnMainSync (AwContentsClient): AwTestContainer... 100% (1/1)100% (17/17)100% (3/3)
createTestDependencyFactory (): AwTestBase$TestDependencyFactory 100% (1/1)100% (5/5)100% (1/1)
getRootLayoutWidthOnMainThread (): int 100% (1/1)100% (17/17)100% (3/3)
loadPageOfSizeAndWaitForSizeChange (AwContents, AndroidViewIntegrationTest$On... 100% (1/1)100% (21/21)100% (5/5)
makeHtmlPageOfSize (int, int): String 100% (1/1)100% (25/25)100% (1/1)
testPreferredSizeUpdateWhenDetached (): void 100% (1/1)100% (24/24)100% (7/7)
testViewSizedCorrectlyInWrapContentMode (): void 100% (1/1)100% (51/51)100% (13/13)
     
class AndroidViewIntegrationTest$1100% (1/1)100% (2/2)100% (13/13)100% (2/2)
AndroidViewIntegrationTest$1 (AndroidViewIntegrationTest): void 100% (1/1)100% (6/6)100% (1/1)
createLayoutSizer (): AwLayoutSizer 100% (1/1)100% (7/7)100% (1/1)
     
class AndroidViewIntegrationTest$2100% (1/1)100% (2/2)100% (39/39)100% (5/5)
AndroidViewIntegrationTest$2 (AndroidViewIntegrationTest, AtomicReference, Aw... 100% (1/1)100% (15/15)100% (1/1)
run (): void 100% (1/1)100% (24/24)100% (4/4)
     
class AndroidViewIntegrationTest$3100% (1/1)100% (2/2)100% (21/21)100% (3/3)
AndroidViewIntegrationTest$3 (AndroidViewIntegrationTest, AtomicReference, Aw... 100% (1/1)100% (12/12)100% (1/1)
run (): void 100% (1/1)100% (9/9)100% (2/2)
     
class AndroidViewIntegrationTest$4100% (1/1)100% (2/2)100% (15/15)100% (3/3)
AndroidViewIntegrationTest$4 (AndroidViewIntegrationTest, AwTestContainerView... 100% (1/1)100% (9/9)100% (1/1)
run (): void 100% (1/1)100% (6/6)100% (2/2)
     
class AndroidViewIntegrationTest$5100% (1/1)100% (2/2)100% (19/19)100% (3/3)
AndroidViewIntegrationTest$5 (AndroidViewIntegrationTest, AtomicReference): void 100% (1/1)100% (9/9)100% (1/1)
run (): void 100% (1/1)100% (10/10)100% (2/2)
     
class AndroidViewIntegrationTest$6100% (1/1)100% (2/2)100% (15/15)100% (3/3)
AndroidViewIntegrationTest$6 (AndroidViewIntegrationTest, AwTestContainerView... 100% (1/1)100% (9/9)100% (1/1)
run (): void 100% (1/1)100% (6/6)100% (2/2)
     
class AndroidViewIntegrationTest$TestAwLayoutSizer100% (1/1)100% (4/4)100% (29/29)100% (7/7)
AndroidViewIntegrationTest$TestAwLayoutSizer (AndroidViewIntegrationTest): void 100% (1/1)100% (6/6)100% (1/1)
AndroidViewIntegrationTest$TestAwLayoutSizer (AndroidViewIntegrationTest, And... 100% (1/1)100% (4/4)100% (1/1)
onContentSizeChanged (int, int): void 100% (1/1)100% (11/11)100% (3/3)
onPageScaleChanged (double): void 100% (1/1)100% (8/8)100% (3/3)

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.view.View;
9import android.view.View.MeasureSpec;
10import android.view.ViewGroup.LayoutParams;
11import android.widget.LinearLayout;
12import android.util.Log;
13 
14import org.chromium.android_webview.AwContents;
15import org.chromium.android_webview.AwContentsClient;
16import org.chromium.android_webview.AwLayoutSizer;
17import org.chromium.android_webview.test.util.CommonResources;
18import org.chromium.base.test.util.Feature;
19import org.chromium.content.browser.ContentViewCore;
20import org.chromium.content.browser.test.util.CallbackHelper;
21import org.chromium.ui.gfx.DeviceDisplayInfo;
22 
23import java.util.concurrent.atomic.AtomicReference;
24import java.util.concurrent.TimeoutException;
25 
26/**
27 * Tests for certain edge cases related to integrating with the Android view system.
28 */
29public class AndroidViewIntegrationTest extends AwTestBase {
30    final int CONTENT_SIZE_CHANGE_STABILITY_TIMEOUT_MS = 1000;
31 
32    private static class OnContentSizeChangedHelper extends CallbackHelper {
33        private int mWidth;
34        private int mHeight;
35 
36        public int getWidth() {
37            assert(getCallCount() > 0);
38            return mWidth;
39        }
40 
41        public int getHeight() {
42            assert(getCallCount() > 0);
43            return mHeight;
44        }
45 
46        public void onContentSizeChanged(int widthCss, int heightCss) {
47            mWidth = widthCss;
48            mHeight = heightCss;
49            notifyCalled();
50        }
51    }
52 
53    private OnContentSizeChangedHelper mOnContentSizeChangedHelper =
54        new OnContentSizeChangedHelper();
55    private CallbackHelper mOnPageScaleChangedHelper = new CallbackHelper();
56 
57    private class TestAwLayoutSizer extends AwLayoutSizer {
58        @Override
59        public void onContentSizeChanged(int widthCss, int heightCss) {
60            super.onContentSizeChanged(widthCss, heightCss);
61            mOnContentSizeChangedHelper.onContentSizeChanged(widthCss, heightCss);
62        }
63 
64        @Override
65        public void onPageScaleChanged(double pageScaleFactor) {
66            super.onPageScaleChanged(pageScaleFactor);
67            mOnPageScaleChangedHelper.notifyCalled();
68        }
69    }
70 
71    @Override
72    protected TestDependencyFactory createTestDependencyFactory() {
73        return new TestDependencyFactory() {
74            @Override
75            public AwLayoutSizer createLayoutSizer() {
76                return new TestAwLayoutSizer();
77            }
78        };
79    }
80 
81    final LinearLayout.LayoutParams wrapContentLayoutParams =
82        new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
83 
84    private AwTestContainerView createCustomTestContainerViewOnMainSync(
85            final AwContentsClient awContentsClient, final int visibility) throws Exception {
86        final AtomicReference<AwTestContainerView> testContainerView =
87                new AtomicReference<AwTestContainerView>();
88        getInstrumentation().runOnMainSync(new Runnable() {
89            @Override
90            public void run() {
91                testContainerView.set(createAwTestContainerView(awContentsClient));
92                testContainerView.get().setLayoutParams(wrapContentLayoutParams);
93                testContainerView.get().setVisibility(visibility);
94            }
95        });
96        return testContainerView.get();
97    }
98 
99    private AwTestContainerView createDetachedTestContainerViewOnMainSync(
100            final AwContentsClient awContentsClient) {
101        final AtomicReference<AwTestContainerView> testContainerView =
102                new AtomicReference<AwTestContainerView>();
103        getInstrumentation().runOnMainSync(new Runnable() {
104            @Override
105            public void run() {
106                testContainerView.set(createDetachedAwTestContainerView(awContentsClient));
107            }
108        });
109        return testContainerView.get();
110    }
111 
112    private void assertZeroHeight(final AwTestContainerView testContainerView) throws Throwable {
113        // Make sure the test isn't broken by the view having a non-zero height.
114        getInstrumentation().runOnMainSync(new Runnable() {
115            @Override
116            public void run() {
117                assertEquals(0, testContainerView.getHeight());
118            }
119        });
120    }
121 
122    private int getRootLayoutWidthOnMainThread() throws Exception {
123        final AtomicReference<Integer> width = new AtomicReference<Integer>();
124        getInstrumentation().runOnMainSync(new Runnable() {
125            @Override
126            public void run() {
127                width.set(Integer.valueOf(getActivity().getRootLayoutWidth()));
128            }
129        });
130        return width.get();
131    }
132 
133    /**
134     * This checks for issues related to loading content into a 0x0 view.
135     *
136     * A 0x0 sized view is common if the WebView is set to wrap_content and newly created. The
137     * expected behavior is for the WebView to expand after some content is loaded.
138     * In Chromium it would be valid to not load or render content into a WebContents with a 0x0
139     * view (since the user can't see it anyway) and only do so after the view's size is non-zero.
140     * Such behavior is unacceptable for the WebView and this test is to ensure that such behavior
141     * is not re-introduced.
142     */
143    @SmallTest
144    @Feature({"AndroidWebView"})
145    public void testZeroByZeroViewLoadsContent() throws Throwable {
146        final TestAwContentsClient contentsClient = new TestAwContentsClient();
147        final AwTestContainerView testContainerView = createCustomTestContainerViewOnMainSync(
148                contentsClient, View.VISIBLE);
149        assertZeroHeight(testContainerView);
150 
151        final int contentSizeChangeCallCount = mOnContentSizeChangedHelper.getCallCount();
152        final int pageScaleChangeCallCount = mOnPageScaleChangedHelper.getCallCount();
153        loadUrlAsync(testContainerView.getAwContents(), CommonResources.ABOUT_HTML);
154        mOnPageScaleChangedHelper.waitForCallback(pageScaleChangeCallCount);
155        mOnContentSizeChangedHelper.waitForCallback(contentSizeChangeCallCount);
156        assertTrue(mOnContentSizeChangedHelper.getHeight() > 0);
157    }
158 
159    /**
160     * Check that a content size change notification is issued when the view is invisible.
161     *
162     * This makes sure that any optimizations related to the view's visibility don't inhibit
163     * the ability to load pages. Many applications keep the WebView hidden when it's loading.
164     */
165    @SmallTest
166    @Feature({"AndroidWebView"})
167    public void testInvisibleViewLoadsContent() throws Throwable {
168        final TestAwContentsClient contentsClient = new TestAwContentsClient();
169        final AwTestContainerView testContainerView = createCustomTestContainerViewOnMainSync(
170                contentsClient, View.INVISIBLE);
171        assertZeroHeight(testContainerView);
172 
173        final int contentSizeChangeCallCount = mOnContentSizeChangedHelper.getCallCount();
174        final int pageScaleChangeCallCount = mOnPageScaleChangedHelper.getCallCount();
175        loadUrlAsync(testContainerView.getAwContents(), CommonResources.ABOUT_HTML);
176        mOnPageScaleChangedHelper.waitForCallback(pageScaleChangeCallCount);
177        mOnContentSizeChangedHelper.waitForCallback(contentSizeChangeCallCount);
178        assertTrue(mOnContentSizeChangedHelper.getHeight() > 0);
179 
180        getInstrumentation().runOnMainSync(new Runnable() {
181            @Override
182            public void run() {
183                assertEquals(View.INVISIBLE, testContainerView.getVisibility());
184            }
185        });
186    }
187 
188    /**
189     * Check that a content size change notification is sent even if the WebView is off screen.
190     */
191    @SmallTest
192    @Feature({"AndroidWebView"})
193    public void testDisconnectedViewLoadsContent() throws Throwable {
194        final TestAwContentsClient contentsClient = new TestAwContentsClient();
195        final AwTestContainerView testContainerView =
196            createDetachedTestContainerViewOnMainSync(contentsClient);
197        assertZeroHeight(testContainerView);
198 
199        final int contentSizeChangeCallCount = mOnContentSizeChangedHelper.getCallCount();
200        final int pageScaleChangeCallCount = mOnPageScaleChangedHelper.getCallCount();
201        loadUrlAsync(testContainerView.getAwContents(), CommonResources.ABOUT_HTML);
202        mOnPageScaleChangedHelper.waitForCallback(pageScaleChangeCallCount);
203        mOnContentSizeChangedHelper.waitForCallback(contentSizeChangeCallCount);
204        assertTrue(mOnContentSizeChangedHelper.getHeight() > 0);
205    }
206 
207    private String makeHtmlPageOfSize(int widthCss, int heightCss) {
208        return CommonResources.makeHtmlPageFrom(
209            "<style type=\"text/css\">" +
210                "body { margin:0px; padding:0px; } " +
211                "div { " +
212                   "width:" + widthCss + "px; " +
213                   "height:" + heightCss + "px; " +
214                   "background-color: red; " +
215                 "} " +
216            "</style>", "<div/>");
217    }
218 
219    private void waitForContentSizeToChangeTo(OnContentSizeChangedHelper helper, int callCount,
220            int widthCss, int heightCss) throws Exception {
221        final int maxSizeChangeNotificationsToWaitFor = 5;
222        for (int i = 1; i <= maxSizeChangeNotificationsToWaitFor; i++) {
223            helper.waitForCallback(callCount, i);
224            if ((heightCss == -1 || helper.getHeight() == heightCss) &&
225                    (widthCss == -1 || helper.getWidth() == widthCss)) {
226                break;
227            }
228            // This means that we hit the max number of iterations but the expected contents size
229            // wasn't reached.
230            assertTrue(i != maxSizeChangeNotificationsToWaitFor);
231        }
232    }
233 
234    private void loadPageOfSizeAndWaitForSizeChange(AwContents awContents,
235            OnContentSizeChangedHelper helper, int widthCss, int heightCss) throws Exception {
236 
237        final String htmlData = makeHtmlPageOfSize(widthCss, heightCss);
238        final int contentSizeChangeCallCount = helper.getCallCount();
239        loadDataAsync(awContents, htmlData, "text/html", false);
240 
241        waitForContentSizeToChangeTo(helper, contentSizeChangeCallCount, widthCss, heightCss);
242    }
243 
244    @SmallTest
245    @Feature({"AndroidWebView"})
246    public void testPreferredSizeUpdateWhenDetached() throws Throwable {
247        final TestAwContentsClient contentsClient = new TestAwContentsClient();
248        final AwTestContainerView testContainerView = createDetachedTestContainerViewOnMainSync(
249                contentsClient);
250        assertZeroHeight(testContainerView);
251 
252        final int contentWidthCss = 142;
253        final int contentHeightCss = 180;
254 
255        loadPageOfSizeAndWaitForSizeChange(testContainerView.getAwContents(),
256                mOnContentSizeChangedHelper, contentWidthCss, contentHeightCss);
257    }
258 
259    @SmallTest
260    @Feature({"AndroidWebView"})
261    public void testViewSizedCorrectlyInWrapContentMode() throws Throwable {
262        final TestAwContentsClient contentsClient = new TestAwContentsClient();
263        final AwTestContainerView testContainerView = createCustomTestContainerViewOnMainSync(
264                contentsClient, View.VISIBLE);
265        assertZeroHeight(testContainerView);
266 
267        final double deviceDIPScale =
268            DeviceDisplayInfo.create(testContainerView.getContext()).getDIPScale();
269 
270        final int contentWidthCss = 142;
271        final int contentHeightCss = 180;
272 
273        // In wrap-content mode the AwLayoutSizer will size the view to be as wide as the parent
274        // view.
275        final int expectedWidthCss = (int) (getRootLayoutWidthOnMainThread() / deviceDIPScale);
276        final int expectedHeightCss = contentHeightCss;
277 
278        loadPageOfSizeAndWaitForSizeChange(testContainerView.getAwContents(),
279                mOnContentSizeChangedHelper, expectedWidthCss, expectedHeightCss);
280 
281        // This is to make sure that there are no more pending size change notifications. Ideally
282        // we'd assert that the renderer is idle (has no pending layout passes) but that would
283        // require quite a bit of plumbing, so we just wait a bit and make sure the size hadn't
284        // changed.
285        Thread.sleep(CONTENT_SIZE_CHANGE_STABILITY_TIMEOUT_MS);
286        assertEquals(expectedWidthCss, mOnContentSizeChangedHelper.getWidth());
287        assertEquals(expectedHeightCss, mOnContentSizeChangedHelper.getHeight());
288    }
289}

[all classes][org.chromium.android_webview.test]
EMMA 2.0.5312 (C) Vladimir Roubtsov