root/android_webview/javatests/src/org/chromium/android_webview/test/WebViewFindApisTestBase.java

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. setUp
  2. contents
  3. onFindResultReceived
  4. loadContentsFromStringSync
  5. findAllAsyncOnUiThread
  6. findNextOnUiThread
  7. clearMatchesOnUiThread
  8. run
  9. get
  10. set

// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.android_webview.test;

import org.chromium.android_webview.AwContents;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * Base class for WebView find-in-page API tests.
 */
public class WebViewFindApisTestBase extends AwTestBase {

    private static final String WOODCHUCK =
            "How much WOOD would a woodchuck chuck if a woodchuck could chuck wOoD?";

    private FindResultListener mFindResultListener;
    private AwContents mContents;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        try {
            mContents = loadContentsFromStringSync(WOODCHUCK);
        } catch (Throwable t) {
            throw new Exception(t);
        }
    }

    protected AwContents contents() {
        return mContents;
    }

    // Internal interface to intercept find results from AwContentsClient.
    private interface FindResultListener {
        public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
                boolean isDoneCounting);
    };

    private AwContents loadContentsFromStringSync(final String html) throws Throwable {
        final TestAwContentsClient contentsClient = new TestAwContentsClient() {
            @Override
            public void onFindResultReceived(int activeMatchOrdinal,
                    int numberOfMatches, boolean isDoneCounting) {
                if (mFindResultListener == null) return;
                mFindResultListener.onFindResultReceived(activeMatchOrdinal, numberOfMatches,
                        isDoneCounting);
            }
        };

        final AwContents contents =
                createAwTestContainerViewOnMainSync(contentsClient).getAwContents();
        final String data = "<html><head></head><body>" + html + "</body></html>";
        loadDataSync(contents, contentsClient.getOnPageFinishedHelper(),
                data, "text/html", false);
        return contents;
    }

    /**
     * Invokes findAllAsync on the UI thread, blocks until find results are
     * received, and returns the number of matches.
     *
     * @param searchString A string to search for.
     * @return The number of instances of the string that were found.
     * @throws Throwable
     */
    protected int findAllAsyncOnUiThread(final String searchString)
            throws Throwable {
        final IntegerFuture future = new IntegerFuture() {
            @Override
            public void run() {
                mFindResultListener = new FindResultListener() {
                    @Override
                    public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
                            boolean isDoneCounting) {
                        if (isDoneCounting) set(numberOfMatches);
                    }
                };
                mContents.findAllAsync(searchString);
            }
        };
        runTestOnUiThread(future);
        return future.get(10, TimeUnit.SECONDS);
    }

    /**
     * Invokes findNext on the UI thread, blocks until find results are
     * received, and returns the ordinal of the highlighted match.
     *
     * @param forwards The direction to search as a boolean, with forwards
     *                 represented as true and backwards as false.
     * @return The ordinal of the highlighted match.
     * @throws Throwable
     */
    protected int findNextOnUiThread(final boolean forwards)
            throws Throwable {
        final IntegerFuture future = new IntegerFuture() {
            @Override
            public void run() {
                mFindResultListener = new FindResultListener() {
                    @Override
                    public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
                            boolean isDoneCounting) {
                        if (isDoneCounting) set(activeMatchOrdinal);
                    }
                };
                mContents.findNext(forwards);
            }
        };
        runTestOnUiThread(future);
        return future.get(10, TimeUnit.SECONDS);
    }

    /**
     * Invokes clearMatches on the UI thread.
     *
     * @throws Throwable
     */
    protected void clearMatchesOnUiThread() throws Throwable {
        runTestOnUiThread(new Runnable() {
            @Override
            public void run() {
                mContents.clearMatches();
            }
        });
    }

    // Similar to java.util.concurrent.Future, but without the ability to cancel.
    private abstract static class IntegerFuture implements Runnable {
        private CountDownLatch mLatch = new CountDownLatch(1);
        private int mValue;

        @Override
        public abstract void run();

        /**
         * Gets the value of this Future, blocking for up to the specified
         * timeout for it become available. Throws a TimeoutException if the
         * timeout expires.
         */
        public int get(long timeout, TimeUnit unit) throws Throwable {
            if (!mLatch.await(timeout, unit)) {
                throw new TimeoutException();
            }
            return mValue;
        }

        /**
         * Sets the value of this Future.
         */
        protected void set(int value) {
            mValue = value;
            mLatch.countDown();
        }
    }
}

/* [<][>][^][v][top][bottom][index][help] */