mobile/android/base/tests/helpers/FrameworkHelper.java

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mobile/android/base/tests/helpers/FrameworkHelper.java	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,88 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +package org.mozilla.gecko.tests.helpers;
     1.9 +
    1.10 +import static org.mozilla.gecko.tests.helpers.AssertionHelper.fFail;
    1.11 +
    1.12 +import java.lang.reflect.Field;
    1.13 +
    1.14 +import android.content.Context;
    1.15 +import android.view.View;
    1.16 +
    1.17 +/**
    1.18 + * Provides helper functions for accessing Android framework features
    1.19 + *
    1.20 + * This class uses reflection to access framework functionalities that are
    1.21 + * unavailable through the regular Android API. Using reflection in this
    1.22 + * case is okay because it does not touch Gecko classes that go through
    1.23 + * ProGuard.
    1.24 + */
    1.25 +public final class FrameworkHelper {
    1.26 +
    1.27 +    private FrameworkHelper() { /* To disallow instantiation. */ }
    1.28 +
    1.29 +    private static Field getClassField(final Class<?> clazz, final String fieldName)
    1.30 +            throws NoSuchFieldException {
    1.31 +        Class<?> cls = clazz;
    1.32 +        do {
    1.33 +            try {
    1.34 +                return cls.getDeclaredField(fieldName);
    1.35 +            } catch (final NoSuchFieldException e) {
    1.36 +                cls = cls.getSuperclass();
    1.37 +            }
    1.38 +        } while (cls != null);
    1.39 +        // We tried getDeclaredField before; now try getField instead.
    1.40 +        // getField behaves differently in that getField traverses the inheritance
    1.41 +        // list, but it only works on public fields. While getField won't get us
    1.42 +        // anything new, it makes code cleaner by throwing an exception for us.
    1.43 +        return clazz.getField(fieldName);
    1.44 +    }
    1.45 +
    1.46 +    private static Object getField(final Object obj, final String fieldName) {
    1.47 +        try {
    1.48 +            final Field field = getClassField(obj.getClass(), fieldName);
    1.49 +            final boolean accessible = field.isAccessible();
    1.50 +            field.setAccessible(true);
    1.51 +            final Object ret = field.get(obj);
    1.52 +            field.setAccessible(accessible);
    1.53 +            return ret;
    1.54 +        } catch (final NoSuchFieldException e) {
    1.55 +            // We expect a valid field name; if it's not valid,
    1.56 +            // the caller is doing something wrong and should be fixed.
    1.57 +            fFail("Argument field should be a valid field name: " + e.toString());
    1.58 +        } catch (final IllegalAccessException e) {
    1.59 +            // This should not happen. If it does, setAccessible above is not working.
    1.60 +            fFail("Field should be accessible: " + e.toString());
    1.61 +        }
    1.62 +        throw new IllegalStateException("Should not continue from previous failures");
    1.63 +    }
    1.64 +
    1.65 +    private static void setField(final Object obj, final String fieldName, final Object value) {
    1.66 +        try {
    1.67 +            final Field field = getClassField(obj.getClass(), fieldName);
    1.68 +            final boolean accessible = field.isAccessible();
    1.69 +            field.setAccessible(true);
    1.70 +            field.set(obj, value);
    1.71 +            field.setAccessible(accessible);
    1.72 +            return;
    1.73 +        } catch (final NoSuchFieldException e) {
    1.74 +            // We expect a valid field name; if it's not valid,
    1.75 +            // the caller is doing something wrong and should be fixed.
    1.76 +            fFail("Argument field should be a valid field name: " + e.toString());
    1.77 +        } catch (final IllegalAccessException e) {
    1.78 +            // This should not happen. If it does, setAccessible above is not working.
    1.79 +            fFail("Field should be accessible: " + e.toString());
    1.80 +        }
    1.81 +        throw new IllegalStateException("Cannot continue from previous failures");
    1.82 +    }
    1.83 +
    1.84 +    public static Context getViewContext(final View v) {
    1.85 +        return (Context) getField(v, "mContext");
    1.86 +    }
    1.87 +
    1.88 +    public static void setViewContext(final View v, final Context c) {
    1.89 +        setField(v, "mContext", c);
    1.90 +    }
    1.91 +}

mercurial