Back out d9bdfdfda06e to dd17e0758a00 (bug 913985) due to incorrect author on some of the patches. r=backout
authorKartikaya Gupta <kgupta@mozilla.com>
Fri, 27 Sep 2013 10:25:23 -0400
changeset 162813 20f8a91110093e917f587a6fb5382dc7ec87e6cb
parent 162812 616819179a674f62a3602b9cd6f494f75b24f8cb
child 162814 05fe8b17516ad91b194a60806a82ea4b88359d35
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs913985
milestone27.0a1
backs outd9bdfdfda06e0c7befd47387441673c3be25ce7e
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
Back out d9bdfdfda06e to dd17e0758a00 (bug 913985) due to incorrect author on some of the patches. r=backout
build/annotationProcessors/AnnotationInfo.java
build/annotationProcessors/AnnotationProcessor.java
build/annotationProcessors/CodeGenerator.java
build/annotationProcessors/MethodWithAnnotationInfo.java
build/annotationProcessors/classloader/AnnotatableEntity.java
build/annotationProcessors/classloader/ClassWithOptions.java
build/annotationProcessors/classloader/IterableJarLoadingURLClassLoader.java
build/annotationProcessors/classloader/JarClassIterator.java
build/annotationProcessors/utils/AlphabeticAnnotatableEntityComparator.java
build/annotationProcessors/utils/AlphabeticMethodComparator.java
build/annotationProcessors/utils/GeneratableElementIterator.java
build/annotationProcessors/utils/GeneratableEntryPointIterator.java
build/annotationProcessors/utils/Utils.java
dom/ipc/ContentParent.cpp
dom/plugins/base/nsNPAPIPlugin.cpp
dom/plugins/base/nsNPAPIPluginInstance.cpp
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/system/android/AndroidLocationProvider.cpp
dom/system/android/nsHapticFeedback.cpp
gfx/gl/GLContext.h
gfx/thebes/nsSurfaceTexture.cpp
hal/android/AndroidHal.cpp
hal/android/AndroidSensor.cpp
ipc/glue/MessagePump.cpp
mobile/android/base/GeckoAppShell.java
mobile/android/base/GeckoEvent.java
mobile/android/base/GeckoJavaSampler.java
mobile/android/base/Makefile.in
mobile/android/base/SurfaceBits.java
mobile/android/base/ThumbnailHelper.java
mobile/android/base/gfx/DisplayPortMetrics.java
mobile/android/base/gfx/GLController.java
mobile/android/base/gfx/GeckoLayerClient.java
mobile/android/base/gfx/ImmutableViewportMetrics.java
mobile/android/base/gfx/LayerRenderer.java
mobile/android/base/gfx/LayerView.java
mobile/android/base/gfx/NativePanZoomController.java
mobile/android/base/gfx/ProgressiveUpdateData.java
mobile/android/base/gfx/ViewTransform.java
mobile/android/base/mozglue/GeneratableAndroidBridgeTarget.java
mobile/android/base/mozglue/NativeZip.java
mobile/android/base/mozglue/OptionalGeneratedParameter.java
mobile/android/base/mozglue/generatorannotations/GeneratorOptions.java
mobile/android/base/mozglue/generatorannotations/OptionalGeneratedParameter.java
mobile/android/base/mozglue/generatorannotations/WrapElementForJNI.java
mobile/android/base/mozglue/generatorannotations/WrapEntireClassForJNI.java
mobile/android/base/sqlite/MatrixBlobCursor.java
mobile/android/base/sqlite/SQLiteBridgeException.java
mobile/android/base/util/Clipboard.java
mobile/android/components/build/nsAndroidHistory.cpp
mobile/android/components/build/nsShellService.cpp
netwerk/base/src/Tickler.cpp
netwerk/protocol/device/CameraStreamImpl.cpp
netwerk/system/android/nsAndroidNetworkLinkService.cpp
toolkit/components/alerts/nsAlertsService.cpp
toolkit/components/downloads/nsDownloadManager.cpp
toolkit/components/jsdownloads/src/DownloadPlatform.cpp
toolkit/xre/nsAndroidStartup.cpp
toolkit/xre/nsAppRunner.cpp
tools/profiler/TableTicker.cpp
tools/profiler/platform.cpp
uriloader/exthandler/android/nsAndroidHandlerApp.cpp
uriloader/exthandler/android/nsExternalSharingAppService.cpp
uriloader/exthandler/android/nsMIMEInfoAndroid.cpp
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/AndroidBridgeUtilities.h
widget/android/AndroidJNI.cpp
widget/android/AndroidJNIWrapper.cpp
widget/android/AndroidJavaWrappers.cpp
widget/android/AndroidJavaWrappers.h
widget/android/GeneratedJNIWrappers.cpp
widget/android/GeneratedJNIWrappers.h
widget/android/nsAppShell.cpp
widget/android/nsClipboard.cpp
widget/android/nsIMEPicker.cpp
widget/android/nsLookAndFeel.cpp
widget/android/nsScreenManagerAndroid.cpp
widget/android/nsWindow.cpp
widget/android/nsWindow.h
xpcom/base/nsSystemInfo.cpp
xpcom/components/ManifestParser.cpp
xpcom/io/nsLocalFileUnix.cpp
--- a/build/annotationProcessors/AnnotationProcessor.java
+++ b/build/annotationProcessors/AnnotationProcessor.java
@@ -1,34 +1,26 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.annotationProcessors;
 
-import org.mozilla.gecko.annotationProcessors.classloader.AnnotatableEntity;
-import org.mozilla.gecko.annotationProcessors.classloader.ClassWithOptions;
 import org.mozilla.gecko.annotationProcessors.classloader.IterableJarLoadingURLClassLoader;
-import org.mozilla.gecko.annotationProcessors.utils.GeneratableElementIterator;
+import org.mozilla.gecko.annotationProcessors.utils.GeneratableEntryPointIterator;
 
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.Iterator;
 
 public class AnnotationProcessor {
     public static final String OUTFILE = "GeneratedJNIWrappers.cpp";
     public static final String HEADERFILE = "GeneratedJNIWrappers.h";
 
-    public static final String GENERATED_COMMENT =
-            "// GENERATED CODE\n" +
-            "// Generated by the Java program at /build/annotationProcessors at compile time from\n" +
-            "// annotations on Java methods. To update, change the annotations on the corresponding Java\n" +
-            "// methods and rerun the build. Manually updating this file will cause your build to fail.\n\n";
-
     public static void main(String[] args) {
         // We expect a list of jars on the commandline. If missing, whinge about it.
         if (args.length <= 1) {
             System.err.println("Usage: java AnnotationProcessor jarfiles ...");
             System.exit(1);
         }
 
         System.out.println("Processing annotations...");
@@ -36,126 +28,49 @@ public class AnnotationProcessor {
         // We want to produce the same output as last time as often as possible. Ordering of
         // generated statements, therefore, needs to be consistent.
         Arrays.sort(args);
 
         // Start the clock!
         long s = System.currentTimeMillis();
 
         // Get an iterator over the classes in the jar files given...
-        Iterator<ClassWithOptions> jarClassIterator = IterableJarLoadingURLClassLoader.getIteratorOverJars(args);
-
-        StringBuilder headerFile = new StringBuilder(GENERATED_COMMENT);
-        headerFile.append("#ifndef GeneratedJNIWrappers_h__\n" +
-                          "#define GeneratedJNIWrappers_h__\n\n" +
-                          "#include \"nsXPCOMStrings.h\"\n" +
-                          "#include \"AndroidJavaWrappers.h\"\n" +
-                          "\n" +
-                          "namespace mozilla {\n" +
-                          "namespace widget {\n" +
-                          "namespace android {\n" +
-                          "void InitStubs(JNIEnv *jEnv);\n\n");
+        Iterator<Class<?>> jarClassIterator = IterableJarLoadingURLClassLoader.getIteratorOverJars(args);
 
-        StringBuilder implementationFile = new StringBuilder(GENERATED_COMMENT);
-        implementationFile.append("#include \"GeneratedJNIWrappers.h\"\n" +
-                                  "#include \"AndroidBridgeUtilities.h\"\n" +
-                                  "#include \"nsXPCOMStrings.h\"\n" +
-                                  "#include \"AndroidBridge.h\"\n" +
-                                  "\n" +
-                                  "namespace mozilla {\n" +
-                                  "namespace widget {\n" +
-                                  "namespace android {\n");
-
-        // Used to track the calls to the various class-specific initialisation functions.
-        StringBuilder stubInitialiser = new StringBuilder();
-        stubInitialiser.append("void InitStubs(JNIEnv *jEnv) {\n");
+        CodeGenerator generatorInstance = new CodeGenerator();
 
         while (jarClassIterator.hasNext()) {
-            ClassWithOptions aClassTuple = jarClassIterator.next();
-
-            CodeGenerator generatorInstance;
+            Class<?> aClass = jarClassIterator.next();
 
             // Get an iterator over the appropriately generated methods of this class
-            Iterator<AnnotatableEntity> methodIterator = new GeneratableElementIterator(aClassTuple.wrappedClass);
+            Iterator<MethodWithAnnotationInfo> methodIterator = new GeneratableEntryPointIterator(aClass.getDeclaredMethods());
 
-            if (!methodIterator.hasNext()) {
-                continue;
-            }
-            generatorInstance = new CodeGenerator(aClassTuple.wrappedClass, aClassTuple.generatedName);
-
-            stubInitialiser.append("    ").append(aClassTuple.generatedName).append("::InitStubs(jEnv);\n");
-
-            // Iterate all annotated members in this class..
+            // Iterate all annotated methods in this class..
             while (methodIterator.hasNext()) {
-                AnnotatableEntity aElementTuple = methodIterator.next();
-                switch (aElementTuple.mEntityType) {
-                    case METHOD:
-                        generatorInstance.generateMethod(aElementTuple);
-                        break;
-                    case FIELD:
-                        generatorInstance.generateField(aElementTuple);
-                        break;
-                    case CONSTRUCTOR:
-                        generatorInstance.generateConstructor(aElementTuple);
-                        break;
-                }
+                MethodWithAnnotationInfo aMethodTuple = methodIterator.next();
+                generatorInstance.generateMethod(aMethodTuple, aClass);
             }
 
-            headerFile.append(generatorInstance.getHeaderFileContents());
-            implementationFile.append(generatorInstance.getWrapperFileContents());
         }
 
-        implementationFile.append('\n');
-        stubInitialiser.append("}");
-        implementationFile.append(stubInitialiser);
-
-        implementationFile.append("\n} /* android */\n" +
-                                    "} /* widget */\n" +
-                                    "} /* mozilla */\n");
-
-        headerFile.append("\n} /* android */\n" +
-                            "} /* widget */\n" +
-                            "} /* mozilla */\n" +
-                            "#endif\n");
-
-        writeOutputFiles(headerFile, implementationFile);
+        writeOutputFiles(generatorInstance);
         long e = System.currentTimeMillis();
         System.out.println("Annotation processing complete in " + (e - s) + "ms");
     }
 
-    private static void writeOutputFiles(StringBuilder aHeaderFile, StringBuilder aImplementationFile) {
-        FileOutputStream headerStream = null;
+    private static void writeOutputFiles(CodeGenerator aGenerator) {
         try {
-            headerStream = new FileOutputStream(OUTFILE);
-            headerStream.write(aImplementationFile.toString().getBytes());
+            FileOutputStream outStream = new FileOutputStream(OUTFILE);
+            outStream.write(aGenerator.getWrapperFileContents());
         } catch (IOException e) {
             System.err.println("Unable to write " + OUTFILE + ". Perhaps a permissions issue?");
             e.printStackTrace(System.err);
-        } finally {
-            if (headerStream != null) {
-                try {
-                    headerStream.close();
-                } catch (IOException e) {
-                    System.err.println("Unable to close headerStream due to "+e);
-                    e.printStackTrace(System.err);
-                }
-            }
         }
 
-        FileOutputStream outStream = null;
         try {
-            outStream = new FileOutputStream(HEADERFILE);
-            outStream.write(aHeaderFile.toString().getBytes());
+            FileOutputStream headerStream = new FileOutputStream(HEADERFILE);
+            headerStream.write(aGenerator.getHeaderFileContents());
         } catch (IOException e) {
-            System.err.println("Unable to write " + HEADERFILE + ". Perhaps a permissions issue?");
+            System.err.println("Unable to write " + OUTFILE + ". Perhaps a permissions issue?");
             e.printStackTrace(System.err);
-        } finally {
-            if (outStream != null) {
-                try {
-                    outStream.close();
-                } catch (IOException e) {
-                    System.err.println("Unable to close outStream due to "+e);
-                    e.printStackTrace(System.err);
-                }
-            }
         }
     }
 }
\ No newline at end of file
--- a/build/annotationProcessors/CodeGenerator.java
+++ b/build/annotationProcessors/CodeGenerator.java
@@ -1,618 +1,336 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.annotationProcessors;
 
-import org.mozilla.gecko.annotationProcessors.classloader.AnnotatableEntity;
 import org.mozilla.gecko.annotationProcessors.utils.Utils;
 
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.HashMap;
 import java.util.HashSet;
 
 public class CodeGenerator {
-    private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
-    private static final Annotation[][] GETTER_ARGUMENT_ANNOTATIONS = new Annotation[0][0];
-    private static final Annotation[][] SETTER_ARGUMENT_ANNOTATIONS = new Annotation[1][0];
-
     // Buffers holding the strings to ultimately be written to the output files.
-    private final StringBuilder zeroingCode = new StringBuilder();
     private final StringBuilder wrapperStartupCode = new StringBuilder();
     private final StringBuilder wrapperMethodBodies = new StringBuilder();
-    private final StringBuilder headerPublic = new StringBuilder();
-    private final StringBuilder headerProtected = new StringBuilder();
+    private final StringBuilder headerFields = new StringBuilder();
+    private final StringBuilder headerMethods = new StringBuilder();
 
     private final HashSet<String> seenClasses = new HashSet<String>();
 
-    private final String mCClassName;
-
-    private final Class<?> mClassToWrap;
-
-    private boolean mHasEncounteredDefaultConstructor;
+    private final String GENERATED_COMMENT = "// GENERATED CODE\n" +
+            "// Generated by the Java program at /build/annotationProcessors at compile time from\n" +
+            "// annotations on Java methods. To update, change the annotations on the corresponding Java\n" +
+            "// methods and rerun the build. Manually updating this file will cause your build to fail.\n\n";
 
-    // Used for creating unique names for method ID fields in the face of
-    private final HashMap<Member, String> mMembersToIds = new HashMap<Member, String>();
-    private final HashSet<String> mTakenMemberNames = new HashSet<String>();
-    private int mNameMunger;
-
-    public CodeGenerator(Class<?> aClass, String aGeneratedName) {
-        mClassToWrap = aClass;
-        mCClassName = aGeneratedName;
-
+    public CodeGenerator() {
         // Write the file header things. Includes and so forth.
         // GeneratedJNIWrappers.cpp is generated as the concatenation of wrapperStartupCode with
-        // wrapperMethodBodies. Similarly, GeneratedJNIWrappers.h is the concatenation of headerPublic
-        // with headerProtected.
-        wrapperStartupCode.append("void ").append(mCClassName).append("::InitStubs(JNIEnv *jEnv) {\n" +
-                                  "    initInit();\n");
-
+        // wrapperMethodBodies. Similarly, GeneratedJNIWrappers.h is the concatenation of headerFields
+        // with headerMethods.
+        wrapperStartupCode.append(GENERATED_COMMENT);
+        wrapperStartupCode.append(
+                "#include \"nsXPCOMStrings.h\"\n" +
+                "#include \"AndroidBridge.h\"\n" +
+                "#include \"AndroidBridgeUtilities.h\"\n" +
+                "\n" +
+                "#ifdef DEBUG\n" +
+                "#define ALOG_BRIDGE(args...) ALOG(args)\n" +
+                "#else\n" +
+                "#define ALOG_BRIDGE(args...) ((void)0)\n" +
+                "#endif\n" +
+                "\n" +
+                "using namespace mozilla;\n" +
+                "void AndroidBridge::InitStubs(JNIEnv *jEnv) {\n" +
+                "    initInit();\n");
         // Now we write the various GetStaticMethodID calls here...
-        headerPublic.append("class ").append(mCClassName).append(" : public AutoGlobalWrappedJavaObject {\n" +
-                            "public:\n" +
-                            "    static void InitStubs(JNIEnv *jEnv);\n");
-        headerProtected.append("protected:");
-
-        generateWrapperMethod();
-    }
 
-    /**
-     * Emit a static method which takes an instance of the class being wrapped and returns an instance
-     * of the C++ wrapper class backed by that object.
-     */
-    private void generateWrapperMethod() {
-        headerPublic.append("    static ").append(mCClassName).append("* Wrap(jobject obj);\n" +
-                "    ").append(mCClassName).append("(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {};\n");
-
-        wrapperMethodBodies.append("\n").append(mCClassName).append("* ").append(mCClassName).append("::Wrap(jobject obj) {\n" +
-                "    JNIEnv *env = GetJNIForThread();\n\n" +
-                "    if (!env) {\n" +
-                "        ALOG_BRIDGE(\"Aborted: No env - %s\", __PRETTY_FUNCTION__);\n" +
-                "        return NULL;\n" +
-                "    }\n\n" +
-                "    ").append(mCClassName).append("* ret = new ").append(mCClassName).append("(obj, env);\n" +
-                "    env->DeleteLocalRef(obj);\n" +
-                "    return ret;\n" +
-                "}\n");
-    }
-
-    private void generateMemberCommon(Member theMethod, String aCMethodName, Class<?> aClass) {
-        ensureClassHeaderAndStartup(aClass);
-        writeMemberIdField(theMethod, aCMethodName);
-        writeStartupCode(theMethod);
+        headerFields.append("protected:\n\n");
+        headerMethods.append(GENERATED_COMMENT);
+        headerMethods.append("public:\n\n");
     }
 
     /**
      * Append the appropriate generated code to the buffers for the method provided.
      *
-     * @param aMethodTuple The Java method, plus annotation data.
+     * @param aMethodTuple The Java method, plus the name for the generated method.
+     * @param aClass       The class to which the Java method belongs.
      */
-    public void generateMethod(AnnotatableEntity aMethodTuple) {
+    public void generateMethod(MethodWithAnnotationInfo aMethodTuple, Class<?> aClass) {
         // Unpack the tuple and extract some useful fields from the Method..
-        Method theMethod = aMethodTuple.getMethod();
-
-        String CMethodName = aMethodTuple.mAnnotationInfo.wrapperName;
+        Method aMethod = aMethodTuple.method;
+        String CMethodName = aMethodTuple.wrapperName;
 
-        generateMemberCommon(theMethod, CMethodName, mClassToWrap);
+        String javaMethodName = aMethod.getName();
 
-        boolean isFieldStatic = Utils.isMemberStatic(theMethod);
-        boolean shallGenerateStatic = isFieldStatic || aMethodTuple.mAnnotationInfo.isStatic;
+        ensureClassHeaderAndStartup(aClass);
 
-        Class<?>[] parameterTypes = theMethod.getParameterTypes();
-        Class<?> returnType = theMethod.getReturnType();
+        writeHeaderField(CMethodName);
+        writeStartupCode(CMethodName, javaMethodName, aMethod, aClass);
 
         // Get the C++ method signature for this method.
-        String implementationSignature = Utils.getCImplementationMethodSignature(parameterTypes, returnType, CMethodName, mCClassName);
-        String headerSignature = Utils.getCHeaderMethodSignature(parameterTypes, theMethod.getParameterAnnotations(), returnType, CMethodName, mCClassName, shallGenerateStatic);
+        String implementationSignature = Utils.getCImplementationMethodSignature(aMethod, CMethodName);
+        String headerSignature = Utils.getCHeaderMethodSignature(aMethod, CMethodName, aMethodTuple.isStatic);
 
         // Add the header signature to the header file.
-        writeSignatureToHeader(headerSignature);
+        headerMethods.append(headerSignature);
+        headerMethods.append(";\n");
 
         // Use the implementation signature to generate the method body...
-        writeMethodBody(implementationSignature, CMethodName, theMethod, mClassToWrap, aMethodTuple.mAnnotationInfo.isStatic, aMethodTuple.mAnnotationInfo.isMultithreaded);
-    }
-
-    private void generateGetterOrSetterBody(Class<?> aFieldType, String aFieldName, boolean aIsFieldStatic, boolean isSetter) {
-        StringBuilder argumentContent = null;
-
-        if (isSetter) {
-            Class<?>[] setterArguments = new Class<?>[]{aFieldType};
-            // Marshall the argument..
-            argumentContent = getArgumentMarshalling(setterArguments);
-        }
-
-        boolean isObjectReturningMethod = Utils.isObjectType(aFieldType);
-        wrapperMethodBodies.append("    ");
-        if (isSetter) {
-            wrapperMethodBodies.append("env->Set");
-        } else {
-            wrapperMethodBodies.append("return ");
-
-            if (isObjectReturningMethod) {
-                wrapperMethodBodies.append("static_cast<").append(Utils.getCReturnType(aFieldType)).append(">(");
-            }
-
-            wrapperMethodBodies.append("env->Get");
-        }
-
-        if (aIsFieldStatic) {
-            wrapperMethodBodies.append("Static");
-        }
-        wrapperMethodBodies.append(Utils.getFieldType(aFieldType))
-                           .append("Field(");
-
-        // Static will require the class and the field id. Nonstatic, the object and the field id.
-        if (aIsFieldStatic) {
-            wrapperMethodBodies.append(Utils.getClassReferenceName(mClassToWrap));
-        } else {
-            wrapperMethodBodies.append("wrapped_obj");
-        }
-        wrapperMethodBodies.append(", j")
-                           .append(aFieldName);
-        if (isSetter) {
-            wrapperMethodBodies.append(argumentContent);
-        }
-
-        if (!isSetter && isObjectReturningMethod) {
-            wrapperMethodBodies.append(')');
-        }
-        wrapperMethodBodies.append(");\n" +
-                               "}\n");
-    }
-
-    public void generateField(AnnotatableEntity aFieldTuple) {
-        Field theField = aFieldTuple.getField();
-
-        // Handles a peculiar case when dealing with enum types. We don't care about this field.
-        // It just gets in the way and stops our code from compiling.
-        if (theField.getName().equals("$VALUES")) {
-            return;
-        }
-
-        String CFieldName = aFieldTuple.mAnnotationInfo.wrapperName;
-
-        Class<?> fieldType = theField.getType();
-
-        generateMemberCommon(theField, CFieldName, mClassToWrap);
-
-        boolean isFieldStatic = Utils.isMemberStatic(theField);
-        boolean isFieldFinal = Utils.isMemberFinal(theField);
-        boolean shallGenerateStatic = isFieldStatic || aFieldTuple.mAnnotationInfo.isStatic;
-
-        String getterName = "get" + CFieldName;
-        String getterSignature = Utils.getCImplementationMethodSignature(EMPTY_CLASS_ARRAY, fieldType, getterName, mCClassName);
-        String getterHeaderSignature = Utils.getCHeaderMethodSignature(EMPTY_CLASS_ARRAY, GETTER_ARGUMENT_ANNOTATIONS, fieldType, getterName, mCClassName, shallGenerateStatic);
-
-        writeSignatureToHeader(getterHeaderSignature);
-
-        writeFunctionStartupBoilerPlate(getterSignature, fieldType, isFieldStatic, true);
-
-        generateGetterOrSetterBody(fieldType, CFieldName, isFieldStatic, false);
-
-        // If field not final, also generate a setter function.
-        if (!isFieldFinal) {
-            String setterName = "set" + CFieldName;
-
-            Class<?>[] setterArguments = new Class<?>[]{fieldType};
-
-            String setterSignature = Utils.getCImplementationMethodSignature(setterArguments, Void.class, setterName, mCClassName);
-            String setterHeaderSignature = Utils.getCHeaderMethodSignature(setterArguments, SETTER_ARGUMENT_ANNOTATIONS, Void.class, setterName, mCClassName, shallGenerateStatic);
-
-            writeSignatureToHeader(setterHeaderSignature);
-
-            writeFunctionStartupBoilerPlate(setterSignature, Void.class, isFieldStatic, true);
-
-            generateGetterOrSetterBody(fieldType, CFieldName, isFieldStatic, true);
-        }
-    }
-
-    public void generateConstructor(AnnotatableEntity aCtorTuple) {
-        // Unpack the tuple and extract some useful fields from the Method..
-        Constructor theCtor = aCtorTuple.getConstructor();
-        String CMethodName = mCClassName;
-
-        generateMemberCommon(theCtor, mCClassName, mClassToWrap);
-
-        String implementationSignature = Utils.getCImplementationMethodSignature(theCtor.getParameterTypes(), Void.class, CMethodName, mCClassName);
-        String headerSignature = Utils.getCHeaderMethodSignature(theCtor.getParameterTypes(), theCtor.getParameterAnnotations(), Void.class, CMethodName, mCClassName, false);
-
-        // Slice off the "void " from the start of the constructor declaration.
-        headerSignature = headerSignature.substring(5);
-        implementationSignature = implementationSignature.substring(5);
-
-        // Add the header signatures to the header file.
-        writeSignatureToHeader(headerSignature);
-
-        // Use the implementation signature to generate the method body...
-        writeCtorBody(implementationSignature, theCtor, aCtorTuple.mAnnotationInfo.isMultithreaded);
-
-        if (theCtor.getParameterTypes().length == 0) {
-            mHasEncounteredDefaultConstructor = true;
-        }
+        writeMethodBody(implementationSignature, CMethodName, aMethod, aClass, aMethodTuple.isStatic, aMethodTuple.isMultithreaded);
     }
 
     /**
      * Writes the appropriate header and startup code to ensure the existence of a reference to the
      * class specified. If this is already done, does nothing.
      *
      * @param aClass The target class.
      */
     private void ensureClassHeaderAndStartup(Class<?> aClass) {
         String className = aClass.getCanonicalName();
         if (seenClasses.contains(className)) {
             return;
         }
 
-        zeroingCode.append("jclass ")
-                   .append(mCClassName)
-                   .append("::")
-                   .append(Utils.getClassReferenceName(aClass))
-                   .append(" = 0;\n");
-
         // Add a field to hold the reference...
-        headerProtected.append("\n    static jclass ")
-                       .append(Utils.getClassReferenceName(aClass))
-                       .append(";\n");
+        headerFields.append("\njclass ");
+        headerFields.append(Utils.getClassReferenceName(aClass));
+        headerFields.append(";\n");
 
         // Add startup code to populate it..
-        wrapperStartupCode.append('\n')
-                          .append(Utils.getStartupLineForClass(aClass));
+        wrapperStartupCode.append('\n');
+        wrapperStartupCode.append(Utils.getStartupLineForClass(aClass));
 
         seenClasses.add(className);
     }
 
     /**
-     * Write out the function startup boilerplate for the method described. Check for environment
-     * existence,
-     * @param methodSignature
-     * @param returnType
-     * @param aIsStatic
-     * @param aIsThreaded
-     */
-    private void writeFunctionStartupBoilerPlate(String methodSignature, Class<?> returnType, boolean aIsStatic, boolean aIsThreaded) {
-        // The start-of-function boilerplate. Does the bridge exist? Does the env exist? etc.
-        wrapperMethodBodies.append('\n')
-                           .append(methodSignature)
-                           .append(" {\n");
-
-        wrapperMethodBodies.append("    JNIEnv *env = ");
-        if (!aIsThreaded) {
-            wrapperMethodBodies.append("AndroidBridge::GetJNIEnv();\n");
-        } else {
-            wrapperMethodBodies.append("GetJNIForThread();\n");
-        }
-        wrapperMethodBodies.append("    if (!env) {\n" +
-                                   "        ALOG_BRIDGE(\"Aborted: No env - %s\", __PRETTY_FUNCTION__);\n" +
-                                   "        return").append(Utils.getFailureReturnForType(returnType)).append(";\n" +
-                "    }\n\n");
-    }
-
-    /**
-     * Write out the appropriate JNI frame pushing boilerplate for a call to the member provided (
-     * which must be a constructor or method).
-     *
-     * @param aMethod A constructor/method being wrapped.
-     * @param aIsObjectReturningMethod Does the method being wrapped return an object?
-     */
-    private void writeFramePushBoilerplate(Member aMethod, boolean aIsObjectReturningMethod) {
-        if (aMethod instanceof Field) {
-            throw new IllegalArgumentException("Tried to push frame for a FIELD?!");
-        }
-
-        Method m;
-        Constructor c;
-
-        Class<?> returnType;
-
-        int localReferencesNeeded;
-        if (aMethod instanceof Method) {
-            m = (Method) aMethod;
-            returnType = m.getReturnType();
-            localReferencesNeeded = Utils.enumerateReferenceArguments(m.getParameterTypes());
-        } else {
-            c = (Constructor) aMethod;
-            returnType = Void.class;
-            localReferencesNeeded = Utils.enumerateReferenceArguments(c.getParameterTypes());
-        }
-
-        // Determine the number of local refs required for our local frame..
-        // AutoLocalJNIFrame is not applicable here due to it's inability to handle return values.
-        if (aIsObjectReturningMethod) {
-            localReferencesNeeded++;
-        }
-        wrapperMethodBodies.append("    if (env->PushLocalFrame(").append(localReferencesNeeded).append(") != 0) {\n" +
-                "        ALOG_BRIDGE(\"Exceptional exit of: %s\", __PRETTY_FUNCTION__);\n" +
-                "        env->ExceptionDescribe();\n"+
-                "        env->ExceptionClear();\n" +
-                "        return").append(Utils.getFailureReturnForType(returnType)).append(";\n" +
-                "    }\n\n");
-
-    }
-
-    private StringBuilder getArgumentMarshalling(Class<?>[] argumentTypes) {
-        StringBuilder argumentContent = new StringBuilder();
-
-        // If we have >2 arguments, use the jvalue[] calling approach.
-        argumentContent.append(", ");
-        if (argumentTypes.length > 2) {
-            wrapperMethodBodies.append("    jvalue args[").append(argumentTypes.length).append("];\n");
-            for (int aT = 0; aT < argumentTypes.length; aT++) {
-                wrapperMethodBodies.append("    args[").append(aT).append("].")
-                                   .append(Utils.getArrayArgumentMashallingLine(argumentTypes[aT], "a" + aT));
-            }
-
-            // The only argument is the array of arguments.
-            argumentContent.append("args");
-            wrapperMethodBodies.append('\n');
-        } else {
-            // Otherwise, use the vanilla calling approach.
-            boolean needsNewline = false;
-            for (int aT = 0; aT < argumentTypes.length; aT++) {
-                // If the argument is a string-esque type, create a jstring from it, otherwise
-                // it can be passed directly.
-                if (Utils.isCharSequence(argumentTypes[aT])) {
-                    wrapperMethodBodies.append("    jstring j").append(aT).append(" = AndroidBridge::NewJavaString(env, a").append(aT).append(");\n");
-                    needsNewline = true;
-                    // Ensure we refer to the newly constructed Java string - not to the original
-                    // parameter to the wrapper function.
-                    argumentContent.append('j').append(aT);
-                } else {
-                    argumentContent.append('a').append(aT);
-                }
-                if (aT != argumentTypes.length - 1) {
-                    argumentContent.append(", ");
-                }
-            }
-            if (needsNewline) {
-                wrapperMethodBodies.append('\n');
-            }
-        }
-
-        return argumentContent;
-    }
-
-    private void writeCtorBody(String implementationSignature, Constructor theCtor, boolean aIsThreaded) {
-        Class<?>[] argumentTypes = theCtor.getParameterTypes();
-
-        writeFunctionStartupBoilerPlate(implementationSignature, Void.class, false, aIsThreaded);
-
-        writeFramePushBoilerplate(theCtor, false);
-
-        // Marshall arguments for this constructor, if any...
-        boolean hasArguments = argumentTypes.length != 0;
-
-        StringBuilder argumentContent = new StringBuilder();
-        if (hasArguments) {
-            argumentContent = getArgumentMarshalling(argumentTypes);
-        }
-
-        // The call into Java
-        wrapperMethodBodies.append("    Init(env->NewObject");
-        if (argumentTypes.length > 2) {
-            wrapperMethodBodies.append('A');
-        }
-
-        wrapperMethodBodies.append('(');
-
-
-        // Call takes class id, method id of constructor method, then arguments.
-        wrapperMethodBodies.append(Utils.getClassReferenceName(mClassToWrap)).append(", ");
-
-        wrapperMethodBodies.append(mMembersToIds.get(theCtor))
-        // Tack on the arguments, if any..
-                           .append(argumentContent)
-                           .append("), env);\n" +
-                                   "    env->PopLocalFrame(NULL);\n" +
-                                   "}\n");
-    }
-
-    /**
      * Generates the method body of the C++ wrapper function for the Java method indicated.
      *
      * @param methodSignature The previously-generated C++ method signature for the method to be
      *                        generated.
      * @param aCMethodName    The C++ method name for the method to be generated.
      * @param aMethod         The Java method to be wrapped by the C++ method being generated.
      * @param aClass          The Java class to which the method belongs.
      */
     private void writeMethodBody(String methodSignature, String aCMethodName, Method aMethod, Class<?> aClass, boolean aIsStaticBridgeMethod, boolean aIsMultithreaded) {
         Class<?>[] argumentTypes = aMethod.getParameterTypes();
         Class<?> returnType = aMethod.getReturnType();
 
-        writeFunctionStartupBoilerPlate(methodSignature, returnType, aIsStaticBridgeMethod, aIsMultithreaded);
+        // The start-of-function boilerplate. Does the bridge exist? Does the env exist? etc.
+        wrapperMethodBodies.append('\n');
+        wrapperMethodBodies.append(methodSignature);
+
+        wrapperMethodBodies.append(" {\n");
 
-        boolean isObjectReturningMethod = !returnType.getCanonicalName().equals("void") && Utils.isObjectType(returnType);
+        // Static stubs check the bridge instance has been created before trying to run.
+        if (aIsStaticBridgeMethod) {
+            wrapperMethodBodies.append("    if (!sBridge) {\n" +
+                                       "        ALOG_BRIDGE(\"Aborted: No sBridge - %s\", __PRETTY_FUNCTION__);\n" +
+                                       "        return").append(Utils.getFailureReturnForType(returnType)).append(";\n" +
+                                       "    }\n\n");
+        }
+        wrapperMethodBodies.append("    JNIEnv *env = ");
+        if (!aIsMultithreaded) {
+            wrapperMethodBodies.append("GetJNIEnv();\n");
+        } else {
+            wrapperMethodBodies.append("GetJNIForThread();\n");
+        }
+        wrapperMethodBodies.append("    if (!env) {\n" +
+                                   "        ALOG_BRIDGE(\"Aborted: No env - %s\", __PRETTY_FUNCTION__);\n" +
+                                   "        return").append(Utils.getFailureReturnForType(returnType)).append(";\n" +
+                                   "    }\n\n");
 
-        writeFramePushBoilerplate(aMethod, isObjectReturningMethod);
+        boolean isObjectReturningMethod = !returnType.getCanonicalName().equals("void") && Utils.doesReturnObjectType(aMethod);
+
+        // Determine the number of local refs required for our local frame..
+        // AutoLocalJNIFrame is not applicable here due to it's inability to handle return values.
+        int localReferencesNeeded = Utils.enumerateReferenceArguments(aMethod);
+        if (isObjectReturningMethod) {
+            localReferencesNeeded++;
+        }
+        wrapperMethodBodies.append("    if (env->PushLocalFrame(").append(localReferencesNeeded).append(") != 0) {\n" +
+                                   "        ALOG_BRIDGE(\"Exceptional exit of: %s\", __PRETTY_FUNCTION__);\n" +
+                                   "        env->ExceptionDescribe();\n"+
+                                   "        env->ExceptionClear();\n" +
+                                   "        return").append(Utils.getFailureReturnForType(returnType)).append(";\n" +
+                                   "    }\n\n");
 
         // Marshall arguments, if we have any.
         boolean hasArguments = argumentTypes.length != 0;
 
         // We buffer the arguments to the call separately to avoid needing to repeatedly iterate the
         // argument list while building this line. In the coming code block, we simultaneously
         // construct any argument marshalling code (Creation of jstrings, placement of arguments
         // into an argument array, etc. and the actual argument list passed to the function (in
         // argumentContent).
         StringBuilder argumentContent = new StringBuilder();
         if (hasArguments) {
-            argumentContent = getArgumentMarshalling(argumentTypes);
+            argumentContent.append(", ");
+            // If we have >2 arguments, use the jvalue[] calling approach.
+            if (argumentTypes.length > 2) {
+                wrapperMethodBodies.append("    jvalue args[").append(argumentTypes.length).append("];\n");
+                for (int aT = 0; aT < argumentTypes.length; aT++) {
+                    wrapperMethodBodies.append("    args[").append(aT).append("].");
+                    wrapperMethodBodies.append(Utils.getArrayArgumentMashallingLine(argumentTypes[aT], "a" + aT));
+                }
+
+                // The only argument is the array of arguments.
+                argumentContent.append("args");
+                wrapperMethodBodies.append('\n');
+            } else {
+                // Otherwise, use the vanilla calling approach.
+                boolean needsNewline = false;
+                for (int aT = 0; aT < argumentTypes.length; aT++) {
+                    // If the argument is a string-esque type, create a jstring from it, otherwise
+                    // it can be passed directly.
+                    if (Utils.isCharSequence(argumentTypes[aT])) {
+                        wrapperMethodBodies.append("    jstring j").append(aT).append(" = NewJavaString(env, a").append(aT).append(");\n");
+                        needsNewline = true;
+                        // Ensure we refer to the newly constructed Java string - not to the original
+                        // parameter to the wrapper function.
+                        argumentContent.append('j').append(aT);
+                    } else {
+                        argumentContent.append('a').append(aT);
+                    }
+                    if (aT != argumentTypes.length - 1) {
+                        argumentContent.append(", ");
+                    }
+                }
+                if (needsNewline) {
+                    wrapperMethodBodies.append('\n');
+                }
+            }
         }
 
-        // Allocate a temporary variable to hold the return type from Java.
         wrapperMethodBodies.append("    ");
         if (!returnType.getCanonicalName().equals("void")) {
             if (isObjectReturningMethod) {
                 wrapperMethodBodies.append("jobject");
             } else {
                 wrapperMethodBodies.append(Utils.getCReturnType(returnType));
             }
             wrapperMethodBodies.append(" temp = ");
         }
 
-        boolean isStaticJavaMethod = Utils.isMemberStatic(aMethod);
+        boolean isStaticJavaMethod = Utils.isMethodStatic(aMethod);
 
         // The call into Java
-        wrapperMethodBodies.append("env->")
-                           .append(Utils.getCallPrefix(returnType, isStaticJavaMethod));
+        wrapperMethodBodies.append("env->");
+        wrapperMethodBodies.append(Utils.getCallPrefix(returnType, isStaticJavaMethod));
         if (argumentTypes.length > 2) {
             wrapperMethodBodies.append('A');
         }
 
         wrapperMethodBodies.append('(');
         // If the underlying Java method is nonstatic, we provide the target object to the JNI.
         if (!isStaticJavaMethod) {
-            wrapperMethodBodies.append("wrapped_obj, ");
+            wrapperMethodBodies.append("aTarget, ");
         } else {
-            // If this is a static underlying Java method, we need to use the class reference in our
+            // If the stub to be generated is static, we need to use the singleton to access the class
+            // reference.
+            if (aIsStaticBridgeMethod) {
+                wrapperMethodBodies.append("sBridge->");
+            }
+            // If this is a static underlyin Java method, we need to use the class reference in our
             // call.
             wrapperMethodBodies.append(Utils.getClassReferenceName(aClass)).append(", ");
         }
 
-        wrapperMethodBodies.append(mMembersToIds.get(aMethod));
+        // Write the method id out..
+        if (aIsStaticBridgeMethod) {
+            wrapperMethodBodies.append("sBridge->");
+        }
+        wrapperMethodBodies.append('j');
+        wrapperMethodBodies.append(aCMethodName);
 
         // Tack on the arguments, if any..
-        wrapperMethodBodies.append(argumentContent)
-                           .append(");\n\n");
+        wrapperMethodBodies.append(argumentContent);
+        wrapperMethodBodies.append(");\n\n");
 
         // Check for exception and return the failure value..
         wrapperMethodBodies.append("    if (env->ExceptionCheck()) {\n" +
                                    "        ALOG_BRIDGE(\"Exceptional exit of: %s\", __PRETTY_FUNCTION__);\n" +
                                    "        env->ExceptionDescribe();\n" +
                                    "        env->ExceptionClear();\n" +
                                    "        env->PopLocalFrame(NULL);\n" +
                                    "        return").append(Utils.getFailureReturnForType(returnType)).append(";\n" +
-                                   "    }\n\n");
+                                   "    }\n");
 
         // If we're returning an object, pop the callee's stack frame extracting our ref as the return
         // value.
         if (isObjectReturningMethod) {
-            wrapperMethodBodies.append("    ")
-                               .append(Utils.getCReturnType(returnType))
-                               .append(" ret = static_cast<").append(Utils.getCReturnType(returnType)).append(">(env->PopLocalFrame(temp));\n" +
+            wrapperMethodBodies.append("    ");
+            wrapperMethodBodies.append(Utils.getCReturnType(returnType));
+            wrapperMethodBodies.append(" ret = static_cast<").append(Utils.getCReturnType(returnType)).append(">(env->PopLocalFrame(temp));\n" +
                                        "    return ret;\n");
         } else if (!returnType.getCanonicalName().equals("void")) {
             // If we're a primitive-returning function, just return the directly-obtained primative
             // from the call to Java.
             wrapperMethodBodies.append("    env->PopLocalFrame(NULL);\n" +
                                        "    return temp;\n");
         } else {
             // If we don't return anything, just pop the stack frame and move on with life.
             wrapperMethodBodies.append("    env->PopLocalFrame(NULL);\n");
         }
         wrapperMethodBodies.append("}\n");
     }
 
     /**
-     * Generates the code to get the id of the given member on startup.
+     * Generates the code to get the method id of the given method on startup.
      *
-     * @param aMember         The Java member being wrapped.
+     * @param aCMethodName    The C method name of the method being generated.
+     * @param aJavaMethodName The name of the Java method being wrapped.
+     * @param aMethod         The Java method being wrapped.
      */
-    private void writeStartupCode(Member aMember) {
-        wrapperStartupCode.append("    ")
-                          .append(mMembersToIds.get(aMember))
-                          .append(" = get");
-        if (Utils.isMemberStatic(aMember)) {
+    private void writeStartupCode(String aCMethodName, String aJavaMethodName, Method aMethod, Class<?> aClass) {
+        wrapperStartupCode.append("    j");
+        wrapperStartupCode.append(aCMethodName);
+        wrapperStartupCode.append(" = get");
+        if (Utils.isMethodStatic(aMethod)) {
             wrapperStartupCode.append("Static");
         }
-
-        boolean isField = aMember instanceof Field;
-        if (isField) {
-            wrapperStartupCode.append("Field(\"");
-        } else {
-            wrapperStartupCode.append("Method(\"");
-        }
-        if (aMember instanceof Constructor) {
-            wrapperStartupCode.append("<init>");
-        } else {
-            wrapperStartupCode.append(aMember.getName());
-        }
-
-        wrapperStartupCode.append("\", \"")
-                          .append(Utils.getTypeSignatureStringForMember(aMember))
-                          .append("\");\n");
-    }
-
-    private void writeZeroingFor(Member aMember, final String aMemberName) {
-        if (aMember instanceof Field) {
-            zeroingCode.append("jfieldID ");
-        } else {
-            zeroingCode.append("jmethodID ");
-        }
-        zeroingCode.append(mCClassName)
-                   .append("::")
-                   .append(aMemberName)
-                   .append(" = 0;\n");
+        wrapperStartupCode.append("Method(\"");
+        wrapperStartupCode.append(aJavaMethodName);
+        wrapperStartupCode.append("\", \"");
+        wrapperStartupCode.append(Utils.getTypeSignatureString(aMethod));
+        wrapperStartupCode.append("\");\n");
     }
 
     /**
-     * Write the field declaration for the C++ id field of the given member.
+     * Create a method id field in the header file for the C method name provided.
      *
-     * @param aMember Member for which an id field needs to be generated.
+     * @param aMethodName C method name to generate a method id field for.
      */
-    private void writeMemberIdField(Member aMember, final String aCMethodName) {
-        String memberName = 'j'+ aCMethodName;
-
-        if (aMember instanceof Field) {
-            headerProtected.append("    static jfieldID ");
-        } else {
-            headerProtected.append("    static jmethodID ");
-        }
-
-        while(mTakenMemberNames.contains(memberName)) {
-            memberName = 'j' + aCMethodName + mNameMunger;
-            mNameMunger++;
-        }
-
-        writeZeroingFor(aMember, memberName);
-        mMembersToIds.put(aMember, memberName);
-        mTakenMemberNames.add(memberName);
-
-        headerProtected.append(memberName)
-                       .append(";\n");
-    }
-
-    /**
-     * Helper function to add a provided method signature to the public section of the generated header.
-     *
-     * @param aSignature The header to add.
-     */
-    private void writeSignatureToHeader(String aSignature) {
-        headerPublic.append("    ")
-                    .append(aSignature)
-                    .append(";\n");
+    private void writeHeaderField(String aMethodName) {
+        headerFields.append("jmethodID j");
+        headerFields.append(aMethodName);
+        headerFields.append(";\n");
     }
 
     /**
      * Get the finalised bytes to go into the generated wrappers file.
      *
      * @return The bytes to be written to the wrappers file.
      */
-    public String getWrapperFileContents() {
+    public byte[] getWrapperFileContents() {
         wrapperStartupCode.append("}\n");
-        zeroingCode.append(wrapperStartupCode)
-                   .append(wrapperMethodBodies);
+        wrapperStartupCode.append(wrapperMethodBodies);
         wrapperMethodBodies.setLength(0);
-        wrapperStartupCode.setLength(0);
-        return zeroingCode.toString();
+        return wrapperStartupCode.toString().getBytes();
     }
 
     /**
      * Get the finalised bytes to go into the generated header file.
      *
      * @return The bytes to be written to the header file.
      */
-    public String getHeaderFileContents() {
-        if (!mHasEncounteredDefaultConstructor) {
-            headerPublic.append("    ").append(mCClassName).append("() : AutoGlobalWrappedJavaObject() {};\n");
-        }
-        headerProtected.append("};\n\n");
-        headerPublic.append(headerProtected);
-        headerProtected.setLength(0);
-        return headerPublic.toString();
+    public byte[] getHeaderFileContents() {
+        headerFields.append('\n');
+        headerFields.append(headerMethods);
+        headerMethods.setLength(0);
+        return headerFields.toString().getBytes();
     }
 }
rename from build/annotationProcessors/AnnotationInfo.java
rename to build/annotationProcessors/MethodWithAnnotationInfo.java
--- a/build/annotationProcessors/AnnotationInfo.java
+++ b/build/annotationProcessors/MethodWithAnnotationInfo.java
@@ -1,20 +1,24 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.annotationProcessors;
 
+import java.lang.reflect.Method;
+
 /**
- * Object holding annotation data. Used by GeneratableElementIterator.
+ * Object holding method and annotation. Used by GeneratableEntryPointIterator.
  */
-public class AnnotationInfo {
+public class MethodWithAnnotationInfo {
+    public final Method method;
     public final String wrapperName;
     public final boolean isStatic;
     public final boolean isMultithreaded;
 
-    public AnnotationInfo(String aWrapperName, boolean aIsStatic, boolean aIsMultithreaded) {
+    public MethodWithAnnotationInfo(Method aMethod, String aWrapperName, boolean aIsStatic, boolean aIsMultithreaded) {
+        method = aMethod;
         wrapperName = aWrapperName;
         isStatic = aIsStatic;
         isMultithreaded = aIsMultithreaded;
     }
 }
deleted file mode 100644
--- a/build/annotationProcessors/classloader/AnnotatableEntity.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.annotationProcessors.classloader;
-
-import org.mozilla.gecko.annotationProcessors.AnnotationInfo;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-
-/**
- * Union type to hold either a method, field, or ctor. Allows us to iterate "The generatable stuff", despite
- * the fact that such things can be of either flavour.
- */
-public class AnnotatableEntity {
-    public enum ENTITY_TYPE {METHOD, FIELD, CONSTRUCTOR}
-
-    private final Member mMember;
-    public final ENTITY_TYPE mEntityType;
-
-    public final AnnotationInfo mAnnotationInfo;
-
-    public AnnotatableEntity(Member aObject, AnnotationInfo aAnnotationInfo) {
-        mMember = aObject;
-        mAnnotationInfo = aAnnotationInfo;
-
-        if (aObject instanceof Method) {
-            mEntityType = ENTITY_TYPE.METHOD;
-        } else if (aObject instanceof Field) {
-            mEntityType = ENTITY_TYPE.FIELD;
-        } else {
-            mEntityType = ENTITY_TYPE.CONSTRUCTOR;
-        }
-    }
-
-    public Method getMethod() {
-        if (mEntityType != ENTITY_TYPE.METHOD) {
-            throw new UnsupportedOperationException("Attempt to cast to unsupported member type.");
-        }
-        return (Method) mMember;
-    }
-    public Field getField() {
-        if (mEntityType != ENTITY_TYPE.FIELD) {
-            throw new UnsupportedOperationException("Attempt to cast to unsupported member type.");
-        }
-        return (Field) mMember;
-    }
-    public Constructor getConstructor() {
-        if (mEntityType != ENTITY_TYPE.CONSTRUCTOR) {
-            throw new UnsupportedOperationException("Attempt to cast to unsupported member type.");
-        }
-        return (Constructor) mMember;
-    }
-}
deleted file mode 100644
--- a/build/annotationProcessors/classloader/ClassWithOptions.java
+++ /dev/null
@@ -1,15 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.annotationProcessors.classloader;
-
-public class ClassWithOptions {
-    public final Class<?> wrappedClass;
-    public final String generatedName;
-
-    public ClassWithOptions(Class<?> someClass, String name) {
-        wrappedClass = someClass;
-        generatedName = name;
-    }
-}
--- a/build/annotationProcessors/classloader/IterableJarLoadingURLClassLoader.java
+++ b/build/annotationProcessors/classloader/IterableJarLoadingURLClassLoader.java
@@ -16,45 +16,50 @@ import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 
 /**
  * A classloader which can be initialised with a list of jar files and which can provide an iterator
  * over the top level classes in the jar files it was initialised with.
  * classNames is kept sorted to ensure iteration order is consistent across program invocations.
  * Otherwise, we'd forever be reporting the outdatedness of the generated code as we permute its
  * contents.
+ * This classloader does not support inner classes. (You probably shouldn't be putting JNI entry
+ * points in inner classes anyway)
  */
 public class IterableJarLoadingURLClassLoader extends URLClassLoader {
     LinkedList<String> classNames = new LinkedList<String>();
 
     /**
      * Create an instance and return its iterator. Provides an iterator over the classes in the jar
      * files provided as arguments.
      * Inner classes are not supported.
      *
      * @param args A list of jar file names an iterator over the classes of which is desired.
      * @return An iterator over the top level classes in the jar files provided, in arbitrary order.
      */
-    public static Iterator<ClassWithOptions> getIteratorOverJars(String[] args) {
+    public static Iterator<Class<?>> getIteratorOverJars(String[] args) {
         URL[] urlArray = new URL[args.length];
         LinkedList<String> aClassNames = new LinkedList<String>();
 
         for (int i = 0; i < args.length; i++) {
             try {
                 urlArray[i] = (new File(args[i])).toURI().toURL();
 
                 Enumeration<JarEntry> entries = new JarFile(args[i]).entries();
                 while (entries.hasMoreElements()) {
                     JarEntry e = entries.nextElement();
                     String fName = e.getName();
                     if (!fName.endsWith(".class")) {
                         continue;
                     }
                     final String className = fName.substring(0, fName.length() - 6).replace('/', '.');
-
+                    // Inner classes are not supported.
+                    if (className.contains("$")) {
+                        continue;
+                    }
                     aClassNames.add(className);
                 }
             } catch (IOException e) {
                 System.err.println("Error loading jar file \"" + args[i] + '"');
                 e.printStackTrace(System.err);
             }
         }
         Collections.sort(aClassNames);
--- a/build/annotationProcessors/classloader/JarClassIterator.java
+++ b/build/annotationProcessors/classloader/JarClassIterator.java
@@ -1,77 +1,38 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.annotationProcessors.classloader;
 
-import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.util.Iterator;
 
 /**
  * Class for iterating over an IterableJarLoadingURLClassLoader's classes.
  */
-public class JarClassIterator implements Iterator<ClassWithOptions> {
+public class JarClassIterator implements Iterator<Class<?>> {
     private IterableJarLoadingURLClassLoader mTarget;
     private Iterator<String> mTargetClassListIterator;
 
     public JarClassIterator(IterableJarLoadingURLClassLoader aTarget) {
         mTarget = aTarget;
         mTargetClassListIterator = aTarget.classNames.iterator();
     }
 
     @Override
     public boolean hasNext() {
         return mTargetClassListIterator.hasNext();
     }
 
     @Override
-    public ClassWithOptions next() {
+    public Class<?> next() {
         String className = mTargetClassListIterator.next();
         try {
-            Class<?> ret = mTarget.loadClass(className);
-            if (ret.getCanonicalName() == null || "null".equals(ret.getCanonicalName())) {
-                // Anonymous inner class - unsupported.
-                return next();
-            } else {
-                String generateName = null;
-                for (Annotation annotation : ret.getAnnotations()) {
-                    Class<?> annotationType = annotation.annotationType();
-                    if (annotationType.getCanonicalName().equals("org.mozilla.gecko.mozglue.generatorannotations.GeneratorOptions")) {
-                        try {
-                            // Determine the explicitly-given name of the stub to generate, if any.
-                            final Method generateNameMethod = annotationType.getDeclaredMethod("generatedClassName");
-                            generateNameMethod.setAccessible(true);
-                            generateName = (String) generateNameMethod.invoke(annotation);
-                            break;
-                        } catch (NoSuchMethodException e) {
-                            System.err.println("Unable to find expected field on GeneratorOptions annotation. Did the signature change?");
-                            e.printStackTrace(System.err);
-                            System.exit(3);
-                        } catch (IllegalAccessException e) {
-                            System.err.println("IllegalAccessException reading fields on GeneratorOptions annotation. Seems the semantics of Reflection have changed...");
-                            e.printStackTrace(System.err);
-                            System.exit(4);
-                        } catch (InvocationTargetException e) {
-                            System.err.println("InvocationTargetException reading fields on GeneratorOptions annotation. This really shouldn't happen.");
-                            e.printStackTrace(System.err);
-                            System.exit(5);
-                        }
-                    }
-                }
-
-                if (generateName == null) {
-                    generateName = ret.getSimpleName();
-                }
-
-                return new ClassWithOptions(ret, generateName);
-            }
+            return mTarget.loadClass(className);
         } catch (ClassNotFoundException e) {
             System.err.println("Unable to enumerate class: " + className + ". Corrupted jar file?");
             e.printStackTrace();
             System.exit(2);
         }
         return null;
     }
 
rename from build/annotationProcessors/utils/AlphabeticAnnotatableEntityComparator.java
rename to build/annotationProcessors/utils/AlphabeticMethodComparator.java
--- a/build/annotationProcessors/utils/AlphabeticAnnotatableEntityComparator.java
+++ b/build/annotationProcessors/utils/AlphabeticMethodComparator.java
@@ -1,81 +1,28 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.annotationProcessors.utils;
 
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
 import java.lang.reflect.Method;
 import java.util.Comparator;
 
-public class AlphabeticAnnotatableEntityComparator<T extends Member> implements Comparator<T> {
+public class AlphabeticMethodComparator implements Comparator<Method> {
     @Override
-    public int compare(T aLhs, T aRhs) {
-        // Constructors, Methods, Fields.
-        boolean lIsConstructor = aLhs instanceof Constructor;
-        boolean rIsConstructor = aRhs instanceof Constructor;
-        boolean lIsMethod = aLhs instanceof Method;
-        boolean rIsField = aRhs instanceof Field;
-
-        if (lIsConstructor) {
-            if (!rIsConstructor) {
-                return -1;
-            }
-        } else if (lIsMethod) {
-            if (rIsConstructor) {
-                return 1;
-            } else if (rIsField) {
-                return -1;
-            }
-        } else {
-            if (!rIsField) {
-                return 1;
-            }
-        }
-
-        // Verify these objects are the same type and cast them.
-        if (aLhs instanceof Method) {
-            return compare((Method) aLhs, (Method) aRhs);
-        } else if (aLhs instanceof Field) {
-            return compare((Field) aLhs, (Field) aRhs);
-        } else {
-            return compare((Constructor) aLhs, (Constructor) aRhs);
-        }
-    }
-
-    // Alas, the type system fails us.
-    private static int compare(Method aLhs, Method aRhs) {
+    public int compare(Method lhs, Method rhs) {
         // Initially, attempt to differentiate the methods be name alone..
-        String lName = aLhs.getName();
-        String rName = aRhs.getName();
+        String lName = lhs.getName();
+        String rName = rhs.getName();
 
         int ret = lName.compareTo(rName);
         if (ret != 0) {
             return ret;
         }
 
         // The names were the same, so we need to compare signatures to find their uniqueness..
-        lName = Utils.getTypeSignatureStringForMethod(aLhs);
-        rName = Utils.getTypeSignatureStringForMethod(aRhs);
-
-        return lName.compareTo(rName);
-    }
-
-    private static int compare(Constructor aLhs, Constructor aRhs) {
-        // The names will be the same, so we need to compare signatures to find their uniqueness..
-        String lName = Utils.getTypeSignatureString(aLhs);
-        String rName = Utils.getTypeSignatureString(aRhs);
-
-        return lName.compareTo(rName);
-    }
-
-    private static int compare(Field aLhs, Field aRhs) {
-        // Compare field names..
-        String lName = aLhs.getName();
-        String rName = aRhs.getName();
+        lName = Utils.getTypeSignatureString(lhs);
+        rName = Utils.getTypeSignatureString(rhs);
 
         return lName.compareTo(rName);
     }
 }
rename from build/annotationProcessors/utils/GeneratableElementIterator.java
rename to build/annotationProcessors/utils/GeneratableEntryPointIterator.java
--- a/build/annotationProcessors/utils/GeneratableElementIterator.java
+++ b/build/annotationProcessors/utils/GeneratableEntryPointIterator.java
@@ -1,84 +1,57 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.annotationProcessors.utils;
 
-import org.mozilla.gecko.annotationProcessors.AnnotationInfo;
-import org.mozilla.gecko.annotationProcessors.classloader.AnnotatableEntity;
+import org.mozilla.gecko.annotationProcessors.MethodWithAnnotationInfo;
 
 import java.lang.annotation.Annotation;
-import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Member;
 import java.lang.reflect.Method;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
 
 /**
- * Iterator over the methods in a given method list which have the WrappedJNIMethod
+ * Iterator over the methods in a given method list which have the GeneratableAndroidBridgeTarget
  * annotation. Returns an object containing both the annotation (Which may contain interesting
  * parameters) and the argument.
  */
-public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
-    private final Member[] mObjects;
-    private AnnotatableEntity mNextReturnValue;
-    private int mElementIndex;
-
-    private boolean mIterateEveryEntry;
-
-    public GeneratableElementIterator(Class<?> aClass) {
-        // Get all the elements of this class as AccessibleObjects.
-        Member[] aMethods = aClass.getDeclaredMethods();
-        Member[] aFields = aClass.getDeclaredFields();
-        Member[] aCtors = aClass.getConstructors();
+public class GeneratableEntryPointIterator implements Iterator<MethodWithAnnotationInfo> {
+    private final Method[] mMethods;
+    private MethodWithAnnotationInfo mNextReturnValue;
+    private int mMethodIndex;
 
-        // Shove them all into one buffer.
-        Member[] objs = new Member[aMethods.length + aFields.length + aCtors.length];
-        int offset = 0;
-        System.arraycopy(aMethods, 0, objs, 0, aMethods.length);
-        offset += aMethods.length;
-        System.arraycopy(aFields, 0, objs, offset, aFields.length);
-        offset += aFields.length;
-        System.arraycopy(aCtors, 0, objs, offset, aCtors.length);
-
-        // Sort the elements to ensure determinism.
-        Arrays.sort(objs, new AlphabeticAnnotatableEntityComparator());
-
-        mObjects = objs;
-
-        // Check for "Wrap ALL the things" flag.
-        for (Annotation annotation : aClass.getDeclaredAnnotations()) {
-            final String annotationTypeName = annotation.annotationType().getName();
-
-            if (annotationTypeName.equals("org.mozilla.gecko.mozglue.generatorannotations.WrapEntireClassForJNI")) {
-                mIterateEveryEntry = true;
-                break;
-            }
-        }
+    public GeneratableEntryPointIterator(Method[] aMethods) {
+        // Sort the methods into alphabetical order by name, to ensure we always iterate methods
+        // in the same order..
+        Arrays.sort(aMethods, new AlphabeticMethodComparator());
+        mMethods = aMethods;
 
         findNextValue();
     }
 
     /**
      * Find and cache the next appropriately annotated method, plus the annotation parameter, if
      * one exists. Otherwise cache null, so hasNext returns false.
      */
     private void findNextValue() {
-        while (mElementIndex < mObjects.length) {
-            Member candidateElement = mObjects[mElementIndex];
-            mElementIndex++;
-            for (Annotation annotation : ((AnnotatedElement) candidateElement).getDeclaredAnnotations()) {
-                // WrappedJNIMethod has a parameter. Use Reflection to obtain it.
+        while (mMethodIndex < mMethods.length) {
+            Method candidateMethod = mMethods[mMethodIndex];
+            mMethodIndex++;
+            for (Annotation annotation : candidateMethod.getDeclaredAnnotations()) {
+                // GeneratableAndroidBridgeTarget has a parameter. Use Reflection to obtain it.
                 Class<? extends Annotation> annotationType = annotation.annotationType();
                 final String annotationTypeName = annotationType.getName();
 
-                if (annotationTypeName.equals("org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI")) {
+                if (annotationTypeName.equals("org.mozilla.gecko.mozglue.GeneratableAndroidBridgeTarget")) {
                     String stubName = null;
                     boolean isStaticStub = false;
                     boolean isMultithreadedStub = false;
                     try {
                         // Determine the explicitly-given name of the stub to generate, if any.
                         final Method stubNameMethod = annotationType.getDeclaredMethod("stubName");
                         stubNameMethod.setAccessible(true);
                         stubName = (String) stubNameMethod.invoke(annotation);
@@ -88,61 +61,51 @@ public class GeneratableElementIterator 
                         staticStubMethod.setAccessible(true);
                         isStaticStub = (Boolean) staticStubMethod.invoke(annotation);
 
                         // Determine if the generated stub is to allow calls from multiple threads.
                         final Method multithreadedStubMethod = annotationType.getDeclaredMethod("allowMultithread");
                         multithreadedStubMethod.setAccessible(true);
                         isMultithreadedStub = (Boolean) multithreadedStubMethod.invoke(annotation);
                     } catch (NoSuchMethodException e) {
-                        System.err.println("Unable to find expected field on WrappedJNIMethod annotation. Did the signature change?");
+                        System.err.println("Unable to find expected field on GeneratableAndroidBridgeTarget annotation. Did the signature change?");
                         e.printStackTrace(System.err);
                         System.exit(3);
                     } catch (IllegalAccessException e) {
-                        System.err.println("IllegalAccessException reading fields on WrappedJNIMethod annotation. Seems the semantics of Reflection have changed...");
+                        System.err.println("IllegalAccessException reading fields on GeneratableAndroidBridgeTarget annotation. Seems the semantics of Reflection have changed...");
                         e.printStackTrace(System.err);
                         System.exit(4);
                     } catch (InvocationTargetException e) {
-                        System.err.println("InvocationTargetException reading fields on WrappedJNIMethod annotation. This really shouldn't happen.");
+                        System.err.println("InvocationTargetException reading fields on GeneratableAndroidBridgeTarget annotation. This really shouldn't happen.");
                         e.printStackTrace(System.err);
                         System.exit(5);
                     }
-
-                    // If the element name was not explicitly given in the annotation generate one...
+                    // If the method name was not explicitly given in the annotation generate one...
                     if (stubName.isEmpty()) {
-                        String elementName = candidateElement.getName();
-                        stubName = elementName.substring(0, 1).toUpperCase() + elementName.substring(1);
+                        String aMethodName = candidateMethod.getName();
+                        stubName = aMethodName.substring(0, 1).toUpperCase() + aMethodName.substring(1);
                     }
 
-                    AnnotationInfo annotationInfo = new AnnotationInfo(stubName, isStaticStub, isMultithreadedStub);
-                    mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo);
+                    mNextReturnValue = new MethodWithAnnotationInfo(candidateMethod, stubName, isStaticStub, isMultithreadedStub);
                     return;
                 }
             }
-
-            // If no annotation found, we might be expected to generate anyway using default arguments,
-            // thanks to the "Generate everything" annotation.
-            if (mIterateEveryEntry) {
-                AnnotationInfo annotationInfo = new AnnotationInfo(candidateElement.getName(), false, false);
-                mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo);
-                return;
-            }
         }
         mNextReturnValue = null;
     }
 
     @Override
     public boolean hasNext() {
         return mNextReturnValue != null;
     }
 
     @Override
-    public AnnotatableEntity next() {
-        AnnotatableEntity ret = mNextReturnValue;
+    public MethodWithAnnotationInfo next() {
+        MethodWithAnnotationInfo ret = mNextReturnValue;
         findNextValue();
         return ret;
     }
 
     @Override
     public void remove() {
-        throw new UnsupportedOperationException("Removal of methods from GeneratableElementIterator not supported.");
+        throw new UnsupportedOperationException("Removal of methods from GeneratableEntryPointIterator not supported.");
     }
 }
--- a/build/annotationProcessors/utils/Utils.java
+++ b/build/annotationProcessors/utils/Utils.java
@@ -1,18 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.annotationProcessors.utils;
 
 import java.lang.annotation.Annotation;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.HashMap;
 
 /**
  * A collection of utility methods used by CodeGenerator. Largely used for translating types.
  */
 public class Utils {
@@ -68,48 +65,33 @@ public class Utils {
         sInstanceCallTypes.put("long", "CallLongMethod");
         sInstanceCallTypes.put("double", "CallDoubleMethod");
         sInstanceCallTypes.put("float", "CallFloatMethod");
         sInstanceCallTypes.put("char", "CallCharMethod");
         sInstanceCallTypes.put("byte", "CallByteMethod");
         sInstanceCallTypes.put("short", "CallShortMethod");
     }
 
-    private static final HashMap<String, String> sFieldTypes = new HashMap<String, String>();
-
-    static {
-        sFieldTypes.put("int", "Int");
-        sFieldTypes.put("boolean", "Boolean");
-        sFieldTypes.put("long", "Long");
-        sFieldTypes.put("double", "Double");
-        sFieldTypes.put("float", "Float");
-        sFieldTypes.put("char", "Char");
-        sFieldTypes.put("byte", "Byte");
-        sFieldTypes.put("short", "Short");
-    }
-
     private static final HashMap<String, String> sFailureReturns = new HashMap<String, String>();
 
     static {
-        sFailureReturns.put("java.lang.Void", "");
         sFailureReturns.put("void", "");
         sFailureReturns.put("int", " 0");
         sFailureReturns.put("boolean", " false");
         sFailureReturns.put("long", " 0");
         sFailureReturns.put("double", " 0.0");
         sFailureReturns.put("float", " 0.0");
         sFailureReturns.put("char", " 0");
         sFailureReturns.put("byte", " 0");
         sFailureReturns.put("short", " 0");
     }
 
     private static final HashMap<String, String> sCanonicalSignatureParts = new HashMap<String, String>();
 
     static {
-        sCanonicalSignatureParts.put("java/lang/Void", "V");
         sCanonicalSignatureParts.put("void", "V");
         sCanonicalSignatureParts.put("int", "I");
         sCanonicalSignatureParts.put("boolean", "Z");
         sCanonicalSignatureParts.put("long", "J");
         sCanonicalSignatureParts.put("double", "D");
         sCanonicalSignatureParts.put("float", "F");
         sCanonicalSignatureParts.put("char", "C");
         sCanonicalSignatureParts.put("byte", "B");
@@ -177,43 +159,26 @@ public class Utils {
 
     /**
      * For a given Java type, get the corresponding C++ type if we're returning it from a function.
      *
      * @param type The Java return type.
      * @return A string representation of the C++ return type.
      */
     public static String getCReturnType(Class<?> type) {
-        if (type.getCanonicalName().equals("java.lang.Void")) {
-            return "void";
-        }
+        // Since there's only one thing we want to do differently...
         String cParameterType = getCParameterType(type);
         if (cParameterType.equals("const nsAString&")) {
             return "jstring";
         } else {
             return cParameterType;
         }
     }
 
     /**
-     * Gets the type-specific part of the  JNI function to use to get or set a field of a given type.
-     *
-     * @param aFieldType The Java type of the field.
-     * @return A string representation of the JNI call function substring to use.
-     */
-    public static String getFieldType(Class<?> aFieldType) {
-        String name = aFieldType.getCanonicalName();
-
-        if (sFieldTypes.containsKey(name)) {
-            return sFieldTypes.get(name);
-        }
-        return "Object";
-    }
-
-    /**
      * Gets the appropriate JNI call function to use to invoke a Java method with the given return
      * type. This, plus a call postfix (Such as "A") forms a complete JNI call function name.
      *
      * @param aReturnType The Java return type of the method being generated.
      * @param isStatic Boolean indicating if the underlying Java method is declared static.
      * @return A string representation of the JNI call function prefix to use.
      */
     public static String getCallPrefix(Class<?> aReturnType, boolean isStatic) {
@@ -242,221 +207,158 @@ public class Utils {
         String name = type.getCanonicalName();
         if (sFailureReturns.containsKey(name)) {
             return sFailureReturns.get(name);
         }
         return " nullptr";
     }
 
     /**
-     * Helper method to get the type signature for methods, given argument and return type.
-     * Allows for the near-identical logic needed for constructors and methods to be shared.
-     * (Alas, constructor does not extend method)
+     * Get the canonical JNI type signature for a method.
      *
-     * @param arguments Argument types of the underlying method.
-     * @param returnType Return type of the underlying method.
-     * @return The canonical Java type string for the method. eg. (IIIIFZ)Lorg/mozilla/gecko/gfx/ViewTransform;
+     * @param aMethod The method to generate a signature for.
+     * @return The canonical JNI type signature for this method.
      */
-    private static String getTypeSignatureInternal(Class<?>[] arguments, Class<?> returnType) {
+    public static String getTypeSignatureString(Method aMethod) {
+        Class<?>[] arguments = aMethod.getParameterTypes();
+        Class<?> returnType = aMethod.getReturnType();
+
         StringBuilder sb = new StringBuilder();
         sb.append('(');
         // For each argument, write its signature component to the buffer..
         for (int i = 0; i < arguments.length; i++) {
             writeTypeSignature(sb, arguments[i]);
         }
         sb.append(')');
         // Write the return value's signature..
         writeTypeSignature(sb, returnType);
         return sb.toString();
     }
 
     /**
-     * Get the canonical JNI type signature for a Field.
-     *
-     * @param aField The field to generate a signature for.
-     * @return The canonical JNI type signature for this method.
-     */
-    protected static String getTypeSignatureStringForField(Field aField) {
-        StringBuilder sb = new StringBuilder();
-        writeTypeSignature(sb, aField.getType());
-        return sb.toString();
-    }
-
-    /**
-     * Get the canonical JNI type signature for a method.
-     *
-     * @param aMethod The method to generate a signature for.
-     * @return The canonical JNI type signature for this method.
-     */
-    protected static String getTypeSignatureStringForMethod(Method aMethod) {
-        Class<?>[] arguments = aMethod.getParameterTypes();
-        Class<?> returnType = aMethod.getReturnType();
-
-        return getTypeSignatureInternal(arguments, returnType);
-    }
-
-    /**
-     * Get the canonical JNI type signature for a Constructor.
-     *
-     * @param aConstructor The Constructor to generate a signature for.
-     * @return The canonical JNI type signature for this method.
-     */
-    protected static String getTypeSignatureStringForConstructor(Constructor aConstructor) {
-        Class<?>[] arguments = aConstructor.getParameterTypes();
-
-        return getTypeSignatureInternal(arguments, Void.class);
-    }
-
-    public static String getTypeSignatureStringForMember(Member aMember) {
-        if (aMember instanceof Method) {
-            return getTypeSignatureStringForMethod((Method) aMember);
-        } else if (aMember instanceof Field) {
-            return getTypeSignatureStringForField((Field) aMember);
-        } else {
-            return getTypeSignatureStringForConstructor((Constructor) aMember);
-        }
-    }
-
-    public static String getTypeSignatureString(Constructor aConstructor) {
-        Class<?>[] arguments = aConstructor.getParameterTypes();
-
-        StringBuilder sb = new StringBuilder();
-        sb.append('(');
-        // For each argument, write its signature component to the buffer..
-        for (int i = 0; i < arguments.length; i++) {
-            writeTypeSignature(sb, arguments[i]);
-        }
-
-        // Constructors always return Void.
-        sb.append(")V");
-        return sb.toString();
-    }
-
-    /**
-     * Helper method used by getTypeSignatureStringForMethod to build the signature. Write the subsignature
+     * Helper method used by getTypeSignatureString to build the signature. Write the subsignature
      * of a given type into the buffer.
      *
      * @param sb The buffer to write into.
      * @param c  The type of the element to write the subsignature of.
      */
     private static void writeTypeSignature(StringBuilder sb, Class<?> c) {
         String name = c.getCanonicalName().replaceAll("\\.", "/");
-
         // Determine if this is an array type and, if so, peel away the array operators..
         int len = name.length();
         while (name.endsWith("[]")) {
             sb.append('[');
             name = name.substring(0, len - 2);
         }
 
-        if (c.isArray()) {
-            c = c.getComponentType();
-        }
-
-        Class<?> containerClass = c.getDeclaringClass();
-        if (containerClass != null) {
-            // Is an inner class. Add the $ symbol.
-            final int lastSlash = name.lastIndexOf('/');
-            name = name.substring(0, lastSlash) + '$' + name.substring(lastSlash+1);
-        }
-
         // Look in the hashmap for the remainder...
         if (sCanonicalSignatureParts.containsKey(name)) {
             // It was a primitive type, so lookup was a success.
             sb.append(sCanonicalSignatureParts.get(name));
         } else {
             // It was a reference type - generate.
             sb.append('L');
             sb.append(name);
             sb.append(';');
         }
     }
 
     /**
      * Produces a C method signature, sans semicolon, for the given Java Method. Useful for both
      * generating header files and method bodies.
      *
-     * @param aArgumentTypes Argument types of the Java method being wrapped.
-     * @param aReturnType Return type of the Java method being wrapped.
-     * @param aCMethodName Name of the method to generate in the C++ class.
-     * @param aCClassName Name of the C++ class into which the method is declared.
-     * @return The C++ method implementation signature for the method described.
+     * @param aMethod      The Java method to generate the corresponding wrapper signature for.
+     * @param aCMethodName The name of the generated method this is to be the signatgure for.
+     * @return The generated method signature.
      */
-    public static String getCImplementationMethodSignature(Class<?>[] aArgumentTypes, Class<?> aReturnType, String aCMethodName, String aCClassName) {
-        StringBuilder retBuffer = new StringBuilder();
+    public static String getCImplementationMethodSignature(Method aMethod, String aCMethodName) {
+        Class<?>[] argumentTypes = aMethod.getParameterTypes();
+        Class<?> returnType = aMethod.getReturnType();
 
-        retBuffer.append(getCReturnType(aReturnType));
-        retBuffer.append(' ');
-        retBuffer.append(aCClassName);
-        retBuffer.append("::");
+        StringBuilder retBuffer = new StringBuilder();
+        // Write return type..
+        retBuffer.append(getCReturnType(returnType));
+        retBuffer.append(" AndroidBridge::");
         retBuffer.append(aCMethodName);
         retBuffer.append('(');
 
+        // For an instance method, the first argument is the target object.
+        if (!isMethodStatic(aMethod)) {
+            retBuffer.append("jobject aTarget");
+            if (argumentTypes.length > 0) {
+                retBuffer.append(", ");
+            }
+        }
+
         // Write argument types...
-        for (int aT = 0; aT < aArgumentTypes.length; aT++) {
-            retBuffer.append(getCParameterType(aArgumentTypes[aT]));
+        for (int aT = 0; aT < argumentTypes.length; aT++) {
+            retBuffer.append(getCParameterType(argumentTypes[aT]));
             retBuffer.append(" a");
             // We, imaginatively, call our arguments a1, a2, a3...
             // The only way to preserve the names from Java would be to parse the
             // Java source, which would be computationally hard.
             retBuffer.append(aT);
-            if (aT != aArgumentTypes.length - 1) {
+            if (aT != argumentTypes.length - 1) {
                 retBuffer.append(", ");
             }
         }
         retBuffer.append(')');
         return retBuffer.toString();
     }
 
     /**
      * Produces a C method signature, sans semicolon, for the given Java Method. Useful for both
      * generating header files and method bodies.
      *
      * @param aMethod      The Java method to generate the corresponding wrapper signature for.
      * @param aCMethodName The name of the generated method this is to be the signatgure for.
      * @return The generated method signature.
      */
-    /**
-     *
-     * @param aArgumentTypes Argument types of the Java method being wrapped.
-     * @param aArgumentAnnotations The annotations on the Java method arguments. Used to specify
-     *                             default values etc.
-     * @param aReturnType Return type of the Java method being wrapped.
-     * @param aCMethodName Name of the method to generate in the C++ class.
-     * @param aCClassName Name of the C++ class into which the method is declared.e
-     * @param aIsStaticStub true if the generated C++ method should be static, false otherwise.
-     * @return The generated C++ header method signature for the method described.
-     */
-    public static String getCHeaderMethodSignature(Class<?>[] aArgumentTypes, Annotation[][] aArgumentAnnotations, Class<?> aReturnType, String aCMethodName, String aCClassName, boolean aIsStaticStub) {
+    public static String getCHeaderMethodSignature(Method aMethod, String aCMethodName, boolean aIsStaticStub) {
+        Class<?>[] argumentTypes = aMethod.getParameterTypes();
+
+        // The annotations on the parameters of this method, in declaration order.
+        // Importantly - the same order as those in argumentTypes.
+        Annotation[][] argumentAnnotations = aMethod.getParameterAnnotations();
+        Class<?> returnType = aMethod.getReturnType();
+
         StringBuilder retBuffer = new StringBuilder();
 
         // Add the static keyword, if applicable.
         if (aIsStaticStub) {
             retBuffer.append("static ");
         }
 
         // Write return type..
-        retBuffer.append(getCReturnType(aReturnType));
+        retBuffer.append(getCReturnType(returnType));
         retBuffer.append(' ');
         retBuffer.append(aCMethodName);
         retBuffer.append('(');
 
+        // For an instance method, the first argument is the target object.
+        if (!isMethodStatic(aMethod)) {
+            retBuffer.append("jobject aTarget");
+            if (argumentTypes.length > 0) {
+                retBuffer.append(", ");
+            }
+        }
+
         // Write argument types...
-        for (int aT = 0; aT < aArgumentTypes.length; aT++) {
-            retBuffer.append(getCParameterType(aArgumentTypes[aT]));
+        for (int aT = 0; aT < argumentTypes.length; aT++) {
+            retBuffer.append(getCParameterType(argumentTypes[aT]));
             retBuffer.append(" a");
             // We, imaginatively, call our arguments a1, a2, a3...
             // The only way to preserve the names from Java would be to parse the
             // Java source, which would be computationally hard.
             retBuffer.append(aT);
 
             // Append the default value, if there is one..
-            retBuffer.append(getDefaultValueString(aArgumentTypes[aT], aArgumentAnnotations[aT]));
+            retBuffer.append(getDefaultValueString(argumentTypes[aT], argumentAnnotations[aT]));
 
-            if (aT != aArgumentTypes.length - 1) {
+            if (aT != argumentTypes.length - 1) {
                 retBuffer.append(", ");
             }
         }
         retBuffer.append(')');
         return retBuffer.toString();
     }
 
     /**
@@ -468,17 +370,17 @@ public class Utils {
      * @param aArgumentAnnotations The annotations on the argument to consider.
      * @return An appropriate string to append to the signature of this argument assigning it to a
      *         default value (Or not, as applicable).
      */
     public static String getDefaultValueString(Class<?> aArgumentType, Annotation[] aArgumentAnnotations) {
         for (int i = 0; i < aArgumentAnnotations.length; i++) {
             Class<? extends Annotation> annotationType = aArgumentAnnotations[i].annotationType();
             final String annotationTypeName = annotationType.getName();
-            if (annotationTypeName.equals("org.mozilla.gecko.mozglue.generatorannotations.OptionalGeneratedParameter")) {
+            if (annotationTypeName.equals("org.mozilla.gecko.mozglue.OptionalGeneratedParameter")) {
                 return " = " + getDefaultParameterValueForType(aArgumentType);
             }
         }
         return "";
     }
 
     /**
      * Helper method to return an appropriate default parameter value for an argument of a given type.
@@ -498,23 +400,24 @@ public class Utils {
         } else {
             return "nullptr";
         }
     }
 
     /**
      * Helper method that returns the number of reference types in the arguments of m.
      *
-     * @param aArgs The method arguments to consider.
+     * @param m The method to consider.
      * @return How many of the arguments of m are nonprimitive.
      */
-    public static int enumerateReferenceArguments(Class<?>[] aArgs) {
+    public static int enumerateReferenceArguments(Method m) {
         int ret = 0;
-        for (int i = 0; i < aArgs.length; i++) {
-            String name = aArgs[i].getCanonicalName();
+        Class<?>[] args = m.getParameterTypes();
+        for (int i = 0; i < args.length; i++) {
+            String name = args[i].getCanonicalName();
             if (!sBasicCTypes.containsKey(name)) {
                 ret++;
             }
         }
         return ret;
     }
 
     /**
@@ -544,33 +447,35 @@ public class Utils {
         StringBuilder sb = new StringBuilder();
 
         String name = type.getCanonicalName();
         if (sCanonicalSignatureParts.containsKey(name)) {
             sb.append(sCanonicalSignatureParts.get(name).toLowerCase());
             sb.append(" = ").append(argName).append(";\n");
         } else {
             if (isCharSequence(type)) {
-                sb.append("l = AndroidBridge::NewJavaString(env, ").append(argName).append(");\n");
+                sb.append("l = NewJavaString(env, ").append(argName).append(");\n");
             } else {
                 sb.append("l = ").append(argName).append(";\n");
             }
         }
 
         return sb.toString();
     }
 
     /**
-     * Returns true if the type provided is an object type. Returns false otherwise
+     * Returns true if the method provided returns an object type. Returns false if it returns a
+     * primitive type.
      *
-     * @param aType The type to consider.
-     * @return true if the method provided is an object type, false otherwise.
+     * @param aMethod The method to consider.
+     * @return true if the method provided returns an object type, false otherwise.
      */
-    public static boolean isObjectType(Class<?> aType) {
-        return !sBasicCTypes.containsKey(aType.getCanonicalName());
+    public static boolean doesReturnObjectType(Method aMethod) {
+        Class<?> returnType = aMethod.getReturnType();
+        return !sBasicCTypes.containsKey(returnType.getCanonicalName());
     }
 
     /**
      * For a given Java class, get the name of the value in C++ which holds a reference to it.
      *
      * @param aClass Target Java class.
      * @return The name of the C++ jclass entity referencing the given class.
      */
@@ -585,26 +490,17 @@ public class Utils {
      * @param aClass The target Java class.
      * @return The generated code to populate the reference to the class.
      */
     public static String getStartupLineForClass(Class<?> aClass) {
         StringBuilder sb = new StringBuilder();
         sb.append("    ");
         sb.append(getClassReferenceName(aClass));
         sb.append(" = getClassGlobalRef(\"");
-
-        String name = aClass.getCanonicalName().replaceAll("\\.", "/");
-        Class<?> containerClass = aClass.getDeclaringClass();
-        if (containerClass != null) {
-            // Is an inner class. Add the $ symbol.
-            final int lastSlash = name.lastIndexOf('/');
-            name = name.substring(0, lastSlash) + '$' + name.substring(lastSlash+1);
-        }
-
-        sb.append(name);
+        sb.append(aClass.getCanonicalName().replaceAll("\\.", "/"));
         sb.append("\");\n");
         return sb.toString();
     }
 
     /**
      * Helper method to determine if this object implements CharSequence
      * @param aClass Class to check for CharSequence-esqueness
      * @return True if the given class implements CharSequence, false otherwise.
@@ -619,26 +515,16 @@ public class Utils {
                 return true;
             }
         }
         return false;
     }
 
     /**
      * Helper method to read the modifier bits of the given method to determine if it is static.
-     * @param aMember The Member to check.
+     * @param aMethod The Method to check.
      * @return true of the method is declared static, false otherwise.
      */
-    public static boolean isMemberStatic(Member aMember) {
-        int aMethodModifiers = aMember.getModifiers();
+    public static boolean isMethodStatic(Method aMethod) {
+        int aMethodModifiers = aMethod.getModifiers();
         return Modifier.isStatic(aMethodModifiers);
     }
-
-    /**
-     * Helper method to read the modifier bits of the given method to determine if it is static.
-     * @param aMember The Member to check.
-     * @return true of the method is declared static, false otherwise.
-     */
-    public static boolean isMemberFinal(Member aMember) {
-        int aMethodModifiers = aMember.getModifiers();
-        return Modifier.isFinal(aMethodModifiers);
-    }
 }
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1554,18 +1554,18 @@ ContentParent::RecvGetIconForExtension(c
 
 bool
 ContentParent::RecvGetShowPasswordSetting(bool* showPassword)
 {
     // default behavior is to show the last password character
     *showPassword = true;
 #ifdef MOZ_WIDGET_ANDROID
     NS_ASSERTION(AndroidBridge::Bridge() != nullptr, "AndroidBridge is not available");
-
-    *showPassword = GeckoAppShell::GetShowPasswordSetting();
+    if (AndroidBridge::Bridge() != nullptr)
+        *showPassword = AndroidBridge::Bridge()->GetShowPasswordSetting();
 #endif
     return true;
 }
 
 bool
 ContentParent::RecvFirstIdle()
 {
     // When the ContentChild goes idle, it sends us a FirstIdle message which we
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -2255,17 +2255,21 @@ NPError NP_CALLBACK
     case kSupportedDrawingModel_ANPGetValue: {
       LOG("get supported drawing model");
       uint32_t* bits = reinterpret_cast<uint32_t*>(result);
       *bits = kBitmap_ANPDrawingModel && kSurface_ANPDrawingModel;
       return NPERR_NO_ERROR;
     }  
 
     case kJavaContext_ANPGetValue: {
-      jobject ret = GeckoAppShell::GetContext();
+      AndroidBridge *bridge = AndroidBridge::Bridge();
+      if (!bridge)
+        return NPERR_GENERIC_ERROR;
+
+      jobject ret = bridge->GetContext();
       if (!ret)
         return NPERR_GENERIC_ERROR;
 
       int32_t* i  = reinterpret_cast<int32_t*>(result);
       *i = reinterpret_cast<int32_t>(ret);
       return NPERR_NO_ERROR;
     }
 
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -860,17 +860,17 @@ void nsNPAPIPluginInstance::NotifyFullSc
 
   if (RUNNING != mRunning || mFullScreen == aFullScreen)
     return;
 
   mFullScreen = aFullScreen;
   SendLifecycleEvent(this, mFullScreen ? kEnterFullScreen_ANPLifecycleAction : kExitFullScreen_ANPLifecycleAction);
 
   if (mFullScreen && mFullScreenOrientation != dom::eScreenOrientation_None) {
-    GeckoAppShell::LockScreenOrientation(mFullScreenOrientation);
+    AndroidBridge::Bridge()->LockScreenOrientation(mFullScreenOrientation);
   }
 }
 
 void nsNPAPIPluginInstance::NotifySize(nsIntSize size)
 {
   if (kOpenGL_ANPDrawingModel != GetANPDrawingModel() ||
       size == mCurrentSize)
     return;
@@ -917,21 +917,21 @@ void nsNPAPIPluginInstance::SetFullScree
 
   uint32_t oldOrientation = mFullScreenOrientation;
   mFullScreenOrientation = orientation;
 
   if (mFullScreen) {
     // We're already fullscreen so immediately apply the orientation change
 
     if (mFullScreenOrientation != dom::eScreenOrientation_None) {
-      GeckoAppShell::LockScreenOrientation(mFullScreenOrientation);
+      AndroidBridge::Bridge()->LockScreenOrientation(mFullScreenOrientation);
     } else if (oldOrientation != dom::eScreenOrientation_None) {
       // We applied an orientation when we entered fullscreen, but
       // we don't want it anymore
-      GeckoAppShell::UnlockScreenOrientation();
+      AndroidBridge::Bridge()->UnlockScreenOrientation();
     }
   }
 }
 
 void nsNPAPIPluginInstance::PopPostedEvent(PluginEventRunnable* r)
 {
   mPostedEvents.RemoveElement(r);
 }
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -1653,17 +1653,19 @@ bool nsPluginInstanceOwner::AddPluginVie
   return true;
 }
 
 void nsPluginInstanceOwner::RemovePluginView()
 {
   if (!mInstance || !mJavaView)
     return;
 
-  GeckoAppShell::RemovePluginView((jobject)mJavaView, mFullScreen);
+  if (AndroidBridge::Bridge())
+    AndroidBridge::Bridge()->RemovePluginView((jobject)mJavaView, mFullScreen);
+
   AndroidBridge::GetJNIEnv()->DeleteGlobalRef((jobject)mJavaView);
   mJavaView = nullptr;
 
   if (mFullScreen)
     sFullScreenInstance = nullptr;
 }
 
 void nsPluginInstanceOwner::GetVideos(nsTArray<nsNPAPIPluginInstance::VideoInfo*>& aVideos)
--- a/dom/system/android/AndroidLocationProvider.cpp
+++ b/dom/system/android/AndroidLocationProvider.cpp
@@ -21,34 +21,40 @@ AndroidLocationProvider::AndroidLocation
 AndroidLocationProvider::~AndroidLocationProvider()
 {
     NS_IF_RELEASE(gLocationCallback);
 }
 
 NS_IMETHODIMP
 AndroidLocationProvider::Startup()
 {
-    GeckoAppShell::EnableLocation(true);
+    if (!AndroidBridge::Bridge())
+        return NS_ERROR_NOT_IMPLEMENTED;
+    AndroidBridge::Bridge()->EnableLocation(true);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 AndroidLocationProvider::Watch(nsIGeolocationUpdate* aCallback)
 {
     NS_IF_RELEASE(gLocationCallback);
     gLocationCallback = aCallback;
     NS_IF_ADDREF(gLocationCallback);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 AndroidLocationProvider::Shutdown()
 {
-    GeckoAppShell::EnableLocation(false);
+    if (!AndroidBridge::Bridge())
+        return NS_ERROR_NOT_IMPLEMENTED;
+    AndroidBridge::Bridge()->EnableLocation(false);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 AndroidLocationProvider::SetHighAccuracy(bool enable)
 {
-    GeckoAppShell::EnableLocationHighAccuracy(enable);
+    if (!AndroidBridge::Bridge())
+        return NS_ERROR_NOT_IMPLEMENTED;
+    AndroidBridge::Bridge()->EnableLocationHighAccuracy(enable);
     return NS_OK;
 }
--- a/dom/system/android/nsHapticFeedback.cpp
+++ b/dom/system/android/nsHapticFeedback.cpp
@@ -9,11 +9,15 @@
 
 using namespace mozilla;
 
 NS_IMPL_ISUPPORTS1(nsHapticFeedback, nsIHapticFeedback)
 
 NS_IMETHODIMP
 nsHapticFeedback::PerformSimpleAction(int32_t aType)
 {
-    GeckoAppShell::PerformHapticFeedback(aType == LongPress);
-    return NS_OK;
+    AndroidBridge* bridge = AndroidBridge::Bridge();
+    if (bridge) {
+        bridge->PerformHapticFeedback(aType == LongPress);
+        return NS_OK;
+    }
+    return NS_ERROR_FAILURE;
 }
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -2413,17 +2413,17 @@ public:
 
 #ifdef MOZ_WIDGET_GONK
     virtual EGLImage CreateEGLImageForNativeBuffer(void* buffer) = 0;
     virtual void DestroyEGLImage(EGLImage image) = 0;
     virtual EGLImage GetNullEGLImage() = 0;
 #endif
 
     virtual already_AddRefed<TextureImage>
-    CreateDirectTextureImage(::android::GraphicBuffer* aBuffer, GLenum aWrapMode)
+    CreateDirectTextureImage(android::GraphicBuffer* aBuffer, GLenum aWrapMode)
     { return nullptr; }
 
     // Before reads from offscreen texture
     void GuaranteeResolve();
 
 protected:
     GLuint mTexBlit_Buffer;
     GLuint mTexBlit_VertShader;
--- a/gfx/thebes/nsSurfaceTexture.cpp
+++ b/gfx/thebes/nsSurfaceTexture.cpp
@@ -205,17 +205,17 @@ nsSurfaceTexture::~nsSurfaceTexture()
     mNativeWindow = nullptr;
   }
 
   JNIEnv* env = GetJNIForThread();
   if (!env)
     return;
 
   if (mSurfaceTexture && env) {
-    GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
+    AndroidBridge::Bridge()->UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
 
     env->DeleteGlobalRef(mSurfaceTexture);
     mSurfaceTexture = nullptr;
   }
 }
 
 void*
 nsSurfaceTexture::GetNativeWindow()
@@ -234,19 +234,19 @@ nsSurfaceTexture::GetTransformMatrix(gfx
 {
   return sJNIFunctions.GetTransformMatrix(mSurfaceTexture, aMatrix);
 }
 
 void
 nsSurfaceTexture::SetFrameAvailableCallback(nsIRunnable* aRunnable)
 {
   if (aRunnable)
-    GeckoAppShell::RegisterSurfaceTextureFrameListener(mSurfaceTexture, mID);
+    AndroidBridge::Bridge()->RegisterSurfaceTextureFrameListener(mSurfaceTexture, mID);
   else
-    GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
+    AndroidBridge::Bridge()->UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
 
   mFrameAvailableCallback = aRunnable;
 }
 
 void
 nsSurfaceTexture::NotifyFrameAvailable()
 {
   if (mFrameAvailableCallback) {
--- a/hal/android/AndroidHal.cpp
+++ b/hal/android/AndroidHal.cpp
@@ -8,17 +8,16 @@
 #include "WindowIdentifier.h"
 #include "AndroidBridge.h"
 #include "mozilla/dom/network/Constants.h"
 #include "mozilla/dom/ScreenOrientation.h"
 #include "nsIScreenManager.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::hal;
-using namespace mozilla::widget::android;
 
 namespace mozilla {
 namespace hal_impl {
 
 void
 Vibrate(const nsTArray<uint32_t> &pattern, const WindowIdentifier &)
 {
   // Ignore the WindowIdentifier parameter; it's here only because hal::Vibrate,
@@ -49,65 +48,107 @@ Vibrate(const nsTArray<uint32_t> &patter
   b->Vibrate(pattern);
 }
 
 void
 CancelVibrate(const WindowIdentifier &)
 {
   // Ignore WindowIdentifier parameter.
 
-  GeckoAppShell::CancelVibrate();
+  AndroidBridge* b = AndroidBridge::Bridge();
+  if (b)
+    b->CancelVibrate();
 }
 
 void
 EnableBatteryNotifications()
 {
-  GeckoAppShell::EnableBatteryNotifications();
+  AndroidBridge* bridge = AndroidBridge::Bridge();
+  if (!bridge) {
+    return;
+  }
+
+  bridge->EnableBatteryNotifications();
 }
 
 void
 DisableBatteryNotifications()
 {
-  GeckoAppShell::DisableBatteryNotifications();
+  AndroidBridge* bridge = AndroidBridge::Bridge();
+  if (!bridge) {
+    return;
+  }
+
+  bridge->DisableBatteryNotifications();
 }
 
 void
 GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo)
 {
-  AndroidBridge::Bridge()->GetCurrentBatteryInformation(aBatteryInfo);
+  AndroidBridge* bridge = AndroidBridge::Bridge();
+  if (!bridge) {
+    return;
+  }
+
+  bridge->GetCurrentBatteryInformation(aBatteryInfo);
 }
 
 void
 EnableNetworkNotifications()
 {
-  GeckoAppShell::EnableNetworkNotifications();
+  AndroidBridge* bridge = AndroidBridge::Bridge();
+  if (!bridge) {
+    return;
+  }
+
+  bridge->EnableNetworkNotifications();
 }
 
 void
 DisableNetworkNotifications()
 {
-  GeckoAppShell::DisableNetworkNotifications();
+  AndroidBridge* bridge = AndroidBridge::Bridge();
+  if (!bridge) {
+    return;
+  }
+
+  bridge->DisableNetworkNotifications();
 }
 
 void
 GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo)
 {
-  AndroidBridge::Bridge()->GetCurrentNetworkInformation(aNetworkInfo);
+  AndroidBridge* bridge = AndroidBridge::Bridge();
+  if (!bridge) {
+    return;
+  }
+
+  bridge->GetCurrentNetworkInformation(aNetworkInfo);
 }
 
 void
 EnableScreenConfigurationNotifications()
 {
-  GeckoAppShell::EnableScreenOrientationNotifications();
+  AndroidBridge* bridge = AndroidBridge::Bridge();
+  if (!bridge) {
+    return;
+  }
+
+  bridge->EnableScreenOrientationNotifications();
 }
 
 void
 DisableScreenConfigurationNotifications()
 {
-  GeckoAppShell::DisableScreenOrientationNotifications();
+  AndroidBridge* bridge = AndroidBridge::Bridge();
+  if (!bridge) {
+    return;
+  }
+
+  bridge->DisableScreenOrientationNotifications();
 }
 
 void
 GetCurrentScreenConfiguration(ScreenConfiguration* aScreenConfiguration)
 {
   AndroidBridge* bridge = AndroidBridge::Bridge();
   if (!bridge) {
     return;
@@ -134,32 +175,42 @@ GetCurrentScreenConfiguration(ScreenConf
 
   *aScreenConfiguration =
     hal::ScreenConfiguration(rect, orientation, colorDepth, pixelDepth);
 }
 
 bool
 LockScreenOrientation(const ScreenOrientation& aOrientation)
 {
+  AndroidBridge* bridge = AndroidBridge::Bridge();
+  if (!bridge) {
+    return false;
+  }
+
   switch (aOrientation) {
     // The Android backend only supports these orientations.
     case eScreenOrientation_PortraitPrimary:
     case eScreenOrientation_PortraitSecondary:
     case eScreenOrientation_PortraitPrimary | eScreenOrientation_PortraitSecondary:
     case eScreenOrientation_LandscapePrimary:
     case eScreenOrientation_LandscapeSecondary:
     case eScreenOrientation_LandscapePrimary | eScreenOrientation_LandscapeSecondary:
-      GeckoAppShell::LockScreenOrientation(aOrientation);
+      bridge->LockScreenOrientation(aOrientation);
       return true;
     default:
       return false;
   }
 }
 
 void
 UnlockScreenOrientation()
 {
-  GeckoAppShell::UnlockScreenOrientation();
+  AndroidBridge* bridge = AndroidBridge::Bridge();
+  if (!bridge) {
+    return;
+  }
+
+  bridge->UnlockScreenOrientation();
 }
 
 } // hal_impl
 } // mozilla
 
--- a/hal/android/AndroidSensor.cpp
+++ b/hal/android/AndroidSensor.cpp
@@ -8,18 +8,18 @@
 
 using namespace mozilla::hal;
 
 namespace mozilla {
 namespace hal_impl {
 
 void
 EnableSensorNotifications(SensorType aSensor) {
-  GeckoAppShell::EnableSensor(aSensor);
+  AndroidBridge::Bridge()->EnableSensor(aSensor);
 }
 
 void
 DisableSensorNotifications(SensorType aSensor) {
-  GeckoAppShell::DisableSensor(aSensor);
+  AndroidBridge::Bridge()->DisableSensor(aSensor);
 }
 
 } // hal_impl
 } // mozilla
--- a/ipc/glue/MessagePump.cpp
+++ b/ipc/glue/MessagePump.cpp
@@ -86,17 +86,17 @@ MessagePump::Run(MessagePump::Delegate* 
     // here.  To ensure that MessageLoop tasks and XPCOM events have
     // equal priority, we sensitively rely on processing exactly one
     // Task per DoWorkRunnable XPCOM event.
 
 #ifdef MOZ_WIDGET_ANDROID
     // This processes messages in the Android Looper. Note that we only
     // get here if the normal Gecko event loop has been awoken above.
     // Bug 750713
-    did_work |= GeckoAppShell::PumpMessageLoop();
+    did_work |= AndroidBridge::Bridge()->PumpMessageLoop();
 #endif
 
     did_work |= aDelegate->DoDelayedWork(&delayed_work_time_);
 
     if (did_work && delayed_work_time_.is_null())
       mDelayedWorkTimer->Cancel();
 
     if (!keep_running_)
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -6,18 +6,18 @@
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.gfx.BitmapUtils;
 import org.mozilla.gecko.gfx.GeckoLayerClient;
 import org.mozilla.gecko.gfx.GfxInfoThread;
 import org.mozilla.gecko.gfx.LayerView;
 import org.mozilla.gecko.gfx.PanZoomController;
 import org.mozilla.gecko.mozglue.GeckoLoader;
-import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
-import org.mozilla.gecko.mozglue.generatorannotations.OptionalGeneratedParameter;
+import org.mozilla.gecko.mozglue.GeneratableAndroidBridgeTarget;
+import org.mozilla.gecko.mozglue.OptionalGeneratedParameter;
 import org.mozilla.gecko.util.EventDispatcher;
 import org.mozilla.gecko.util.GeckoEventListener;
 import org.mozilla.gecko.util.HardwareUtils;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.PendingIntent;
@@ -368,33 +368,33 @@ public class GeckoAppShell
     }
 
     // Tell the Gecko event loop that an event is available.
     public static native void notifyGeckoOfEvent(GeckoEvent event);
 
     /*
      *  The Gecko-side API: API methods that Gecko calls
      */
-    @WrapElementForJNI(generateStatic = true)
+    @GeneratableAndroidBridgeTarget(generateStatic = true)
     public static void notifyIME(int type) {
         if (mEditableListener != null) {
             mEditableListener.notifyIME(type);
         }
     }
 
-    @WrapElementForJNI(generateStatic = true)
+    @GeneratableAndroidBridgeTarget(generateStatic = true)
     public static void notifyIMEContext(int state, String typeHint,
                                         String modeHint, String actionHint) {
         if (mEditableListener != null) {
             mEditableListener.notifyIMEContext(state, typeHint,
                                                modeHint, actionHint);
         }
     }
 
-    @WrapElementForJNI(generateStatic = true)
+    @GeneratableAndroidBridgeTarget(generateStatic = true)
     public static void notifyIMEChange(String text, int start, int end, int newEnd) {
         if (newEnd < 0) { // Selection change
             mEditableListener.onSelectionChange(start, end);
         } else { // Text change
             mEditableListener.onTextChange(text, start, end, newEnd);
         }
     }
 
@@ -428,17 +428,17 @@ public class GeckoAppShell
                 }
                 long waited = SystemClock.uptimeMillis() - time;
                 Log.d(LOGTAG, "Gecko event sync taking too long: " + waited + "ms");
             }
         }
     }
 
     // Signal the Java thread that it's time to wake up
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void acknowledgeEvent() {
         synchronized (sEventAckLock) {
             sWaitingForEventAck = false;
             sEventAckLock.notifyAll();
         }
     }
 
     private static float getLocationAccuracy(Location location) {
@@ -467,17 +467,17 @@ public class GeckoAppShell
                  getLocationAccuracy(location) < getLocationAccuracy(lastKnownLocation))) {
                 lastKnownLocation = location;
             }
         }
 
         return lastKnownLocation;
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void enableLocation(final boolean enable) {
         ThreadUtils.postToUiThread(new Runnable() {
                 @Override
                 public void run() {
                     LocationManager lm = getLocationManager(getContext());
                     if (lm == null) {
                         return;
                     }
@@ -523,22 +523,22 @@ public class GeckoAppShell
             // which allows enabling/disabling location update notifications from the cell radio.
             // CONTROL_LOCATION_UPDATES is not for use by normal applications, but we might be
             // hitting this problem if the Tegras are confused about missing cell radios.
             Log.e(LOGTAG, "LOCATION_SERVICE not found?!", e);
             return null;
         }
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void enableLocationHighAccuracy(final boolean enable) {
         mLocationHighAccuracy = enable;
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void enableSensor(int aSensortype) {
         GeckoInterface gi = getGeckoInterface();
         if (gi == null)
             return;
         SensorManager sm = (SensorManager)
             getContext().getSystemService(Context.SENSOR_SERVICE);
 
         switch(aSensortype) {
@@ -583,17 +583,17 @@ public class GeckoAppShell
             if (gGyroscopeSensor != null)
                 sm.registerListener(gi.getSensorEventListener(), gGyroscopeSensor, sDefaultSensorHint);
             break;
         default:
             Log.w(LOGTAG, "Error! Can't enable unknown SENSOR type " + aSensortype);
         }
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void disableSensor(int aSensortype) {
         GeckoInterface gi = getGeckoInterface();
         if (gi == null)
             return;
 
         SensorManager sm = (SensorManager)
             getContext().getSystemService(Context.SENSOR_SERVICE);
 
@@ -627,44 +627,44 @@ public class GeckoAppShell
             if (gGyroscopeSensor != null)
                 sm.unregisterListener(gi.getSensorEventListener(), gGyroscopeSensor);
             break;
         default:
             Log.w(LOGTAG, "Error! Can't disable unknown SENSOR type " + aSensortype);
         }
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void moveTaskToBack() {
         if (getGeckoInterface() != null)
             getGeckoInterface().getActivity().moveTaskToBack(true);
     }
 
     public static void returnIMEQueryResult(String result, int selectionStart, int selectionLength) {
         // This method may be called from JNI to report Gecko's current selection indexes, but
         // Native Fennec doesn't care because the Java code already knows the selection indexes.
     }
 
-    @WrapElementForJNI(stubName = "NotifyXreExit")
+    @GeneratableAndroidBridgeTarget(stubName = "NotifyXreExit")
     static void onXreExit() {
         // The launch state can only be Launched or GeckoRunning at this point
         GeckoThread.setLaunchState(GeckoThread.LaunchState.GeckoExiting);
         if (getGeckoInterface() != null) {
             if (gRestartScheduled) {
                 getGeckoInterface().doRestart();
             } else {
                 getGeckoInterface().getActivity().finish();
             }
         }
 
         Log.d(LOGTAG, "Killing via System.exit()");
         System.exit(0);
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     static void scheduleRestart() {
         gRestartScheduled = true;
     }
 
     public static File preInstallWebApp(String aTitle, String aURI, String aOrigin) {
         int index = WebAppAllocator.getInstance(getContext()).findAndAllocateIndex(aOrigin, aTitle, (String) null);
         GeckoProfile profile = GeckoProfile.get(getContext(), "webapp" + index);
         return profile.getDir();
@@ -697,17 +697,17 @@ public class GeckoAppShell
         intent.setData(Uri.parse(aURI));
         intent.setClassName(AppConstants.ANDROID_PACKAGE_NAME,
                             AppConstants.ANDROID_PACKAGE_NAME + ".WebApps$WebApp" + aIndex);
         return intent;
     }
 
     // "Installs" an application by creating a shortcut
     // This is the entry point from AndroidBridge.h
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     static void createShortcut(String aTitle, String aURI, String aIconData, String aType) {
         if ("webapp".equals(aType)) {
             Log.w(LOGTAG, "createShortcut with no unique URI should not be used for aType = webapp!");
         }
 
         createShortcut(aTitle, aURI, aURI, aIconData, aType);
     }
 
@@ -892,25 +892,25 @@ public class GeckoAppShell
                                    halfSize - sHeight,
                                    halfSize + sWidth,
                                    halfSize + sHeight),
                           null);
 
         return bitmap;
     }
 
-    @WrapElementForJNI(stubName = "GetHandlersForMimeTypeWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "GetHandlersForMimeTypeWrapper")
     static String[] getHandlersForMimeType(String aMimeType, String aAction) {
         Intent intent = getIntentForActionString(aAction);
         if (aMimeType != null && aMimeType.length() > 0)
             intent.setType(aMimeType);
         return getHandlersForIntent(intent);
     }
 
-    @WrapElementForJNI(stubName = "GetHandlersForURLWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "GetHandlersForURLWrapper")
     static String[] getHandlersForURL(String aURL, String aAction) {
         // aURL may contain the whole URL or just the protocol
         Uri uri = aURL.indexOf(':') >= 0 ? Uri.parse(aURL) : new Uri.Builder().scheme(aURL).build();
 
         Intent intent = getOpenURIIntent(getContext(), uri.toString(), "",
             TextUtils.isEmpty(aAction) ? Intent.ACTION_VIEW : aAction, "");
 
         return getHandlersForIntent(intent);
@@ -943,22 +943,22 @@ public class GeckoAppShell
     static Intent getIntentForActionString(String aAction) {
         // Default to the view action if no other action as been specified.
         if (TextUtils.isEmpty(aAction)) {
             return new Intent(Intent.ACTION_VIEW);
         }
         return new Intent(aAction);
     }
 
-    @WrapElementForJNI(stubName = "GetExtensionFromMimeTypeWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "GetExtensionFromMimeTypeWrapper")
     static String getExtensionFromMimeType(String aMimeType) {
         return MimeTypeMap.getSingleton().getExtensionFromMimeType(aMimeType);
     }
 
-    @WrapElementForJNI(stubName = "GetMimeTypeFromExtensionsWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "GetMimeTypeFromExtensionsWrapper")
     static String getMimeTypeFromExtensions(String aFileExt) {
         StringTokenizer st = new StringTokenizer(aFileExt, ".,; ");
         String type = null;
         String subType = null;
         while (st.hasMoreElements()) {
             String ext = st.nextToken();
             String mt = getMimeTypeFromExtension(ext);
             if (mt == null)
@@ -1081,17 +1081,17 @@ public class GeckoAppShell
      *
      * @param targetURI the string spec of the URI to open.
      * @param mimeType an optional MIME type string.
      * @param action an Android action specifier, such as
      *               <code>Intent.ACTION_SEND</code>.
      * @param title the title to use in <code>ACTION_SEND</code> intents.
      * @return true if the activity started successfully; false otherwise.
      */
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static boolean openUriExternal(String targetURI,
                                           String mimeType,
               @OptionalGeneratedParameter String packageName,
               @OptionalGeneratedParameter String className,
               @OptionalGeneratedParameter String action,
               @OptionalGeneratedParameter String title) {
         final Context context = getContext();
         final Intent intent = getOpenURIIntent(context, targetURI,
@@ -1267,17 +1267,17 @@ public class GeckoAppShell
     public static void setNotificationClient(NotificationClient client) {
         if (sNotificationClient == null) {
             sNotificationClient = client;
         } else {
             Log.d(LOGTAG, "Notification client already set");
         }
     }
 
-    @WrapElementForJNI(stubName = "ShowAlertNotificationWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "ShowAlertNotificationWrapper")
     public static void showAlertNotification(String aImageUrl, String aAlertTitle, String aAlertText,
                                              String aAlertCookie, String aAlertName) {
         // The intent to launch when the user clicks the expanded notification
         String app = getContext().getClass().getName();
         Intent notificationIntent = new Intent(GeckoApp.ACTION_ALERT_CALLBACK);
         notificationIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, app);
         notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
@@ -1294,23 +1294,23 @@ public class GeckoAppShell
                 getContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
 
         mAlertCookies.put(aAlertName, aAlertCookie);
         callObserver(aAlertName, "alertshow", aAlertCookie);
 
         sNotificationClient.add(notificationID, aImageUrl, aAlertTitle, aAlertText, contentIntent);
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void alertsProgressListener_OnProgress(String aAlertName, long aProgress, long aProgressMax, String aAlertText) {
         int notificationID = aAlertName.hashCode();
         sNotificationClient.update(notificationID, aProgress, aProgressMax, aAlertText);
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void closeNotification(String aAlertName) {
         String alertCookie = mAlertCookies.get(aAlertName);
         if (alertCookie != null) {
             callObserver(aAlertName, "alertfinished", alertCookie);
             mAlertCookies.remove(aAlertName);
         }
 
         removeObserver(aAlertName);
@@ -1328,26 +1328,26 @@ public class GeckoAppShell
             if (sNotificationClient.isOngoing(notificationID)) {
                 // When clicked, keep the notification if it displays progress
                 return;
             }
         }
         closeNotification(aAlertName);
     }
 
-    @WrapElementForJNI(stubName = "GetDpiWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "GetDpiWrapper")
     public static int getDpi() {
         if (sDensityDpi == 0) {
             sDensityDpi = getContext().getResources().getDisplayMetrics().densityDpi;
         }
 
         return sDensityDpi;
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget()
     public static float getDensity() {
         return getContext().getResources().getDisplayMetrics().density;
     }
 
     private static boolean isHighMemoryDevice() {
         BufferedReader br = null;
         FileReader fr = null;
         try {
@@ -1372,17 +1372,17 @@ public class GeckoAppShell
         }
         return false;
     }
 
     /**
      * Returns the colour depth of the default screen. This will either be
      * 24 or 16.
      */
-    @WrapElementForJNI(stubName = "GetScreenDepthWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "GetScreenDepthWrapper")
     public static synchronized int getScreenDepth() {
         if (sScreenDepth == 0) {
             sScreenDepth = 16;
             PixelFormat info = new PixelFormat();
             PixelFormat.getPixelFormatInfo(getGeckoInterface().getActivity().getWindowManager().getDefaultDisplay().getPixelFormat(), info);
             if (info.bitsPerPixel >= 24 && isHighMemoryDevice()) {
                 sScreenDepth = 24;
             }
@@ -1395,133 +1395,133 @@ public class GeckoAppShell
         if (sScreenDepth != 0) {
             Log.e(LOGTAG, "Tried to override screen depth after it's already been set");
             return;
         }
 
         sScreenDepth = aScreenDepth;
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void setFullScreen(boolean fullscreen) {
         if (getGeckoInterface() != null)
             getGeckoInterface().setFullScreen(fullscreen);
     }
 
-    @WrapElementForJNI(stubName = "ShowFilePickerForExtensionsWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "ShowFilePickerForExtensionsWrapper")
     public static String showFilePickerForExtensions(String aExtensions) {
         if (getGeckoInterface() != null)
             return sActivityHelper.showFilePicker(getGeckoInterface().getActivity(), getMimeTypeFromExtensions(aExtensions));
         return "";
     }
 
-    @WrapElementForJNI(stubName = "ShowFilePickerForMimeTypeWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "ShowFilePickerForMimeTypeWrapper")
     public static String showFilePickerForMimeType(String aMimeType) {
         if (getGeckoInterface() != null)
             return sActivityHelper.showFilePicker(getGeckoInterface().getActivity(), aMimeType);
         return "";
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void performHapticFeedback(boolean aIsLongPress) {
         // Don't perform haptic feedback if a vibration is currently playing,
         // because the haptic feedback will nuke the vibration.
         if (!sVibrationMaybePlaying || System.nanoTime() >= sVibrationEndTime) {
             LayerView layerView = getLayerView();
             layerView.performHapticFeedback(aIsLongPress ?
                                             HapticFeedbackConstants.LONG_PRESS :
                                             HapticFeedbackConstants.VIRTUAL_KEY);
         }
     }
 
     private static Vibrator vibrator() {
         LayerView layerView = getLayerView();
         return (Vibrator) layerView.getContext().getSystemService(Context.VIBRATOR_SERVICE);
     }
 
-    @WrapElementForJNI(stubName = "Vibrate1")
+    @GeneratableAndroidBridgeTarget(stubName = "Vibrate1")
     public static void vibrate(long milliseconds) {
         sVibrationEndTime = System.nanoTime() + milliseconds * 1000000;
         sVibrationMaybePlaying = true;
         vibrator().vibrate(milliseconds);
     }
 
-    @WrapElementForJNI(stubName = "VibrateA")
+    @GeneratableAndroidBridgeTarget(stubName = "VibrateA")
     public static void vibrate(long[] pattern, int repeat) {
         // If pattern.length is even, the last element in the pattern is a
         // meaningless delay, so don't include it in vibrationDuration.
         long vibrationDuration = 0;
         int iterLen = pattern.length - (pattern.length % 2 == 0 ? 1 : 0);
         for (int i = 0; i < iterLen; i++) {
           vibrationDuration += pattern[i];
         }
 
         sVibrationEndTime = System.nanoTime() + vibrationDuration * 1000000;
         sVibrationMaybePlaying = true;
         vibrator().vibrate(pattern, repeat);
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void cancelVibrate() {
         sVibrationMaybePlaying = false;
         sVibrationEndTime = 0;
         vibrator().cancel();
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void showInputMethodPicker() {
         InputMethodManager imm = (InputMethodManager)
             getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
         imm.showInputMethodPicker();
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void setKeepScreenOn(final boolean on) {
         ThreadUtils.postToUiThread(new Runnable() {
             @Override
             public void run() {
                 // TODO
             }
         });
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void notifyDefaultPrevented(final boolean defaultPrevented) {
         ThreadUtils.postToUiThread(new Runnable() {
             @Override
             public void run() {
                 LayerView view = getLayerView();
                 PanZoomController controller = (view == null ? null : view.getPanZoomController());
                 if (controller != null) {
                     controller.notifyDefaultActionPrevented(defaultPrevented);
                 }
             }
         });
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static boolean isNetworkLinkUp() {
         ConnectivityManager cm = (ConnectivityManager)
            getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
         NetworkInfo info = cm.getActiveNetworkInfo();
         if (info == null || !info.isConnected())
             return false;
         return true;
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static boolean isNetworkLinkKnown() {
         ConnectivityManager cm = (ConnectivityManager)
             getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
         if (cm.getActiveNetworkInfo() == null)
             return false;
         return true;
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void setSelectedLocale(String localeCode) {
         /* Bug 713464: This method is still called from Gecko side.
            Earlier we had an option to run Firefox in a language other than system's language.
            However, this is not supported as of now.
            Gecko resets the locale to en-US by calling this function with an empty string.
            This affects GeckoPreferences activity in multi-locale builds.
 
         //We're not using this, not need to save it (see bug 635342)
@@ -1544,17 +1544,17 @@ public class GeckoAppShell
         Resources res = getContext().getBaseContext().getResources();
         Configuration config = res.getConfiguration();
         config.locale = locale;
         res.updateConfiguration(config, res.getDisplayMetrics());
         */
     }
 
 
-    @WrapElementForJNI(stubName = "GetSystemColoursWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "GetSystemColoursWrapper")
     public static int[] getSystemColors() {
         // attrsAppearance[] must correspond to AndroidSystemColors structure in android/AndroidBridge.h
         final int[] attrsAppearance = {
             android.R.attr.textColor,
             android.R.attr.textColorPrimary,
             android.R.attr.textColorPrimaryInverse,
             android.R.attr.textColorSecondary,
             android.R.attr.textColorSecondaryInverse,
@@ -1581,17 +1581,17 @@ public class GeckoAppShell
                 result[idx] = color;
             }
             appearance.recycle();
         }
 
         return result;
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void killAnyZombies() {
         GeckoProcessesVisitor visitor = new GeckoProcessesVisitor() {
             @Override
             public boolean callback(int pid) {
                 if (pid != android.os.Process.myPid())
                     android.os.Process.killProcess(pid);
                 return true;
             }
@@ -1737,31 +1737,31 @@ public class GeckoAppShell
                 String file = split[nameColumn];
                 if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(file) && file.startsWith(filter))
                     Log.i(LOGTAG, "[OPENFILE] " + name + "(" + split[pidColumn] + ") : " + file);
             }
             in.close();
         } catch (Exception e) { }
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void scanMedia(String aFile, String aMimeType) {
         // If the platform didn't give us a mimetype, try to guess one from the filename
         if (TextUtils.isEmpty(aMimeType)) {
             int extPosition = aFile.lastIndexOf(".");
             if (extPosition > 0 && extPosition < aFile.length() - 1) {
                 aMimeType = getMimeTypeFromExtension(aFile.substring(extPosition+1));
             }
         }
 
         Context context = getContext();
         GeckoMediaScannerClient.startScan(context, aFile, aMimeType);
     }
 
-    @WrapElementForJNI(stubName = "GetIconForExtensionWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "GetIconForExtensionWrapper")
     public static byte[] getIconForExtension(String aExt, int iconSize) {
         try {
             if (iconSize <= 0)
                 iconSize = 16;
 
             if (aExt != null && aExt.length() > 1 && aExt.charAt(0) == '.')
                 aExt = aExt.substring(1);
 
@@ -1809,39 +1809,39 @@ public class GeckoAppShell
         if (resolveInfo == null)
             return null;
 
         ActivityInfo activityInfo = resolveInfo.activityInfo;
 
         return activityInfo.loadIcon(pm);
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static boolean getShowPasswordSetting() {
         try {
             int showPassword =
                 Settings.System.getInt(getContext().getContentResolver(),
                                        Settings.System.TEXT_SHOW_PASSWORD, 1);
             return (showPassword > 0);
         }
         catch (Exception e) {
             return true;
         }
     }
 
-    @WrapElementForJNI(stubName = "AddPluginViewWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "AddPluginViewWrapper")
     public static void addPluginView(View view,
                                      float x, float y,
                                      float w, float h,
                                      boolean isFullScreen) {
         if (getGeckoInterface() != null)
              getGeckoInterface().addPluginView(view, new RectF(x, y, x + w, y + h), isFullScreen);
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void removePluginView(View view, boolean isFullScreen) {
         if (getGeckoInterface() != null)
             getGeckoInterface().removePluginView(view, isFullScreen);
     }
 
     /**
      * A plugin that wish to be loaded in the WebView must provide this permission
      * in their AndroidManifest.xml.
@@ -2055,17 +2055,17 @@ public class GeckoAppShell
         } catch (android.content.pm.PackageManager.NameNotFoundException nnfe) {
             Log.w(LOGTAG, "Couldn't find package.", nnfe);
             return null;
         }
     }
 
     private static ContextGetter sContextGetter;
 
-    @WrapElementForJNI(allowMultithread = true)
+    @GeneratableAndroidBridgeTarget(allowMultithread = true)
     public static Context getContext() {
         return sContextGetter.getContext();
     }
 
     public static void setContextGetter(ContextGetter cg) {
         sContextGetter = cg;
     }
 
@@ -2113,17 +2113,17 @@ public class GeckoAppShell
     public static android.hardware.Camera sCamera = null;
 
     static native void cameraCallbackBridge(byte[] data);
 
     static int kPreferedFps = 25;
     static byte[] sCameraBuffer = null;
 
 
-    @WrapElementForJNI(stubName = "InitCameraWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "InitCameraWrapper")
     static int[] initCamera(String aContentType, int aCamera, int aWidth, int aHeight) {
         ThreadUtils.postToUiThread(new Runnable() {
                 @Override
                 public void run() {
                     try {
                         if (getGeckoInterface() != null)
                             getGeckoInterface().enableCameraView();
                     } catch (Exception e) {}
@@ -2214,17 +2214,17 @@ public class GeckoAppShell
             result[3] = params.getPreviewFrameRate();
         } catch(RuntimeException e) {
             Log.w(LOGTAG, "initCamera RuntimeException.", e);
             result[0] = result[1] = result[2] = result[3] = 0;
         }
         return result;
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     static synchronized void closeCamera() {
         ThreadUtils.postToUiThread(new Runnable() {
                 @Override
                 public void run() {
                     try {
                         if (getGeckoInterface() != null)
                             getGeckoInterface().disableCameraView();
                     } catch (Exception e) {}
@@ -2266,148 +2266,148 @@ public class GeckoAppShell
      */
     public static void unregisterEventListener(String event, GeckoEventListener listener) {
         sEventDispatcher.unregisterEventListener(event, listener);
     }
 
     /*
      * Battery API related methods.
      */
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void enableBatteryNotifications() {
         GeckoBatteryManager.enableNotifications();
     }
 
-    @WrapElementForJNI(stubName = "HandleGeckoMessageWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "HandleGeckoMessageWrapper")
     public static String handleGeckoMessage(String message) {
         return sEventDispatcher.dispatchEvent(message);
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void disableBatteryNotifications() {
         GeckoBatteryManager.disableNotifications();
     }
 
-    @WrapElementForJNI(stubName = "GetCurrentBatteryInformationWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "GetCurrentBatteryInformationWrapper")
     public static double[] getCurrentBatteryInformation() {
         return GeckoBatteryManager.getCurrentInformation();
     }
 
-    @WrapElementForJNI(stubName = "CheckURIVisited")
+    @GeneratableAndroidBridgeTarget(stubName = "CheckURIVisited")
     static void checkUriVisited(String uri) {
         GlobalHistory.getInstance().checkUriVisited(uri);
     }
 
-    @WrapElementForJNI(stubName = "MarkURIVisited")
+    @GeneratableAndroidBridgeTarget(stubName = "MarkURIVisited")
     static void markUriVisited(final String uri) {
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             public void run() {
                 GlobalHistory.getInstance().add(uri);
             }
         });
     }
 
-    @WrapElementForJNI(stubName = "SetURITitle")
+    @GeneratableAndroidBridgeTarget(stubName = "SetURITitle")
     static void setUriTitle(final String uri, final String title) {
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             public void run() {
                 GlobalHistory.getInstance().update(uri, title);
             }
         });
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     static void hideProgressDialog() {
         // unused stub
     }
 
     /*
      * WebSMS related methods.
      */
-    @WrapElementForJNI(stubName = "SendMessageWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "SendMessageWrapper")
     public static void sendMessage(String aNumber, String aMessage, int aRequestId) {
         if (SmsManager.getInstance() == null) {
             return;
         }
 
         SmsManager.getInstance().send(aNumber, aMessage, aRequestId);
     }
 
-    @WrapElementForJNI(stubName = "GetMessageWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "GetMessageWrapper")
     public static void getMessage(int aMessageId, int aRequestId) {
         if (SmsManager.getInstance() == null) {
             return;
         }
 
         SmsManager.getInstance().getMessage(aMessageId, aRequestId);
     }
 
-    @WrapElementForJNI(stubName = "DeleteMessageWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "DeleteMessageWrapper")
     public static void deleteMessage(int aMessageId, int aRequestId) {
         if (SmsManager.getInstance() == null) {
             return;
         }
 
         SmsManager.getInstance().deleteMessage(aMessageId, aRequestId);
     }
 
-    @WrapElementForJNI(stubName = "CreateMessageListWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "CreateMessageListWrapper")
     public static void createMessageList(long aStartDate, long aEndDate, String[] aNumbers, int aNumbersCount, int aDeliveryState, boolean aReverse, int aRequestId) {
         if (SmsManager.getInstance() == null) {
             return;
         }
 
         SmsManager.getInstance().createMessageList(aStartDate, aEndDate, aNumbers, aNumbersCount, aDeliveryState, aReverse, aRequestId);
     }
 
-    @WrapElementForJNI(stubName = "GetNextMessageInListWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "GetNextMessageInListWrapper")
     public static void getNextMessageInList(int aListId, int aRequestId) {
         if (SmsManager.getInstance() == null) {
             return;
         }
 
         SmsManager.getInstance().getNextMessageInList(aListId, aRequestId);
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void clearMessageList(int aListId) {
         if (SmsManager.getInstance() == null) {
             return;
         }
 
         SmsManager.getInstance().clearMessageList(aListId);
     }
 
     /* Called by JNI from AndroidBridge, and by reflection from tests/BaseTest.java.in */
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static boolean isTablet() {
         return HardwareUtils.isTablet();
     }
 
     public static void viewSizeChanged() {
         LayerView v = getLayerView();
         if (v != null && v.isIMEEnabled()) {
             sendEventToGecko(GeckoEvent.createBroadcastEvent(
                     "ScrollTo:FocusedInput", ""));
         }
     }
 
-    @WrapElementForJNI(stubName = "GetCurrentNetworkInformationWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "GetCurrentNetworkInformationWrapper")
     public static double[] getCurrentNetworkInformation() {
         return GeckoNetworkManager.getInstance().getCurrentInformation();
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void enableNetworkNotifications() {
         GeckoNetworkManager.getInstance().enableNotifications();
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void disableNetworkNotifications() {
         GeckoNetworkManager.getInstance().disableNotifications();
     }
 
     // values taken from android's Base64
     public static final int BASE64_DEFAULT = 0;
     public static final int BASE64_URL_SAFE = 8;
 
@@ -2511,42 +2511,42 @@ public class GeckoAppShell
             if (op<oLen) out[op++] = (byte)o2; }
         return out; 
     }
 
     public static byte[] decodeBase64(String s, int flags) {
         return decodeBase64(s.getBytes(), flags);
     }
 
-    @WrapElementForJNI(stubName = "GetScreenOrientationWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "GetScreenOrientationWrapper")
     public static short getScreenOrientation() {
         return GeckoScreenOrientationListener.getInstance().getScreenOrientation();
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void enableScreenOrientationNotifications() {
         GeckoScreenOrientationListener.getInstance().enableNotifications();
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void disableScreenOrientationNotifications() {
         GeckoScreenOrientationListener.getInstance().disableNotifications();
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void lockScreenOrientation(int aOrientation) {
         GeckoScreenOrientationListener.getInstance().lockScreenOrientation(aOrientation);
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void unlockScreenOrientation() {
         GeckoScreenOrientationListener.getInstance().unlockScreenOrientation();
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static boolean pumpMessageLoop() {
         Handler geckoHandler = ThreadUtils.sGeckoHandler;
         Message msg = getNextMessageFromQueue(ThreadUtils.sGeckoQueue);
 
         if (msg == null)
             return false;
         if (msg.obj == geckoHandler && msg.getTarget() == geckoHandler) {
             // Our "queue is empty" message; see runGecko()
@@ -2558,66 +2558,66 @@ public class GeckoAppShell
         else
             msg.getTarget().dispatchMessage(msg);
         msg.recycle();
         return true;
     }
 
     static native void notifyFilePickerResult(String filePath, long id);
 
-    @WrapElementForJNI(stubName = "ShowFilePickerAsyncWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "ShowFilePickerAsyncWrapper")
     public static void showFilePickerAsync(String aMimeType, final long id) {
         sActivityHelper.showFilePickerAsync(getGeckoInterface().getActivity(), aMimeType, new ActivityHandlerHelper.FileResultHandler() {
             public void gotFile(String filename) {
                 GeckoAppShell.notifyFilePickerResult(filename, id);
             }
         });
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void notifyWakeLockChanged(String topic, String state) {
         if (getGeckoInterface() != null)
             getGeckoInterface().notifyWakeLockChanged(topic, state);
     }
 
-    @WrapElementForJNI(stubName = "GetGfxInfoDataWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "GetGfxInfoDataWrapper")
     public static String getGfxInfoData() {
         return GfxInfoThread.getData();
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static void registerSurfaceTextureFrameListener(Object surfaceTexture, final int id) {
         ((SurfaceTexture)surfaceTexture).setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
             @Override
             public void onFrameAvailable(SurfaceTexture surfaceTexture) {
                 GeckoAppShell.onSurfaceTextureFrameAvailable(surfaceTexture, id);
             }
         });
     }
 
-    @WrapElementForJNI(allowMultithread = true)
+    @GeneratableAndroidBridgeTarget(allowMultithread = true)
     public static void unregisterSurfaceTextureFrameListener(Object surfaceTexture) {
         ((SurfaceTexture)surfaceTexture).setOnFrameAvailableListener(null);
     }
 
-    @WrapElementForJNI
+    @GeneratableAndroidBridgeTarget
     public static boolean unlockProfile() {
         // Try to kill any zombie Fennec's that might be running
         GeckoAppShell.killAnyZombies();
 
         // Then force unlock this profile
         if (getGeckoInterface() != null) {
             GeckoProfile profile = getGeckoInterface().getProfile();
             File lock = profile.getFile(".parentlock");
             return lock.exists() && lock.delete();
         }
         return false;
     }
 
-    @WrapElementForJNI(stubName = "GetProxyForURIWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "GetProxyForURIWrapper")
     public static String getProxyForURI(String spec, String scheme, String host, int port) {
         URI uri = null;
         try {
             uri = new URI(spec);
         } catch(java.net.URISyntaxException uriEx) {
             try {
                 uri = new URI(scheme, null, host, port, null, null, null);
             } catch(java.net.URISyntaxException uriEx2) {
--- a/mobile/android/base/GeckoEvent.java
+++ b/mobile/android/base/GeckoEvent.java
@@ -2,18 +2,16 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.gfx.DisplayPortMetrics;
 import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
-import org.mozilla.gecko.mozglue.generatorannotations.GeneratorOptions;
-import org.mozilla.gecko.mozglue.generatorannotations.WrapEntireClassForJNI;
 
 import android.content.res.Resources;
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorManager;
@@ -80,18 +78,16 @@ public class GeckoEvent {
             this.value = value;
          }
     }
 
     /**
      * The DomKeyLocation enum encapsulates the DOM KeyboardEvent's constants.
      * @see https://developer.mozilla.org/en-US/docs/DOM/KeyboardEvent#Key_location_constants
      */
-    @GeneratorOptions(generatedClassName = "JavaDomKeyLocation")
-    @WrapEntireClassForJNI
     public enum DomKeyLocation {
         DOM_KEY_LOCATION_STANDARD(0),
         DOM_KEY_LOCATION_LEFT(1),
         DOM_KEY_LOCATION_RIGHT(2),
         DOM_KEY_LOCATION_NUMPAD(3),
         DOM_KEY_LOCATION_MOBILE(4),
         DOM_KEY_LOCATION_JOYSTICK(5);
 
--- a/mobile/android/base/GeckoJavaSampler.java
+++ b/mobile/android/base/GeckoJavaSampler.java
@@ -3,17 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
 import android.os.SystemClock;
 import android.util.Log;
 
-import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
+import org.mozilla.gecko.mozglue.GeneratableAndroidBridgeTarget;
 
 import java.lang.Thread;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
 public class GeckoJavaSampler {
     private static final String LOGTAG = "JavaSampler";
@@ -121,82 +121,82 @@ public class GeckoJavaSampler {
                 int readPos = (startPos + aSampleId) % mSamples.get(aThreadId).length;
                 return mSamples.get(aThreadId)[readPos];
             }
             return null;
         }
     }
 
 
-    @WrapElementForJNI(allowMultithread = true, stubName = "GetThreadNameJavaProfilingWrapper")
+    @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "GetThreadNameJavaProfilingWrapper")
     public synchronized static String getThreadName(int aThreadId) {
         if (aThreadId == 0 && sMainThread != null) {
             return sMainThread.getName();
         }
         return null;
     }
 
     private synchronized static Sample getSample(int aThreadId, int aSampleId) {
         return sSamplingRunnable.getSample(aThreadId, aSampleId);
     }
 
-    @WrapElementForJNI(allowMultithread = true, stubName = "GetSampleTimeJavaProfiling")
+    @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "GetSampleTimeJavaProfiling")
     public synchronized static double getSampleTime(int aThreadId, int aSampleId) {
         Sample sample = getSample(aThreadId, aSampleId);
         if (sample != null) {
             if (sample.mJavaTime != 0) {
                 return (double)(sample.mJavaTime -
                     SystemClock.elapsedRealtime()) + getProfilerTime();
             }
             System.out.println("Sample: " + sample.mTime);
             return sample.mTime;
         }
         return 0;
     }
 
-    @WrapElementForJNI(allowMultithread = true, stubName = "GetFrameNameJavaProfilingWrapper")
+    @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "GetFrameNameJavaProfilingWrapper")
     public synchronized static String getFrameName(int aThreadId, int aSampleId, int aFrameId) {
         Sample sample = getSample(aThreadId, aSampleId);
         if (sample != null && aFrameId < sample.mFrames.length) {
             Frame frame = sample.mFrames[aFrameId];
             if (frame == null) {
                 return null;
             }
             return frame.className + "." + frame.methodName + "()";
         }
         return null;
     }
 
-    @WrapElementForJNI(allowMultithread = true, stubName = "StartJavaProfiling")
+    @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "StartJavaProfiling")
     public static void start(int aInterval, int aSamples) {
         synchronized (GeckoJavaSampler.class) {
             if (sSamplingRunnable != null) {
                 return;
             }
             sSamplingRunnable = new SamplingThread(aInterval, aSamples);
             sSamplingThread = new Thread(sSamplingRunnable, "Java Sampler");
             sSamplingThread.start();
         }
     }
 
-    @WrapElementForJNI(allowMultithread = true, stubName = "PauseJavaProfiling")
+    @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "PauseJavaProfiling")
     public static void pause() {
         synchronized (GeckoJavaSampler.class) {
             sSamplingRunnable.mPauseSampler = true;
         }
     }
 
-    @WrapElementForJNI(allowMultithread = true, stubName = "UnpauseJavaProfiling")
+    @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "UnpauseJavaProfiling")
     public static void unpause() {
         synchronized (GeckoJavaSampler.class) {
             sSamplingRunnable.mPauseSampler = false;
         }
     }
 
-    @WrapElementForJNI(allowMultithread = true, stubName = "StopJavaProfiling")
+    @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "StopJavaProfiling")
     public static void stop() {
         synchronized (GeckoJavaSampler.class) {
             if (sSamplingThread == null) {
                 return;
             }
 
             sSamplingRunnable.mStopSampler = true;
             try {
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -4,22 +4,20 @@
 
 DIST_FILES = package-name.txt
 
 include $(topsrcdir)/mobile/android/base/android-services-files.mk
 
 MOZGLUE_JAVA_FILES := \
   mozglue/ByteBufferInputStream.java \
   mozglue/DirectBufferAllocator.java \
-  mozglue/generatorannotations/GeneratorOptions.java \
-  mozglue/generatorannotations/OptionalGeneratedParameter.java \
-  mozglue/generatorannotations/WrapEntireClassForJNI.java \
-  mozglue/generatorannotations/WrapElementForJNI.java \
+  mozglue/GeneratableAndroidBridgeTarget.java \
   mozglue/NativeReference.java \
   mozglue/NativeZip.java \
+  mozglue/OptionalGeneratedParameter.java \
   $(NULL)
 
 MOZGLUE_PP_JAVA_FILES := \
   mozglue/GeckoLoader.java \
   $(NULL)
 
 UTIL_JAVA_FILES := \
   util/ActivityResultHandler.java \
@@ -1305,23 +1303,21 @@ endif
 
 jni-stubs.inc: jars/gecko-browser.jar jars/gecko-mozglue.jar jars/gecko-util.jar jars/sync-thirdparty.jar
 	$(JAVAH) -o javah.out -bootclasspath $(JAVA_BOOTCLASSPATH) -classpath $(subst $(NULL) $(NULL),:,$^) $(CLASSES_WITH_JNI)
 	$(PYTHON) $(topsrcdir)/mobile/android/base/jni-generator.py javah.out $@
 
 ANNOTATION_PROCESSOR_JAVA_FILES = \
   build/annotationProcessors/AnnotationProcessor.java \
   build/annotationProcessors/CodeGenerator.java \
-  build/annotationProcessors/AnnotationInfo.java \
-  build/annotationProcessors/classloader/AnnotatableEntity.java \
-  build/annotationProcessors/classloader/ClassWithOptions.java \
+  build/annotationProcessors/MethodWithAnnotationInfo.java \
   build/annotationProcessors/classloader/IterableJarLoadingURLClassLoader.java \
   build/annotationProcessors/classloader/JarClassIterator.java \
-  build/annotationProcessors/utils/AlphabeticAnnotatableEntityComparator.java \
-  build/annotationProcessors/utils/GeneratableElementIterator.java \
+  build/annotationProcessors/utils/AlphabeticMethodComparator.java \
+  build/annotationProcessors/utils/GeneratableEntryPointIterator.java \
   build/annotationProcessors/utils/Utils.java \
   $(NULL)
 
 GeneratedJNIWrappers.cpp: jars/gecko-browser.jar jars/gecko-mozglue.jar jars/gecko-util.jar jars/sync-thirdparty.jar
 	$(JAVAC) $(addprefix $(topsrcdir)/,$(ANNOTATION_PROCESSOR_JAVA_FILES)) -d $(CURDIR)
 	$(JAVA) -classpath $(JAVA_BOOTCLASSPATH):$(CURDIR) org.mozilla.gecko.annotationProcessors.AnnotationProcessor $^
 
 PP_RES_XML= \
--- a/mobile/android/base/SurfaceBits.java
+++ b/mobile/android/base/SurfaceBits.java
@@ -1,17 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
-import org.mozilla.gecko.mozglue.generatorannotations.WrapEntireClassForJNI;
-
 import java.nio.ByteBuffer;
 
-@WrapEntireClassForJNI
 public class SurfaceBits {
     public int width;
     public int height;
     public int format;
     public ByteBuffer buffer;
 }
--- a/mobile/android/base/ThumbnailHelper.java
+++ b/mobile/android/base/ThumbnailHelper.java
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.gfx.BitmapUtils;
 import org.mozilla.gecko.gfx.IntSize;
 import org.mozilla.gecko.mozglue.DirectBufferAllocator;
-import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
+import org.mozilla.gecko.mozglue.GeneratableAndroidBridgeTarget;
 
 import android.graphics.Bitmap;
 import android.util.Log;
 
 import java.nio.ByteBuffer;
 import java.util.LinkedList;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -139,17 +139,17 @@ public final class ThumbnailHelper {
             return;
         }
 
         GeckoEvent e = GeckoEvent.createThumbnailEvent(tab.getId(), mWidth, mHeight, mBuffer);
         GeckoAppShell.sendEventToGecko(e);
     }
 
     /* This method is invoked by JNI once the thumbnail data is ready. */
-    @WrapElementForJNI(stubName = "SendThumbnail")
+    @GeneratableAndroidBridgeTarget(stubName = "SendThumbnail")
     public static void notifyThumbnail(ByteBuffer data, int tabId, boolean success) {
         Tab tab = Tabs.getInstance().getTab(tabId);
         ThumbnailHelper helper = ThumbnailHelper.getInstance();
         if (success && tab != null) {
             helper.handleThumbnailData(tab, data);
         }
         helper.processNextThumbnail(tab);
     }
--- a/mobile/android/base/gfx/DisplayPortMetrics.java
+++ b/mobile/android/base/gfx/DisplayPortMetrics.java
@@ -1,39 +1,35 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
-import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
 import org.mozilla.gecko.util.FloatUtils;
 
 import android.graphics.RectF;
 
 /*
  * This class keeps track of the area we request Gecko to paint, as well
  * as the resolution of the paint. The area may be different from the visible
  * area of the page, and the resolution may be different from the resolution
  * used in the compositor to render the page. This is so that we can ask Gecko
  * to paint a much larger area without using extra memory, and then render some
  * subsection of that with compositor scaling.
  */
 public final class DisplayPortMetrics {
-    @WrapElementForJNI
     public final float resolution;
-    @WrapElementForJNI
     private final RectF mPosition;
 
     public DisplayPortMetrics() {
         this(0, 0, 0, 0, 1);
     }
 
-    @WrapElementForJNI
     public DisplayPortMetrics(float left, float top, float right, float bottom, float resolution) {
         this.resolution = resolution;
         mPosition = new RectF(left, top, right, bottom);
     }
 
     public float getLeft() {
         return mPosition.left;
     }
--- a/mobile/android/base/gfx/GLController.java
+++ b/mobile/android/base/gfx/GLController.java
@@ -3,17 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.GeckoThread;
-import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
+import org.mozilla.gecko.mozglue.GeneratableAndroidBridgeTarget;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.util.Log;
 
 import javax.microedition.khronos.egl.EGL10;
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.egl.EGLContext;
 import javax.microedition.khronos.egl.EGLDisplay;
@@ -258,17 +258,17 @@ public class GLController {
             if (red[0] == rSize && green[0] == gSize && blue[0] == bSize) {
                 return config;
             }
         }
 
         throw new GLControllerException("No suitable EGL configuration found");
     }
 
-    @WrapElementForJNI(allowMultithread = true, stubName = "ProvideEGLSurfaceWrapper")
+    @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "ProvideEGLSurfaceWrapper")
     private EGLSurface provideEGLSurface() {
         return mEGLSurface;
     }
 
     private String getEGLError() {
         return "Error " + (mEGL == null ? "(no mEGL)" : mEGL.eglGetError());
     }
 
--- a/mobile/android/base/gfx/GeckoLayerClient.java
+++ b/mobile/android/base/gfx/GeckoLayerClient.java
@@ -6,17 +6,16 @@
 package org.mozilla.gecko.gfx;
 
 import org.mozilla.gecko.BrowserApp;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.Tab;
 import org.mozilla.gecko.Tabs;
 import org.mozilla.gecko.ZoomConstraints;
-import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
 import org.mozilla.gecko.util.EventDispatcher;
 import org.mozilla.gecko.util.FloatUtils;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.content.Context;
 import android.graphics.PointF;
 import android.graphics.RectF;
 import android.os.SystemClock;
@@ -405,49 +404,48 @@ public class GeckoLayerClient implements
             });
 
             setViewportMetrics(newMetrics, type == ViewportMessageType.UPDATE);
             mDisplayPort = DisplayPortCalculator.calculate(getViewportMetrics(), null);
         }
         return mDisplayPort;
     }
 
-    @WrapElementForJNI
+    /* This is invoked by JNI on the gecko thread */
     DisplayPortMetrics getDisplayPort(boolean pageSizeUpdate, boolean isBrowserContentDisplayed, int tabId, ImmutableViewportMetrics metrics) {
         Tabs tabs = Tabs.getInstance();
         if (tabs.isSelectedTab(tabs.getTab(tabId)) && isBrowserContentDisplayed) {
             // for foreground tabs, send the viewport update unless the document
             // displayed is different from the content document. In that case, just
             // calculate the display port.
             return handleViewportMessage(metrics, pageSizeUpdate ? ViewportMessageType.PAGE_SIZE : ViewportMessageType.UPDATE);
         } else {
             // for background tabs, request a new display port calculation, so that
             // when we do switch to that tab, we have the correct display port and
             // don't need to draw twice (once to allow the first-paint viewport to
             // get to java, and again once java figures out the display port).
             return DisplayPortCalculator.calculate(metrics, null);
         }
     }
 
-    @WrapElementForJNI
+    /* This is invoked by JNI on the gecko thread */
     void contentDocumentChanged() {
         mContentDocumentIsDisplayed = false;
     }
 
-    @WrapElementForJNI
+    /* This is invoked by JNI on the gecko thread */
     boolean isContentDocumentDisplayed() {
         return mContentDocumentIsDisplayed;
     }
 
     // This is called on the Gecko thread to determine if we're still interested
     // in the update of this display-port to continue. We can return true here
     // to abort the current update and continue with any subsequent ones. This
     // is useful for slow-to-render pages when the display-port starts lagging
     // behind enough that continuing to draw it is wasted effort.
-    @WrapElementForJNI(allowMultithread = true)
     public ProgressiveUpdateData progressiveUpdateCallback(boolean aHasPendingNewThebesContent,
                                                            float x, float y, float width, float height,
                                                            float resolution, boolean lowPrecision) {
         // Reset the checkerboard risk flag when switching to low precision
         // rendering.
         if (lowPrecision && !mLastProgressiveUpdateWasLowPrecision) {
             // Skip low precision rendering until we're at risk of checkerboarding.
             if (!mProgressiveUpdateWasInDanger) {
@@ -545,23 +543,23 @@ public class GeckoLayerClient implements
 
     void setIsRTL(boolean aIsRTL) {
         synchronized (getLock()) {
             ImmutableViewportMetrics newMetrics = getViewportMetrics().setIsRTL(aIsRTL);
             setViewportMetrics(newMetrics, false);
         }
     }
 
-    /** The compositor invokes this function just before compositing a frame where the document
+    /** This function is invoked by Gecko via JNI; be careful when modifying signature.
+      * The compositor invokes this function just before compositing a frame where the document
       * is different from the document composited on the last frame. In these cases, the viewport
       * information we have in Java is no longer valid and needs to be replaced with the new
       * viewport information provided. setPageRect will never be invoked on the same frame that
       * this function is invoked on; and this function will always be called prior to syncViewportInfo.
       */
-    @WrapElementForJNI(allowMultithread = true)
     public void setFirstPaintViewport(float offsetX, float offsetY, float zoom,
             float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom) {
         synchronized (getLock()) {
             ImmutableViewportMetrics currentMetrics = getViewportMetrics();
 
             Tab tab = Tabs.getInstance().getSelectedTab();
 
             RectF cssPageRect = new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom);
@@ -604,43 +602,43 @@ public class GeckoLayerClient implements
             }
         }
         DisplayPortCalculator.resetPageState();
         mDrawTimingQueue.reset();
 
         mContentDocumentIsDisplayed = true;
     }
 
-    /** The compositor invokes this function whenever it determines that the page rect
+    /** This function is invoked by Gecko via JNI; be careful when modifying signature.
+      * The compositor invokes this function whenever it determines that the page rect
       * has changed (based on the information it gets from layout). If setFirstPaintViewport
       * is invoked on a frame, then this function will not be. For any given frame, this
       * function will be invoked before syncViewportInfo.
       */
-    @WrapElementForJNI(allowMultithread = true)
     public void setPageRect(float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom) {
         synchronized (getLock()) {
             RectF cssPageRect = new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom);
             float ourZoom = getViewportMetrics().zoomFactor;
             setPageRect(RectUtils.scale(cssPageRect, ourZoom), cssPageRect);
             // Here the page size of the document has changed, but the document being displayed
             // is still the same. Therefore, we don't need to send anything to browser.js; any
             // changes we need to make to the display port will get sent the next time we call
             // adjustViewport().
         }
     }
 
-    /** The compositor invokes this function on every frame to figure out what part of the
+    /** This function is invoked by Gecko via JNI; be careful when modifying signature.
+      * The compositor invokes this function on every frame to figure out what part of the
       * page to display, and to inform Java of the current display port. Since it is called
       * on every frame, it needs to be ultra-fast.
       * It avoids taking any locks or allocating any objects. We keep around a
       * mCurrentViewTransform so we don't need to allocate a new ViewTransform
       * everytime we're called. NOTE: we might be able to return a ImmutableViewportMetrics
       * which would avoid the copy into mCurrentViewTransform.
       */
-    @WrapElementForJNI(allowMultithread = true)
     public ViewTransform syncViewportInfo(int x, int y, int width, int height, float resolution, boolean layersUpdated) {
         // getViewportMetrics is thread safe so we don't need to synchronize.
         // We save the viewport metrics here, so we later use it later in
         // createFrame (which will be called by nsWindow::DrawWindowUnderlay on
         // the native side, by the compositor). The viewport
         // metrics can change between here and there, as it's accessed outside
         // of the compositor thread.
         mFrameMetrics = getViewportMetrics();
@@ -684,48 +682,48 @@ public class GeckoLayerClient implements
         if (layersUpdated && mDrawListener != null) {
             /* Used by robocop for testing purposes */
             mDrawListener.drawFinished();
         }
 
         return mCurrentViewTransform;
     }
 
-    @WrapElementForJNI(allowMultithread = true)
+    /* Invoked by JNI from the compositor thread */
     public ViewTransform syncFrameMetrics(float offsetX, float offsetY, float zoom,
                 float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom,
                 boolean layersUpdated, int x, int y, int width, int height, float resolution,
                 boolean isFirstPaint)
     {
         if (isFirstPaint) {
             setFirstPaintViewport(offsetX, offsetY, zoom,
                                   cssPageLeft, cssPageTop, cssPageRight, cssPageBottom);
         }
 
         return syncViewportInfo(x, y, width, height, resolution, layersUpdated);
     }
 
-    @WrapElementForJNI(allowMultithread = true)
+    /** This function is invoked by Gecko via JNI; be careful when modifying signature. */
     public LayerRenderer.Frame createFrame() {
         // Create the shaders and textures if necessary.
         if (!mLayerRendererInitialized) {
             mLayerRenderer.checkMonitoringEnabled();
             mLayerRenderer.createDefaultProgram();
             mLayerRendererInitialized = true;
         }
 
         return mLayerRenderer.createFrame(mFrameMetrics);
     }
 
-    @WrapElementForJNI(allowMultithread = true)
+    /** This function is invoked by Gecko via JNI; be careful when modifying signature. */
     public void activateProgram() {
         mLayerRenderer.activateDefaultProgram();
     }
 
-    @WrapElementForJNI(allowMultithread = true)
+    /** This function is invoked by Gecko via JNI; be careful when modifying signature. */
     public void deactivateProgram() {
         mLayerRenderer.deactivateDefaultProgram();
     }
 
     private void geometryChanged(DisplayPortMetrics displayPort) {
         /* Let Gecko know if the screensize has changed */
         sendResizeEventIfNecessary(false);
         if (getRedrawHint()) {
--- a/mobile/android/base/gfx/ImmutableViewportMetrics.java
+++ b/mobile/android/base/gfx/ImmutableViewportMetrics.java
@@ -1,16 +1,15 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
-import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
 import org.mozilla.gecko.util.FloatUtils;
 
 import android.graphics.PointF;
 import android.graphics.RectF;
 import android.util.DisplayMetrics;
 
 /**
  * ImmutableViewportMetrics are used to store the viewport metrics
@@ -48,18 +47,17 @@ public class ImmutableViewportMetrics {
         marginLeft = marginTop = marginRight = marginBottom = 0;
         zoomFactor = 1.0f;
         isRTL = false;
     }
 
     /** This constructor is used by native code in AndroidJavaWrappers.cpp, be
      * careful when modifying the signature.
      */
-    @WrapElementForJNI(allowMultithread = true)
-    public ImmutableViewportMetrics(float aPageRectLeft, float aPageRectTop,
+    private ImmutableViewportMetrics(float aPageRectLeft, float aPageRectTop,
         float aPageRectRight, float aPageRectBottom, float aCssPageRectLeft,
         float aCssPageRectTop, float aCssPageRectRight, float aCssPageRectBottom,
         float aViewportRectLeft, float aViewportRectTop, float aViewportRectRight,
         float aViewportRectBottom, float aZoomFactor)
     {
         this(aPageRectLeft, aPageRectTop,
              aPageRectRight, aPageRectBottom, aCssPageRectLeft,
              aCssPageRectTop, aCssPageRectRight, aCssPageRectBottom,
--- a/mobile/android/base/gfx/LayerRenderer.java
+++ b/mobile/android/base/gfx/LayerRenderer.java
@@ -7,25 +7,24 @@ package org.mozilla.gecko.gfx;
 
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Tab;
 import org.mozilla.gecko.Tabs;
 import org.mozilla.gecko.gfx.Layer.RenderContext;
 import org.mozilla.gecko.gfx.RenderTask;
 import org.mozilla.gecko.mozglue.DirectBufferAllocator;
-import org.mozilla.gecko.mozglue.generatorannotations.GeneratorOptions;
-import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
 
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Matrix;
+import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.opengl.GLES20;
 import android.os.SystemClock;
 import android.util.Log;
 
 import java.nio.ByteBuffer;
@@ -433,17 +432,16 @@ public class LayerRenderer implements Ta
             } else {
                 // reached the run-at time, execute
                 mStarted = false;
                 mView.requestRender();
             }
         }
     }
 
-    @GeneratorOptions(generatedClassName = "LayerRendererFrame")
     public class Frame {
         // The timestamp recording the start of this frame.
         private long mFrameStartTime;
         // A fixed snapshot of the viewport metrics that this frame is using to render content.
         private ImmutableViewportMetrics mFrameMetrics;
         // A rendering context for page-positioned layers, and one for screen-positioned layers.
         private RenderContext mPageContext, mScreenContext;
         // Whether a layer was updated.
@@ -487,17 +485,16 @@ public class LayerRenderer implements Ta
             Rect scissorRect = new Rect(left, screenSize.height - bottom, right,
                                         (screenSize.height - bottom) + (bottom - top));
             scissorRect.offset(Math.round(-mRenderOffset.x), Math.round(-mRenderOffset.y));
 
             return scissorRect;
         }
 
         /** This function is invoked via JNI; be careful when modifying signature. */
-        @WrapElementForJNI(allowMultithread = true)
         public void beginDrawing() {
             mFrameStartTime = System.nanoTime();
 
             TextureReaper.get().reap();
             TextureGenerator.get().fill();
 
             mUpdated = true;
 
@@ -577,17 +574,16 @@ public class LayerRenderer implements Ta
                                 0.0f);
             // The bits set here need to match up with those used
             // in gfx/layers/opengl/LayerManagerOGL.cpp.
             GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT |
                            GLES20.GL_DEPTH_BUFFER_BIT);
         }
 
         /** This function is invoked via JNI; be careful when modifying signature. */
-        @WrapElementForJNI(allowMultithread = true)
         public void drawBackground() {
             GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
 
             // Draw the overscroll background area as a solid color
             clear(mOverscrollColor);
 
             // Update background color.
             mBackgroundColor = mView.getBackgroundColor();
@@ -610,17 +606,16 @@ public class LayerRenderer implements Ta
             if (rootLayer == null) {
                 return;
             }
 
             rootLayer.draw(mPageContext);
         }
 
         /** This function is invoked via JNI; be careful when modifying signature. */
-        @WrapElementForJNI(allowMultithread = true)
         public void drawForeground() {
             /* Draw any extra layers that were added (likely plugins) */
             if (mExtraLayers.size() > 0) {
                 for (Layer layer : mExtraLayers) {
                     layer.draw(mPageContext);
                 }
             }
 
@@ -661,17 +656,16 @@ public class LayerRenderer implements Ta
 
                 GLES20.glEnable(GLES20.GL_BLEND);
                 GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
                 mFrameRateLayer.draw(mScreenContext);
             }
         }
 
         /** This function is invoked via JNI; be careful when modifying signature. */
-        @WrapElementForJNI(allowMultithread = true)
         public void endDrawing() {
             // If a layer update requires further work, schedule another redraw
             if (!mUpdated)
                 mView.requestRender();
 
             PanningPerfAPI.recordFrameTime();
 
             /* Used by robocop for testing purposes */
--- a/mobile/android/base/gfx/LayerView.java
+++ b/mobile/android/base/gfx/LayerView.java
@@ -7,17 +7,17 @@ package org.mozilla.gecko.gfx;
 
 import org.mozilla.gecko.GeckoAccessibility;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.PrefsHelper;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.TouchEventInterceptor;
 import org.mozilla.gecko.ZoomConstraints;
-import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
+import org.mozilla.gecko.mozglue.GeneratableAndroidBridgeTarget;
 import org.mozilla.gecko.util.EventDispatcher;
 
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Color;
 import android.graphics.PixelFormat;
 import android.graphics.PointF;
@@ -503,17 +503,17 @@ public class LayerView extends FrameLayo
 
     public Object getNativeWindow() {
         if (mSurfaceView != null)
             return mSurfaceView.getHolder();
 
         return mTextureView.getSurfaceTexture();
     }
 
-    @WrapElementForJNI(allowMultithread = true, stubName = "RegisterCompositorWrapper")
+    @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "RegisterCompositorWrapper")
     public static GLController registerCxxCompositor() {
         try {
             LayerView layerView = GeckoAppShell.getLayerView();
             GLController controller = layerView.getGLController();
             controller.compositorCreated();
             return controller;
         } catch (Exception e) {
             Log.e(LOGTAG, "Error registering compositor!", e);
--- a/mobile/android/base/gfx/NativePanZoomController.java
+++ b/mobile/android/base/gfx/NativePanZoomController.java
@@ -2,17 +2,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
 import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.GeckoThread;
-import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
+import org.mozilla.gecko.mozglue.GeneratableAndroidBridgeTarget;
 import org.mozilla.gecko.util.EventDispatcher;
 import org.mozilla.gecko.util.GeckoEventListener;
 
 import org.json.JSONObject;
 
 import android.graphics.PointF;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -78,22 +78,22 @@ class NativePanZoomController implements
     private native long runDelayedCallback();
 
     public native void destroy();
     public native void notifyDefaultActionPrevented(boolean prevented);
     public native boolean getRedrawHint();
     public native void setOverScrollMode(int overscrollMode);
     public native int getOverScrollMode();
 
-    @WrapElementForJNI(allowMultithread = true, stubName = "RequestContentRepaintWrapper")
+    @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "RequestContentRepaintWrapper")
     private void requestContentRepaint(float x, float y, float width, float height, float resolution) {
         mTarget.forceRedraw(new DisplayPortMetrics(x, y, x + width, y + height, resolution));
     }
 
-    @WrapElementForJNI(allowMultithread = true, stubName = "PostDelayedCallbackWrapper")
+    @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "PostDelayedCallbackWrapper")
     private void postDelayedCallback(long delay) {
         mTarget.postDelayed(mCallbackRunnable, delay);
     }
 
     class CallbackRunnable implements Runnable {
         @Override
         public void run() {
             long nextDelay = runDelayedCallback();
--- a/mobile/android/base/gfx/ProgressiveUpdateData.java
+++ b/mobile/android/base/gfx/ProgressiveUpdateData.java
@@ -1,24 +1,21 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
-import org.mozilla.gecko.mozglue.generatorannotations.WrapEntireClassForJNI;
-
 /**
  * This is the data structure that's returned by the progressive tile update
  * callback function. It encompasses the current viewport and a boolean value
  * representing whether the front-end is interested in the current progressive
  * update continuing.
  */
-@WrapEntireClassForJNI
 public class ProgressiveUpdateData {
     public float x;
     public float y;
     public float width;
     public float height;
     public float scale;
     public boolean abort;
 
--- a/mobile/android/base/gfx/ViewTransform.java
+++ b/mobile/android/base/gfx/ViewTransform.java
@@ -1,18 +1,15 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.gfx;
 
-import org.mozilla.gecko.mozglue.generatorannotations.WrapEntireClassForJNI;
-
-@WrapEntireClassForJNI
 public class ViewTransform {
     public float x;
     public float y;
     public float scale;
     public float fixedLayerMarginLeft;
     public float fixedLayerMarginTop;
     public float fixedLayerMarginRight;
     public float fixedLayerMarginBottom;
rename from mobile/android/base/mozglue/generatorannotations/WrapElementForJNI.java
rename to mobile/android/base/mozglue/GeneratableAndroidBridgeTarget.java
--- a/mobile/android/base/mozglue/generatorannotations/WrapElementForJNI.java
+++ b/mobile/android/base/mozglue/GeneratableAndroidBridgeTarget.java
@@ -1,13 +1,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-package org.mozilla.gecko.mozglue.generatorannotations;
+package org.mozilla.gecko.mozglue;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
 /**
  * This annotation is used to tag methods that are to have wrapper methods generated in the android
  * bridge. Such methods will be protected from destruction by Proguard, and allow us to avoid writing
  * by hand large amounts of boring boilerplate.
@@ -16,17 +16,17 @@ import java.lang.annotation.RetentionPol
  * the first letter in upper case. The stubName property may be used to specify a custom name for the
  * generated method stub.
  *
  * allowMultithreaded should be used as sparingly as possible - the resulting code will allow the
  * Java method to be invoked from the C side from multiple threads. Often, this isn't what is wanted
  * and may lead to subtle bugs.
  */
 @Retention(RetentionPolicy.RUNTIME)
-public @interface WrapElementForJNI {
+public @interface GeneratableAndroidBridgeTarget {
     // Optional parameter specifying the name of the generated method stub. If omitted, the name
     // of the Java method will be used.
     String stubName() default "";
 
     // Optional parameter specifying if the generated method should be a static member of AndroidBridge
     // By default, an instance member is produced. This is almost always what is wanted.
     boolean generateStatic() default false;
 
--- a/mobile/android/base/mozglue/NativeZip.java
+++ b/mobile/android/base/mozglue/NativeZip.java
@@ -1,17 +1,15 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.mozglue;
 
-import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
-
 import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.util.zip.Inflater;
 import java.util.zip.InflaterInputStream;
 
 public class NativeZip implements NativeReference {
     private static final int DEFLATE = 8;
     private static final int STORE = 0;
@@ -65,17 +63,16 @@ public class NativeZip implements Native
         return _getInputStream(mObj, path);
     }
 
     private static native long getZip(String path);
     private static native long getZipFromByteBuffer(ByteBuffer buffer);
     private static native void _release(long obj);
     private native InputStream _getInputStream(long obj, String path);
 
-    @WrapElementForJNI
     private InputStream createInputStream(ByteBuffer buffer, int compression) {
         if (compression != STORE && compression != DEFLATE) {
             throw new IllegalArgumentException("Unexpected compression: " + compression);
         }
 
         InputStream input = new ByteBufferInputStream(buffer, this);
         if (compression == DEFLATE) {
             Inflater inflater = new Inflater(true);
rename from mobile/android/base/mozglue/generatorannotations/OptionalGeneratedParameter.java
rename to mobile/android/base/mozglue/OptionalGeneratedParameter.java
--- a/mobile/android/base/mozglue/generatorannotations/OptionalGeneratedParameter.java
+++ b/mobile/android/base/mozglue/OptionalGeneratedParameter.java
@@ -1,13 +1,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-package org.mozilla.gecko.mozglue.generatorannotations;
+package org.mozilla.gecko.mozglue;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
 /**
  * Used to annotate parameters which are optional on the C++ side of the bridge. The annotation is
  * used by the annotation processor to generate the appropriate C++ headers so calls into the Java
  * method all have the optional params set to the default value.
deleted file mode 100644
--- a/mobile/android/base/mozglue/generatorannotations/GeneratorOptions.java
+++ /dev/null
@@ -1,14 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.mozglue.generatorannotations;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-@Retention(RetentionPolicy.RUNTIME)
-public @interface GeneratorOptions {
-    // Specifies a custom name for the generated C++ class. If left empty, is AndroidJavaClassName.
-    String generatedClassName() default "";
-}
\ No newline at end of file
deleted file mode 100644
--- a/mobile/android/base/mozglue/generatorannotations/WrapEntireClassForJNI.java
+++ /dev/null
@@ -1,15 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.mozglue.generatorannotations;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Handy shortcut annotation. Functionally equivalent to tagging every member individually with default
- * settings.
- */
-@Retention(RetentionPolicy.RUNTIME)
-public @interface WrapEntireClassForJNI {}
--- a/mobile/android/base/sqlite/MatrixBlobCursor.java
+++ b/mobile/android/base/sqlite/MatrixBlobCursor.java
@@ -12,18 +12,16 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 package org.mozilla.gecko.sqlite;
 
-import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
-
 import android.database.AbstractCursor;
 import android.database.CursorIndexOutOfBoundsException;
 
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 
 /*
  * Android's AbstractCursor throws on getBlob()
@@ -47,17 +45,16 @@ public class MatrixBlobCursor extends Ab
 
     /**
      * Constructs a new cursor with the given initial capacity.
      *
      * @param columnNames names of the columns, the ordering of which
      *  determines column ordering elsewhere in this cursor
      * @param initialCapacity in rows
      */
-    @WrapElementForJNI
     public MatrixBlobCursor(String[] columnNames, int initialCapacity) {
         this.columnNames = columnNames;
         this.columnCount = columnNames.length;
 
         if (initialCapacity < 1) {
             initialCapacity = 1;
         }
 
@@ -65,17 +62,16 @@ public class MatrixBlobCursor extends Ab
     }
 
     /**
      * Constructs a new cursor.
      *
      * @param columnNames names of the columns, the ordering of which
      *  determines column ordering elsewhere in this cursor
      */
-    @WrapElementForJNI
     public MatrixBlobCursor(String[] columnNames) {
         this(columnNames, 16);
     }
 
     /**
      * Gets value at the given column for the current row.
      */
     protected Object get(int column) {
@@ -111,17 +107,16 @@ public class MatrixBlobCursor extends Ab
      * Adds a new row to the end with the given column values. Not safe
      * for concurrent use.
      *
      * @throws IllegalArgumentException if {@code columnValues.length !=
      *  columnNames.length}
      * @param columnValues in the same order as the the column names specified
      *  at cursor construction time
      */
-    @WrapElementForJNI
     public void addRow(Object[] columnValues) {
         if (columnValues.length != columnCount) {
             throw new IllegalArgumentException("columnNames.length = "
                     + columnCount + ", columnValues.length = "
                     + columnValues.length);
         }
 
         int start = rowCount++ * columnCount;
@@ -133,17 +128,16 @@ public class MatrixBlobCursor extends Ab
      * Adds a new row to the end with the given column values. Not safe
      * for concurrent use.
      *
      * @throws IllegalArgumentException if {@code columnValues.size() !=
      *  columnNames.length}
      * @param columnValues in the same order as the the column names specified
      *  at cursor construction time
      */
-    @WrapElementForJNI
     public void addRow(Iterable<?> columnValues) {
         int start = rowCount * columnCount;
         int end = start + columnCount;
         ensureCapacity(end);
 
         if (columnValues instanceof ArrayList<?>) {
             addRow((ArrayList<?>) columnValues, start);
             return;
@@ -166,17 +160,16 @@ public class MatrixBlobCursor extends Ab
                     "columnValues.size() < columnNames.length");
         }
 
         // Increase row count here in case we encounter an exception.
         rowCount++;
     }
 
     /** Optimization for {@link ArrayList}. */
-    @WrapElementForJNI
     private void addRow(ArrayList<?> columnValues, int start) {
         int size = columnValues.size();
         if (size != columnCount) {
             throw new IllegalArgumentException("columnNames.length = "
                     + columnCount + ", columnValues.size() = " + size);
         }
 
         rowCount++;
--- a/mobile/android/base/sqlite/SQLiteBridgeException.java
+++ b/mobile/android/base/sqlite/SQLiteBridgeException.java
@@ -1,18 +1,15 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.sqlite;
 
-import org.mozilla.gecko.mozglue.generatorannotations.WrapEntireClassForJNI;
-
-@WrapEntireClassForJNI
 public class SQLiteBridgeException extends RuntimeException {
     static final long serialVersionUID = 1L;
 
     public SQLiteBridgeException() {}
     public SQLiteBridgeException(String msg) {
         super(msg);
     }
 }
--- a/mobile/android/base/util/Clipboard.java
+++ b/mobile/android/base/util/Clipboard.java
@@ -4,17 +4,17 @@
 
 package org.mozilla.gecko.util;
 
 import android.content.ClipData;
 import android.content.Context;
 import android.os.Build;
 import android.util.Log;
 
-import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
+import org.mozilla.gecko.mozglue.GeneratableAndroidBridgeTarget;
 
 import java.util.concurrent.SynchronousQueue;
 
 public final class Clipboard {
     private static Context mContext;
     private final static String LOG_TAG = "Clipboard";
     private final static SynchronousQueue<String> sClipboardQueue = new SynchronousQueue<String>();
 
@@ -24,17 +24,17 @@ public final class Clipboard {
     public static void init(Context c) {
         if (mContext != null) {
             Log.w(LOG_TAG, "Clipboard.init() called twice!");
             return;
         }
         mContext = c;
     }
 
-    @WrapElementForJNI(stubName = "GetClipboardTextWrapper")
+    @GeneratableAndroidBridgeTarget(stubName = "GetClipboardTextWrapper")
     public static String getText() {
         // If we're on the UI thread or the background thread, we have a looper on the thread
         // and can just call this directly. For any other threads, post the call to the
         // background thread.
 
         if (ThreadUtils.isOnUiThread() || ThreadUtils.isOnBackgroundThread()) {
             return getClipboardTextImpl();
         }
@@ -50,17 +50,17 @@ public final class Clipboard {
         });
         try {
             return sClipboardQueue.take();
         } catch (InterruptedException ie) {
             return "";
         }
     }
 
-    @WrapElementForJNI(stubName = "SetClipboardText")
+    @GeneratableAndroidBridgeTarget(stubName = "SetClipboardText")
     public static void setText(final CharSequence text) {
         ThreadUtils.postToBackgroundThread(new Runnable() {
             @Override
             @SuppressWarnings("deprecation")
             public void run() {
                 if (Build.VERSION.SDK_INT >= 11) {
                     android.content.ClipboardManager cm = getClipboardManager11(mContext);
                     ClipData clip = ClipData.newPlainText("Text", text);
@@ -74,35 +74,16 @@ public final class Clipboard {
                 } else {
                     android.text.ClipboardManager cm = getClipboardManager(mContext);
                     cm.setText(text);
                 }
             }
         });
     }
 
-    /**
-     * Returns true if the clipboard is nonempty, false otherwise.
-     *
-     * @return true if the clipboard is nonempty, false otherwise.
-     */
-    @WrapElementForJNI
-    public static boolean hasText() {
-        String text = getText();
-        return text != null;
-    }
-
-    /**
-     * Deletes all text from the clipboard.
-     */
-    @WrapElementForJNI
-    public static void clearText() {
-        setText(null);
-    }
-
     private static android.content.ClipboardManager getClipboardManager11(Context context) {
         // In API Level 11 and above, CLIPBOARD_SERVICE returns android.content.ClipboardManager,
         // which is a subclass of android.text.ClipboardManager.
         return (android.content.ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
     }
 
     private static android.text.ClipboardManager getClipboardManager(Context context) {
         return (android.text.ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
--- a/mobile/android/components/build/nsAndroidHistory.cpp
+++ b/mobile/android/components/build/nsAndroidHistory.cpp
@@ -45,17 +45,20 @@ nsAndroidHistory::RegisterVisitedCallbac
 
   nsTArray<Link*>* list = mListeners.Get(uriString);
   if (! list) {
     list = new nsTArray<Link*>();
     mListeners.Put(uriString, list);
   }
   list->AppendElement(aContent);
 
- GeckoAppShell::CheckURIVisited(uriString);
+  AndroidBridge *bridge = AndroidBridge::Bridge();
+  if (bridge) {
+    bridge->CheckURIVisited(uriString);
+  }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAndroidHistory::UnregisterVisitedCallback(nsIURI *aURI, Link *aContent)
 {
   if (!aContent || !aURI)
@@ -88,33 +91,37 @@ nsAndroidHistory::VisitURI(nsIURI *aURI,
     return NS_OK;
 
   if (aFlags & VisitFlags::REDIRECT_SOURCE)
     return NS_OK;
 
   if (aFlags & VisitFlags::UNRECOVERABLE_ERROR)
     return NS_OK;
 
-  nsAutoCString uri;
-  nsresult rv = aURI->GetSpec(uri);
-  if (NS_FAILED(rv)) return rv;
-  NS_ConvertUTF8toUTF16 uriString(uri);
-  GeckoAppShell::MarkURIVisited(uriString);
+  AndroidBridge *bridge = AndroidBridge::Bridge();
+  if (bridge) {
+    nsAutoCString uri;
+    nsresult rv = aURI->GetSpec(uri);
+    if (NS_FAILED(rv)) return rv;
+    NS_ConvertUTF8toUTF16 uriString(uri);
+    bridge->MarkURIVisited(uriString);
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAndroidHistory::SetURITitle(nsIURI *aURI, const nsAString& aTitle)
 {
-  if (AndroidBridge::Bridge()) {
+  AndroidBridge *bridge = AndroidBridge::Bridge();
+  if (bridge) {
     nsAutoCString uri;
     nsresult rv = aURI->GetSpec(uri);
     if (NS_FAILED(rv)) return rv;
     NS_ConvertUTF8toUTF16 uriString(uri);
-    GeckoAppShell::SetURITitle(uriString, aTitle);
+    bridge->SetURITitle(uriString, aTitle);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAndroidHistory::NotifyVisited(nsIURI *aURI)
 {
   if (aURI && sHistory) {
--- a/mobile/android/components/build/nsShellService.cpp
+++ b/mobile/android/components/build/nsShellService.cpp
@@ -3,27 +3,25 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsShellService.h"
 #include "nsString.h"
 
 #include "AndroidBridge.h"
 
-using namespace mozilla::widget::android;
-
 NS_IMPL_ISUPPORTS1(nsShellService, nsIShellService)
 
 NS_IMETHODIMP
 nsShellService::SwitchTask()
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsShellService::CreateShortcut(const nsAString& aTitle, const nsAString& aURI, const nsAString& aIconData, const nsAString& aIntent)
 {
   if (!aTitle.Length() || !aURI.Length() || !aIconData.Length())
     return NS_ERROR_FAILURE;
 
-  GeckoAppShell::CreateShortcut(aTitle, aURI, aIconData, aIntent);
+  mozilla::AndroidBridge::Bridge()->CreateShortcut(aTitle, aURI, aIconData, aIntent);
   return NS_OK;
 }
--- a/netwerk/base/src/Tickler.cpp
+++ b/netwerk/base/src/Tickler.cpp
@@ -75,17 +75,17 @@ nsresult
 Tickler::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mTimer);
   MOZ_ASSERT(!mActive);
   MOZ_ASSERT(!mThread);
   MOZ_ASSERT(!mFD);
 
-  GeckoAppShell::EnableNetworkNotifications();
+  AndroidBridge::Bridge()->EnableNetworkNotifications();
 
   mFD = PR_OpenUDPSocket(PR_AF_INET);
   if (!mFD)
     return NS_ERROR_FAILURE;
 
   // make sure new socket has a ttl of 1
   // failure is not fatal.
   PRSocketOptionData opt;
--- a/netwerk/protocol/device/CameraStreamImpl.cpp
+++ b/netwerk/protocol/device/CameraStreamImpl.cpp
@@ -85,14 +85,14 @@ bool CameraStreamImpl::Init(const nsCStr
 {
     mCallback = aCallback;
     mWidth = width;
     mHeight = height;
     return AndroidBridge::Bridge()->InitCamera(contentType, camera, &mWidth, &mHeight, &mFps);
 }
 
 void CameraStreamImpl::Close() {
-    GeckoAppShell::CloseCamera();
+    AndroidBridge::Bridge()->CloseCamera();
     mCallback = nullptr;
 }
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/system/android/nsAndroidNetworkLinkService.cpp
+++ b/netwerk/system/android/nsAndroidNetworkLinkService.cpp
@@ -5,18 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsAndroidNetworkLinkService.h"
 #include "nsServiceManagerUtils.h"
 #include "mozilla/Services.h"
 
 #include "AndroidBridge.h"
 
-using namespace mozilla::widget::android;
-
 NS_IMPL_ISUPPORTS1(nsAndroidNetworkLinkService,
                    nsINetworkLinkService)
 
 nsAndroidNetworkLinkService::nsAndroidNetworkLinkService()
 {
 }
 
 nsAndroidNetworkLinkService::~nsAndroidNetworkLinkService()
@@ -28,26 +26,26 @@ nsAndroidNetworkLinkService::GetIsLinkUp
 {
   if (!mozilla::AndroidBridge::Bridge()) {
     // Fail soft here and assume a connection exists
     NS_WARNING("GetIsLinkUp is not supported without a bridge connection");
     *aIsUp = true;
     return NS_OK;
   }
 
-  *aIsUp = GeckoAppShell::IsNetworkLinkUp();
+  *aIsUp = mozilla::AndroidBridge::Bridge()->IsNetworkLinkUp();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAndroidNetworkLinkService::GetLinkStatusKnown(bool *aIsKnown)
 {
   NS_ENSURE_TRUE(mozilla::AndroidBridge::Bridge(), NS_ERROR_NOT_IMPLEMENTED);
 
-  *aIsKnown = GeckoAppShell::IsNetworkLinkKnown();
+  *aIsKnown = mozilla::AndroidBridge::Bridge()->IsNetworkLinkKnown();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAndroidNetworkLinkService::GetLinkType(uint32_t *aLinkType)
 {
   NS_ENSURE_ARG_POINTER(aLinkType);
 
--- a/toolkit/components/alerts/nsAlertsService.cpp
+++ b/toolkit/components/alerts/nsAlertsService.cpp
@@ -5,17 +5,16 @@
 
 #include "mozilla/dom/ContentChild.h"
 #include "nsXULAppAPI.h"
 
 #include "nsAlertsService.h"
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidBridge.h"
-using namespace mozilla::widget::android;
 #else
 
 #include "nsXPCOM.h"
 #include "nsIServiceManager.h"
 #include "nsIDOMWindow.h"
 #include "nsPromiseFlatString.h"
 #include "nsToolkitCompsCID.h"
 
@@ -119,17 +118,17 @@ NS_IMETHODIMP nsAlertsService::CloseAler
 {
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     ContentChild* cpc = ContentChild::GetSingleton();
     cpc->SendCloseAlert(nsAutoString(aAlertName));
     return NS_OK;
   }
 
 #ifdef MOZ_WIDGET_ANDROID
-  GeckoAppShell::CloseNotification(aAlertName);
+  mozilla::AndroidBridge::Bridge()->CloseNotification(aAlertName);
   return NS_OK;
 #else
 
   // Try the system notification service.
   nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID));
   if (sysAlerts) {
     return sysAlerts->CloseAlert(aAlertName);
   }
@@ -140,24 +139,24 @@ NS_IMETHODIMP nsAlertsService::CloseAler
 
 
 NS_IMETHODIMP nsAlertsService::OnProgress(const nsAString & aAlertName,
                                           int64_t aProgress,
                                           int64_t aProgressMax,
                                           const nsAString & aAlertText)
 {
 #ifdef MOZ_WIDGET_ANDROID
-  GeckoAppShell::AlertsProgressListener_OnProgress(aAlertName, aProgress, aProgressMax, aAlertText);
+  mozilla::AndroidBridge::Bridge()->AlertsProgressListener_OnProgress(aAlertName, aProgress, aProgressMax, aAlertText);
   return NS_OK;
 #else
   return NS_ERROR_NOT_IMPLEMENTED;
 #endif // !MOZ_WIDGET_ANDROID
 }
 
 NS_IMETHODIMP nsAlertsService::OnCancel(const nsAString & aAlertName)
 {
 #ifdef MOZ_WIDGET_ANDROID
-  GeckoAppShell::CloseNotification(aAlertName);
+  mozilla::AndroidBridge::Bridge()->CloseNotification(aAlertName);
   return NS_OK;
 #else
   return NS_ERROR_NOT_IMPLEMENTED;
 #endif // !MOZ_WIDGET_ANDROID
 }
--- a/toolkit/components/downloads/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/nsDownloadManager.cpp
@@ -46,17 +46,16 @@
 #endif
 
 #ifdef XP_MACOSX
 #include <CoreFoundation/CoreFoundation.h>
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidBridge.h"
-using namespace mozilla::widget::android;
 #endif
 
 #ifdef MOZ_WIDGET_GTK
 #include <gtk/gtk.h>
 #endif
 
 using namespace mozilla;
 using mozilla::downloads::GenerateGUID;
@@ -2771,17 +2770,17 @@ nsDownload::SetState(DownloadState aStat
 #ifdef MOZ_WIDGET_ANDROID
         nsCOMPtr<nsIMIMEInfo> mimeInfo;
         nsAutoCString contentType;
         GetMIMEInfo(getter_AddRefs(mimeInfo));
 
         if (mimeInfo)
           mimeInfo->GetMIMEType(contentType);
 
-        GeckoAppShell::ScanMedia(path, NS_ConvertUTF8toUTF16(contentType));
+        mozilla::AndroidBridge::Bridge()->ScanMedia(path, NS_ConvertUTF8toUTF16(contentType));
 #endif
       }
 
 #ifdef XP_WIN
       // Adjust file attributes so that by default, new files are indexed
       // by desktop search services. Skip off those that land in the temp
       // folder.
       nsCOMPtr<nsIFile> tempDir, fileDir;
--- a/toolkit/components/jsdownloads/src/DownloadPlatform.cpp
+++ b/toolkit/components/jsdownloads/src/DownloadPlatform.cpp
@@ -113,17 +113,17 @@ nsresult DownloadPlatform::DownloadDone(
                                              kCFStringEncodingUTF8);
     CFNotificationCenterRef center = ::CFNotificationCenterGetDistributedCenter();
     ::CFNotificationCenterPostNotification(center, CFSTR("com.apple.DownloadFileFinished"),
                                            observedObject, NULL, TRUE);
     ::CFRelease(observedObject);
 #endif
 #ifdef MOZ_WIDGET_ANDROID
     if (!aContentType.IsEmpty()) {
-      mozilla::widget::android::GeckoAppShell::ScanMedia(path, NS_ConvertUTF8toUTF16(aContentType));
+      mozilla::AndroidBridge::Bridge()->ScanMedia(path, NS_ConvertUTF8toUTF16(aContentType));
     }
 #endif
   }
 
 #ifdef XP_WIN
   // Adjust file attributes so that by default, new files are indexed by
   // desktop search services. Skip off those that land in the temp folder.
   nsCOMPtr<nsIFile> tempDir, fileDir;
--- a/toolkit/xre/nsAndroidStartup.cpp
+++ b/toolkit/xre/nsAndroidStartup.cpp
@@ -70,14 +70,14 @@ GeckoStart(void *data, const nsXREAppDat
     }
     targs.AppendElement(static_cast<char *>(nullptr));
 
     int result = XRE_main(targs.Length() - 1, targs.Elements(), appData, 0);
 
     if (result)
         LOG("XRE_main returned %d", result);
 
-    mozilla::widget::android::GeckoAppShell::NotifyXreExit();
+    mozilla::AndroidBridge::Bridge()->NotifyXreExit();
 
     free(targs[0]);
     nsMemory::Free(data);
     return;
 }
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -1642,17 +1642,17 @@ static nsresult LaunchChild(nsINativeApp
     gRestartArgc = 1;
     gRestartArgv[gRestartArgc] = nullptr;
 #endif
   }
 
   SaveToEnv("MOZ_LAUNCHED_CHILD=1");
 
 #if defined(MOZ_WIDGET_ANDROID)
-  mozilla::widget::android::GeckoAppShell::ScheduleRestart();
+  mozilla::AndroidBridge::Bridge()->ScheduleRestart();
 #else
 #if defined(XP_MACOSX)
   CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
   uint32_t restartMode = 0;
   restartMode = gRestartMode;
   LaunchChildMac(gRestartArgc, gRestartArgv, restartMode);
 #else
   nsCOMPtr<nsIFile> lf;
@@ -1754,17 +1754,17 @@ ProfileLockedDialog(nsIFile* aProfileDir
 
     nsCOMPtr<nsIPromptService> ps
       (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
     NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
 
     if (aUnlocker) {
       int32_t button;
 #ifdef MOZ_WIDGET_ANDROID
-      mozilla::widget::android::GeckoAppShell::KillAnyZombies();
+      mozilla::AndroidBridge::Bridge()->KillAnyZombies();
       button = 1;
 #else
       const uint32_t flags =
         (nsIPromptService::BUTTON_TITLE_CANCEL * 
          nsIPromptService::BUTTON_POS_0) +
         (nsIPromptService::BUTTON_TITLE_IS_STRING * 
          nsIPromptService::BUTTON_POS_1) +
         nsIPromptService::BUTTON_POS_1_DEFAULT;
@@ -1781,17 +1781,17 @@ ProfileLockedDialog(nsIFile* aProfileDir
         if (NS_FAILED(rv)) 
           return rv;
 
         return NS_LockProfilePath(aProfileDir, aProfileLocalDir, 
                                   nullptr, aResult);
       }
     } else {
 #ifdef MOZ_WIDGET_ANDROID
-      if (mozilla::widget::android::GeckoAppShell::UnlockProfile()) {
+      if (mozilla::AndroidBridge::Bridge()->UnlockProfile()) {
         return NS_LockProfilePath(aProfileDir, aProfileLocalDir, 
                                   nullptr, aResult);
       }
 #else
       rv = ps->Alert(nullptr, killTitle, killMessage);
       NS_ENSURE_SUCCESS_LOG(rv, rv);
 #endif
     }
--- a/tools/profiler/TableTicker.cpp
+++ b/tools/profiler/TableTicker.cpp
@@ -225,17 +225,17 @@ typename Builder::Object BuildJavaThread
         break;
       }
       if (!sample) {
         sample = b.CreateObject();
         frames = b.CreateArray();
         b.DefineProperty(sample, "frames", frames);
         b.ArrayPush(samples, sample);
 
-        double sampleTime = GeckoJavaSampler::GetSampleTimeJavaProfiling(0, sampleId);
+        double sampleTime = AndroidBridge::Bridge()->GetSampleTimeJavaProfiling(0, sampleId);
         b.DefineProperty(sample, "time", sampleTime);
       }
       typename Builder::RootedObject frame(b.context(), b.CreateObject());
       b.DefineProperty(frame, "location", result.BeginReading());
       b.ArrayPush(frames, frame);
       frameId++;
     }
     if (frameId == 0) {
@@ -277,22 +277,22 @@ void TableTicker::BuildJSObject(Builder&
       typename Builder::RootedObject threadSamples(b.context(), b.CreateObject());
       sRegisteredThreads->at(i)->Profile()->BuildJSObject(b, threadSamples);
       b.ArrayPush(threads, threadSamples);
     }
   }
 
 #if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
   if (ProfileJava()) {
-    GeckoJavaSampler::PauseJavaProfiling();
+    AndroidBridge::Bridge()->PauseJavaProfiling();
 
     typename Builder::RootedObject javaThread(b.context(), BuildJavaThreadJSObject(b));
     b.ArrayPush(threads, javaThread);
 
-    GeckoJavaSampler::UnpauseJavaProfiling();
+    AndroidBridge::Bridge()->UnpauseJavaProfiling();
   }
 #endif
 
   SetPaused(false);
 
   // Send a event asking any subprocesses (plugins) to
   // give us their information
   SubprocessClosure<Builder> closure(&b, threads);
--- a/tools/profiler/platform.cpp
+++ b/tools/profiler/platform.cpp
@@ -22,17 +22,16 @@
 #include "nsDirectoryServiceUtils.h"
 #include "nsDirectoryServiceDefs.h"
 #include "mozilla/Services.h"
 #include "nsThreadUtils.h"
 #include "ProfilerMarkers.h"
 
 #if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
   #include "AndroidBridge.h"
-  using namespace mozilla::widget::android;
 #endif
 
 mozilla::ThreadLocal<PseudoStack *> tlsPseudoStack;
 mozilla::ThreadLocal<TableTicker *> tlsTicker;
 mozilla::ThreadLocal<void *> tlsStackTop;
 // We need to track whether we've been initialized otherwise
 // we end up using tlsStack without initializing it.
 // Because tlsStack is totally opaque to us we can't reuse
@@ -594,17 +593,17 @@ void mozilla_sampler_start(int aProfileE
 
 #if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
   if (t->ProfileJava()) {
     int javaInterval = aInterval;
     // Java sampling doesn't accuratly keep up with 1ms sampling
     if (javaInterval < 10) {
       aInterval = 10;
     }
-    GeckoJavaSampler::StartJavaProfiling(javaInterval, 1000);
+    mozilla::AndroidBridge::Bridge()->StartJavaProfiling(javaInterval, 1000);
   }
 #endif
 
   if (t->AddMainThreadIO()) {
     if (!sInterposeObserver) {
       // Lazily create IO interposer observer
       sInterposeObserver = new mozilla::ProfilerIOInterposeObserver();
     }
--- a/uriloader/exthandler/android/nsAndroidHandlerApp.cpp
+++ b/uriloader/exthandler/android/nsAndroidHandlerApp.cpp
@@ -1,18 +1,16 @@
 /* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsAndroidHandlerApp.h"
 #include "AndroidBridge.h"
 
-using namespace mozilla::widget::android;
-
 
 NS_IMPL_ISUPPORTS2(nsAndroidHandlerApp, nsIHandlerApp, nsISharingHandlerApp)
 
 nsAndroidHandlerApp::nsAndroidHandlerApp(const nsAString& aName,
                                          const nsAString& aDescription,
                                          const nsAString& aPackageName,
                                          const nsAString& aClassName,
                                          const nsACString& aMimeType,
@@ -62,21 +60,29 @@ nsAndroidHandlerApp::Equals(nsIHandlerAp
   *aRetval = aApp && aApp->mName.Equals(mName) &&
     aApp->mDescription.Equals(mDescription);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAndroidHandlerApp::LaunchWithURI(nsIURI *aURI, nsIInterfaceRequestor *aWindowContext)
 {
+  if (!mozilla::AndroidBridge::Bridge())
+    return NS_ERROR_FAILURE;
+
   nsCString uriSpec;
   aURI->GetSpec(uriSpec);
-  return GeckoAppShell::OpenUriExternal(NS_ConvertUTF8toUTF16(uriSpec), NS_ConvertUTF8toUTF16(mMimeType), mPackageName, mClassName, mAction) ? 
+  return mozilla::AndroidBridge::Bridge()->
+    OpenUriExternal(NS_ConvertUTF8toUTF16(uriSpec), NS_ConvertUTF8toUTF16(mMimeType), mPackageName, mClassName, mAction) ? 
     NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsAndroidHandlerApp::Share(const nsAString & data, const nsAString & title)
 {
-  return GeckoAppShell::OpenUriExternal(data, NS_ConvertUTF8toUTF16(mMimeType), mPackageName, 
+  if (!mozilla::AndroidBridge::Bridge())
+    return NS_ERROR_FAILURE;
+
+  return mozilla::AndroidBridge::Bridge()->
+    OpenUriExternal(data, NS_ConvertUTF8toUTF16(mMimeType), mPackageName, 
                     mClassName, mAction) ? NS_OK : NS_ERROR_FAILURE;
 }
 
--- a/uriloader/exthandler/android/nsExternalSharingAppService.cpp
+++ b/uriloader/exthandler/android/nsExternalSharingAppService.cpp
@@ -26,17 +26,22 @@ nsExternalSharingAppService::~nsExternal
 
 NS_IMETHODIMP
 nsExternalSharingAppService::ShareWithDefault(const nsAString & data,
                                               const nsAString & mime,
                                               const nsAString & title)
 {
   NS_NAMED_LITERAL_STRING(sendAction, "android.intent.action.SEND");
   const nsString emptyString = EmptyString();
-  return GeckoAppShell::OpenUriExternal(data, mime, emptyString,emptyString, sendAction, title) ? NS_OK : NS_ERROR_FAILURE;
+  if (AndroidBridge::Bridge())
+    return AndroidBridge::Bridge()->
+      OpenUriExternal(data, mime,
+                      emptyString,emptyString, sendAction, title) ? NS_OK : NS_ERROR_FAILURE;
+
+  return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsExternalSharingAppService::GetSharingApps(const nsAString & aMIMEType,
                                             uint32_t *aLen,
                                             nsISharingHandlerApp ***aHandlers)
 {
   nsresult rv;
--- a/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp
+++ b/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp
@@ -5,18 +5,16 @@
 #include "nsMIMEInfoAndroid.h"
 #include "AndroidBridge.h"
 #include "nsAndroidHandlerApp.h"
 #include "nsArrayUtils.h"
 #include "nsISupportsUtils.h"
 #include "nsStringEnumerator.h"
 #include "nsNetUtil.h"
 
-using namespace mozilla::widget::android;
-
 NS_IMPL_ISUPPORTS2(nsMIMEInfoAndroid, nsIMIMEInfo, nsIHandlerInfo)
 
 NS_IMETHODIMP
 nsMIMEInfoAndroid::LaunchDefaultWithFile(nsIFile* aFile)
 {
   LaunchWithFile(aFile);
   return NS_OK;
 }
@@ -25,17 +23,21 @@ NS_IMETHODIMP
 nsMIMEInfoAndroid::LoadUriInternal(nsIURI * aURI)
 {
   nsCString uriSpec;
   aURI->GetSpec(uriSpec);
 
   nsCString uriScheme;
   aURI->GetScheme(uriScheme);
 
-  return GeckoAppShell::OpenUriExternal(NS_ConvertUTF8toUTF16(uriSpec), (mType.Equals(uriScheme) || mType.Equals(uriSpec)) ? EmptyString() : NS_ConvertUTF8toUTF16(mType)) ? NS_OK : NS_ERROR_FAILURE;
+  if (mozilla::AndroidBridge::Bridge())
+    return mozilla::AndroidBridge::Bridge()->
+      OpenUriExternal(NS_ConvertUTF8toUTF16(uriSpec), (mType.Equals(uriScheme) || mType.Equals(uriSpec)) ? EmptyString() : NS_ConvertUTF8toUTF16(mType)) ? NS_OK : NS_ERROR_FAILURE;
+
+  return NS_ERROR_FAILURE;
 }
 
 
 bool
 nsMIMEInfoAndroid::GetMimeInfoForMimeType(const nsACString& aMimeType,
                                           nsMIMEInfoAndroid** aMimeInfo)
 {
   nsRefPtr<nsMIMEInfoAndroid> info = new nsMIMEInfoAndroid(aMimeType);
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -32,18 +32,23 @@
 #include "nsPIDOMWindow.h"
 #include "mozilla/dom/ScreenOrientation.h"
 #include "nsIDOMWindowUtils.h"
 #include "nsIDOMClientRect.h"
 #include "StrongPointer.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "nsPrintfCString.h"
 
+#ifdef DEBUG
+#define ALOG_BRIDGE(args...) ALOG(args)
+#else
+#define ALOG_BRIDGE(args...) ((void)0)
+#endif
+
 using namespace mozilla;
-using namespace mozilla::widget::android;
 
 NS_IMPL_ISUPPORTS0(nsFilePickerCallback)
 
 StaticRefPtr<AndroidBridge> AndroidBridge::sBridge;
 static unsigned sJavaEnvThreadIndex = 0;
 static jobject sGlobalContext = nullptr;
 static void JavaThreadDetachFunc(void *arg);
 
@@ -157,23 +162,24 @@ AndroidBridge::Init(JNIEnv *jEnv)
 {
     ALOG_BRIDGE("AndroidBridge::Init");
     jEnv->GetJavaVM(&mJavaVM);
 
     AutoLocalJNIFrame jniFrame(jEnv);
 
     mJNIEnv = nullptr;
     mThread = -1;
-    mGLControllerObj = NULL;
+    mGLControllerObj = nullptr;
     mOpenedGraphicsLibraries = false;
     mHasNativeBitmapAccess = false;
     mHasNativeWindowAccess = false;
     mHasNativeWindowFallback = false;
 
     initInit();
+    InitStubs(jEnv);
 
 #ifdef MOZ_WEBSMS_BACKEND
     mAndroidSmsMessageClass = getClassGlobalRef("android/telephony/SmsMessage");
     jCalculateLength = getStaticMethod("calculateLength", "(Ljava/lang/CharSequence;Z)[I");
 #endif
 
     jStringClass = getClassGlobalRef("java/lang/String");
 
@@ -261,62 +267,16 @@ jstring AndroidBridge::NewJavaString(Aut
 jstring AndroidBridge::NewJavaString(AutoLocalJNIFrame* frame, const char* string) {
     return NewJavaString(frame, NS_ConvertUTF8toUTF16(string));
 }
 
 jstring AndroidBridge::NewJavaString(AutoLocalJNIFrame* frame, const nsACString& string) {
     return NewJavaString(frame, NS_ConvertUTF8toUTF16(string));
 }
 
-extern "C" {
-    __attribute__ ((visibility("default")))
-    JNIEnv * GetJNIForThread()
-    {
-        JNIEnv *jEnv = NULL;
-        JavaVM *jVm  = mozilla::AndroidBridge::GetVM();
-        if (!jVm) {
-            __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread", "Returned a null VM");
-            return NULL;
-        }
-        jEnv = static_cast<JNIEnv*>(PR_GetThreadPrivate(sJavaEnvThreadIndex));
-
-        if (jEnv)
-            return jEnv;
-
-        int status = jVm->GetEnv((void**) &jEnv, JNI_VERSION_1_2);
-        if (status) {
-
-            status = jVm->AttachCurrentThread(&jEnv, NULL);
-            if (status) {
-                __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread",  "Could not attach");
-                return NULL;
-            }
-
-            PR_SetThreadPrivate(sJavaEnvThreadIndex, jEnv);
-        }
-        if (!jEnv) {
-            __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread", "returning NULL");
-        }
-        return jEnv;
-    }
-}
-
-void AutoGlobalWrappedJavaObject::Dispose() {
-    if (isNull()) {
-        return;
-    }
-
-    GetJNIForThread()->DeleteGlobalRef(wrapped_obj);
-    wrapped_obj = NULL;
-}
-
-AutoGlobalWrappedJavaObject::~AutoGlobalWrappedJavaObject() {
-    Dispose();
-}
-
 static void
 getHandlersFromStringArray(JNIEnv *aJNIEnv, jobjectArray jArr, jsize aLen,
                            nsIMutableArray *aHandlersArray,
                            nsIHandlerApp **aDefaultApp,
                            const nsAString& aAction = EmptyString(),
                            const nsACString& aMimeType = EmptyCString())
 {
     nsString empty = EmptyString();
@@ -346,17 +306,17 @@ AndroidBridge::GetHandlersForMimeType(co
                                       const nsAString& aAction)
 {
     ALOG_BRIDGE("AndroidBridge::GetHandlersForMimeType");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return false;
 
-    jobjectArray arr = GeckoAppShell::GetHandlersForMimeTypeWrapper(aMimeType, aAction);
+    jobjectArray arr = GetHandlersForMimeTypeWrapper(aMimeType, aAction);
     if (!arr)
         return false;
 
     jsize len = env->GetArrayLength(arr);
 
     if (!aHandlersArray)
         return len > 0;
 
@@ -375,17 +335,17 @@ AndroidBridge::GetHandlersForURL(const n
                                  const nsAString& aAction)
 {
     ALOG_BRIDGE("AndroidBridge::GetHandlersForURL");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return false;
 
-    jobjectArray arr = GeckoAppShell::GetHandlersForURLWrapper(aURL, aAction);
+    jobjectArray arr = GetHandlersForURLWrapper(aURL, aAction);
     if (!arr)
         return false;
 
     jsize len = env->GetArrayLength(arr);
 
     if (!aHandlersArray)
         return len > 0;
 
@@ -400,17 +360,17 @@ void
 AndroidBridge::GetMimeTypeFromExtensions(const nsACString& aFileExt, nsCString& aMimeType)
 {
     ALOG_BRIDGE("AndroidBridge::GetMimeTypeFromExtensions");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
-    jstring jstrType = GeckoAppShell::GetMimeTypeFromExtensionsWrapper(NS_ConvertUTF8toUTF16(aFileExt));
+    jstring jstrType = GetMimeTypeFromExtensionsWrapper(NS_ConvertUTF8toUTF16(aFileExt));
     if (!jstrType) {
         return;
     }
     nsJNIString jniStr(jstrType, env);
     CopyUTF16toUTF8(jniStr.get(), aMimeType);
 
     env->DeleteLocalRef(jstrType);
 }
@@ -419,17 +379,17 @@ void
 AndroidBridge::GetExtensionFromMimeType(const nsACString& aMimeType, nsACString& aFileExt)
 {
     ALOG_BRIDGE("AndroidBridge::GetExtensionFromMimeType");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
-    jstring jstrExt = GeckoAppShell::GetExtensionFromMimeTypeWrapper(NS_ConvertUTF8toUTF16(aMimeType));
+    jstring jstrExt = GetExtensionFromMimeTypeWrapper(NS_ConvertUTF8toUTF16(aMimeType));
     if (!jstrExt) {
         return;
     }
     nsJNIString jniStr(jstrExt, env);
     CopyUTF16toUTF8(jniStr.get(), aFileExt);
 
     env->DeleteLocalRef(jstrExt);
 }
@@ -438,53 +398,83 @@ bool
 AndroidBridge::GetClipboardText(nsAString& aText)
 {
     ALOG_BRIDGE("AndroidBridge::GetClipboardText");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return false;
 
-    jstring result = Clipboard::GetClipboardTextWrapper();
+    jstring result = GetClipboardTextWrapper();
     if (!result)
         return false;
 
     nsJNIString jniStr(result, env);
     aText.Assign(jniStr);
 
     env->DeleteLocalRef(result);
     return true;
 }
 
+bool
+AndroidBridge::ClipboardHasText()
+{
+    ALOG_BRIDGE("AndroidBridge::ClipboardHasText");
+
+    JNIEnv *env = GetJNIEnv();
+    if (!env)
+        return false;
+
+    AutoLocalJNIFrame jniFrame(env);
+
+    jstring jStr = GetClipboardTextWrapper();
+    bool ret = jStr;
+
+    return ret;
+}
+
+void
+AndroidBridge::EmptyClipboard()
+{
+    ALOG_BRIDGE("AndroidBridge::EmptyClipboard");
+
+    JNIEnv *env = GetJNIEnv();
+    if (!env)
+        return;
+
+    AutoLocalJNIFrame jniFrame(env, 0);
+    env->CallStaticVoidMethod(mClipboardClass, jSetClipboardText, nullptr);
+}
+
 void
 AndroidBridge::ShowAlertNotification(const nsAString& aImageUrl,
                                      const nsAString& aAlertTitle,
                                      const nsAString& aAlertText,
                                      const nsAString& aAlertCookie,
                                      nsIObserver *aAlertListener,
                                      const nsAString& aAlertName)
 {
     if (nsAppShell::gAppShell && aAlertListener) {
         // This will remove any observers already registered for this id
         nsAppShell::gAppShell->PostEvent(AndroidGeckoEvent::MakeAddObserver(aAlertName, aAlertListener));
     }
 
-    GeckoAppShell::ShowAlertNotificationWrapper(aImageUrl, aAlertTitle, aAlertText, aAlertCookie, aAlertName);
+    ShowAlertNotificationWrapper(aImageUrl, aAlertTitle, aAlertText, aAlertCookie, aAlertName);
 }
 
 int
 AndroidBridge::GetDPI()
 {
     static int sDPI = 0;
     if (sDPI)
         return sDPI;
 
     const int DEFAULT_DPI = 160;
 
-    sDPI = GeckoAppShell::GetDpiWrapper();
+    sDPI = GetDpiWrapper();
     if (!sDPI) {
         return DEFAULT_DPI;
     }
 
     return sDPI;
 }
 
 int
@@ -493,60 +483,72 @@ AndroidBridge::GetScreenDepth()
     ALOG_BRIDGE("%s", __PRETTY_FUNCTION__);
 
     static int sDepth = 0;
     if (sDepth)
         return sDepth;
 
     const int DEFAULT_DEPTH = 16;
 
-    sDepth = GeckoAppShell::GetScreenDepthWrapper();
+    sDepth = GetScreenDepthWrapper();
     if (!sDepth)
         return DEFAULT_DEPTH;
 
     return sDepth;
 }
 
 void
 AndroidBridge::ShowFilePickerForExtensions(nsAString& aFilePath, const nsAString& aExtensions)
 {
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
-    jstring jstr = GeckoAppShell::ShowFilePickerForExtensionsWrapper(aExtensions);
+    jstring jstr = ShowFilePickerForExtensionsWrapper(aExtensions);
     if (jstr == nullptr) {
         return;
     }
 
     aFilePath.Assign(nsJNIString(jstr, env));
     env->DeleteLocalRef(jstr);
 }
 
 void
 AndroidBridge::ShowFilePickerForMimeType(nsAString& aFilePath, const nsAString& aMimeType)
 {
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
-    jstring jstr = GeckoAppShell::ShowFilePickerForMimeTypeWrapper(aMimeType);
+    jstring jstr = ShowFilePickerForMimeTypeWrapper(aMimeType);
     if (jstr == nullptr) {
         return;
     }
 
     aFilePath.Assign(nsJNIString(jstr, env));
     env->DeleteLocalRef(jstr);
 }
 
 void
 AndroidBridge::ShowFilePickerAsync(const nsAString& aMimeType, nsFilePickerCallback* callback)
 {
     callback->AddRef();
-    GeckoAppShell::ShowFilePickerAsyncWrapper(aMimeType, (int64_t) callback);
+    ShowFilePickerAsyncWrapper(aMimeType, (int64_t) callback);
+}
+
+void
+AndroidBridge::HideProgressDialogOnce()
+{
+    static bool once = false;
+    if (once)
+        return;
+
+    HideProgressDialog();
+
+    once = true;
 }
 
 void
 AndroidBridge::Vibrate(const nsTArray<uint32_t>& aPattern)
 {
     ALOG_BRIDGE("%s", __PRETTY_FUNCTION__);
 
     uint32_t len = aPattern.Length();
@@ -564,17 +566,17 @@ AndroidBridge::Vibrate(const nsTArray<ui
     // It's clear if this worth special-casing, but it creates less
     // java junk, so dodges the GC.
     if (len == 1) {
         jlong d = aPattern[0];
         if (d < 0) {
             ALOG_BRIDGE("  invalid vibration duration < 0");
             return;
         }
-        GeckoAppShell::Vibrate1(d);
+        Vibrate1(d);
         return;
     }
 
     // First element of the array vibrate() expects is how long to wait
     // *before* vibrating.  For us, this is always 0.
 
     jlongArray array = env->NewLongArray(len + 1);
     if (!array) {
@@ -590,34 +592,34 @@ AndroidBridge::Vibrate(const nsTArray<ui
             ALOG_BRIDGE("  invalid vibration duration < 0");
             env->ReleaseLongArrayElements(array, elts, JNI_ABORT);
             return;
         }
         elts[i + 1] = d;
     }
     env->ReleaseLongArrayElements(array, elts, 0);
 
-    GeckoAppShell::VibrateA(array, -1/*don't repeat*/);
+    VibrateA(array, -1/*don't repeat*/);
 }
 
 void
 AndroidBridge::GetSystemColors(AndroidSystemColors *aColors)
 {
 
     NS_ASSERTION(aColors != nullptr, "AndroidBridge::GetSystemColors: aColors is null!");
     if (!aColors)
         return;
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
     AutoLocalJNIFrame jniFrame(env);
 
-    jintArray arr = GeckoAppShell::GetSystemColoursWrapper();
+    jintArray arr = GetSystemColoursWrapper();
     if (!arr)
         return;
 
     uint32_t len = static_cast<uint32_t>(env->GetArrayLength(arr));
     jint *elements = env->GetIntArrayElements(arr, 0);
 
     uint32_t colorsCount = sizeof(AndroidSystemColors) / sizeof(nscolor);
     if (len < colorsCount)
@@ -645,17 +647,17 @@ AndroidBridge::GetIconForExtension(const
         return;
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
     AutoLocalJNIFrame jniFrame(env);
 
-    jbyteArray arr = GeckoAppShell::GetIconForExtensionWrapper(NS_ConvertUTF8toUTF16(aFileExt), aIconSize);
+    jbyteArray arr = GetIconForExtensionWrapper(NS_ConvertUTF8toUTF16(aFileExt), aIconSize);
 
     NS_ASSERTION(arr != nullptr, "AndroidBridge::GetIconForExtension: Returned pixels array is null!");
     if (!arr)
         return;
 
     uint32_t len = static_cast<uint32_t>(env->GetArrayLength(arr));
     jbyte *elements = env->GetByteArrayElements(arr, 0);
 
@@ -673,60 +675,72 @@ AndroidBridge::SetLayerClient(JNIEnv* en
     // if resetting is true, that means Android destroyed our GeckoApp activity
     // and we had to recreate it, but all the Gecko-side things were not destroyed.
     // We therefore need to link up the new java objects to Gecko, and that's what
     // we do here.
     bool resetting = (mLayerClient != NULL);
 
     if (resetting) {
         // clear out the old layer client
+        env->DeleteGlobalRef(mLayerClient->wrappedObject());
         delete mLayerClient;
         mLayerClient = NULL;
     }
 
-    mLayerClient = GeckoLayerClient::Wrap(jobj);
+    AndroidGeckoLayerClient *client = new AndroidGeckoLayerClient();
+    client->Init(env->NewGlobalRef(jobj));
+    mLayerClient = client;
 
     if (resetting) {
         // since we are re-linking the new java objects to Gecko, we need to get
         // the viewport from the compositor (since the Java copy was thrown away)
         // and we do that by setting the first-paint flag.
         nsWindow::ForceIsFirstPaint();
     }
 }
 
 void
 AndroidBridge::RegisterCompositor(JNIEnv *env)
 {
-    if (mGLControllerObj != NULL && !mGLControllerObj->isNull()) {
+    ALOG_BRIDGE("AndroidBridge::RegisterCompositor");
+    if (mGLControllerObj) {
         // we already have this set up, no need to do it again
         return;
     }
 
-    jobject glController = LayerView::RegisterCompositorWrapper();
+    if (!env) {
+        env = GetJNIForThread();    // called on the compositor thread
+    }
+    if (!env) {
+        return;
+    }
+
+    jobject glController = RegisterCompositorWrapper();
     if (!glController) {
         return;
     }
 
-    mGLControllerObj = GLController::Wrap(glController);
+    mGLControllerObj = env->NewGlobalRef(glController);
+    env->DeleteLocalRef(glController);
 }
 
 EGLSurface
 AndroidBridge::ProvideEGLSurface()
 {
     if (!jEGLSurfacePointerField) {
         return NULL;
     }
     MOZ_ASSERT(mGLControllerObj, "AndroidBridge::ProvideEGLSurface called with a null GL controller ref");
 
     JNIEnv* env = GetJNIForThread(); // called on the compositor thread
     if (!env) {
         return NULL;
     }
 
-    jobject eglSurface = mGLControllerObj->ProvideEGLSurfaceWrapper();
+    jobject eglSurface = ProvideEGLSurfaceWrapper(mGLControllerObj);
     if (!eglSurface)
         return NULL;
 
     EGLSurface ret = reinterpret_cast<EGLSurface>(env->GetIntField(eglSurface, jEGLSurfacePointerField));
     env->DeleteLocalRef(eglSurface);
     return ret;
 }
 
@@ -788,16 +802,21 @@ AndroidBridge::GetStaticStringField(cons
 
 // Available for places elsewhere in the code to link to.
 bool
 mozilla_AndroidBridge_SetMainThread(pthread_t thr)
 {
     return AndroidBridge::Bridge()->SetMainThread(thr);
 }
 
+jclass GetGeckoAppShellClass()
+{
+    return mozilla::AndroidBridge::GetGeckoAppShellClass();
+}
+
 void*
 AndroidBridge::GetNativeSurface(JNIEnv* env, jobject surface) {
     if (!env || !mHasNativeWindowFallback || !jSurfacePointerField)
         return nullptr;
 
     return (void*)env->GetIntField(surface, jSurfacePointerField);
 }
 
@@ -984,17 +1003,17 @@ AndroidBridge::ValidateBitmap(jobject bi
 bool
 AndroidBridge::InitCamera(const nsCString& contentType, uint32_t camera, uint32_t *width, uint32_t *height, uint32_t *fps)
 {
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return false;
 
     AutoLocalJNIFrame jniFrame(env);
-    jintArray arr = GeckoAppShell::InitCameraWrapper(NS_ConvertUTF8toUTF16(contentType), (int32_t) camera, (int32_t) width, (int32_t) height);
+    jintArray arr = InitCameraWrapper(NS_ConvertUTF8toUTF16(contentType), (int32_t) camera, (int32_t) width, (int32_t) height);
 
     if (!arr)
         return false;
 
     jint *elements = env->GetIntArrayElements(arr, 0);
 
     *width = elements[1];
     *height = elements[2];
@@ -1015,17 +1034,17 @@ AndroidBridge::GetCurrentBatteryInformat
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
     AutoLocalJNIFrame jniFrame(env);
 
     // To prevent calling too many methods through JNI, the Java method returns
     // an array of double even if we actually want a double and a boolean.
-    jdoubleArray arr = GeckoAppShell::GetCurrentBatteryInformationWrapper();
+    jdoubleArray arr = GetCurrentBatteryInformationWrapper();
     if (!arr || env->GetArrayLength(arr) != 3) {
         return;
     }
 
     jdouble* info = env->GetDoubleArrayElements(arr, 0);
 
     aBatteryInfo->level() = info[0];
     aBatteryInfo->charging() = info[1] == 1.0f;
@@ -1039,17 +1058,17 @@ AndroidBridge::HandleGeckoMessage(const 
 {
     ALOG_BRIDGE("%s", __PRETTY_FUNCTION__);
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
     AutoLocalJNIFrame jniFrame(env);
-    jstring returnMessage = GeckoAppShell::HandleGeckoMessageWrapper(aMessage);
+    jstring returnMessage = HandleGeckoMessageWrapper(aMessage);
 
     if (!returnMessage)
         return;
 
     nsJNIString jniStr(returnMessage, env);
     aRet.Assign(jniStr);
     ALOG_BRIDGE("leaving %s", __PRETTY_FUNCTION__);
 }
@@ -1106,41 +1125,41 @@ AndroidBridge::SendMessage(const nsAStri
                            nsIMobileMessageCallback* aRequest)
 {
     ALOG_BRIDGE("AndroidBridge::SendMessage");
 
     uint32_t requestId;
     if (!QueueSmsRequest(aRequest, &requestId))
         return;
 
-    GeckoAppShell::SendMessageWrapper(aNumber, aMessage, requestId);
+    SendMessageWrapper(aNumber, aMessage, requestId);
 }
 
 void
 AndroidBridge::GetMessage(int32_t aMessageId, nsIMobileMessageCallback* aRequest)
 {
     ALOG_BRIDGE("AndroidBridge::GetMessage");
 
     uint32_t requestId;
     if (!QueueSmsRequest(aRequest, &requestId))
         return;
 
-    GeckoAppShell::GetMessageWrapper(aMessageId, requestId);
+    GetMessageWrapper(aMessageId, requestId);
 }
 
 void
 AndroidBridge::DeleteMessage(int32_t aMessageId, nsIMobileMessageCallback* aRequest)
 {
     ALOG_BRIDGE("AndroidBridge::DeleteMessage");
 
     uint32_t requestId;
     if (!QueueSmsRequest(aRequest, &requestId))
         return;
 
-    GeckoAppShell::DeleteMessageWrapper(aMessageId, requestId);
+    DeleteMessageWrapper(aMessageId, requestId);
 }
 
 void
 AndroidBridge::CreateMessageList(const dom::mobilemessage::SmsFilterData& aFilter, bool aReverse,
                                  nsIMobileMessageCallback* aRequest)
 {
     ALOG_BRIDGE("AndroidBridge::CreateMessageList");
 
@@ -1159,31 +1178,31 @@ AndroidBridge::CreateMessageList(const d
                                           jStringClass,
                                           NewJavaString(&jniFrame, EmptyString()));
 
     for (uint32_t i = 0; i < aFilter.numbers().Length(); ++i) {
         env->SetObjectArrayElement(numbers, i,
                                    NewJavaString(&jniFrame, aFilter.numbers()[i]));
     }
 
-    GeckoAppShell::CreateMessageListWrapper(aFilter.startDate(), aFilter.endDate(),
+    CreateMessageListWrapper(aFilter.startDate(), aFilter.endDate(),
                              numbers, aFilter.numbers().Length(),
                              aFilter.delivery(), aReverse, requestId);
 }
 
 void
 AndroidBridge::GetNextMessageInList(int32_t aListId, nsIMobileMessageCallback* aRequest)
 {
     ALOG_BRIDGE("AndroidBridge::GetNextMessageInList");
 
     uint32_t requestId;
     if (!QueueSmsRequest(aRequest, &requestId))
         return;
 
-    GeckoAppShell::GetNextMessageInListWrapper(aListId, requestId);
+    GetNextMessageInListWrapper(aListId, requestId);
 }
 
 bool
 AndroidBridge::QueueSmsRequest(nsIMobileMessageCallback* aRequest, uint32_t* aRequestIdOut)
 {
     MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
     MOZ_ASSERT(aRequest && aRequestIdOut);
 
@@ -1225,17 +1244,17 @@ AndroidBridge::GetCurrentNetworkInformat
     if (!env)
         return;
 
     AutoLocalJNIFrame jniFrame(env);
 
     // To prevent calling too many methods through JNI, the Java method returns
     // an array of double even if we actually want a double, two booleans, and an integer.
 
-    jdoubleArray arr = GeckoAppShell::GetCurrentNetworkInformationWrapper();
+    jdoubleArray arr = GetCurrentNetworkInformationWrapper();
     if (!arr || env->GetArrayLength(arr) != 4) {
         return;
     }
 
     jdouble* info = env->GetDoubleArrayElements(arr, 0);
 
     aNetworkInfo->bandwidth() = info[0];
     aNetworkInfo->canBeMetered() = info[1] == 1.0f;
@@ -1418,17 +1437,17 @@ jobject
 AndroidBridge::GetGlobalContextRef() {
     if (sGlobalContext == nullptr) {
         JNIEnv *env = GetJNIForThread();
         if (!env)
             return 0;
 
         AutoLocalJNIFrame jniFrame(env, 4);
 
-        jobject context = GeckoAppShell::GetContext();
+        jobject context = GetContext();
         if (!context) {
             ALOG_BRIDGE("%s: Could not GetContext()", __FUNCTION__);
             return 0;
         }
         jclass contextClass = env->FindClass("android/content/Context");
         if (!contextClass) {
             ALOG_BRIDGE("%s: Could not find Context class.", __FUNCTION__);
             return 0;
@@ -1469,109 +1488,58 @@ AndroidBridge::UnlockWindow(void* window
     }
 
     return true;
 }
 
 void
 AndroidBridge::SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect)
 {
-    GeckoLayerClient *client = mLayerClient;
+    AndroidGeckoLayerClient *client = mLayerClient;
     if (!client)
         return;
 
-    client->SetFirstPaintViewport((float)aOffset.x, (float)aOffset.y, aZoom.scale,
-                                  aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
+    client->SetFirstPaintViewport(aOffset, aZoom, aCssPageRect);
 }
 
 void
 AndroidBridge::SetPageRect(const CSSRect& aCssPageRect)
 {
-    GeckoLayerClient *client = mLayerClient;
+    AndroidGeckoLayerClient *client = mLayerClient;
     if (!client)
         return;
 
-    client->SetPageRect(aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
+    client->SetPageRect(aCssPageRect);
 }
 
 void
 AndroidBridge::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
                                 bool aLayersUpdated, ScreenPoint& aScrollOffset, CSSToScreenScale& aScale,
                                 LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset)
 {
-    ALOG_BRIDGE("Enter: %s", __PRETTY_FUNCTION__);
-    GeckoLayerClient *client = mLayerClient;
-    if (!client) {
-        ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
+    AndroidGeckoLayerClient *client = mLayerClient;
+    if (!client)
         return;
-    }
-
-    jobject viewTransformJObj = client->SyncViewportInfo(aDisplayPort.x, aDisplayPort.y,
-                                aDisplayPort.width, aDisplayPort.height,
-                                aDisplayResolution.scale, aLayersUpdated);
-
-    NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
-    if (!viewTransformJObj) {
-        return;
-    }
 
-    ViewTransform* viewTransform = ViewTransform::Wrap(viewTransformJObj);
-
-    aScrollOffset = ScreenPoint(viewTransform->getx(), viewTransform->gety());
-    aScale.scale = viewTransform->getscale();
-
-    aFixedLayerMargins.top = viewTransform->getfixedLayerMarginTop();
-    aFixedLayerMargins.right = viewTransform->getfixedLayerMarginRight();
-    aFixedLayerMargins.bottom = viewTransform->getfixedLayerMarginBottom();
-    aFixedLayerMargins.left = viewTransform->getfixedLayerMarginLeft();
-
-    aOffset.x = viewTransform->getoffsetX();
-    aOffset.y = viewTransform->getoffsetY();
-
-    delete viewTransform;
-    ALOG_BRIDGE("Exit: %s", __PRETTY_FUNCTION__);
+    client->SyncViewportInfo(aDisplayPort, aDisplayResolution, aLayersUpdated,
+                             aScrollOffset, aScale, aFixedLayerMargins,
+                             aOffset);
 }
 
 void AndroidBridge::SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect,
                                      bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
                                      bool aIsFirstPaint, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset)
 {
-    ALOG_BRIDGE("Enter: %s", __PRETTY_FUNCTION__);
-    GeckoLayerClient *client = mLayerClient;
-    if (!client) {
-        ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
+    AndroidGeckoLayerClient *client = mLayerClient;
+    if (!client)
         return;
-    }
-
-    // convert the displayport rect from scroll-relative CSS pixels to document-relative device pixels
-    LayerRect dpUnrounded = aDisplayPort * aDisplayResolution;
-    dpUnrounded += LayerPoint::FromUnknownPoint(aScrollOffset.ToUnknownPoint());
-    LayerIntRect dp = gfx::RoundedToInt(dpUnrounded);
-
-    jobject viewTransformJObj = client->SyncFrameMetrics(aScrollOffset.x, aScrollOffset.y, aZoom,
-                                                         aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost(),
-                                                         aLayersUpdated, dp.x, dp.y, dp.width, dp.height, aDisplayResolution.scale,
-                                                         aIsFirstPaint);
 
-    NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
-    if (!viewTransformJObj) {
-        return;
-    }
-    ViewTransform* viewTransform = ViewTransform::Wrap(viewTransformJObj);
-
-    aFixedLayerMargins.top = viewTransform->getfixedLayerMarginTop();
-    aFixedLayerMargins.right = viewTransform->getfixedLayerMarginRight();
-    aFixedLayerMargins.bottom = viewTransform->getfixedLayerMarginBottom();
-    aFixedLayerMargins.left = viewTransform->getfixedLayerMarginLeft();
-
-    aOffset.x = viewTransform->getoffsetX();
-    aOffset.y = viewTransform->getoffsetY();
-
-    delete viewTransform;
-    ALOG_BRIDGE("Exit: %s", __PRETTY_FUNCTION__);
+    client->SyncFrameMetrics(aScrollOffset, aZoom, aCssPageRect,
+                             aLayersUpdated, aDisplayPort, aDisplayResolution,
+                             aIsFirstPaint, aFixedLayerMargins, aOffset);
 }
 
 AndroidBridge::AndroidBridge()
   : mLayerClient(NULL),
     mNativePanZoomController(NULL)
 {
 }
 
@@ -1626,22 +1594,55 @@ static void
 JavaThreadDetachFunc(void *arg)
 {
     JNIEnv *env = (JNIEnv*) arg;
     JavaVM *vm = NULL;
     env->GetJavaVM(&vm);
     vm->DetachCurrentThread();
 }
 
+extern "C" {
+    __attribute__ ((visibility("default")))
+    JNIEnv * GetJNIForThread()
+    {
+        JNIEnv *jEnv = NULL;
+        JavaVM *jVm  = mozilla::AndroidBridge::GetVM();
+        if (!jVm) {
+            __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread", "Returned a null VM");
+            return NULL;
+        }
+        jEnv = static_cast<JNIEnv*>(PR_GetThreadPrivate(sJavaEnvThreadIndex));
+
+        if (jEnv)
+            return jEnv;
+
+        int status = jVm->GetEnv((void**) &jEnv, JNI_VERSION_1_2);
+        if (status) {
+
+            status = jVm->AttachCurrentThread(&jEnv, NULL);
+            if (status) {
+                __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread",  "Could not attach");
+                return NULL;
+            }
+            
+            PR_SetThreadPrivate(sJavaEnvThreadIndex, jEnv);
+        }
+        if (!jEnv) {
+            __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread", "returning NULL");
+        }
+        return jEnv;
+    }
+}
+
 uint32_t
 AndroidBridge::GetScreenOrientation()
 {
     ALOG_BRIDGE("AndroidBridge::GetScreenOrientation");
 
-    int16_t orientation = GeckoAppShell::GetScreenOrientationWrapper();
+    int16_t orientation = GetScreenOrientationWrapper();
 
     if (!orientation)
         return dom::eScreenOrientation_None;
 
     return static_cast<dom::ScreenOrientation>(orientation);
 }
 
 void
@@ -1655,17 +1656,17 @@ AndroidBridge::GetGfxInfoData(nsACString
 {
     ALOG_BRIDGE("AndroidBridge::GetGfxInfoData");
 
     JNIEnv* env = GetJNIEnv();
     if (!env)
         return;
 
     AutoLocalJNIFrame jniFrame(env);
-    jstring jstrRet = GeckoAppShell::GetGfxInfoDataWrapper();
+    jstring jstrRet = GetGfxInfoDataWrapper();
 
     if (!jstrRet)
         return;
 
     nsJNIString jniStr(jstrRet, env);
     CopyUTF16toUTF8(jniStr, aRet);
 }
 
@@ -1676,17 +1677,17 @@ AndroidBridge::GetProxyForURI(const nsAC
                               const int32_t      aPort,
                               nsACString & aResult)
 {
     JNIEnv* env = GetJNIEnv();
     if (!env)
         return NS_ERROR_FAILURE;
 
     AutoLocalJNIFrame jniFrame(env);
-    jstring jstrRet = GeckoAppShell::GetProxyForURIWrapper(NS_ConvertUTF8toUTF16(aSpec),
+    jstring jstrRet = GetProxyForURIWrapper(NS_ConvertUTF8toUTF16(aSpec),
                                             NS_ConvertUTF8toUTF16(aScheme),
                                             NS_ConvertUTF8toUTF16(aHost),
                                             aPort);
 
     if (!jstrRet)
         return NS_ERROR_FAILURE;
 
     nsJNIString jniStr(jstrRet, env);
@@ -1712,34 +1713,34 @@ NS_IMETHODIMP nsAndroidBridge::SetBrowse
 
 void
 AndroidBridge::AddPluginView(jobject view, const LayoutDeviceRect& rect, bool isFullScreen) {
     nsWindow* win = nsWindow::TopWindow();
     if (!win)
         return;
 
     CSSRect cssRect = rect / win->GetDefaultScale();
-    GeckoAppShell::AddPluginViewWrapper(view, cssRect.x, cssRect.y, cssRect.width, cssRect.height, isFullScreen);
+    AddPluginViewWrapper(view, cssRect.x, cssRect.y, cssRect.width, cssRect.height, isFullScreen);
 }
 
 extern "C"
 __attribute__ ((visibility("default")))
 jobject JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(JNIEnv *env, jclass, jlong size);
 
 bool
 AndroidBridge::GetThreadNameJavaProfiling(uint32_t aThreadId, nsCString & aResult)
 {
     JNIEnv* env = GetJNIForThread();
     if (!env)
         return false;
 
     AutoLocalJNIFrame jniFrame(env);
 
-    jstring jstrThreadName = GeckoJavaSampler::GetThreadNameJavaProfilingWrapper(aThreadId);
+    jstring jstrThreadName = GetThreadNameJavaProfilingWrapper(aThreadId);
 
     if (!jstrThreadName)
         return false;
 
     nsJNIString jniStr(jstrThreadName, env);
     CopyUTF16toUTF8(jniStr.get(), aResult);
     return true;
 }
@@ -1749,17 +1750,17 @@ AndroidBridge::GetFrameNameJavaProfiling
                                           uint32_t aFrameId, nsCString & aResult)
 {
     JNIEnv* env = GetJNIForThread();
     if (!env)
         return false;
 
     AutoLocalJNIFrame jniFrame(env);
 
-    jstring jstrSampleName = GeckoJavaSampler::GetFrameNameJavaProfilingWrapper(aThreadId, aSampleId, aFrameId);
+    jstring jstrSampleName = GetFrameNameJavaProfilingWrapper(aThreadId, aSampleId, aFrameId);
 
     if (!jstrSampleName)
         return false;
 
     nsJNIString jniStr(jstrSampleName, env);
     CopyUTF16toUTF8(jniStr.get(), aResult);
     env->DeleteLocalRef(jstrSampleName);
     return true;
@@ -1857,144 +1858,71 @@ nsresult AndroidBridge::CaptureThumbnail
     }
     NS_ENSURE_SUCCESS(rv, rv);
     return NS_OK;
 }
 
 void
 AndroidBridge::GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort)
 {
-
-    ALOG_BRIDGE("Enter: %s", __PRETTY_FUNCTION__);
     JNIEnv* env = GetJNIEnv();
-    if (!env || !mLayerClient || mLayerClient->isNull()) {
-
-        ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
+    if (!env || !mLayerClient)
         return;
-    }
     AutoLocalJNIFrame jniFrame(env, 0);
-
-    float x, y, width, height,
-        pageLeft, pageTop, pageRight, pageBottom,
-        cssPageLeft, cssPageTop, cssPageRight, cssPageBottom,
-        zoom;
-    metrics->GetX(&x);
-    metrics->GetY(&y);
-    metrics->GetWidth(&width);
-    metrics->GetHeight(&height);
-    metrics->GetPageLeft(&pageLeft);
-    metrics->GetPageTop(&pageTop);
-    metrics->GetPageRight(&pageRight);
-    metrics->GetPageBottom(&pageBottom);
-    metrics->GetCssPageLeft(&cssPageLeft);
-    metrics->GetCssPageTop(&cssPageTop);
-    metrics->GetCssPageRight(&cssPageRight);
-    metrics->GetCssPageBottom(&cssPageBottom);
-    metrics->GetZoom(&zoom);
-
-    ImmutableViewportMetrics jmetrics = ImmutableViewportMetrics(pageLeft, pageTop, pageRight, pageBottom,
-                                                                 cssPageLeft, cssPageTop, cssPageRight, cssPageBottom,
-                                                                 x, y, x + width, y + height,
-                                                                 zoom);
-
-    jobject jobj = mLayerClient->GetDisplayPort(aPageSizeUpdate, aIsBrowserContentDisplayed, tabId, jmetrics.wrappedObject());
-    if (!jobj) {
-        ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
-        return;
-    }
-    DisplayPortMetrics* displayPortMetrics = DisplayPortMetrics::Wrap(jobj);
-
-    AndroidRectF rect(env, displayPortMetrics->getMPosition());
-    if (jniFrame.CheckForException()) {
-        ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
-        return;
-    }
-
-    float resolution = displayPortMetrics->getResolution();
-    if (jniFrame.CheckForException()) {
-        ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
-        return;
-    }
-
-    *displayPort = new nsAndroidDisplayport(rect, resolution);
-    (*displayPort)->AddRef();
-
-    delete displayPortMetrics;
-    ALOG_BRIDGE("Exit: %s", __PRETTY_FUNCTION__);
+    mLayerClient->GetDisplayPort(&jniFrame, aPageSizeUpdate, aIsBrowserContentDisplayed, tabId, metrics, displayPort);
 }
 
 void
 AndroidBridge::ContentDocumentChanged()
 {
-    if (!mLayerClient) {
+    JNIEnv* env = GetJNIEnv();
+    if (!env || !mLayerClient)
         return;
-    }
-    mLayerClient->ContentDocumentChanged();
+    AutoLocalJNIFrame jniFrame(env, 0);
+    mLayerClient->ContentDocumentChanged(&jniFrame);
 }
 
 bool
 AndroidBridge::IsContentDocumentDisplayed()
 {
     JNIEnv* env = GetJNIEnv();
     if (!env || !mLayerClient)
         return false;
-
-    return mLayerClient->IsContentDocumentDisplayed();
+    AutoLocalJNIFrame jniFrame(env, 0);
+    return mLayerClient->IsContentDocumentDisplayed(&jniFrame);
 }
 
 bool
 AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY)
 {
-    GeckoLayerClient *client = mLayerClient;
-    if (!client) {
-        ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
+    AndroidGeckoLayerClient *client = mLayerClient;
+    if (!client)
         return false;
-    }
-
-    jobject progressiveUpdateDataJObj = client->ProgressiveUpdateCallback(aHasPendingNewThebesContent,
-                                                                   (float)aDisplayPort.x,
-                                                                   (float)aDisplayPort.y,
-                                                                   (float)aDisplayPort.width,
-                                                                   (float)aDisplayPort.height,
-                                                                          aDisplayResolution,
-                                                                         !aDrawingCritical);
 
-    NS_ABORT_IF_FALSE(progressiveUpdateDataJObj, "No progressive update data!");
-
-    ProgressiveUpdateData* progressiveUpdateData = ProgressiveUpdateData::Wrap(progressiveUpdateDataJObj);
-
-    aViewport.x = progressiveUpdateData->getx();
-    aViewport.y = progressiveUpdateData->gety();
-    aViewport.width = progressiveUpdateData->getwidth();
-    aViewport.height = progressiveUpdateData->getheight();
-    aScaleX = aScaleY = progressiveUpdateData->getscale();
-
-    bool ret = progressiveUpdateData->getabort();
-    delete progressiveUpdateData;
-
-    return ret;
+    return client->ProgressiveUpdateCallback(aHasPendingNewThebesContent, aDisplayPort, aDisplayResolution, aDrawingCritical, aViewport, aScaleX, aScaleY);
 }
 
-NativePanZoomController*
+jobject
 AndroidBridge::SetNativePanZoomController(jobject obj)
 {
-    NativePanZoomController* old = mNativePanZoomController;
-    mNativePanZoomController = NativePanZoomController::Wrap(obj);
+    jobject old = mNativePanZoomController;
+    mNativePanZoomController = obj;
     return old;
 }
 
 void
 AndroidBridge::RequestContentRepaint(const mozilla::layers::FrameMetrics& aFrameMetrics)
 {
     ALOG_BRIDGE("AndroidBridge::RequestContentRepaint");
 
     CSSToScreenScale resolution = aFrameMetrics.mZoom;
     ScreenRect dp = (aFrameMetrics.mDisplayPort + aFrameMetrics.mScrollOffset) * resolution;
 
-    mNativePanZoomController->RequestContentRepaintWrapper(dp.x, dp.y, dp.width, dp.height, resolution.scale);
+    RequestContentRepaintWrapper(mNativePanZoomController,
+        dp.x, dp.y, dp.width, dp.height, resolution.scale);
 }
 
 void
 AndroidBridge::HandleDoubleTap(const CSSIntPoint& aPoint)
 {
     nsCString data = nsPrintfCString("{ \"x\": %d, \"y\": %d }", aPoint.x, aPoint.y);
     nsAppShell::gAppShell->PostEvent(AndroidGeckoEvent::MakeBroadcastEvent(
             NS_LITERAL_CSTRING("Gesture:DoubleTap"), data));
@@ -2041,17 +1969,17 @@ AndroidBridge::PostDelayedTask(Task* aTa
     if (i == mDelayedTaskQueue.Length()) {
         // this new task will run after all the existing tasks in the queue
         mDelayedTaskQueue.AppendElement(newTask);
     }
     if (i == 0) {
         // if we're inserting it at the head of the queue, notify Java because
         // we need to get a callback at an earlier time than the last scheduled
         // callback
-        mNativePanZoomController->PostDelayedCallbackWrapper((int64_t)aDelayMs);
+        PostDelayedCallbackWrapper(mNativePanZoomController, (int64_t)aDelayMs);
     }
 }
 
 int64_t
 AndroidBridge::RunDelayedTasks()
 {
     while (mDelayedTaskQueue.Length() > 0) {
         DelayedTask* nextTask = mDelayedTaskQueue[0];
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -9,17 +9,17 @@
 #include <jni.h>
 #include <android/log.h>
 #include <cstdlib>
 #include <pthread.h>
 
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
 
-#include "GeneratedJNIWrappers.h"
+#include "AndroidJavaWrappers.h"
 
 #include "nsIMutableArray.h"
 #include "nsIMIMEInfo.h"
 #include "nsColor.h"
 #include "gfxRect.h"
 
 #include "nsIAndroidBridge.h"
 #include "nsIMobileMessageCallback.h"
@@ -36,25 +36,24 @@
 class nsWindow;
 class nsIDOMMozSmsMessage;
 class nsIObserver;
 
 /* See the comment in AndroidBridge about this function before using it */
 extern "C" JNIEnv * GetJNIForThread();
 
 extern bool mozilla_AndroidBridge_SetMainThread(pthread_t);
+extern jclass GetGeckoAppShellClass();
 
 namespace base {
 class Thread;
 } // end namespace base
 
 typedef void* EGLSurface;
 
-using namespace mozilla::widget::android;
-
 namespace mozilla {
 
 namespace hal {
 class BatteryInformation;
 class NetworkInformation;
 } // namespace hal
 
 namespace dom {
@@ -156,16 +155,20 @@ public:
                 return nullptr;
             }
             return sBridge->mJNIEnv;
 
         }
         return nullptr;
     }
 
+    static jclass GetGeckoAppShellClass() {
+        return sBridge->mGeckoAppShellClass;
+    }
+
     // The bridge needs to be constructed via ConstructBridge first,
     // and then once the Gecko main thread is spun up (Gecko side),
     // SetMainThread should be called which will create the JNIEnv for
     // us to use.  toolkit/xre/nsAndroidStartup.cpp calls
     // SetMainThread.
     bool SetMainThread(pthread_t thr);
 
     /* These are all implemented in Java */
@@ -175,32 +178,36 @@ public:
     nsresult CaptureThumbnail(nsIDOMWindow *window, int32_t bufW, int32_t bufH, int32_t tabId, jobject buffer);
     void GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort);
     void ContentDocumentChanged();
     bool IsContentDocumentDisplayed();
 
     bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY);
 
     void SetLayerClient(JNIEnv* env, jobject jobj);
-    GeckoLayerClient* GetLayerClient() { return mLayerClient; }
+    AndroidGeckoLayerClient &GetLayerClient() { return *mLayerClient; }
 
     bool GetHandlersForURL(const nsAString& aURL,
                            nsIMutableArray* handlersArray = nullptr,
                            nsIHandlerApp **aDefaultApp = nullptr,
                            const nsAString& aAction = EmptyString());
 
     bool GetHandlersForMimeType(const nsAString& aMimeType,
                                 nsIMutableArray* handlersArray = nullptr,
                                 nsIHandlerApp **aDefaultApp = nullptr,
                                 const nsAString& aAction = EmptyString());
 
     void GetMimeTypeFromExtensions(const nsACString& aFileExt, nsCString& aMimeType);
     void GetExtensionFromMimeType(const nsACString& aMimeType, nsACString& aFileExt);
 
     bool GetClipboardText(nsAString& aText);
+    
+    void EmptyClipboard();
+
+    bool ClipboardHasText();
 
     void ShowAlertNotification(const nsAString& aImageUrl,
                                const nsAString& aAlertTitle,
                                const nsAString& aAlertText,
                                const nsAString& aAlertData,
                                nsIObserver *aAlertListener,
                                const nsAString& aAlertName);
 
@@ -208,16 +215,18 @@ public:
     int GetScreenDepth();
 
     void ShowFilePickerForExtensions(nsAString& aFilePath, const nsAString& aExtensions);
     void ShowFilePickerForMimeType(nsAString& aFilePath, const nsAString& aMimeType);
     void ShowFilePickerAsync(const nsAString& aMimeType, nsFilePickerCallback* callback);
 
     void Vibrate(const nsTArray<uint32_t>& aPattern);
 
+    void HideProgressDialogOnce();
+
     void GetSystemColors(AndroidSystemColors *aColors);
 
     void GetIconForExtension(const nsACString& aFileExt, uint32_t aIconSize, uint8_t * const aBuf);
 
     // Switch Java to composite with the Gecko Compositor thread
     void RegisterCompositor(JNIEnv* env = NULL);
     EGLSurface ProvideEGLSurface();
 
@@ -327,17 +336,17 @@ protected:
 
     // the global JavaVM
     JavaVM *mJavaVM;
 
     // the JNIEnv for the main thread
     JNIEnv *mJNIEnv;
     pthread_t mThread;
 
-    GeckoLayerClient *mLayerClient = NULL;
+    AndroidGeckoLayerClient *mLayerClient;
 
     // the android.telephony.SmsMessage class
     jclass mAndroidSmsMessageClass;
 
     AndroidBridge();
     ~AndroidBridge();
 
     void InitStubs(JNIEnv *jEnv);
@@ -368,17 +377,17 @@ protected:
 
     // For native surface stuff
     jclass jSurfaceClass;
     jfieldID jSurfacePointerField;
 
     jclass jLayerView;
 
     jfieldID jEGLSurfacePointerField;
-    GLController *mGLControllerObj;
+    jobject mGLControllerObj;
 
     // some convinient types to have around
     jclass jStringClass;
 
     // calls we've dlopened from libjnigraphics.so
     int (* AndroidBitmap_getInfo)(JNIEnv *env, jobject bitmap, void *info);
     int (* AndroidBitmap_lockPixels)(JNIEnv *env, jobject bitmap, void **buffer);
     int (* AndroidBitmap_unlockPixels)(JNIEnv *env, jobject bitmap);
@@ -392,24 +401,25 @@ protected:
     int (* ANativeWindow_unlockAndPost)(void *window);
 
     int (* Surface_lock)(void* surface, void* surfaceInfo, void* region, bool block);
     int (* Surface_unlockAndPost)(void* surface);
     void (* Region_constructor)(void* region);
     void (* Region_set)(void* region, void* rect);
 
 private:
-    NativePanZoomController* mNativePanZoomController;
+    jobject mNativePanZoomController;
     // This will always be accessed from one thread (the APZC "controller"
     // thread, which is the Java UI thread), so we don't need to do locking
     // to touch it
     nsTArray<DelayedTask*> mDelayedTaskQueue;
 
 public:
-    NativePanZoomController* SetNativePanZoomController(jobject obj);
+    #include "GeneratedJNIWrappers.h"
+    jobject SetNativePanZoomController(jobject obj);
     // GeckoContentController methods
     void RequestContentRepaint(const mozilla::layers::FrameMetrics& aFrameMetrics) MOZ_OVERRIDE;
     void HandleDoubleTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE;
     void HandleSingleTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE;
     void HandleLongTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE;
     void SendAsyncScrollDOMEvent(mozilla::layers::FrameMetrics::ViewID aScrollId,
                                  const CSSRect& aContentRect,
                                  const CSSSize& aScrollableSize) MOZ_OVERRIDE;
--- a/widget/android/AndroidBridgeUtilities.h
+++ b/widget/android/AndroidBridgeUtilities.h
@@ -12,22 +12,8 @@
 #define getMethod(fname, ftype) \
     AndroidBridge::GetMethodID(jEnv, jClass, fname, ftype)
 
 #define getStaticField(fname, ftype) \
     AndroidBridge::GetStaticFieldID(jEnv, jClass, fname, ftype)
 
 #define getStaticMethod(fname, ftype) \
     AndroidBridge::GetStaticMethodID(jEnv, jClass, fname, ftype)
-
-#ifndef ALOG
-#if defined(DEBUG) || defined(FORCE_ALOG)
-#define ALOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gecko" , ## args)
-#else
-#define ALOG(args...) ((void)0)
-#endif
-#endif
-
-#ifdef DEBUG
-#define ALOG_BRIDGE(args...) ALOG(args)
-#else
-#define ALOG_BRIDGE(args...) ((void)0)
-#endif
--- a/widget/android/AndroidJNI.cpp
+++ b/widget/android/AndroidJNI.cpp
@@ -856,20 +856,20 @@ Java_org_mozilla_gecko_gfx_NativePanZoom
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_gfx_NativePanZoomController_init(JNIEnv* env, jobject instance)
 {
     if (!AndroidBridge::Bridge()) {
         return;
     }
 
-    NativePanZoomController* oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(instance);
-    if (oldRef && !oldRef->isNull()) {
+    jobject oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(env->NewGlobalRef(instance));
+    if (oldRef) {
         MOZ_ASSERT(false, "Registering a new NPZC when we already have one");
-        delete oldRef;
+        env->DeleteGlobalRef(oldRef);
     }
 }
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_gfx_NativePanZoomController_handleTouchEvent(JNIEnv* env, jobject instance, jobject event)
 {
     APZCTreeManager *controller = nsWindow::GetAPZCTreeManager();
     if (controller) {
@@ -900,21 +900,21 @@ Java_org_mozilla_gecko_gfx_NativePanZoom
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_gfx_NativePanZoomController_destroy(JNIEnv* env, jobject instance)
 {
     if (!AndroidBridge::Bridge()) {
         return;
     }
 
-    NativePanZoomController* oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(NULL);
-    if (!oldRef || oldRef->isNull()) {
+    jobject oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(NULL);
+    if (!oldRef) {
         MOZ_ASSERT(false, "Clearing a non-existent NPZC");
     } else {
-        delete oldRef;
+        env->DeleteGlobalRef(oldRef);
     }
 }
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_gfx_NativePanZoomController_notifyDefaultActionPrevented(JNIEnv* env, jobject instance, jboolean prevented)
 {
     APZCTreeManager *controller = nsWindow::GetAPZCTreeManager();
     if (controller) {
--- a/widget/android/AndroidJNIWrapper.cpp
+++ b/widget/android/AndroidJNIWrapper.cpp
@@ -9,16 +9,22 @@
 #include <dlfcn.h>
 #include <prthread.h>
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Assertions.h"
 #include "nsThreadUtils.h"
 #include "AndroidBridge.h"
 
+#ifdef DEBUG
+#define ALOG_BRIDGE(args...) ALOG(args)
+#else
+#define ALOG_BRIDGE(args...)
+#endif
+
 extern "C" {
   jclass __jsjni_GetGlobalClassRef(const char *className);
 }
 
 class GetGlobalClassRefRunnable : public nsRunnable {
   public:
     GetGlobalClassRefRunnable(const char *className, jclass *foundClass) :
         mClassName(className), mResult(foundClass) {}
--- a/widget/android/AndroidJavaWrappers.cpp
+++ b/widget/android/AndroidJavaWrappers.cpp
@@ -1,23 +1,23 @@
 /* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AndroidJavaWrappers.h"
 #include "AndroidBridge.h"
 #include "AndroidBridgeUtilities.h"
+#include "nsIAndroidBridge.h"
 #include "nsIDOMKeyEvent.h"
 #include "nsIWidget.h"
 #include "mozilla/TouchEvents.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
-using namespace mozilla::widget::android;
 
 jclass AndroidGeckoEvent::jGeckoEventClass = 0;
 jfieldID AndroidGeckoEvent::jActionField = 0;
 jfieldID AndroidGeckoEvent::jTypeField = 0;
 jfieldID AndroidGeckoEvent::jAckNeededField = 0;
 jfieldID AndroidGeckoEvent::jTimeField = 0;
 jfieldID AndroidGeckoEvent::jPoints = 0;
 jfieldID AndroidGeckoEvent::jPointIndicies = 0;
@@ -86,31 +86,77 @@ jclass AndroidLocation::jLocationClass =
 jmethodID AndroidLocation::jGetLatitudeMethod = 0;
 jmethodID AndroidLocation::jGetLongitudeMethod = 0;
 jmethodID AndroidLocation::jGetAltitudeMethod = 0;
 jmethodID AndroidLocation::jGetAccuracyMethod = 0;
 jmethodID AndroidLocation::jGetBearingMethod = 0;
 jmethodID AndroidLocation::jGetSpeedMethod = 0;
 jmethodID AndroidLocation::jGetTimeMethod = 0;
 
+jclass AndroidGeckoLayerClient::jGeckoLayerClientClass = 0;
+jclass AndroidGeckoLayerClient::jViewportClass = 0;
+jclass AndroidGeckoLayerClient::jDisplayportClass = 0;
+jmethodID AndroidGeckoLayerClient::jSetFirstPaintViewport = 0;
+jmethodID AndroidGeckoLayerClient::jSetPageRect = 0;
+jmethodID AndroidGeckoLayerClient::jSyncViewportInfoMethod = 0;
+jmethodID AndroidGeckoLayerClient::jSyncFrameMetricsMethod = 0;
+jmethodID AndroidGeckoLayerClient::jCreateFrameMethod = 0;
+jmethodID AndroidGeckoLayerClient::jActivateProgramMethod = 0;
+jmethodID AndroidGeckoLayerClient::jDeactivateProgramMethod = 0;
+jmethodID AndroidGeckoLayerClient::jGetDisplayPort = 0;
+jmethodID AndroidGeckoLayerClient::jContentDocumentChanged = 0;
+jmethodID AndroidGeckoLayerClient::jIsContentDocumentDisplayed = 0;
+jmethodID AndroidGeckoLayerClient::jViewportCtor = 0;
+jfieldID AndroidGeckoLayerClient::jDisplayportPosition = 0;
+jfieldID AndroidGeckoLayerClient::jDisplayportResolution = 0;
+jmethodID AndroidGeckoLayerClient::jProgressiveUpdateCallbackMethod = 0;
+
+jclass AndroidLayerRendererFrame::jLayerRendererFrameClass = 0;
+jmethodID AndroidLayerRendererFrame::jBeginDrawingMethod = 0;
+jmethodID AndroidLayerRendererFrame::jDrawBackgroundMethod = 0;
+jmethodID AndroidLayerRendererFrame::jDrawForegroundMethod = 0;
+jmethodID AndroidLayerRendererFrame::jEndDrawingMethod = 0;
+
+jclass AndroidViewTransform::jViewTransformClass = 0;
+jfieldID AndroidViewTransform::jXField = 0;
+jfieldID AndroidViewTransform::jYField = 0;
+jfieldID AndroidViewTransform::jScaleField = 0;
+jfieldID AndroidViewTransform::jFixedLayerMarginLeft = 0;
+jfieldID AndroidViewTransform::jFixedLayerMarginTop = 0;
+jfieldID AndroidViewTransform::jFixedLayerMarginRight = 0;
+jfieldID AndroidViewTransform::jFixedLayerMarginBottom = 0;
+jfieldID AndroidViewTransform::jOffsetXField = 0;
+jfieldID AndroidViewTransform::jOffsetYField = 0;
+
+jclass AndroidProgressiveUpdateData::jProgressiveUpdateDataClass = 0;
+jfieldID AndroidProgressiveUpdateData::jXField = 0;
+jfieldID AndroidProgressiveUpdateData::jYField = 0;
+jfieldID AndroidProgressiveUpdateData::jWidthField = 0;
+jfieldID AndroidProgressiveUpdateData::jHeightField = 0;
+jfieldID AndroidProgressiveUpdateData::jScaleField = 0;
+jfieldID AndroidProgressiveUpdateData::jShouldAbortField = 0;
+
 RefCountedJavaObject::~RefCountedJavaObject() {
     if (mObject)
         GetJNIForThread()->DeleteGlobalRef(mObject);
     mObject = NULL;
 }
 
 void
 mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv)
 {
     AndroidGeckoEvent::InitGeckoEventClass(jEnv);
     AndroidPoint::InitPointClass(jEnv);
     AndroidLocation::InitLocationClass(jEnv);
     AndroidRect::InitRectClass(jEnv);
     AndroidRectF::InitRectFClass(jEnv);
-    InitStubs(jEnv);
+    AndroidGeckoLayerClient::InitGeckoLayerClientClass(jEnv);
+    AndroidLayerRendererFrame::InitLayerRendererFrameClass(jEnv);
+    AndroidViewTransform::InitViewTransformClass(jEnv);
+    AndroidProgressiveUpdateData::InitProgressiveUpdateDataClass(jEnv);
 }
 
 void
 AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv)
 {
     initInit();
 
     jGeckoEventClass = getClassGlobalRef("org/mozilla/gecko/GeckoEvent");
@@ -239,16 +285,92 @@ AndroidRectF::InitRectFClass(JNIEnv *jEn
     jRectClass = getClassGlobalRef("android/graphics/RectF");
 
     jBottomField = getField("bottom", "F");
     jLeftField = getField("left", "F");
     jTopField = getField("top", "F");
     jRightField = getField("right", "F");
 }
 
+void
+AndroidGeckoLayerClient::InitGeckoLayerClientClass(JNIEnv *jEnv)
+{
+    initInit();
+
+    jGeckoLayerClientClass = getClassGlobalRef("org/mozilla/gecko/gfx/GeckoLayerClient");
+
+    jProgressiveUpdateCallbackMethod = getMethod("progressiveUpdateCallback",
+                                                 "(ZFFFFFZ)Lorg/mozilla/gecko/gfx/ProgressiveUpdateData;");
+    jSetFirstPaintViewport = getMethod("setFirstPaintViewport", "(FFFFFFF)V");
+    jSetPageRect = getMethod("setPageRect", "(FFFF)V");
+    jSyncViewportInfoMethod = getMethod("syncViewportInfo",
+                                        "(IIIIFZ)Lorg/mozilla/gecko/gfx/ViewTransform;");
+    jSyncFrameMetricsMethod = getMethod("syncFrameMetrics",
+                                        "(FFFFFFFZIIIIFZ)Lorg/mozilla/gecko/gfx/ViewTransform;");
+    jCreateFrameMethod = getMethod("createFrame", "()Lorg/mozilla/gecko/gfx/LayerRenderer$Frame;");
+    jActivateProgramMethod = getMethod("activateProgram", "()V");
+    jDeactivateProgramMethod = getMethod("deactivateProgram", "()V");
+    jGetDisplayPort = getMethod("getDisplayPort", "(ZZILorg/mozilla/gecko/gfx/ImmutableViewportMetrics;)Lorg/mozilla/gecko/gfx/DisplayPortMetrics;");
+    jContentDocumentChanged = getMethod("contentDocumentChanged", "()V");
+    jIsContentDocumentDisplayed = getMethod("isContentDocumentDisplayed", "()Z");
+
+    jViewportClass = getClassGlobalRef("org/mozilla/gecko/gfx/ImmutableViewportMetrics");
+    jViewportCtor = getMethod("<init>", "(FFFFFFFFFFFFF)V");
+
+    jDisplayportClass = getClassGlobalRef("org/mozilla/gecko/gfx/DisplayPortMetrics");
+    jDisplayportPosition = getField("mPosition", "Landroid/graphics/RectF;");
+    jDisplayportResolution = getField("resolution", "F");
+}
+
+void
+AndroidLayerRendererFrame::InitLayerRendererFrameClass(JNIEnv *jEnv)
+{
+    initInit();
+
+    jLayerRendererFrameClass = getClassGlobalRef("org/mozilla/gecko/gfx/LayerRenderer$Frame");
+
+    jBeginDrawingMethod = getMethod("beginDrawing", "()V");
+    jDrawBackgroundMethod = getMethod("drawBackground", "()V");
+    jDrawForegroundMethod = getMethod("drawForeground", "()V");
+    jEndDrawingMethod = getMethod("endDrawing", "()V");
+}
+
+void
+AndroidViewTransform::InitViewTransformClass(JNIEnv *jEnv)
+{
+    initInit();
+
+    jViewTransformClass = getClassGlobalRef("org/mozilla/gecko/gfx/ViewTransform");
+
+    jXField = getField("x", "F");
+    jYField = getField("y", "F");
+    jScaleField = getField("scale", "F");
+    jFixedLayerMarginLeft = getField("fixedLayerMarginLeft", "F");
+    jFixedLayerMarginTop = getField("fixedLayerMarginTop", "F");
+    jFixedLayerMarginRight = getField("fixedLayerMarginRight", "F");
+    jFixedLayerMarginBottom = getField("fixedLayerMarginBottom", "F");
+    jOffsetXField = getField("offsetX", "F");
+    jOffsetYField = getField("offsetY", "F");
+}
+
+void
+AndroidProgressiveUpdateData::InitProgressiveUpdateDataClass(JNIEnv *jEnv)
+{
+    initInit();
+
+    jProgressiveUpdateDataClass = getClassGlobalRef("org/mozilla/gecko/gfx/ProgressiveUpdateData");
+
+    jXField = getField("x", "F");
+    jYField = getField("y", "F");
+    jWidthField = getField("width", "F");
+    jHeightField = getField("height", "F");
+    jScaleField = getField("scale", "F");
+    jShouldAbortField = getField("abort", "Z");
+}
+
 #undef initInit
 #undef initClassGlobalRef
 #undef getField
 #undef getMethod
 
 void
 AndroidGeckoEvent::ReadPointArray(nsTArray<nsIntPoint> &points,
                                   JNIEnv *jenv,
@@ -718,18 +840,471 @@ AndroidPoint::Init(JNIEnv *jenv, jobject
         mX = jenv->GetIntField(jobj, jXField);
         mY = jenv->GetIntField(jobj, jYField);
     } else {
         mX = 0;
         mY = 0;
     }
 }
 
+void
+AndroidGeckoLayerClient::Init(jobject jobj)
+{
+    NS_ASSERTION(wrapped_obj == nullptr, "Init called on non-null wrapped_obj!");
+    wrapped_obj = jobj;
+}
+
+void
+AndroidLayerRendererFrame::Init(JNIEnv *env, jobject jobj)
+{
+    if (!isNull()) {
+        Dispose(env);
+    }
+
+    wrapped_obj = env->NewGlobalRef(jobj);
+}
+
+void
+AndroidLayerRendererFrame::Dispose(JNIEnv *env)
+{
+    if (isNull()) {
+        return;
+    }
+
+    env->DeleteGlobalRef(wrapped_obj);
+    wrapped_obj = 0;
+}
+
+void
+AndroidViewTransform::Init(jobject jobj)
+{
+    NS_ABORT_IF_FALSE(wrapped_obj == nullptr, "Init called on non-null wrapped_obj!");
+    wrapped_obj = jobj;
+}
+
+void
+AndroidProgressiveUpdateData::Init(jobject jobj)
+{
+    NS_ABORT_IF_FALSE(wrapped_obj == nullptr, "Init called on non-null wrapped_obj!");
+    wrapped_obj = jobj;
+}
+
+void
+AndroidGeckoLayerClient::SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect)
+{
+    NS_ASSERTION(!isNull(), "SetFirstPaintViewport called on null layer client!");
+    JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
+    if (!env)
+        return;
+
+    AutoLocalJNIFrame jniFrame(env, 0);
+    return env->CallVoidMethod(wrapped_obj, jSetFirstPaintViewport, (float)aOffset.x, (float)aOffset.y, aZoom.scale,
+                               aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
+}
+
+void
+AndroidGeckoLayerClient::SetPageRect(const CSSRect& aCssPageRect)
+{
+    NS_ASSERTION(!isNull(), "SetPageRect called on null layer client!");
+    JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
+    if (!env)
+        return;
+
+    AutoLocalJNIFrame jniFrame(env, 0);
+    return env->CallVoidMethod(wrapped_obj, jSetPageRect,
+                               aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
+}
+
+void
+AndroidGeckoLayerClient::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
+                                          bool aLayersUpdated, ScreenPoint& aScrollOffset, CSSToScreenScale& aScale,
+                                          LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset)
+{
+    NS_ASSERTION(!isNull(), "SyncViewportInfo called on null layer client!");
+    JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
+    if (!env)
+        return;
+
+    AutoLocalJNIFrame jniFrame(env);
+
+    jobject viewTransformJObj = env->CallObjectMethod(wrapped_obj, jSyncViewportInfoMethod,
+                                                      aDisplayPort.x, aDisplayPort.y,
+                                                      aDisplayPort.width, aDisplayPort.height,
+                                                      aDisplayResolution.scale, aLayersUpdated);
+    if (jniFrame.CheckForException())
+        return;
+
+    NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
+
+    AndroidViewTransform viewTransform;
+    viewTransform.Init(viewTransformJObj);
+
+    aScrollOffset = ScreenPoint(viewTransform.GetX(env), viewTransform.GetY(env));
+    aScale.scale = viewTransform.GetScale(env);
+    viewTransform.GetFixedLayerMargins(env, aFixedLayerMargins);
+
+    aOffset.x = viewTransform.GetOffsetX(env);
+    aOffset.y = viewTransform.GetOffsetY(env);
+}
+
+void
+AndroidGeckoLayerClient::SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect,
+                                          bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
+                                          bool aIsFirstPaint, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset)
+{
+    NS_ASSERTION(!isNull(), "SyncFrameMetrics called on null layer client!");
+    JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
+    if (!env)
+        return;
+
+    AutoLocalJNIFrame jniFrame(env);
+
+    // convert the displayport rect from scroll-relative CSS pixels to document-relative device pixels
+    LayerRect dpUnrounded = aDisplayPort * aDisplayResolution;
+    dpUnrounded += LayerPoint::FromUnknownPoint(aScrollOffset.ToUnknownPoint());
+    LayerIntRect dp = gfx::RoundedToInt(dpUnrounded);
+
+    jobject viewTransformJObj = env->CallObjectMethod(wrapped_obj, jSyncFrameMetricsMethod,
+            aScrollOffset.x, aScrollOffset.y, aZoom,
+            aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost(),
+            aLayersUpdated, dp.x, dp.y, dp.width, dp.height, aDisplayResolution.scale,
+            aIsFirstPaint);
+
+    if (jniFrame.CheckForException())
+        return;
+
+    NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
+
+    AndroidViewTransform viewTransform;
+    viewTransform.Init(viewTransformJObj);
+    viewTransform.GetFixedLayerMargins(env, aFixedLayerMargins);
+    aOffset.x = viewTransform.GetOffsetX(env);
+    aOffset.y = viewTransform.GetOffsetY(env);
+}
+
+bool
+AndroidGeckoLayerClient::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
+                                                   const LayerRect& aDisplayPort,
+                                                   float aDisplayResolution,
+                                                   bool aDrawingCritical,
+                                                   gfx::Rect& aViewport,
+                                                   float& aScaleX,
+                                                   float& aScaleY)
+{
+    JNIEnv *env = AndroidBridge::GetJNIEnv();
+    if (!env)
+        return false;
+
+    AutoJObject progressiveUpdateDataJObj(env, env->CallObjectMethod(wrapped_obj,
+                                                                     jProgressiveUpdateCallbackMethod,
+                                                                     aHasPendingNewThebesContent,
+                                                                     (float)aDisplayPort.x,
+                                                                     (float)aDisplayPort.y,
+                                                                     (float)aDisplayPort.width,
+                                                                     (float)aDisplayPort.height,
+                                                                     aDisplayResolution,
+                                                                     !aDrawingCritical));
+    if (env->ExceptionCheck()) {
+        env->ExceptionDescribe();
+        env->ExceptionClear();
+        return false;
+    }
+
+    NS_ABORT_IF_FALSE(progressiveUpdateDataJObj, "No progressive update data!");
+
+    AndroidProgressiveUpdateData progressiveUpdateData(progressiveUpdateDataJObj);
+
+    aViewport.x = progressiveUpdateData.GetX(env);
+    aViewport.y = progressiveUpdateData.GetY(env);
+    aViewport.width = progressiveUpdateData.GetWidth(env);
+    aViewport.height = progressiveUpdateData.GetHeight(env);
+    aScaleX = aScaleY = progressiveUpdateData.GetScale(env);
+
+    return progressiveUpdateData.GetShouldAbort(env);
+}
+
+jobject ConvertToJavaViewportMetrics(JNIEnv* env, nsIAndroidViewport* metrics) {
+    float x, y, width, height,
+        pageLeft, pageTop, pageRight, pageBottom,
+        cssPageLeft, cssPageTop, cssPageRight, cssPageBottom,
+        zoom;
+    metrics->GetX(&x);
+    metrics->GetY(&y);
+    metrics->GetWidth(&width);
+    metrics->GetHeight(&height);
+    metrics->GetPageLeft(&pageLeft);
+    metrics->GetPageTop(&pageTop);
+    metrics->GetPageRight(&pageRight);
+    metrics->GetPageBottom(&pageBottom);
+    metrics->GetCssPageLeft(&cssPageLeft);
+    metrics->GetCssPageTop(&cssPageTop);
+    metrics->GetCssPageRight(&cssPageRight);
+    metrics->GetCssPageBottom(&cssPageBottom);
+    metrics->GetZoom(&zoom);
+
+    jobject jobj = env->NewObject(AndroidGeckoLayerClient::jViewportClass, AndroidGeckoLayerClient::jViewportCtor,
+                                  pageLeft, pageTop, pageRight, pageBottom,
+                                  cssPageLeft, cssPageTop, cssPageRight, cssPageBottom,
+                                  x, y, x + width, y + height,
+                                  zoom);
+    return jobj;
+}
+
+class nsAndroidDisplayport MOZ_FINAL : public nsIAndroidDisplayport
+{
+public:
+    NS_DECL_ISUPPORTS
+    virtual nsresult GetLeft(float *aLeft) { *aLeft = mLeft; return NS_OK; }
+    virtual nsresult GetTop(float *aTop) { *aTop = mTop; return NS_OK; }
+    virtual nsresult GetRight(float *aRight) { *aRight = mRight; return NS_OK; }
+    virtual nsresult GetBottom(float *aBottom) { *aBottom = mBottom; return NS_OK; }
+    virtual nsresult GetResolution(float *aResolution) { *aResolution = mResolution; return NS_OK; }
+    virtual nsresult SetLeft(float aLeft) { mLeft = aLeft; return NS_OK; }
+    virtual nsresult SetTop(float aTop) { mTop = aTop; return NS_OK; }
+    virtual nsresult SetRight(float aRight) { mRight = aRight; return NS_OK; }
+    virtual nsresult SetBottom(float aBottom) { mBottom = aBottom; return NS_OK; }
+    virtual nsresult SetResolution(float aResolution) { mResolution = aResolution; return NS_OK; }
+
+    nsAndroidDisplayport(AndroidRectF aRect, float aResolution):
+        mLeft(aRect.Left()), mTop(aRect.Top()), mRight(aRect.Right()), mBottom(aRect.Bottom()), mResolution(aResolution) {}
+
+private:
+    ~nsAndroidDisplayport() {}
+    float mLeft, mTop, mRight, mBottom, mResolution;
+};
+
 NS_IMPL_ISUPPORTS1(nsAndroidDisplayport, nsIAndroidDisplayport)
 
+void createDisplayPort(AutoLocalJNIFrame *jniFrame, jobject jobj, nsIAndroidDisplayport** displayPort) {
+    JNIEnv* env = jniFrame->GetEnv();
+    AndroidRectF rect(env, env->GetObjectField(jobj, AndroidGeckoLayerClient::jDisplayportPosition));
+    if (jniFrame->CheckForException()) return;
+    float resolution = env->GetFloatField(jobj, AndroidGeckoLayerClient::jDisplayportResolution);
+    if (jniFrame->CheckForException()) return;
+    *displayPort = new nsAndroidDisplayport(rect, resolution);
+}
+
+void
+AndroidGeckoLayerClient::GetDisplayPort(AutoLocalJNIFrame *jniFrame, bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort)
+{
+    jobject jmetrics = ConvertToJavaViewportMetrics(jniFrame->GetEnv(), metrics);
+    if (jniFrame->CheckForException()) return;
+    if (!jmetrics)
+        return;
+    jobject jobj = jniFrame->GetEnv()->CallObjectMethod(wrapped_obj, jGetDisplayPort, aPageSizeUpdate, aIsBrowserContentDisplayed, tabId, jmetrics);
+    if (jniFrame->CheckForException()) return;
+    createDisplayPort(jniFrame, jobj, displayPort);
+    (*displayPort)->AddRef();
+}
+
+void
+AndroidGeckoLayerClient::ContentDocumentChanged(AutoLocalJNIFrame *jniFrame)
+{
+    jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jContentDocumentChanged);
+}
+
+bool
+AndroidGeckoLayerClient::IsContentDocumentDisplayed(AutoLocalJNIFrame *jniFrame)
+{
+    return jniFrame->GetEnv()->CallBooleanMethod(wrapped_obj, jIsContentDocumentDisplayed);
+}
+
+bool
+AndroidGeckoLayerClient::CreateFrame(AutoLocalJNIFrame *jniFrame, AndroidLayerRendererFrame& aFrame)
+{
+    if (!jniFrame || !jniFrame->GetEnv())
+        return false;
+
+    jobject frameJObj = jniFrame->GetEnv()->CallObjectMethod(wrapped_obj, jCreateFrameMethod);
+    if (jniFrame->CheckForException())
+        return false;
+    NS_ABORT_IF_FALSE(frameJObj, "No frame object!");
+
+    aFrame.Init(jniFrame->GetEnv(), frameJObj);
+    return true;
+}
+
+bool
+AndroidGeckoLayerClient::ActivateProgram(AutoLocalJNIFrame *jniFrame)
+{
+    if (!jniFrame || !jniFrame->GetEnv())
+        return false;
+
+    jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jActivateProgramMethod);
+    if (jniFrame->CheckForException())
+        return false;
+
+    return true;
+}
+
+bool
+AndroidGeckoLayerClient::DeactivateProgram(AutoLocalJNIFrame *jniFrame)
+{
+    if (!jniFrame || !jniFrame->GetEnv())
+        return false;
+
+    jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jDeactivateProgramMethod);
+    if (jniFrame->CheckForException())
+        return false;
+
+    return true;
+}
+
+bool
+AndroidLayerRendererFrame::BeginDrawing(AutoLocalJNIFrame *jniFrame)
+{
+    if (!jniFrame || !jniFrame->GetEnv())
+        return false;
+
+    jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jBeginDrawingMethod);
+    if (jniFrame->CheckForException())
+        return false;
+
+    return true;
+}
+
+bool
+AndroidLayerRendererFrame::DrawBackground(AutoLocalJNIFrame *jniFrame)
+{
+    if (!jniFrame || !jniFrame->GetEnv())
+        return false;
+
+    jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jDrawBackgroundMethod);
+    if (jniFrame->CheckForException())
+        return false;
+
+    return true;
+}
+
+bool
+AndroidLayerRendererFrame::DrawForeground(AutoLocalJNIFrame *jniFrame)
+{
+    if (!jniFrame || !jniFrame->GetEnv())
+        return false;
+
+    jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jDrawForegroundMethod);
+    if (jniFrame->CheckForException())
+        return false;
+
+    return true;
+}
+
+bool
+AndroidLayerRendererFrame::EndDrawing(AutoLocalJNIFrame *jniFrame)
+{
+    if (!jniFrame || !jniFrame->GetEnv())
+        return false;
+
+    jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jEndDrawingMethod);
+    if (jniFrame->CheckForException())
+        return false;
+
+    return true;
+}
+
+float
+AndroidViewTransform::GetX(JNIEnv *env)
+{
+    if (!env)
+        return 0.0f;
+    return env->GetFloatField(wrapped_obj, jXField);
+}
+
+float
+AndroidViewTransform::GetY(JNIEnv *env)
+{
+    if (!env)
+        return 0.0f;
+    return env->GetFloatField(wrapped_obj, jYField);
+}
+
+float
+AndroidViewTransform::GetScale(JNIEnv *env)
+{
+    if (!env)
+        return 0.0f;
+    return env->GetFloatField(wrapped_obj, jScaleField);
+}
+
+void
+AndroidViewTransform::GetFixedLayerMargins(JNIEnv *env, LayerMargin &aFixedLayerMargins)
+{
+    if (!env)
+        return;
+
+    aFixedLayerMargins.top = env->GetFloatField(wrapped_obj, jFixedLayerMarginTop);
+    aFixedLayerMargins.right = env->GetFloatField(wrapped_obj, jFixedLayerMarginRight);
+    aFixedLayerMargins.bottom = env->GetFloatField(wrapped_obj, jFixedLayerMarginBottom);
+    aFixedLayerMargins.left = env->GetFloatField(wrapped_obj, jFixedLayerMarginLeft);
+}
+
+float
+AndroidViewTransform::GetOffsetX(JNIEnv *env)
+{
+    if (!env)
+        return 0.0f;
+    return env->GetFloatField(wrapped_obj, jOffsetXField);
+}
+
+float
+AndroidViewTransform::GetOffsetY(JNIEnv *env)
+{
+    if (!env)
+        return 0.0f;
+    return env->GetFloatField(wrapped_obj, jOffsetYField);
+}
+
+float
+AndroidProgressiveUpdateData::GetX(JNIEnv *env)
+{
+    if (!env)
+        return 0.0f;
+    return env->GetFloatField(wrapped_obj, jXField);
+}
+
+float
+AndroidProgressiveUpdateData::GetY(JNIEnv *env)
+{
+    if (!env)
+        return 0.0f;
+    return env->GetFloatField(wrapped_obj, jYField);
+}
+
+float
+AndroidProgressiveUpdateData::GetWidth(JNIEnv *env)
+{
+    if (!env)
+        return 0.0f;
+    return env->GetFloatField(wrapped_obj, jWidthField);
+}
+
+float
+AndroidProgressiveUpdateData::GetHeight(JNIEnv *env)
+{
+    if (!env)
+        return 0.0f;
+    return env->GetFloatField(wrapped_obj, jHeightField);
+}
+
+float
+AndroidProgressiveUpdateData::GetScale(JNIEnv *env)
+{
+    if (!env)
+        return 0.0f;
+    return env->GetFloatField(wrapped_obj, jScaleField);
+}
+
+bool
+AndroidProgressiveUpdateData::GetShouldAbort(JNIEnv *env)
+{
+    if (!env)
+        return false;
+    return env->GetBooleanField(wrapped_obj, jShouldAbortField);
+}
+
 void
 AndroidRect::Init(JNIEnv *jenv, jobject jobj)
 {
     NS_ASSERTION(wrapped_obj == nullptr, "Init called on non-null wrapped_obj!");
 
     wrapped_obj = jobj;
 
     if (jobj) {
--- a/widget/android/AndroidJavaWrappers.h
+++ b/widget/android/AndroidJavaWrappers.h
@@ -9,32 +9,40 @@
 #include <jni.h>
 #include <android/input.h>
 #include <android/log.h>
 
 #include "nsGeoPosition.h"
 #include "nsRect.h"
 #include "nsString.h"
 #include "nsTArray.h"
-#include "nsIAndroidBridge.h"
 #include "nsIObserver.h"
 #include "mozilla/gfx/Rect.h"
 #include "mozilla/dom/Touch.h"
 #include "mozilla/EventForwards.h"
 #include "InputData.h"
 #include "Units.h"
 
 //#define FORCE_ALOG 1
 
+#ifndef ALOG
+#if defined(DEBUG) || defined(FORCE_ALOG)
+#define ALOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gecko" , ## args)
+#else
+#define ALOG(args...) ((void)0)
+#endif
+#endif
+
 class nsIAndroidDisplayport;
 class nsIAndroidViewport;
 class nsIWidget;
 
 namespace mozilla {
 
+class AndroidGeckoLayerClient;
 class AutoLocalJNIFrame;
 
 void InitAndroidJavaWrappers(JNIEnv *jEnv);
 
 /*
  * Note: do not store global refs to any WrappedJavaObject;
  * these are live only during a particular JNI method, as
  * NewGlobalRef is -not- called on the jobject.
@@ -62,61 +70,29 @@ public:
 private:
     int32_t mRefCnt;
     jobject mObject;
 };
 
 class WrappedJavaObject {
 public:
     WrappedJavaObject() :
-        wrapped_obj(NULL)
+        wrapped_obj(0)
     { }
 
-    WrappedJavaObject(jobject jobj) : wrapped_obj(NULL) {
+    WrappedJavaObject(jobject jobj) {
         Init(jobj);
     }
 
     void Init(jobject jobj) {
         wrapped_obj = jobj;
     }
 
     bool isNull() const {
-        return wrapped_obj == NULL;
-    }
-
-    jobject wrappedObject() const {
-        return wrapped_obj;
-    }
-
-protected:
-    jobject wrapped_obj;
-};
-
-class AutoGlobalWrappedJavaObject : protected WrappedJavaObject{
-public:
-    AutoGlobalWrappedJavaObject() :
-        wrapped_obj(NULL)
-    { }
-
-    AutoGlobalWrappedJavaObject(jobject jobj, JNIEnv* env) : wrapped_obj(NULL) {
-        Init(jobj, env);
-    }
-
-    virtual ~AutoGlobalWrappedJavaObject();
-    void Dispose();
-
-    void Init(jobject jobj, JNIEnv* env) {
-        if (!isNull()) {
-            env->DeleteGlobalRef(wrapped_obj);
-        }
-        wrapped_obj = env->NewGlobalRef(jobj);
-    }
-
-    bool isNull() const {
-        return wrapped_obj == NULL;
+        return wrapped_obj == 0;
     }
 
     jobject wrappedObject() const {
         return wrapped_obj;
     }
 
 protected:
     jobject wrapped_obj;
@@ -205,16 +181,138 @@ protected:
 
     static jclass jRectClass;
     static jfieldID jBottomField;
     static jfieldID jLeftField;
     static jfieldID jRightField;
     static jfieldID jTopField;
 };
 
+class AndroidViewTransform : public WrappedJavaObject {
+public:
+    static void InitViewTransformClass(JNIEnv *jEnv);
+
+    void Init(jobject jobj);
+
+    AndroidViewTransform() {}
+    AndroidViewTransform(jobject jobj) { Init(jobj); }
+
+    float GetX(JNIEnv *env);
+    float GetY(JNIEnv *env);
+    float GetScale(JNIEnv *env);
+    void GetFixedLayerMargins(JNIEnv *env, LayerMargin &aFixedLayerMargins);
+    float GetOffsetX(JNIEnv *env);
+    float GetOffsetY(JNIEnv *env);
+
+private:
+    static jclass jViewTransformClass;
+    static jfieldID jXField;
+    static jfieldID jYField;
+    static jfieldID jScaleField;
+    static jfieldID jFixedLayerMarginLeft;
+    static jfieldID jFixedLayerMarginTop;
+    static jfieldID jFixedLayerMarginRight;
+    static jfieldID jFixedLayerMarginBottom;
+    static jfieldID jOffsetXField;
+    static jfieldID jOffsetYField;
+};
+
+class AndroidProgressiveUpdateData : public WrappedJavaObject {
+public:
+    static void InitProgressiveUpdateDataClass(JNIEnv *jEnv);
+
+    void Init(jobject jobj);
+
+    AndroidProgressiveUpdateData() {}
+    AndroidProgressiveUpdateData(jobject jobj) { Init(jobj); }
+
+    float GetX(JNIEnv *env);
+    float GetY(JNIEnv *env);
+    float GetWidth(JNIEnv *env);
+    float GetHeight(JNIEnv *env);
+    float GetScale(JNIEnv *env);
+    bool GetShouldAbort(JNIEnv *env);
+
+private:
+    static jclass jProgressiveUpdateDataClass;
+    static jfieldID jXField;
+    static jfieldID jYField;
+    static jfieldID jWidthField;
+    static jfieldID jHeightField;
+    static jfieldID jScaleField;
+    static jfieldID jShouldAbortField;
+};
+
+class AndroidLayerRendererFrame : public WrappedJavaObject {
+public:
+    static void InitLayerRendererFrameClass(JNIEnv *jEnv);
+
+    void Init(JNIEnv *env, jobject jobj);
+    void Dispose(JNIEnv *env);
+
+    bool BeginDrawing(AutoLocalJNIFrame *jniFrame);
+    bool DrawBackground(AutoLocalJNIFrame *jniFrame);
+    bool DrawForeground(AutoLocalJNIFrame *jniFrame);
+    bool EndDrawing(AutoLocalJNIFrame *jniFrame);
+
+private:
+    static jclass jLayerRendererFrameClass;
+    static jmethodID jBeginDrawingMethod;
+    static jmethodID jDrawBackgroundMethod;
+    static jmethodID jDrawForegroundMethod;
+    static jmethodID jEndDrawingMethod;
+};
+
+class AndroidGeckoLayerClient : public WrappedJavaObject {
+public:
+    static void InitGeckoLayerClientClass(JNIEnv *jEnv);
+
+    void Init(jobject jobj);
+
+    AndroidGeckoLayerClient() {}
+    AndroidGeckoLayerClient(jobject jobj) { Init(jobj); }
+
+    void SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect);
+    void SetPageRect(const CSSRect& aCssPageRect);
+    void SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
+                          bool aLayersUpdated, ScreenPoint& aScrollOffset, CSSToScreenScale& aScale,
+                          LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset);
+    void SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect,
+                          bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
+                          bool aIsFirstPaint, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset);
+    bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY);
+    bool CreateFrame(AutoLocalJNIFrame *jniFrame, AndroidLayerRendererFrame& aFrame);
+    bool ActivateProgram(AutoLocalJNIFrame *jniFrame);
+    bool DeactivateProgram(AutoLocalJNIFrame *jniFrame);
+    void GetDisplayPort(AutoLocalJNIFrame *jniFrame, bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort);
+    void ContentDocumentChanged(AutoLocalJNIFrame *jniFrame);
+    bool IsContentDocumentDisplayed(AutoLocalJNIFrame *jniFrame);
+
+protected:
+    static jclass jGeckoLayerClientClass;
+    static jmethodID jSetFirstPaintViewport;
+    static jmethodID jSetPageRect;
+    static jmethodID jSyncViewportInfoMethod;
+    static jmethodID jSyncFrameMetricsMethod;
+    static jmethodID jCreateFrameMethod;
+    static jmethodID jActivateProgramMethod;
+    static jmethodID jDeactivateProgramMethod;
+    static jmethodID jGetDisplayPort;
+    static jmethodID jContentDocumentChanged;
+    static jmethodID jIsContentDocumentDisplayed;
+    static jmethodID jProgressiveUpdateCallbackMethod;
+
+public:
+    static jclass jViewportClass;
+    static jclass jDisplayportClass;
+    static jmethodID jViewportCtor;
+    static jfieldID jDisplayportPosition;
+    static jfieldID jDisplayportResolution;
+};
+
 enum {
     // These keycode masks are not defined in android/keycodes.h:
     AKEYCODE_ESCAPE             = 111,
     AKEYCODE_FORWARD_DEL        = 112,
     AKEYCODE_CTRL_LEFT          = 113,
     AKEYCODE_CTRL_RIGHT         = 114,
     AKEYCODE_CAPS_LOCK          = 115,
     AKEYCODE_SCROLL_LOCK        = 116,
@@ -330,39 +428,16 @@ enum {
     AMETA_META_RIGHT_ON         = 0x00040000,
 
     AMETA_ALT_MASK              = AMETA_ALT_LEFT_ON   | AMETA_ALT_RIGHT_ON   | AMETA_ALT_ON,
     AMETA_CTRL_MASK             = AMETA_CTRL_LEFT_ON  | AMETA_CTRL_RIGHT_ON  | AMETA_CTRL_ON,
     AMETA_META_MASK             = AMETA_META_LEFT_ON  | AMETA_META_RIGHT_ON  | AMETA_META_ON,
     AMETA_SHIFT_MASK            = AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON | AMETA_SHIFT_ON,
 };
 
-class nsAndroidDisplayport MOZ_FINAL : public nsIAndroidDisplayport
-{
-public:
-    NS_DECL_ISUPPORTS
-    virtual nsresult GetLeft(float *aLeft) { *aLeft = mLeft; return NS_OK; }
-    virtual nsresult GetTop(float *aTop) { *aTop = mTop; return NS_OK; }
-    virtual nsresult GetRight(float *aRight) { *aRight = mRight; return NS_OK; }
-    virtual nsresult GetBottom(float *aBottom) { *aBottom = mBottom; return NS_OK; }
-    virtual nsresult GetResolution(float *aResolution) { *aResolution = mResolution; return NS_OK; }
-    virtual nsresult SetLeft(float aLeft) { mLeft = aLeft; return NS_OK; }
-    virtual nsresult SetTop(float aTop) { mTop = aTop; return NS_OK; }
-    virtual nsresult SetRight(float aRight) { mRight = aRight; return NS_OK; }
-    virtual nsresult SetBottom(float aBottom) { mBottom = aBottom; return NS_OK; }
-    virtual nsresult SetResolution(float aResolution) { mResolution = aResolution; return NS_OK; }
-
-    nsAndroidDisplayport(AndroidRectF aRect, float aResolution):
-        mLeft(aRect.Left()), mTop(aRect.Top()), mRight(aRect.Right()), mBottom(aRect.Bottom()), mResolution(aResolution) {}
-
-private:
-    ~nsAndroidDisplayport() {}
-    float mLeft, mTop, mRight, mBottom, mResolution;
-};
-
 class AndroidMotionEvent
 {
 public:
     enum {
         ACTION_DOWN = 0,
         ACTION_UP = 1,
         ACTION_MOVE = 2,
         ACTION_CANCEL = 3,
--- a/widget/android/GeneratedJNIWrappers.cpp
+++ b/widget/android/GeneratedJNIWrappers.cpp
@@ -1,100 +1,25 @@
 // GENERATED CODE
 // Generated by the Java program at /build/annotationProcessors at compile time from
 // annotations on Java methods. To update, change the annotations on the corresponding Java
 // methods and rerun the build. Manually updating this file will cause your build to fail.
 
-#include "GeneratedJNIWrappers.h"
-#include "AndroidBridgeUtilities.h"
 #include "nsXPCOMStrings.h"
 #include "AndroidBridge.h"
-
-namespace mozilla {
-namespace widget {
-namespace android {
-jclass GeckoAppShell::mGeckoAppShellClass = 0;
-jmethodID GeckoAppShell::jAcknowledgeEvent = 0;
-jmethodID GeckoAppShell::jAddPluginViewWrapper = 0;
-jmethodID GeckoAppShell::jAlertsProgressListener_OnProgress = 0;
-jmethodID GeckoAppShell::jCancelVibrate = 0;
-jmethodID GeckoAppShell::jCheckURIVisited = 0;
-jmethodID GeckoAppShell::jClearMessageList = 0;
-jmethodID GeckoAppShell::jCloseCamera = 0;
-jmethodID GeckoAppShell::jCloseNotification = 0;
-jmethodID GeckoAppShell::jCreateMessageListWrapper = 0;
-jmethodID GeckoAppShell::jCreateShortcut = 0;
-jmethodID GeckoAppShell::jDeleteMessageWrapper = 0;
-jmethodID GeckoAppShell::jDisableBatteryNotifications = 0;
-jmethodID GeckoAppShell::jDisableNetworkNotifications = 0;
-jmethodID GeckoAppShell::jDisableScreenOrientationNotifications = 0;
-jmethodID GeckoAppShell::jDisableSensor = 0;
-jmethodID GeckoAppShell::jEnableBatteryNotifications = 0;
-jmethodID GeckoAppShell::jEnableLocation = 0;
-jmethodID GeckoAppShell::jEnableLocationHighAccuracy = 0;
-jmethodID GeckoAppShell::jEnableNetworkNotifications = 0;
-jmethodID GeckoAppShell::jEnableScreenOrientationNotifications = 0;
-jmethodID GeckoAppShell::jEnableSensor = 0;
-jmethodID GeckoAppShell::jGetContext = 0;
-jmethodID GeckoAppShell::jGetCurrentBatteryInformationWrapper = 0;
-jmethodID GeckoAppShell::jGetCurrentNetworkInformationWrapper = 0;
-jmethodID GeckoAppShell::jGetDensity = 0;
-jmethodID GeckoAppShell::jGetDpiWrapper = 0;
-jmethodID GeckoAppShell::jGetExtensionFromMimeTypeWrapper = 0;
-jmethodID GeckoAppShell::jGetGfxInfoDataWrapper = 0;
-jmethodID GeckoAppShell::jGetHandlersForMimeTypeWrapper = 0;
-jmethodID GeckoAppShell::jGetHandlersForURLWrapper = 0;
-jmethodID GeckoAppShell::jGetIconForExtensionWrapper = 0;
-jmethodID GeckoAppShell::jGetMessageWrapper = 0;
-jmethodID GeckoAppShell::jGetMimeTypeFromExtensionsWrapper = 0;
-jmethodID GeckoAppShell::jGetNextMessageInListWrapper = 0;
-jmethodID GeckoAppShell::jGetProxyForURIWrapper = 0;
-jmethodID GeckoAppShell::jGetScreenDepthWrapper = 0;
-jmethodID GeckoAppShell::jGetScreenOrientationWrapper = 0;
-jmethodID GeckoAppShell::jGetShowPasswordSetting = 0;
-jmethodID GeckoAppShell::jGetSystemColoursWrapper = 0;
-jmethodID GeckoAppShell::jHandleGeckoMessageWrapper = 0;
-jmethodID GeckoAppShell::jHideProgressDialog = 0;
-jmethodID GeckoAppShell::jInitCameraWrapper = 0;
-jmethodID GeckoAppShell::jIsNetworkLinkKnown = 0;
-jmethodID GeckoAppShell::jIsNetworkLinkUp = 0;
-jmethodID GeckoAppShell::jIsTablet = 0;
-jmethodID GeckoAppShell::jKillAnyZombies = 0;
-jmethodID GeckoAppShell::jLockScreenOrientation = 0;
-jmethodID GeckoAppShell::jMarkURIVisited = 0;
-jmethodID GeckoAppShell::jMoveTaskToBack = 0;
-jmethodID GeckoAppShell::jNotifyDefaultPrevented = 0;
-jmethodID GeckoAppShell::jNotifyIME = 0;
-jmethodID GeckoAppShell::jNotifyIMEChange = 0;
-jmethodID GeckoAppShell::jNotifyIMEContext = 0;
-jmethodID GeckoAppShell::jNotifyWakeLockChanged = 0;
-jmethodID GeckoAppShell::jNotifyXreExit = 0;
-jmethodID GeckoAppShell::jOpenUriExternal = 0;
-jmethodID GeckoAppShell::jPerformHapticFeedback = 0;
-jmethodID GeckoAppShell::jPumpMessageLoop = 0;
-jmethodID GeckoAppShell::jRegisterSurfaceTextureFrameListener = 0;
-jmethodID GeckoAppShell::jRemovePluginView = 0;
-jmethodID GeckoAppShell::jScanMedia = 0;
-jmethodID GeckoAppShell::jScheduleRestart = 0;
-jmethodID GeckoAppShell::jSendMessageWrapper = 0;
-jmethodID GeckoAppShell::jSetFullScreen = 0;
-jmethodID GeckoAppShell::jSetKeepScreenOn = 0;
-jmethodID GeckoAppShell::jSetSelectedLocale = 0;
-jmethodID GeckoAppShell::jSetURITitle = 0;
-jmethodID GeckoAppShell::jShowAlertNotificationWrapper = 0;
-jmethodID GeckoAppShell::jShowFilePickerAsyncWrapper = 0;
-jmethodID GeckoAppShell::jShowFilePickerForExtensionsWrapper = 0;
-jmethodID GeckoAppShell::jShowFilePickerForMimeTypeWrapper = 0;
-jmethodID GeckoAppShell::jShowInputMethodPicker = 0;
-jmethodID GeckoAppShell::jUnlockProfile = 0;
-jmethodID GeckoAppShell::jUnlockScreenOrientation = 0;
-jmethodID GeckoAppShell::jUnregisterSurfaceTextureFrameListener = 0;
-jmethodID GeckoAppShell::jVibrate1 = 0;
-jmethodID GeckoAppShell::jVibrateA = 0;
-void GeckoAppShell::InitStubs(JNIEnv *jEnv) {
+#include "AndroidBridgeUtilities.h"
+
+#ifdef DEBUG
+#define ALOG_BRIDGE(args...) ALOG(args)
+#else
+#define ALOG_BRIDGE(args...) ((void)0)
+#endif
+
+using namespace mozilla;
+void AndroidBridge::InitStubs(JNIEnv *jEnv) {
     initInit();
 
     mGeckoAppShellClass = getClassGlobalRef("org/mozilla/gecko/GeckoAppShell");
     jAcknowledgeEvent = getStaticMethod("acknowledgeEvent", "()V");
     jAddPluginViewWrapper = getStaticMethod("addPluginView", "(Landroid/view/View;FFFFZ)V");
     jAlertsProgressListener_OnProgress = getStaticMethod("alertsProgressListener_OnProgress", "(Ljava/lang/String;JJLjava/lang/String;)V");
     jCancelVibrate = getStaticMethod("cancelVibrate", "()V");
     jCheckURIVisited = getStaticMethod("checkUriVisited", "(Ljava/lang/String;)V");
@@ -165,33 +90,46 @@ void GeckoAppShell::InitStubs(JNIEnv *jE
     jShowFilePickerForExtensionsWrapper = getStaticMethod("showFilePickerForExtensions", "(Ljava/lang/String;)Ljava/lang/String;");
     jShowFilePickerForMimeTypeWrapper = getStaticMethod("showFilePickerForMimeType", "(Ljava/lang/String;)Ljava/lang/String;");
     jShowInputMethodPicker = getStaticMethod("showInputMethodPicker", "()V");
     jUnlockProfile = getStaticMethod("unlockProfile", "()Z");
     jUnlockScreenOrientation = getStaticMethod("unlockScreenOrientation", "()V");
     jUnregisterSurfaceTextureFrameListener = getStaticMethod("unregisterSurfaceTextureFrameListener", "(Ljava/lang/Object;)V");
     jVibrate1 = getStaticMethod("vibrate", "(J)V");
     jVibrateA = getStaticMethod("vibrate", "([JI)V");
+
+    mGeckoJavaSamplerClass = getClassGlobalRef("org/mozilla/gecko/GeckoJavaSampler");
+    jGetFrameNameJavaProfilingWrapper = getStaticMethod("getFrameName", "(III)Ljava/lang/String;");
+    jGetSampleTimeJavaProfiling = getStaticMethod("getSampleTime", "(II)D");
+    jGetThreadNameJavaProfilingWrapper = getStaticMethod("getThreadName", "(I)Ljava/lang/String;");
+    jPauseJavaProfiling = getStaticMethod("pause", "()V");
+    jStartJavaProfiling = getStaticMethod("start", "(II)V");
+    jStopJavaProfiling = getStaticMethod("stop", "()V");
+    jUnpauseJavaProfiling = getStaticMethod("unpause", "()V");
+
+    mThumbnailHelperClass = getClassGlobalRef("org/mozilla/gecko/ThumbnailHelper");
+    jSendThumbnail = getStaticMethod("notifyThumbnail", "(Ljava/nio/ByteBuffer;IZ)V");
+
+    mGLControllerClass = getClassGlobalRef("org/mozilla/gecko/gfx/GLController");
+    jProvideEGLSurfaceWrapper = getMethod("provideEGLSurface", "()Ljavax/microedition/khronos/egl/EGLSurface;");
+
+    mLayerViewClass = getClassGlobalRef("org/mozilla/gecko/gfx/LayerView");
+    jRegisterCompositorWrapper = getStaticMethod("registerCxxCompositor", "()Lorg/mozilla/gecko/gfx/GLController;");
+
+    mNativePanZoomControllerClass = getClassGlobalRef("org/mozilla/gecko/gfx/NativePanZoomController");
+    jPostDelayedCallbackWrapper = getMethod("postDelayedCallback", "(J)V");
+    jRequestContentRepaintWrapper = getMethod("requestContentRepaint", "(FFFFF)V");
+
+    mClipboardClass = getClassGlobalRef("org/mozilla/gecko/util/Clipboard");
+    jGetClipboardTextWrapper = getStaticMethod("getText", "()Ljava/lang/String;");
+    jSetClipboardText = getStaticMethod("setText", "(Ljava/lang/CharSequence;)V");
 }
 
-GeckoAppShell* GeckoAppShell::Wrap(jobject obj) {
-    JNIEnv *env = GetJNIForThread();
-
-    if (!env) {
-        ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
-        return NULL;
-    }
-
-    GeckoAppShell* ret = new GeckoAppShell(obj, env);
-    env->DeleteLocalRef(obj);
-    return ret;
-}
-
-void GeckoAppShell::AcknowledgeEvent() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::AcknowledgeEvent() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -203,22 +141,21 @@ void GeckoAppShell::AcknowledgeEvent() {
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::AddPluginViewWrapper(jobject a0, jfloat a1, jfloat a2, jfloat a3, jfloat a4, bool a5) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::AddPluginViewWrapper(jobject a0, jfloat a1, jfloat a2, jfloat a3, jfloat a4, bool a5) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(1) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -238,55 +175,53 @@ void GeckoAppShell::AddPluginViewWrapper
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::AlertsProgressListener_OnProgress(const nsAString& a0, int64_t a1, int64_t a2, const nsAString& a3) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::AlertsProgressListener_OnProgress(const nsAString& a0, int64_t a1, int64_t a2, const nsAString& a3) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(2) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return;
     }
 
     jvalue args[4];
-    args[0].l = AndroidBridge::NewJavaString(env, a0);
+    args[0].l = NewJavaString(env, a0);
     args[1].j = a1;
     args[2].j = a2;
-    args[3].l = AndroidBridge::NewJavaString(env, a3);
+    args[3].l = NewJavaString(env, a3);
 
     env->CallStaticVoidMethodA(mGeckoAppShellClass, jAlertsProgressListener_OnProgress, args);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::CancelVibrate() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::CancelVibrate() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -298,51 +233,49 @@ void GeckoAppShell::CancelVibrate() {
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::CheckURIVisited(const nsAString& a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::CheckURIVisited(const nsAString& a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(1) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return;
     }
 
-    jstring j0 = AndroidBridge::NewJavaString(env, a0);
+    jstring j0 = NewJavaString(env, a0);
 
     env->CallStaticVoidMethod(mGeckoAppShellClass, jCheckURIVisited, j0);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::ClearMessageList(int32_t a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::ClearMessageList(int32_t a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -354,22 +287,21 @@ void GeckoAppShell::ClearMessageList(int
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::CloseCamera() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::CloseCamera() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -381,51 +313,49 @@ void GeckoAppShell::CloseCamera() {
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::CloseNotification(const nsAString& a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::CloseNotification(const nsAString& a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(1) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return;
     }
 
-    jstring j0 = AndroidBridge::NewJavaString(env, a0);
+    jstring j0 = NewJavaString(env, a0);
 
     env->CallStaticVoidMethod(mGeckoAppShellClass, jCloseNotification, j0);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::CreateMessageListWrapper(int64_t a0, int64_t a1, jobjectArray a2, int32_t a3, int32_t a4, bool a5, int32_t a6) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::CreateMessageListWrapper(int64_t a0, int64_t a1, jobjectArray a2, int32_t a3, int32_t a4, bool a5, int32_t a6) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(1) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -446,55 +376,53 @@ void GeckoAppShell::CreateMessageListWra
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::CreateShortcut(const nsAString& a0, const nsAString& a1, const nsAString& a2, const nsAString& a3) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::CreateShortcut(const nsAString& a0, const nsAString& a1, const nsAString& a2, const nsAString& a3) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(4) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return;
     }
 
     jvalue args[4];
-    args[0].l = AndroidBridge::NewJavaString(env, a0);
-    args[1].l = AndroidBridge::NewJavaString(env, a1);
-    args[2].l = AndroidBridge::NewJavaString(env, a2);
-    args[3].l = AndroidBridge::NewJavaString(env, a3);
+    args[0].l = NewJavaString(env, a0);
+    args[1].l = NewJavaString(env, a1);
+    args[2].l = NewJavaString(env, a2);
+    args[3].l = NewJavaString(env, a3);
 
     env->CallStaticVoidMethodA(mGeckoAppShellClass, jCreateShortcut, args);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::DeleteMessageWrapper(int32_t a0, int32_t a1) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::DeleteMessageWrapper(int32_t a0, int32_t a1) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -506,22 +434,21 @@ void GeckoAppShell::DeleteMessageWrapper
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::DisableBatteryNotifications() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::DisableBatteryNotifications() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -533,22 +460,21 @@ void GeckoAppShell::DisableBatteryNotifi
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::DisableNetworkNotifications() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::DisableNetworkNotifications() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -560,22 +486,21 @@ void GeckoAppShell::DisableNetworkNotifi
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::DisableScreenOrientationNotifications() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::DisableScreenOrientationNotifications() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -587,22 +512,21 @@ void GeckoAppShell::DisableScreenOrienta
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::DisableSensor(int32_t a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::DisableSensor(int32_t a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -614,22 +538,21 @@ void GeckoAppShell::DisableSensor(int32_
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::EnableBatteryNotifications() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::EnableBatteryNotifications() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -641,22 +564,21 @@ void GeckoAppShell::EnableBatteryNotific
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::EnableLocation(bool a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::EnableLocation(bool a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -668,22 +590,21 @@ void GeckoAppShell::EnableLocation(bool 
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::EnableLocationHighAccuracy(bool a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::EnableLocationHighAccuracy(bool a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -695,22 +616,21 @@ void GeckoAppShell::EnableLocationHighAc
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::EnableNetworkNotifications() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::EnableNetworkNotifications() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -722,22 +642,21 @@ void GeckoAppShell::EnableNetworkNotific
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::EnableScreenOrientationNotifications() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::EnableScreenOrientationNotifications() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -749,22 +668,21 @@ void GeckoAppShell::EnableScreenOrientat
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::EnableSensor(int32_t a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::EnableSensor(int32_t a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -776,21 +694,20 @@ void GeckoAppShell::EnableSensor(int32_t
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-jobject GeckoAppShell::GetContext() {
+jobject AndroidBridge::GetContext() {
     JNIEnv *env = GetJNIForThread();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return nullptr;
     }
 
     if (env->PushLocalFrame(1) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
@@ -803,23 +720,22 @@ jobject GeckoAppShell::GetContext() {
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return nullptr;
     }
-
     jobject ret = static_cast<jobject>(env->PopLocalFrame(temp));
     return ret;
 }
 
-jdoubleArray GeckoAppShell::GetCurrentBatteryInformationWrapper() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+jdoubleArray AndroidBridge::GetCurrentBatteryInformationWrapper() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return nullptr;
     }
 
     if (env->PushLocalFrame(1) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -831,23 +747,22 @@ jdoubleArray GeckoAppShell::GetCurrentBa
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return nullptr;
     }
-
     jdoubleArray ret = static_cast<jdoubleArray>(env->PopLocalFrame(temp));
     return ret;
 }
 
-jdoubleArray GeckoAppShell::GetCurrentNetworkInformationWrapper() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+jdoubleArray AndroidBridge::GetCurrentNetworkInformationWrapper() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return nullptr;
     }
 
     if (env->PushLocalFrame(1) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -859,23 +774,22 @@ jdoubleArray GeckoAppShell::GetCurrentNe
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return nullptr;
     }
-
     jdoubleArray ret = static_cast<jdoubleArray>(env->PopLocalFrame(temp));
     return ret;
 }
 
-jfloat GeckoAppShell::GetDensity() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+jfloat AndroidBridge::GetDensity() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return 0.0;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -887,23 +801,22 @@ jfloat GeckoAppShell::GetDensity() {
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return 0.0;
     }
-
     env->PopLocalFrame(NULL);
     return temp;
 }
 
-int32_t GeckoAppShell::GetDpiWrapper() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+int32_t AndroidBridge::GetDpiWrapper() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return 0;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -915,53 +828,51 @@ int32_t GeckoAppShell::GetDpiWrapper() {
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return 0;
     }
-
     env->PopLocalFrame(NULL);
     return temp;
 }
 
-jstring GeckoAppShell::GetExtensionFromMimeTypeWrapper(const nsAString& a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+jstring AndroidBridge::GetExtensionFromMimeTypeWrapper(const nsAString& a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return nullptr;
     }
 
     if (env->PushLocalFrame(2) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return nullptr;
     }
 
-    jstring j0 = AndroidBridge::NewJavaString(env, a0);
+    jstring j0 = NewJavaString(env, a0);
 
     jobject temp = env->CallStaticObjectMethod(mGeckoAppShellClass, jGetExtensionFromMimeTypeWrapper, j0);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return nullptr;
     }
-
     jstring ret = static_cast<jstring>(env->PopLocalFrame(temp));
     return ret;
 }
 
-jstring GeckoAppShell::GetGfxInfoDataWrapper() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+jstring AndroidBridge::GetGfxInfoDataWrapper() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return nullptr;
     }
 
     if (env->PushLocalFrame(1) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -973,115 +884,111 @@ jstring GeckoAppShell::GetGfxInfoDataWra
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return nullptr;
     }
-
     jstring ret = static_cast<jstring>(env->PopLocalFrame(temp));
     return ret;
 }
 
-jobjectArray GeckoAppShell::GetHandlersForMimeTypeWrapper(const nsAString& a0, const nsAString& a1) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+jobjectArray AndroidBridge::GetHandlersForMimeTypeWrapper(const nsAString& a0, const nsAString& a1) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return nullptr;
     }
 
     if (env->PushLocalFrame(3) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return nullptr;
     }
 
-    jstring j0 = AndroidBridge::NewJavaString(env, a0);
-    jstring j1 = AndroidBridge::NewJavaString(env, a1);
+    jstring j0 = NewJavaString(env, a0);
+    jstring j1 = NewJavaString(env, a1);
 
     jobject temp = env->CallStaticObjectMethod(mGeckoAppShellClass, jGetHandlersForMimeTypeWrapper, j0, j1);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return nullptr;
     }
-
     jobjectArray ret = static_cast<jobjectArray>(env->PopLocalFrame(temp));
     return ret;
 }
 
-jobjectArray GeckoAppShell::GetHandlersForURLWrapper(const nsAString& a0, const nsAString& a1) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+jobjectArray AndroidBridge::GetHandlersForURLWrapper(const nsAString& a0, const nsAString& a1) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return nullptr;
     }
 
     if (env->PushLocalFrame(3) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return nullptr;
     }
 
-    jstring j0 = AndroidBridge::NewJavaString(env, a0);
-    jstring j1 = AndroidBridge::NewJavaString(env, a1);
+    jstring j0 = NewJavaString(env, a0);
+    jstring j1 = NewJavaString(env, a1);
 
     jobject temp = env->CallStaticObjectMethod(mGeckoAppShellClass, jGetHandlersForURLWrapper, j0, j1);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return nullptr;
     }
-
     jobjectArray ret = static_cast<jobjectArray>(env->PopLocalFrame(temp));
     return ret;
 }
 
-jbyteArray GeckoAppShell::GetIconForExtensionWrapper(const nsAString& a0, int32_t a1) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+jbyteArray AndroidBridge::GetIconForExtensionWrapper(const nsAString& a0, int32_t a1) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return nullptr;
     }
 
     if (env->PushLocalFrame(2) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return nullptr;
     }
 
-    jstring j0 = AndroidBridge::NewJavaString(env, a0);
+    jstring j0 = NewJavaString(env, a0);
 
     jobject temp = env->CallStaticObjectMethod(mGeckoAppShellClass, jGetIconForExtensionWrapper, j0, a1);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return nullptr;
     }
-
     jbyteArray ret = static_cast<jbyteArray>(env->PopLocalFrame(temp));
     return ret;
 }
 
-void GeckoAppShell::GetMessageWrapper(int32_t a0, int32_t a1) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::GetMessageWrapper(int32_t a0, int32_t a1) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1093,52 +1000,50 @@ void GeckoAppShell::GetMessageWrapper(in
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-jstring GeckoAppShell::GetMimeTypeFromExtensionsWrapper(const nsAString& a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+jstring AndroidBridge::GetMimeTypeFromExtensionsWrapper(const nsAString& a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return nullptr;
     }
 
     if (env->PushLocalFrame(2) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return nullptr;
     }
 
-    jstring j0 = AndroidBridge::NewJavaString(env, a0);
+    jstring j0 = NewJavaString(env, a0);
 
     jobject temp = env->CallStaticObjectMethod(mGeckoAppShellClass, jGetMimeTypeFromExtensionsWrapper, j0);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return nullptr;
     }
-
     jstring ret = static_cast<jstring>(env->PopLocalFrame(temp));
     return ret;
 }
 
-void GeckoAppShell::GetNextMessageInListWrapper(int32_t a0, int32_t a1) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::GetNextMessageInListWrapper(int32_t a0, int32_t a1) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1150,56 +1055,54 @@ void GeckoAppShell::GetNextMessageInList
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-jstring GeckoAppShell::GetProxyForURIWrapper(const nsAString& a0, const nsAString& a1, const nsAString& a2, int32_t a3) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+jstring AndroidBridge::GetProxyForURIWrapper(const nsAString& a0, const nsAString& a1, const nsAString& a2, int32_t a3) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return nullptr;
     }
 
     if (env->PushLocalFrame(4) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return nullptr;
     }
 
     jvalue args[4];
-    args[0].l = AndroidBridge::NewJavaString(env, a0);
-    args[1].l = AndroidBridge::NewJavaString(env, a1);
-    args[2].l = AndroidBridge::NewJavaString(env, a2);
+    args[0].l = NewJavaString(env, a0);
+    args[1].l = NewJavaString(env, a1);
+    args[2].l = NewJavaString(env, a2);
     args[3].i = a3;
 
     jobject temp = env->CallStaticObjectMethodA(mGeckoAppShellClass, jGetProxyForURIWrapper, args);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return nullptr;
     }
-
     jstring ret = static_cast<jstring>(env->PopLocalFrame(temp));
     return ret;
 }
 
-int32_t GeckoAppShell::GetScreenDepthWrapper() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+int32_t AndroidBridge::GetScreenDepthWrapper() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return 0;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1211,23 +1114,22 @@ int32_t GeckoAppShell::GetScreenDepthWra
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return 0;
     }
-
     env->PopLocalFrame(NULL);
     return temp;
 }
 
-int16_t GeckoAppShell::GetScreenOrientationWrapper() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+int16_t AndroidBridge::GetScreenOrientationWrapper() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return 0;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1239,23 +1141,22 @@ int16_t GeckoAppShell::GetScreenOrientat
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return 0;
     }
-
     env->PopLocalFrame(NULL);
     return temp;
 }
 
-bool GeckoAppShell::GetShowPasswordSetting() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+bool AndroidBridge::GetShowPasswordSetting() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return false;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1267,23 +1168,22 @@ bool GeckoAppShell::GetShowPasswordSetti
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return false;
     }
-
     env->PopLocalFrame(NULL);
     return temp;
 }
 
-jintArray GeckoAppShell::GetSystemColoursWrapper() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+jintArray AndroidBridge::GetSystemColoursWrapper() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return nullptr;
     }
 
     if (env->PushLocalFrame(1) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1295,53 +1195,51 @@ jintArray GeckoAppShell::GetSystemColour
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return nullptr;
     }
-
     jintArray ret = static_cast<jintArray>(env->PopLocalFrame(temp));
     return ret;
 }
 
-jstring GeckoAppShell::HandleGeckoMessageWrapper(const nsAString& a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+jstring AndroidBridge::HandleGeckoMessageWrapper(const nsAString& a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return nullptr;
     }
 
     if (env->PushLocalFrame(2) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return nullptr;
     }
 
-    jstring j0 = AndroidBridge::NewJavaString(env, a0);
+    jstring j0 = NewJavaString(env, a0);
 
     jobject temp = env->CallStaticObjectMethod(mGeckoAppShellClass, jHandleGeckoMessageWrapper, j0);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return nullptr;
     }
-
     jstring ret = static_cast<jstring>(env->PopLocalFrame(temp));
     return ret;
 }
 
-void GeckoAppShell::HideProgressDialog() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::HideProgressDialog() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1353,56 +1251,54 @@ void GeckoAppShell::HideProgressDialog()
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-jintArray GeckoAppShell::InitCameraWrapper(const nsAString& a0, int32_t a1, int32_t a2, int32_t a3) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+jintArray AndroidBridge::InitCameraWrapper(const nsAString& a0, int32_t a1, int32_t a2, int32_t a3) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return nullptr;
     }
 
     if (env->PushLocalFrame(2) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return nullptr;
     }
 
     jvalue args[4];
-    args[0].l = AndroidBridge::NewJavaString(env, a0);
+    args[0].l = NewJavaString(env, a0);
     args[1].i = a1;
     args[2].i = a2;
     args[3].i = a3;
 
     jobject temp = env->CallStaticObjectMethodA(mGeckoAppShellClass, jInitCameraWrapper, args);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return nullptr;
     }
-
     jintArray ret = static_cast<jintArray>(env->PopLocalFrame(temp));
     return ret;
 }
 
-bool GeckoAppShell::IsNetworkLinkKnown() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+bool AndroidBridge::IsNetworkLinkKnown() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return false;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1414,23 +1310,22 @@ bool GeckoAppShell::IsNetworkLinkKnown()
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return false;
     }
-
     env->PopLocalFrame(NULL);
     return temp;
 }
 
-bool GeckoAppShell::IsNetworkLinkUp() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+bool AndroidBridge::IsNetworkLinkUp() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return false;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1442,23 +1337,22 @@ bool GeckoAppShell::IsNetworkLinkUp() {
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return false;
     }
-
     env->PopLocalFrame(NULL);
     return temp;
 }
 
-bool GeckoAppShell::IsTablet() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+bool AndroidBridge::IsTablet() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return false;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1470,23 +1364,22 @@ bool GeckoAppShell::IsTablet() {
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return false;
     }
-
     env->PopLocalFrame(NULL);
     return temp;
 }
 
-void GeckoAppShell::KillAnyZombies() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::KillAnyZombies() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1498,22 +1391,21 @@ void GeckoAppShell::KillAnyZombies() {
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::LockScreenOrientation(int32_t a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::LockScreenOrientation(int32_t a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1525,51 +1417,49 @@ void GeckoAppShell::LockScreenOrientatio
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::MarkURIVisited(const nsAString& a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::MarkURIVisited(const nsAString& a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(1) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return;
     }
 
-    jstring j0 = AndroidBridge::NewJavaString(env, a0);
+    jstring j0 = NewJavaString(env, a0);
 
     env->CallStaticVoidMethod(mGeckoAppShellClass, jMarkURIVisited, j0);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::MoveTaskToBack() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::MoveTaskToBack() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1581,22 +1471,21 @@ void GeckoAppShell::MoveTaskToBack() {
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::NotifyDefaultPrevented(bool a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::NotifyDefaultPrevented(bool a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1608,145 +1497,155 @@ void GeckoAppShell::NotifyDefaultPrevent
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::NotifyIME(int32_t a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::NotifyIME(int32_t a0) {
+    if (!sBridge) {
+        ALOG_BRIDGE("Aborted: No sBridge - %s", __PRETTY_FUNCTION__);
+        return;
+    }
+
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return;
     }
 
-    env->CallStaticVoidMethod(mGeckoAppShellClass, jNotifyIME, a0);
+    env->CallStaticVoidMethod(sBridge->mGeckoAppShellClass, sBridge->jNotifyIME, a0);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::NotifyIMEChange(const nsAString& a0, int32_t a1, int32_t a2, int32_t a3) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::NotifyIMEChange(const nsAString& a0, int32_t a1, int32_t a2, int32_t a3) {
+    if (!sBridge) {
+        ALOG_BRIDGE("Aborted: No sBridge - %s", __PRETTY_FUNCTION__);
+        return;
+    }
+
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(1) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return;
     }
 
     jvalue args[4];
-    args[0].l = AndroidBridge::NewJavaString(env, a0);
+    args[0].l = NewJavaString(env, a0);
     args[1].i = a1;
     args[2].i = a2;
     args[3].i = a3;
 
-    env->CallStaticVoidMethodA(mGeckoAppShellClass, jNotifyIMEChange, args);
+    env->CallStaticVoidMethodA(sBridge->mGeckoAppShellClass, sBridge->jNotifyIMEChange, args);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::NotifyIMEContext(int32_t a0, const nsAString& a1, const nsAString& a2, const nsAString& a3) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::NotifyIMEContext(int32_t a0, const nsAString& a1, const nsAString& a2, const nsAString& a3) {
+    if (!sBridge) {
+        ALOG_BRIDGE("Aborted: No sBridge - %s", __PRETTY_FUNCTION__);
+        return;
+    }
+
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(3) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return;
     }
 
     jvalue args[4];
     args[0].i = a0;
-    args[1].l = AndroidBridge::NewJavaString(env, a1);
-    args[2].l = AndroidBridge::NewJavaString(env, a2);
-    args[3].l = AndroidBridge::NewJavaString(env, a3);
-
-    env->CallStaticVoidMethodA(mGeckoAppShellClass, jNotifyIMEContext, args);
+    args[1].l = NewJavaString(env, a1);
+    args[2].l = NewJavaString(env, a2);
+    args[3].l = NewJavaString(env, a3);
+
+    env->CallStaticVoidMethodA(sBridge->mGeckoAppShellClass, sBridge->jNotifyIMEContext, args);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::NotifyWakeLockChanged(const nsAString& a0, const nsAString& a1) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::NotifyWakeLockChanged(const nsAString& a0, const nsAString& a1) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(2) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return;
     }
 
-    jstring j0 = AndroidBridge::NewJavaString(env, a0);
-    jstring j1 = AndroidBridge::NewJavaString(env, a1);
+    jstring j0 = NewJavaString(env, a0);
+    jstring j1 = NewJavaString(env, a1);
 
     env->CallStaticVoidMethod(mGeckoAppShellClass, jNotifyWakeLockChanged, j0, j1);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::NotifyXreExit() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::NotifyXreExit() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1758,58 +1657,56 @@ void GeckoAppShell::NotifyXreExit() {
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-bool GeckoAppShell::OpenUriExternal(const nsAString& a0, const nsAString& a1, const nsAString& a2, const nsAString& a3, const nsAString& a4, const nsAString& a5) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+bool AndroidBridge::OpenUriExternal(const nsAString& a0, const nsAString& a1, const nsAString& a2, const nsAString& a3, const nsAString& a4, const nsAString& a5) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return false;
     }
 
     if (env->PushLocalFrame(6) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return false;
     }
 
     jvalue args[6];
-    args[0].l = AndroidBridge::NewJavaString(env, a0);
-    args[1].l = AndroidBridge::NewJavaString(env, a1);
-    args[2].l = AndroidBridge::NewJavaString(env, a2);
-    args[3].l = AndroidBridge::NewJavaString(env, a3);
-    args[4].l = AndroidBridge::NewJavaString(env, a4);
-    args[5].l = AndroidBridge::NewJavaString(env, a5);
+    args[0].l = NewJavaString(env, a0);
+    args[1].l = NewJavaString(env, a1);
+    args[2].l = NewJavaString(env, a2);
+    args[3].l = NewJavaString(env, a3);
+    args[4].l = NewJavaString(env, a4);
+    args[5].l = NewJavaString(env, a5);
 
     bool temp = env->CallStaticBooleanMethodA(mGeckoAppShellClass, jOpenUriExternal, args);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return false;
     }
-
     env->PopLocalFrame(NULL);
     return temp;
 }
 
-void GeckoAppShell::PerformHapticFeedback(bool a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::PerformHapticFeedback(bool a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1821,22 +1718,21 @@ void GeckoAppShell::PerformHapticFeedbac
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-bool GeckoAppShell::PumpMessageLoop() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+bool AndroidBridge::PumpMessageLoop() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return false;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1848,23 +1744,22 @@ bool GeckoAppShell::PumpMessageLoop() {
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return false;
     }
-
     env->PopLocalFrame(NULL);
     return temp;
 }
 
-void GeckoAppShell::RegisterSurfaceTextureFrameListener(jobject a0, int32_t a1) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::RegisterSurfaceTextureFrameListener(jobject a0, int32_t a1) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(1) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1876,22 +1771,21 @@ void GeckoAppShell::RegisterSurfaceTextu
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::RemovePluginView(jobject a0, bool a1) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::RemovePluginView(jobject a0, bool a1) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(1) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1903,52 +1797,50 @@ void GeckoAppShell::RemovePluginView(job
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::ScanMedia(const nsAString& a0, const nsAString& a1) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::ScanMedia(const nsAString& a0, const nsAString& a1) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(2) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return;
     }
 
-    jstring j0 = AndroidBridge::NewJavaString(env, a0);
-    jstring j1 = AndroidBridge::NewJavaString(env, a1);
+    jstring j0 = NewJavaString(env, a0);
+    jstring j1 = NewJavaString(env, a1);
 
     env->CallStaticVoidMethod(mGeckoAppShellClass, jScanMedia, j0, j1);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::ScheduleRestart() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::ScheduleRestart() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -1960,54 +1852,52 @@ void GeckoAppShell::ScheduleRestart() {
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::SendMessageWrapper(const nsAString& a0, const nsAString& a1, int32_t a2) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::SendMessageWrapper(const nsAString& a0, const nsAString& a1, int32_t a2) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(2) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return;
     }
 
     jvalue args[3];
-    args[0].l = AndroidBridge::NewJavaString(env, a0);
-    args[1].l = AndroidBridge::NewJavaString(env, a1);
+    args[0].l = NewJavaString(env, a0);
+    args[1].l = NewJavaString(env, a1);
     args[2].i = a2;
 
     env->CallStaticVoidMethodA(mGeckoAppShellClass, jSendMessageWrapper, args);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::SetFullScreen(bool a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::SetFullScreen(bool a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -2019,22 +1909,21 @@ void GeckoAppShell::SetFullScreen(bool a
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::SetKeepScreenOn(bool a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::SetKeepScreenOn(bool a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -2046,204 +1935,197 @@ void GeckoAppShell::SetKeepScreenOn(bool
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::SetSelectedLocale(const nsAString& a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::SetSelectedLocale(const nsAString& a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(1) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return;
     }
 
-    jstring j0 = AndroidBridge::NewJavaString(env, a0);
+    jstring j0 = NewJavaString(env, a0);
 
     env->CallStaticVoidMethod(mGeckoAppShellClass, jSetSelectedLocale, j0);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::SetURITitle(const nsAString& a0, const nsAString& a1) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::SetURITitle(const nsAString& a0, const nsAString& a1) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(2) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return;
     }
 
-    jstring j0 = AndroidBridge::NewJavaString(env, a0);
-    jstring j1 = AndroidBridge::NewJavaString(env, a1);
+    jstring j0 = NewJavaString(env, a0);
+    jstring j1 = NewJavaString(env, a1);
 
     env->CallStaticVoidMethod(mGeckoAppShellClass, jSetURITitle, j0, j1);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::ShowAlertNotificationWrapper(const nsAString& a0, const nsAString& a1, const nsAString& a2, const nsAString& a3, const nsAString& a4) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::ShowAlertNotificationWrapper(const nsAString& a0, const nsAString& a1, const nsAString& a2, const nsAString& a3, const nsAString& a4) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(5) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return;
     }
 
     jvalue args[5];
-    args[0].l = AndroidBridge::NewJavaString(env, a0);
-    args[1].l = AndroidBridge::NewJavaString(env, a1);
-    args[2].l = AndroidBridge::NewJavaString(env, a2);
-    args[3].l = AndroidBridge::NewJavaString(env, a3);
-    args[4].l = AndroidBridge::NewJavaString(env, a4);
+    args[0].l = NewJavaString(env, a0);
+    args[1].l = NewJavaString(env, a1);
+    args[2].l = NewJavaString(env, a2);
+    args[3].l = NewJavaString(env, a3);
+    args[4].l = NewJavaString(env, a4);
 
     env->CallStaticVoidMethodA(mGeckoAppShellClass, jShowAlertNotificationWrapper, args);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-void GeckoAppShell::ShowFilePickerAsyncWrapper(const nsAString& a0, int64_t a1) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::ShowFilePickerAsyncWrapper(const nsAString& a0, int64_t a1) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(1) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return;
     }
 
-    jstring j0 = AndroidBridge::NewJavaString(env, a0);
+    jstring j0 = NewJavaString(env, a0);
 
     env->CallStaticVoidMethod(mGeckoAppShellClass, jShowFilePickerAsyncWrapper, j0, a1);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-jstring GeckoAppShell::ShowFilePickerForExtensionsWrapper(const nsAString& a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+jstring AndroidBridge::ShowFilePickerForExtensionsWrapper(const nsAString& a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return nullptr;
     }
 
     if (env->PushLocalFrame(2) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return nullptr;
     }
 
-    jstring j0 = AndroidBridge::NewJavaString(env, a0);
+    jstring j0 = NewJavaString(env, a0);
 
     jobject temp = env->CallStaticObjectMethod(mGeckoAppShellClass, jShowFilePickerForExtensionsWrapper, j0);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return nullptr;
     }
-
     jstring ret = static_cast<jstring>(env->PopLocalFrame(temp));
     return ret;
 }
 
-jstring GeckoAppShell::ShowFilePickerForMimeTypeWrapper(const nsAString& a0) {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+jstring AndroidBridge::ShowFilePickerForMimeTypeWrapper(const nsAString& a0) {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return nullptr;
     }
 
     if (env->PushLocalFrame(2) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         return nullptr;
     }
 
-    jstring j0 = AndroidBridge::NewJavaString(env, a0);
+    jstring j0 = NewJavaString(env, a0);
 
     jobject temp = env->CallStaticObjectMethod(mGeckoAppShellClass, jShowFilePickerForMimeTypeWrapper, j0);
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return nullptr;
     }
-
     jstring ret = static_cast<jstring>(env->PopLocalFrame(temp));
     return ret;
 }
 
-void GeckoAppShell::ShowInputMethodPicker() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+void AndroidBridge::ShowInputMethodPicker() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -2255,22 +2137,21 @@ void GeckoAppShell::ShowInputMethodPicke
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return;
     }
-
     env->PopLocalFrame(NULL);
 }
 
-bool GeckoAppShell::UnlockProfile() {
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
+bool AndroidBridge::UnlockProfile() {
+    JNIEnv *env = GetJNIEnv();
     if (!env) {
         ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__);
         return false;
     }
 
     if (env->PushLocalFrame(0) != 0) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
@@ -2282,23 +2163,22 @@ bool GeckoAppShell::UnlockProfile() {
 
     if (env->ExceptionCheck()) {
         ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__);
         env->ExceptionDescribe();
         env->ExceptionClear();
         env->PopLocalFrame(NULL);
         return false;
     }