Upstream version 10.39.233.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.AwSettings;
19 import org.chromium.android_webview.test.util.JSUtils;
20 import org.chromium.base.test.util.InMemorySharedPreferences;
21 import org.chromium.content.browser.ContentSettings;
22 import org.chromium.content.browser.test.util.CallbackHelper;
23 import org.chromium.content.browser.test.util.Criteria;
24 import org.chromium.content.browser.test.util.CriteriaHelper;
25 import org.chromium.content_public.browser.LoadUrlParams;
26
27 import java.util.Map;
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     public static final long WAIT_TIMEOUT_MS = scaleTimeout(15000);
39     public 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     public 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     public 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     public void loadUrlSync(final AwContents awContents,
106                                CallbackHelper onPageFinishedHelper,
107                                final String url) throws Exception {
108         loadUrlSync(awContents, onPageFinishedHelper, url, null);
109     }
110
111     public void loadUrlSync(final AwContents awContents,
112                                CallbackHelper onPageFinishedHelper,
113                                final String url,
114                                final Map<String, String> extraHeaders) throws Exception {
115         int currentCallCount = onPageFinishedHelper.getCallCount();
116         loadUrlAsync(awContents, url, extraHeaders);
117         onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS,
118                 TimeUnit.MILLISECONDS);
119     }
120
121     public void loadUrlSyncAndExpectError(final AwContents awContents,
122             CallbackHelper onPageFinishedHelper,
123             CallbackHelper onReceivedErrorHelper,
124             final String url) throws Exception {
125         int onErrorCallCount = onReceivedErrorHelper.getCallCount();
126         int onFinishedCallCount = onPageFinishedHelper.getCallCount();
127         loadUrlAsync(awContents, url);
128         onReceivedErrorHelper.waitForCallback(onErrorCallCount, 1, WAIT_TIMEOUT_MS,
129                 TimeUnit.MILLISECONDS);
130         onPageFinishedHelper.waitForCallback(onFinishedCallCount, 1, WAIT_TIMEOUT_MS,
131                 TimeUnit.MILLISECONDS);
132     }
133
134     /**
135      * Loads url on the UI thread but does not block.
136      */
137     public void loadUrlAsync(final AwContents awContents,
138                                 final String url) throws Exception {
139         loadUrlAsync(awContents, url, null);
140     }
141
142     public void loadUrlAsync(final AwContents awContents,
143                                 final String url,
144                                 final Map<String, String> extraHeaders) {
145         getInstrumentation().runOnMainSync(new Runnable() {
146             @Override
147             public void run() {
148                 LoadUrlParams params = new LoadUrlParams(url);
149                 params.setExtraHeaders(extraHeaders);
150                 awContents.loadUrl(params);
151             }
152         });
153     }
154
155     /**
156      * Posts url on the UI thread and blocks until onPageFinished is called.
157      */
158     public void postUrlSync(final AwContents awContents,
159             CallbackHelper onPageFinishedHelper, final String url,
160             byte[] postData) throws Exception {
161         int currentCallCount = onPageFinishedHelper.getCallCount();
162         postUrlAsync(awContents, url, postData);
163         onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS,
164                 TimeUnit.MILLISECONDS);
165     }
166
167     /**
168      * Loads url on the UI thread but does not block.
169      */
170     public void postUrlAsync(final AwContents awContents,
171             final String url, byte[] postData) throws Exception {
172         class PostUrl implements Runnable {
173             byte[] mPostData;
174             public PostUrl(byte[] postData) {
175                 mPostData = postData;
176             }
177             @Override
178             public void run() {
179                 awContents.loadUrl(LoadUrlParams.createLoadHttpPostParams(url,
180                         mPostData));
181             }
182         }
183         getInstrumentation().runOnMainSync(new PostUrl(postData));
184     }
185
186     /**
187      * Loads data on the UI thread and blocks until onPageFinished is called.
188      */
189     public void loadDataSync(final AwContents awContents,
190                                 CallbackHelper onPageFinishedHelper,
191                                 final String data, final String mimeType,
192                                 final boolean isBase64Encoded) throws Exception {
193         int currentCallCount = onPageFinishedHelper.getCallCount();
194         loadDataAsync(awContents, data, mimeType, isBase64Encoded);
195         onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS,
196                 TimeUnit.MILLISECONDS);
197     }
198
199     public void loadDataSyncWithCharset(final AwContents awContents,
200                                            CallbackHelper onPageFinishedHelper,
201                                            final String data, final String mimeType,
202                                            final boolean isBase64Encoded, final String charset)
203             throws Exception {
204         int currentCallCount = onPageFinishedHelper.getCallCount();
205         getInstrumentation().runOnMainSync(new Runnable() {
206             @Override
207             public void run() {
208                 awContents.loadUrl(LoadUrlParams.createLoadDataParams(
209                         data, mimeType, isBase64Encoded, charset));
210             }
211         });
212         onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS,
213                 TimeUnit.MILLISECONDS);
214     }
215
216     /**
217      * Loads data on the UI thread but does not block.
218      */
219     public void loadDataAsync(final AwContents awContents, final String data,
220                                  final String mimeType, final boolean isBase64Encoded)
221             throws Exception {
222         getInstrumentation().runOnMainSync(new Runnable() {
223             @Override
224             public void run() {
225                 awContents.loadUrl(LoadUrlParams.createLoadDataParams(
226                         data, mimeType, isBase64Encoded));
227             }
228         });
229     }
230
231     public void loadDataWithBaseUrlSync(final AwContents awContents,
232             CallbackHelper onPageFinishedHelper, final String data, final String mimeType,
233             final boolean isBase64Encoded, final String baseUrl,
234             final String historyUrl) throws Throwable {
235         int currentCallCount = onPageFinishedHelper.getCallCount();
236         loadDataWithBaseUrlAsync(awContents, data, mimeType, isBase64Encoded, baseUrl, historyUrl);
237         onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS,
238                 TimeUnit.MILLISECONDS);
239     }
240
241     public void loadDataWithBaseUrlAsync(final AwContents awContents,
242             final String data, final String mimeType, final boolean isBase64Encoded,
243             final String baseUrl, final String historyUrl) throws Throwable {
244         runTestOnUiThread(new Runnable() {
245             @Override
246             public void run() {
247                 awContents.loadUrl(LoadUrlParams.createLoadDataParamsWithBaseUrl(
248                         data, mimeType, isBase64Encoded, baseUrl, historyUrl));
249             }
250         });
251     }
252
253     /**
254      * Reloads the current page synchronously.
255      */
256     public void reloadSync(final AwContents awContents,
257                               CallbackHelper onPageFinishedHelper) throws Exception {
258         int currentCallCount = onPageFinishedHelper.getCallCount();
259         getInstrumentation().runOnMainSync(new Runnable() {
260             @Override
261             public void run() {
262                 awContents.getNavigationController().reload(true);
263             }
264         });
265         onPageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_MS,
266                 TimeUnit.MILLISECONDS);
267     }
268
269     /**
270      * Factory class used in creation of test AwContents instances.
271      *
272      * Test cases can provide subclass instances to the createAwTest* methods in order to create an
273      * AwContents instance with injected test dependencies.
274      */
275     public static class TestDependencyFactory extends AwContents.DependencyFactory {
276         public AwTestContainerView createAwTestContainerView(AwTestRunnerActivity activity) {
277             return new AwTestContainerView(activity, false);
278         }
279         public AwSettings createAwSettings(Context context, boolean supportsLegacyQuirks) {
280             return new AwSettings(context, false, supportsLegacyQuirks);
281         }
282     }
283
284     protected TestDependencyFactory createTestDependencyFactory() {
285         return new TestDependencyFactory();
286     }
287
288     public AwTestContainerView createAwTestContainerView(
289             final AwContentsClient awContentsClient) {
290         return createAwTestContainerView(awContentsClient, false);
291     }
292
293     public AwTestContainerView createAwTestContainerView(
294             final AwContentsClient awContentsClient, boolean supportsLegacyQuirks) {
295         AwTestContainerView testContainerView =
296                 createDetachedAwTestContainerView(awContentsClient, supportsLegacyQuirks);
297         getActivity().addView(testContainerView);
298         testContainerView.requestFocus();
299         return testContainerView;
300     }
301
302     // The browser context needs to be a process-wide singleton.
303     private AwBrowserContext mBrowserContext =
304             new AwBrowserContext(new InMemorySharedPreferences());
305
306     public AwTestContainerView createDetachedAwTestContainerView(
307             final AwContentsClient awContentsClient) {
308         return createDetachedAwTestContainerView(awContentsClient, false);
309     }
310
311     public AwTestContainerView createDetachedAwTestContainerView(
312             final AwContentsClient awContentsClient, boolean supportsLegacyQuirks) {
313         final TestDependencyFactory testDependencyFactory = createTestDependencyFactory();
314         final AwTestContainerView testContainerView =
315             testDependencyFactory.createAwTestContainerView(getActivity());
316         AwSettings awSettings = testDependencyFactory.createAwSettings(getActivity(),
317                 supportsLegacyQuirks);
318         testContainerView.initialize(new AwContents(
319                 mBrowserContext, testContainerView, testContainerView.getContext(),
320                 testContainerView.getInternalAccessDelegate(),
321                 testContainerView.getNativeGLDelegate(), awContentsClient,
322                 awSettings, testDependencyFactory));
323         return testContainerView;
324     }
325
326     public AwTestContainerView createAwTestContainerViewOnMainSync(
327             final AwContentsClient client) throws Exception {
328         return createAwTestContainerViewOnMainSync(client, false);
329     }
330
331     public AwTestContainerView createAwTestContainerViewOnMainSync(
332             final AwContentsClient client, final boolean supportsLegacyQuirks) throws Exception {
333         final AtomicReference<AwTestContainerView> testContainerView =
334                 new AtomicReference<AwTestContainerView>();
335         getInstrumentation().runOnMainSync(new Runnable() {
336             @Override
337             public void run() {
338                 testContainerView.set(createAwTestContainerView(client, supportsLegacyQuirks));
339             }
340         });
341         return testContainerView.get();
342     }
343
344     public void destroyAwContentsOnMainSync(final AwContents awContents) {
345         if (awContents == null) return;
346         getInstrumentation().runOnMainSync(new Runnable() {
347             @Override
348             public void run() {
349                 awContents.destroy();
350             }
351         });
352     }
353
354     public String getTitleOnUiThread(final AwContents awContents) throws Exception {
355         return runTestOnUiThreadAndGetResult(new Callable<String>() {
356             @Override
357             public String call() throws Exception {
358                 return awContents.getTitle();
359             }
360         });
361     }
362
363     public ContentSettings getContentSettingsOnUiThread(
364             final AwContents awContents) throws Exception {
365         return runTestOnUiThreadAndGetResult(new Callable<ContentSettings>() {
366             @Override
367             public ContentSettings call() throws Exception {
368                 return awContents.getContentViewCore().getContentSettings();
369             }
370         });
371     }
372
373     public AwSettings getAwSettingsOnUiThread(
374             final AwContents awContents) throws Exception {
375         return runTestOnUiThreadAndGetResult(new Callable<AwSettings>() {
376             @Override
377             public AwSettings call() throws Exception {
378                 return awContents.getSettings();
379             }
380         });
381     }
382
383     /**
384      * Executes the given snippet of JavaScript code within the given ContentView. Returns the
385      * result of its execution in JSON format.
386      */
387     public String executeJavaScriptAndWaitForResult(final AwContents awContents,
388             TestAwContentsClient viewClient, final String code) throws Exception {
389         return JSUtils.executeJavaScriptAndWaitForResult(this, awContents,
390                 viewClient.getOnEvaluateJavaScriptResultHelper(),
391                 code);
392     }
393
394     /**
395      * Wrapper around CriteriaHelper.pollForCriteria. This uses AwTestBase-specifc timeouts and
396      * treats timeouts and exceptions as test failures automatically.
397      */
398     public static void poll(final Callable<Boolean> callable) throws Exception {
399         assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
400             @Override
401             public boolean isSatisfied() {
402                 try {
403                     return callable.call();
404                 } catch (Throwable e) {
405                     Log.e(TAG, "Exception while polling.", e);
406                     return false;
407                 }
408             }
409         }, WAIT_TIMEOUT_MS, CHECK_INTERVAL));
410     }
411
412     /**
413      * Wrapper around {@link AwTestBase#poll()} but runs the callable on the UI thread.
414      */
415     public void pollOnUiThread(final Callable<Boolean> callable) throws Exception {
416         poll(new Callable<Boolean>() {
417             @Override
418             public Boolean call() throws Exception {
419                 return runTestOnUiThreadAndGetResult(callable);
420             }
421         });
422     }
423
424     /**
425      * Clears the resource cache. Note that the cache is per-application, so this will clear the
426      * cache for all WebViews used.
427      */
428     public void clearCacheOnUiThread(
429             final AwContents awContents,
430             final boolean includeDiskFiles) throws Exception {
431         getInstrumentation().runOnMainSync(new Runnable() {
432             @Override
433             public void run() {
434                 awContents.clearCache(includeDiskFiles);
435             }
436         });
437     }
438
439     /**
440      * Returns pure page scale.
441      */
442     public float getScaleOnUiThread(final AwContents awContents) throws Exception {
443         return runTestOnUiThreadAndGetResult(new Callable<Float>() {
444             @Override
445             public Float call() throws Exception {
446                 return awContents.getPageScaleFactor();
447             }
448         });
449     }
450
451     /**
452      * Returns page scale multiplied by the screen density.
453      */
454     public float getPixelScaleOnUiThread(final AwContents awContents) throws Exception {
455         return runTestOnUiThreadAndGetResult(new Callable<Float>() {
456             @Override
457             public Float call() throws Exception {
458                 return awContents.getScale();
459             }
460         });
461     }
462
463     /**
464      * Returns whether a user can zoom the page in.
465      */
466     public boolean canZoomInOnUiThread(final AwContents awContents) throws Exception {
467         return runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
468             @Override
469             public Boolean call() throws Exception {
470                 return awContents.canZoomIn();
471             }
472         });
473     }
474
475     /**
476      * Returns whether a user can zoom the page out.
477      */
478     public boolean canZoomOutOnUiThread(final AwContents awContents) throws Exception {
479         return runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
480             @Override
481             public Boolean call() throws Exception {
482                 return awContents.canZoomOut();
483             }
484         });
485     }
486
487 }