Bug 805162 - i. Refactor DebugGeckoInputConnection to be smaller by using reflection; r=cpeterson
authorJim Chen <nchen@mozilla.com>
Thu, 01 Nov 2012 16:11:03 -0400
changeset 112076 889288379ae3dd6c265ea6e52a57b9d02ae74270
parent 112075 5186a8d3722c970f733f13dca830f65ad6c08047
child 112077 d7660aa2bc1d1ec8cf5c01eaabf62f488d705a63
push id23790
push userryanvm@gmail.com
push dateFri, 02 Nov 2012 01:26:40 +0000
treeherdermozilla-central@556b9cfb269f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpeterson
bugs805162
milestone19.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 805162 - i. Refactor DebugGeckoInputConnection to be smaller by using reflection; r=cpeterson
mobile/android/base/GeckoInputConnection.java
--- a/mobile/android/base/GeckoInputConnection.java
+++ b/mobile/android/base/GeckoInputConnection.java
@@ -21,16 +21,19 @@ import android.view.KeyEvent;
 import android.view.View;
 import android.view.inputmethod.BaseInputConnection;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.ExtractedText;
 import android.view.inputmethod.ExtractedTextRequest;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
 
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
 import java.util.Timer;
 import java.util.TimerTask;
 
 class GeckoInputConnection
     extends BaseInputConnection
     implements InputConnectionHandler, GeckoEditableListener {
 
     private static final boolean DEBUG = false;
@@ -548,265 +551,82 @@ class GeckoInputConnection
                         imm.showSoftInput(v, 0);
                     } else if (imm.isActive(v)) {
                         imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
                     }
                 }
             });
         }
     }
-
-private static final class DebugGeckoInputConnection extends GeckoInputConnection {
-    public DebugGeckoInputConnection(View targetView) {
-        super(targetView);
-        GeckoApp.assertOnUiThread();
-    }
+}
 
