1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Copyright (c) 2013-2014 Intel Corporation. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
6 package org.xwalk.core.xwview.test;
8 import android.app.Activity;
9 import android.content.Context;
10 import android.net.Uri;
11 import android.test.ActivityInstrumentationTestCase2;
12 import android.util.Log;
13 import android.view.KeyEvent;
14 import android.webkit.ValueCallback;
15 import android.webkit.WebResourceResponse;
17 import java.io.InputStream;
18 import java.io.IOException;
19 import java.util.concurrent.atomic.AtomicReference;
20 import java.util.concurrent.Callable;
21 import java.util.concurrent.FutureTask;
22 import java.util.concurrent.TimeUnit;
24 import junit.framework.Assert;
26 import org.chromium.content_public.browser.LoadUrlParams;
27 import org.chromium.content.browser.test.util.CallbackHelper;
28 import org.chromium.content.browser.test.util.Criteria;
29 import org.chromium.content.browser.test.util.CriteriaHelper;
31 import org.xwalk.core.XWalkJavascriptResult;
32 import org.xwalk.core.XWalkNavigationHistory;
33 import org.xwalk.core.XWalkNavigationItem;
34 import org.xwalk.core.XWalkResourceClient;
35 import org.xwalk.core.XWalkUIClient;
36 import org.xwalk.core.XWalkView;
38 public class XWalkViewTestBase
39 extends ActivityInstrumentationTestCase2<XWalkViewTestRunnerActivity> {
40 protected final static int WAIT_TIMEOUT_SECONDS = 15;
41 protected final static long WAIT_TIMEOUT_MS = 2000;
42 private final static int CHECK_INTERVAL = 100;
43 private final static String TAG = "XWalkViewTestBase";
44 private XWalkView mXWalkView;
45 final TestHelperBridge mTestHelperBridge = new TestHelperBridge();
47 class TestXWalkUIClientBase extends XWalkUIClient {
48 TestHelperBridge mInnerContentsClient;
49 public TestXWalkUIClientBase(TestHelperBridge client) {
50 super(getXWalkView());
51 mInnerContentsClient = client;
55 public void onPageLoadStarted(XWalkView view, String url) {
56 mInnerContentsClient.onPageStarted(url);
60 public void onPageLoadStopped(XWalkView view, String url, LoadStatus status) {
61 mInnerContentsClient.onPageFinished(url, status);
65 public void onReceivedTitle(XWalkView view, String title) {
66 mInnerContentsClient.onTitleChanged(title);
70 public void onJavascriptCloseWindow(XWalkView view) {
71 mInnerContentsClient.onJavascriptCloseWindow();
75 public void onScaleChanged(XWalkView view, float oldScale, float newScale) {
76 mInnerContentsClient.onScaleChanged(newScale);
80 public void onRequestFocus(XWalkView view) {
81 mInnerContentsClient.onRequestFocus();
85 public boolean onJavascriptModalDialog(XWalkView view,
86 XWalkUIClient.JavascriptMessageType type, String url, String message,
87 String defaultValue, XWalkJavascriptResult result) {
88 return mInnerContentsClient.onJavascriptModalDialog(message);
92 public void openFileChooser(XWalkView view, ValueCallback<Uri> uploadFile,
93 String acceptType, String capture) {
94 mInnerContentsClient.openFileChooser(uploadFile);
98 public void onFullscreenToggled(XWalkView view, boolean enterFullscreen) {
99 mInnerContentsClient.onFullscreenToggled(enterFullscreen);
103 public boolean shouldOverrideKeyEvent(XWalkView view, KeyEvent event) {
104 return mInnerContentsClient.overrideOrUnhandledKeyEvent(event);
108 class TestXWalkUIClient extends TestXWalkUIClientBase {
109 public TestXWalkUIClient() {
110 super(mTestHelperBridge);
114 class TestXWalkResourceClientBase extends XWalkResourceClient {
115 TestHelperBridge mInnerContentsClient;
116 public TestXWalkResourceClientBase(TestHelperBridge client) {
118 mInnerContentsClient = client;
122 public void onLoadStarted(XWalkView view, String url) {
123 mInnerContentsClient.onLoadStarted(url);
127 public void onReceivedLoadError(XWalkView view, int errorCode, String description, String failingUrl) {
128 mInnerContentsClient.onReceivedLoadError(errorCode, description, failingUrl);
132 public WebResourceResponse shouldInterceptLoadRequest(XWalkView view,
134 return mInnerContentsClient.shouldInterceptLoadRequest(url);
138 public void onProgressChanged(XWalkView view, int progressInPercent) {
139 mTestHelperBridge.onProgressChanged(progressInPercent);
143 public boolean shouldOverrideUrlLoading(XWalkView view, String url) {
144 return mTestHelperBridge.shouldOverrideUrlLoading(url);
148 class TestXWalkResourceClient extends TestXWalkResourceClientBase {
149 public TestXWalkResourceClient() {
150 super(mTestHelperBridge);
154 void setUIClient(final XWalkUIClient client) {
155 getInstrumentation().runOnMainSync(new Runnable() {
158 getXWalkView().setUIClient(client);
163 void setResourceClient(final XWalkResourceClient client) {
164 getInstrumentation().runOnMainSync(new Runnable() {
167 getXWalkView().setResourceClient(client);
172 public XWalkViewTestBase() {
173 super(XWalkViewTestRunnerActivity.class);
177 protected void setUp() throws Exception {
180 // Must call getActivity() here but not in main thread.
181 final Activity activity = getActivity();
182 getInstrumentation().runOnMainSync(new Runnable() {
185 mXWalkView = new XWalkView(activity, activity);
186 getActivity().addView(mXWalkView);
187 mXWalkView.setUIClient(new TestXWalkUIClient());
188 mXWalkView.setResourceClient(new TestXWalkResourceClient());
189 // mXWalkView.getXWalkViewContentForTest().installWebContentsObserverForTest(mTestHelperBridge);
194 protected boolean pollOnUiThread(final Callable<Boolean> callable) throws Exception {
195 return CriteriaHelper.pollForCriteria(new Criteria() {
197 public boolean isSatisfied() {
199 return runTestOnUiThreadAndGetResult(callable);
200 } catch (Throwable e) {
207 protected void loadJavaScriptUrl(final String url) throws Exception {
208 if (!url.startsWith("javascript:")) {
209 Log.w(TAG, "loadJavascriptUrl only accepts javascript: url");
215 protected void loadUrlSync(final String url) throws Exception {
216 CallbackHelper pageFinishedHelper = mTestHelperBridge.getOnPageFinishedHelper();
217 int currentCallCount = pageFinishedHelper.getCallCount();
220 pageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_SECONDS,
224 protected void loadUrlAsync(final String url) throws Exception {
225 getInstrumentation().runOnMainSync(new Runnable() {
228 mXWalkView.load(url, null);
233 protected void loadDataSync(final String url, final String data, final String mimeType,
234 final boolean isBase64Encoded) throws Exception {
235 CallbackHelper pageFinishedHelper = mTestHelperBridge.getOnPageFinishedHelper();
236 int currentCallCount = pageFinishedHelper.getCallCount();
237 loadDataAsync(url, data, mimeType, isBase64Encoded);
238 pageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_SECONDS,
242 protected void loadDataAsync(final String url, final String data, final String mimeType,
243 final boolean isBase64Encoded) throws Exception {
244 getInstrumentation().runOnMainSync(new Runnable() {
247 mXWalkView.load(url, data);
252 protected void loadUrlSyncByContent(final XWalkView xWalkContent,
253 final TestHelperBridge contentsClient,
254 final String url) throws Exception {
255 CallbackHelper pageFinishedHelper = contentsClient.getOnPageFinishedHelper();
256 int currentCallCount = pageFinishedHelper.getCallCount();
257 loadUrlAsyncByContent(xWalkContent, url);
259 pageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_SECONDS,
263 protected void loadUrlAsyncByContent(final XWalkView xWalkContent,
264 final String url) throws Exception {
265 getInstrumentation().runOnMainSync(new Runnable() {
268 xWalkContent.load(url, null);
273 protected String getTitleOnUiThread() throws Exception {
274 return runTestOnUiThreadAndGetResult(new Callable<String>() {
276 public String call() throws Exception {
277 return mXWalkView.getTitle();
282 protected <R> R runTestOnUiThreadAndGetResult(Callable<R> callable)
284 FutureTask<R> task = new FutureTask<R>(callable);
285 getInstrumentation().waitForIdleSync();
286 getInstrumentation().runOnMainSync(task);
290 protected String getFileContent(String fileName) {
292 Context context = getInstrumentation().getContext();
293 InputStream inputStream = context.getAssets().open(fileName);
294 int size = inputStream.available();
295 byte buffer[] = new byte[size];
296 inputStream.read(buffer);
299 String fileContent = new String(buffer);
301 } catch (IOException e) {
302 throw new RuntimeException(e);
306 protected String getTitleOnUiThreadByContent(final XWalkView xWalkContent) throws Exception {
307 return runTestOnUiThreadAndGetResult(new Callable<String>() {
309 public String call() throws Exception {
310 String title = xWalkContent.getTitle();
316 protected XWalkView createXWalkViewContainerOnMainSync(
317 final Context context,
318 final XWalkUIClient uiClient,
319 final XWalkResourceClient resourceClient) throws Exception {
320 final AtomicReference<XWalkView> xWalkViewContainer =
321 new AtomicReference<XWalkView>();
322 getInstrumentation().runOnMainSync(new Runnable() {
325 xWalkViewContainer.set(new XWalkView(context, getActivity()));
326 getActivity().addView(xWalkViewContainer.get());
327 xWalkViewContainer.get().setUIClient(uiClient);
328 xWalkViewContainer.get().setResourceClient(resourceClient);
332 return xWalkViewContainer.get();
335 protected void loadAssetFile(String fileName) throws Exception {
336 String fileContent = getFileContent(fileName);
337 loadDataSync(fileName, fileContent, "text/html", false);
340 public void loadAssetFileAndWaitForTitle(String fileName) throws Exception {
341 CallbackHelper getTitleHelper = mTestHelperBridge.getOnTitleUpdatedHelper();
342 int currentCallCount = getTitleHelper.getCallCount();
343 String fileContent = getFileContent(fileName);
345 loadDataSync(fileName, fileContent, "text/html", false);
347 getTitleHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_SECONDS,
351 protected XWalkView getXWalkView() {
355 protected void runTestWaitPageFinished(Runnable runnable) throws Exception{
356 CallbackHelper pageFinishedHelper = mTestHelperBridge.getOnPageFinishedHelper();
357 int currentCallCount = pageFinishedHelper.getCallCount();
359 pageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_SECONDS,
363 protected void reloadSync(final int mode) throws Exception {
364 runTestWaitPageFinished(new Runnable(){
367 getInstrumentation().runOnMainSync(new Runnable() {
370 mXWalkView.reload(mode);
377 protected void goBackSync() throws Throwable {
378 runTestWaitPageFinished(new Runnable(){
381 getInstrumentation().runOnMainSync(new Runnable() {
384 mXWalkView.getNavigationHistory().navigate(
385 XWalkNavigationHistory.Direction.BACKWARD, 1);
392 protected void goForwardSync() throws Throwable {
393 runTestWaitPageFinished(new Runnable(){
396 getInstrumentation().runOnMainSync(new Runnable() {
399 mXWalkView.getNavigationHistory().navigate(
400 XWalkNavigationHistory.Direction.FORWARD, 1);
407 protected void clearHistoryOnUiThread() throws Exception {
408 getInstrumentation().runOnMainSync(new Runnable() {
411 mXWalkView.getNavigationHistory().clear();
416 protected boolean canGoBackOnUiThread() throws Throwable {
417 return runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
419 public Boolean call() {
420 return mXWalkView.getNavigationHistory().canGoBack();
425 protected boolean canGoForwardOnUiThread() throws Throwable {
426 return runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
428 public Boolean call() {
429 return mXWalkView.getNavigationHistory().canGoForward();
434 protected int historySizeOnUiThread() throws Throwable {
435 return runTestOnUiThreadAndGetResult(new Callable<Integer>() {
437 public Integer call() {
438 return mXWalkView.getNavigationHistory().size();
443 protected boolean hasItemAtOnUiThread(final int index) throws Throwable {
444 return runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
446 public Boolean call() {
447 return mXWalkView.getNavigationHistory().hasItemAt(index);
452 protected XWalkNavigationItem getItemAtOnUiThread(final int index) throws Throwable {
453 return runTestOnUiThreadAndGetResult(new Callable<XWalkNavigationItem>() {
455 public XWalkNavigationItem call() {
456 return mXWalkView.getNavigationHistory().getItemAt(index);
461 protected XWalkNavigationItem getCurrentItemOnUiThread() throws Throwable {
462 return runTestOnUiThreadAndGetResult(new Callable<XWalkNavigationItem>() {
464 public XWalkNavigationItem call() {
465 return mXWalkView.getNavigationHistory().getCurrentItem();
470 protected String executeJavaScriptAndWaitForResult(final String code) throws Exception {
472 final TestHelperBridge.OnEvaluateJavaScriptResultHelper helper =
473 mTestHelperBridge.getOnEvaluateJavaScriptResultHelper();
474 getInstrumentation().runOnMainSync(new Runnable() {
477 helper.evaluateJavascript(mXWalkView, code);
480 helper.waitUntilHasValue();
481 Assert.assertTrue("Failed to retrieve JavaScript evaluation results.", helper.hasValue());
482 return helper.getJsonResultAndClear();
485 protected String getUrlOnUiThread() throws Exception {
486 return runTestOnUiThreadAndGetResult(new Callable<String>() {
488 public String call() throws Exception {
489 return mXWalkView.getUrl();
494 protected void clearCacheOnUiThread(final boolean includeDiskFiles) throws Exception {
495 getInstrumentation().runOnMainSync(new Runnable() {
498 mXWalkView.clearCache(includeDiskFiles);
503 protected String getAPIVersionOnUiThread() throws Exception {
504 return runTestOnUiThreadAndGetResult(new Callable<String>() {
506 public String call() throws Exception {
507 return mXWalkView.getAPIVersion();
512 protected String getXWalkVersionOnUiThread() throws Exception {
513 return runTestOnUiThreadAndGetResult(new Callable<String>() {
515 public String call() throws Exception {
516 return mXWalkView.getXWalkVersion();
521 public void clickOnElementId(final String id, String frameName) throws Exception {
523 if (frameName != null) {
524 str = "top.window." + "LeftFrame" + ".document.getElementById('" + id + "')";
526 str = "document.getElementById('" + id + "')";
528 final String script1 = str + " != null";
529 final String script2 = str + ".dispatchEvent(evObj);";
530 Assert.assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
532 public boolean isSatisfied() {
534 String idIsNotNull = executeJavaScriptAndWaitForResult(script1);
535 return idIsNotNull.equals("true");
536 } catch (Throwable t) {
538 Assert.fail("Failed to check if DOM is loaded: " + t.toString());
542 }, WAIT_TIMEOUT_MS, CHECK_INTERVAL));
545 String result = executeJavaScriptAndWaitForResult(
546 "var evObj = document.createEvent('Events'); " +
547 "evObj.initEvent('click', true, false); " +
549 "console.log('element with id [" + id + "] clicked');");
550 } catch (Throwable t) {
555 public void simulateKeyAction(final int action) {
556 new Thread(new Runnable() {
559 getInstrumentation().sendKeySync(new KeyEvent(action,
560 KeyEvent.KEYCODE_DPAD_CENTER));
561 } catch (Exception e) {
568 protected void stopLoading() throws Exception {
569 getInstrumentation().runOnMainSync(new Runnable() {
572 mXWalkView.stopLoading();