Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / android_webview / javatests / src / org / chromium / android_webview / test / AwTestBase.java
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.android_webview.test;
6
7 import android.app.Instrumentation;
8 import android.content.Context;
9 import android.test.ActivityInstrumentationTestCase2;
10 import android.util.Log;
11
12 import static org.chromium.base.test.util.ScalableTimeout.ScaleTimeout;
13
14 import org.chromium.android_webview.AwBrowserContext;
15 import org.chromium.android_webview.AwBrowserProcess;
16 import org.chromium.android_webview.AwContents;
17 import org.chromium.android_webview.AwContentsClient;
18 import org.chromium.android_webview.AwLayoutSizer;
19 import org.chromium.android_webview.AwSettings;
20 import org.chromium.android_webview.test.util.JSUtils;
21 import org.chromium.base.test.util.InMemorySharedPreferences;
22 import org.chromium.content.browser.ContentSettings;
23 import org.chromium.content.browser.LoadUrlParams;
24 import org.chromium.content.browser.test.util.CallbackHelper;
25 import org.chromium.content.browser.test.util.Criteria;
26 import org.chromium.content.browser.test.util.CriteriaHelper;
27
28 import java.util.concurrent.Callable;
29 import java.util.concurrent.FutureTask;
30 import java.util.concurrent.TimeUnit;
31 import java.util.concurrent.atomic.AtomicReference;
32
33 /**
34  * A base class for android_webview tests.
35  */
36 public class AwTestBase
37         extends ActivityInstrumentationTestCase2<AwTestRunnerActivity> {
38     protected static final long WAIT_TIMEOUT_MS = ScaleTimeout(15000);
39     protected static final int CHECK_INTERVAL = 100;
40     private static final String TAG = "AwTestBase";
41
42     public AwTestBase() {
43         super(AwTestRunnerActivity.class);
44     }
45
46     @Override
47     protected void setUp() throws Exception {
48         super.setUp();
49         if (needsBrowserProcessStarted()) {
50             final Context context = getActivity();
51             getInstrumentation().runOnMainSync(new Runnable() {
52                 @Override
53                 public void run() {
54                     AwBrowserProcess.start(context);
55                 }
56             });
57         }
58     }
59
60     /* Override this to return false if the test doesn't want the browser startup sequence to
61      * be run automatically.
62      */
63     protected boolean needsBrowserProcessStarted() {
64         return true;
65     }
66
67     /**
68      * Runs a {@link Callable} on the main thread, blocking until it is
69      * complete, and returns the result. Calls
70      * {@link Instrumentation#waitForIdleSync()} first to help avoid certain
71      * race conditions.
72      *
73      * @param <R> Type of result to return
74      */
75     public <R> R runTestOnUiThreadAndGetResult(Callable<R> callable)
76             throws Exception {
77         FutureTask<R> task = new FutureTask<R>(callable);
78         getInstrumentation().waitForIdleSync();
79         getInstrumentation().runOnMainSync(task);
80         return task.get();
81     }
82
83     protected void enableJavaScriptOnUiThread(final AwContents awContents) {
84         getInstrumentation().runOnMainSync(new Runnable() {
85             @Override
86             public void run() {
87                 awContents.getSettings().setJavaScriptEnabled(true);
88             }
89         });
90     }
91
92     protected void setNetworkAvailableOnUiThread(final AwContents awContents,
93             final boolean networkUp) {
94         getInstrumentation().runOnMainSync(new Runnable() {
95             @Override
96             public void run() {
97                 awContents.setNetworkAvailable(networkUp);
98             }
99         });
100     }
101
102     /**
103      * Loads url on the UI thread and blocks until onPageFinished is called.
104      */
105     protected void loadUrlSync(final AwContents awContents,
106                                CallbackHelper onPageFinishedHelper,
107                                final String url) throws Exception {
108         int currentCallCount = onPageFinishedHelper.getCallCount();
109         loadUrlAsync(awContents, url);
110         onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS,
111                 TimeUnit.MILLISECONDS);
112     }
113
114     protected void loadUrlSyncAndExpectError(final AwContents awContents,
115             CallbackHelper onPageFinishedHelper,
116             CallbackHelper onReceivedErrorHelper,
117             final String url) throws Exception {
118         int onErrorCallCount = onReceivedErrorHelper.getCallCount();
119         int onFinishedCallCount = onPageFinishedHelper.getCallCount();
120         loadUrlAsync(awContents, url);
121         onReceivedErrorHelper.waitForCallback(onErrorCallCount, 1, WAIT_TIMEOUT_MS,
122                 TimeUnit.MILLISECONDS);
123         onPageFinishedHelper.waitForCallback(onFinishedCallCount, 1, WAIT_TIMEOUT_MS,
124                 TimeUnit.MILLISECONDS);
125     }
126
127     /**
128      * Loads url on the UI thread but does not block.
129      */
130     protected void loadUrlAsync(final AwContents awContents,
131                                 final String url) throws Exception {
132         getInstrumentation().runOnMainSync(new Runnable() {
133             @Override
134             public void run() {
135                 awContents.loadUrl(new LoadUrlParams(url));
136             }
137         });
138     }
139
140     /**
141      * Posts url on the UI thread and blocks until onPageFinished is called.
142      */
143     protected void postUrlSync(final AwContents awContents,
144             CallbackHelper onPageFinishedHelper, final String url,
145             byte[] postData) throws Exception {
146         int currentCallCount = onPageFinishedHelper.getCallCount();
147         postUrlAsync(awContents, url, postData);
148         onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS,
149                 TimeUnit.MILLISECONDS);
150     }
151
152     /**
153      * Loads url on the UI thread but does not block.
154      */
155     protected void postUrlAsync(final AwContents awContents,
156             final String url, byte[] postData) throws Exception {
157         class PostUrl implements Runnable {
158             byte[] mPostData;
159             public PostUrl(byte[] postData) {
160                 mPostData = postData;
161             }
162             @Override
163             public void run() {
164                 awContents.loadUrl(LoadUrlParams.createLoadHttpPostParams(url,
165                         mPostData));
166             }
167         }
168         getInstrumentation().runOnMainSync(new PostUrl(postData));
169     }
170
171     /**
172      * Loads data on the UI thread and blocks until onPageFinished is called.
173      */
174     protected void loadDataSync(final AwContents awContents,
175                                 CallbackHelper onPageFinishedHelper,
176                                 final String data, final String mimeType,
177                                 final boolean isBase64Encoded) throws Exception {
178         int currentCallCount = onPageFinishedHelper.getCallCount();
179         loadDataAsync(awContents, data, mimeType, isBase64Encoded);
180         onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS,
181                 TimeUnit.MILLISECONDS);
182     }
183
184     protected void loadDataSyncWithCharset(final AwContents awContents,
185                                            CallbackHelper onPageFinishedHelper,
186                                            final String data, final String mimeType,
187                                            final boolean isBase64Encoded, final String charset)
188             throws Exception {
189         int currentCallCount = onPageFinishedHelper.getCallCount();
190         getInstrumentation().runOnMainSync(new Runnable() {
191             @Override
192             public void run() {
193                 awContents.loadUrl(LoadUrlParams.createLoadDataParams(
194                         data, mimeType, isBase64Encoded, charset));
195             }
196         });
197         onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS,
198                 TimeUnit.MILLISECONDS);
199     }
200
201     /**
202      * Loads data on the UI thread but does not block.
203      */
204     protected void loadDataAsync(final AwContents awContents, final String data,
205                                  final String mimeType, final boolean isBase64Encoded)
206             throws Exception {
207         getInstrumentation().runOnMainSync(new Runnable() {
208             @Override
209             public void run() {
210                 awContents.loadUrl(LoadUrlParams.createLoadDataParams(
211                         data, mimeType, isBase64Encoded));
212             }
213         });
214     }
215
216     /**
217      * Reloads the current page synchronously.
218      */
219     protected void reloadSync(final AwContents awContents,
220                               CallbackHelper onPageFinishedHelper) throws Exception {
221         int currentCallCount = onPageFinishedHelper.getCallCount();
222         getInstrumentation().runOnMainSync(new Runnable() {
223             @Override
224             public void run() {
225                 awContents.getContentViewCore().reload(true);
226             }
227         });
228         onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS,
229                 TimeUnit.MILLISECONDS);
230     }
231
232     /**
233      * Factory class used in creation of test AwContents instances.
234      *
235      * Test cases can provide subclass instances to the createAwTest* methods in order to create an
236      * AwContents instance with injected test dependencies.
237      */
238     public static class TestDependencyFactory {
239         public AwLayoutSizer createLayoutSizer() {
240             return new AwLayoutSizer();
241         }
242         public AwTestContainerView createAwTestContainerView(AwTestRunnerActivity activity) {
243             return new AwTestContainerView(activity);
244         }
245         public AwSettings createAwSettings(Context context, boolean supportsLegacyQuirks) {
246             return new AwSettings(context, false, supportsLegacyQuirks);
247         }
248     }
249
250     protected TestDependencyFactory createTestDependencyFactory() {
251         return new TestDependencyFactory();
252     }
253
254     protected AwTestContainerView createAwTestContainerView(
255             final AwContentsClient awContentsClient) {
256         return createAwTestContainerView(awContentsClient, true);
257     }
258
259     protected AwTestContainerView createAwTestContainerView(
260             final AwContentsClient awContentsClient, boolean supportsLegacyQuirks) {
261         AwTestContainerView testContainerView =
262                 createDetachedAwTestContainerView(awContentsClient, supportsLegacyQuirks);
263         getActivity().addView(testContainerView);
264         testContainerView.requestFocus();
265         return testContainerView;
266     }
267
268     // The browser context needs to be a process-wide singleton.
269     private AwBrowserContext mBrowserContext =
270             new AwBrowserContext(new InMemorySharedPreferences());
271
272     protected AwTestContainerView createDetachedAwTestContainerView(
273             final AwContentsClient awContentsClient) {
274         return createDetachedAwTestContainerView(awContentsClient, true);
275     }
276
277     protected AwTestContainerView createDetachedAwTestContainerView(
278             final AwContentsClient awContentsClient, boolean supportsLegacyQuirks) {
279         final TestDependencyFactory testDependencyFactory = createTestDependencyFactory();
280         final AwTestContainerView testContainerView =
281             testDependencyFactory.createAwTestContainerView(getActivity());
282         AwSettings awSettings = testDependencyFactory.createAwSettings(getActivity(),
283                 supportsLegacyQuirks);
284         // TODO(mnaganov): Should also have tests for the "pure Chromium" mode.
285         // See http://crbug.com/278106
286         testContainerView.initialize(new AwContents(
287                 mBrowserContext, testContainerView, testContainerView.getInternalAccessDelegate(),
288                 awContentsClient, awSettings, testDependencyFactory.createLayoutSizer()));
289         AwContents.setShouldDownloadFavicons();
290         return testContainerView;
291     }
292
293     protected AwTestContainerView createAwTestContainerViewOnMainSync(
294             final AwContentsClient client) throws Exception {
295         return createAwTestContainerViewOnMainSync(client, true);
296     }
297
298     protected AwTestContainerView createAwTestContainerViewOnMainSync(
299             final AwContentsClient client, final boolean supportsLegacyQuirks) throws Exception {
300         final AtomicReference<AwTestContainerView> testContainerView =
301                 new AtomicReference<AwTestContainerView>();
302         getInstrumentation().runOnMainSync(new Runnable() {
303             @Override
304             public void run() {
305                 testContainerView.set(createAwTestContainerView(client, supportsLegacyQuirks));
306             }
307         });
308         return testContainerView.get();
309     }
310
311     protected void destroyAwContentsOnMainSync(final AwContents awContents) {
312         if (awContents == null) return;
313         getInstrumentation().runOnMainSync(new Runnable() {
314             @Override
315             public void run() {
316                 awContents.destroy();
317             }
318         });
319     }
320
321     protected String getTitleOnUiThread(final AwContents awContents) throws Exception {
322         return runTestOnUiThreadAndGetResult(new Callable<String>() {
323             @Override
324             public String call() throws Exception {
325                 return awContents.getContentViewCore().getTitle();
326             }
327         });
328     }
329
330     protected ContentSettings getContentSettingsOnUiThread(
331             final AwContents awContents) throws Exception {
332         return runTestOnUiThreadAndGetResult(new Callable<ContentSettings>() {
333             @Override
334             public ContentSettings call() throws Exception {
335                 return awContents.getContentViewCore().getContentSettings();
336             }
337         });
338     }
339
340     protected AwSettings getAwSettingsOnUiThread(
341             final AwContents awContents) throws Exception {
342         return runTestOnUiThreadAndGetResult(new Callable<AwSettings>() {
343             @Override
344             public AwSettings call() throws Exception {
345                 return awContents.getSettings();
346             }
347         });
348     }
349
350     /**
351      * Executes the given snippet of JavaScript code within the given ContentView. Returns the
352      * result of its execution in JSON format.
353      */
354     protected String executeJavaScriptAndWaitForResult(final AwContents awContents,
355             TestAwContentsClient viewClient, final String code) throws Exception {
356         return JSUtils.executeJavaScriptAndWaitForResult(this, awContents,
357                 viewClient.getOnEvaluateJavaScriptResultHelper(),
358                 code);
359     }
360
361     /**
362      * Wrapper around CriteriaHelper.pollForCriteria. This uses AwTestBase-specifc timeouts and
363      * treats timeouts and exceptions as test failures automatically.
364      */
365     protected static void poll(final Callable<Boolean> callable) throws Exception {
366         assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
367             @Override
368             public boolean isSatisfied() {
369                 try {
370                     return callable.call();
371                 } catch (Throwable e) {
372                     Log.e(TAG, "Exception while polling.", e);
373                     return false;
374                 }
375             }
376         }, WAIT_TIMEOUT_MS, CHECK_INTERVAL));
377     }
378
379     /**
380      * Wrapper around {@link AwTestBase#poll()} but runs the callable on the UI thread.
381      */
382     protected void pollOnUiThread(final Callable<Boolean> callable) throws Exception {
383         poll(new Callable<Boolean>() {
384             @Override
385             public Boolean call() throws Exception {
386                 return runTestOnUiThreadAndGetResult(callable);
387             }
388         });
389     }
390
391     /**
392      * Clears the resource cache. Note that the cache is per-application, so this will clear the
393      * cache for all WebViews used.
394      */
395     protected void clearCacheOnUiThread(
396             final AwContents awContents,
397             final boolean includeDiskFiles) throws Exception {
398         getInstrumentation().runOnMainSync(new Runnable() {
399             @Override
400             public void run() {
401                 awContents.clearCache(includeDiskFiles);
402             }
403         });
404     }
405
406     /**
407      * Returns pure page scale.
408      */
409     protected float getScaleOnUiThread(final AwContents awContents) throws Exception {
410         return runTestOnUiThreadAndGetResult(new Callable<Float>() {
411             @Override
412             public Float call() throws Exception {
413                 return awContents.getPageScaleFactor();
414             }
415         });
416     }
417
418     /**
419      * Returns page scale multiplied by the screen density.
420      */
421     protected float getPixelScaleOnUiThread(final AwContents awContents) throws Exception {
422         return runTestOnUiThreadAndGetResult(new Callable<Float>() {
423             @Override
424             public Float call() throws Exception {
425                 return awContents.getScale();
426             }
427         });
428     }
429
430     /**
431      * Returns whether a user can zoom the page in.
432      */
433     protected boolean canZoomInOnUiThread(final AwContents awContents) throws Exception {
434         return runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
435             @Override
436             public Boolean call() throws Exception {
437                 return awContents.canZoomIn();
438             }
439         });
440     }
441
442     /**
443      * Returns whether a user can zoom the page out.
444      */
445     protected boolean canZoomOutOnUiThread(final AwContents awContents) throws Exception {
446         return runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
447             @Override
448             public Boolean call() throws Exception {
449                 return awContents.canZoomOut();
450             }
451         });
452     }
453 }