1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Copyright (c) 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.internal.xwview.test;
8 import android.app.Activity;
9 import android.content.Context;
10 import android.test.ActivityInstrumentationTestCase2;
11 import android.util.Log;
12 import android.view.Gravity;
13 import android.view.View;
14 import android.view.ViewGroup;
15 import android.view.WindowManager;
16 import android.webkit.WebResourceResponse;
17 import android.widget.FrameLayout;
19 import java.io.InputStream;
20 import java.io.IOException;
21 import java.util.concurrent.atomic.AtomicReference;
22 import java.util.concurrent.Callable;
23 import java.util.concurrent.FutureTask;
24 import java.util.concurrent.TimeoutException;
25 import java.util.concurrent.TimeUnit;
27 import junit.framework.Assert;
29 import org.chromium.content.browser.ContentViewCore;
30 import org.chromium.content.browser.test.util.CallbackHelper;
31 import org.chromium.content.browser.test.util.Criteria;
32 import org.chromium.content.browser.test.util.CriteriaHelper;
34 import org.xwalk.core.internal.XWalkNavigationHistoryInternal;
35 import org.xwalk.core.internal.XWalkNavigationItemInternal;
36 import org.xwalk.core.internal.XWalkResourceClientInternal;
37 import org.xwalk.core.internal.XWalkSettings;
38 import org.xwalk.core.internal.XWalkUIClientInternal;
39 import org.xwalk.core.internal.XWalkViewInternal;
40 import org.xwalk.core.internal.XWalkWebChromeClient;
42 public class XWalkViewInternalTestBase
43 extends ActivityInstrumentationTestCase2<XWalkViewInternalTestRunnerActivity> {
44 protected final static int WAIT_TIMEOUT_SECONDS = 15;
45 private final static String TAG = "XWalkViewInternalTestBase";
46 private XWalkViewInternal mXWalkViewInternal;
47 final TestHelperBridge mTestHelperBridge = new TestHelperBridge();
49 class TestXWalkUIClientInternalBase extends XWalkUIClientInternal {
50 TestHelperBridge mInnerContentsClient;
51 public TestXWalkUIClientInternalBase(TestHelperBridge client) {
52 super(getXWalkView());
53 mInnerContentsClient = client;
57 public void onPageLoadStarted(XWalkViewInternal view, String url) {
58 mInnerContentsClient.onPageStarted(url);
62 public void onPageLoadStopped(XWalkViewInternal view, String url, LoadStatusInternal status) {
63 mInnerContentsClient.onPageFinished(url);
67 public void onReceivedTitle(XWalkViewInternal view, String title) {
68 mInnerContentsClient.onTitleChanged(title);
72 class TestXWalkUIClientInternal extends TestXWalkUIClientInternalBase {
73 public TestXWalkUIClientInternal() {
74 super(mTestHelperBridge);
78 class TestXWalkResourceClientBase extends XWalkResourceClientInternal {
79 TestHelperBridge mInnerContentsClient;
80 public TestXWalkResourceClientBase(TestHelperBridge client) {
81 super(mXWalkViewInternal);
82 mInnerContentsClient = client;
86 public void onLoadStarted(XWalkViewInternal view, String url) {
87 mInnerContentsClient.onLoadStarted(url);
91 public void onReceivedLoadError(XWalkViewInternal view, int errorCode,
92 String description, String failingUrl) {
93 mInnerContentsClient.onReceivedLoadError(errorCode, description, failingUrl);
97 public WebResourceResponse shouldInterceptLoadRequest(XWalkViewInternal view,
99 return mInnerContentsClient.shouldInterceptLoadRequest(url);
103 class TestXWalkResourceClient extends TestXWalkResourceClientBase {
104 public TestXWalkResourceClient() {
105 super(mTestHelperBridge);
109 class TestXWalkWebChromeClientBase extends XWalkWebChromeClient {
110 private CallbackHelper mOnShowCustomViewCallbackHelper = new CallbackHelper();
111 private CallbackHelper mOnHideCustomViewCallbackHelper = new CallbackHelper();
113 private Activity mActivity = getActivity();
114 private View mCustomView;
115 private XWalkWebChromeClient.CustomViewCallback mExitCallback;
117 public TestXWalkWebChromeClientBase() {
118 super(mXWalkViewInternal);
122 public void onShowCustomView(View view, XWalkWebChromeClient.CustomViewCallback callback) {
124 mExitCallback = callback;
125 mActivity.getWindow().setFlags(
126 WindowManager.LayoutParams.FLAG_FULLSCREEN,
127 WindowManager.LayoutParams.FLAG_FULLSCREEN);
129 mActivity.getWindow().addContentView(view,
130 new FrameLayout.LayoutParams(
131 ViewGroup.LayoutParams.MATCH_PARENT,
132 ViewGroup.LayoutParams.MATCH_PARENT,
134 mOnShowCustomViewCallbackHelper.notifyCalled();
138 public void onHideCustomView() {
139 mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
140 mOnHideCustomViewCallbackHelper.notifyCalled();
143 public XWalkWebChromeClient.CustomViewCallback getExitCallback() {
144 return mExitCallback;
147 public View getCustomView() {
151 public boolean wasCustomViewShownCalled() {
152 return mOnShowCustomViewCallbackHelper.getCallCount() > 0;
155 public void waitForCustomViewShown() throws TimeoutException, InterruptedException {
156 mOnShowCustomViewCallbackHelper.waitForCallback(0, 1, WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
159 public void waitForCustomViewHidden() throws InterruptedException, TimeoutException {
160 mOnHideCustomViewCallbackHelper.waitForCallback(0, 1, WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
164 void setUIClient(final XWalkUIClientInternal client) {
165 getInstrumentation().runOnMainSync(new Runnable() {
168 getXWalkView().setUIClient(client);
173 void setResourceClient(final XWalkResourceClientInternal client) {
174 getInstrumentation().runOnMainSync(new Runnable() {
177 getXWalkView().setResourceClient(client);
182 void setXWalkWebChromeClient(final TestXWalkWebChromeClientBase client) {
183 getInstrumentation().runOnMainSync(new Runnable() {
186 mXWalkViewInternal.setXWalkWebChromeClient(client);
191 static class ViewPair {
192 private final XWalkViewInternal view0;
193 private final TestHelperBridge client0;
194 private final XWalkViewInternal view1;
195 private final TestHelperBridge client1;
197 ViewPair(XWalkViewInternal view0, TestHelperBridge client0,
198 XWalkViewInternal view1, TestHelperBridge client1) {
200 this.client0 = client0;
202 this.client1 = client1;
205 XWalkViewInternal getView0() {
209 TestHelperBridge getClient0() {
213 XWalkViewInternal getView1() {
217 TestHelperBridge getClient1() {
222 public XWalkViewInternalTestBase() {
223 super(XWalkViewInternalTestRunnerActivity.class);
227 protected void setUp() throws Exception {
230 // Must call getActivity() here but not in main thread.
231 final Activity activity = getActivity();
232 getInstrumentation().runOnMainSync(new Runnable() {
235 mXWalkViewInternal = new XWalkViewInternal(activity, activity);
236 getActivity().addView(mXWalkViewInternal);
237 mXWalkViewInternal.setUIClient(new TestXWalkUIClientInternal());
238 mXWalkViewInternal.setResourceClient(new TestXWalkResourceClient());
243 protected boolean pollOnUiThread(final Callable<Boolean> callable) throws Exception {
244 return CriteriaHelper.pollForCriteria(new Criteria() {
246 public boolean isSatisfied() {
248 return runTestOnUiThreadAndGetResult(callable);
249 } catch (Throwable e) {
256 protected void loadJavaScriptUrl(final String url) throws Exception {
257 if (!url.startsWith("javascript:")) {
258 Log.w(TAG, "loadJavascriptUrl only accepts javascript: url");
264 protected void loadUrlSync(final String url) throws Exception {
265 CallbackHelper pageFinishedHelper = mTestHelperBridge.getOnPageFinishedHelper();
266 int currentCallCount = pageFinishedHelper.getCallCount();
269 pageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_SECONDS,
273 protected void loadUrlAsync(final String url) throws Exception {
274 getInstrumentation().runOnMainSync(new Runnable() {
277 mXWalkViewInternal.load(url, null);
282 protected void loadDataSync(final String url, final String data, final String mimeType,
283 final boolean isBase64Encoded) throws Exception {
284 CallbackHelper pageFinishedHelper = mTestHelperBridge.getOnPageFinishedHelper();
285 int currentCallCount = pageFinishedHelper.getCallCount();
286 loadDataAsync(url, data, mimeType, isBase64Encoded);
287 pageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_SECONDS,
291 protected void loadDataAsync(final String url, final String data, final String mimeType,
292 final boolean isBase64Encoded) throws Exception {
293 getInstrumentation().runOnMainSync(new Runnable() {
296 mXWalkViewInternal.load(url, data);
301 protected void loadUrlSyncByContent(final XWalkViewInternal xWalkViewInternal,
302 final TestHelperBridge contentsClient,
303 final String url) throws Exception {
304 CallbackHelper pageFinishedHelper = contentsClient.getOnPageFinishedHelper();
305 int currentCallCount = pageFinishedHelper.getCallCount();
306 loadUrlAsyncByContent(xWalkViewInternal, url);
308 pageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_SECONDS,
312 protected void loadUrlAsyncByContent(final XWalkViewInternal xWalkViewInternal,
313 final String url) throws Exception {
314 getInstrumentation().runOnMainSync(new Runnable() {
317 xWalkViewInternal.load(url, null);
322 protected String getTitleOnUiThread() throws Exception {
323 return runTestOnUiThreadAndGetResult(new Callable<String>() {
325 public String call() throws Exception {
326 return mXWalkViewInternal.getTitle();
331 protected <R> R runTestOnUiThreadAndGetResult(Callable<R> callable)
333 FutureTask<R> task = new FutureTask<R>(callable);
334 getInstrumentation().waitForIdleSync();
335 getInstrumentation().runOnMainSync(task);
339 protected String getFileContent(String fileName) {
341 Context context = getInstrumentation().getContext();
342 InputStream inputStream = context.getAssets().open(fileName);
343 int size = inputStream.available();
344 byte buffer[] = new byte[size];
345 inputStream.read(buffer);
348 String fileContent = new String(buffer);
350 } catch (IOException e) {
351 throw new RuntimeException(e);
355 protected String getTitleOnUiThreadByContent(final XWalkViewInternal xWalkViewInternal) throws Exception {
356 return runTestOnUiThreadAndGetResult(new Callable<String>() {
358 public String call() throws Exception {
359 String title = xWalkViewInternal.getTitle();
365 protected XWalkSettings getXWalkSettingsOnUiThreadByContent(
366 final XWalkViewInternal xWalkViewInternal) throws Exception {
367 return runTestOnUiThreadAndGetResult(new Callable<XWalkSettings>() {
369 public XWalkSettings call() throws Exception {
370 return xWalkViewInternal.getSettings();
375 protected XWalkViewInternal createXWalkViewContainerOnMainSync(
376 final Context context,
377 final XWalkUIClientInternal uiClient,
378 final XWalkResourceClientInternal resourceClient) throws Exception {
379 final AtomicReference<XWalkViewInternal> xWalkViewContainer =
380 new AtomicReference<XWalkViewInternal>();
381 getInstrumentation().runOnMainSync(new Runnable() {
384 xWalkViewContainer.set(new XWalkViewInternal(context, getActivity()));
385 getActivity().addView(xWalkViewContainer.get());
386 xWalkViewContainer.get().setUIClient(uiClient);
387 xWalkViewContainer.get().setResourceClient(resourceClient);
391 return xWalkViewContainer.get();
394 protected ViewPair createViewsOnMainSync(final TestHelperBridge helperBridge0,
395 final TestHelperBridge helperBridge1,
396 final XWalkUIClientInternal uiClient0,
397 final XWalkUIClientInternal uiClient1,
398 final XWalkResourceClientInternal resourceClient0,
399 final XWalkResourceClientInternal resourceClient1,
400 final Context context) throws Throwable {
401 final XWalkViewInternal walkView0 = createXWalkViewContainerOnMainSync(context,
402 uiClient0, resourceClient0);
403 final XWalkViewInternal walkView1 = createXWalkViewContainerOnMainSync(context,
404 uiClient1, resourceClient1);
405 final AtomicReference<ViewPair> viewPair = new AtomicReference<ViewPair>();
407 getInstrumentation().runOnMainSync(new Runnable() {
410 viewPair.set(new ViewPair(walkView0, helperBridge0, walkView1, helperBridge1));
414 return viewPair.get();
417 protected void loadAssetFile(String fileName) throws Exception {
418 String fileContent = getFileContent(fileName);
419 loadDataSync(fileName, fileContent, "text/html", false);
422 public void loadAssetFileAndWaitForTitle(String fileName) throws Exception {
423 CallbackHelper getTitleHelper = mTestHelperBridge.getOnTitleUpdatedHelper();
424 int currentCallCount = getTitleHelper.getCallCount();
425 String fileContent = getFileContent(fileName);
427 loadDataSync(fileName, fileContent, "text/html", false);
429 getTitleHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_SECONDS,
433 protected XWalkViewInternal getXWalkView() {
434 return mXWalkViewInternal;
437 protected void runTestWaitPageFinished(Runnable runnable) throws Exception{
438 CallbackHelper pageFinishedHelper = mTestHelperBridge.getOnPageFinishedHelper();
439 int currentCallCount = pageFinishedHelper.getCallCount();
441 pageFinishedHelper.waitForCallback(currentCallCount, 1, WAIT_TIMEOUT_SECONDS,
445 protected void reloadSync(final int mode) throws Exception {
446 runTestWaitPageFinished(new Runnable(){
449 getInstrumentation().runOnMainSync(new Runnable() {
452 mXWalkViewInternal.reload(mode);
459 protected void goBackSync() throws Throwable {
460 runTestWaitPageFinished(new Runnable(){
463 getInstrumentation().runOnMainSync(new Runnable() {
466 mXWalkViewInternal.getNavigationHistory().navigate(
467 XWalkNavigationHistoryInternal.DirectionInternal.BACKWARD, 1);
474 protected void goForwardSync() throws Throwable {
475 runTestWaitPageFinished(new Runnable(){
478 getInstrumentation().runOnMainSync(new Runnable() {
481 mXWalkViewInternal.getNavigationHistory().navigate(
482 XWalkNavigationHistoryInternal.DirectionInternal.FORWARD, 1);
489 protected void clearHistoryOnUiThread() throws Exception {
490 getInstrumentation().runOnMainSync(new Runnable() {
493 mXWalkViewInternal.getNavigationHistory().clear();
498 protected boolean canGoBackOnUiThread() throws Throwable {
499 return runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
501 public Boolean call() {
502 return mXWalkViewInternal.getNavigationHistory().canGoBack();
507 protected boolean canGoForwardOnUiThread() throws Throwable {
508 return runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
510 public Boolean call() {
511 return mXWalkViewInternal.getNavigationHistory().canGoForward();
516 protected int historySizeOnUiThread() throws Throwable {
517 return runTestOnUiThreadAndGetResult(new Callable<Integer>() {
519 public Integer call() {
520 return mXWalkViewInternal.getNavigationHistory().size();
525 protected boolean hasItemAtOnUiThread(final int index) throws Throwable {
526 return runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
528 public Boolean call() {
529 return mXWalkViewInternal.getNavigationHistory().hasItemAt(index);
534 protected XWalkNavigationItemInternal getItemAtOnUiThread(final int index) throws Throwable {
535 return runTestOnUiThreadAndGetResult(new Callable<XWalkNavigationItemInternal>() {
537 public XWalkNavigationItemInternal call() {
538 return mXWalkViewInternal.getNavigationHistory().getItemAt(index);
543 protected XWalkNavigationItemInternal getCurrentItemOnUiThread() throws Throwable {
544 return runTestOnUiThreadAndGetResult(new Callable<XWalkNavigationItemInternal>() {
546 public XWalkNavigationItemInternal call() {
547 return mXWalkViewInternal.getNavigationHistory().getCurrentItem();
552 protected String executeJavaScriptAndWaitForResult(final String code) throws Exception {
553 final TestHelperBridge.OnEvaluateJavaScriptResultHelper helper =
554 mTestHelperBridge.getOnEvaluateJavaScriptResultHelper();
555 getInstrumentation().runOnMainSync(new Runnable() {
558 helper.evaluateJavascript(mXWalkViewInternal, code);
561 helper.waitUntilHasValue();
562 Assert.assertTrue("Failed to retrieve JavaScript evaluation results.", helper.hasValue());
563 return helper.getJsonResultAndClear();
566 protected ViewPair createViews() throws Throwable {
567 TestHelperBridge helperBridge0 = new TestHelperBridge();
568 TestHelperBridge helperBridge1 = new TestHelperBridge();
569 TestXWalkUIClientInternalBase uiClient0 = new TestXWalkUIClientInternalBase(helperBridge0);
570 TestXWalkUIClientInternalBase uiClient1 = new TestXWalkUIClientInternalBase(helperBridge1);
571 TestXWalkResourceClientBase resourceClient0 =
572 new TestXWalkResourceClientBase(helperBridge0);
573 TestXWalkResourceClientBase resourceClient1 =
574 new TestXWalkResourceClientBase(helperBridge1);
576 createViewsOnMainSync(helperBridge0, helperBridge1, uiClient0, uiClient1,
577 resourceClient0, resourceClient1, getActivity());
582 protected String getUrlOnUiThread() throws Exception {
583 return runTestOnUiThreadAndGetResult(new Callable<String>() {
585 public String call() throws Exception {
586 return mXWalkViewInternal.getUrl();
591 protected void clearCacheOnUiThread(final boolean includeDiskFiles) throws Exception {
592 getInstrumentation().runOnMainSync(new Runnable() {
595 mXWalkViewInternal.clearCache(includeDiskFiles);
600 protected String getAPIVersionOnUiThread() throws Exception {
601 return runTestOnUiThreadAndGetResult(new Callable<String>() {
603 public String call() throws Exception {
604 return mXWalkViewInternal.getAPIVersion();
609 protected String getXWalkVersionOnUiThread() throws Exception {
610 return runTestOnUiThreadAndGetResult(new Callable<String>() {
612 public String call() throws Exception {
613 return mXWalkViewInternal.getXWalkVersion();
618 protected ContentViewCore getContentViewCore() throws Exception {
619 return runTestOnUiThreadAndGetResult(new Callable<ContentViewCore>() {
621 public ContentViewCore call() throws Exception {
622 return mXWalkViewInternal.getXWalkContentForTest();