Merge "Refactor FindActionModeCallback."
diff --git a/core/java/android/webkit/FindActionModeCallback.java b/core/java/android/webkit/FindActionModeCallback.java
index 1a4ccfa..d7a0b60 100644
--- a/core/java/android/webkit/FindActionModeCallback.java
+++ b/core/java/android/webkit/FindActionModeCallback.java
@@ -33,12 +33,15 @@
 import android.widget.EditText;
 import android.widget.TextView;
 
-class FindActionModeCallback implements ActionMode.Callback, TextWatcher,
-        View.OnClickListener {
+/**
+ * @hide
+ */
+public class FindActionModeCallback implements ActionMode.Callback, TextWatcher,
+        View.OnClickListener, WebView.FindListener {
     private View mCustomView;
     private EditText mEditText;
     private TextView mMatches;
-    private WebViewClassic mWebView;
+    private WebView mWebView;
     private InputMethodManager mInput;
     private Resources mResources;
     private boolean mMatchesFound;
@@ -46,7 +49,7 @@
     private int mActiveMatchIndex;
     private ActionMode mActionMode;
 
-    FindActionModeCallback(Context context) {
+    public FindActionModeCallback(Context context) {
         mCustomView = LayoutInflater.from(context).inflate(
                 com.android.internal.R.layout.webview_find, null);
         mEditText = (EditText) mCustomView.findViewById(
@@ -61,7 +64,7 @@
         mResources = context.getResources();
     }
 
-    void finish() {
+    public void finish() {
         mActionMode.finish();
     }
 
@@ -69,7 +72,7 @@
      * Place text in the text field so it can be searched for.  Need to press
      * the find next or find previous button to find all of the matches.
      */
-    void setText(String text) {
+    public void setText(String text) {
         mEditText.setText(text);
         Spannable span = (Spannable) mEditText.getText();
         int length = span.length();
@@ -84,15 +87,23 @@
     }
 
     /*
-     * Set the WebView to search.  Must be non null, and set before calling
-     * startActionMode.
+     * Set the WebView to search.  Must be non null.
      */
-    void setWebView(WebViewClassic webView) {
+    public void setWebView(WebView webView) {
         if (null == webView) {
             throw new AssertionError("WebView supplied to "
                     + "FindActionModeCallback cannot be null");
         }
         mWebView = webView;
+        mWebView.setFindDialogFindListener(this);
+    }
+
+    @Override
+    public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
+            boolean isDoneCounting) {
+        if (isDoneCounting) {
+            updateMatchCount(activeMatchOrdinal, numberOfMatches, numberOfMatches == 0);
+        }
     }
 
     /*
@@ -121,7 +132,7 @@
     /*
      * Highlight all the instances of the string from mEditText in mWebView.
      */
-    void findAll() {
+    public void findAll() {
         if (mWebView == null) {
             throw new AssertionError(
                     "No WebView for FindActionModeCallback::findAll");
@@ -208,7 +219,8 @@
     public void onDestroyActionMode(ActionMode mode) {
         mActionMode = null;
         mWebView.notifyFindDialogDismissed();
-        mInput.hideSoftInputFromWindow(mWebView.getWebView().getWindowToken(), 0);
+        mWebView.setFindDialogFindListener(null);
+        mInput.hideSoftInputFromWindow(mWebView.getWindowToken(), 0);
     }
 
     @Override
@@ -222,7 +234,7 @@
             throw new AssertionError(
                     "No WebView for FindActionModeCallback::onActionItemClicked");
         }
-        mInput.hideSoftInputFromWindow(mWebView.getWebView().getWindowToken(), 0);
+        mInput.hideSoftInputFromWindow(mWebView.getWindowToken(), 0);
         switch(item.getItemId()) {
             case com.android.internal.R.id.find_prev:
                 findNext(false);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 1abea2b..5412400 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1329,7 +1329,8 @@
      */
     public void setFindListener(FindListener listener) {
         checkThread();
-        mProvider.setFindListener(listener);
+        setupFindListenerIfNeeded();
+        mFindListener.mUserFindListener = listener;
     }
 
     /**
@@ -1850,11 +1851,60 @@
     }
 
     //-------------------------------------------------------------------------
+    // Package-private internal stuff
+    //-------------------------------------------------------------------------
+
+    // Only used by android.webkit.FindActionModeCallback.
+    void setFindDialogFindListener(FindListener listener) {
+        checkThread();
+        setupFindListenerIfNeeded();
+        mFindListener.mFindDialogFindListener = listener;
+    }
+
+    // Only used by android.webkit.FindActionModeCallback.
+    void notifyFindDialogDismissed() {
+        checkThread();
+        mProvider.notifyFindDialogDismissed();
+    }
+
+    //-------------------------------------------------------------------------
     // Private internal stuff
     //-------------------------------------------------------------------------
 
     private WebViewProvider mProvider;
 
+    /**
+     * In addition to the FindListener that the user may set via the WebView.setFindListener
+     * API, FindActionModeCallback will register it's own FindListener. We keep them separate
+     * via this class so that that the two FindListeners can potentially exist at once.
+     */
+    private class FindListenerDistributor implements FindListener {
+        private FindListener mFindDialogFindListener;
+        private FindListener mUserFindListener;
+
+        @Override
+        public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
+                boolean isDoneCounting) {
+            if (mFindDialogFindListener != null) {
+                mFindDialogFindListener.onFindResultReceived(activeMatchOrdinal, numberOfMatches,
+                        isDoneCounting);
+            }
+
+            if (mUserFindListener != null) {
+                mUserFindListener.onFindResultReceived(activeMatchOrdinal, numberOfMatches,
+                        isDoneCounting);
+            }
+        }
+    }
+    private FindListenerDistributor mFindListener;
+
+    private void setupFindListenerIfNeeded() {
+        if (mFindListener == null) {
+            mFindListener = new FindListenerDistributor();
+            mProvider.setFindListener(mFindListener);
+        }
+    }
+
     private void ensureProviderCreated() {
         checkThread();
         if (mProvider == null) {
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 9a83964..a867d39 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -3668,7 +3668,7 @@
         mCachedOverlappingActionModeHeight = -1;
         mFindCallback = callback;
         setFindIsUp(true);
-        mFindCallback.setWebView(this);
+        mFindCallback.setWebView(getWebView());
         if (showIme) {
             mFindCallback.showSoftInput();
         } else if (text != null) {
@@ -3770,7 +3770,8 @@
     /**
      * Called when the find ActionMode ends.
      */
-    void notifyFindDialogDismissed() {
+    @Override
+    public void notifyFindDialogDismissed() {
         mFindCallback = null;
         mCachedOverlappingActionModeHeight = -1;
         if (mWebViewCore == null) {
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 1020634..fa17ab9 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -240,7 +240,7 @@
     public View findHierarchyView(String className, int hashCode);
 
     //-------------------------------------------------------------------------
-    // Provider glue methods
+    // Provider internal methods
     //-------------------------------------------------------------------------
 
     /**
@@ -255,6 +255,12 @@
      */
     /* package */ ScrollDelegate getScrollDelegate();
 
+    /**
+     * Only used by FindActionModeCallback to inform providers that the find dialog has
+     * been dismissed.
+     */
+    public void notifyFindDialogDismissed();
+
     //-------------------------------------------------------------------------
     // View / ViewGroup delegation methods
     //-------------------------------------------------------------------------