author | Wes Kocher <wkocher@mozilla.com> |
Thu, 21 Nov 2013 19:16:50 -0800 | |
changeset 156937 | dbf94e314cde175900e0d95d211f7d163bafe4c9 |
parent 156918 | d93ca560b15c3473400f16fc7b5661b6a9f907d5 (current diff) |
parent 156936 | 5c11b81a0c9191ad78786fcd28c361d0f23d52a6 (diff) |
child 156983 | 7a703a1f974b5f3c44b11e40699013d47d57748c |
child 157013 | cff1826bfddbe9c33ae0d91c0cac57f0e2c27303 |
child 157025 | b2a0444bc991771fb68e92937c5b011586fee98d |
child 161492 | bd5d668bbac482e5203a1cfef5a8c208e94e9ba4 |
push id | 25693 |
push user | kwierso@gmail.com |
push date | Fri, 22 Nov 2013 03:17:02 +0000 |
treeherder | mozilla-central@dbf94e314cde [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
milestone | 28.0a1 |
first release with | nightly linux32
dbf94e314cde
/
28.0a1
/
20131122030202
/
files
nightly linux64
dbf94e314cde
/
28.0a1
/
20131122030202
/
files
nightly mac
dbf94e314cde
/
28.0a1
/
20131122030202
/
files
nightly win32
dbf94e314cde
/
28.0a1
/
20131122030202
/
files
nightly win64
dbf94e314cde
/
28.0a1
/
20131122030202
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
28.0a1
/
20131122030202
/
pushlog to previous
nightly linux64
28.0a1
/
20131122030202
/
pushlog to previous
nightly mac
28.0a1
/
20131122030202
/
pushlog to previous
nightly win32
28.0a1
/
20131122030202
/
pushlog to previous
nightly win64
28.0a1
/
20131122030202
/
pushlog to previous
|
build/annotationProcessors/MethodWithAnnotationInfo.java | file | annotate | diff | comparison | revisions | |
build/annotationProcessors/utils/AlphabeticMethodComparator.java | file | annotate | diff | comparison | revisions | |
build/annotationProcessors/utils/GeneratableEntryPointIterator.java | file | annotate | diff | comparison | revisions | |
mobile/android/base/mozglue/GeneratableAndroidBridgeTarget.java | file | annotate | diff | comparison | revisions | |
mobile/android/base/mozglue/OptionalGeneratedParameter.java | file | annotate | diff | comparison | revisions |
--- a/browser/base/content/test/general/browser.ini +++ b/browser/base/content/test/general/browser.ini @@ -107,16 +107,18 @@ run-if = crashreporter [browser_CTP_nonplugins.js] [browser_CTP_resize.js] [browser_URLBarSetURI.js] [browser_aboutHealthReport.js] [browser_aboutHome.js] [browser_aboutSyncProgress.js] [browser_addKeywordSearch.js] [browser_alltabslistener.js] +[browser_backButtonFitts.js] +skip-if = os != "win" # The Fitts Law back button is only supported on Windows (bug 571454) [browser_blob-channelname.js] [browser_bookmark_titles.js] skip-if = toolkit == "windows" # Disabled on Windows due to frequent failures (bugs 825739, 841341) [browser_bug304198.js] [browser_bug321000.js] skip-if = true # browser_bug321000.js is disabled because newline handling is shaky (bug 592528) [browser_bug329212.js] [browser_bug356571.js]
new file mode 100644 --- /dev/null +++ b/browser/base/content/test/general/browser_backButtonFitts.js @@ -0,0 +1,30 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +function test () { + waitForExplicitFinish(); + var firstLocation = "http://example.org/browser/browser/base/content/test/general/dummy_page.html"; + gBrowser.selectedTab = gBrowser.addTab(firstLocation); + gBrowser.selectedBrowser.addEventListener("pageshow", function onPageShow1() { + gBrowser.selectedBrowser.removeEventListener("pageshow", onPageShow1); + gBrowser.selectedBrowser.contentWindow.history.pushState("page2", "page2", "page2"); + window.maximize(); + + // Find where the nav-bar is vertically. + var navBar = document.getElementById("nav-bar"); + var boundingRect = navBar.getBoundingClientRect(); + var yPixel = boundingRect.top + Math.floor(boundingRect.height / 2); + var xPixel = 0; // Use the first pixel of the screen since it is maximized. + + gBrowser.selectedBrowser.contentWindow.addEventListener("popstate", function onPopState() { + gBrowser.selectedBrowser.contentWindow.removeEventListener("popstate", onPopState); + is(gBrowser.selectedBrowser.contentDocument.location.href, firstLocation, + "Clicking the first pixel should have navigated back."); + window.restore(); + gBrowser.removeCurrentTab(); + finish(); + }); + EventUtils.synthesizeMouseAtPoint(xPixel, yPixel, {}, window); + }); +}
--- a/browser/components/sessionstore/test/browser_625016.js +++ b/browser/components/sessionstore/test/browser_625016.js @@ -35,27 +35,31 @@ function setup() { is(ss.getClosedWindowCount(), 0, "starting with no closed windows"); // Open a new window, which should trigger a save event soon. waitForSaveState(onSaveState); newWin = openDialog(location, "_blank", "chrome,all,dialog=no", "about:rights"); } function onSaveState() { + try { + ss.getWindowValue(newWin, "foobar"); + } catch (e) { + // The window is untracked which means that the saveState() call isn't the + // one we're waiting for. It's most likely been triggered by an async + // collection running in the background. + waitForSaveState(onSaveState); + return; + } + // Double check that we have no closed windows is(ss.getClosedWindowCount(), 0, "no closed windows on first save"); Services.obs.addObserver(observe1, "sessionstore-state-write", false); - try { - ss.getWindowValue(newWin, "foobar"); - } catch (e) { - ok(false, "window is untracked!"); - } - // Now close the new window, which should trigger another save event newWin.close(); } function observe1(aSubject, aTopic, aData) { info("observe1: " + aTopic); switch (aTopic) { case "sessionstore-state-write":
--- a/browser/devtools/shared/test/browser_outputparser.js +++ b/browser/devtools/shared/test/browser_outputparser.js @@ -44,31 +44,46 @@ function testParseCssProperty() { testParseHTMLAttribute(); } function testParseHTMLAttribute() { let attrib = "color:red; font-size: 12px; background-image: " + "url(chrome://branding/content/about-logo.png)"; let frag = parser.parseHTMLAttribute(attrib, { - colorSwatchClass: "test-colorswatch", urlClass: "theme-link" }); let target = doc.querySelector("div"); ok(target, "captain, we have the div"); target.appendChild(frag); - let expected = 'color:<span style="background-color:red" ' + - 'class="test-colorswatch"></span>#F00; font-size: 12px; ' + + let expected = 'color:#F00; font-size: 12px; ' + 'background-image: url(\'<a href="chrome://branding/content/about-logo.png" ' + 'class="theme-link" ' + 'target="_blank">chrome://branding/content/about-logo.png</a>\')'; is(target.innerHTML, expected, "HTML Attribute correctly parsed"); + target.innerHTML = ""; + testParseNonCssHTMLAttribute(); +} + +function testParseNonCssHTMLAttribute() { + let attrib = "someclass background someotherclass red"; + let frag = parser.parseHTMLAttribute(attrib); + + let target = doc.querySelector("div"); + ok(target, "captain, we have the div"); + target.appendChild(frag); + + let expected = 'someclass background someotherclass red'; + + is(target.innerHTML, expected, "Non-CSS HTML Attribute correctly parsed"); + target.innerHTML = ""; finishUp(); } + function finishUp() { Services = Loader = OutputParser = parser = doc = null; gBrowser.removeCurrentTab(); finish(); }
--- a/browser/devtools/sourceeditor/editor.js +++ b/browser/devtools/sourceeditor/editor.js @@ -52,17 +52,17 @@ const CM_SCRIPTS = [ const CM_IFRAME = "data:text/html;charset=utf8,<!DOCTYPE html>" + "<html dir='ltr'>" + " <head>" + " <style>" + " html, body { height: 100%; }" + " body { margin: 0; overflow: hidden; }" + - " .CodeMirror { width: 100%; height: 100% !important; }" + + " .CodeMirror { width: 100%; height: 100% !important; line-height: normal!important}" + " </style>" + [ " <link rel='stylesheet' href='" + style + "'>" for (style of CM_STYLES) ].join("\n") + " </head>" + " <body class='theme-body devtools-monospace'></body>" + "</html>"; const CM_MAPPING = [ "focus",
--- a/browser/metro/base/content/contenthandlers/Content.js +++ b/browser/metro/base/content/contenthandlers/Content.js @@ -44,16 +44,18 @@ let HTMLFrameElement = Ci.nsIDOMHTMLFram let HTMLFrameSetElement = Ci.nsIDOMHTMLFrameSetElement; let HTMLSelectElement = Ci.nsIDOMHTMLSelectElement; let HTMLOptionElement = Ci.nsIDOMHTMLOptionElement; const kReferenceDpi = 240; // standard "pixel" size used in some preferences const kStateActive = 0x00000001; // :active pseudoclass for elements +const kZoomToElementMargin = 16; // in px + /* * getBoundingContentRect * * @param aElement * @return Bounding content rect adjusted for scroll and frame offsets. */ function getBoundingContentRect(aElement) { if (!aElement) @@ -390,46 +392,47 @@ let Content = { this._zoomToElement(aElement); } }, /****************************************************** * Zoom utilities */ _zoomOut: function() { - let rect = getBoundingContentRect(content.document.documentElement); - - let utils = Util.getWindowUtils(content); - let viewId = utils.getViewId(content.document.documentElement); - let presShellId = {}; - utils.getPresShellId(presShellId); - let zoomData = [rect.x, - rect.y, - rect.width, - rect.height, - presShellId.value, - viewId].join(","); - Services.obs.notifyObservers(null, "Metro:ZoomToRect", zoomData); + let rect = new Rect(0,0,0,0); + this._zoomToRect(rect); this._isZoomedIn = false; }, _zoomToElement: function(aElement) { let rect = getBoundingContentRect(aElement); + this._inflateRect(rect, kZoomToElementMargin); + this._zoomToRect(rect); + this._isZoomedIn = true; + }, + + _inflateRect: function(aRect, aMargin) { + aRect.left -= aMargin; + aRect.top -= aMargin; + aRect.bottom += aMargin; + aRect.right += aMargin; + }, + + _zoomToRect: function (aRect) { let utils = Util.getWindowUtils(content); let viewId = utils.getViewId(content.document.documentElement); let presShellId = {}; utils.getPresShellId(presShellId); - let zoomData = [rect.x, - rect.y, - rect.width, - rect.height, + let zoomData = [aRect.x, + aRect.y, + aRect.width, + aRect.height, presShellId.value, viewId].join(","); Services.obs.notifyObservers(null, "Metro:ZoomToRect", zoomData); - this._isZoomedIn = true; }, _shouldZoomToElement: function(aElement) { let win = aElement.ownerDocument.defaultView; if (win.getComputedStyle(aElement, null).display == "inline") { return false; } else if (aElement instanceof Ci.nsIDOMHTMLLIElement) {
--- a/browser/themes/osx/devtools/common.css +++ b/browser/themes/osx/devtools/common.css @@ -7,17 +7,17 @@ /* Font for code */ :root { font: message-box; } .devtools-monospace { - font-family: monospace; + font-family: Menlo, monospace; font-size: 108%; } /* Toolbar and Toolbar items */ .devtools-toolbar { -moz-appearance: none; padding: 4px 3px;
--- a/browser/themes/windows/devtools/common.css +++ b/browser/themes/windows/devtools/common.css @@ -5,17 +5,17 @@ /* Font for code */ :root { font: message-box; } .devtools-monospace { - font-family: monospace; + font-family: Consolas, monospace; } /* Toolbar and Toolbar items */ .devtools-toolbar { -moz-appearance: none; padding: 4px 3px; color: hsl(210,30%,85%);
rename from build/annotationProcessors/MethodWithAnnotationInfo.java rename to build/annotationProcessors/AnnotationInfo.java --- a/build/annotationProcessors/MethodWithAnnotationInfo.java +++ b/build/annotationProcessors/AnnotationInfo.java @@ -1,24 +1,20 @@ /* 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 method and annotation. Used by GeneratableEntryPointIterator. + * Object holding annotation data. Used by GeneratableElementIterator. */ -public class MethodWithAnnotationInfo { - public final Method method; +public class AnnotationInfo { public final String wrapperName; public final boolean isStatic; public final boolean isMultithreaded; - public MethodWithAnnotationInfo(Method aMethod, String aWrapperName, boolean aIsStatic, boolean aIsMultithreaded) { - method = aMethod; + public AnnotationInfo(String aWrapperName, boolean aIsStatic, boolean aIsMultithreaded) { wrapperName = aWrapperName; isStatic = aIsStatic; isMultithreaded = aIsMultithreaded; } }
--- a/build/annotationProcessors/AnnotationProcessor.java +++ b/build/annotationProcessors/AnnotationProcessor.java @@ -1,26 +1,34 @@ /* 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.GeneratableEntryPointIterator; +import org.mozilla.gecko.annotationProcessors.utils.GeneratableElementIterator; 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..."); @@ -28,49 +36,126 @@ 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<Class<?>> jarClassIterator = IterableJarLoadingURLClassLoader.getIteratorOverJars(args); + 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"); - CodeGenerator generatorInstance = new CodeGenerator(); + 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"); while (jarClassIterator.hasNext()) { - Class<?> aClass = jarClassIterator.next(); + ClassWithOptions aClassTuple = jarClassIterator.next(); + + CodeGenerator generatorInstance; // Get an iterator over the appropriately generated methods of this class - Iterator<MethodWithAnnotationInfo> methodIterator = new GeneratableEntryPointIterator(aClass.getDeclaredMethods()); + Iterator<AnnotatableEntity> methodIterator = new GeneratableElementIterator(aClassTuple.wrappedClass); + + if (!methodIterator.hasNext()) { + continue; + } + generatorInstance = new CodeGenerator(aClassTuple.wrappedClass, aClassTuple.generatedName); + + stubInitialiser.append(" ").append(aClassTuple.generatedName).append("::InitStubs(jEnv);\n"); - // Iterate all annotated methods in this class.. + // Iterate all annotated members in this class.. while (methodIterator.hasNext()) { - MethodWithAnnotationInfo aMethodTuple = methodIterator.next(); - generatorInstance.generateMethod(aMethodTuple, aClass); + 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; + } } + headerFile.append(generatorInstance.getHeaderFileContents()); + implementationFile.append(generatorInstance.getWrapperFileContents()); } - writeOutputFiles(generatorInstance); + 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); long e = System.currentTimeMillis(); System.out.println("Annotation processing complete in " + (e - s) + "ms"); } - private static void writeOutputFiles(CodeGenerator aGenerator) { + private static void writeOutputFiles(StringBuilder aHeaderFile, StringBuilder aImplementationFile) { + FileOutputStream headerStream = null; try { - FileOutputStream outStream = new FileOutputStream(OUTFILE); - outStream.write(aGenerator.getWrapperFileContents()); + headerStream = new FileOutputStream(OUTFILE); + headerStream.write(aImplementationFile.toString().getBytes()); } 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 { - FileOutputStream headerStream = new FileOutputStream(HEADERFILE); - headerStream.write(aGenerator.getHeaderFileContents()); + outStream = new FileOutputStream(HEADERFILE); + outStream.write(aHeaderFile.toString().getBytes()); } catch (IOException e) { - System.err.println("Unable to write " + OUTFILE + ". Perhaps a permissions issue?"); + System.err.println("Unable to write " + HEADERFILE + ". 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,336 +1,618 @@ /* 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 headerFields = new StringBuilder(); - private final StringBuilder headerMethods = new StringBuilder(); + private final StringBuilder headerPublic = new StringBuilder(); + private final StringBuilder headerProtected = new StringBuilder(); private final HashSet<String> seenClasses = new HashSet<String>(); - 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"; + private final String mCClassName; + + private final Class<?> mClassToWrap; + + private boolean mHasEncounteredDefaultConstructor; - public CodeGenerator() { + // 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; + // 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 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"); + // wrapperMethodBodies. Similarly, GeneratedJNIWrappers.h is the concatenation of headerPublic + // with headerProtected. + wrapperStartupCode.append("void ").append(mCClassName).append("::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:"); - headerFields.append("protected:\n\n"); - headerMethods.append(GENERATED_COMMENT); - headerMethods.append("public:\n\n"); + 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); } /** * Append the appropriate generated code to the buffers for the method provided. * - * @param aMethodTuple The Java method, plus the name for the generated method. - * @param aClass The class to which the Java method belongs. + * @param aMethodTuple The Java method, plus annotation data. */ - public void generateMethod(MethodWithAnnotationInfo aMethodTuple, Class<?> aClass) { + public void generateMethod(AnnotatableEntity aMethodTuple) { // Unpack the tuple and extract some useful fields from the Method.. - Method aMethod = aMethodTuple.method; - String CMethodName = aMethodTuple.wrapperName; + Method theMethod = aMethodTuple.getMethod(); - String javaMethodName = aMethod.getName(); + String CMethodName = aMethodTuple.mAnnotationInfo.wrapperName; + + generateMemberCommon(theMethod, CMethodName, mClassToWrap); - ensureClassHeaderAndStartup(aClass); + boolean isFieldStatic = Utils.isMemberStatic(theMethod); + boolean shallGenerateStatic = isFieldStatic || aMethodTuple.mAnnotationInfo.isStatic; - writeHeaderField(CMethodName); - writeStartupCode(CMethodName, javaMethodName, aMethod, aClass); + Class<?>[] parameterTypes = theMethod.getParameterTypes(); + Class<?> returnType = theMethod.getReturnType(); // Get the C++ method signature for this method. - String implementationSignature = Utils.getCImplementationMethodSignature(aMethod, CMethodName); - String headerSignature = Utils.getCHeaderMethodSignature(aMethod, CMethodName, aMethodTuple.isStatic); + String implementationSignature = Utils.getCImplementationMethodSignature(parameterTypes, returnType, CMethodName, mCClassName); + String headerSignature = Utils.getCHeaderMethodSignature(parameterTypes, theMethod.getParameterAnnotations(), returnType, CMethodName, mCClassName, shallGenerateStatic); // Add the header signature to the header file. - headerMethods.append(headerSignature); - headerMethods.append(";\n"); + writeSignatureToHeader(headerSignature); // Use the implementation signature to generate the method body... - writeMethodBody(implementationSignature, CMethodName, aMethod, aClass, aMethodTuple.isStatic, aMethodTuple.isMultithreaded); + 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; + } } /** * 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... - headerFields.append("\njclass "); - headerFields.append(Utils.getClassReferenceName(aClass)); - headerFields.append(";\n"); + headerProtected.append("\n static jclass ") + .append(Utils.getClassReferenceName(aClass)) + .append(";\n"); // Add startup code to populate it.. - wrapperStartupCode.append('\n'); - wrapperStartupCode.append(Utils.getStartupLineForClass(aClass)); + wrapperStartupCode.append('\n') + .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(); - // The start-of-function boilerplate. Does the bridge exist? Does the env exist? etc. - wrapperMethodBodies.append('\n'); - wrapperMethodBodies.append(methodSignature); - - wrapperMethodBodies.append(" {\n"); + writeFunctionStartupBoilerPlate(methodSignature, returnType, aIsStaticBridgeMethod, aIsMultithreaded); - // 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"); + boolean isObjectReturningMethod = !returnType.getCanonicalName().equals("void") && Utils.isObjectType(returnType); - 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"); + writeFramePushBoilerplate(aMethod, isObjectReturningMethod); // 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.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'); - } - } + argumentContent = getArgumentMarshalling(argumentTypes); } + // 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.isMethodStatic(aMethod); + boolean isStaticJavaMethod = Utils.isMemberStatic(aMethod); // The call into Java - wrapperMethodBodies.append("env->"); - wrapperMethodBodies.append(Utils.getCallPrefix(returnType, isStaticJavaMethod)); + wrapperMethodBodies.append("env->") + .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("aTarget, "); + wrapperMethodBodies.append("wrapped_obj, "); } else { - // 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 + // If this is a static underlying Java method, we need to use the class reference in our // call. wrapperMethodBodies.append(Utils.getClassReferenceName(aClass)).append(", "); } - // Write the method id out.. - if (aIsStaticBridgeMethod) { - wrapperMethodBodies.append("sBridge->"); - } - wrapperMethodBodies.append('j'); - wrapperMethodBodies.append(aCMethodName); + wrapperMethodBodies.append(mMembersToIds.get(aMethod)); // Tack on the arguments, if any.. - wrapperMethodBodies.append(argumentContent); - wrapperMethodBodies.append(");\n\n"); + wrapperMethodBodies.append(argumentContent) + .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(" "); - wrapperMethodBodies.append(Utils.getCReturnType(returnType)); - wrapperMethodBodies.append(" ret = static_cast<").append(Utils.getCReturnType(returnType)).append(">(env->PopLocalFrame(temp));\n" + + wrapperMethodBodies.append(" ") + .append(Utils.getCReturnType(returnType)) + .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 method id of the given method on startup. + * Generates the code to get the id of the given member on startup. * - * @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. + * @param aMember The Java member being wrapped. */ - private void writeStartupCode(String aCMethodName, String aJavaMethodName, Method aMethod, Class<?> aClass) { - wrapperStartupCode.append(" j"); - wrapperStartupCode.append(aCMethodName); - wrapperStartupCode.append(" = get"); - if (Utils.isMethodStatic(aMethod)) { + private void writeStartupCode(Member aMember) { + wrapperStartupCode.append(" ") + .append(mMembersToIds.get(aMember)) + .append(" = get"); + if (Utils.isMemberStatic(aMember)) { wrapperStartupCode.append("Static"); } - wrapperStartupCode.append("Method(\""); - wrapperStartupCode.append(aJavaMethodName); - wrapperStartupCode.append("\", \""); - wrapperStartupCode.append(Utils.getTypeSignatureString(aMethod)); - wrapperStartupCode.append("\");\n"); + + 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"); } /** - * Create a method id field in the header file for the C method name provided. + * Write the field declaration for the C++ id field of the given member. * - * @param aMethodName C method name to generate a method id field for. + * @param aMember Member for which an id field needs to be generated. */ - private void writeHeaderField(String aMethodName) { - headerFields.append("jmethodID j"); - headerFields.append(aMethodName); - headerFields.append(";\n"); + 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"); } /** * Get the finalised bytes to go into the generated wrappers file. * * @return The bytes to be written to the wrappers file. */ - public byte[] getWrapperFileContents() { + public String getWrapperFileContents() { wrapperStartupCode.append("}\n"); - wrapperStartupCode.append(wrapperMethodBodies); + zeroingCode.append(wrapperStartupCode) + .append(wrapperMethodBodies); wrapperMethodBodies.setLength(0); - return wrapperStartupCode.toString().getBytes(); + wrapperStartupCode.setLength(0); + return zeroingCode.toString(); } /** * Get the finalised bytes to go into the generated header file. * * @return The bytes to be written to the header file. */ - public byte[] getHeaderFileContents() { - headerFields.append('\n'); - headerFields.append(headerMethods); - headerMethods.setLength(0); - return headerFields.toString().getBytes(); + 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(); } }
new file mode 100644 --- /dev/null +++ b/build/annotationProcessors/classloader/AnnotatableEntity.java @@ -0,0 +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.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; + } +}
new file mode 100644 --- /dev/null +++ b/build/annotationProcessors/classloader/ClassWithOptions.java @@ -0,0 +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.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,50 +16,45 @@ 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<Class<?>> getIteratorOverJars(String[] args) { + public static Iterator<ClassWithOptions> 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,38 +1,75 @@ /* 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<Class<?>> { +public class JarClassIterator implements Iterator<ClassWithOptions> { 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 Class<?> next() { + public ClassWithOptions next() { String className = mTargetClassListIterator.next(); try { - return mTarget.loadClass(className); + 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); + } } catch (ClassNotFoundException e) { System.err.println("Unable to enumerate class: " + className + ". Corrupted jar file?"); e.printStackTrace(); System.exit(2); } return null; }
--- a/build/annotationProcessors/moz.build +++ b/build/annotationProcessors/moz.build @@ -1,17 +1,19 @@ # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- # vim: set filetype=python: # 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/. jar = add_java_jar('annotationProcessors') jar.sources += [ + 'AnnotationInfo.java', 'AnnotationProcessor.java', + 'classloader/AnnotatableEntity.java', + 'classloader/ClassWithOptions.java', 'classloader/IterableJarLoadingURLClassLoader.java', 'classloader/JarClassIterator.java', 'CodeGenerator.java', - 'MethodWithAnnotationInfo.java', - 'utils/AlphabeticMethodComparator.java', - 'utils/GeneratableEntryPointIterator.java', + 'utils/AlphabeticAnnotatableEntityComparator.java', + 'utils/GeneratableElementIterator.java', 'utils/Utils.java', ]
rename from build/annotationProcessors/utils/AlphabeticMethodComparator.java rename to build/annotationProcessors/utils/AlphabeticAnnotatableEntityComparator.java --- a/build/annotationProcessors/utils/AlphabeticMethodComparator.java +++ b/build/annotationProcessors/utils/AlphabeticAnnotatableEntityComparator.java @@ -1,28 +1,81 @@ /* 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 AlphabeticMethodComparator implements Comparator<Method> { +public class AlphabeticAnnotatableEntityComparator<T extends Member> implements Comparator<T> { @Override - public int compare(Method lhs, Method rhs) { + 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) { // Initially, attempt to differentiate the methods be name alone.. - String lName = lhs.getName(); - String rName = rhs.getName(); + String lName = aLhs.getName(); + String rName = aRhs.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.getTypeSignatureString(lhs); - rName = Utils.getTypeSignatureString(rhs); + 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(); return lName.compareTo(rName); } }
rename from build/annotationProcessors/utils/GeneratableEntryPointIterator.java rename to build/annotationProcessors/utils/GeneratableElementIterator.java --- a/build/annotationProcessors/utils/GeneratableEntryPointIterator.java +++ b/build/annotationProcessors/utils/GeneratableElementIterator.java @@ -1,57 +1,82 @@ /* 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.MethodWithAnnotationInfo; +import org.mozilla.gecko.annotationProcessors.AnnotationInfo; +import org.mozilla.gecko.annotationProcessors.classloader.AnnotatableEntity; 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 GeneratableAndroidBridgeTarget + * Iterator over the methods in a given method list which have the WrappedJNIMethod * annotation. Returns an object containing both the annotation (Which may contain interesting * parameters) and the argument. */ -public class GeneratableEntryPointIterator implements Iterator<MethodWithAnnotationInfo> { - private final Method[] mMethods; - private MethodWithAnnotationInfo mNextReturnValue; - private int mMethodIndex; +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(); + + // Shove them all into one buffer. + Member[] objs = new Member[aMethods.length + aFields.length + aCtors.length]; - 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; + 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; + } + } 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 (mMethodIndex < mMethods.length) { - Method candidateMethod = mMethods[mMethodIndex]; - mMethodIndex++; - for (Annotation annotation : candidateMethod.getDeclaredAnnotations()) { - // GeneratableAndroidBridgeTarget has a parameter. Use Reflection to obtain it. + while (mElementIndex < mObjects.length) { + Member candidateElement = mObjects[mElementIndex]; + mElementIndex++; + for (Annotation annotation : ((AnnotatedElement) candidateElement).getDeclaredAnnotations()) { + // WrappedJNIMethod has parameters. Use Reflection to obtain them. Class<? extends Annotation> annotationType = annotation.annotationType(); final String annotationTypeName = annotationType.getName(); - - if (annotationTypeName.equals("org.mozilla.gecko.mozglue.GeneratableAndroidBridgeTarget")) { + if (annotationTypeName.equals("org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI")) { 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); @@ -61,51 +86,61 @@ public class GeneratableEntryPointIterat 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 GeneratableAndroidBridgeTarget annotation. Did the signature change?"); + System.err.println("Unable to find expected field on WrapElementForJNI annotation. Did the signature change?"); e.printStackTrace(System.err); System.exit(3); } catch (IllegalAccessException e) { - System.err.println("IllegalAccessException reading fields on GeneratableAndroidBridgeTarget annotation. Seems the semantics of Reflection have changed..."); + System.err.println("IllegalAccessException reading fields on WrapElementForJNI 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 GeneratableAndroidBridgeTarget annotation. This really shouldn't happen."); + System.err.println("InvocationTargetException reading fields on WrapElementForJNI annotation. This really shouldn't happen."); e.printStackTrace(System.err); System.exit(5); } + // If the method name was not explicitly given in the annotation generate one... if (stubName.isEmpty()) { - String aMethodName = candidateMethod.getName(); + String aMethodName = candidateElement.getName(); stubName = aMethodName.substring(0, 1).toUpperCase() + aMethodName.substring(1); } - mNextReturnValue = new MethodWithAnnotationInfo(candidateMethod, stubName, isStaticStub, isMultithreadedStub); + AnnotationInfo annotationInfo = new AnnotationInfo(stubName, isStaticStub, isMultithreadedStub); + mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo); 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 MethodWithAnnotationInfo next() { - MethodWithAnnotationInfo ret = mNextReturnValue; + public AnnotatableEntity next() { + AnnotatableEntity ret = mNextReturnValue; findNextValue(); return ret; } @Override public void remove() { - throw new UnsupportedOperationException("Removal of methods from GeneratableEntryPointIterator not supported."); + throw new UnsupportedOperationException("Removal of methods from GeneratableElementIterator not supported."); } }
--- a/build/annotationProcessors/utils/Utils.java +++ b/build/annotationProcessors/utils/Utils.java @@ -1,15 +1,18 @@ /* 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 { @@ -65,33 +68,48 @@ 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"); @@ -159,26 +177,43 @@ 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) { - // Since there's only one thing we want to do differently... + if (type.getCanonicalName().equals("java.lang.Void")) { + return "void"; + } 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) { @@ -207,159 +242,216 @@ public class Utils { String name = type.getCanonicalName(); if (sFailureReturns.containsKey(name)) { return sFailureReturns.get(name); } return " nullptr"; } /** - * Get the canonical JNI type signature for a method. + * 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) * - * @param aMethod The method to generate a signature for. - * @return The canonical JNI type signature for this 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; */ - public static String getTypeSignatureString(Method aMethod) { - Class<?>[] arguments = aMethod.getParameterTypes(); - Class<?> returnType = aMethod.getReturnType(); - + private static String getTypeSignatureInternal(Class<?>[] arguments, Class<?> returnType) { 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(); } /** - * Helper method used by getTypeSignatureString to build the signature. Write the subsignature + * 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 * 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); len = 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 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 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. */ - public static String getCImplementationMethodSignature(Method aMethod, String aCMethodName) { - Class<?>[] argumentTypes = aMethod.getParameterTypes(); - Class<?> returnType = aMethod.getReturnType(); + public static String getCImplementationMethodSignature(Class<?>[] aArgumentTypes, Class<?> aReturnType, String aCMethodName, String aCClassName) { + StringBuilder retBuffer = new StringBuilder(); - StringBuilder retBuffer = new StringBuilder(); - // Write return type.. - retBuffer.append(getCReturnType(returnType)); - retBuffer.append(" AndroidBridge::"); + retBuffer.append(getCReturnType(aReturnType)); + retBuffer.append(' '); + retBuffer.append(aCClassName); + 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 < argumentTypes.length; aT++) { - retBuffer.append(getCParameterType(argumentTypes[aT])); + for (int aT = 0; aT < aArgumentTypes.length; aT++) { + retBuffer.append(getCParameterType(aArgumentTypes[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 != argumentTypes.length - 1) { + if (aT != aArgumentTypes.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(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(); - + public static String getCHeaderMethodSignature(Class<?>[] aArgumentTypes, Annotation[][] aArgumentAnnotations, Class<?> aReturnType, String aCMethodName, String aCClassName, boolean aIsStaticStub) { StringBuilder retBuffer = new StringBuilder(); // Add the static keyword, if applicable. if (aIsStaticStub) { retBuffer.append("static "); } // Write return type.. - retBuffer.append(getCReturnType(returnType)); + retBuffer.append(getCReturnType(aReturnType)); 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 < argumentTypes.length; aT++) { - retBuffer.append(getCParameterType(argumentTypes[aT])); + for (int aT = 0; aT < aArgumentTypes.length; aT++) { + retBuffer.append(getCParameterType(aArgumentTypes[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(argumentTypes[aT], argumentAnnotations[aT])); + retBuffer.append(getDefaultValueString(aArgumentTypes[aT], aArgumentAnnotations[aT])); - if (aT != argumentTypes.length - 1) { + if (aT != aArgumentTypes.length - 1) { retBuffer.append(", "); } } retBuffer.append(')'); return retBuffer.toString(); } /** @@ -371,17 +463,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.OptionalGeneratedParameter")) { + if (annotationTypeName.equals("org.mozilla.gecko.mozglue.generatorannotations.OptionalGeneratedParameter")) { return " = " + getDefaultParameterValueForType(aArgumentType); } } return ""; } /** * Helper method to return an appropriate default parameter value for an argument of a given type. @@ -401,24 +493,23 @@ public class Utils { } else { return "nullptr"; } } /** * Helper method that returns the number of reference types in the arguments of m. * - * @param m The method to consider. + * @param aArgs The method arguments to consider. * @return How many of the arguments of m are nonprimitive. */ - public static int enumerateReferenceArguments(Method m) { + public static int enumerateReferenceArguments(Class<?>[] aArgs) { int ret = 0; - Class<?>[] args = m.getParameterTypes(); - for (int i = 0; i < args.length; i++) { - String name = args[i].getCanonicalName(); + for (int i = 0; i < aArgs.length; i++) { + String name = aArgs[i].getCanonicalName(); if (!sBasicCTypes.containsKey(name)) { ret++; } } return ret; } /** @@ -448,35 +539,33 @@ 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 = NewJavaString(env, ").append(argName).append(");\n"); + sb.append("l = AndroidBridge::NewJavaString(env, ").append(argName).append(");\n"); } else { sb.append("l = ").append(argName).append(";\n"); } } return sb.toString(); } /** - * Returns true if the method provided returns an object type. Returns false if it returns a - * primitive type. + * Returns true if the type provided is an object type. Returns false otherwise * - * @param aMethod The method to consider. - * @return true if the method provided returns an object type, false otherwise. + * @param aType The type to consider. + * @return true if the method provided is an object type, false otherwise. */ - public static boolean doesReturnObjectType(Method aMethod) { - Class<?> returnType = aMethod.getReturnType(); - return !sBasicCTypes.containsKey(returnType.getCanonicalName()); + public static boolean isObjectType(Class<?> aType) { + return !sBasicCTypes.containsKey(aType.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. */ @@ -491,17 +580,26 @@ 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(\""); - sb.append(aClass.getCanonicalName().replaceAll("\\.", "/")); + + 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("\");\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. @@ -516,16 +614,26 @@ 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 aMethod The Method to check. + * @param aMember The Member to check. * @return true of the method is declared static, false otherwise. */ - public static boolean isMethodStatic(Method aMethod) { - int aMethodModifiers = aMethod.getModifiers(); + public static boolean isMemberStatic(Member aMember) { + int aMethodModifiers = aMember.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 @@ -1787,18 +1787,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"); - if (AndroidBridge::Bridge() != nullptr) - *showPassword = AndroidBridge::Bridge()->GetShowPasswordSetting(); + + *showPassword = GeckoAppShell::GetShowPasswordSetting(); #endif return true; } bool ContentParent::RecvFirstIdle() { #ifdef MOZ_NUWA_PROCESS
--- a/dom/plugins/base/nsNPAPIPlugin.cpp +++ b/dom/plugins/base/nsNPAPIPlugin.cpp @@ -2257,21 +2257,17 @@ 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: { - AndroidBridge *bridge = AndroidBridge::Bridge(); - if (!bridge) - return NPERR_GENERIC_ERROR; - - jobject ret = bridge->GetContext(); + jobject ret = GeckoAppShell::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 @@ -863,17 +863,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) { - AndroidBridge::Bridge()->LockScreenOrientation(mFullScreenOrientation); + GeckoAppShell::LockScreenOrientation(mFullScreenOrientation); } } void nsNPAPIPluginInstance::NotifySize(nsIntSize size) { if (kOpenGL_ANPDrawingModel != GetANPDrawingModel() || size == mCurrentSize) return; @@ -920,21 +920,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) { - AndroidBridge::Bridge()->LockScreenOrientation(mFullScreenOrientation); + GeckoAppShell::LockScreenOrientation(mFullScreenOrientation); } else if (oldOrientation != dom::eScreenOrientation_None) { // We applied an orientation when we entered fullscreen, but // we don't want it anymore - AndroidBridge::Bridge()->UnlockScreenOrientation(); + GeckoAppShell::UnlockScreenOrientation(); } } } void nsNPAPIPluginInstance::PopPostedEvent(PluginEventRunnable* r) { mPostedEvents.RemoveElement(r); }
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -1667,19 +1667,17 @@ bool nsPluginInstanceOwner::AddPluginVie return true; } void nsPluginInstanceOwner::RemovePluginView() { if (!mInstance || !mJavaView) return; - if (AndroidBridge::Bridge()) - AndroidBridge::Bridge()->RemovePluginView((jobject)mJavaView, mFullScreen); - + GeckoAppShell::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,40 +21,34 @@ AndroidLocationProvider::AndroidLocation AndroidLocationProvider::~AndroidLocationProvider() { NS_IF_RELEASE(gLocationCallback); } NS_IMETHODIMP AndroidLocationProvider::Startup() { - if (!AndroidBridge::Bridge()) - return NS_ERROR_NOT_IMPLEMENTED; - AndroidBridge::Bridge()->EnableLocation(true); + GeckoAppShell::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() { - if (!AndroidBridge::Bridge()) - return NS_ERROR_NOT_IMPLEMENTED; - AndroidBridge::Bridge()->EnableLocation(false); + GeckoAppShell::EnableLocation(false); return NS_OK; } NS_IMETHODIMP AndroidLocationProvider::SetHighAccuracy(bool enable) { - if (!AndroidBridge::Bridge()) - return NS_ERROR_NOT_IMPLEMENTED; - AndroidBridge::Bridge()->EnableLocationHighAccuracy(enable); + GeckoAppShell::EnableLocationHighAccuracy(enable); return NS_OK; }
--- a/dom/system/android/nsHapticFeedback.cpp +++ b/dom/system/android/nsHapticFeedback.cpp @@ -9,15 +9,11 @@ using namespace mozilla; NS_IMPL_ISUPPORTS1(nsHapticFeedback, nsIHapticFeedback) NS_IMETHODIMP nsHapticFeedback::PerformSimpleAction(int32_t aType) { - AndroidBridge* bridge = AndroidBridge::Bridge(); - if (bridge) { - bridge->PerformHapticFeedback(aType == LongPress); - return NS_OK; - } - return NS_ERROR_FAILURE; + GeckoAppShell::PerformHapticFeedback(aType == LongPress); + return NS_OK; }
--- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -2510,17 +2510,17 @@ public: virtual bool UnbindExternalBuffer(GLuint texture) { return false; } #ifdef MOZ_WIDGET_GONK virtual EGLImage CreateEGLImageForNativeBuffer(void* buffer) = 0; virtual void DestroyEGLImage(EGLImage image) = 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) { - AndroidBridge::Bridge()->UnregisterSurfaceTextureFrameListener(mSurfaceTexture); + GeckoAppShell::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) - AndroidBridge::Bridge()->RegisterSurfaceTextureFrameListener(mSurfaceTexture, mID); + GeckoAppShell::RegisterSurfaceTextureFrameListener(mSurfaceTexture, mID); else - AndroidBridge::Bridge()->UnregisterSurfaceTextureFrameListener(mSurfaceTexture); + GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture); mFrameAvailableCallback = aRunnable; } void nsSurfaceTexture::NotifyFrameAvailable() { if (mFrameAvailableCallback) {
--- a/hal/android/AndroidHal.cpp +++ b/hal/android/AndroidHal.cpp @@ -9,16 +9,17 @@ #include "AndroidBridge.h" #include "mozilla/dom/network/Constants.h" #include "mozilla/dom/ScreenOrientation.h" #include "nsIScreenManager.h" #include "nsServiceManagerUtils.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,107 +50,65 @@ Vibrate(const nsTArray<uint32_t> &patter b->Vibrate(pattern); } void CancelVibrate(const WindowIdentifier &) { // Ignore WindowIdentifier parameter. - AndroidBridge* b = AndroidBridge::Bridge(); - if (b) - b->CancelVibrate(); + GeckoAppShell::CancelVibrate(); } void EnableBatteryNotifications() { - AndroidBridge* bridge = AndroidBridge::Bridge(); - if (!bridge) { - return; - } - - bridge->EnableBatteryNotifications(); + GeckoAppShell::EnableBatteryNotifications(); } void DisableBatteryNotifications() { - AndroidBridge* bridge = AndroidBridge::Bridge(); - if (!bridge) { - return; - } - - bridge->DisableBatteryNotifications(); + GeckoAppShell::DisableBatteryNotifications(); } void GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo) { - AndroidBridge* bridge = AndroidBridge::Bridge(); - if (!bridge) { - return; - } - - bridge->GetCurrentBatteryInformation(aBatteryInfo); + AndroidBridge::Bridge()->GetCurrentBatteryInformation(aBatteryInfo); } void EnableNetworkNotifications() { - AndroidBridge* bridge = AndroidBridge::Bridge(); - if (!bridge) { - return; - } - - bridge->EnableNetworkNotifications(); + GeckoAppShell::EnableNetworkNotifications(); } void DisableNetworkNotifications() { - AndroidBridge* bridge = AndroidBridge::Bridge(); - if (!bridge) { - return; - } - - bridge->DisableNetworkNotifications(); + GeckoAppShell::DisableNetworkNotifications(); } void GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo) { - AndroidBridge* bridge = AndroidBridge::Bridge(); - if (!bridge) { - return; - } - - bridge->GetCurrentNetworkInformation(aNetworkInfo); + AndroidBridge::Bridge()->GetCurrentNetworkInformation(aNetworkInfo); } void EnableScreenConfigurationNotifications() { - AndroidBridge* bridge = AndroidBridge::Bridge(); - if (!bridge) { - return; - } - - bridge->EnableScreenOrientationNotifications(); + GeckoAppShell::EnableScreenOrientationNotifications(); } void DisableScreenConfigurationNotifications() { - AndroidBridge* bridge = AndroidBridge::Bridge(); - if (!bridge) { - return; - } - - bridge->DisableScreenOrientationNotifications(); + GeckoAppShell::DisableScreenOrientationNotifications(); } void GetCurrentScreenConfiguration(ScreenConfiguration* aScreenConfiguration) { AndroidBridge* bridge = AndroidBridge::Bridge(); if (!bridge) { return; @@ -176,43 +135,33 @@ 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: case eScreenOrientation_Default: - bridge->LockScreenOrientation(aOrientation); + GeckoAppShell::LockScreenOrientation(aOrientation); return true; default: return false; } } void UnlockScreenOrientation() { - AndroidBridge* bridge = AndroidBridge::Bridge(); - if (!bridge) { - return; - } - - bridge->UnlockScreenOrientation(); + GeckoAppShell::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) { - AndroidBridge::Bridge()->EnableSensor(aSensor); + GeckoAppShell::EnableSensor(aSensor); } void DisableSensorNotifications(SensorType aSensor) { - AndroidBridge::Bridge()->DisableSensor(aSensor); + GeckoAppShell::DisableSensor(aSensor); } } // hal_impl } // mozilla
--- a/ipc/glue/MessagePump.cpp +++ b/ipc/glue/MessagePump.cpp @@ -90,17 +90,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 |= AndroidBridge::Bridge()->PumpMessageLoop(); + did_work |= GeckoAppShell::PumpMessageLoop(); #endif did_work |= aDelegate->DoDelayedWork(&delayed_work_time_); if (did_work && delayed_work_time_.is_null() #ifdef MOZ_NUWA_PROCESS && (!IsNuwaReady() || !IsNuwaProcess()) #endif
--- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -5,20 +5,20 @@ package org.mozilla.gecko; import org.mozilla.gecko.favicons.OnFaviconLoadedListener; import org.mozilla.gecko.gfx.BitmapUtils; import org.mozilla.gecko.gfx.GeckoLayerClient; import org.mozilla.gecko.gfx.LayerView; import org.mozilla.gecko.gfx.PanZoomController; +import org.mozilla.gecko.mozglue.generatorannotations.OptionalGeneratedParameter; +import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI; import org.mozilla.gecko.prompts.PromptService; import org.mozilla.gecko.mozglue.GeckoLoader; -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; @@ -397,33 +397,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 */ - @GeneratableAndroidBridgeTarget(generateStatic = true) + @WrapElementForJNI(generateStatic = true) public static void notifyIME(int type) { if (mEditableListener != null) { mEditableListener.notifyIME(type); } } - @GeneratableAndroidBridgeTarget(generateStatic = true) + @WrapElementForJNI(generateStatic = true) public static void notifyIMEContext(int state, String typeHint, String modeHint, String actionHint) { if (mEditableListener != null) { mEditableListener.notifyIMEContext(state, typeHint, modeHint, actionHint); } } - @GeneratableAndroidBridgeTarget(generateStatic = true) + @WrapElementForJNI(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); } } @@ -457,17 +457,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 - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void acknowledgeEvent() { synchronized (sEventAckLock) { sWaitingForEventAck = false; sEventAckLock.notifyAll(); } } private static float getLocationAccuracy(Location location) { @@ -496,17 +496,17 @@ public class GeckoAppShell getLocationAccuracy(location) < getLocationAccuracy(lastKnownLocation))) { lastKnownLocation = location; } } return lastKnownLocation; } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void enableLocation(final boolean enable) { ThreadUtils.postToUiThread(new Runnable() { @Override public void run() { LocationManager lm = getLocationManager(getContext()); if (lm == null) { return; } @@ -552,22 +552,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; } } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void enableLocationHighAccuracy(final boolean enable) { mLocationHighAccuracy = enable; } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void enableSensor(int aSensortype) { GeckoInterface gi = getGeckoInterface(); if (gi == null) return; SensorManager sm = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); switch(aSensortype) { @@ -612,17 +612,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); } } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void disableSensor(int aSensortype) { GeckoInterface gi = getGeckoInterface(); if (gi == null) return; SensorManager sm = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); @@ -656,44 +656,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); } } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI 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. } - @GeneratableAndroidBridgeTarget(stubName = "NotifyXreExit") + @WrapElementForJNI(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); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI 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(); @@ -726,17 +726,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 - @GeneratableAndroidBridgeTarget + @WrapElementForJNI 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); } @@ -921,25 +921,25 @@ public class GeckoAppShell halfSize - sHeight, halfSize + sWidth, halfSize + sHeight), null); return bitmap; } - @GeneratableAndroidBridgeTarget(stubName = "GetHandlersForMimeTypeWrapper") + @WrapElementForJNI(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); } - @GeneratableAndroidBridgeTarget(stubName = "GetHandlersForURLWrapper") + @WrapElementForJNI(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); @@ -972,22 +972,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); } - @GeneratableAndroidBridgeTarget(stubName = "GetExtensionFromMimeTypeWrapper") + @WrapElementForJNI(stubName = "GetExtensionFromMimeTypeWrapper") static String getExtensionFromMimeType(String aMimeType) { return MimeTypeMap.getSingleton().getExtensionFromMimeType(aMimeType); } - @GeneratableAndroidBridgeTarget(stubName = "GetMimeTypeFromExtensionsWrapper") + @WrapElementForJNI(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) @@ -1110,17 +1110,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. */ - @GeneratableAndroidBridgeTarget + @WrapElementForJNI 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, @@ -1296,17 +1296,17 @@ public class GeckoAppShell public static void setNotificationClient(NotificationClient client) { if (sNotificationClient == null) { sNotificationClient = client; } else { Log.d(LOGTAG, "Notification client already set"); } } - @GeneratableAndroidBridgeTarget(stubName = "ShowAlertNotificationWrapper") + @WrapElementForJNI(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); @@ -1323,23 +1323,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); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void alertsProgressListener_OnProgress(String aAlertName, long aProgress, long aProgressMax, String aAlertText) { int notificationID = aAlertName.hashCode(); sNotificationClient.update(notificationID, aProgress, aProgressMax, aAlertText); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void closeNotification(String aAlertName) { String alertCookie = mAlertCookies.get(aAlertName); if (alertCookie != null) { callObserver(aAlertName, "alertfinished", alertCookie); mAlertCookies.remove(aAlertName); } removeObserver(aAlertName); @@ -1357,26 +1357,26 @@ public class GeckoAppShell if (sNotificationClient.isOngoing(notificationID)) { // When clicked, keep the notification if it displays progress return; } } closeNotification(aAlertName); } - @GeneratableAndroidBridgeTarget(stubName = "GetDpiWrapper") + @WrapElementForJNI(stubName = "GetDpiWrapper") public static int getDpi() { if (sDensityDpi == 0) { sDensityDpi = getContext().getResources().getDisplayMetrics().densityDpi; } return sDensityDpi; } - @GeneratableAndroidBridgeTarget() + @WrapElementForJNI public static float getDensity() { return getContext().getResources().getDisplayMetrics().density; } private static boolean isHighMemoryDevice() { BufferedReader br = null; FileReader fr = null; try { @@ -1401,17 +1401,17 @@ public class GeckoAppShell } return false; } /** * Returns the colour depth of the default screen. This will either be * 24 or 16. */ - @GeneratableAndroidBridgeTarget(stubName = "GetScreenDepthWrapper") + @WrapElementForJNI(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; } @@ -1424,133 +1424,133 @@ public class GeckoAppShell if (sScreenDepth != 0) { Log.e(LOGTAG, "Tried to override screen depth after it's already been set"); return; } sScreenDepth = aScreenDepth; } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void setFullScreen(boolean fullscreen) { if (getGeckoInterface() != null) getGeckoInterface().setFullScreen(fullscreen); } - @GeneratableAndroidBridgeTarget(stubName = "ShowFilePickerForExtensionsWrapper") + @WrapElementForJNI(stubName = "ShowFilePickerForExtensionsWrapper") public static String showFilePickerForExtensions(String aExtensions) { if (getGeckoInterface() != null) return sActivityHelper.showFilePicker(getGeckoInterface().getActivity(), getMimeTypeFromExtensions(aExtensions)); return ""; } - @GeneratableAndroidBridgeTarget(stubName = "ShowFilePickerForMimeTypeWrapper") + @WrapElementForJNI(stubName = "ShowFilePickerForMimeTypeWrapper") public static String showFilePickerForMimeType(String aMimeType) { if (getGeckoInterface() != null) return sActivityHelper.showFilePicker(getGeckoInterface().getActivity(), aMimeType); return ""; } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI 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); } - @GeneratableAndroidBridgeTarget(stubName = "Vibrate1") + @WrapElementForJNI(stubName = "Vibrate1") public static void vibrate(long milliseconds) { sVibrationEndTime = System.nanoTime() + milliseconds * 1000000; sVibrationMaybePlaying = true; vibrator().vibrate(milliseconds); } - @GeneratableAndroidBridgeTarget(stubName = "VibrateA") + @WrapElementForJNI(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); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void cancelVibrate() { sVibrationMaybePlaying = false; sVibrationEndTime = 0; vibrator().cancel(); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void showInputMethodPicker() { InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.showInputMethodPicker(); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void setKeepScreenOn(final boolean on) { ThreadUtils.postToUiThread(new Runnable() { @Override public void run() { // TODO } }); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI 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); } } }); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI 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; } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static boolean isNetworkLinkKnown() { ConnectivityManager cm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE); if (cm.getActiveNetworkInfo() == null) return false; return true; } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static int networkLinkType() { ConnectivityManager cm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo info = cm.getActiveNetworkInfo(); if (info == null) { return LINK_TYPE_UNKNOWN; } @@ -1599,17 +1599,17 @@ public class GeckoAppShell return LINK_TYPE_4G; // 3.9G case TelephonyManager.NETWORK_TYPE_UNKNOWN: default: Log.w(LOGTAG, "Connected to an unknown mobile network!"); return LINK_TYPE_UNKNOWN; } } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI 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. N.B., if this code ever becomes live again, you need to hook it up to locale @@ -1638,17 +1638,17 @@ public class GeckoAppShell Resources res = getContext().getBaseContext().getResources(); Configuration config = res.getConfiguration(); config.locale = locale; res.updateConfiguration(config, res.getDisplayMetrics()); */ } - @GeneratableAndroidBridgeTarget(stubName = "GetSystemColoursWrapper") + @WrapElementForJNI(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, @@ -1675,17 +1675,17 @@ public class GeckoAppShell result[idx] = color; } appearance.recycle(); } return result; } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI 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; } @@ -1831,31 +1831,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) { } } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI 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); } - @GeneratableAndroidBridgeTarget(stubName = "GetIconForExtensionWrapper") + @WrapElementForJNI(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); @@ -1903,39 +1903,39 @@ public class GeckoAppShell if (resolveInfo == null) return null; ActivityInfo activityInfo = resolveInfo.activityInfo; return activityInfo.loadIcon(pm); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI 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; } } - @GeneratableAndroidBridgeTarget(stubName = "AddPluginViewWrapper") + @WrapElementForJNI(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); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI 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. @@ -2149,17 +2149,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; - @GeneratableAndroidBridgeTarget(allowMultithread = true) + @WrapElementForJNI(allowMultithread = true) public static Context getContext() { return sContextGetter.getContext(); } public static void setContextGetter(ContextGetter cg) { sContextGetter = cg; } @@ -2207,17 +2207,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; - @GeneratableAndroidBridgeTarget(stubName = "InitCameraWrapper") + @WrapElementForJNI(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) {} @@ -2308,17 +2308,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; } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI static synchronized void closeCamera() { ThreadUtils.postToUiThread(new Runnable() { @Override public void run() { try { if (getGeckoInterface() != null) getGeckoInterface().disableCameraView(); } catch (Exception e) {} @@ -2360,148 +2360,148 @@ public class GeckoAppShell */ public static void unregisterEventListener(String event, GeckoEventListener listener) { sEventDispatcher.unregisterEventListener(event, listener); } /* * Battery API related methods. */ - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void enableBatteryNotifications() { GeckoBatteryManager.enableNotifications(); } - @GeneratableAndroidBridgeTarget(stubName = "HandleGeckoMessageWrapper") + @WrapElementForJNI(stubName = "HandleGeckoMessageWrapper") public static String handleGeckoMessage(String message) { return sEventDispatcher.dispatchEvent(message); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void disableBatteryNotifications() { GeckoBatteryManager.disableNotifications(); } - @GeneratableAndroidBridgeTarget(stubName = "GetCurrentBatteryInformationWrapper") + @WrapElementForJNI(stubName = "GetCurrentBatteryInformationWrapper") public static double[] getCurrentBatteryInformation() { return GeckoBatteryManager.getCurrentInformation(); } - @GeneratableAndroidBridgeTarget(stubName = "CheckURIVisited") + @WrapElementForJNI(stubName = "CheckURIVisited") static void checkUriVisited(String uri) { GlobalHistory.getInstance().checkUriVisited(uri); } - @GeneratableAndroidBridgeTarget(stubName = "MarkURIVisited") + @WrapElementForJNI(stubName = "MarkURIVisited") static void markUriVisited(final String uri) { ThreadUtils.postToBackgroundThread(new Runnable() { @Override public void run() { GlobalHistory.getInstance().add(uri); } }); } - @GeneratableAndroidBridgeTarget(stubName = "SetURITitle") + @WrapElementForJNI(stubName = "SetURITitle") static void setUriTitle(final String uri, final String title) { ThreadUtils.postToBackgroundThread(new Runnable() { @Override public void run() { GlobalHistory.getInstance().update(uri, title); } }); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI static void hideProgressDialog() { // unused stub } /* * WebSMS related methods. */ - @GeneratableAndroidBridgeTarget(stubName = "SendMessageWrapper") + @WrapElementForJNI(stubName = "SendMessageWrapper") public static void sendMessage(String aNumber, String aMessage, int aRequestId) { if (SmsManager.getInstance() == null) { return; } SmsManager.getInstance().send(aNumber, aMessage, aRequestId); } - @GeneratableAndroidBridgeTarget(stubName = "GetMessageWrapper") + @WrapElementForJNI(stubName = "GetMessageWrapper") public static void getMessage(int aMessageId, int aRequestId) { if (SmsManager.getInstance() == null) { return; } SmsManager.getInstance().getMessage(aMessageId, aRequestId); } - @GeneratableAndroidBridgeTarget(stubName = "DeleteMessageWrapper") + @WrapElementForJNI(stubName = "DeleteMessageWrapper") public static void deleteMessage(int aMessageId, int aRequestId) { if (SmsManager.getInstance() == null) { return; } SmsManager.getInstance().deleteMessage(aMessageId, aRequestId); } - @GeneratableAndroidBridgeTarget(stubName = "CreateMessageListWrapper") + @WrapElementForJNI(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); } - @GeneratableAndroidBridgeTarget(stubName = "GetNextMessageInListWrapper") + @WrapElementForJNI(stubName = "GetNextMessageInListWrapper") public static void getNextMessageInList(int aListId, int aRequestId) { if (SmsManager.getInstance() == null) { return; } SmsManager.getInstance().getNextMessageInList(aListId, aRequestId); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI 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 */ - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static boolean isTablet() { return HardwareUtils.isTablet(); } public static void viewSizeChanged() { LayerView v = getLayerView(); if (v != null && v.isIMEEnabled()) { sendEventToGecko(GeckoEvent.createBroadcastEvent( "ScrollTo:FocusedInput", "")); } } - @GeneratableAndroidBridgeTarget(stubName = "GetCurrentNetworkInformationWrapper") + @WrapElementForJNI(stubName = "GetCurrentNetworkInformationWrapper") public static double[] getCurrentNetworkInformation() { return GeckoNetworkManager.getInstance().getCurrentInformation(); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void enableNetworkNotifications() { GeckoNetworkManager.getInstance().enableNotifications(); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI 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; @@ -2605,42 +2605,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); } - @GeneratableAndroidBridgeTarget(stubName = "GetScreenOrientationWrapper") + @WrapElementForJNI(stubName = "GetScreenOrientationWrapper") public static short getScreenOrientation() { return GeckoScreenOrientationListener.getInstance().getScreenOrientation(); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void enableScreenOrientationNotifications() { GeckoScreenOrientationListener.getInstance().enableNotifications(); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void disableScreenOrientationNotifications() { GeckoScreenOrientationListener.getInstance().disableNotifications(); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void lockScreenOrientation(int aOrientation) { GeckoScreenOrientationListener.getInstance().lockScreenOrientation(aOrientation); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void unlockScreenOrientation() { GeckoScreenOrientationListener.getInstance().unlockScreenOrientation(); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI 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() @@ -2652,61 +2652,61 @@ public class GeckoAppShell else msg.getTarget().dispatchMessage(msg); msg.recycle(); return true; } static native void notifyFilePickerResult(String filePath, long id); - @GeneratableAndroidBridgeTarget(stubName = "ShowFilePickerAsyncWrapper") + @WrapElementForJNI(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); } }); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI public static void notifyWakeLockChanged(String topic, String state) { if (getGeckoInterface() != null) getGeckoInterface().notifyWakeLockChanged(topic, state); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI 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); } }); } - @GeneratableAndroidBridgeTarget(allowMultithread = true) + @WrapElementForJNI(allowMultithread = true) public static void unregisterSurfaceTextureFrameListener(Object surfaceTexture) { ((SurfaceTexture)surfaceTexture).setOnFrameAvailableListener(null); } - @GeneratableAndroidBridgeTarget + @WrapElementForJNI 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; } - @GeneratableAndroidBridgeTarget(stubName = "GetProxyForURIWrapper") + @WrapElementForJNI(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,16 +2,18 @@ * 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; @@ -78,16 +80,18 @@ 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.GeneratableAndroidBridgeTarget; +import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI; 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; } } - @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "GetThreadNameJavaProfilingWrapper") + @WrapElementForJNI(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); } - @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "GetSampleTimeJavaProfiling") + @WrapElementForJNI(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; } - @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "GetFrameNameJavaProfilingWrapper") + @WrapElementForJNI(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; } - @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "StartJavaProfiling") + @WrapElementForJNI(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(); } } - @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "PauseJavaProfiling") + @WrapElementForJNI(allowMultithread = true, stubName = "PauseJavaProfiling") public static void pause() { synchronized (GeckoJavaSampler.class) { sSamplingRunnable.mPauseSampler = true; } } - @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "UnpauseJavaProfiling") + @WrapElementForJNI(allowMultithread = true, stubName = "UnpauseJavaProfiling") public static void unpause() { synchronized (GeckoJavaSampler.class) { sSamplingRunnable.mPauseSampler = false; } } - @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "StopJavaProfiling") + @WrapElementForJNI(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 @@ -146,17 +146,17 @@ endif jni-stubs.inc: gecko-browser.jar gecko-mozglue.jar gecko-util.jar 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_JAR_FILES := $(DEPTH)/build/annotationProcessors/annotationProcessors.jar GeneratedJNIWrappers.cpp: $(ANNOTATION_PROCESSOR_JAR_FILES) GeneratedJNIWrappers.cpp: $(ALL_JARS) - $(JAVA) -classpath $(JAVA_BOOTCLASSPATH):$(ANNOTATION_PROCESSOR_JAR_FILES) org.mozilla.gecko.annotationProcessors.AnnotationProcessor $(ALL_JARS) + $(JAVA) -classpath gecko-mozglue.jar:$(JAVA_BOOTCLASSPATH):$(ANNOTATION_PROCESSOR_JAR_FILES) org.mozilla.gecko.annotationProcessors.AnnotationProcessor $(ALL_JARS) gecko_package_dir = generated/org/mozilla/gecko # Like generated/org/mozilla/fennec_$USERID. android_package_dir = $(addprefix generated/,$(subst .,/,$(ANDROID_PACKAGE_NAME))) # These _PP_JAVAFILES are specified in moz.build and defined in # backend.mk, which is included by config.mk. Therefore this needs to # be defined after config.mk is included.
--- a/mobile/android/base/SurfaceBits.java +++ b/mobile/android/base/SurfaceBits.java @@ -1,14 +1,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; +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.GeneratableAndroidBridgeTarget; +import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI; import android.graphics.Bitmap; import android.util.Log; import java.nio.ByteBuffer; import java.util.LinkedList; import java.util.concurrent.atomic.AtomicInteger; @@ -146,17 +146,17 @@ public final class ThumbnailHelper { } Log.d(LOGTAG, "Sending thumbnail event: " + mWidth + ", " + mHeight); GeckoEvent e = GeckoEvent.createThumbnailEvent(tab.getId(), mWidth, mHeight, mBuffer); GeckoAppShell.sendEventToGecko(e); } /* This method is invoked by JNI once the thumbnail data is ready. */ - @GeneratableAndroidBridgeTarget(stubName = "SendThumbnail") + @WrapElementForJNI(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/db/LocalBrowserDB.java +++ b/mobile/android/base/db/LocalBrowserDB.java @@ -397,20 +397,21 @@ public class LocalBrowserDB implements B Bookmarks.UNFILED_FOLDER_GUID }, null); } else { // Right now, we only support showing folder and bookmark type of // entries. We should add support for other types though (bug 737024) c = cr.query(mBookmarksUriWithProfile, DEFAULT_BOOKMARK_COLUMNS, Bookmarks.PARENT + " = ? AND " + - "(" + Bookmarks.TYPE + " = ? OR " + Bookmarks.TYPE + " = ?)", + "(" + Bookmarks.TYPE + " = ? OR " + + "(" + Bookmarks.TYPE + " = ? AND " + Bookmarks.URL + " IS NOT NULL))", new String[] { String.valueOf(folderId), - String.valueOf(Bookmarks.TYPE_BOOKMARK), - String.valueOf(Bookmarks.TYPE_FOLDER) }, + String.valueOf(Bookmarks.TYPE_FOLDER), + String.valueOf(Bookmarks.TYPE_BOOKMARK) }, null); } if (addDesktopFolder) { // Wrap cursor to add fake desktop bookmarks and reading list folders c = new SpecialFoldersCursorWrapper(c, addDesktopFolder); }
--- a/mobile/android/base/gfx/DisplayPortMetrics.java +++ b/mobile/android/base/gfx/DisplayPortMetrics.java @@ -1,35 +1,39 @@ /* -*- 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.GeneratableAndroidBridgeTarget; +import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI; 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; @@ -210,17 +210,17 @@ public class GLController { if (red[0] == rSize && green[0] == gSize && blue[0] == bSize) { return config; } } throw new GLControllerException("No suitable EGL configuration found"); } - @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "CreateEGLSurfaceForCompositorWrapper") + @WrapElementForJNI(allowMultithread = true, stubName = "CreateEGLSurfaceForCompositorWrapper") private EGLSurface createEGLSurfaceForCompositor() { initEGL(); return mEGL.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, mView.getNativeWindow(), null); } 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,16 +6,17 @@ 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; @@ -408,48 +409,49 @@ public class GeckoLayerClient implements }); setViewportMetrics(newMetrics, type == ViewportMessageType.UPDATE); mDisplayPort = DisplayPortCalculator.calculate(getViewportMetrics(), null); } return mDisplayPort; } - /* This is invoked by JNI on the gecko thread */ + @WrapElementForJNI DisplayPortMetrics getDisplayPort(boolean pageSizeUpdate, boolean isBrowserContentDisplayed, int tabId, ImmutableViewportMetrics metrics) { Tabs tabs = Tabs.getInstance(); if (isBrowserContentDisplayed && tabs.isSelectedTabId(tabId)) { // 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); } } - /* This is invoked by JNI on the gecko thread */ + @WrapElementForJNI void contentDocumentChanged() { mContentDocumentIsDisplayed = false; } - /* This is invoked by JNI on the gecko thread */ + @WrapElementForJNI 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) { @@ -547,23 +549,23 @@ public class GeckoLayerClient implements void setIsRTL(boolean aIsRTL) { synchronized (getLock()) { ImmutableViewportMetrics newMetrics = getViewportMetrics().setIsRTL(aIsRTL); setViewportMetrics(newMetrics, false); } } - /** 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 + /** 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); @@ -606,43 +608,43 @@ public class GeckoLayerClient implements } } DisplayPortCalculator.resetPageState(); mDrawTimingQueue.reset(); mContentDocumentIsDisplayed = true; } - /** 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 + /** 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(). } } - /** 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 + /** 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(); @@ -686,48 +688,48 @@ public class GeckoLayerClient implements if (layersUpdated && mDrawListener != null) { /* Used by robocop for testing purposes */ mDrawListener.drawFinished(); } return mCurrentViewTransform; } - /* Invoked by JNI from the compositor thread */ + @WrapElementForJNI(allowMultithread = true) 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); } - /** This function is invoked by Gecko via JNI; be careful when modifying signature. */ + @WrapElementForJNI(allowMultithread = true) public LayerRenderer.Frame createFrame() { // Create the shaders and textures if necessary. if (!mLayerRendererInitialized) { mLayerRenderer.checkMonitoringEnabled(); mLayerRenderer.createDefaultProgram(); mLayerRendererInitialized = true; } return mLayerRenderer.createFrame(mFrameMetrics); } - /** This function is invoked by Gecko via JNI; be careful when modifying signature. */ + @WrapElementForJNI(allowMultithread = true) public void activateProgram() { mLayerRenderer.activateDefaultProgram(); } - /** This function is invoked by Gecko via JNI; be careful when modifying signature. */ + @WrapElementForJNI(allowMultithread = true) 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,15 +1,16 @@ /* -*- 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 @@ -47,17 +48,18 @@ 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. */ - private ImmutableViewportMetrics(float aPageRectLeft, float aPageRectTop, + @WrapElementForJNI(allowMultithread = true) + public 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 @@ -14,17 +14,16 @@ import org.mozilla.gecko.gfx.RenderTask; import org.mozilla.gecko.mozglue.DirectBufferAllocator; 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;
--- a/mobile/android/base/gfx/LayerView.java +++ b/mobile/android/base/gfx/LayerView.java @@ -9,17 +9,17 @@ import org.mozilla.gecko.GeckoAccessibil import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.GeckoEvent; import org.mozilla.gecko.PrefsHelper; import org.mozilla.gecko.R; import org.mozilla.gecko.Tab; import org.mozilla.gecko.Tabs; import org.mozilla.gecko.TouchEventInterceptor; import org.mozilla.gecko.ZoomConstraints; -import org.mozilla.gecko.mozglue.GeneratableAndroidBridgeTarget; +import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI; import org.mozilla.gecko.util.EventDispatcher; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.PixelFormat; @@ -557,17 +557,17 @@ public class LayerView extends FrameLayo public Object getNativeWindow() { if (mSurfaceView != null) return mSurfaceView.getHolder(); return mTextureView.getSurfaceTexture(); } - @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "RegisterCompositorWrapper") + @WrapElementForJNI(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.GeneratableAndroidBridgeTarget; +import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI; 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(); - @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "RequestContentRepaintWrapper") + @WrapElementForJNI(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)); } - @GeneratableAndroidBridgeTarget(allowMultithread = true, stubName = "PostDelayedCallbackWrapper") + @WrapElementForJNI(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,21 +1,24 @@ /* -*- 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,15 +1,18 @@ /* -*- 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;
--- a/mobile/android/base/moz.build +++ b/mobile/android/base/moz.build @@ -9,20 +9,22 @@ DIRS += ['locales'] include('android-services.mozbuild') thirdparty_source_dir = TOPSRCDIR + '/mobile/android/thirdparty/' mgjar = add_java_jar('gecko-mozglue') mgjar.sources += [ 'mozglue/ByteBufferInputStream.java', 'mozglue/DirectBufferAllocator.java', - 'mozglue/GeneratableAndroidBridgeTarget.java', + 'mozglue/generatorannotations/GeneratorOptions.java', + 'mozglue/generatorannotations/OptionalGeneratedParameter.java', + 'mozglue/generatorannotations/WrapElementForJNI.java', + 'mozglue/generatorannotations/WrapEntireClassForJNI.java', 'mozglue/NativeReference.java', 'mozglue/NativeZip.java', - 'mozglue/OptionalGeneratedParameter.java', ] mgjar.generated_sources += [ 'org/mozilla/gecko/mozglue/GeckoLoader.java', ] mgjar.javac_flags += ['-Xlint:all'] wsjar = add_java_jar('websockets') wsjar.sources += [ thirdparty_source_dir + f for f in [
--- a/mobile/android/base/mozglue/NativeZip.java +++ b/mobile/android/base/mozglue/NativeZip.java @@ -1,15 +1,17 @@ /* -*- 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; @@ -63,16 +65,17 @@ 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);
new file mode 100644 --- /dev/null +++ b/mobile/android/base/mozglue/generatorannotations/GeneratorOptions.java @@ -0,0 +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.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
rename from mobile/android/base/mozglue/OptionalGeneratedParameter.java rename to mobile/android/base/mozglue/generatorannotations/OptionalGeneratedParameter.java --- a/mobile/android/base/mozglue/OptionalGeneratedParameter.java +++ b/mobile/android/base/mozglue/generatorannotations/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; +package org.mozilla.gecko.mozglue.generatorannotations; 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.
rename from mobile/android/base/mozglue/GeneratableAndroidBridgeTarget.java rename to mobile/android/base/mozglue/generatorannotations/WrapElementForJNI.java --- a/mobile/android/base/mozglue/GeneratableAndroidBridgeTarget.java +++ b/mobile/android/base/mozglue/generatorannotations/WrapElementForJNI.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; +package org.mozilla.gecko.mozglue.generatorannotations; 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 GeneratableAndroidBridgeTarget { +public @interface WrapElementForJNI { // 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;
new file mode 100644 --- /dev/null +++ b/mobile/android/base/mozglue/generatorannotations/WrapEntireClassForJNI.java @@ -0,0 +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.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,16 +12,18 @@ * 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() @@ -45,16 +47,17 @@ 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; } @@ -62,16 +65,17 @@ 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) { @@ -107,16 +111,17 @@ 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; @@ -128,16 +133,17 @@ 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; @@ -160,16 +166,17 @@ 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,15 +1,18 @@ /* -*- 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.GeneratableAndroidBridgeTarget; +import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI; 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; } - @GeneratableAndroidBridgeTarget(stubName = "GetClipboardTextWrapper") + @WrapElementForJNI(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 ""; } } - @GeneratableAndroidBridgeTarget(stubName = "SetClipboardText") + @WrapElementForJNI(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,16 +74,35 @@ 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,20 +45,17 @@ nsAndroidHistory::RegisterVisitedCallbac nsTArray<Link*>* list = mListeners.Get(uriString); if (! list) { list = new nsTArray<Link*>(); mListeners.Put(uriString, list); } list->AppendElement(aContent); - AndroidBridge *bridge = AndroidBridge::Bridge(); - if (bridge) { - bridge->CheckURIVisited(uriString); - } + GeckoAppShell::CheckURIVisited(uriString); return NS_OK; } NS_IMETHODIMP nsAndroidHistory::UnregisterVisitedCallback(nsIURI *aURI, Link *aContent) { if (!aContent || !aURI) @@ -91,37 +88,33 @@ nsAndroidHistory::VisitURI(nsIURI *aURI, return NS_OK; if (aFlags & VisitFlags::REDIRECT_SOURCE) return NS_OK; if (aFlags & VisitFlags::UNRECOVERABLE_ERROR) return NS_OK; - 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); - } + nsAutoCString uri; + nsresult rv = aURI->GetSpec(uri); + if (NS_FAILED(rv)) return rv; + NS_ConvertUTF8toUTF16 uriString(uri); + GeckoAppShell::MarkURIVisited(uriString); return NS_OK; } NS_IMETHODIMP nsAndroidHistory::SetURITitle(nsIURI *aURI, const nsAString& aTitle) { - AndroidBridge *bridge = AndroidBridge::Bridge(); - if (bridge) { + if (AndroidBridge::Bridge()) { nsAutoCString uri; nsresult rv = aURI->GetSpec(uri); if (NS_FAILED(rv)) return rv; NS_ConvertUTF8toUTF16 uriString(uri); - bridge->SetURITitle(uriString, aTitle); + GeckoAppShell::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,25 +3,27 @@ * 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; - mozilla::AndroidBridge::Bridge()->CreateShortcut(aTitle, aURI, aIconData, aIntent); + GeckoAppShell::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); - AndroidBridge::Bridge()->EnableNetworkNotifications(); + GeckoAppShell::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() { - AndroidBridge::Bridge()->CloseCamera(); + GeckoAppShell::CloseCamera(); mCallback = nullptr; } } // namespace net } // namespace mozilla
--- a/netwerk/system/android/nsAndroidNetworkLinkService.cpp +++ b/netwerk/system/android/nsAndroidNetworkLinkService.cpp @@ -5,16 +5,18 @@ * 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() @@ -26,36 +28,36 @@ 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 = mozilla::AndroidBridge::Bridge()->IsNetworkLinkUp(); + *aIsUp = GeckoAppShell::IsNetworkLinkUp(); return NS_OK; } NS_IMETHODIMP nsAndroidNetworkLinkService::GetLinkStatusKnown(bool *aIsKnown) { NS_ENSURE_TRUE(mozilla::AndroidBridge::Bridge(), NS_ERROR_NOT_IMPLEMENTED); - *aIsKnown = mozilla::AndroidBridge::Bridge()->IsNetworkLinkKnown(); + *aIsKnown = GeckoAppShell::IsNetworkLinkKnown(); return NS_OK; } NS_IMETHODIMP nsAndroidNetworkLinkService::GetLinkType(uint32_t *aLinkType) { NS_ENSURE_ARG_POINTER(aLinkType); if (!mozilla::AndroidBridge::Bridge()) { // Fail soft here and assume a connection exists NS_WARNING("GetLinkType is not supported without a bridge connection"); *aLinkType = nsINetworkLinkService::LINK_TYPE_UNKNOWN; return NS_OK; } - *aLinkType = mozilla::AndroidBridge::Bridge()->NetworkLinkType(); + *aLinkType = GeckoAppShell::NetworkLinkType(); return NS_OK; }
--- a/toolkit/components/alerts/nsAlertsService.cpp +++ b/toolkit/components/alerts/nsAlertsService.cpp @@ -6,16 +6,17 @@ #include "mozilla/dom/ContentChild.h" #include "mozilla/dom/PermissionMessageUtils.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" @@ -122,17 +123,17 @@ NS_IMETHODIMP nsAlertsService::CloseAler { if (XRE_GetProcessType() == GeckoProcessType_Content) { ContentChild* cpc = ContentChild::GetSingleton(); cpc->SendCloseAlert(nsAutoString(aAlertName), IPC::Principal(aPrincipal)); return NS_OK; } #ifdef MOZ_WIDGET_ANDROID - mozilla::AndroidBridge::Bridge()->CloseNotification(aAlertName); + GeckoAppShell::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, nullptr); } @@ -143,24 +144,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 - mozilla::AndroidBridge::Bridge()->AlertsProgressListener_OnProgress(aAlertName, aProgress, aProgressMax, aAlertText); + GeckoAppShell::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 - mozilla::AndroidBridge::Bridge()->CloseNotification(aAlertName); + GeckoAppShell::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 @@ -47,16 +47,17 @@ #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; @@ -2792,17 +2793,17 @@ nsDownload::SetState(DownloadState aStat #ifdef MOZ_WIDGET_ANDROID nsCOMPtr<nsIMIMEInfo> mimeInfo; nsAutoCString contentType; GetMIMEInfo(getter_AddRefs(mimeInfo)); if (mimeInfo) mimeInfo->GetMIMEType(contentType); - mozilla::AndroidBridge::Bridge()->ScanMedia(path, NS_ConvertUTF8toUTF16(contentType)); + GeckoAppShell::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, nullptr, TRUE); ::CFRelease(observedObject); #endif #ifdef MOZ_WIDGET_ANDROID if (!aContentType.IsEmpty()) { - mozilla::AndroidBridge::Bridge()->ScanMedia(path, NS_ConvertUTF8toUTF16(aContentType)); + mozilla::widget::android::GeckoAppShell::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/devtools/output-parser.js +++ b/toolkit/devtools/output-parser.js @@ -108,16 +108,17 @@ OutputParser.prototype = { * Text to parse. * @param {Object} [options] * Options object. For valid options and default values see * _mergeOptions(). * @return {DocumentFragment} * A document fragment. Colors will not be parsed. */ parseHTMLAttribute: function(value, options={}) { + options.isHTMLAttribute = true; options = this._mergeOptions(options); return this._parse(value, options); }, /** * Parse a string. * @@ -127,91 +128,141 @@ OutputParser.prototype = { * Options object. For valid options and default values see * _mergeOptions(). * @return {DocumentFragment} * A document fragment. */ _parse: function(text, options={}) { text = text.trim(); this.parsed.length = 0; - let dirty = false; - let matched = null; let i = 0; - let trimMatchFromStart = function(match) { - text = text.substr(match.length); - dirty = true; - matched = null; - }; + while (text.length > 0) { + let matched = null; - while (text.length > 0) { + // Prevent this loop from slowing down the browser with too + // many nodes being appended into output. In practice it is very unlikely + // that this will ever happen. + i++; + if (i > MAX_ITERATIONS) { + this._appendTextNode(text); + text = ""; + break; + } + matched = text.match(REGEX_QUOTES); if (matched) { let match = matched[0]; - trimMatchFromStart(match); + + text = this._trimMatchFromStart(text, match); this._appendTextNode(match); + continue; } matched = text.match(REGEX_WHITESPACE); if (matched) { let match = matched[0]; - trimMatchFromStart(match); + + text = this._trimMatchFromStart(text, match); this._appendTextNode(match); + continue; } matched = text.match(REGEX_URL); if (matched) { let [match, url] = matched; - trimMatchFromStart(match); + + text = this._trimMatchFromStart(text, match); this._appendURL(match, url, options); + continue; } matched = text.match(REGEX_ALL_CSS_PROPERTIES); if (matched) { let [match] = matched; - trimMatchFromStart(match); + + text = this._trimMatchFromStart(text, match); this._appendTextNode(match); - dirty = true; + if (options.isHTMLAttribute) { + [text] = this._appendColorOnMatch(text, options); + } + continue; } - matched = text.match(REGEX_ALL_COLORS); - if (matched) { - let match = matched[0]; - if (this._appendColor(match, options)) { - trimMatchFromStart(match); + if (!options.isHTMLAttribute) { + let dirty; + + [text, dirty] = this._appendColorOnMatch(text, options); + + if (dirty) { + continue; } } - if (!dirty) { - // This test must always be last as it indicates use of an unknown - // character that needs to be removed to prevent infinite loops. - matched = text.match(REGEX_FIRST_WORD_OR_CHAR); - if (matched) { - let match = matched[0]; - trimMatchFromStart(match); - this._appendTextNode(match); - } - } + // This test must always be last as it indicates use of an unknown + // character that needs to be removed to prevent infinite loops. + matched = text.match(REGEX_FIRST_WORD_OR_CHAR); + if (matched) { + let match = matched[0]; - dirty = false; - - // Prevent this loop from slowing down the browser with too - // many nodes being appended into output. - i++; - if (i > MAX_ITERATIONS) { - trimMatchFromStart(text); - this._appendTextNode(text); + text = this._trimMatchFromStart(text, match); + this._appendTextNode(match); } } return this._toDOM(); }, /** + * Convenience function to make the parser a little more readable. + * + * @param {String} text + * Main text + * @param {String} match + * Text to remove from the beginning + * + * @return {String} + * The string passed as 'text' with 'match' stripped from the start. + */ + _trimMatchFromStart: function(text, match) { + return text.substr(match.length); + }, + + /** + * Check if there is a color match and append it if it is valid. + * + * @param {String} text + * Main text + * @param {Object} options + * Options object. For valid options and default values see + * _mergeOptions(). + * + * @return {Array} + * An array containing the remaining text and a dirty flag. This array + * is designed for deconstruction using [text, dirty]. + */ + _appendColorOnMatch: function(text, options) { + let dirty; + let matched = text.match(REGEX_ALL_COLORS); + + if (matched) { + let match = matched[0]; + if (this._appendColor(match, options)) { + text = this._trimMatchFromStart(text, match); + dirty = true; + } + } else { + dirty = false; + } + + return [text, dirty]; + }, + + /** * Check if a CSS property supports a specific value. * * @param {String} name * CSS Property name to check * @param {String} value * CSS Property value to check */ _cssPropertySupportsValue: function(name, value) { @@ -327,17 +378,17 @@ OutputParser.prototype = { * node then we append the text to that node. * * @param {String} text * Text to append */ _appendTextNode: function(text) { let lastItem = this.parsed[this.parsed.length - 1]; if (typeof lastItem === "string") { - this.parsed[this.parsed.length - 1] = lastItem + text + this.parsed[this.parsed.length - 1] = lastItem + text; } else { this.parsed.push(text); } }, /** * Take all output and append it into a single DocumentFragment. * @@ -366,26 +417,34 @@ OutputParser.prototype = { * * @param {Object} overrides * The option values to override e.g. _mergeOptions({colors: false}) * * Valid options are: * - defaultColorType: true // Convert colors to the default type * // selected in the options panel. * - colorSwatchClass: "" // The class to use for color swatches. + * - isHTMLAttribute: false // This property indicates whether we + * // are parsing an HTML attribute value. + * // When the value is passed in from an + * // HTML attribute we need to check that + * // any CSS property values are supported + * // by the property name before + * // processing the property value. * - urlClass: "" // The class to be used for url() links. * - baseURI: "" // A string or nsIURI used to resolve * // relative links. * @return {Object} * Overridden options object */ _mergeOptions: function(overrides) { let defaults = { defaultColorType: true, colorSwatchClass: "", + isHTMLAttribute: false, urlClass: "", baseURI: "" }; if (typeof overrides.baseURI === "string") { overrides.baseURI = Services.io.newURI(overrides.baseURI, null, null); }
--- a/toolkit/mozapps/extensions/XPIProvider.jsm +++ b/toolkit/mozapps/extensions/XPIProvider.jsm @@ -3303,17 +3303,17 @@ var XPIProvider = { // All the remaining add-ons in this install location must be new. // Get the migration data for this install location. let locMigrateData = {}; if (XPIDatabase.migrateData && installLocation.name in XPIDatabase.migrateData) locMigrateData = XPIDatabase.migrateData[installLocation.name]; for (let id in addonStates) { changed = addMetadata(installLocation, id, addonStates[id], - locMigrateData[id]) || changed; + locMigrateData[id] || null) || changed; } } // The remaining locations that had add-ons installed in them no longer // have any add-ons installed in them, or the locations no longer exist. // The metadata for the add-ons that were in them must be removed from the // database. for (let location of knownLocations) { @@ -6918,17 +6918,17 @@ DirectoryInstallLocation.prototype = { let dir = this.getStagingDir(); for (let name of aLeafNames) { let file = dir.clone(); file.append(name); recursiveRemove(file); } - if (this.stagingDirLock > 0) + if (this._stagingDirLock > 0) return; let dirEntries = dir.directoryEntries.QueryInterface(Ci.nsIDirectoryEnumerator); try { if (dirEntries.nextFile) return; } finally {
--- 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::AndroidBridge::Bridge()->NotifyXreExit(); + mozilla::widget::android::GeckoAppShell::NotifyXreExit(); free(targs[0]); nsMemory::Free(data); return; }
--- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -1644,17 +1644,17 @@ static nsresult LaunchChild(nsINativeApp gRestartArgc = 1; gRestartArgv[gRestartArgc] = nullptr; #endif } SaveToEnv("MOZ_LAUNCHED_CHILD=1"); #if defined(MOZ_WIDGET_ANDROID) - mozilla::AndroidBridge::Bridge()->ScheduleRestart(); + mozilla::widget::android::GeckoAppShell::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; @@ -1756,17 +1756,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::AndroidBridge::Bridge()->KillAnyZombies(); + mozilla::widget::android::GeckoAppShell::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; @@ -1783,17 +1783,17 @@ ProfileLockedDialog(nsIFile* aProfileDir if (NS_FAILED(rv)) return rv; return NS_LockProfilePath(aProfileDir, aProfileLocalDir, nullptr, aResult); } } else { #ifdef MOZ_WIDGET_ANDROID - if (mozilla::AndroidBridge::Bridge()->UnlockProfile()) { + if (mozilla::widget::android::GeckoAppShell::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 = AndroidBridge::Bridge()->GetSampleTimeJavaProfiling(0, sampleId); + double sampleTime = GeckoJavaSampler::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()) { - AndroidBridge::Bridge()->PauseJavaProfiling(); + GeckoJavaSampler::PauseJavaProfiling(); typename Builder::RootedObject javaThread(b.context(), BuildJavaThreadJSObject(b)); b.ArrayPush(threads, javaThread); - AndroidBridge::Bridge()->UnpauseJavaProfiling(); + GeckoJavaSampler::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 @@ -23,16 +23,17 @@ #include "nsDirectoryServiceDefs.h" #include "mozilla/Services.h" #include "nsThreadUtils.h" #include "ProfilerMarkers.h" #include "nsXULAppAPI.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 @@ -670,17 +671,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; } - mozilla::AndroidBridge::Bridge()->StartJavaProfiling(javaInterval, 1000); + GeckoJavaSampler::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,16 +1,18 @@ /* -*- 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, @@ -60,29 +62,21 @@ 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 mozilla::AndroidBridge::Bridge()-> - OpenUriExternal(NS_ConvertUTF8toUTF16(uriSpec), NS_ConvertUTF8toUTF16(mMimeType), mPackageName, mClassName, mAction) ? + return GeckoAppShell::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) { - if (!mozilla::AndroidBridge::Bridge()) - return NS_ERROR_FAILURE; - - return mozilla::AndroidBridge::Bridge()-> - OpenUriExternal(data, NS_ConvertUTF8toUTF16(mMimeType), mPackageName, + return GeckoAppShell::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,22 +26,17 @@ 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(); - if (AndroidBridge::Bridge()) - return AndroidBridge::Bridge()-> - OpenUriExternal(data, mime, - emptyString,emptyString, sendAction, title) ? NS_OK : NS_ERROR_FAILURE; - - return NS_ERROR_FAILURE; + return GeckoAppShell::OpenUriExternal(data, mime, emptyString,emptyString, sendAction, title) ? NS_OK : 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,16 +5,18 @@ #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; } @@ -23,21 +25,17 @@ NS_IMETHODIMP nsMIMEInfoAndroid::LoadUriInternal(nsIURI * aURI) { nsCString uriSpec; aURI->GetSpec(uriSpec); nsCString uriScheme; aURI->GetScheme(uriScheme); - 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; + return GeckoAppShell::OpenUriExternal(NS_ConvertUTF8toUTF16(uriSpec), (mType.Equals(uriScheme) || mType.Equals(uriSpec)) ? EmptyString() : NS_ConvertUTF8toUTF16(mType)) ? NS_OK : 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 @@ -34,23 +34,18 @@ #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; using namespace mozilla::gfx; NS_IMPL_ISUPPORTS0(nsFilePickerCallback) StaticRefPtr<AndroidBridge> AndroidBridge::sBridge; static unsigned sJavaEnvThreadIndex = 0; static jobject sGlobalContext = nullptr; static void JavaThreadDetachFunc(void *arg); @@ -165,24 +160,23 @@ AndroidBridge::Init(JNIEnv *jEnv) { ALOG_BRIDGE("AndroidBridge::Init"); jEnv->GetJavaVM(&mJavaVM); AutoLocalJNIFrame jniFrame(jEnv); mJNIEnv = nullptr; mThread = -1; - mGLControllerObj = nullptr; + mGLControllerObj = NULL; 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"); @@ -267,16 +261,62 @@ 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(); @@ -306,17 +346,17 @@ AndroidBridge::GetHandlersForMimeType(co const nsAString& aAction) { ALOG_BRIDGE("AndroidBridge::GetHandlersForMimeType"); JNIEnv *env = GetJNIEnv(); if (!env) return false; - jobjectArray arr = GetHandlersForMimeTypeWrapper(aMimeType, aAction); + jobjectArray arr = GeckoAppShell::GetHandlersForMimeTypeWrapper(aMimeType, aAction); if (!arr) return false; jsize len = env->GetArrayLength(arr); if (!aHandlersArray) return len > 0; @@ -335,17 +375,17 @@ AndroidBridge::GetHandlersForURL(const n const nsAString& aAction) { ALOG_BRIDGE("AndroidBridge::GetHandlersForURL"); JNIEnv *env = GetJNIEnv(); if (!env) return false; - jobjectArray arr = GetHandlersForURLWrapper(aURL, aAction); + jobjectArray arr = GeckoAppShell::GetHandlersForURLWrapper(aURL, aAction); if (!arr) return false; jsize len = env->GetArrayLength(arr); if (!aHandlersArray) return len > 0; @@ -360,17 +400,17 @@ void AndroidBridge::GetMimeTypeFromExtensions(const nsACString& aFileExt, nsCString& aMimeType) { ALOG_BRIDGE("AndroidBridge::GetMimeTypeFromExtensions"); JNIEnv *env = GetJNIEnv(); if (!env) return; - jstring jstrType = GetMimeTypeFromExtensionsWrapper(NS_ConvertUTF8toUTF16(aFileExt)); + jstring jstrType = GeckoAppShell::GetMimeTypeFromExtensionsWrapper(NS_ConvertUTF8toUTF16(aFileExt)); if (!jstrType) { return; } nsJNIString jniStr(jstrType, env); CopyUTF16toUTF8(jniStr.get(), aMimeType); env->DeleteLocalRef(jstrType); } @@ -379,17 +419,17 @@ void AndroidBridge::GetExtensionFromMimeType(const nsACString& aMimeType, nsACString& aFileExt) { ALOG_BRIDGE("AndroidBridge::GetExtensionFromMimeType"); JNIEnv *env = GetJNIEnv(); if (!env) return; - jstring jstrExt = GetExtensionFromMimeTypeWrapper(NS_ConvertUTF8toUTF16(aMimeType)); + jstring jstrExt = GeckoAppShell::GetExtensionFromMimeTypeWrapper(NS_ConvertUTF8toUTF16(aMimeType)); if (!jstrExt) { return; } nsJNIString jniStr(jstrExt, env); CopyUTF16toUTF8(jniStr.get(), aFileExt); env->DeleteLocalRef(jstrExt); } @@ -398,83 +438,53 @@ bool AndroidBridge::GetClipboardText(nsAString& aText) { ALOG_BRIDGE("AndroidBridge::GetClipboardText"); JNIEnv *env = GetJNIEnv(); if (!env) return false; - jstring result = GetClipboardTextWrapper(); + jstring result = Clipboard::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)); } - ShowAlertNotificationWrapper(aImageUrl, aAlertTitle, aAlertText, aAlertCookie, aAlertName); + GeckoAppShell::ShowAlertNotificationWrapper(aImageUrl, aAlertTitle, aAlertText, aAlertCookie, aAlertName); } int AndroidBridge::GetDPI() { static int sDPI = 0; if (sDPI) return sDPI; const int DEFAULT_DPI = 160; - sDPI = GetDpiWrapper(); + sDPI = GeckoAppShell::GetDpiWrapper(); if (!sDPI) { return DEFAULT_DPI; } return sDPI; } int @@ -483,72 +493,60 @@ AndroidBridge::GetScreenDepth() ALOG_BRIDGE("%s", __PRETTY_FUNCTION__); static int sDepth = 0; if (sDepth) return sDepth; const int DEFAULT_DEPTH = 16; - sDepth = GetScreenDepthWrapper(); + sDepth = GeckoAppShell::GetScreenDepthWrapper(); if (!sDepth) return DEFAULT_DEPTH; return sDepth; } void AndroidBridge::ShowFilePickerForExtensions(nsAString& aFilePath, const nsAString& aExtensions) { JNIEnv *env = GetJNIEnv(); if (!env) return; - jstring jstr = ShowFilePickerForExtensionsWrapper(aExtensions); + jstring jstr = GeckoAppShell::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 = ShowFilePickerForMimeTypeWrapper(aMimeType); + jstring jstr = GeckoAppShell::ShowFilePickerForMimeTypeWrapper(aMimeType); if (jstr == nullptr) { return; } aFilePath.Assign(nsJNIString(jstr, env)); env->DeleteLocalRef(jstr); } void AndroidBridge::ShowFilePickerAsync(const nsAString& aMimeType, nsFilePickerCallback* callback) { callback->AddRef(); - ShowFilePickerAsyncWrapper(aMimeType, (int64_t) callback); -} - -void -AndroidBridge::HideProgressDialogOnce() -{ - static bool once = false; - if (once) - return; - - HideProgressDialog(); - - once = true; + GeckoAppShell::ShowFilePickerAsyncWrapper(aMimeType, (int64_t) callback); } void AndroidBridge::Vibrate(const nsTArray<uint32_t>& aPattern) { ALOG_BRIDGE("%s", __PRETTY_FUNCTION__); uint32_t len = aPattern.Length(); @@ -566,17 +564,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; } - Vibrate1(d); + GeckoAppShell::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) { @@ -592,34 +590,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); - VibrateA(array, -1/*don't repeat*/); + GeckoAppShell::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 = GetSystemColoursWrapper(); + jintArray arr = GeckoAppShell::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) @@ -647,17 +645,17 @@ AndroidBridge::GetIconForExtension(const return; JNIEnv *env = GetJNIEnv(); if (!env) return; AutoLocalJNIFrame jniFrame(env); - jbyteArray arr = GetIconForExtensionWrapper(NS_ConvertUTF8toUTF16(aFileExt), aIconSize); + jbyteArray arr = GeckoAppShell::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); @@ -675,72 +673,60 @@ 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 != nullptr); if (resetting) { // clear out the old layer client - env->DeleteGlobalRef(mLayerClient->wrappedObject()); delete mLayerClient; mLayerClient = nullptr; } - AndroidGeckoLayerClient *client = new AndroidGeckoLayerClient(); - client->Init(env->NewGlobalRef(jobj)); - mLayerClient = client; + mLayerClient = GeckoLayerClient::Wrap(jobj); 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) { - ALOG_BRIDGE("AndroidBridge::RegisterCompositor"); - if (mGLControllerObj) { + if (mGLControllerObj != NULL && !mGLControllerObj->isNull()) { // we already have this set up, no need to do it again return; } - if (!env) { - env = GetJNIForThread(); // called on the compositor thread - } - if (!env) { - return; - } - - jobject glController = RegisterCompositorWrapper(); + jobject glController = LayerView::RegisterCompositorWrapper(); if (!glController) { return; } - mGLControllerObj = env->NewGlobalRef(glController); - env->DeleteLocalRef(glController); + mGLControllerObj = GLController::Wrap(glController); } EGLSurface AndroidBridge::CreateEGLSurfaceForCompositor() { if (!jEGLSurfacePointerField) { return nullptr; } MOZ_ASSERT(mGLControllerObj, "AndroidBridge::CreateEGLSurfaceForCompositor called with a null GL controller ref"); JNIEnv* env = GetJNIForThread(); // called on the compositor thread if (!env) { return nullptr; } - jobject eglSurface = CreateEGLSurfaceForCompositorWrapper(mGLControllerObj); + jobject eglSurface = mGLControllerObj->CreateEGLSurfaceForCompositorWrapper(); if (!eglSurface) return nullptr; EGLSurface ret = reinterpret_cast<EGLSurface>(env->GetIntField(eglSurface, jEGLSurfacePointerField)); env->DeleteLocalRef(eglSurface); return ret; } @@ -802,21 +788,16 @@ 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); } @@ -1003,17 +984,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 = InitCameraWrapper(NS_ConvertUTF8toUTF16(contentType), (int32_t) camera, (int32_t) width, (int32_t) height); + jintArray arr = GeckoAppShell::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]; @@ -1034,17 +1015,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 = GetCurrentBatteryInformationWrapper(); + jdoubleArray arr = GeckoAppShell::GetCurrentBatteryInformationWrapper(); if (!arr || env->GetArrayLength(arr) != 3) { return; } jdouble* info = env->GetDoubleArrayElements(arr, 0); aBatteryInfo->level() = info[0]; aBatteryInfo->charging() = info[1] == 1.0f; @@ -1058,17 +1039,17 @@ AndroidBridge::HandleGeckoMessage(const { ALOG_BRIDGE("%s", __PRETTY_FUNCTION__); JNIEnv *env = GetJNIEnv(); if (!env) return; AutoLocalJNIFrame jniFrame(env); - jstring returnMessage = HandleGeckoMessageWrapper(aMessage); + jstring returnMessage = GeckoAppShell::HandleGeckoMessageWrapper(aMessage); if (!returnMessage) return; nsJNIString jniStr(returnMessage, env); aRet.Assign(jniStr); ALOG_BRIDGE("leaving %s", __PRETTY_FUNCTION__); } @@ -1125,41 +1106,41 @@ AndroidBridge::SendMessage(const nsAStri nsIMobileMessageCallback* aRequest) { ALOG_BRIDGE("AndroidBridge::SendMessage"); uint32_t requestId; if (!QueueSmsRequest(aRequest, &requestId)) return; - SendMessageWrapper(aNumber, aMessage, requestId); + GeckoAppShell::SendMessageWrapper(aNumber, aMessage, requestId); } void AndroidBridge::GetMessage(int32_t aMessageId, nsIMobileMessageCallback* aRequest) { ALOG_BRIDGE("AndroidBridge::GetMessage"); uint32_t requestId; if (!QueueSmsRequest(aRequest, &requestId)) return; - GetMessageWrapper(aMessageId, requestId); + GeckoAppShell::GetMessageWrapper(aMessageId, requestId); } void AndroidBridge::DeleteMessage(int32_t aMessageId, nsIMobileMessageCallback* aRequest) { ALOG_BRIDGE("AndroidBridge::DeleteMessage"); uint32_t requestId; if (!QueueSmsRequest(aRequest, &requestId)) return; - DeleteMessageWrapper(aMessageId, requestId); + GeckoAppShell::DeleteMessageWrapper(aMessageId, requestId); } void AndroidBridge::CreateMessageList(const dom::mobilemessage::SmsFilterData& aFilter, bool aReverse, nsIMobileMessageCallback* aRequest) { ALOG_BRIDGE("AndroidBridge::CreateMessageList"); @@ -1178,31 +1159,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])); } - CreateMessageListWrapper(aFilter.startDate(), aFilter.endDate(), + GeckoAppShell::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; - GetNextMessageInListWrapper(aListId, requestId); + GeckoAppShell::GetNextMessageInListWrapper(aListId, requestId); } bool AndroidBridge::QueueSmsRequest(nsIMobileMessageCallback* aRequest, uint32_t* aRequestIdOut) { MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); MOZ_ASSERT(aRequest && aRequestIdOut); @@ -1244,17 +1225,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 = GetCurrentNetworkInformationWrapper(); + jdoubleArray arr = GeckoAppShell::GetCurrentNetworkInformationWrapper(); if (!arr || env->GetArrayLength(arr) != 4) { return; } jdouble* info = env->GetDoubleArrayElements(arr, 0); aNetworkInfo->bandwidth() = info[0]; aNetworkInfo->canBeMetered() = info[1] == 1.0f; @@ -1437,17 +1418,17 @@ jobject AndroidBridge::GetGlobalContextRef() { if (sGlobalContext == nullptr) { JNIEnv *env = GetJNIForThread(); if (!env) return 0; AutoLocalJNIFrame jniFrame(env, 4); - jobject context = GetContext(); + jobject context = GeckoAppShell::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; @@ -1488,58 +1469,101 @@ AndroidBridge::UnlockWindow(void* window } return true; } void AndroidBridge::SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect) { - AndroidGeckoLayerClient *client = mLayerClient; + GeckoLayerClient *client = mLayerClient; if (!client) return; - client->SetFirstPaintViewport(aOffset, aZoom, aCssPageRect); + client->SetFirstPaintViewport((float)aOffset.x, (float)aOffset.y, aZoom.scale, + aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost()); } void AndroidBridge::SetPageRect(const CSSRect& aCssPageRect) { - AndroidGeckoLayerClient *client = mLayerClient; + GeckoLayerClient *client = mLayerClient; if (!client) return; - client->SetPageRect(aCssPageRect); + client->SetPageRect(aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost()); } void AndroidBridge::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, bool aLayersUpdated, ScreenPoint& aScrollOffset, CSSToScreenScale& aScale, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset) { - AndroidGeckoLayerClient *client = mLayerClient; - if (!client) + GeckoLayerClient *client = mLayerClient; + if (!client) { + ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__); 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!"); - client->SyncViewportInfo(aDisplayPort, aDisplayResolution, aLayersUpdated, - aScrollOffset, aScale, aFixedLayerMargins, - aOffset); + 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; } 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) { - AndroidGeckoLayerClient *client = mLayerClient; - if (!client) + GeckoLayerClient *client = mLayerClient; + if (!client) { + ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__); 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); - client->SyncFrameMetrics(aScrollOffset, aZoom, aCssPageRect, - aLayersUpdated, aDisplayPort, aDisplayResolution, - aIsFirstPaint, aFixedLayerMargins, aOffset); + 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; } AndroidBridge::AndroidBridge() : mLayerClient(nullptr), mNativePanZoomController(nullptr) { } @@ -1594,55 +1618,22 @@ static void JavaThreadDetachFunc(void *arg) { JNIEnv *env = (JNIEnv*) arg; JavaVM *vm = nullptr; env->GetJavaVM(&vm); vm->DetachCurrentThread(); } -extern "C" { - __attribute__ ((visibility("default"))) - JNIEnv * GetJNIForThread() - { - JNIEnv *jEnv = nullptr; - JavaVM *jVm = mozilla::AndroidBridge::GetVM(); - if (!jVm) { - __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread", "Returned a null VM"); - return nullptr; - } - 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, nullptr); - if (status) { - __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread", "Could not attach"); - return nullptr; - } - - 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 = GetScreenOrientationWrapper(); + int16_t orientation = GeckoAppShell::GetScreenOrientationWrapper(); if (!orientation) return dom::eScreenOrientation_None; return static_cast<dom::ScreenOrientation>(orientation); } void @@ -1658,17 +1649,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 = GetProxyForURIWrapper(NS_ConvertUTF8toUTF16(aSpec), + jstring jstrRet = GeckoAppShell::GetProxyForURIWrapper(NS_ConvertUTF8toUTF16(aSpec), NS_ConvertUTF8toUTF16(aScheme), NS_ConvertUTF8toUTF16(aHost), aPort); if (!jstrRet) return NS_ERROR_FAILURE; nsJNIString jniStr(jstrRet, env); @@ -1694,34 +1685,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(); - AddPluginViewWrapper(view, cssRect.x, cssRect.y, cssRect.width, cssRect.height, isFullScreen); + GeckoAppShell::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 = GetThreadNameJavaProfilingWrapper(aThreadId); + jstring jstrThreadName = GeckoJavaSampler::GetThreadNameJavaProfilingWrapper(aThreadId); if (!jstrThreadName) return false; nsJNIString jniStr(jstrThreadName, env); CopyUTF16toUTF8(jniStr.get(), aResult); return true; } @@ -1731,17 +1722,17 @@ AndroidBridge::GetFrameNameJavaProfiling uint32_t aFrameId, nsCString & aResult) { JNIEnv* env = GetJNIForThread(); if (!env) return false; AutoLocalJNIFrame jniFrame(env); - jstring jstrSampleName = GetFrameNameJavaProfilingWrapper(aThreadId, aSampleId, aFrameId); + jstring jstrSampleName = GeckoJavaSampler::GetFrameNameJavaProfilingWrapper(aThreadId, aSampleId, aFrameId); if (!jstrSampleName) return false; nsJNIString jniStr(jstrSampleName, env); CopyUTF16toUTF8(jniStr.get(), aResult); env->DeleteLocalRef(jstrSampleName); return true; @@ -1852,71 +1843,144 @@ 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) + if (!env || !mLayerClient || mLayerClient->isNull()) { + + ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__); return; + } AutoLocalJNIFrame jniFrame(env, 0); - mLayerClient->GetDisplayPort(&jniFrame, aPageSizeUpdate, aIsBrowserContentDisplayed, tabId, metrics, displayPort); + + 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__); } void AndroidBridge::ContentDocumentChanged() { - JNIEnv* env = GetJNIEnv(); - if (!env || !mLayerClient) + if (!mLayerClient) { return; - AutoLocalJNIFrame jniFrame(env, 0); - mLayerClient->ContentDocumentChanged(&jniFrame); + } + mLayerClient->ContentDocumentChanged(); } bool AndroidBridge::IsContentDocumentDisplayed() { JNIEnv* env = GetJNIEnv(); if (!env || !mLayerClient) return false; - AutoLocalJNIFrame jniFrame(env, 0); - return mLayerClient->IsContentDocumentDisplayed(&jniFrame); + + return mLayerClient->IsContentDocumentDisplayed(); } bool AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY) { - AndroidGeckoLayerClient *client = mLayerClient; - if (!client) + GeckoLayerClient *client = mLayerClient; + if (!client) { + ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__); return false; + } - return client->ProgressiveUpdateCallback(aHasPendingNewThebesContent, aDisplayPort, aDisplayResolution, aDrawingCritical, aViewport, aScaleX, aScaleY); + 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; } -jobject +NativePanZoomController* AndroidBridge::SetNativePanZoomController(jobject obj) { - jobject old = mNativePanZoomController; - mNativePanZoomController = obj; + NativePanZoomController* old = mNativePanZoomController; + mNativePanZoomController = NativePanZoomController::Wrap(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; - RequestContentRepaintWrapper(mNativePanZoomController, - dp.x, dp.y, dp.width, dp.height, resolution.scale); + mNativePanZoomController->RequestContentRepaintWrapper(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)); @@ -1963,17 +2027,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 - PostDelayedCallbackWrapper(mNativePanZoomController, (int64_t)aDelayMs); + mNativePanZoomController->PostDelayedCallbackWrapper((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 "AndroidJavaWrappers.h" +#include "GeneratedJNIWrappers.h" #include "nsIMutableArray.h" #include "nsIMIMEInfo.h" #include "nsColor.h" #include "gfxRect.h" #include "nsIAndroidBridge.h" #include "nsIMobileMessageCallback.h" @@ -36,24 +36,25 @@ 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 { @@ -155,20 +156,16 @@ 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 */ @@ -178,36 +175,32 @@ 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); - AndroidGeckoLayerClient &GetLayerClient() { return *mLayerClient; } + GeckoLayerClient* 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); @@ -215,18 +208,16 @@ 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 = nullptr); EGLSurface CreateEGLSurfaceForCompositor(); @@ -335,17 +326,17 @@ protected: // the global JavaVM JavaVM *mJavaVM; // the JNIEnv for the main thread JNIEnv *mJNIEnv; pthread_t mThread; - AndroidGeckoLayerClient *mLayerClient; + GeckoLayerClient *mLayerClient = NULL; // the android.telephony.SmsMessage class jclass mAndroidSmsMessageClass; AndroidBridge(); ~AndroidBridge(); void InitStubs(JNIEnv *jEnv); @@ -376,17 +367,17 @@ protected: // For native surface stuff jclass jSurfaceClass; jfieldID jSurfacePointerField; jclass jLayerView; jfieldID jEGLSurfacePointerField; - jobject mGLControllerObj; + GLController *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); @@ -400,25 +391,24 @@ 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: - jobject mNativePanZoomController; + NativePanZoomController* 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: - #include "GeneratedJNIWrappers.h" - jobject SetNativePanZoomController(jobject obj); + NativePanZoomController* 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(bool aIsRoot, const CSSRect& aContentRect, const CSSSize& aScrollableSize) MOZ_OVERRIDE;
--- a/widget/android/AndroidBridgeUtilities.h +++ b/widget/android/AndroidBridgeUtilities.h @@ -12,8 +12,22 @@ #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 @@ -857,20 +857,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; } - jobject oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(env->NewGlobalRef(instance)); - if (oldRef) { + NativePanZoomController* oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(instance); + if (oldRef && !oldRef->isNull()) { MOZ_ASSERT(false, "Registering a new NPZC when we already have one"); - env->DeleteGlobalRef(oldRef); + delete oldRef; } } NS_EXPORT void JNICALL Java_org_mozilla_gecko_gfx_NativePanZoomController_handleTouchEvent(JNIEnv* env, jobject instance, jobject event) { APZCTreeManager *controller = nsWindow::GetAPZCTreeManager(); if (controller) { @@ -901,21 +901,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; } - jobject oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(nullptr); - if (!oldRef) { + NativePanZoomController* oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(NULL); + if (!oldRef || oldRef->isNull()) { MOZ_ASSERT(false, "Clearing a non-existent NPZC"); } else { - env->DeleteGlobalRef(oldRef); + delete 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,22 +9,16 @@ #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,77 +86,38 @@ 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 = nullptr; } void mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv) { AndroidGeckoEvent::InitGeckoEventClass(jEnv); AndroidPoint::InitPointClass(jEnv); AndroidLocation::InitLocationClass(jEnv); AndroidRect::InitRectClass(jEnv); AndroidRectF::InitRectFClass(jEnv); - AndroidGeckoLayerClient::InitGeckoLayerClientClass(jEnv); AndroidLayerRendererFrame::InitLayerRendererFrameClass(jEnv); - AndroidViewTransform::InitViewTransformClass(jEnv); - AndroidProgressiveUpdateData::InitProgressiveUpdateDataClass(jEnv); + InitStubs(jEnv); } void AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv) { initInit(); jGeckoEventClass = getClassGlobalRef("org/mozilla/gecko/GeckoEvent"); @@ -286,91 +247,28 @@ AndroidRectF::InitRectFClass(JNIEnv *jEn 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, @@ -888,23 +786,16 @@ AndroidPoint::Init(JNIEnv *jenv, jobject 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); } @@ -915,291 +806,18 @@ AndroidLayerRendererFrame::Dispose(JNIEn 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()) @@ -1242,116 +860,16 @@ AndroidLayerRendererFrame::EndDrawing(Au 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 @@ -10,39 +10,31 @@ #include <android/input.h> #include <android/log.h> #include "nsGeoPosition.h" #include "nsRect.h" #include "nsString.h" #include "nsTArray.h" #include "nsIObserver.h" +#include "nsIAndroidBridge.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. @@ -70,29 +62,61 @@ public: private: int32_t mRefCnt; jobject mObject; }; class WrappedJavaObject { public: WrappedJavaObject() : - wrapped_obj(0) + wrapped_obj(NULL) { } - WrappedJavaObject(jobject jobj) { + WrappedJavaObject(jobject jobj) : wrapped_obj(NULL) { Init(jobj); } void Init(jobject jobj) { wrapped_obj = jobj; } bool isNull() const { - return wrapped_obj == 0; + 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; } jobject wrappedObject() const { return wrapped_obj; } protected: jobject wrapped_obj; @@ -181,71 +205,16 @@ 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); @@ -256,63 +225,16 @@ public: 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, @@ -428,16 +350,39 @@ 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,25 +1,100 @@ // 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" -#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) { + +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::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::jNetworkLinkType = 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) { 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"); @@ -90,46 +165,33 @@ void AndroidBridge::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"); - jCreateEGLSurfaceForCompositorWrapper = getMethod("createEGLSurfaceForCompositor", "()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"); } -void AndroidBridge::AcknowledgeEvent() { - JNIEnv *env = GetJNIEnv(); +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(); 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(); @@ -141,21 +203,22 @@ void AndroidBridge::AcknowledgeEvent() { if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::AddPluginViewWrapper(jobject a0, jfloat a1, jfloat a2, jfloat a3, jfloat a4, bool a5) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::AddPluginViewWrapper(jobject a0, jfloat a1, jfloat a2, jfloat a3, jfloat a4, bool a5) { + JNIEnv *env = AndroidBridge::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(); @@ -175,53 +238,55 @@ void AndroidBridge::AddPluginViewWrapper if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::AlertsProgressListener_OnProgress(const nsAString& a0, int64_t a1, int64_t a2, const nsAString& a3) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::AlertsProgressListener_OnProgress(const nsAString& a0, int64_t a1, int64_t a2, const nsAString& a3) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); + args[0].l = AndroidBridge::NewJavaString(env, a0); args[1].j = a1; args[2].j = a2; - args[3].l = NewJavaString(env, a3); + args[3].l = AndroidBridge::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 AndroidBridge::CancelVibrate() { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::CancelVibrate() { + JNIEnv *env = AndroidBridge::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(); @@ -233,49 +298,51 @@ void AndroidBridge::CancelVibrate() { if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::CheckURIVisited(const nsAString& a0) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::CheckURIVisited(const nsAString& a0) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); + jstring j0 = AndroidBridge::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 AndroidBridge::ClearMessageList(int32_t a0) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::ClearMessageList(int32_t a0) { + JNIEnv *env = AndroidBridge::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(); @@ -287,21 +354,22 @@ void AndroidBridge::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 AndroidBridge::CloseCamera() { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::CloseCamera() { + JNIEnv *env = AndroidBridge::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(); @@ -313,49 +381,51 @@ void AndroidBridge::CloseCamera() { if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::CloseNotification(const nsAString& a0) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::CloseNotification(const nsAString& a0) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); + jstring j0 = AndroidBridge::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 AndroidBridge::CreateMessageListWrapper(int64_t a0, int64_t a1, jobjectArray a2, int32_t a3, int32_t a4, bool a5, int32_t a6) { - JNIEnv *env = GetJNIEnv(); +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(); 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(); @@ -376,53 +446,55 @@ void AndroidBridge::CreateMessageListWra if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::CreateShortcut(const nsAString& a0, const nsAString& a1, const nsAString& a2, const nsAString& a3) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::CreateShortcut(const nsAString& a0, const nsAString& a1, const nsAString& a2, const nsAString& a3) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); - args[1].l = NewJavaString(env, a1); - args[2].l = NewJavaString(env, a2); - args[3].l = NewJavaString(env, a3); + 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); 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 AndroidBridge::DeleteMessageWrapper(int32_t a0, int32_t a1) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::DeleteMessageWrapper(int32_t a0, int32_t a1) { + JNIEnv *env = AndroidBridge::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(); @@ -434,21 +506,22 @@ void AndroidBridge::DeleteMessageWrapper if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::DisableBatteryNotifications() { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::DisableBatteryNotifications() { + JNIEnv *env = AndroidBridge::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(); @@ -460,21 +533,22 @@ void AndroidBridge::DisableBatteryNotifi if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::DisableNetworkNotifications() { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::DisableNetworkNotifications() { + JNIEnv *env = AndroidBridge::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(); @@ -486,21 +560,22 @@ void AndroidBridge::DisableNetworkNotifi if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::DisableScreenOrientationNotifications() { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::DisableScreenOrientationNotifications() { + JNIEnv *env = AndroidBridge::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(); @@ -512,21 +587,22 @@ void AndroidBridge::DisableScreenOrienta if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::DisableSensor(int32_t a0) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::DisableSensor(int32_t a0) { + JNIEnv *env = AndroidBridge::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(); @@ -538,21 +614,22 @@ void AndroidBridge::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 AndroidBridge::EnableBatteryNotifications() { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::EnableBatteryNotifications() { + JNIEnv *env = AndroidBridge::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(); @@ -564,21 +641,22 @@ void AndroidBridge::EnableBatteryNotific if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::EnableLocation(bool a0) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::EnableLocation(bool a0) { + JNIEnv *env = AndroidBridge::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(); @@ -590,21 +668,22 @@ void AndroidBridge::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 AndroidBridge::EnableLocationHighAccuracy(bool a0) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::EnableLocationHighAccuracy(bool a0) { + JNIEnv *env = AndroidBridge::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(); @@ -616,21 +695,22 @@ void AndroidBridge::EnableLocationHighAc if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::EnableNetworkNotifications() { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::EnableNetworkNotifications() { + JNIEnv *env = AndroidBridge::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(); @@ -642,21 +722,22 @@ void AndroidBridge::EnableNetworkNotific if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::EnableScreenOrientationNotifications() { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::EnableScreenOrientationNotifications() { + JNIEnv *env = AndroidBridge::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,21 +749,22 @@ void AndroidBridge::EnableScreenOrientat if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::EnableSensor(int32_t a0) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::EnableSensor(int32_t a0) { + JNIEnv *env = AndroidBridge::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(); @@ -694,20 +776,21 @@ void AndroidBridge::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 AndroidBridge::GetContext() { +jobject GeckoAppShell::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__); @@ -720,22 +803,23 @@ jobject AndroidBridge::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 AndroidBridge::GetCurrentBatteryInformationWrapper() { - JNIEnv *env = GetJNIEnv(); +jdoubleArray GeckoAppShell::GetCurrentBatteryInformationWrapper() { + JNIEnv *env = AndroidBridge::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(); @@ -747,22 +831,23 @@ jdoubleArray AndroidBridge::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 AndroidBridge::GetCurrentNetworkInformationWrapper() { - JNIEnv *env = GetJNIEnv(); +jdoubleArray GeckoAppShell::GetCurrentNetworkInformationWrapper() { + JNIEnv *env = AndroidBridge::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(); @@ -774,22 +859,23 @@ jdoubleArray AndroidBridge::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 AndroidBridge::GetDensity() { - JNIEnv *env = GetJNIEnv(); +jfloat GeckoAppShell::GetDensity() { + JNIEnv *env = AndroidBridge::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(); @@ -801,22 +887,23 @@ jfloat AndroidBridge::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 AndroidBridge::GetDpiWrapper() { - JNIEnv *env = GetJNIEnv(); +int32_t GeckoAppShell::GetDpiWrapper() { + JNIEnv *env = AndroidBridge::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(); @@ -828,140 +915,145 @@ int32_t AndroidBridge::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 AndroidBridge::GetExtensionFromMimeTypeWrapper(const nsAString& a0) { - JNIEnv *env = GetJNIEnv(); +jstring GeckoAppShell::GetExtensionFromMimeTypeWrapper(const nsAString& a0) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); + jstring j0 = AndroidBridge::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; } -jobjectArray AndroidBridge::GetHandlersForMimeTypeWrapper(const nsAString& a0, const nsAString& a1) { - JNIEnv *env = GetJNIEnv(); +jobjectArray GeckoAppShell::GetHandlersForMimeTypeWrapper(const nsAString& a0, const nsAString& a1) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); - jstring j1 = NewJavaString(env, a1); + jstring j0 = AndroidBridge::NewJavaString(env, a0); + jstring j1 = AndroidBridge::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 AndroidBridge::GetHandlersForURLWrapper(const nsAString& a0, const nsAString& a1) { - JNIEnv *env = GetJNIEnv(); +jobjectArray GeckoAppShell::GetHandlersForURLWrapper(const nsAString& a0, const nsAString& a1) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); - jstring j1 = NewJavaString(env, a1); + jstring j0 = AndroidBridge::NewJavaString(env, a0); + jstring j1 = AndroidBridge::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 AndroidBridge::GetIconForExtensionWrapper(const nsAString& a0, int32_t a1) { - JNIEnv *env = GetJNIEnv(); +jbyteArray GeckoAppShell::GetIconForExtensionWrapper(const nsAString& a0, int32_t a1) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); + jstring j0 = AndroidBridge::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 AndroidBridge::GetMessageWrapper(int32_t a0, int32_t a1) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::GetMessageWrapper(int32_t a0, int32_t a1) { + JNIEnv *env = AndroidBridge::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(); @@ -973,50 +1065,52 @@ void AndroidBridge::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 AndroidBridge::GetMimeTypeFromExtensionsWrapper(const nsAString& a0) { - JNIEnv *env = GetJNIEnv(); +jstring GeckoAppShell::GetMimeTypeFromExtensionsWrapper(const nsAString& a0) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); + jstring j0 = AndroidBridge::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 AndroidBridge::GetNextMessageInListWrapper(int32_t a0, int32_t a1) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::GetNextMessageInListWrapper(int32_t a0, int32_t a1) { + JNIEnv *env = AndroidBridge::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(); @@ -1028,54 +1122,56 @@ void AndroidBridge::GetNextMessageInList if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -jstring AndroidBridge::GetProxyForURIWrapper(const nsAString& a0, const nsAString& a1, const nsAString& a2, int32_t a3) { - JNIEnv *env = GetJNIEnv(); +jstring GeckoAppShell::GetProxyForURIWrapper(const nsAString& a0, const nsAString& a1, const nsAString& a2, int32_t a3) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); - args[1].l = NewJavaString(env, a1); - args[2].l = NewJavaString(env, a2); + args[0].l = AndroidBridge::NewJavaString(env, a0); + args[1].l = AndroidBridge::NewJavaString(env, a1); + args[2].l = AndroidBridge::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 AndroidBridge::GetScreenDepthWrapper() { - JNIEnv *env = GetJNIEnv(); +int32_t GeckoAppShell::GetScreenDepthWrapper() { + JNIEnv *env = AndroidBridge::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(); @@ -1087,22 +1183,23 @@ int32_t AndroidBridge::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 AndroidBridge::GetScreenOrientationWrapper() { - JNIEnv *env = GetJNIEnv(); +int16_t GeckoAppShell::GetScreenOrientationWrapper() { + JNIEnv *env = AndroidBridge::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(); @@ -1114,22 +1211,23 @@ int16_t AndroidBridge::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 AndroidBridge::GetShowPasswordSetting() { - JNIEnv *env = GetJNIEnv(); +bool GeckoAppShell::GetShowPasswordSetting() { + JNIEnv *env = AndroidBridge::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(); @@ -1141,22 +1239,23 @@ bool AndroidBridge::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 AndroidBridge::GetSystemColoursWrapper() { - JNIEnv *env = GetJNIEnv(); +jintArray GeckoAppShell::GetSystemColoursWrapper() { + JNIEnv *env = AndroidBridge::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(); @@ -1168,51 +1267,53 @@ jintArray AndroidBridge::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 AndroidBridge::HandleGeckoMessageWrapper(const nsAString& a0) { - JNIEnv *env = GetJNIEnv(); +jstring GeckoAppShell::HandleGeckoMessageWrapper(const nsAString& a0) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); + jstring j0 = AndroidBridge::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 AndroidBridge::HideProgressDialog() { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::HideProgressDialog() { + JNIEnv *env = AndroidBridge::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(); @@ -1224,54 +1325,56 @@ void AndroidBridge::HideProgressDialog() if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -jintArray AndroidBridge::InitCameraWrapper(const nsAString& a0, int32_t a1, int32_t a2, int32_t a3) { - JNIEnv *env = GetJNIEnv(); +jintArray GeckoAppShell::InitCameraWrapper(const nsAString& a0, int32_t a1, int32_t a2, int32_t a3) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); + args[0].l = AndroidBridge::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 AndroidBridge::IsNetworkLinkKnown() { - JNIEnv *env = GetJNIEnv(); +bool GeckoAppShell::IsNetworkLinkKnown() { + JNIEnv *env = AndroidBridge::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(); @@ -1283,22 +1386,23 @@ bool AndroidBridge::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 AndroidBridge::IsNetworkLinkUp() { - JNIEnv *env = GetJNIEnv(); +bool GeckoAppShell::IsNetworkLinkUp() { + JNIEnv *env = AndroidBridge::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(); @@ -1310,22 +1414,23 @@ bool AndroidBridge::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 AndroidBridge::IsTablet() { - JNIEnv *env = GetJNIEnv(); +bool GeckoAppShell::IsTablet() { + JNIEnv *env = AndroidBridge::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(); @@ -1337,22 +1442,23 @@ bool AndroidBridge::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 AndroidBridge::KillAnyZombies() { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::KillAnyZombies() { + JNIEnv *env = AndroidBridge::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(); @@ -1364,21 +1470,22 @@ void AndroidBridge::KillAnyZombies() { if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::LockScreenOrientation(int32_t a0) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::LockScreenOrientation(int32_t a0) { + JNIEnv *env = AndroidBridge::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(); @@ -1390,49 +1497,51 @@ void AndroidBridge::LockScreenOrientatio if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::MarkURIVisited(const nsAString& a0) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::MarkURIVisited(const nsAString& a0) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); + jstring j0 = AndroidBridge::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 AndroidBridge::MoveTaskToBack() { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::MoveTaskToBack() { + JNIEnv *env = AndroidBridge::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(); @@ -1444,21 +1553,22 @@ void AndroidBridge::MoveTaskToBack() { if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -int32_t AndroidBridge::NetworkLinkType() { - JNIEnv *env = GetJNIEnv(); +int32_t GeckoAppShell::NetworkLinkType() { + JNIEnv *env = AndroidBridge::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(); @@ -1470,22 +1580,23 @@ int32_t AndroidBridge::NetworkLinkType() 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; } -void AndroidBridge::NotifyDefaultPrevented(bool a0) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::NotifyDefaultPrevented(bool a0) { + JNIEnv *env = AndroidBridge::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(); @@ -1497,155 +1608,145 @@ void AndroidBridge::NotifyDefaultPrevent if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::NotifyIME(int32_t a0) { - if (!sBridge) { - ALOG_BRIDGE("Aborted: No sBridge - %s", __PRETTY_FUNCTION__); - return; - } - - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::NotifyIME(int32_t a0) { + JNIEnv *env = AndroidBridge::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(sBridge->mGeckoAppShellClass, sBridge->jNotifyIME, a0); + env->CallStaticVoidMethod(mGeckoAppShellClass, 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 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(); +void GeckoAppShell::NotifyIMEChange(const nsAString& a0, int32_t a1, int32_t a2, int32_t a3) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); + args[0].l = AndroidBridge::NewJavaString(env, a0); args[1].i = a1; args[2].i = a2; args[3].i = a3; - env->CallStaticVoidMethodA(sBridge->mGeckoAppShellClass, sBridge->jNotifyIMEChange, args); + env->CallStaticVoidMethodA(mGeckoAppShellClass, 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 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(); +void GeckoAppShell::NotifyIMEContext(int32_t a0, const nsAString& a1, const nsAString& a2, const nsAString& a3) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a1); - args[2].l = NewJavaString(env, a2); - args[3].l = NewJavaString(env, a3); - - env->CallStaticVoidMethodA(sBridge->mGeckoAppShellClass, sBridge->jNotifyIMEContext, args); + 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); if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::NotifyWakeLockChanged(const nsAString& a0, const nsAString& a1) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::NotifyWakeLockChanged(const nsAString& a0, const nsAString& a1) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); - jstring j1 = NewJavaString(env, a1); + jstring j0 = AndroidBridge::NewJavaString(env, a0); + jstring j1 = AndroidBridge::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 AndroidBridge::NotifyXreExit() { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::NotifyXreExit() { + JNIEnv *env = AndroidBridge::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(); @@ -1657,56 +1758,58 @@ void AndroidBridge::NotifyXreExit() { if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -bool AndroidBridge::OpenUriExternal(const nsAString& a0, const nsAString& a1, const nsAString& a2, const nsAString& a3, const nsAString& a4, const nsAString& a5) { - JNIEnv *env = GetJNIEnv(); +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(); 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 = 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); + 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); 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 AndroidBridge::PerformHapticFeedback(bool a0) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::PerformHapticFeedback(bool a0) { + JNIEnv *env = AndroidBridge::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(); @@ -1718,21 +1821,22 @@ void AndroidBridge::PerformHapticFeedbac if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -bool AndroidBridge::PumpMessageLoop() { - JNIEnv *env = GetJNIEnv(); +bool GeckoAppShell::PumpMessageLoop() { + JNIEnv *env = AndroidBridge::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(); @@ -1744,22 +1848,23 @@ bool AndroidBridge::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 AndroidBridge::RegisterSurfaceTextureFrameListener(jobject a0, int32_t a1) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::RegisterSurfaceTextureFrameListener(jobject a0, int32_t a1) { + JNIEnv *env = AndroidBridge::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(); @@ -1771,21 +1876,22 @@ void AndroidBridge::RegisterSurfaceTextu if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::RemovePluginView(jobject a0, bool a1) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::RemovePluginView(jobject a0, bool a1) { + JNIEnv *env = AndroidBridge::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(); @@ -1797,50 +1903,52 @@ void AndroidBridge::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 AndroidBridge::ScanMedia(const nsAString& a0, const nsAString& a1) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::ScanMedia(const nsAString& a0, const nsAString& a1) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); - jstring j1 = NewJavaString(env, a1); + jstring j0 = AndroidBridge::NewJavaString(env, a0); + jstring j1 = AndroidBridge::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 AndroidBridge::ScheduleRestart() { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::ScheduleRestart() { + JNIEnv *env = AndroidBridge::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(); @@ -1852,52 +1960,54 @@ void AndroidBridge::ScheduleRestart() { if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::SendMessageWrapper(const nsAString& a0, const nsAString& a1, int32_t a2) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::SendMessageWrapper(const nsAString& a0, const nsAString& a1, int32_t a2) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); - args[1].l = NewJavaString(env, a1); + args[0].l = AndroidBridge::NewJavaString(env, a0); + args[1].l = AndroidBridge::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 AndroidBridge::SetFullScreen(bool a0) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::SetFullScreen(bool a0) { + JNIEnv *env = AndroidBridge::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(); @@ -1909,21 +2019,22 @@ void AndroidBridge::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 AndroidBridge::SetKeepScreenOn(bool a0) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::SetKeepScreenOn(bool a0) { + JNIEnv *env = AndroidBridge::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(); @@ -1935,197 +2046,204 @@ void AndroidBridge::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 AndroidBridge::SetSelectedLocale(const nsAString& a0) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::SetSelectedLocale(const nsAString& a0) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); + jstring j0 = AndroidBridge::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 AndroidBridge::SetURITitle(const nsAString& a0, const nsAString& a1) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::SetURITitle(const nsAString& a0, const nsAString& a1) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); - jstring j1 = NewJavaString(env, a1); + jstring j0 = AndroidBridge::NewJavaString(env, a0); + jstring j1 = AndroidBridge::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 AndroidBridge::ShowAlertNotificationWrapper(const nsAString& a0, const nsAString& a1, const nsAString& a2, const nsAString& a3, const nsAString& a4) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::ShowAlertNotificationWrapper(const nsAString& a0, const nsAString& a1, const nsAString& a2, const nsAString& a3, const nsAString& a4) { + JNIEnv *env = AndroidBridge::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 = 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[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); 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 AndroidBridge::ShowFilePickerAsyncWrapper(const nsAString& a0, int64_t a1) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::ShowFilePickerAsyncWrapper(const nsAString& a0, int64_t a1) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); + jstring j0 = AndroidBridge::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 AndroidBridge::ShowFilePickerForExtensionsWrapper(const nsAString& a0) { - JNIEnv *env = GetJNIEnv(); +jstring GeckoAppShell::ShowFilePickerForExtensionsWrapper(const nsAString& a0) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); + jstring j0 = AndroidBridge::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 AndroidBridge::ShowFilePickerForMimeTypeWrapper(const nsAString& a0) { - JNIEnv *env = GetJNIEnv(); +jstring GeckoAppShell::ShowFilePickerForMimeTypeWrapper(const nsAString& a0) { + JNIEnv *env = AndroidBridge::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 = NewJavaString(env, a0); + jstring j0 = AndroidBridge::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 AndroidBridge::ShowInputMethodPicker() { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::ShowInputMethodPicker() { + JNIEnv *env = AndroidBridge::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(); @@ -2137,21 +2255,22 @@ void AndroidBridge::ShowInputMethodPicke if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -bool AndroidBridge::UnlockProfile() { - JNIEnv *env = GetJNIEnv(); +bool GeckoAppShell::UnlockProfile() { + JNIEnv *env = AndroidBridge::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(); @@ -2163,22 +2282,23 @@ bool AndroidBridge::UnlockProfile() { 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 AndroidBridge::UnlockScreenOrientation() { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::UnlockScreenOrientation() { + JNIEnv *env = AndroidBridge::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(); @@ -2190,20 +2310,21 @@ void AndroidBridge::UnlockScreenOrientat if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::UnregisterSurfaceTextureFrameListener(jobject a0) { +void GeckoAppShell::UnregisterSurfaceTextureFrameListener(jobject a0) { JNIEnv *env = GetJNIForThread(); if (!env) { ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__); return; } if (env->PushLocalFrame(1) != 0) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); @@ -2216,21 +2337,22 @@ void AndroidBridge::UnregisterSurfaceTex if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::Vibrate1(int64_t a0) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::Vibrate1(int64_t a0) { + JNIEnv *env = AndroidBridge::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(); @@ -2242,21 +2364,22 @@ void AndroidBridge::Vibrate1(int64_t a0) if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } -void AndroidBridge::VibrateA(jlongArray a0, int32_t a1) { - JNIEnv *env = GetJNIEnv(); +void GeckoAppShell::VibrateA(jlongArray a0, int32_t a1) { + JNIEnv *env = AndroidBridge::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(); @@ -2268,20 +2391,219 @@ void AndroidBridge::VibrateA(jlongArray if (env->ExceptionCheck()) { ALOG_BRIDGE("Exceptional exit of: %s", __PRETTY_FUNCTION__); env->ExceptionDescribe(); env->ExceptionClear(); env->PopLocalFrame(NULL); return; } + env->PopLocalFrame(NULL); } - -jstring AndroidBridge::GetFrameNameJavaProfilingWrapper(int32_t a0, int32_t a1, int32_t a2) { +jclass JavaDomKeyLocation::mDomKeyLocationClass = 0; +jmethodID JavaDomKeyLocation::jvalueOf = 0; +jmethodID JavaDomKeyLocation::jvalues = 0; +jfieldID JavaDomKeyLocation::jDOM_KEY_LOCATION_JOYSTICK = 0; +jfieldID JavaDomKeyLocation::jDOM_KEY_LOCATION_LEFT = 0; +jfieldID JavaDomKeyLocation::jDOM_KEY_LOCATION_MOBILE = 0; +jfieldID JavaDomKeyLocation::jDOM_KEY_LOCATION_NUMPAD = 0; +jfieldID JavaDomKeyLocation::jDOM_KEY_LOCATION_RIGHT = 0; +jfieldID JavaDomKeyLocation::jDOM_KEY_LOCATION_STANDARD = 0; +jfieldID JavaDomKeyLocation::jvalue = 0; +void JavaDomKeyLocation::InitStubs(JNIEnv *jEnv) { + initInit(); + + mDomKeyLocationClass = getClassGlobalRef("org/mozilla/gecko/GeckoEvent$DomKeyLocation"); + jvalueOf = getStaticMethod("valueOf", "(Ljava/lang/String;)Lorg/mozilla/gecko/GeckoEvent$DomKeyLocation;"); + jvalues = getStaticMethod("values", "()[Lorg/mozilla/gecko/GeckoEvent$DomKeyLocation;"); + jDOM_KEY_LOCATION_JOYSTICK = getStaticField("DOM_KEY_LOCATION_JOYSTICK", "Lorg/mozilla/gecko/GeckoEvent$DomKeyLocation;"); + jDOM_KEY_LOCATION_LEFT = getStaticField("DOM_KEY_LOCATION_LEFT", "Lorg/mozilla/gecko/GeckoEvent$DomKeyLocation;"); + jDOM_KEY_LOCATION_MOBILE = getStaticField("DOM_KEY_LOCATION_MOBILE", "Lorg/mozilla/gecko/GeckoEvent$DomKeyLocation;"); + jDOM_KEY_LOCATION_NUMPAD = getStaticField("DOM_KEY_LOCATION_NUMPAD", "Lorg/mozilla/gecko/GeckoEvent$DomKeyLocation;"); + jDOM_KEY_LOCATION_RIGHT = getStaticField("DOM_KEY_LOCATION_RIGHT", "Lorg/mozilla/gecko/GeckoEvent$DomKeyLocation;"); + jDOM_KEY_LOCATION_STANDARD = getStaticField("DOM_KEY_LOCATION_STANDARD", "Lorg/mozilla/gecko/GeckoEvent$DomKeyLocation;"); + jvalue = getField("value", "I"); +} + +JavaDomKeyLocation* JavaDomKeyLocation::Wrap(jobject obj) { + JNIEnv *env = GetJNIForThread(); + + if (!env) { + ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__); + return NULL; + } + + JavaDomKeyLocation* ret = new JavaDomKeyLocation(obj, env); + env->DeleteLocalRef(obj); + return ret; +} + +jobject JavaDomKeyLocation::valueOf(const nsAString& a0) { + JNIEnv *env = AndroidBridge::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); + + jobject temp = env->CallStaticObjectMethod(mDomKeyLocationClass, jvalueOf, j0); + + 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; +} + +jobjectArray JavaDomKeyLocation::values() { + JNIEnv *env = AndroidBridge::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(); + env->ExceptionClear(); + return nullptr; + } + + jobject temp = env->CallStaticObjectMethod(mDomKeyLocationClass, jvalues); + + 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; +} + +jobject JavaDomKeyLocation::getDOM_KEY_LOCATION_JOYSTICK() { + JNIEnv *env = GetJNIForThread(); + if (!env) { + ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__); + return nullptr; + } + + return static_cast<jobject>(env->GetStaticObjectField(mDomKeyLocationClass, jDOM_KEY_LOCATION_JOYSTICK)); +} + +jobject JavaDomKeyLocation::getDOM_KEY_LOCATION_LEFT() { + JNIEnv *env = GetJNIForThread(); + if (!env) { + ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__); + return nullptr; + } + + return static_cast<jobject>(env->GetStaticObjectField(mDomKeyLocationClass, jDOM_KEY_LOCATION_LEFT)); +} + +jobject JavaDomKeyLocation::getDOM_KEY_LOCATION_MOBILE() { + JNIEnv *env = GetJNIForThread(); + if (!env) { + ALOG_BRIDGE("Aborted: No env - %s", __PRETTY_FUNCTION__); + return nullptr; + } + + return static_cast<jobject>(env->GetStaticObjectField(mDomKeyLocationClass, jDOM_KEY_LOCATION_MOBILE)); +} + +jobject JavaDomKeyLocation::getDOM_KEY_LOCATION_NUMPAD() { + JNIEnv *env = GetJNIForThread(); + if (!env) { + ALOG_BRIDGE("Aborted