Upstream version 5.34.104.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     protected void loadDataWithBaseUrlSync(final AwContents awContents,
217             CallbackHelper onPageFinishedHelper, final String data, final String mimeType,
218             final boolean isBase64Encoded, final String baseUrl,
219             final String historyUrl) throws Throwable {
220         int currentCallCount = onPageFinishedHelper.getCallCount();
221         loadDataWithBaseUrlAsync(awContents, data, mimeType, isBase64Encoded, baseUrl, historyUrl);
222         onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS,
223                 TimeUnit.MILLISECONDS);
224     }
225
226     protected void loadDataWithBaseUrlAsync(final AwContents awContents,
227             final String data, final String mimeType, final boolean isBase64Encoded,
228             final String baseUrl, final String historyUrl) throws Throwable {
229         runTestOnUiThread(new Runnable() {
230             @Override
231             public void run() {
232                 awContents.loadUrl(LoadUrlParams.createLoadDataParamsWithBaseUrl(
233                         data, mimeType, isBase64Encoded, baseUrl, historyUrl));
234             }
235         });
236     }
237
238     /**
239      * Reloads the current page synchronously.
240      */
241     protected void reloadSync(final AwContents awContents,
242                               CallbackHelper onPageFinishedHelper) throws Exception {
243         int currentCallCount = onPageFinishedHelper.getCallCount();
244         getInstrumentation().runOnMainSync(new Runnable() {
245             @Override
246             public void run() {
247                 awContents.getContentViewCore().reload(true);
248             }
249         });
250         onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS,
251                 TimeUnit.MILLISECONDS);
252     }
253
254     /**
255      * Factory class used in creation of test AwContents instances.
256      *
257      * Test cases can provide subclass instances to the createAwTest* methods in order to create an
258      * AwContents instance with injected test dependencies.
259      */
260     public static class TestDependencyFactory {
261         public AwLayoutSizer createLayoutSizer() {
262             return new AwLayoutSizer();
263         }
264         public AwTestContainerView createAwTestContainerView(AwTestRunnerActivity activity) {
265             return new AwTestContainerView(activity);
266         }
267         public AwSettings createAwSettings(Context context, boolean supportsLegacyQuirks) {
268             return new AwSettings(context, false, supportsLegacyQuirks);
269         }
270     }
271
272     protected TestDependencyFactory createTestDependencyFactory() {
273         return new TestDependencyFactory();
274     }
275
276     protected AwTestContainerView createAwTestContainerView(
277             final AwContentsClient awContentsClient) {
278         return createAwTestContainerView(awContentsClient, false);
279     }
280
281     protected AwTestContainerView createAwTestContainerView(
282             final AwContentsClient awContentsClient, boolean supportsLegacyQuirks) {
283         AwTestContainerView testContainerView =
284                 createDetachedAwTestContainerView(awContentsClient, supportsLegacyQuirks);
285         getActivity().addView(testContainerView);
286         testContainerView.requestFocus();
287         return testContainerView;
288     }
289
290     // The browser context needs to be a process-wide singleton.
291     private AwBrowserContext mBrowserContext =
292             new AwBrowserContext(new InMemorySharedPreferences());
293
294     protected AwTestContainerView createDetachedAwTestContainerView(
295             final AwContentsClient awContentsClient) {
296         return createDetachedAwTestContainerView(awContentsClient, false);
297     }
298
299     protected AwTestContainerView createDetachedAwTestContainerView(
300             final AwContentsClient awContentsClient, boolean supportsLegacyQuirks) {
301         final TestDependencyFactory testDependencyFactory = createTestDependencyFactory();
302         final AwTestContainerView testContainerView =
303             testDependencyFactory.createAwTestContainerView(getActivity());
304         AwSettings awSettings = testDependencyFactory.createAwSettings(getActivity(),
305                 supportsLegacyQuirks);
306         testContainerView.initialize(new AwContents(
307                 mBrowserContext, testContainerView, testContainerView.getInternalAccessDelegate(),
308                 awContentsClient, awSettings, testDependencyFactory.createLayoutSizer()));
309         AwContents.setShouldDownloadFavicons();
310         return testContainerView;
311     }
312
313     protected AwTestContainerView createAwTestContainerViewOnMainSync(
314             final AwContentsClient client) throws Exception {
315         return createAwTestContainerViewOnMainSync(client, false);
316     }
317
318     protected AwTestContainerView createAwTestContainerViewOnMainSync(
319             final AwContentsClient client, final boolean supportsLegacyQuirks) throws Exception {
320         final AtomicReference<AwTestContainerView> testContainerView =
321                 new AtomicReference<AwTestContainerView>();
322         getInstrumentation().runOnMainSync(new Runnable() {
323             @Override
324             public void run() {
325                 testContainerView.set(createAwTestContainerView(client, supportsLegacyQuirks));
326             }
327         });
328         return testContainerView.get();
329     }
330
331     protected void destroyAwContentsOnMainSync(final AwContents awContents) {
332         if (awContents == null) return;
333         getInstrumentation().runOnMainSync(new Runnable() {
334             @Override
335             public void run() {
336                 awContents.destroy();
337             }
338         });
339     }
340
341     protected String getTitleOnUiThread(final AwContents awContents) throws Exception {
342         return runTestOnUiThreadAndGetResult(new Callable<String>() {
343             @Override
344             public String call() throws Exception {
345                 return awContents.getContentViewCore().getTitle();
346             }
347         });
348     }
349
350     protected ContentSettings getContentSettingsOnUiThread(
351             final AwContents awContents) throws Exception {
352         return runTestOnUiThreadAndGetResult(new Callable<ContentSettings>() {
353             @Override
354             public ContentSettings call() throws Exception {
355                 return awContents.getContentViewCore().getContentSettings();
356             }
357         });
358     }
359
360     protected AwSettings getAwSettingsOnUiThread(
361             final AwContents awContents) throws Exception {
362         return runTestOnUiThreadAndGetResult(new Callable<AwSettings>() {
363             @Override
364             public AwSettings call() throws Exception {
365                 return awContents.getSettings();
366             }
367         });
368     }
369
370     /**
371      * Executes the given snippet of JavaScript code within the given ContentView. Returns the
372      * result of its execution in JSON format.
373      */
374     protected String executeJavaScriptAndWaitForResult(final AwContents awContents,
375             TestAwContentsClient viewClient, final String code) throws Exception {
376         return JSUtils.executeJavaScriptAndWaitForResult(this, awContents,
377                 viewClient.getOnEvaluateJavaScriptResultHelper(),
378                 code);
379     }
380
381     /**
382      * Wrapper around CriteriaHelper.pollForCriteria. This uses AwTestBase-specifc timeouts and
383      * treats timeouts and exceptions as test failures automatically.
384      */
385     protected static void poll(final Callable<Boolean> callable) throws Exception {
386         assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
387             @Override
388             public boolean isSatisfied() {
389                 try {
390                     return callable.call();
391                 } catch (Throwable e) {
392                     Log.e(TAG, "Exception while polling.", e);
393                     return false;
394                 }
395             }
396         }, WAIT_TIMEOUT_MS, CHECK_INTERVAL));
397     }
398
399     /**
400      * Wrapper around {@link AwTestBase#poll()} but runs the callable on the UI thread.
401      */
402     protected void pollOnUiThread(final Callable<Boolean> callable) throws Exception {
403         poll(new Callable<Boolean>() {
404             @Override
405             public Boolean call() throws Exception {
406                 return runTestOnUiThreadAndGetResult(callable);
407             }
408         });
409     }
410
411     /**
412      * Clears the resource cache. Note that the cache is per-application, so this will clear the
413      * cache for all WebViews used.
414      */
415     protected void clearCacheOnUiThread(
416             final AwContents awContents,
417             final boolean includeDiskFiles) throws Exception {
418         getInstrumentation().runOnMainSync(new Runnable() {
419             @Override
420             public void run() {
421                 awContents.clearCache(includeDiskFiles);
422             }
423         });
424     }
425
426     /**
427      * Returns pure page scale.
428      */
429     protected float getScaleOnUiThread(final AwContents awContents) throws Exception {
430         return runTestOnUiThreadAndGetResult(new Callable<Float>() {
431             @Override
432             public Float call() throws Exception {
433                 return awContents.getPageScaleFactor();
434             }
435         });
436     }
437
438     /**
439      * Returns page scale multiplied by the screen density.
440      */
441     protected float getPixelScaleOnUiThread(final AwContents awContents) throws Exception {
442         return runTestOnUiThreadAndGetResult(new Callable<Float>() {
443             @Override
444             public Float call() throws Exception {
445                 return awContents.getScale();
446             }
447         });
448     }
449
450     /**
451      * Returns whether a user can zoom the page in.
452      */
453     protected boolean canZoomInOnUiThread(final AwContents awContents) throws Exception {
454         return runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
455             @Override
456             public Boolean call() throws Exception {
457                 return awContents.canZoomIn();
458             }
459         });
460     }
461
462     /**
463      * Returns whether a user can zoom the page out.
464      */
465     protected boolean canZoomOutOnUiThread(final AwContents awContents) throws Exception {
466         return runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
467             @Override
468             public Boolean call() throws Exception {
469                 return awContents.canZoomOut();
470             }
471         });
472     }
473 }