OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser; | 5 package org.chromium.chrome.browser; |
6 | 6 |
7 import android.graphics.Rect; | 7 import android.graphics.Rect; |
8 import android.support.test.filters.MediumTest; | 8 import android.support.test.filters.MediumTest; |
9 import android.test.MoreAsserts; | 9 import android.test.MoreAsserts; |
10 | 10 |
| 11 import org.junit.Assert; |
| 12 import org.junit.Rule; |
| 13 import org.junit.Test; |
| 14 import org.junit.runner.RunWith; |
| 15 |
11 import org.chromium.base.ThreadUtils; | 16 import org.chromium.base.ThreadUtils; |
12 import org.chromium.base.test.util.CommandLineFlags; | 17 import org.chromium.base.test.util.CommandLineFlags; |
13 import org.chromium.base.test.util.RetryOnFailure; | 18 import org.chromium.base.test.util.RetryOnFailure; |
14 import org.chromium.base.test.util.UrlUtils; | 19 import org.chromium.base.test.util.UrlUtils; |
15 import org.chromium.chrome.test.ChromeActivityTestCaseBase; | 20 import org.chromium.chrome.test.ChromeActivityTestRule; |
| 21 import org.chromium.chrome.test.ChromeJUnit4ClassRunner; |
16 import org.chromium.content.browser.ContentViewCore; | 22 import org.chromium.content.browser.ContentViewCore; |
17 import org.chromium.content.browser.test.util.Criteria; | 23 import org.chromium.content.browser.test.util.Criteria; |
18 import org.chromium.content.browser.test.util.CriteriaHelper; | 24 import org.chromium.content.browser.test.util.CriteriaHelper; |
19 import org.chromium.content.browser.test.util.DOMUtils; | 25 import org.chromium.content.browser.test.util.DOMUtils; |
20 import org.chromium.content.browser.test.util.JavaScriptUtils; | 26 import org.chromium.content.browser.test.util.JavaScriptUtils; |
21 import org.chromium.content_public.browser.WebContents; | 27 import org.chromium.content_public.browser.WebContents; |
22 import org.chromium.ui.UiUtils; | 28 import org.chromium.ui.UiUtils; |
23 | 29 |
24 import java.util.Locale; | 30 import java.util.Locale; |
25 import java.util.concurrent.ExecutionException; | 31 import java.util.concurrent.ExecutionException; |
26 import java.util.concurrent.TimeoutException; | 32 import java.util.concurrent.TimeoutException; |
27 import java.util.concurrent.atomic.AtomicReference; | 33 import java.util.concurrent.atomic.AtomicReference; |
28 | 34 |
29 | 35 |
30 /** | 36 /** |
31 * Integration test to ensure that OSK resizes only the visual viewport. | 37 * Integration test to ensure that OSK resizes only the visual viewport. |
32 */ | 38 */ |
33 | 39 |
34 public class OSKOverscrollTest extends ChromeActivityTestCaseBase<ChromeActivity
> { | 40 @RunWith(ChromeJUnit4ClassRunner.class) |
| 41 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, |
| 42 ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG}) |
| 43 public class OSKOverscrollTest { |
| 44 @Rule |
| 45 public ChromeActivityTestRule<ChromeActivity> mActivityTestRule = |
| 46 new ChromeActivityTestRule<>(ChromeActivity.class); |
| 47 |
35 private static final String FIXED_FOOTER_PAGE = UrlUtils.encodeHtmlDataUri("
" | 48 private static final String FIXED_FOOTER_PAGE = UrlUtils.encodeHtmlDataUri("
" |
36 + "<html>" | 49 + "<html>" |
37 + "<head>" | 50 + "<head>" |
38 + " <meta name=\"viewport\" " | 51 + " <meta name=\"viewport\" " |
39 + " content=\"width=device-width, initial-scale=1.0, maximum-scal
e=1.0\" />" | 52 + " content=\"width=device-width, initial-scale=1.0, maximum-scal
e=1.0\" />" |
40 + " <style>" | 53 + " <style>" |
41 + " body {" | 54 + " body {" |
42 + " height:1500px;" | 55 + " height:1500px;" |
43 + " margin:0px;" | 56 + " margin:0px;" |
44 + " }" | 57 + " }" |
(...skipping 13 matching lines...) Expand all Loading... |
58 + " <div id=\"footer\"></div>" | 71 + " <div id=\"footer\"></div>" |
59 + " </form>" | 72 + " </form>" |
60 + "</body>" | 73 + "</body>" |
61 + "</html>"); | 74 + "</html>"); |
62 | 75 |
63 // We convert CSS pixels into device pixels and compare the viewport size be
fore and after the | 76 // We convert CSS pixels into device pixels and compare the viewport size be
fore and after the |
64 // keyboard show. window.innerHeight returns an integer and the actual heigh
t is a floating | 77 // keyboard show. window.innerHeight returns an integer and the actual heigh
t is a floating |
65 // point. Need some buffer for error. | 78 // point. Need some buffer for error. |
66 private static final int ERROR_EPS_PIX = 1; | 79 private static final int ERROR_EPS_PIX = 1; |
67 | 80 |
68 public OSKOverscrollTest() { | |
69 super(ChromeActivity.class); | |
70 } | |
71 | |
72 @Override | |
73 public void startMainActivity() { | |
74 // Don't launch activity automatically. | |
75 } | |
76 | |
77 private void waitForKeyboard() { | 81 private void waitForKeyboard() { |
78 // Wait until the keyboard is showing. | 82 // Wait until the keyboard is showing. |
79 CriteriaHelper.pollUiThread(new Criteria("Keyboard was never shown.") { | 83 CriteriaHelper.pollUiThread(new Criteria("Keyboard was never shown.") { |
80 @Override | 84 @Override |
81 public boolean isSatisfied() { | 85 public boolean isSatisfied() { |
82 return UiUtils.isKeyboardShowing( | 86 return UiUtils.isKeyboardShowing(mActivityTestRule.getActivity()
, |
83 getActivity(), | 87 mActivityTestRule.getActivity() |
84 getActivity().getCurrentContentViewCore().getContainerVi
ew()); | 88 .getCurrentContentViewCore() |
| 89 .getContainerView()); |
85 } | 90 } |
86 }); | 91 }); |
87 } | 92 } |
88 | 93 |
89 private int getViewportHeight(WebContents webContents) { | 94 private int getViewportHeight(WebContents webContents) { |
90 try { | 95 try { |
91 String jsonText = JavaScriptUtils.executeJavaScriptAndWaitForResult( | 96 String jsonText = JavaScriptUtils.executeJavaScriptAndWaitForResult( |
92 webContents, "window.innerHeight"); | 97 webContents, "window.innerHeight"); |
93 MoreAsserts.assertNotEqual(jsonText.trim().toLowerCase(Locale.US), "
null"); | 98 MoreAsserts.assertNotEqual(jsonText.trim().toLowerCase(Locale.US), "
null"); |
94 return Integer.parseInt(jsonText); | 99 return Integer.parseInt(jsonText); |
95 } catch (Exception ex) { | 100 } catch (Exception ex) { |
96 fail(ex.toString()); | 101 Assert.fail(ex.toString()); |
97 } | 102 } |
98 return -1; | 103 return -1; |
99 } | 104 } |
100 | 105 |
101 private boolean almostEqual(int a, int b) { | 106 private boolean almostEqual(int a, int b) { |
102 return Math.abs(a - b) <= ERROR_EPS_PIX; | 107 return Math.abs(a - b) <= ERROR_EPS_PIX; |
103 } | 108 } |
104 | 109 |
105 /** | 110 /** |
106 * Verify that OSK show only resizes the visual viewport when the ENABLE_OSK
_OVERSCROLL flag is | 111 * Verify that OSK show only resizes the visual viewport when the ENABLE_OSK
_OVERSCROLL flag is |
107 * set. | 112 * set. |
108 * @throws InterruptedException | 113 * @throws InterruptedException |
109 * @throws TimeoutException | 114 * @throws TimeoutException |
110 * @throws ExecutionException | 115 * @throws ExecutionException |
111 */ | 116 */ |
| 117 @Test |
112 @MediumTest | 118 @MediumTest |
113 @CommandLineFlags.Add({ChromeSwitches.ENABLE_OSK_OVERSCROLL}) | 119 @CommandLineFlags.Add({ChromeSwitches.ENABLE_OSK_OVERSCROLL}) |
114 @RetryOnFailure | 120 @RetryOnFailure |
115 public void testOnlyVisualViewportResizes() | 121 public void testOnlyVisualViewportResizes() |
116 throws InterruptedException, TimeoutException, ExecutionException { | 122 throws InterruptedException, TimeoutException, ExecutionException { |
117 startMainActivityWithURL(FIXED_FOOTER_PAGE); | 123 mActivityTestRule.startMainActivityWithURL(FIXED_FOOTER_PAGE); |
118 | 124 |
119 final AtomicReference<ContentViewCore> viewCoreRef = new AtomicReference
<ContentViewCore>(); | 125 final AtomicReference<ContentViewCore> viewCoreRef = new AtomicReference
<ContentViewCore>(); |
120 final AtomicReference<WebContents> webContentsRef = new AtomicReference<
WebContents>(); | 126 final AtomicReference<WebContents> webContentsRef = new AtomicReference<
WebContents>(); |
121 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | 127 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
122 @Override | 128 @Override |
123 public void run() { | 129 public void run() { |
124 viewCoreRef.set(getActivity().getCurrentContentViewCore()); | 130 viewCoreRef.set(mActivityTestRule.getActivity().getCurrentConten
tViewCore()); |
125 webContentsRef.set(viewCoreRef.get().getWebContents()); | 131 webContentsRef.set(viewCoreRef.get().getWebContents()); |
126 } | 132 } |
127 }); | 133 }); |
128 | 134 |
129 DOMUtils.waitForNonZeroNodeBounds(webContentsRef.get(), "fn"); | 135 DOMUtils.waitForNonZeroNodeBounds(webContentsRef.get(), "fn"); |
130 | 136 |
131 // Get the position of the footer and the viewport height before bringin
g up the OSK. | 137 // Get the position of the footer and the viewport height before bringin
g up the OSK. |
132 Rect footerPositionBefore = DOMUtils.getNodeBounds(webContentsRef.get(),
"footer"); | 138 Rect footerPositionBefore = DOMUtils.getNodeBounds(webContentsRef.get(),
"footer"); |
133 final int viewportHeightBeforeCss = getViewportHeight(webContentsRef.get
()); | 139 final int viewportHeightBeforeCss = getViewportHeight(webContentsRef.get
()); |
134 final float cssToDevicePixFactor = viewCoreRef.get().getPageScaleFactor(
) | 140 final float cssToDevicePixFactor = viewCoreRef.get().getPageScaleFactor(
) |
135 * viewCoreRef.get().getDeviceScaleFactor(); | 141 * viewCoreRef.get().getDeviceScaleFactor(); |
136 | 142 |
137 // Click on the unfocused input element for the first time to focus on i
t. This brings up | 143 // Click on the unfocused input element for the first time to focus on i
t. This brings up |
138 // the OSK. | 144 // the OSK. |
139 DOMUtils.clickNode(viewCoreRef.get(), "fn"); | 145 DOMUtils.clickNode(viewCoreRef.get(), "fn"); |
140 | 146 |
141 waitForKeyboard(); | 147 waitForKeyboard(); |
142 | 148 |
143 // Get the position of the footer after bringing up the OSK. This should
be the same as the | 149 // Get the position of the footer after bringing up the OSK. This should
be the same as the |
144 // position before because only the visual viewport should have resized. | 150 // position before because only the visual viewport should have resized. |
145 Rect footerPositionAfter = DOMUtils.getNodeBounds(webContentsRef.get(),
"footer"); | 151 Rect footerPositionAfter = DOMUtils.getNodeBounds(webContentsRef.get(),
"footer"); |
146 assertEquals(footerPositionBefore, footerPositionAfter); | 152 Assert.assertEquals(footerPositionBefore, footerPositionAfter); |
147 | 153 |
148 CriteriaHelper.pollInstrumentationThread(new Criteria() { | 154 CriteriaHelper.pollInstrumentationThread(new Criteria() { |
149 @Override | 155 @Override |
150 public boolean isSatisfied() { | 156 public boolean isSatisfied() { |
151 // Verify that the size of the viewport before the OSK show is e
qual to the size of | 157 // Verify that the size of the viewport before the OSK show is e
qual to the size of |
152 // the viewport after the OSK show plus the size of the keyboard
. | 158 // the viewport after the OSK show plus the size of the keyboard
. |
153 int viewportHeightAfterCss = getViewportHeight(webContentsRef.ge
t()); | 159 int viewportHeightAfterCss = getViewportHeight(webContentsRef.ge
t()); |
154 int keyboardHeight = getActivity().getActivityTab().getSystemWin
dowInsetBottom(); | 160 int keyboardHeight = mActivityTestRule.getActivity() |
| 161 .getActivityTab() |
| 162 .getSystemWindowInsetBottom(); |
155 | 163 |
156 int priorHeight = (int) (viewportHeightBeforeCss * cssToDevicePi
xFactor); | 164 int priorHeight = (int) (viewportHeightBeforeCss * cssToDevicePi
xFactor); |
157 int afterHeightPlusKeyboard = | 165 int afterHeightPlusKeyboard = |
158 (int) (viewportHeightAfterCss * cssToDevicePixFactor) +
keyboardHeight; | 166 (int) (viewportHeightAfterCss * cssToDevicePixFactor) +
keyboardHeight; |
159 updateFailureReason("Values [" + priorHeight + "], [" + afterHei
ghtPlusKeyboard | 167 updateFailureReason("Values [" + priorHeight + "], [" + afterHei
ghtPlusKeyboard |
160 + "] did not match within allowed error range [" + ERROR
_EPS_PIX + "]"); | 168 + "] did not match within allowed error range [" + ERROR
_EPS_PIX + "]"); |
161 return almostEqual(priorHeight, afterHeightPlusKeyboard); | 169 return almostEqual(priorHeight, afterHeightPlusKeyboard); |
162 } | 170 } |
163 }); | 171 }); |
164 } | 172 } |
165 } | 173 } |
OLD | NEW |