-    @Override
-    public boolean beginBatchEdit() {
-        Log.d(LOGTAG, "IME: beginBatchEdit: mBatchEditCount " + mBatchEditCount
-                                                     + " -> " + (mBatchEditCount+1));
-        GeckoApp.assertOnUiThread();
-        return super.beginBatchEdit();
-    }
-
-    @Override
-    public boolean endBatchEdit() {
-        Log.d(LOGTAG, "IME: endBatchEdit: mBatchEditCount " + mBatchEditCount
-                                                   + " -> " + (mBatchEditCount-1));
-        GeckoApp.assertOnUiThread();
-        if (mBatchEditCount <= 0) {
-            throw new IllegalStateException("Expected positive mBatchEditCount, but got "
-                                            + mBatchEditCount);
-        }
-        return super.endBatchEdit();
-    }
+final class DebugGeckoInputConnection
+        extends GeckoInputConnection
+        implements InvocationHandler {
 
-    @Override
-    public boolean commitCompletion(CompletionInfo text) {
-        Log.d(LOGTAG, "IME: commitCompletion");
-        GeckoApp.assertOnUiThread();
-        return super.commitCompletion(text);
-    }
-
-    @Override
-    public boolean commitText(CharSequence text, int newCursorPosition) {
-        Log.d(LOGTAG, String.format("IME: commitText(\"%s\", %d)", text, newCursorPosition));
-        GeckoApp.assertOnUiThread();
-        return super.commitText(text, newCursorPosition);
-    }
+    private InputConnection mProxy;
 
-    @Override
-    public boolean deleteSurroundingText(int leftLength, int rightLength) {
-        Log.d(LOGTAG, "IME: deleteSurroundingText(leftLen=" + leftLength + ", rightLen="
-                      + rightLength + ")");
-        GeckoApp.assertOnUiThread();
-        return super.deleteSurroundingText(leftLength, rightLength);
-    }
-
-    @Override
-    public boolean finishComposingText() {
-        Log.d(LOGTAG, "IME: finishComposingText");
-        // finishComposingText will post itself to the ui thread,
-        // no need to assert it.
-        return super.finishComposingText();
+    private DebugGeckoInputConnection(View targetView,
+                                      GeckoEditableClient editable) {
+        super(targetView, editable);
     }
 
-    @Override
-    public Editable getEditable() {
-        Editable editable = super.getEditable();
-        Log.d(LOGTAG, "IME: getEditable -> " + prettyPrintString(editable));
-        // FIXME: Uncomment assert after bug 780543 is fixed. //GeckoApp.assertOnUiThread();
-        return editable;
-    }
-
-    @Override
-    public boolean performContextMenuAction(int id) {
-        Log.d(LOGTAG, "IME: performContextMenuAction");
-        GeckoApp.assertOnUiThread();
-        return super.performContextMenuAction(id);
-    }
-
-    @Override
-    public ExtractedText getExtractedText(ExtractedTextRequest req, int flags) {
-        Log.d(LOGTAG, "IME: getExtractedText");
-        GeckoApp.assertOnUiThread();
-        ExtractedText extract = super.getExtractedText(req, flags);
-        if (extract != null)
-            Log.d(LOGTAG, String.format(
-                          ". . . getExtractedText: extract.text=\"%s\", selStart=%d, selEnd=%d",
-                          extract.text, extract.selectionStart, extract.selectionEnd));
-        return extract;
-    }
-
-    @Override
-    public CharSequence getTextAfterCursor(int length, int flags) {
-        Log.d(LOGTAG, "IME: getTextAfterCursor(length=" + length + ", flags=" + flags + ")");
-        GeckoApp.assertOnUiThread();
-        CharSequence s = super.getTextAfterCursor(length, flags);
-        Log.d(LOGTAG, ". . . getTextAfterCursor returns \"" + s + "\"");
-        return s;
-    }
-
-    @Override
-    public CharSequence getTextBeforeCursor(int length, int flags) {
-        Log.d(LOGTAG, "IME: getTextBeforeCursor");
-        GeckoApp.assertOnUiThread();
-        CharSequence s = super.getTextBeforeCursor(length, flags);
-        Log.d(LOGTAG, ". . . getTextBeforeCursor returns \"" + s + "\"");
-        return s;
-    }
-
-    @Override
-    public boolean setComposingText(CharSequence text, int newCursorPosition) {
-        Log.d(LOGTAG, String.format("IME: setComposingText(\"%s\", %d)", text, newCursorPosition));
-        GeckoApp.assertOnUiThread();
-        return super.setComposingText(text, newCursorPosition);
-    }
-
-    @Override
-    public boolean setComposingRegion(int start, int end) {
-        Log.d(LOGTAG, "IME: setComposingRegion(start=" + start + ", end=" + end + ")");
-        GeckoApp.assertOnUiThread();
-        return super.setComposingRegion(start, end);
-    }
-
-    @Override
-    public boolean setSelection(int start, int end) {
-        Log.d(LOGTAG, "IME: setSelection(start=" + start + ", end=" + end + ")");
-        GeckoApp.assertOnUiThread();
-        return super.setSelection(start, end);
+    public static InputConnectionHandler create(View targetView,
+                                                GeckoEditableClient editable) {
+        final Class[] PROXY_INTERFACES = { InputConnection.class,
+                InputConnectionHandler.class,
+                GeckoEditableListener.class };
+        DebugGeckoInputConnection dgic =
+                new DebugGeckoInputConnection(targetView, editable);
+        dgic.mProxy = (InputConnection)Proxy.newProxyInstance(
+                GeckoInputConnection.class.getClassLoader(),
+                PROXY_INTERFACES, dgic);
+        editable.setListener((GeckoEditableListener)dgic.mProxy);
+        return (InputConnectionHandler)dgic.mProxy;
     }
 
-    @Override
-    public String getComposingText() {
-        Log.d(LOGTAG, "IME: getComposingText");
-        GeckoApp.assertOnUiThread();
-        String s = super.getComposingText();
-        Log.d(LOGTAG, ". . . getComposingText: Composing text = \"" + s + "\"");
-        return s;
-    }
-
-    @Override
-    public boolean onKeyDel() {
-        Log.d(LOGTAG, "IME: onKeyDel");
-        GeckoApp.assertOnUiThread();
-        return super.onKeyDel();
-    }
-
-    @Override
-    protected void notifyTextChange(String text, int start, int oldEnd, int newEnd) {
-        // notifyTextChange() call is posted to UI thread from notifyIMEChange().
-        GeckoApp.assertOnUiThread();
-        String msg = String.format("IME: >notifyTextChange(%s, start=%d, oldEnd=%d, newEnd=%d)",
-                                   prettyPrintString(text), start, oldEnd, newEnd);
-        Log.d(LOGTAG, msg);
-        if (start < 0 || oldEnd < start || newEnd < start || newEnd > text.length()) {
-            throw new IllegalArgumentException("BUG! " + msg);
+    private static StringBuilder debugAppend(StringBuilder sb, Object obj) {
+        if (obj == null) {
+            sb.append("null");
+        } else if (obj instanceof GeckoEditable) {
+            sb.append("GeckoEditable");
+        } else if (Proxy.isProxyClass(obj.getClass())) {
+            debugAppend(sb, Proxy.getInvocationHandler(obj));
+        } else if (obj instanceof CharSequence) {
+            sb.append("\"").append(obj.toString().replace('\n', '\u21b2')).append("\"");
+        } else if (obj.getClass().isArray()) {
+            Class cls = obj.getClass();
+            sb.append(cls.getComponentType().getSimpleName()).append("[")
+              .append(java.lang.reflect.Array.getLength(obj)).append("]");
+        } else {
+            sb.append(obj.toString());
         }
-        super.notifyTextChange(text, start, oldEnd, newEnd);
-    }
-
-    @Override
-    protected void notifySelectionChange(int start, int end) {
-        // notifySelectionChange() call is posted to UI thread from notifyIMEChange().
-        // FIXME: Uncomment assert after bug 780543 is fixed.
-        //GeckoApp.assertOnUiThread();
-        Log.d(LOGTAG, String.format("IME: >notifySelectionChange(start=%d, end=%d)", start, end));
-        super.notifySelectionChange(start, end);
-    }
-
-    @Override
-    protected void resetCompositionState() {
-        Log.d(LOGTAG, "IME: resetCompositionState");
-        GeckoApp.assertOnUiThread();
-        if (hasCompositionString()) {
-            Log.d(LOGTAG, "resetCompositionState() is abandoning an active composition string");
-        }
-        super.resetCompositionState();
-    }
-
-    @Override
-    public void onTextChanged(CharSequence s, int start, int before, int count) {
-        Log.d(LOGTAG, String.format("IME: onTextChanged(\"%s\" start=%d, before=%d, count=%d)",
-                                    s, start, before, count));
-        GeckoApp.assertOnUiThread();
-        super.onTextChanged(s, start, before, count);
-    }
-
-    @Override
-    public void afterTextChanged(Editable s) {
-        Log.d(LOGTAG, "IME: afterTextChanged(\"" + s + "\")");
-        GeckoApp.assertOnUiThread();
-        super.afterTextChanged(s);
+        return sb;
     }
 
-    @Override
-    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
-        Log.d(LOGTAG, String.format("IME: beforeTextChanged(\"%s\", start=%d, count=%d, after=%d)",
-                                    s, start, count, after));
-        GeckoApp.assertOnUiThread();
-        super.beforeTextChanged(s, start, count, after);
-    }
-
-    @Override
-    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
-        Log.d(LOGTAG, "IME: onCreateInputConnection called");
-        GeckoApp.assertOnUiThread();
-        return super.onCreateInputConnection(outAttrs);
-    }
+    public Object invoke(Object proxy, Method method, Object[] args)
+            throws Throwable {
 
-    @Override
-    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
-        Log.d(LOGTAG, "IME: onKeyPreIme(keyCode=" + keyCode + ", event=" + event + ")");
-        GeckoApp.assertOnUiThread();
-        return super.onKeyPreIme(keyCode, event);
-    }
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        Log.d(LOGTAG, "IME: onKeyDown(keyCode=" + keyCode + ", event=" + event + ")");
-        GeckoApp.assertOnUiThread();
-        return super.onKeyDown(keyCode, event);
-    }
-
-    @Override
-    public boolean onKeyUp(int keyCode, KeyEvent event) {
-        Log.d(LOGTAG, "IME: onKeyUp(keyCode=" + keyCode + ", event=" + event + ")");
         GeckoApp.assertOnUiThread();
-        return super.onKeyUp(keyCode, event);
-    }
-
-    @Override
-    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
-        Log.d(LOGTAG, "IME: onKeyMultiple(keyCode=" + keyCode + ", repeatCount=" + repeatCount
-                      + ", event=" + event + ")");
-        GeckoApp.assertOnUiThread();
-        return super.onKeyMultiple(keyCode, repeatCount, event);
-    }
+        Object ret = method.invoke(this, args);
+        if (ret == this) {
+            ret = mProxy;
+        }
 
-    @Override
-    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
-        Log.d(LOGTAG, "IME: onKeyLongPress(keyCode=" + keyCode + ", event=" + event + ")");
-        GeckoApp.assertOnUiThread();
-        return super.onKeyLongPress(keyCode, event);
-    }
+        StringBuilder log = new StringBuilder(method.getName());
+        log.append("(");
+        for (Object arg : args) {
+            debugAppend(log, arg).append(", ");
+        }
+        if (args.length > 0) {
+            log.setLength(log.length() - 2);
+        }
+        if (method.getReturnType().equals(Void.TYPE)) {
+            log.append(")");
+        } else {
+            debugAppend(log.append(") = "), ret);
+        }
+        Log.d(LOGTAG, log.toString());
 
-    @Override
-    public void notifyIME(int type, int state) {
-        Log.d(LOGTAG, "IME: >notifyIME(type=" + type + ", state=" + state + ")");
-        GeckoApp.assertOnGeckoThread();
-        super.notifyIME(type, state);
-    }
-
-    @Override
-    public void notifyIMEEnabled(int state, String typeHint, String modeHint, String actionHint) {
-        Log.d(LOGTAG, "IME: >notifyIMEEnabled(state=" + state + ", typeHint=\"" + typeHint
-                      + "\", modeHint=\"" + modeHint + "\", actionHint=\""
-                      + actionHint + "\"");
-        GeckoApp.assertOnGeckoThread();
-        if (state < IME_STATE_DISABLED || state > IME_STATE_PLUGIN)
-            throw new IllegalArgumentException("Unexpected IMEState=" + state);
-        super.notifyIMEEnabled(state, typeHint, modeHint, actionHint);
+        return ret;
     }
 }
 
-}