Index: content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
index 4a50997b1341bd4a637c574dd7811ebf5a0c4cf8..14b389c52a52f90116996a5a0861323bd933ebd2 100644 |
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java |
@@ -362,6 +362,29 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Screen |
} |
/** |
+ * {@ResultReceiver} passed in InputMethodManager#showSoftInput}. We need this to scroll to the |
+ * editable node at the right timing, which is after input method window shows up. |
+ */ |
+ private static class ShowKeyboardResultReceiver extends ResultReceiver { |
+ |
+ // Unfortunately, ResultReceiver used in showSoftInput() will be leaked. We minimize |
+ // the leak by weak referencing CVC and therefore WebView object. |
+ private final WeakReference<ContentViewCore> mContentViewCore; |
+ |
+ public ShowKeyboardResultReceiver(ContentViewCore contentViewCore, Handler handler) { |
+ super(handler); |
+ mContentViewCore = new WeakReference<>(contentViewCore); |
+ } |
+ |
+ @Override |
+ public void onReceiveResult(int resultCode, Bundle resultData) { |
+ ContentViewCore contentViewCore = mContentViewCore.get(); |
+ if (contentViewCore == null) return; |
+ contentViewCore.onShowKeyboardReceiveResult(resultCode); |
+ } |
+ } |
+ |
+ /** |
* Interface that consumers of {@link ContentViewCore} must implement to allow the proper |
* dispatching of view methods through the containing view. |
* |
@@ -585,6 +608,10 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Screen |
// The client that implements Contextual Search functionality, or null if none exists. |
private ContextualSearchClient mContextualSearchClient; |
+ // NOTE: This object will not be released by Android framework until the matching |
+ // ResultReceiver in the InputMethodService (IME app) gets gc'ed. |
+ private ShowKeyboardResultReceiver mShowKeyboardResultReceiver; |
+ |
/** |
* @param webContents The {@link WebContents} to find a {@link ContentViewCore} of. |
* @return A {@link ContentViewCore} that is connected to {@code webContents} or |
@@ -739,26 +766,7 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Screen |
@Override |
public ResultReceiver getNewShowKeyboardReceiver() { |
- return new ResultReceiver(new Handler()) { |
- @Override |
- public void onReceiveResult(int resultCode, Bundle resultData) { |
- if (resultCode == InputMethodManager.RESULT_SHOWN) { |
- // If OSK is newly shown, delay the form focus until |
- // the onSizeChanged (in order to adjust relative to the |
- // new size). |
- // TODO(jdduke): We should not assume that onSizeChanged will |
- // always be called, crbug.com/294908. |
- getContainerView().getWindowVisibleDisplayFrame( |
- mFocusPreOSKViewportRect); |
- } else if (hasFocus() && resultCode |
- == InputMethodManager.RESULT_UNCHANGED_SHOWN) { |
- // If the OSK was already there, focus the form immediately. |
- if (mWebContents != null) { |
- mWebContents.scrollFocusedEditableNodeIntoView(); |
- } |
- } |
- } |
- }; |
+ return ContentViewCore.this.getNewShowKeyboardReceiver(); |
} |
}); |
} |
@@ -3283,6 +3291,36 @@ public class ContentViewCore implements AccessibilityStateChangeListener, Screen |
mContextualSearchClient = contextualSearchClient; |
} |
+ /** |
+ * Call this when we get result from ResultReceiver passed in calling showSoftInput(). |
+ * @param resultCode The result of showSoftInput() as defined in InputMethodManager. |
+ */ |
+ public void onShowKeyboardReceiveResult(int resultCode) { |
+ if (resultCode == InputMethodManager.RESULT_SHOWN) { |
+ // If OSK is newly shown, delay the form focus until |
+ // the onSizeChanged (in order to adjust relative to the |
+ // new size). |
+ // TODO(jdduke): We should not assume that onSizeChanged will |
+ // always be called, crbug.com/294908. |
+ getContainerView().getWindowVisibleDisplayFrame( |
+ mFocusPreOSKViewportRect); |
+ } else if (hasFocus() && resultCode == InputMethodManager.RESULT_UNCHANGED_SHOWN) { |
+ // If the OSK was already there, focus the form immediately. |
+ if (mWebContents != null) { |
+ mWebContents.scrollFocusedEditableNodeIntoView(); |
+ } |
+ } |
+ } |
+ |
+ @VisibleForTesting |
+ public ResultReceiver getNewShowKeyboardReceiver() { |
+ if (mShowKeyboardResultReceiver == null) { |
+ // Note: the returned object will get leaked by Android framework. |
+ mShowKeyboardResultReceiver = new ShowKeyboardResultReceiver(this, new Handler()); |
+ } |
+ return mShowKeyboardResultReceiver; |
+ } |
+ |
private native long nativeInit(WebContents webContents, ViewAndroidDelegate viewAndroidDelegate, |
long windowAndroidPtr, HashSet<Object> retainedObjectSet); |
private static native ContentViewCore nativeFromWebContentsAndroid(WebContents webContents); |