Index: content/public/android/java/src/org/chromium/content/browser/input/InputConnectionHandlerFactory.java |
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/InputConnectionHandlerFactory.java b/content/public/android/java/src/org/chromium/content/browser/input/InputConnectionHandlerFactory.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5239aeef3e8a05fccf1bd7897050433354c0cc02 |
--- /dev/null |
+++ b/content/public/android/java/src/org/chromium/content/browser/input/InputConnectionHandlerFactory.java |
@@ -0,0 +1,78 @@ |
+// Copyright 2015 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.content.browser.input; |
+ |
+import android.os.Handler; |
+import android.os.HandlerThread; |
+ |
+import org.chromium.base.CommandLine; |
+import org.chromium.base.Log; |
+import org.chromium.content.common.ContentSwitches; |
+ |
+/** |
+ * A class to create InputConnection Handler as necessary. |
+ */ |
+public class InputConnectionHandlerFactory { |
+ private static final String TAG = "cr.Ime"; |
+ |
+ public static Handler getHandler(Handler defaultHandler) { |
+ if (shouldReturnInputConnectionHandler()) { |
+ return getInputConnectionHandler(); |
+ } |
+ return defaultHandler; |
+ } |
+ |
+ private static boolean shouldReturnInputConnectionHandler() { |
+ if (!CommandLine.getInstance().hasSwitch(ContentSwitches.USE_IME_THREAD)) { |
+ Log.d(TAG, "USE_IME_THREAD not set. Returning the default handler."); |
+ return false; |
+ } |
+ for (StackTraceElement frame : Thread.currentThread().getStackTrace()) { |
+ // We only return our custom Handler to InputMethodManager's InputConnection |
+ // proxy. For all other purposes, we return the regular Handler. |
+ // InputMethodManager retrieves the Handler for its InputConnection proxy |
+ // inside its method startInputInner(), so we check for that here. This is |
+ // valid from Android 2.2 to at least Android 4.2. If this situation ever |
+ // changes, we gracefully fall back to using the regular Handler. |
+ if ("startInputInner".equals(frame.getMethodName()) |
+ && android.view.inputmethod.InputMethodManager.class.getName().equals( |
+ frame.getClassName())) { |
+ // Return our own Handler to InputMethodManager |
+ Log.d(TAG, "getHandler() is called from InputMethodManager." |
+ + " Returning custom handler."); |
+ return true; |
+ } |
+ } |
+ Log.d(TAG, "getHandler() is not called from InputMethodManager. Returning the default" |
+ + " handler."); |
+ return false; |
+ } |
+ |
+ // Initialization-on-demand holder for thread-safe-lazy initialization. |
+ static Handler getInputConnectionHandler() { |
+ return LazyHandlerHolder.sInstance.getHandler(); |
+ } |
+ |
+ // Initialization-on-demand holder for thread-safe lazy initialization. |
+ private static class LazyHandlerHolder { |
+ private static final InputConnectionHandlerContainer sInstance = |
+ new InputConnectionHandlerContainer(); |
+ } |
+ |
+ private static class InputConnectionHandlerContainer { |
+ private final Handler mHandler; |
+ |
+ public InputConnectionHandlerContainer() { |
+ HandlerThread thread = |
+ new HandlerThread("InputConnectionHandlerThread", HandlerThread.NORM_PRIORITY); |
+ thread.start(); |
+ mHandler = new Handler(thread.getLooper()); |
+ } |
+ |
+ public Handler getHandler() { |
+ return mHandler; |
+ } |
+ } |
+} |