OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 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.android_webview.test; | 5 package org.chromium.android_webview.test; |
6 | 6 |
| 7 import static org.chromium.android_webview.test.AwTestCommon.WAIT_TIMEOUT_MS; |
| 8 |
7 import android.content.Context; | 9 import android.content.Context; |
8 import android.graphics.Bitmap; | 10 import android.graphics.Bitmap; |
9 import android.graphics.BitmapFactory; | 11 import android.graphics.BitmapFactory; |
10 import android.graphics.Canvas; | 12 import android.graphics.Canvas; |
11 import android.os.Handler; | 13 import android.os.Handler; |
12 import android.os.Looper; | 14 import android.os.Looper; |
13 import android.os.Message; | 15 import android.os.Message; |
| 16 import android.support.test.InstrumentationRegistry; |
14 import android.support.test.filters.LargeTest; | 17 import android.support.test.filters.LargeTest; |
15 import android.support.test.filters.SmallTest; | 18 import android.support.test.filters.SmallTest; |
16 import android.test.UiThreadTest; | |
17 import android.util.Pair; | 19 import android.util.Pair; |
18 import android.view.KeyEvent; | 20 import android.view.KeyEvent; |
19 import android.view.View; | 21 import android.view.View; |
20 import android.webkit.JavascriptInterface; | 22 import android.webkit.JavascriptInterface; |
21 | 23 |
| 24 import org.junit.Assert; |
| 25 import org.junit.Rule; |
| 26 import org.junit.Test; |
| 27 import org.junit.runner.RunWith; |
| 28 |
22 import org.chromium.android_webview.AwContents; | 29 import org.chromium.android_webview.AwContents; |
23 import org.chromium.android_webview.AwSettings; | 30 import org.chromium.android_webview.AwSettings; |
24 import org.chromium.android_webview.AwSwitches; | 31 import org.chromium.android_webview.AwSwitches; |
25 import org.chromium.android_webview.renderer_priority.RendererPriority; | 32 import org.chromium.android_webview.renderer_priority.RendererPriority; |
26 import org.chromium.android_webview.test.TestAwContentsClient.OnDownloadStartHel
per; | 33 import org.chromium.android_webview.test.TestAwContentsClient.OnDownloadStartHel
per; |
27 import org.chromium.android_webview.test.util.CommonResources; | 34 import org.chromium.android_webview.test.util.CommonResources; |
28 import org.chromium.android_webview.test.util.JSUtils; | 35 import org.chromium.android_webview.test.util.JSUtils; |
29 import org.chromium.base.annotations.SuppressFBWarnings; | 36 import org.chromium.base.annotations.SuppressFBWarnings; |
30 import org.chromium.base.process_launcher.ChildProcessConnection; | 37 import org.chromium.base.process_launcher.ChildProcessConnection; |
31 import org.chromium.base.test.util.CallbackHelper; | 38 import org.chromium.base.test.util.CallbackHelper; |
(...skipping 13 matching lines...) Expand all Loading... |
45 import java.util.List; | 52 import java.util.List; |
46 import java.util.Map; | 53 import java.util.Map; |
47 import java.util.concurrent.Callable; | 54 import java.util.concurrent.Callable; |
48 import java.util.concurrent.Semaphore; | 55 import java.util.concurrent.Semaphore; |
49 import java.util.concurrent.TimeUnit; | 56 import java.util.concurrent.TimeUnit; |
50 import java.util.concurrent.atomic.AtomicInteger; | 57 import java.util.concurrent.atomic.AtomicInteger; |
51 | 58 |
52 /** | 59 /** |
53 * AwContents tests. | 60 * AwContents tests. |
54 */ | 61 */ |
55 public class AwContentsTest extends AwTestBase { | 62 @RunWith(AwJUnit4ClassRunner.class) |
| 63 public class AwContentsTest { |
| 64 @Rule |
| 65 public AwActivityTestRule mActivityTestRule = new AwActivityTestRule(); |
56 | 66 |
57 private TestAwContentsClient mContentsClient = new TestAwContentsClient(); | 67 private TestAwContentsClient mContentsClient = new TestAwContentsClient(); |
58 | 68 |
| 69 @Test |
59 @SmallTest | 70 @SmallTest |
60 @Feature({"AndroidWebView"}) | 71 @Feature({"AndroidWebView"}) |
61 @UiThreadTest | |
62 public void testCreateDestroy() throws Throwable { | 72 public void testCreateDestroy() throws Throwable { |
63 // NOTE this test runs on UI thread, so we cannot call any async methods
. | 73 // NOTE this test runs on UI thread, so we cannot call any async methods
. |
64 createAwTestContainerView(mContentsClient).getAwContents().destroy(); | 74 mActivityTestRule.runOnUiThread(new Runnable() { |
| 75 @Override |
| 76 public void run() { |
| 77 mActivityTestRule.createAwTestContainerView(mContentsClient) |
| 78 .getAwContents() |
| 79 .destroy(); |
| 80 } |
| 81 }); |
65 } | 82 } |
66 | 83 |
| 84 @Test |
67 @SmallTest | 85 @SmallTest |
68 @Feature({"AndroidWebView"}) | 86 @Feature({"AndroidWebView"}) |
69 public void testCreateLoadPageDestroy() throws Throwable { | 87 public void testCreateLoadPageDestroy() throws Throwable { |
70 AwTestContainerView awTestContainerView = | 88 AwTestContainerView awTestContainerView = |
71 createAwTestContainerViewOnMainSync(mContentsClient); | 89 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
72 loadDataSync(awTestContainerView.getAwContents(), mContentsClient.getOnP
ageFinishedHelper(), | 90 mActivityTestRule.loadDataSync(awTestContainerView.getAwContents(), |
73 CommonResources.ABOUT_HTML, "text/html", false); | 91 mContentsClient.getOnPageFinishedHelper(), CommonResources.ABOUT
_HTML, "text/html", |
| 92 false); |
74 | 93 |
75 destroyAwContentsOnMainSync(awTestContainerView.getAwContents()); | 94 mActivityTestRule.destroyAwContentsOnMainSync(awTestContainerView.getAwC
ontents()); |
76 // It should be safe to call destroy multiple times. | 95 // It should be safe to call destroy multiple times. |
77 destroyAwContentsOnMainSync(awTestContainerView.getAwContents()); | 96 mActivityTestRule.destroyAwContentsOnMainSync(awTestContainerView.getAwC
ontents()); |
78 } | 97 } |
79 | 98 |
| 99 @Test |
80 @LargeTest | 100 @LargeTest |
81 @Feature({"AndroidWebView"}) | 101 @Feature({"AndroidWebView"}) |
82 public void testCreateLoadDestroyManyTimes() throws Throwable { | 102 public void testCreateLoadDestroyManyTimes() throws Throwable { |
83 for (int i = 0; i < 10; ++i) { | 103 for (int i = 0; i < 10; ++i) { |
84 AwTestContainerView testView = createAwTestContainerViewOnMainSync(m
ContentsClient); | 104 AwTestContainerView testView = |
| 105 mActivityTestRule.createAwTestContainerViewOnMainSync(mConte
ntsClient); |
85 AwContents awContents = testView.getAwContents(); | 106 AwContents awContents = testView.getAwContents(); |
86 | 107 |
87 loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), | 108 mActivityTestRule.loadUrlSync(awContents, mContentsClient.getOnPageF
inishedHelper(), |
88 ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); | 109 ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); |
89 destroyAwContentsOnMainSync(awContents); | 110 mActivityTestRule.destroyAwContentsOnMainSync(awContents); |
90 } | 111 } |
91 } | 112 } |
92 | 113 |
| 114 @Test |
93 @LargeTest | 115 @LargeTest |
94 @Feature({"AndroidWebView"}) | 116 @Feature({"AndroidWebView"}) |
95 public void testCreateLoadDestroyManyAtOnce() throws Throwable { | 117 public void testCreateLoadDestroyManyAtOnce() throws Throwable { |
96 AwTestContainerView views[] = new AwTestContainerView[10]; | 118 AwTestContainerView views[] = new AwTestContainerView[10]; |
97 | 119 |
98 for (int i = 0; i < views.length; ++i) { | 120 for (int i = 0; i < views.length; ++i) { |
99 views[i] = createAwTestContainerViewOnMainSync(mContentsClient); | 121 views[i] = mActivityTestRule.createAwTestContainerViewOnMainSync(mCo
ntentsClient); |
100 loadUrlSync(views[i].getAwContents(), mContentsClient.getOnPageFinis
hedHelper(), | 122 mActivityTestRule.loadUrlSync(views[i].getAwContents(), |
| 123 mContentsClient.getOnPageFinishedHelper(), |
101 ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); | 124 ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); |
102 } | 125 } |
103 | 126 |
104 for (int i = 0; i < views.length; ++i) { | 127 for (int i = 0; i < views.length; ++i) { |
105 destroyAwContentsOnMainSync(views[i].getAwContents()); | 128 mActivityTestRule.destroyAwContentsOnMainSync(views[i].getAwContents
()); |
106 views[i] = null; | 129 views[i] = null; |
107 } | 130 } |
108 } | 131 } |
109 | 132 |
| 133 @Test |
110 @SmallTest | 134 @SmallTest |
111 @Feature({"AndroidWebView"}) | 135 @Feature({"AndroidWebView"}) |
112 @UiThreadTest | |
113 public void testWebViewApisFailGracefullyAfterDestruction() throws Throwable
{ | 136 public void testWebViewApisFailGracefullyAfterDestruction() throws Throwable
{ |
114 AwContents awContents = | 137 mActivityTestRule.runOnUiThread(new Runnable() { |
115 createAwTestContainerView(mContentsClient).getAwContents(); | 138 @Override |
116 awContents.destroy(); | 139 public void run() { |
| 140 AwContents awContents = mActivityTestRule.createAwTestContainerV
iew(mContentsClient) |
| 141 .getAwContents(); |
| 142 awContents.destroy(); |
117 | 143 |
118 // The documentation for WebView#destroy() reads "This method should be
called | 144 // The documentation for WebView#destroy() reads "This method sh
ould be called |
119 // after this WebView has been removed from the view system. No other me
thods | 145 // after this WebView has been removed from the view system. No
other methods |
120 // may be called on this WebView after destroy". | 146 // may be called on this WebView after destroy". |
121 // However, some apps do not respect that restriction so we need to ensu
re that | 147 // However, some apps do not respect that restriction so we need
to ensure that |
122 // we fail gracefully and do not crash when APIs are invoked after destr
uction. | 148 // we fail gracefully and do not crash when APIs are invoked aft
er destruction. |
123 // Due to the large number of APIs we only test a representative selecti
on here. | 149 // Due to the large number of APIs we only test a representative
selection here. |
124 awContents.clearHistory(); | 150 awContents.clearHistory(); |
125 awContents.loadUrl("http://www.google.com"); | 151 awContents.loadUrl("http://www.google.com"); |
126 awContents.findAllAsync("search"); | 152 awContents.findAllAsync("search"); |
127 assertNull(awContents.getUrl()); | 153 Assert.assertNull(awContents.getUrl()); |
128 assertFalse(awContents.canGoBack()); | 154 Assert.assertFalse(awContents.canGoBack()); |
129 awContents.disableJavascriptInterfacesInspection(); | 155 awContents.disableJavascriptInterfacesInspection(); |
130 awContents.invokeZoomPicker(); | 156 awContents.invokeZoomPicker(); |
131 awContents.onResume(); | 157 awContents.onResume(); |
132 awContents.stopLoading(); | 158 awContents.stopLoading(); |
133 awContents.onWindowVisibilityChanged(View.VISIBLE); | 159 awContents.onWindowVisibilityChanged(View.VISIBLE); |
134 awContents.requestFocus(); | 160 awContents.requestFocus(); |
135 awContents.isMultiTouchZoomSupported(); | 161 awContents.isMultiTouchZoomSupported(); |
136 awContents.setOverScrollMode(View.OVER_SCROLL_NEVER); | 162 awContents.setOverScrollMode(View.OVER_SCROLL_NEVER); |
137 awContents.pauseTimers(); | 163 awContents.pauseTimers(); |
138 awContents.onContainerViewScrollChanged(200, 200, 100, 100); | 164 awContents.onContainerViewScrollChanged(200, 200, 100, 100); |
139 awContents.computeScroll(); | 165 awContents.computeScroll(); |
140 awContents.onMeasure(100, 100); | 166 awContents.onMeasure(100, 100); |
141 awContents.onDraw(new Canvas()); | 167 awContents.onDraw(new Canvas()); |
142 awContents.getMostRecentProgress(); | 168 awContents.getMostRecentProgress(); |
143 assertEquals(0, awContents.computeHorizontalScrollOffset()); | 169 Assert.assertEquals(0, awContents.computeHorizontalScrollOffset(
)); |
144 assertEquals(0, awContents.getContentWidthCss()); | 170 Assert.assertEquals(0, awContents.getContentWidthCss()); |
145 awContents.onKeyUp(KeyEvent.KEYCODE_BACK, | 171 awContents.onKeyUp(KeyEvent.KEYCODE_BACK, |
146 new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU)); | 172 new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU
)); |
| 173 } |
| 174 }); |
147 } | 175 } |
148 | 176 |
| 177 @Test |
149 @SmallTest | 178 @SmallTest |
150 @Feature({"AndroidWebView"}) | 179 @Feature({"AndroidWebView"}) |
151 public void testUseAwSettingsAfterDestroy() throws Throwable { | 180 public void testUseAwSettingsAfterDestroy() throws Throwable { |
152 AwTestContainerView awTestContainerView = | 181 AwTestContainerView awTestContainerView = |
153 createAwTestContainerViewOnMainSync(mContentsClient); | 182 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
154 AwSettings awSettings = getAwSettingsOnUiThread(awTestContainerView.getA
wContents()); | 183 AwSettings awSettings = |
155 loadDataSync(awTestContainerView.getAwContents(), mContentsClient.getOnP
ageFinishedHelper(), | 184 mActivityTestRule.getAwSettingsOnUiThread(awTestContainerView.ge
tAwContents()); |
156 CommonResources.ABOUT_HTML, "text/html", false); | 185 mActivityTestRule.loadDataSync(awTestContainerView.getAwContents(), |
157 destroyAwContentsOnMainSync(awTestContainerView.getAwContents()); | 186 mContentsClient.getOnPageFinishedHelper(), CommonResources.ABOUT
_HTML, "text/html", |
| 187 false); |
| 188 mActivityTestRule.destroyAwContentsOnMainSync(awTestContainerView.getAwC
ontents()); |
158 | 189 |
159 // AwSettings should still be usable even after native side is destroyed
. | 190 // AwSettings should still be usable even after native side is destroyed
. |
160 String newFontFamily = "serif"; | 191 String newFontFamily = "serif"; |
161 awSettings.setStandardFontFamily(newFontFamily); | 192 awSettings.setStandardFontFamily(newFontFamily); |
162 assertEquals(newFontFamily, awSettings.getStandardFontFamily()); | 193 Assert.assertEquals(newFontFamily, awSettings.getStandardFontFamily()); |
163 boolean newBlockNetworkLoads = !awSettings.getBlockNetworkLoads(); | 194 boolean newBlockNetworkLoads = !awSettings.getBlockNetworkLoads(); |
164 awSettings.setBlockNetworkLoads(newBlockNetworkLoads); | 195 awSettings.setBlockNetworkLoads(newBlockNetworkLoads); |
165 assertEquals(newBlockNetworkLoads, awSettings.getBlockNetworkLoads()); | 196 Assert.assertEquals(newBlockNetworkLoads, awSettings.getBlockNetworkLoad
s()); |
166 } | 197 } |
167 | 198 |
168 private int callDocumentHasImagesSync(final AwContents awContents) | 199 private int callDocumentHasImagesSync(final AwContents awContents) |
169 throws Throwable, InterruptedException { | 200 throws Throwable, InterruptedException { |
170 // Set up a container to hold the result object and a semaphore to | 201 // Set up a container to hold the result object and a semaphore to |
171 // make the test wait for the result. | 202 // make the test wait for the result. |
172 final AtomicInteger val = new AtomicInteger(); | 203 final AtomicInteger val = new AtomicInteger(); |
173 final Semaphore s = new Semaphore(0); | 204 final Semaphore s = new Semaphore(0); |
174 final Message msg = Message.obtain(new Handler(Looper.getMainLooper()) { | 205 final Message msg = Message.obtain(new Handler(Looper.getMainLooper()) { |
175 @Override | 206 @Override |
176 public void handleMessage(Message msg) { | 207 public void handleMessage(Message msg) { |
177 val.set(msg.arg1); | 208 val.set(msg.arg1); |
178 s.release(); | 209 s.release(); |
179 } | 210 } |
180 }); | 211 }); |
181 runTestOnUiThread(new Runnable() { | 212 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable(
) { |
182 @Override | 213 @Override |
183 public void run() { | 214 public void run() { |
184 awContents.documentHasImages(msg); | 215 awContents.documentHasImages(msg); |
185 } | 216 } |
186 }); | 217 }); |
187 assertTrue(s.tryAcquire(WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS)); | 218 Assert.assertTrue(s.tryAcquire(AwActivityTestRule.WAIT_TIMEOUT_MS, TimeU
nit.MILLISECONDS)); |
188 int result = val.get(); | 219 int result = val.get(); |
189 return result; | 220 return result; |
190 } | 221 } |
191 | 222 |
| 223 @Test |
192 @SmallTest | 224 @SmallTest |
193 @Feature({"AndroidWebView"}) | 225 @Feature({"AndroidWebView"}) |
194 public void testDocumentHasImages() throws Throwable { | 226 public void testDocumentHasImages() throws Throwable { |
195 AwTestContainerView testView = createAwTestContainerViewOnMainSync(mCont
entsClient); | 227 AwTestContainerView testView = |
| 228 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
196 AwContents awContents = testView.getAwContents(); | 229 AwContents awContents = testView.getAwContents(); |
197 | 230 |
198 final CallbackHelper loadHelper = mContentsClient.getOnPageFinishedHelpe
r(); | 231 final CallbackHelper loadHelper = mContentsClient.getOnPageFinishedHelpe
r(); |
199 | 232 |
200 final String mime = "text/html"; | 233 final String mime = "text/html"; |
201 final String emptyDoc = "<head/><body/>"; | 234 final String emptyDoc = "<head/><body/>"; |
202 final String imageDoc = "<head/><body><img/><img/></body>"; | 235 final String imageDoc = "<head/><body><img/><img/></body>"; |
203 | 236 |
204 // Make sure a document that does not have images returns 0 | 237 // Make sure a document that does not have images returns 0 |
205 loadDataSync(awContents, loadHelper, emptyDoc, mime, false); | 238 mActivityTestRule.loadDataSync(awContents, loadHelper, emptyDoc, mime, f
alse); |
206 int result = callDocumentHasImagesSync(awContents); | 239 int result = callDocumentHasImagesSync(awContents); |
207 assertEquals(0, result); | 240 Assert.assertEquals(0, result); |
208 | 241 |
209 // Make sure a document that does have images returns 1 | 242 // Make sure a document that does have images returns 1 |
210 loadDataSync(awContents, loadHelper, imageDoc, mime, false); | 243 mActivityTestRule.loadDataSync(awContents, loadHelper, imageDoc, mime, f
alse); |
211 result = callDocumentHasImagesSync(awContents); | 244 result = callDocumentHasImagesSync(awContents); |
212 assertEquals(1, result); | 245 Assert.assertEquals(1, result); |
213 } | 246 } |
214 | 247 |
| 248 @Test |
215 @SmallTest | 249 @SmallTest |
216 @Feature({"AndroidWebView"}) | 250 @Feature({"AndroidWebView"}) |
217 public void testClearCacheMemoryAndDisk() throws Throwable { | 251 public void testClearCacheMemoryAndDisk() throws Throwable { |
218 final AwTestContainerView testContainer = | 252 final AwTestContainerView testContainer = |
219 createAwTestContainerViewOnMainSync(mContentsClient); | 253 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
220 final AwContents awContents = testContainer.getAwContents(); | 254 final AwContents awContents = testContainer.getAwContents(); |
221 | 255 |
222 TestWebServer webServer = TestWebServer.start(); | 256 TestWebServer webServer = TestWebServer.start(); |
223 try { | 257 try { |
224 final String pagePath = "/clear_cache_test.html"; | 258 final String pagePath = "/clear_cache_test.html"; |
225 List<Pair<String, String>> headers = new ArrayList<Pair<String, Stri
ng>>(); | 259 List<Pair<String, String>> headers = new ArrayList<Pair<String, Stri
ng>>(); |
226 // Set Cache-Control headers to cache this request. One century shou
ld be long enough. | 260 // Set Cache-Control headers to cache this request. One century shou
ld be long enough. |
227 headers.add(Pair.create("Cache-Control", "max-age=3153600000")); | 261 headers.add(Pair.create("Cache-Control", "max-age=3153600000")); |
228 headers.add(Pair.create("Last-Modified", "Wed, 3 Oct 2012 00:00:00 G
MT")); | 262 headers.add(Pair.create("Last-Modified", "Wed, 3 Oct 2012 00:00:00 G
MT")); |
229 final String pageUrl = webServer.setResponse( | 263 final String pageUrl = webServer.setResponse( |
230 pagePath, "<html><body>foo</body></html>", headers); | 264 pagePath, "<html><body>foo</body></html>", headers); |
231 | 265 |
232 // First load to populate cache. | 266 // First load to populate cache. |
233 clearCacheOnUiThread(awContents, true); | 267 mActivityTestRule.clearCacheOnUiThread(awContents, true); |
234 loadUrlSync(awContents, | 268 mActivityTestRule.loadUrlSync( |
235 mContentsClient.getOnPageFinishedHelper(), | 269 awContents, mContentsClient.getOnPageFinishedHelper(), pageU
rl); |
236 pageUrl); | 270 Assert.assertEquals(1, webServer.getRequestCount(pagePath)); |
237 assertEquals(1, webServer.getRequestCount(pagePath)); | |
238 | 271 |
239 // Load about:blank so next load is not treated as reload by webkit
and force | 272 // Load about:blank so next load is not treated as reload by webkit
and force |
240 // revalidate with the server. | 273 // revalidate with the server. |
241 loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), | 274 mActivityTestRule.loadUrlSync(awContents, mContentsClient.getOnPageF
inishedHelper(), |
242 ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); | 275 ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); |
243 | 276 |
244 // No clearCache call, so should be loaded from cache. | 277 // No clearCache call, so should be loaded from cache. |
245 loadUrlSync(awContents, | 278 mActivityTestRule.loadUrlSync( |
246 mContentsClient.getOnPageFinishedHelper(), | 279 awContents, mContentsClient.getOnPageFinishedHelper(), pageU
rl); |
247 pageUrl); | 280 Assert.assertEquals(1, webServer.getRequestCount(pagePath)); |
248 assertEquals(1, webServer.getRequestCount(pagePath)); | |
249 | 281 |
250 // Same as above. | 282 // Same as above. |
251 loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), | 283 mActivityTestRule.loadUrlSync(awContents, mContentsClient.getOnPageF
inishedHelper(), |
252 ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); | 284 ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); |
253 | 285 |
254 // Clear cache, so should hit server again. | 286 // Clear cache, so should hit server again. |
255 clearCacheOnUiThread(awContents, true); | 287 mActivityTestRule.clearCacheOnUiThread(awContents, true); |
256 loadUrlSync(awContents, | 288 mActivityTestRule.loadUrlSync( |
257 mContentsClient.getOnPageFinishedHelper(), | 289 awContents, mContentsClient.getOnPageFinishedHelper(), pageU
rl); |
258 pageUrl); | 290 Assert.assertEquals(2, webServer.getRequestCount(pagePath)); |
259 assertEquals(2, webServer.getRequestCount(pagePath)); | |
260 } finally { | 291 } finally { |
261 webServer.shutdown(); | 292 webServer.shutdown(); |
262 } | 293 } |
263 } | 294 } |
264 | 295 |
| 296 @Test |
265 @SmallTest | 297 @SmallTest |
266 @Feature({"AndroidWebView"}) | 298 @Feature({"AndroidWebView"}) |
267 public void testClearCacheInQuickSuccession() throws Throwable { | 299 public void testClearCacheInQuickSuccession() throws Throwable { |
268 final AwTestContainerView testContainer = | 300 final AwTestContainerView testContainer = |
269 createAwTestContainerViewOnMainSync(new TestAwContentsClient()); | 301 mActivityTestRule.createAwTestContainerViewOnMainSync(new TestAw
ContentsClient()); |
270 final AwContents awContents = testContainer.getAwContents(); | 302 final AwContents awContents = testContainer.getAwContents(); |
271 | 303 |
272 runTestOnUiThread(new Runnable() { | 304 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable(
) { |
273 @Override | 305 @Override |
274 public void run() { | 306 public void run() { |
275 for (int i = 0; i < 10; ++i) { | 307 for (int i = 0; i < 10; ++i) { |
276 awContents.clearCache(true); | 308 awContents.clearCache(true); |
277 } | 309 } |
278 } | 310 } |
279 }); | 311 }); |
280 } | 312 } |
281 | 313 |
| 314 @Test |
282 @SmallTest | 315 @SmallTest |
283 @Feature({"AndroidWebView"}) | 316 @Feature({"AndroidWebView"}) |
284 public void testGetFavicon() throws Throwable { | 317 public void testGetFavicon() throws Throwable { |
285 AwContents.setShouldDownloadFavicons(); | 318 AwContents.setShouldDownloadFavicons(); |
286 final AwTestContainerView testView = createAwTestContainerViewOnMainSync
(mContentsClient); | 319 final AwTestContainerView testView = |
| 320 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
287 final AwContents awContents = testView.getAwContents(); | 321 final AwContents awContents = testView.getAwContents(); |
288 | 322 |
289 TestWebServer webServer = TestWebServer.start(); | 323 TestWebServer webServer = TestWebServer.start(); |
290 try { | 324 try { |
291 final String faviconUrl = webServer.setResponseBase64( | 325 final String faviconUrl = webServer.setResponseBase64( |
292 "/" + CommonResources.FAVICON_FILENAME, CommonResources.FAVI
CON_DATA_BASE64, | 326 "/" + CommonResources.FAVICON_FILENAME, CommonResources.FAVI
CON_DATA_BASE64, |
293 CommonResources.getImagePngHeaders(false)); | 327 CommonResources.getImagePngHeaders(false)); |
294 final String pageUrl = webServer.setResponse("/favicon.html", | 328 final String pageUrl = webServer.setResponse("/favicon.html", |
295 CommonResources.FAVICON_STATIC_HTML, null); | 329 CommonResources.FAVICON_STATIC_HTML, null); |
296 | 330 |
297 // The getFavicon will return the right icon a certain time after | 331 // The getFavicon will return the right icon a certain time after |
298 // the page load completes which makes it slightly hard to test. | 332 // the page load completes which makes it slightly hard to test. |
299 final Bitmap defaultFavicon = awContents.getFavicon(); | 333 final Bitmap defaultFavicon = awContents.getFavicon(); |
300 | 334 |
301 getAwSettingsOnUiThread(awContents).setImagesEnabled(true); | 335 mActivityTestRule.getAwSettingsOnUiThread(awContents).setImagesEnabl
ed(true); |
302 loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), p
ageUrl); | 336 mActivityTestRule.loadUrlSync( |
| 337 awContents, mContentsClient.getOnPageFinishedHelper(), pageU
rl); |
303 | 338 |
304 pollUiThread(new Callable<Boolean>() { | 339 mActivityTestRule.pollUiThread(new Callable<Boolean>() { |
305 @Override | 340 @Override |
306 public Boolean call() { | 341 public Boolean call() { |
307 return awContents.getFavicon() != null | 342 return awContents.getFavicon() != null |
308 && !awContents.getFavicon().sameAs(defaultFavicon); | 343 && !awContents.getFavicon().sameAs(defaultFavicon); |
309 } | 344 } |
310 }); | 345 }); |
311 | 346 |
312 final Object originalFaviconSource = (new URL(faviconUrl)).getConten
t(); | 347 final Object originalFaviconSource = (new URL(faviconUrl)).getConten
t(); |
313 final Bitmap originalFavicon = | 348 final Bitmap originalFavicon = |
314 BitmapFactory.decodeStream((InputStream) originalFaviconSour
ce); | 349 BitmapFactory.decodeStream((InputStream) originalFaviconSour
ce); |
315 assertNotNull(originalFavicon); | 350 Assert.assertNotNull(originalFavicon); |
316 | 351 |
317 assertTrue(awContents.getFavicon().sameAs(originalFavicon)); | 352 Assert.assertTrue(awContents.getFavicon().sameAs(originalFavicon)); |
318 | 353 |
319 } finally { | 354 } finally { |
320 webServer.shutdown(); | 355 webServer.shutdown(); |
321 } | 356 } |
322 } | 357 } |
323 | 358 |
| 359 @Test |
324 @Feature({"AndroidWebView", "Downloads"}) | 360 @Feature({"AndroidWebView", "Downloads"}) |
325 @SmallTest | 361 @SmallTest |
326 public void testDownload() throws Throwable { | 362 public void testDownload() throws Throwable { |
327 AwTestContainerView testView = createAwTestContainerViewOnMainSync(mCont
entsClient); | 363 AwTestContainerView testView = |
| 364 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
328 AwContents awContents = testView.getAwContents(); | 365 AwContents awContents = testView.getAwContents(); |
329 | 366 |
330 final String data = "download data"; | 367 final String data = "download data"; |
331 final String contentDisposition = "attachment;filename=\"download.txt\""
; | 368 final String contentDisposition = "attachment;filename=\"download.txt\""
; |
332 final String mimeType = "text/plain"; | 369 final String mimeType = "text/plain"; |
333 | 370 |
334 List<Pair<String, String>> downloadHeaders = new ArrayList<Pair<String,
String>>(); | 371 List<Pair<String, String>> downloadHeaders = new ArrayList<Pair<String,
String>>(); |
335 downloadHeaders.add(Pair.create("Content-Disposition", contentDispositio
n)); | 372 downloadHeaders.add(Pair.create("Content-Disposition", contentDispositio
n)); |
336 downloadHeaders.add(Pair.create("Content-Type", mimeType)); | 373 downloadHeaders.add(Pair.create("Content-Type", mimeType)); |
337 downloadHeaders.add(Pair.create("Content-Length", Integer.toString(data.
length()))); | 374 downloadHeaders.add(Pair.create("Content-Length", Integer.toString(data.
length()))); |
338 | 375 |
339 TestWebServer webServer = TestWebServer.start(); | 376 TestWebServer webServer = TestWebServer.start(); |
340 try { | 377 try { |
341 final String pageUrl = webServer.setResponse( | 378 final String pageUrl = webServer.setResponse( |
342 "/download.txt", data, downloadHeaders); | 379 "/download.txt", data, downloadHeaders); |
343 final OnDownloadStartHelper downloadStartHelper = | 380 final OnDownloadStartHelper downloadStartHelper = |
344 mContentsClient.getOnDownloadStartHelper(); | 381 mContentsClient.getOnDownloadStartHelper(); |
345 final int callCount = downloadStartHelper.getCallCount(); | 382 final int callCount = downloadStartHelper.getCallCount(); |
346 loadUrlAsync(awContents, pageUrl); | 383 mActivityTestRule.loadUrlAsync(awContents, pageUrl); |
347 downloadStartHelper.waitForCallback(callCount); | 384 downloadStartHelper.waitForCallback(callCount); |
348 | 385 |
349 assertEquals(pageUrl, downloadStartHelper.getUrl()); | 386 Assert.assertEquals(pageUrl, downloadStartHelper.getUrl()); |
350 assertEquals(contentDisposition, downloadStartHelper.getContentDispo
sition()); | 387 Assert.assertEquals(contentDisposition, downloadStartHelper.getConte
ntDisposition()); |
351 assertEquals(mimeType, downloadStartHelper.getMimeType()); | 388 Assert.assertEquals(mimeType, downloadStartHelper.getMimeType()); |
352 assertEquals(data.length(), downloadStartHelper.getContentLength()); | 389 Assert.assertEquals(data.length(), downloadStartHelper.getContentLen
gth()); |
353 } finally { | 390 } finally { |
354 webServer.shutdown(); | 391 webServer.shutdown(); |
355 } | 392 } |
356 } | 393 } |
357 | 394 |
| 395 @Test |
358 @Feature({"AndroidWebView", "setNetworkAvailable"}) | 396 @Feature({"AndroidWebView", "setNetworkAvailable"}) |
359 @SmallTest | 397 @SmallTest |
360 public void testSetNetworkAvailable() throws Throwable { | 398 public void testSetNetworkAvailable() throws Throwable { |
361 AwTestContainerView testView = createAwTestContainerViewOnMainSync(mCont
entsClient); | 399 AwTestContainerView testView = |
| 400 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
362 AwContents awContents = testView.getAwContents(); | 401 AwContents awContents = testView.getAwContents(); |
363 String script = "navigator.onLine"; | 402 String script = "navigator.onLine"; |
364 | 403 |
365 enableJavaScriptOnUiThread(awContents); | 404 mActivityTestRule.enableJavaScriptOnUiThread(awContents); |
366 loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), | 405 mActivityTestRule.loadUrlSync(awContents, mContentsClient.getOnPageFinis
hedHelper(), |
367 ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); | 406 ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); |
368 | 407 |
369 // Default to "online". | 408 // Default to "online". |
370 assertEquals("true", executeJavaScriptAndWaitForResult(awContents, mCont
entsClient, | 409 Assert.assertEquals("true", |
371 script)); | 410 mActivityTestRule.executeJavaScriptAndWaitForResult( |
| 411 awContents, mContentsClient, script)); |
372 | 412 |
373 // Forcing "offline". | 413 // Forcing "offline". |
374 setNetworkAvailableOnUiThread(awContents, false); | 414 mActivityTestRule.setNetworkAvailableOnUiThread(awContents, false); |
375 assertEquals("false", executeJavaScriptAndWaitForResult(awContents, mCon
tentsClient, | 415 Assert.assertEquals("false", |
376 script)); | 416 mActivityTestRule.executeJavaScriptAndWaitForResult( |
| 417 awContents, mContentsClient, script)); |
377 | 418 |
378 // Forcing "online". | 419 // Forcing "online". |
379 setNetworkAvailableOnUiThread(awContents, true); | 420 mActivityTestRule.setNetworkAvailableOnUiThread(awContents, true); |
380 assertEquals("true", executeJavaScriptAndWaitForResult(awContents, mCont
entsClient, | 421 Assert.assertEquals("true", |
381 script)); | 422 mActivityTestRule.executeJavaScriptAndWaitForResult( |
| 423 awContents, mContentsClient, script)); |
382 } | 424 } |
383 | 425 |
384 | 426 |
385 static class JavaScriptObject { | 427 static class JavaScriptObject { |
386 private CallbackHelper mCallbackHelper; | 428 private CallbackHelper mCallbackHelper; |
387 public JavaScriptObject(CallbackHelper callbackHelper) { | 429 public JavaScriptObject(CallbackHelper callbackHelper) { |
388 mCallbackHelper = callbackHelper; | 430 mCallbackHelper = callbackHelper; |
389 } | 431 } |
390 | 432 |
391 @JavascriptInterface | 433 @JavascriptInterface |
392 public void run() { | 434 public void run() { |
393 mCallbackHelper.notifyCalled(); | 435 mCallbackHelper.notifyCalled(); |
394 } | 436 } |
395 } | 437 } |
396 | 438 |
| 439 @Test |
397 @Feature({"AndroidWebView", "Android-JavaBridge"}) | 440 @Feature({"AndroidWebView", "Android-JavaBridge"}) |
398 @SmallTest | 441 @SmallTest |
399 public void testJavaBridge() throws Throwable { | 442 public void testJavaBridge() throws Throwable { |
400 final AwTestContainerView testView = createAwTestContainerViewOnMainSync
(mContentsClient); | 443 final AwTestContainerView testView = |
| 444 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
401 final CallbackHelper callback = new CallbackHelper(); | 445 final CallbackHelper callback = new CallbackHelper(); |
402 | 446 |
403 runTestOnUiThread(new Runnable() { | 447 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable(
) { |
404 @Override | 448 @Override |
405 public void run() { | 449 public void run() { |
406 AwContents awContents = testView.getAwContents(); | 450 AwContents awContents = testView.getAwContents(); |
407 AwSettings awSettings = awContents.getSettings(); | 451 AwSettings awSettings = awContents.getSettings(); |
408 awSettings.setJavaScriptEnabled(true); | 452 awSettings.setJavaScriptEnabled(true); |
409 awContents.addJavascriptInterface(new JavaScriptObject(callback)
, "bridge"); | 453 awContents.addJavascriptInterface(new JavaScriptObject(callback)
, "bridge"); |
410 awContents.evaluateJavaScriptForTests("window.bridge.run();", nu
ll); | 454 awContents.evaluateJavaScriptForTests("window.bridge.run();", nu
ll); |
411 } | 455 } |
412 }); | 456 }); |
413 callback.waitForCallback(0, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); | 457 callback.waitForCallback(0, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); |
414 } | 458 } |
415 | 459 |
| 460 @Test |
416 @Feature({"AndroidWebView"}) | 461 @Feature({"AndroidWebView"}) |
417 @SmallTest | 462 @SmallTest |
418 public void testEscapingOfErrorPage() throws Throwable { | 463 public void testEscapingOfErrorPage() throws Throwable { |
419 AwTestContainerView testView = createAwTestContainerViewOnMainSync(mCont
entsClient); | 464 AwTestContainerView testView = |
| 465 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
420 AwContents awContents = testView.getAwContents(); | 466 AwContents awContents = testView.getAwContents(); |
421 String script = "window.failed == true"; | 467 String script = "window.failed == true"; |
422 | 468 |
423 enableJavaScriptOnUiThread(awContents); | 469 mActivityTestRule.enableJavaScriptOnUiThread(awContents); |
424 CallbackHelper onPageFinishedHelper = mContentsClient.getOnPageFinishedH
elper(); | 470 CallbackHelper onPageFinishedHelper = mContentsClient.getOnPageFinishedH
elper(); |
425 int currentCallCount = onPageFinishedHelper.getCallCount(); | 471 int currentCallCount = onPageFinishedHelper.getCallCount(); |
426 loadUrlAsync(awContents, | 472 mActivityTestRule.loadUrlAsync(awContents, |
427 "file:///file-that-does-not-exist#<script>window.failed = true;<
/script>"); | 473 "file:///file-that-does-not-exist#<script>window.failed = true;<
/script>"); |
428 onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_M
S, | 474 onPageFinishedHelper.waitForCallback( |
429 TimeUnit.MILLISECONDS); | 475 currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); |
430 | 476 |
431 assertEquals("false", executeJavaScriptAndWaitForResult(awContents, mCon
tentsClient, | 477 Assert.assertEquals("false", |
432 script)); | 478 mActivityTestRule.executeJavaScriptAndWaitForResult( |
| 479 awContents, mContentsClient, script)); |
433 } | 480 } |
434 | 481 |
| 482 @Test |
435 @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE") | 483 @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE") |
436 @Feature({"AndroidWebView"}) | 484 @Feature({"AndroidWebView"}) |
437 @SmallTest | 485 @SmallTest |
438 public void testCanInjectHeaders() throws Throwable { | 486 public void testCanInjectHeaders() throws Throwable { |
439 final AwTestContainerView testContainer = | 487 final AwTestContainerView testContainer = |
440 createAwTestContainerViewOnMainSync(mContentsClient); | 488 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
441 final AwContents awContents = testContainer.getAwContents(); | 489 final AwContents awContents = testContainer.getAwContents(); |
442 | 490 |
443 enableJavaScriptOnUiThread(awContents); | 491 mActivityTestRule.enableJavaScriptOnUiThread(awContents); |
444 | 492 |
445 EmbeddedTestServer testServer = | 493 EmbeddedTestServer testServer = EmbeddedTestServer.createAndStartServer( |
446 EmbeddedTestServer.createAndStartServer(getInstrumentation().get
Context()); | 494 InstrumentationRegistry.getInstrumentation().getContext()); |
447 | 495 |
448 try { | 496 try { |
449 String url = testServer.getURL("/echoheader?X-foo"); | 497 String url = testServer.getURL("/echoheader?X-foo"); |
450 | 498 |
451 final Map<String, String> extraHeaders = new HashMap<String, String>
(); | 499 final Map<String, String> extraHeaders = new HashMap<String, String>
(); |
452 extraHeaders.put("X-foo", "bar"); | 500 extraHeaders.put("X-foo", "bar"); |
453 loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), u
rl, extraHeaders); | 501 mActivityTestRule.loadUrlSync( |
| 502 awContents, mContentsClient.getOnPageFinishedHelper(), url,
extraHeaders); |
454 | 503 |
455 String xfoo = getJavaScriptResultBodyTextContent(awContents, mConten
tsClient); | 504 String xfoo = mActivityTestRule.getJavaScriptResultBodyTextContent( |
456 assertEquals("bar", xfoo); | 505 awContents, mContentsClient); |
| 506 Assert.assertEquals("bar", xfoo); |
457 | 507 |
458 url = testServer.getURL("/echoheader?Referer"); | 508 url = testServer.getURL("/echoheader?Referer"); |
459 | 509 |
460 extraHeaders.clear(); | 510 extraHeaders.clear(); |
461 extraHeaders.put("Referer", "http://www.example.com/"); | 511 extraHeaders.put("Referer", "http://www.example.com/"); |
462 loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), u
rl, extraHeaders); | 512 mActivityTestRule.loadUrlSync( |
| 513 awContents, mContentsClient.getOnPageFinishedHelper(), url,
extraHeaders); |
463 | 514 |
464 String referer = getJavaScriptResultBodyTextContent(awContents, mCon
tentsClient); | 515 String referer = mActivityTestRule.getJavaScriptResultBodyTextConten
t( |
465 assertEquals("http://www.example.com/", referer); | 516 awContents, mContentsClient); |
| 517 Assert.assertEquals("http://www.example.com/", referer); |
466 } finally { | 518 } finally { |
467 testServer.stopAndDestroyServer(); | 519 testServer.stopAndDestroyServer(); |
468 } | 520 } |
469 } | 521 } |
470 | 522 |
471 // This is a meta test that we don't accidentally turn off hardware | 523 // This is a meta test that we don't accidentally turn off hardware |
472 // acceleration in instrumentation tests without notice. Do not add the | 524 // acceleration in instrumentation tests without notice. Do not add the |
473 // @DisableHardwareAccelerationForTest annotation for this test. | 525 // @DisableHardwareAccelerationForTest annotation for this test. |
| 526 @Test |
474 @Feature({"AndroidWebView"}) | 527 @Feature({"AndroidWebView"}) |
475 @SmallTest | 528 @SmallTest |
476 public void testHardwareModeWorks() throws Throwable { | 529 public void testHardwareModeWorks() throws Throwable { |
477 AwTestContainerView testContainer = | 530 AwTestContainerView testContainer = |
478 createAwTestContainerViewOnMainSync(mContentsClient); | 531 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
479 assertTrue(testContainer.isHardwareAccelerated()); | 532 Assert.assertTrue(testContainer.isHardwareAccelerated()); |
480 assertTrue(testContainer.isBackedByHardwareView()); | 533 Assert.assertTrue(testContainer.isBackedByHardwareView()); |
481 } | 534 } |
482 | 535 |
483 // TODO(hush): more ssl tests. And put the ssl tests into a separate test | 536 // TODO(hush): more ssl tests. And put the ssl tests into a separate test |
484 // class. | 537 // class. |
| 538 @Test |
485 @Feature({"AndroidWebView"}) | 539 @Feature({"AndroidWebView"}) |
486 @SmallTest | 540 @SmallTest |
487 // If the user allows the ssl error, the same ssl error will not trigger | 541 // If the user allows the ssl error, the same ssl error will not trigger |
488 // the onReceivedSslError callback; If the user denies it, the same ssl | 542 // the onReceivedSslError callback; If the user denies it, the same ssl |
489 // error will still trigger the onReceivedSslError callback. | 543 // error will still trigger the onReceivedSslError callback. |
490 public void testSslPreferences() throws Throwable { | 544 public void testSslPreferences() throws Throwable { |
491 final AwTestContainerView testContainer = | 545 final AwTestContainerView testContainer = |
492 createAwTestContainerViewOnMainSync(mContentsClient); | 546 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
493 final AwContents awContents = testContainer.getAwContents(); | 547 final AwContents awContents = testContainer.getAwContents(); |
494 TestWebServer webServer = TestWebServer.startSsl(); | 548 TestWebServer webServer = TestWebServer.startSsl(); |
495 final String pagePath = "/hello.html"; | 549 final String pagePath = "/hello.html"; |
496 final String pageUrl = | 550 final String pageUrl = |
497 webServer.setResponse(pagePath, "<html><body>hello world</body><
/html>", null); | 551 webServer.setResponse(pagePath, "<html><body>hello world</body><
/html>", null); |
498 final CallbackHelper onReceivedSslErrorHelper = | 552 final CallbackHelper onReceivedSslErrorHelper = |
499 mContentsClient.getOnReceivedSslErrorHelper(); | 553 mContentsClient.getOnReceivedSslErrorHelper(); |
500 int onSslErrorCallCount = onReceivedSslErrorHelper.getCallCount(); | 554 int onSslErrorCallCount = onReceivedSslErrorHelper.getCallCount(); |
501 | 555 |
502 loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), pageU
rl); | 556 mActivityTestRule.loadUrlSync( |
| 557 awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); |
503 | 558 |
504 assertEquals(onSslErrorCallCount + 1, onReceivedSslErrorHelper.getCallCo
unt()); | 559 Assert.assertEquals(onSslErrorCallCount + 1, onReceivedSslErrorHelper.ge
tCallCount()); |
505 assertEquals(1, webServer.getRequestCount(pagePath)); | 560 Assert.assertEquals(1, webServer.getRequestCount(pagePath)); |
506 | 561 |
507 // Now load the page again. This time, we expect no ssl error, because | 562 // Now load the page again. This time, we expect no ssl error, because |
508 // user's decision should be remembered. | 563 // user's decision should be remembered. |
509 onSslErrorCallCount = onReceivedSslErrorHelper.getCallCount(); | 564 onSslErrorCallCount = onReceivedSslErrorHelper.getCallCount(); |
510 loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), pageU
rl); | 565 mActivityTestRule.loadUrlSync( |
511 assertEquals(onSslErrorCallCount, onReceivedSslErrorHelper.getCallCount(
)); | 566 awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); |
| 567 Assert.assertEquals(onSslErrorCallCount, onReceivedSslErrorHelper.getCal
lCount()); |
512 | 568 |
513 // Now clear the ssl preferences then load the same url again. Expect to
see | 569 // Now clear the ssl preferences then load the same url again. Expect to
see |
514 // onReceivedSslError getting called again. | 570 // onReceivedSslError getting called again. |
515 awContents.clearSslPreferences(); | 571 awContents.clearSslPreferences(); |
516 onSslErrorCallCount = onReceivedSslErrorHelper.getCallCount(); | 572 onSslErrorCallCount = onReceivedSslErrorHelper.getCallCount(); |
517 loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), pageU
rl); | 573 mActivityTestRule.loadUrlSync( |
518 assertEquals(onSslErrorCallCount + 1, onReceivedSslErrorHelper.getCallCo
unt()); | 574 awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); |
| 575 Assert.assertEquals(onSslErrorCallCount + 1, onReceivedSslErrorHelper.ge
tCallCount()); |
519 | 576 |
520 // Now clear the stored decisions and tell the client to deny ssl errors
. | 577 // Now clear the stored decisions and tell the client to deny ssl errors
. |
521 awContents.clearSslPreferences(); | 578 awContents.clearSslPreferences(); |
522 mContentsClient.setAllowSslError(false); | 579 mContentsClient.setAllowSslError(false); |
523 onSslErrorCallCount = onReceivedSslErrorHelper.getCallCount(); | 580 onSslErrorCallCount = onReceivedSslErrorHelper.getCallCount(); |
524 loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), pageU
rl); | 581 mActivityTestRule.loadUrlSync( |
525 assertEquals(onSslErrorCallCount + 1, onReceivedSslErrorHelper.getCallCo
unt()); | 582 awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); |
| 583 Assert.assertEquals(onSslErrorCallCount + 1, onReceivedSslErrorHelper.ge
tCallCount()); |
526 | 584 |
527 // Now load the same page again. This time, we still expect onReceivedSs
lError, | 585 // Now load the same page again. This time, we still expect onReceivedSs
lError, |
528 // because we only remember user's decision if it is "allow". | 586 // because we only remember user's decision if it is "allow". |
529 onSslErrorCallCount = onReceivedSslErrorHelper.getCallCount(); | 587 onSslErrorCallCount = onReceivedSslErrorHelper.getCallCount(); |
530 loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), pageU
rl); | 588 mActivityTestRule.loadUrlSync( |
531 assertEquals(onSslErrorCallCount + 1, onReceivedSslErrorHelper.getCallCo
unt()); | 589 awContents, mContentsClient.getOnPageFinishedHelper(), pageUrl); |
| 590 Assert.assertEquals(onSslErrorCallCount + 1, onReceivedSslErrorHelper.ge
tCallCount()); |
532 } | 591 } |
533 | 592 |
534 /** | 593 /** |
535 * Verifies that Web Notifications and the Push API are not exposed in WebVi
ew. | 594 * Verifies that Web Notifications and the Push API are not exposed in WebVi
ew. |
536 */ | 595 */ |
| 596 @Test |
537 @Feature({"AndroidWebView"}) | 597 @Feature({"AndroidWebView"}) |
538 @SmallTest | 598 @SmallTest |
539 public void testPushAndNotificationsDisabled() throws Throwable { | 599 public void testPushAndNotificationsDisabled() throws Throwable { |
540 AwTestContainerView testView = createAwTestContainerViewOnMainSync(mCont
entsClient); | 600 AwTestContainerView testView = |
| 601 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
541 AwContents awContents = testView.getAwContents(); | 602 AwContents awContents = testView.getAwContents(); |
542 | 603 |
543 String script = "window.Notification || window.PushManager"; | 604 String script = "window.Notification || window.PushManager"; |
544 | 605 |
545 enableJavaScriptOnUiThread(awContents); | 606 mActivityTestRule.enableJavaScriptOnUiThread(awContents); |
546 loadUrlSync(awContents, mContentsClient.getOnPageFinishedHelper(), | 607 mActivityTestRule.loadUrlSync(awContents, mContentsClient.getOnPageFinis
hedHelper(), |
547 ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); | 608 ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL); |
548 assertEquals("null", executeJavaScriptAndWaitForResult(awContents, mCont
entsClient, | 609 Assert.assertEquals("null", |
549 script)); | 610 mActivityTestRule.executeJavaScriptAndWaitForResult( |
| 611 awContents, mContentsClient, script)); |
550 } | 612 } |
551 | 613 |
552 private static class MockBindingManager implements BindingManager { | 614 private static class MockBindingManager implements BindingManager { |
553 private boolean mIsChildProcessCreated; | 615 private boolean mIsChildProcessCreated; |
554 | 616 |
555 private Object mForegroundStateLock; | 617 private Object mForegroundStateLock; |
556 private ArrayList<Boolean> mForegroundState; | 618 private ArrayList<Boolean> mForegroundState; |
557 | 619 |
558 public MockBindingManager() { | 620 public MockBindingManager() { |
559 super(); | 621 super(); |
560 mForegroundStateLock = new Object(); | 622 mForegroundStateLock = new Object(); |
561 mForegroundState = new ArrayList<Boolean>(); | 623 mForegroundState = new ArrayList<Boolean>(); |
562 } | 624 } |
563 | 625 |
564 boolean isChildProcessCreated() { | 626 boolean isChildProcessCreated() { |
565 return mIsChildProcessCreated; | 627 return mIsChildProcessCreated; |
566 } | 628 } |
567 | 629 |
568 void assertSetInForegroundCall(boolean inForeground) { | 630 void assertSetInForegroundCall(boolean inForeground) { |
569 synchronized (mForegroundStateLock) { | 631 synchronized (mForegroundStateLock) { |
570 if (mForegroundState.size() == 0) { | 632 if (mForegroundState.size() == 0) { |
571 try { | 633 try { |
572 mForegroundStateLock.wait(WAIT_TIMEOUT_MS); | 634 mForegroundStateLock.wait(WAIT_TIMEOUT_MS); |
573 } catch (InterruptedException e) { | 635 } catch (InterruptedException e) { |
574 } | 636 } |
575 } | 637 } |
576 assertTrue(mForegroundState.size() != 0); | 638 Assert.assertTrue(mForegroundState.size() != 0); |
577 assertEquals(inForeground, mForegroundState.get(0).booleanValue(
)); | 639 Assert.assertEquals(inForeground, mForegroundState.get(0).boolea
nValue()); |
578 mForegroundState.remove(0); | 640 mForegroundState.remove(0); |
579 return; | 641 return; |
580 } | 642 } |
581 } | 643 } |
582 | 644 |
583 @Override | 645 @Override |
584 public void addNewConnection(int pid, ChildProcessConnection connection)
{ | 646 public void addNewConnection(int pid, ChildProcessConnection connection)
{ |
585 mIsChildProcessCreated = true; | 647 mIsChildProcessCreated = true; |
586 } | 648 } |
587 | 649 |
(...skipping 17 matching lines...) Expand all Loading... |
605 @Override | 667 @Override |
606 public void startModerateBindingManagement(Context context, int maxSize)
{} | 668 public void startModerateBindingManagement(Context context, int maxSize)
{} |
607 | 669 |
608 @Override | 670 @Override |
609 public void releaseAllModerateBindings() {} | 671 public void releaseAllModerateBindings() {} |
610 } | 672 } |
611 | 673 |
612 /** | 674 /** |
613 * Verifies that a child process is actually gets created with WEBVIEW_SANDB
OXED_RENDERER flag. | 675 * Verifies that a child process is actually gets created with WEBVIEW_SANDB
OXED_RENDERER flag. |
614 */ | 676 */ |
| 677 @Test |
615 @Feature({"AndroidWebView"}) | 678 @Feature({"AndroidWebView"}) |
616 @SmallTest | 679 @SmallTest |
617 @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER) | 680 @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER) |
618 @SkipCommandLineParameterization | 681 @SkipCommandLineParameterization |
619 public void testSandboxedRendererWorks() throws Throwable { | 682 public void testSandboxedRendererWorks() throws Throwable { |
620 MockBindingManager bindingManager = new MockBindingManager(); | 683 MockBindingManager bindingManager = new MockBindingManager(); |
621 ChildProcessLauncherHelper.setBindingManagerForTesting(bindingManager); | 684 ChildProcessLauncherHelper.setBindingManagerForTesting(bindingManager); |
622 assertFalse(bindingManager.isChildProcessCreated()); | 685 Assert.assertFalse(bindingManager.isChildProcessCreated()); |
623 | 686 |
624 AwTestContainerView testView = createAwTestContainerViewOnMainSync(mCont
entsClient); | 687 AwTestContainerView testView = |
| 688 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
625 AwContents awContents = testView.getAwContents(); | 689 AwContents awContents = testView.getAwContents(); |
626 final String pageTitle = "I am sandboxed"; | 690 final String pageTitle = "I am sandboxed"; |
627 loadDataSync(awContents, mContentsClient.getOnPageFinishedHelper(), | 691 mActivityTestRule.loadDataSync(awContents, mContentsClient.getOnPageFini
shedHelper(), |
628 "<html><head><title>" + pageTitle + "</title></head></html>", "t
ext/html", false); | 692 "<html><head><title>" + pageTitle + "</title></head></html>", "t
ext/html", false); |
629 assertEquals(pageTitle, getTitleOnUiThread(awContents)); | 693 Assert.assertEquals(pageTitle, mActivityTestRule.getTitleOnUiThread(awCo
ntents)); |
630 | 694 |
631 assertTrue(bindingManager.isChildProcessCreated()); | 695 Assert.assertTrue(bindingManager.isChildProcessCreated()); |
632 | 696 |
633 // Test end-to-end interaction with the renderer. | 697 // Test end-to-end interaction with the renderer. |
634 AwSettings awSettings = getAwSettingsOnUiThread(awContents); | 698 AwSettings awSettings = mActivityTestRule.getAwSettingsOnUiThread(awCont
ents); |
635 awSettings.setJavaScriptEnabled(true); | 699 awSettings.setJavaScriptEnabled(true); |
636 assertEquals("42", JSUtils.executeJavaScriptAndWaitForResult(this, awCon
tents, | 700 Assert.assertEquals("42", |
| 701 JSUtils.executeJavaScriptAndWaitForResult( |
| 702 InstrumentationRegistry.getInstrumentation(), awContents
, |
637 mContentsClient.getOnEvaluateJavaScriptResultHelper(), "
21 + 21")); | 703 mContentsClient.getOnEvaluateJavaScriptResultHelper(), "
21 + 21")); |
638 } | 704 } |
639 | 705 |
640 /** | 706 /** |
641 * By default the renderer should be considererd to be in the | 707 * By default the renderer should be considererd to be in the |
642 * foreground. | 708 * foreground. |
643 */ | 709 */ |
| 710 @Test |
644 @Feature({"AndroidWebView"}) | 711 @Feature({"AndroidWebView"}) |
645 @SmallTest | 712 @SmallTest |
646 @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER) | 713 @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER) |
647 @SkipCommandLineParameterization | 714 @SkipCommandLineParameterization |
648 public void testRendererPriorityStartsHigh() throws Throwable { | 715 public void testRendererPriorityStartsHigh() throws Throwable { |
649 MockBindingManager bindingManager = new MockBindingManager(); | 716 MockBindingManager bindingManager = new MockBindingManager(); |
650 ChildProcessLauncherHelper.setBindingManagerForTesting(bindingManager); | 717 ChildProcessLauncherHelper.setBindingManagerForTesting(bindingManager); |
651 assertFalse(bindingManager.isChildProcessCreated()); | 718 Assert.assertFalse(bindingManager.isChildProcessCreated()); |
652 | 719 |
653 AwTestContainerView testView = createAwTestContainerViewOnMainSync(mCont
entsClient); | 720 AwTestContainerView testView = |
| 721 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
654 AwContents awContents = testView.getAwContents(); | 722 AwContents awContents = testView.getAwContents(); |
655 loadDataSync(awContents, mContentsClient.getOnPageFinishedHelper(), "<ht
ml></html>", | 723 mActivityTestRule.loadDataSync(awContents, mContentsClient.getOnPageFini
shedHelper(), |
656 "text/html", false); | 724 "<html></html>", "text/html", false); |
657 | 725 |
658 assertTrue(bindingManager.isChildProcessCreated()); | 726 Assert.assertTrue(bindingManager.isChildProcessCreated()); |
659 bindingManager.assertSetInForegroundCall(true); | 727 bindingManager.assertSetInForegroundCall(true); |
660 } | 728 } |
661 | 729 |
662 /** | 730 /** |
663 * If we specify that the priority is WAIVED, then the renderer | 731 * If we specify that the priority is WAIVED, then the renderer |
664 * should not be in the foreground. | 732 * should not be in the foreground. |
665 */ | 733 */ |
| 734 @Test |
666 @Feature({"AndroidWebView"}) | 735 @Feature({"AndroidWebView"}) |
667 @SmallTest | 736 @SmallTest |
668 @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER) | 737 @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER) |
669 @SkipCommandLineParameterization | 738 @SkipCommandLineParameterization |
670 public void testRendererPriorityLow() throws Throwable { | 739 public void testRendererPriorityLow() throws Throwable { |
671 MockBindingManager bindingManager = new MockBindingManager(); | 740 MockBindingManager bindingManager = new MockBindingManager(); |
672 ChildProcessLauncherHelper.setBindingManagerForTesting(bindingManager); | 741 ChildProcessLauncherHelper.setBindingManagerForTesting(bindingManager); |
673 assertFalse(bindingManager.isChildProcessCreated()); | 742 Assert.assertFalse(bindingManager.isChildProcessCreated()); |
674 | 743 |
675 final AwTestContainerView testView = createAwTestContainerViewOnMainSync
(mContentsClient); | 744 final AwTestContainerView testView = |
| 745 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
676 final AwContents awContents = testView.getAwContents(); | 746 final AwContents awContents = testView.getAwContents(); |
677 runTestOnUiThread(new Runnable() { | 747 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable(
) { |
678 @Override | 748 @Override |
679 public void run() { | 749 public void run() { |
680 awContents.setRendererPriorityPolicy(RendererPriority.WAIVED, fa
lse); | 750 awContents.setRendererPriorityPolicy(RendererPriority.WAIVED, fa
lse); |
681 } | 751 } |
682 }); | 752 }); |
683 loadDataSync(awContents, mContentsClient.getOnPageFinishedHelper(), "<ht
ml></html>", | 753 mActivityTestRule.loadDataSync(awContents, mContentsClient.getOnPageFini
shedHelper(), |
684 "text/html", false); | 754 "<html></html>", "text/html", false); |
685 | 755 |
686 assertTrue(awContents.isPageVisible()); | 756 Assert.assertTrue(awContents.isPageVisible()); |
687 assertTrue(bindingManager.isChildProcessCreated()); | 757 Assert.assertTrue(bindingManager.isChildProcessCreated()); |
688 bindingManager.assertSetInForegroundCall(false); | 758 bindingManager.assertSetInForegroundCall(false); |
689 } | 759 } |
690 | 760 |
691 /** | 761 /** |
692 * If we specify that the priority is HIGH, but WAIVED when in the | 762 * If we specify that the priority is HIGH, but WAIVED when in the |
693 * background, then pausing the view should send the renderer to | 763 * background, then pausing the view should send the renderer to |
694 * the background. | 764 * the background. |
695 */ | 765 */ |
| 766 @Test |
696 @Feature({"AndroidWebView"}) | 767 @Feature({"AndroidWebView"}) |
697 @SmallTest | 768 @SmallTest |
698 @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER) | 769 @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER) |
699 @SkipCommandLineParameterization | 770 @SkipCommandLineParameterization |
700 public void testRendererPriorityManaged() throws Throwable { | 771 public void testRendererPriorityManaged() throws Throwable { |
701 MockBindingManager bindingManager = new MockBindingManager(); | 772 MockBindingManager bindingManager = new MockBindingManager(); |
702 ChildProcessLauncherHelper.setBindingManagerForTesting(bindingManager); | 773 ChildProcessLauncherHelper.setBindingManagerForTesting(bindingManager); |
703 assertFalse(bindingManager.isChildProcessCreated()); | 774 Assert.assertFalse(bindingManager.isChildProcessCreated()); |
704 | 775 |
705 final AwTestContainerView testView = createAwTestContainerViewOnMainSync
(mContentsClient); | 776 final AwTestContainerView testView = |
| 777 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
706 final AwContents awContents = testView.getAwContents(); | 778 final AwContents awContents = testView.getAwContents(); |
707 runTestOnUiThread(new Runnable() { | 779 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable(
) { |
708 @Override | 780 @Override |
709 public void run() { | 781 public void run() { |
710 awContents.setRendererPriorityPolicy(RendererPriority.HIGH, true
); | 782 awContents.setRendererPriorityPolicy(RendererPriority.HIGH, true
); |
711 } | 783 } |
712 }); | 784 }); |
713 loadDataSync(awContents, mContentsClient.getOnPageFinishedHelper(), "<ht
ml></html>", | 785 mActivityTestRule.loadDataSync(awContents, mContentsClient.getOnPageFini
shedHelper(), |
714 "text/html", false); | 786 "<html></html>", "text/html", false); |
715 | 787 |
716 assertTrue(awContents.isPageVisible()); | 788 Assert.assertTrue(awContents.isPageVisible()); |
717 assertTrue(bindingManager.isChildProcessCreated()); | 789 Assert.assertTrue(bindingManager.isChildProcessCreated()); |
718 bindingManager.assertSetInForegroundCall(true); | 790 bindingManager.assertSetInForegroundCall(true); |
719 runTestOnUiThread(new Runnable() { | 791 InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable(
) { |
720 @Override | 792 @Override |
721 public void run() { | 793 public void run() { |
722 awContents.onPause(); | 794 awContents.onPause(); |
723 } | 795 } |
724 }); | 796 }); |
725 bindingManager.assertSetInForegroundCall(false); | 797 bindingManager.assertSetInForegroundCall(false); |
726 } | 798 } |
727 | 799 |
| 800 @Test |
728 @Feature({"AndroidWebView"}) | 801 @Feature({"AndroidWebView"}) |
729 @SmallTest | 802 @SmallTest |
730 @UiThreadTest | |
731 @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER) | 803 @CommandLineFlags.Add(AwSwitches.WEBVIEW_SANDBOXED_RENDERER) |
732 @SkipCommandLineParameterization | 804 @SkipCommandLineParameterization |
733 public void testPauseDestroyResume() throws Throwable { | 805 public void testPauseDestroyResume() throws Throwable { |
734 AwContents awContents; | 806 mActivityTestRule.runOnUiThread(new Runnable() { |
735 awContents = createAwTestContainerView(mContentsClient).getAwContents(); | 807 @Override |
736 awContents.pauseTimers(); | 808 public void run() { |
737 awContents.pauseTimers(); | 809 AwContents awContents; |
738 awContents.destroy(); | 810 awContents = mActivityTestRule.createAwTestContainerView(mConten
tsClient) |
739 awContents = createAwTestContainerView(mContentsClient).getAwContents(); | 811 .getAwContents(); |
740 awContents.resumeTimers(); | 812 awContents.pauseTimers(); |
| 813 awContents.pauseTimers(); |
| 814 awContents.destroy(); |
| 815 awContents = mActivityTestRule.createAwTestContainerView(mConten
tsClient) |
| 816 .getAwContents(); |
| 817 awContents.resumeTimers(); |
| 818 } |
| 819 }); |
741 } | 820 } |
742 | 821 |
743 /** Regression test for https://crbug.com/732976. Load a data URL, then imme
diately | 822 /** Regression test for https://crbug.com/732976. Load a data URL, then imme
diately |
744 * after that load a javascript URL. The data URL navigation shouldn't be bl
ocked. | 823 * after that load a javascript URL. The data URL navigation shouldn't be bl
ocked. |
745 */ | 824 */ |
| 825 @Test |
746 @LargeTest | 826 @LargeTest |
747 @Feature({"AndroidWebView"}) | 827 @Feature({"AndroidWebView"}) |
748 public void testJavaScriptUrlAfterLoadData() throws Throwable { | 828 public void testJavaScriptUrlAfterLoadData() throws Throwable { |
749 AwTestContainerView testView = createAwTestContainerViewOnMainSync(mCont
entsClient); | 829 AwTestContainerView testView = |
| 830 mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsC
lient); |
750 final AwContents awContents = testView.getAwContents(); | 831 final AwContents awContents = testView.getAwContents(); |
751 getInstrumentation().runOnMainSync(new Runnable() { | 832 mActivityTestRule.runOnUiThread(new Runnable() { |
752 @Override | 833 @Override |
753 public void run() { | 834 public void run() { |
754 // Run javascript navigation immediately, without waiting for th
e completion of data | 835 // Run javascript navigation immediately, without waiting for th
e completion of data |
755 // URL. | 836 // URL. |
756 awContents.loadData("<html>test</html>", "text/html", "utf-8"); | 837 awContents.loadData("<html>test</html>", "text/html", "utf-8"); |
757 awContents.loadUrl("javascript: void(0)"); | 838 awContents.loadUrl("javascript: void(0)"); |
758 } | 839 } |
759 }); | 840 }); |
760 | 841 |
761 mContentsClient.getOnPageFinishedHelper().waitForCallback( | 842 mContentsClient.getOnPageFinishedHelper().waitForCallback( |
762 0, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); | 843 0, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); |
763 assertEquals("data:text/html,<html>test</html>", awContents.getLastCommi
ttedUrl()); | 844 Assert.assertEquals("data:text/html,<html>test</html>", awContents.getLa
stCommittedUrl()); |
764 | 845 |
765 TestAwContentsClient.AddMessageToConsoleHelper consoleHelper = | 846 TestAwContentsClient.AddMessageToConsoleHelper consoleHelper = |
766 mContentsClient.getAddMessageToConsoleHelper(); | 847 mContentsClient.getAddMessageToConsoleHelper(); |
767 assertEquals(0, consoleHelper.getMessages().size()); | 848 Assert.assertEquals(0, consoleHelper.getMessages().size()); |
768 } | 849 } |
769 } | 850 } |
OLD | NEW |