2010-06-03 13:56:36 -07:00
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
2012-05-21 04:12:37 -07:00
* 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/. */
2010-06-03 13:56:36 -07:00
2012-02-03 18:35:58 -08:00
# include "mozilla/Util.h"
# include "mozilla/layers/CompositorChild.h"
# include "mozilla/layers/CompositorParent.h"
2010-06-03 13:56:36 -07:00
# include <android/log.h>
2011-06-16 02:03:00 -07:00
# include <dlfcn.h>
2010-06-03 13:56:36 -07:00
2011-11-02 08:35:11 -07:00
# include "mozilla/Hal.h"
2010-08-17 01:07:45 -07:00
# include "nsXULAppAPI.h"
2010-06-03 13:56:36 -07:00
# include <prthread.h>
2010-06-29 19:22:08 -07:00
# include "nsXPCOMStrings.h"
2010-06-03 13:56:36 -07:00
# include "AndroidBridge.h"
2013-02-09 15:50:28 -08:00
# include "AndroidJNIWrapper.h"
2013-09-09 05:57:36 -07:00
# include "AndroidBridgeUtilities.h"
2010-06-14 19:17:37 -07:00
# include "nsAppShell.h"
2010-09-30 08:37:36 -07:00
# include "nsOSHelperAppService.h"
2011-04-11 13:41:03 -07:00
# include "nsWindow.h"
2011-06-07 00:38:00 -07:00
# include "mozilla/Preferences.h"
2011-08-04 00:32:57 -07:00
# include "nsThreadUtils.h"
2012-01-29 12:39:30 -08:00
# include "nsIThreadManager.h"
2013-03-01 00:38:47 -08:00
# include "mozilla/dom/mobilemessage/PSms.h"
2012-02-03 22:48:26 -08:00
# include "gfxImageSurface.h"
# include "gfxContext.h"
2013-07-24 06:18:05 -07:00
# include "gfxUtils.h"
2012-02-03 22:48:26 -08:00
# include "nsPresContext.h"
# include "nsIDocShell.h"
# include "nsPIDOMWindow.h"
2012-03-20 06:09:45 -07:00
# include "mozilla/dom/ScreenOrientation.h"
2012-06-01 20:50:57 -07:00
# include "nsIDOMWindowUtils.h"
# include "nsIDOMClientRect.h"
2012-07-20 12:20:51 -07:00
# include "StrongPointer.h"
2012-11-06 13:32:07 -08:00
# include "mozilla/ClearOnShutdown.h"
2013-04-26 10:26:46 -07:00
# include "nsPrintfCString.h"
2010-06-03 13:56:36 -07:00
2011-02-28 20:25:11 -08:00
# ifdef DEBUG
# define ALOG_BRIDGE(args...) ALOG(args)
# else
2013-01-25 11:00:00 -08:00
# define ALOG_BRIDGE(args...) ((void)0)
2011-02-28 20:25:11 -08:00
# endif
2010-06-03 13:56:36 -07:00
using namespace mozilla ;
2013-07-18 19:24:15 -07:00
NS_IMPL_ISUPPORTS0 ( nsFilePickerCallback )
2012-04-04 22:50:06 -07:00
2013-08-12 07:58:36 -07:00
StaticRefPtr < AndroidBridge > AndroidBridge : : sBridge ;
2012-08-22 08:56:38 -07:00
static unsigned sJavaEnvThreadIndex = 0 ;
2013-09-24 23:06:21 -07:00
static jobject sGlobalContext = nullptr ;
2012-07-17 07:25:48 -07:00
static void JavaThreadDetachFunc ( void * arg ) ;
2010-06-03 13:56:36 -07:00
2012-07-20 12:20:51 -07:00
// This is a dummy class that can be used in the template for android::sp
class AndroidRefable {
void incStrong ( void * thing ) { }
void decStrong ( void * thing ) { }
} ;
// This isn't in AndroidBridge.h because including StrongPointer.h there is gross
2012-07-30 07:20:58 -07:00
static android : : sp < AndroidRefable > ( * android_SurfaceTexture_getNativeWindow ) ( JNIEnv * env , jobject surfaceTexture ) = nullptr ;
2012-07-20 12:20:51 -07:00
2013-09-09 05:57:36 -07:00
jclass AndroidBridge : : GetClassGlobalRef ( JNIEnv * env , const char * className )
{
jobject classLocalRef = env - > FindClass ( className ) ;
if ( ! classLocalRef ) {
ALOG ( " >>> FATAL JNI ERROR! FindClass(className= \" %s \" ) failed. Did "
" ProGuard optimize away a non-public class? " , className ) ;
env - > ExceptionDescribe ( ) ;
MOZ_CRASH ( ) ;
}
jobject classGlobalRef = env - > NewGlobalRef ( classLocalRef ) ;
if ( ! classGlobalRef ) {
env - > ExceptionDescribe ( ) ;
MOZ_CRASH ( ) ;
}
// Local ref no longer necessary because we have a global ref.
env - > DeleteLocalRef ( classLocalRef ) ;
classLocalRef = NULL ;
return static_cast < jclass > ( classGlobalRef ) ;
}
jmethodID AndroidBridge : : GetMethodID ( JNIEnv * env , jclass jClass ,
const char * methodName , const char * methodType )
{
jmethodID methodID = env - > GetMethodID ( jClass , methodName , methodType ) ;
if ( ! methodID ) {
ALOG ( " >>> FATAL JNI ERROR! GetMethodID(methodName= \" %s \" , "
" methodType= \" %s \" ) failed. Did ProGuard optimize away a non- "
" public method? " , methodName , methodType ) ;
env - > ExceptionDescribe ( ) ;
MOZ_CRASH ( ) ;
}
return methodID ;
}
jmethodID AndroidBridge : : GetStaticMethodID ( JNIEnv * env , jclass jClass ,
const char * methodName , const char * methodType )
{
jmethodID methodID = env - > GetStaticMethodID ( jClass , methodName , methodType ) ;
if ( ! methodID ) {
ALOG ( " >>> FATAL JNI ERROR! GetStaticMethodID(methodName= \" %s \" , "
" methodType= \" %s \" ) failed. Did ProGuard optimize away a non- "
" public method? " , methodName , methodType ) ;
env - > ExceptionDescribe ( ) ;
MOZ_CRASH ( ) ;
}
return methodID ;
}
jfieldID AndroidBridge : : GetFieldID ( JNIEnv * env , jclass jClass ,
const char * fieldName , const char * fieldType )
{
jfieldID fieldID = env - > GetFieldID ( jClass , fieldName , fieldType ) ;
if ( ! fieldID ) {
ALOG ( " >>> FATAL JNI ERROR! GetFieldID(fieldName= \" %s \" , "
" fieldType= \" %s \" ) failed. Did ProGuard optimize away a non- "
" public field? " , fieldName , fieldType ) ;
env - > ExceptionDescribe ( ) ;
MOZ_CRASH ( ) ;
}
return fieldID ;
}
jfieldID AndroidBridge : : GetStaticFieldID ( JNIEnv * env , jclass jClass ,
const char * fieldName , const char * fieldType )
{
jfieldID fieldID = env - > GetStaticFieldID ( jClass , fieldName , fieldType ) ;
if ( ! fieldID ) {
ALOG ( " >>> FATAL JNI ERROR! GetStaticFieldID(fieldName= \" %s \" , "
" fieldType= \" %s \" ) failed. Did ProGuard optimize away a non- "
" public field? " , fieldName , fieldType ) ;
env - > ExceptionDescribe ( ) ;
MOZ_CRASH ( ) ;
}
return fieldID ;
}
2012-07-31 14:34:06 -07:00
void
2013-09-09 05:57:36 -07:00
AndroidBridge : : ConstructBridge ( JNIEnv * jEnv )
2010-06-03 13:56:36 -07:00
{
/* NSS hack -- bionic doesn't handle recursive unloads correctly,
* because library finalizer functions are called with the dynamic
* linker lock still held . This results in a deadlock when trying
* to call dlclose ( ) while we ' re already inside dlclose ( ) .
* Conveniently , NSS has an env var that can prevent it from unloading .
*/
2012-07-02 12:32:34 -07:00
putenv ( " NSS_DISABLE_UNLOAD=1 " ) ;
2010-06-03 13:56:36 -07:00
2012-07-17 07:25:48 -07:00
PR_NewThreadPrivateIndex ( & sJavaEnvThreadIndex , JavaThreadDetachFunc ) ;
2012-07-31 14:34:06 -07:00
AndroidBridge * bridge = new AndroidBridge ( ) ;
2013-09-09 05:57:36 -07:00
if ( ! bridge - > Init ( jEnv ) ) {
2012-07-31 14:34:06 -07:00
delete bridge ;
2010-06-03 13:56:36 -07:00
}
2012-07-31 14:34:06 -07:00
sBridge = bridge ;
2010-06-03 13:56:36 -07:00
}
2011-09-28 23:19:26 -07:00
bool
2013-09-09 05:57:36 -07:00
AndroidBridge : : Init ( JNIEnv * jEnv )
2010-06-03 13:56:36 -07:00
{
2011-12-05 22:56:04 -08:00
ALOG_BRIDGE ( " AndroidBridge::Init " ) ;
2010-06-03 13:56:36 -07:00
jEnv - > GetJavaVM ( & mJavaVM ) ;
2012-05-04 08:08:47 -07:00
AutoLocalJNIFrame jniFrame ( jEnv ) ;
2012-04-27 13:04:47 -07:00
2012-07-30 07:20:58 -07:00
mJNIEnv = nullptr ;
2013-09-09 05:57:37 -07:00
mThread = - 1 ;
2013-02-28 10:28:24 -08:00
mGLControllerObj = nullptr ;
2011-09-21 09:46:00 -07:00
mOpenedGraphicsLibraries = false ;
2011-06-16 02:03:00 -07:00
mHasNativeBitmapAccess = false ;
2011-09-21 09:46:00 -07:00
mHasNativeWindowAccess = false ;
2012-04-27 13:04:47 -07:00
mHasNativeWindowFallback = false ;
2010-06-03 13:56:36 -07:00
2013-09-09 05:57:36 -07:00
initInit ( ) ;
2013-09-09 05:57:37 -07:00
InitStubs ( jEnv ) ;
2010-06-03 13:56:36 -07:00
2013-05-28 21:52:40 -07:00
# ifdef MOZ_WEBSMS_BACKEND
2013-09-09 05:57:36 -07:00
mAndroidSmsMessageClass = getClassGlobalRef ( " android/telephony/SmsMessage " ) ;
jCalculateLength = getStaticMethod ( " calculateLength " , " (Ljava/lang/CharSequence;Z)[I " ) ;
2013-05-28 21:52:40 -07:00
# endif
2013-01-03 22:26:27 -08:00
2013-09-09 05:57:36 -07:00
jStringClass = getClassGlobalRef ( " java/lang/String " ) ;
if ( ! GetStaticIntField ( " android/os/Build$VERSION " , " SDK_INT " , & mAPIVersion , jEnv ) ) {
2012-04-27 13:04:47 -07:00
ALOG_BRIDGE ( " Failed to find API version " ) ;
2013-09-09 05:57:36 -07:00
}
2012-04-27 13:04:47 -07:00
2013-09-09 05:57:36 -07:00
jSurfaceClass = getClassGlobalRef ( " android/view/Surface " ) ;
2013-02-26 06:28:57 -08:00
if ( mAPIVersion < = 8 /* Froyo */ ) {
2013-09-09 05:57:36 -07:00
jSurfacePointerField = getField ( " mSurface " , " I " ) ;
2013-02-26 06:28:57 -08:00
} else {
2013-09-09 05:57:36 -07:00
jSurfacePointerField = getField ( " mNativeSurface " , " I " ) ;
2012-04-27 13:04:47 -07:00
2013-02-26 06:28:57 -08:00
// Apparently mNativeSurface doesn't exist in Key Lime Pie, so just clear the
// exception if we have one and move on.
if ( jEnv - > ExceptionCheck ( ) ) {
jEnv - > ExceptionClear ( ) ;
}
}
2013-09-09 05:57:36 -07:00
jclass eglClass = getClassGlobalRef ( " com/google/android/gles_jni/EGLSurfaceImpl " ) ;
2013-02-28 10:28:24 -08:00
if ( eglClass ) {
2013-09-09 05:57:36 -07:00
jEGLSurfacePointerField = getField ( " mEGLSurface " , " I " ) ;
2013-02-28 10:28:24 -08:00
} else {
jEGLSurfacePointerField = 0 ;
}
2012-03-08 07:22:42 -08:00
2010-06-03 13:56:36 -07:00
InitAndroidJavaWrappers ( jEnv ) ;
// jEnv should NOT be cached here by anything -- the jEnv here
// is not valid for the real gecko main thread, which is set
// at SetMainThread time.
2011-10-17 07:59:28 -07:00
return true ;
2010-06-03 13:56:36 -07:00
}
2011-09-28 23:19:26 -07:00
bool
2013-09-09 05:57:37 -07:00
AndroidBridge : : SetMainThread ( pthread_t thr )
2010-06-03 13:56:36 -07:00
{
2011-02-28 20:25:11 -08:00
ALOG_BRIDGE ( " AndroidBridge::SetMainThread " ) ;
2010-06-03 13:56:36 -07:00
if ( thr ) {
mThread = thr ;
2012-01-29 12:39:30 -08:00
mJavaVM - > GetEnv ( ( void * * ) & mJNIEnv , JNI_VERSION_1_2 ) ;
return ( bool ) mJNIEnv ;
2010-06-03 13:56:36 -07:00
}
2012-07-30 07:20:58 -07:00
mJNIEnv = nullptr ;
2013-09-09 05:57:37 -07:00
mThread = - 1 ;
2011-10-17 07:59:28 -07:00
return true ;
2010-06-03 13:56:36 -07:00
}
2013-09-09 05:57:37 -07:00
// Raw JNIEnv variants.
jstring AndroidBridge : : NewJavaString ( JNIEnv * env , const PRUnichar * string , uint32_t len ) {
jstring ret = env - > NewString ( string , len ) ;
if ( env - > ExceptionCheck ( ) ) {
ALOG_BRIDGE ( " Exceptional exit of: %s " , __PRETTY_FUNCTION__ ) ;
env - > ExceptionDescribe ( ) ;
env - > ExceptionClear ( ) ;
return NULL ;
}
2012-09-04 21:23:02 -07:00
return ret ;
}
2013-09-09 05:57:37 -07:00
jstring AndroidBridge : : NewJavaString ( JNIEnv * env , const nsAString & string ) {
return NewJavaString ( env , string . BeginReading ( ) , string . Length ( ) ) ;
2011-03-02 09:23:02 -08:00
}
2013-09-09 05:57:37 -07:00
jstring AndroidBridge : : NewJavaString ( JNIEnv * env , const char * string ) {
return NewJavaString ( env , NS_ConvertUTF8toUTF16 ( string ) ) ;
2010-06-04 14:14:43 -07:00
}
2013-09-09 05:57:37 -07:00
jstring AndroidBridge : : NewJavaString ( JNIEnv * env , const nsACString & string ) {
return NewJavaString ( env , NS_ConvertUTF8toUTF16 ( string ) ) ;
2012-03-21 10:52:35 -07:00
}
2013-09-09 05:57:37 -07:00
// AutoLocalJNIFrame variants..
jstring AndroidBridge : : NewJavaString ( AutoLocalJNIFrame * frame , const PRUnichar * string , uint32_t len ) {
return NewJavaString ( frame - > GetEnv ( ) , string , len ) ;
2012-02-05 11:51:05 -08:00
}
2013-09-09 05:57:37 -07:00
jstring AndroidBridge : : NewJavaString ( AutoLocalJNIFrame * frame , const nsAString & string ) {
return NewJavaString ( frame , string . BeginReading ( ) , string . Length ( ) ) ;
2012-02-05 11:51:05 -08:00
}
2013-09-09 05:57:37 -07:00
jstring AndroidBridge : : NewJavaString ( AutoLocalJNIFrame * frame , const char * string ) {
return NewJavaString ( frame , NS_ConvertUTF8toUTF16 ( string ) ) ;
2010-06-03 13:56:36 -07:00
}
2013-09-09 05:57:37 -07:00
jstring AndroidBridge : : NewJavaString ( AutoLocalJNIFrame * frame , const nsACString & string ) {
return NewJavaString ( frame , NS_ConvertUTF8toUTF16 ( string ) ) ;
2010-06-03 13:56:36 -07:00
}
2012-07-02 12:32:34 -07:00
static void
2010-09-30 08:37:36 -07:00
getHandlersFromStringArray ( JNIEnv * aJNIEnv , jobjectArray jArr , jsize aLen ,
nsIMutableArray * aHandlersArray ,
nsIHandlerApp * * aDefaultApp ,
const nsAString & aAction = EmptyString ( ) ,
const nsACString & aMimeType = EmptyCString ( ) )
{
nsString empty = EmptyString ( ) ;
for ( jsize i = 0 ; i < aLen ; i + = 4 ) {
2012-07-02 12:32:34 -07:00
nsJNIString name (
2012-04-16 15:31:05 -07:00
static_cast < jstring > ( aJNIEnv - > GetObjectArrayElement ( jArr , i ) ) , aJNIEnv ) ;
2010-09-30 08:37:36 -07:00
nsJNIString isDefault (
2012-04-16 15:31:05 -07:00
static_cast < jstring > ( aJNIEnv - > GetObjectArrayElement ( jArr , i + 1 ) ) , aJNIEnv ) ;
2012-07-02 12:32:34 -07:00
nsJNIString packageName (
2012-04-16 15:31:05 -07:00
static_cast < jstring > ( aJNIEnv - > GetObjectArrayElement ( jArr , i + 2 ) ) , aJNIEnv ) ;
2012-07-02 12:32:34 -07:00
nsJNIString className (
2012-04-16 15:31:05 -07:00
static_cast < jstring > ( aJNIEnv - > GetObjectArrayElement ( jArr , i + 3 ) ) , aJNIEnv ) ;
2010-09-30 08:37:36 -07:00
nsIHandlerApp * app = nsOSHelperAppService : :
CreateAndroidHandlerApp ( name , className , packageName ,
className , aMimeType , aAction ) ;
2012-07-02 12:32:34 -07:00
2011-10-17 07:59:28 -07:00
aHandlersArray - > AppendElement ( app , false ) ;
2010-09-30 08:37:36 -07:00
if ( aDefaultApp & & isDefault . Length ( ) > 0 )
* aDefaultApp = app ;
}
}
2011-09-28 23:19:26 -07:00
bool
2013-09-09 05:57:36 -07:00
AndroidBridge : : GetHandlersForMimeType ( const nsAString & aMimeType ,
2010-09-30 08:37:36 -07:00
nsIMutableArray * aHandlersArray ,
nsIHandlerApp * * aDefaultApp ,
const nsAString & aAction )
2010-06-14 12:04:16 -07:00
{
2011-02-28 20:25:11 -08:00
ALOG_BRIDGE ( " AndroidBridge::GetHandlersForMimeType " ) ;
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return false ;
2013-09-09 05:57:37 -07:00
jobjectArray arr = GetHandlersForMimeTypeWrapper ( aMimeType , aAction ) ;
2010-06-15 16:39:43 -07:00
if ( ! arr )
2011-10-17 07:59:28 -07:00
return false ;
2010-06-29 19:22:08 -07:00
2012-01-29 12:39:30 -08:00
jsize len = env - > GetArrayLength ( arr ) ;
2010-06-29 19:22:08 -07:00
2010-09-30 08:37:36 -07:00
if ( ! aHandlersArray )
2010-06-29 19:22:08 -07:00
return len > 0 ;
2012-07-02 12:32:34 -07:00
getHandlersFromStringArray ( env , arr , len , aHandlersArray ,
2010-09-30 08:37:36 -07:00
aDefaultApp , aAction ,
2013-09-09 05:57:36 -07:00
NS_ConvertUTF16toUTF8 ( aMimeType ) ) ;
2013-09-09 05:57:37 -07:00
env - > DeleteLocalRef ( arr ) ;
2011-10-17 07:59:28 -07:00
return true ;
2010-06-29 19:22:08 -07:00
}
2011-09-28 23:19:26 -07:00
bool
2013-09-09 05:57:36 -07:00
AndroidBridge : : GetHandlersForURL ( const nsAString & aURL ,
2011-09-30 00:00:48 -07:00
nsIMutableArray * aHandlersArray ,
nsIHandlerApp * * aDefaultApp ,
const nsAString & aAction )
2010-06-29 19:22:08 -07:00
{
2011-02-28 20:25:11 -08:00
ALOG_BRIDGE ( " AndroidBridge::GetHandlersForURL " ) ;
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return false ;
2013-09-09 05:57:37 -07:00
jobjectArray arr = GetHandlersForURLWrapper ( aURL , aAction ) ;
2010-06-29 19:22:08 -07:00
if ( ! arr )
2011-10-17 07:59:28 -07:00
return false ;
2010-06-29 19:22:08 -07:00
2012-01-29 12:39:30 -08:00
jsize len = env - > GetArrayLength ( arr ) ;
2010-06-29 19:22:08 -07:00
2010-09-30 08:37:36 -07:00
if ( ! aHandlersArray )
2010-06-29 19:22:08 -07:00
return len > 0 ;
2012-07-02 12:32:34 -07:00
getHandlersFromStringArray ( env , arr , len , aHandlersArray ,
2010-09-30 08:37:36 -07:00
aDefaultApp , aAction ) ;
2012-01-29 12:39:30 -08:00
2013-09-09 05:57:37 -07:00
env - > DeleteLocalRef ( arr ) ;
return true ;
2010-06-14 12:04:16 -07:00
}
void
2011-02-28 20:25:11 -08:00
AndroidBridge : : GetMimeTypeFromExtensions ( const nsACString & aFileExt , nsCString & aMimeType )
{
ALOG_BRIDGE ( " AndroidBridge::GetMimeTypeFromExtensions " ) ;
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return ;
2013-09-09 05:57:37 -07:00
jstring jstrType = GetMimeTypeFromExtensionsWrapper ( NS_ConvertUTF8toUTF16 ( aFileExt ) ) ;
if ( ! jstrType ) {
2012-05-04 08:08:47 -07:00
return ;
2013-09-09 05:57:37 -07:00
}
2012-04-16 15:31:05 -07:00
nsJNIString jniStr ( jstrType , env ) ;
2012-12-13 14:03:44 -08:00
CopyUTF16toUTF8 ( jniStr . get ( ) , aMimeType ) ;
2013-09-09 05:57:37 -07:00
env - > DeleteLocalRef ( jstrType ) ;
2010-06-14 12:04:16 -07:00
}
2011-03-07 21:45:43 -08:00
void
2011-09-15 00:40:17 -07:00
AndroidBridge : : GetExtensionFromMimeType ( const nsACString & aMimeType , nsACString & aFileExt )
2011-03-07 21:45:43 -08:00
{
ALOG_BRIDGE ( " AndroidBridge::GetExtensionFromMimeType " ) ;
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return ;
2013-09-09 05:57:37 -07:00
jstring jstrExt = GetExtensionFromMimeTypeWrapper ( NS_ConvertUTF8toUTF16 ( aMimeType ) ) ;
if ( ! jstrExt ) {
2012-05-04 08:08:47 -07:00
return ;
2013-09-09 05:57:37 -07:00
}
2012-04-16 15:31:05 -07:00
nsJNIString jniStr ( jstrExt , env ) ;
2012-12-13 14:03:44 -08:00
CopyUTF16toUTF8 ( jniStr . get ( ) , aFileExt ) ;
2011-03-07 21:45:43 -08:00
2013-09-09 05:57:37 -07:00
env - > DeleteLocalRef ( jstrExt ) ;
2010-06-16 10:20:54 -07:00
}
2010-08-26 16:43:23 -07:00
bool
AndroidBridge : : GetClipboardText ( nsAString & aText )
{
2011-02-28 20:25:11 -08:00
ALOG_BRIDGE ( " AndroidBridge::GetClipboardText " ) ;
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return false ;
2013-09-09 05:57:37 -07:00
jstring result = GetClipboardTextWrapper ( ) ;
if ( ! result )
2011-10-17 07:59:28 -07:00
return false ;
2012-05-04 08:08:47 -07:00
2013-09-09 05:57:37 -07:00
nsJNIString jniStr ( result , env ) ;
2010-08-26 16:43:23 -07:00
aText . Assign ( jniStr ) ;
2012-01-29 12:39:30 -08:00
2013-09-09 05:57:37 -07:00
env - > DeleteLocalRef ( result ) ;
return true ;
2010-08-26 16:43:23 -07:00
}
bool
AndroidBridge : : ClipboardHasText ( )
{
2011-02-28 20:25:11 -08:00
ALOG_BRIDGE ( " AndroidBridge::ClipboardHasText " ) ;
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return false ;
2012-05-04 08:08:47 -07:00
AutoLocalJNIFrame jniFrame ( env ) ;
2013-09-09 05:57:37 -07:00
jstring jStr = GetClipboardTextWrapper ( ) ;
bool ret = jStr ;
return ret ;
2010-08-26 16:43:23 -07:00
}
void
AndroidBridge : : EmptyClipboard ( )
{
2011-02-28 20:25:11 -08:00
ALOG_BRIDGE ( " AndroidBridge::EmptyClipboard " ) ;
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return ;
2012-05-04 08:08:47 -07:00
AutoLocalJNIFrame jniFrame ( env , 0 ) ;
2013-09-09 05:57:37 -07:00
env - > CallStaticVoidMethod ( mClipboardClass , jSetClipboardText , nullptr ) ;
2010-08-26 16:43:23 -07:00
}
2010-06-14 19:17:37 -07:00
void
AndroidBridge : : ShowAlertNotification ( const nsAString & aImageUrl ,
const nsAString & aAlertTitle ,
const nsAString & aAlertText ,
const nsAString & aAlertCookie ,
nsIObserver * aAlertListener ,
const nsAString & aAlertName )
{
2013-08-02 11:04:49 -07:00
if ( nsAppShell : : gAppShell & & aAlertListener ) {
// This will remove any observers already registered for this id
2013-09-05 12:32:04 -07:00
nsAppShell : : gAppShell - > PostEvent ( AndroidGeckoEvent : : MakeAddObserver ( aAlertName , aAlertListener ) ) ;
2013-08-02 11:04:49 -07:00
}
2010-06-14 19:17:37 -07:00
2013-09-09 05:57:37 -07:00
ShowAlertNotificationWrapper ( aImageUrl , aAlertTitle , aAlertText , aAlertCookie , aAlertName ) ;
2010-06-14 19:17:37 -07:00
}
2010-10-07 10:28:27 -07:00
int
AndroidBridge : : GetDPI ( )
{
2012-09-28 12:05:50 -07:00
static int sDPI = 0 ;
if ( sDPI )
return sDPI ;
const int DEFAULT_DPI = 160 ;
2012-01-29 12:39:30 -08:00
2013-09-09 05:57:37 -07:00
sDPI = GetDpiWrapper ( ) ;
if ( ! sDPI ) {
2012-05-04 08:08:47 -07:00
return DEFAULT_DPI ;
2012-09-28 12:05:50 -07:00
}
2012-05-04 08:08:47 -07:00
2012-09-28 12:05:50 -07:00
return sDPI ;
2010-10-07 10:28:27 -07:00
}
2013-07-04 06:53:25 -07:00
int
AndroidBridge : : GetScreenDepth ( )
{
2013-09-09 05:57:37 -07:00
ALOG_BRIDGE ( " %s " , __PRETTY_FUNCTION__ ) ;
2013-07-04 06:53:25 -07:00
static int sDepth = 0 ;
if ( sDepth )
return sDepth ;
const int DEFAULT_DEPTH = 16 ;
2013-09-09 05:57:37 -07:00
sDepth = GetScreenDepthWrapper ( ) ;
if ( ! sDepth )
2013-07-04 06:53:25 -07:00
return DEFAULT_DEPTH ;
return sDepth ;
}
2010-09-30 08:37:36 -07:00
void
2012-03-18 09:15:56 -07:00
AndroidBridge : : ShowFilePickerForExtensions ( nsAString & aFilePath , const nsAString & aExtensions )
2012-03-16 14:44:00 -07:00
{
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return ;
2013-09-09 05:57:37 -07:00
jstring jstr = ShowFilePickerForExtensionsWrapper ( aExtensions ) ;
if ( jstr = = nullptr ) {
2012-05-04 08:08:47 -07:00
return ;
2013-09-09 05:57:37 -07:00
}
2012-05-04 08:08:47 -07:00
2012-04-16 15:31:05 -07:00
aFilePath . Assign ( nsJNIString ( jstr , env ) ) ;
2013-09-09 05:57:37 -07:00
env - > DeleteLocalRef ( jstr ) ;
2012-03-18 09:15:56 -07:00
}
void
AndroidBridge : : ShowFilePickerForMimeType ( nsAString & aFilePath , const nsAString & aMimeType )
{
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return ;
2013-09-09 05:57:37 -07:00
jstring jstr = ShowFilePickerForMimeTypeWrapper ( aMimeType ) ;
if ( jstr = = nullptr ) {
2012-05-04 08:08:47 -07:00
return ;
2013-09-09 05:57:37 -07:00
}
2012-05-04 08:08:47 -07:00
2012-04-16 15:31:05 -07:00
aFilePath . Assign ( nsJNIString ( jstr , env ) ) ;
2013-09-09 05:57:37 -07:00
env - > DeleteLocalRef ( jstr ) ;
2010-09-30 08:37:36 -07:00
}
2010-11-08 18:11:13 -08:00
void
2012-04-04 22:50:06 -07:00
AndroidBridge : : ShowFilePickerAsync ( const nsAString & aMimeType , nsFilePickerCallback * callback )
{
callback - > AddRef ( ) ;
2013-09-09 05:57:37 -07:00
ShowFilePickerAsyncWrapper ( aMimeType , ( int64_t ) callback ) ;
2010-11-08 18:11:13 -08:00
}
2010-11-12 12:02:14 -08:00
void
AndroidBridge : : HideProgressDialogOnce ( )
{
static bool once = false ;
2012-05-04 08:08:47 -07:00
if ( once )
return ;
2012-01-29 12:39:30 -08:00
2013-09-09 05:57:37 -07:00
HideProgressDialog ( ) ;
2012-05-04 08:08:47 -07:00
once = true ;
2010-11-12 12:02:14 -08:00
}
2010-11-22 08:38:02 -08:00
void
2013-09-09 05:57:37 -07:00
AndroidBridge : : Vibrate ( const nsTArray < uint32_t > & aPattern )
2010-11-22 08:38:02 -08:00
{
2013-09-09 05:57:37 -07:00
ALOG_BRIDGE ( " %s " , __PRETTY_FUNCTION__ ) ;
2012-01-29 12:39:30 -08:00
2013-09-09 05:57:37 -07:00
uint32_t len = aPattern . Length ( ) ;
if ( ! len ) {
ALOG_BRIDGE ( " invalid 0-length array " ) ;
2012-01-29 12:39:30 -08:00
return ;
2013-09-09 05:57:37 -07:00
}
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return ;
2012-04-28 09:55:59 -07:00
AutoLocalJNIFrame jniFrame ( env ) ;
2011-09-30 00:00:48 -07:00
// 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 ;
}
2013-09-09 05:57:37 -07:00
Vibrate1 ( d ) ;
2012-05-04 08:08:45 -07:00
return ;
2011-09-30 00:00:48 -07:00
}
// First element of the array vibrate() expects is how long to wait
// *before* vibrating. For us, this is always 0.
2012-01-29 12:39:30 -08:00
jlongArray array = env - > NewLongArray ( len + 1 ) ;
2011-09-30 00:00:48 -07:00
if ( ! array ) {
ALOG_BRIDGE ( " failed to allocate array " ) ;
return ;
}
2012-07-30 07:20:58 -07:00
jlong * elts = env - > GetLongArrayElements ( array , nullptr ) ;
2011-09-30 00:00:48 -07:00
elts [ 0 ] = 0 ;
2012-08-22 08:56:38 -07:00
for ( uint32_t i = 0 ; i < aPattern . Length ( ) ; + + i ) {
2011-09-30 00:00:48 -07:00
jlong d = aPattern [ i ] ;
if ( d < 0 ) {
ALOG_BRIDGE ( " invalid vibration duration < 0 " ) ;
2012-01-29 12:39:30 -08:00
env - > ReleaseLongArrayElements ( array , elts , JNI_ABORT ) ;
2011-09-30 00:00:48 -07:00
return ;
}
elts [ i + 1 ] = d ;
}
2012-01-29 12:39:30 -08:00
env - > ReleaseLongArrayElements ( array , elts , 0 ) ;
2011-09-30 00:00:48 -07:00
2013-09-09 05:57:37 -07:00
VibrateA ( array , - 1 /*don't repeat*/ ) ;
2011-02-27 07:50:56 -08:00
}
2011-03-30 11:04:41 -07:00
void
AndroidBridge : : GetSystemColors ( AndroidSystemColors * aColors )
{
2012-07-30 07:20:58 -07:00
NS_ASSERTION ( aColors ! = nullptr , " AndroidBridge::GetSystemColors: aColors is null! " ) ;
2011-03-30 11:04:41 -07:00
if ( ! aColors )
return ;
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return ;
2012-07-02 12:32:34 -07:00
AutoLocalJNIFrame jniFrame ( env ) ;
2011-03-30 11:04:41 -07:00
2013-09-09 05:57:37 -07:00
jintArray arr = GetSystemColoursWrapper ( ) ;
2011-03-30 11:04:41 -07:00
if ( ! arr )
return ;
2012-08-22 08:56:38 -07:00
uint32_t len = static_cast < uint32_t > ( env - > GetArrayLength ( arr ) ) ;
2012-01-29 12:39:30 -08:00
jint * elements = env - > GetIntArrayElements ( arr , 0 ) ;
2011-03-30 11:04:41 -07:00
2012-08-22 08:56:38 -07:00
uint32_t colorsCount = sizeof ( AndroidSystemColors ) / sizeof ( nscolor ) ;
2011-03-30 11:04:41 -07:00
if ( len < colorsCount )
colorsCount = len ;
// Convert Android colors to nscolor by switching R and B in the ARGB 32 bit value
nscolor * colors = ( nscolor * ) aColors ;
2012-08-22 08:56:38 -07:00
for ( uint32_t i = 0 ; i < colorsCount ; i + + ) {
uint32_t androidColor = static_cast < uint32_t > ( elements [ i ] ) ;
uint8_t r = ( androidColor & 0x00ff0000 ) > > 16 ;
uint8_t b = ( androidColor & 0x000000ff ) ;
2012-07-12 09:52:52 -07:00
colors [ i ] = ( androidColor & 0xff00ff00 ) | ( b < < 16 ) | r ;
2011-03-30 11:04:41 -07:00
}
2012-01-29 12:39:30 -08:00
env - > ReleaseIntArrayElements ( arr , elements , 0 ) ;
2011-03-30 11:04:41 -07:00
}
2011-06-13 14:02:13 -07:00
void
2012-08-22 08:56:38 -07:00
AndroidBridge : : GetIconForExtension ( const nsACString & aFileExt , uint32_t aIconSize , uint8_t * const aBuf )
2011-06-13 14:02:13 -07:00
{
ALOG_BRIDGE ( " AndroidBridge::GetIconForExtension " ) ;
2012-07-30 07:20:58 -07:00
NS_ASSERTION ( aBuf ! = nullptr , " AndroidBridge::GetIconForExtension: aBuf is null! " ) ;
2011-06-13 14:02:13 -07:00
if ( ! aBuf )
return ;
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return ;
2012-07-02 12:32:34 -07:00
AutoLocalJNIFrame jniFrame ( env ) ;
2011-06-13 14:02:13 -07:00
2013-09-09 05:57:37 -07:00
jbyteArray arr = GetIconForExtensionWrapper ( NS_ConvertUTF8toUTF16 ( aFileExt ) , aIconSize ) ;
2012-05-04 08:08:47 -07:00
2012-07-30 07:20:58 -07:00
NS_ASSERTION ( arr ! = nullptr , " AndroidBridge::GetIconForExtension: Returned pixels array is null! " ) ;
2011-06-13 14:02:13 -07:00
if ( ! arr )
return ;
2012-08-22 08:56:38 -07:00
uint32_t len = static_cast < uint32_t > ( env - > GetArrayLength ( arr ) ) ;
2012-01-29 12:39:30 -08:00
jbyte * elements = env - > GetByteArrayElements ( arr , 0 ) ;
2011-06-13 14:02:13 -07:00
2012-08-22 08:56:38 -07:00
uint32_t bufSize = aIconSize * aIconSize * 4 ;
2011-06-13 14:02:13 -07:00
NS_ASSERTION ( len = = bufSize , " AndroidBridge::GetIconForExtension: Pixels array is incomplete! " ) ;
if ( len = = bufSize )
memcpy ( aBuf , elements , bufSize ) ;
2012-01-29 12:39:30 -08:00
env - > ReleaseByteArrayElements ( arr , elements , 0 ) ;
2011-06-13 14:02:13 -07:00
}
2010-06-03 13:56:36 -07:00
void
2012-07-13 07:19:46 -07:00
AndroidBridge : : SetLayerClient ( JNIEnv * env , jobject jobj )
2012-02-17 06:16:14 -08:00
{
2012-07-13 07:19:46 -07:00
// if resetting is true, that means Android destroyed our GeckoApp activity
// and we had to recreate it, but all the Gecko-side things were not destroyed.
// We therefore need to link up the new java objects to Gecko, and that's what
// we do here.
bool resetting = ( mLayerClient ! = NULL ) ;
if ( resetting ) {
// clear out the old layer client
env - > DeleteGlobalRef ( mLayerClient - > wrappedObject ( ) ) ;
delete mLayerClient ;
mLayerClient = NULL ;
}
2012-02-22 11:45:44 -08:00
AndroidGeckoLayerClient * client = new AndroidGeckoLayerClient ( ) ;
2012-07-13 07:19:46 -07:00
client - > Init ( env - > NewGlobalRef ( jobj ) ) ;
2012-02-17 06:16:14 -08:00
mLayerClient = client ;
2012-07-13 07:19:46 -07:00
if ( resetting ) {
2013-02-04 12:13:17 -08:00
// 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 ( ) ;
2012-07-13 07:19:46 -07:00
}
2010-06-03 13:56:36 -07:00
}
2012-02-06 13:53:09 -08:00
void
2013-02-28 10:28:23 -08:00
AndroidBridge : : RegisterCompositor ( JNIEnv * env )
2012-01-26 11:23:13 -08:00
{
ALOG_BRIDGE ( " AndroidBridge::RegisterCompositor " ) ;
2013-02-28 10:28:24 -08:00
if ( mGLControllerObj ) {
// we already have this set up, no need to do it again
return ;
}
if ( ! env ) {
2012-07-13 14:34:58 -07:00
env = GetJNIForThread ( ) ; // called on the compositor thread
2013-02-28 10:28:24 -08:00
}
if ( ! env ) {
2012-02-06 13:53:09 -08:00
return ;
2013-02-28 10:28:24 -08:00
}
2012-01-26 11:23:13 -08:00
2013-09-09 05:57:37 -07:00
jobject glController = RegisterCompositorWrapper ( ) ;
if ( ! glController ) {
2012-05-04 08:08:47 -07:00
return ;
2013-09-09 05:57:37 -07:00
}
2012-02-01 13:18:35 -08:00
2013-02-28 10:28:24 -08:00
mGLControllerObj = env - > NewGlobalRef ( glController ) ;
2013-09-09 05:57:37 -07:00
env - > DeleteLocalRef ( glController ) ;
2012-02-06 13:53:09 -08:00
}
EGLSurface
2013-02-28 10:28:23 -08:00
AndroidBridge : : ProvideEGLSurface ( )
2012-02-06 13:53:09 -08:00
{
2013-02-28 10:28:24 -08:00
if ( ! jEGLSurfacePointerField ) {
return NULL ;
}
MOZ_ASSERT ( mGLControllerObj , " AndroidBridge::ProvideEGLSurface called with a null GL controller ref " ) ;
JNIEnv * env = GetJNIForThread ( ) ; // called on the compositor thread
2013-09-09 05:57:37 -07:00
if ( ! env ) {
return NULL ;
}
jobject eglSurface = ProvideEGLSurfaceWrapper ( mGLControllerObj ) ;
if ( ! eglSurface )
2013-02-28 10:28:24 -08:00
return NULL ;
2013-09-09 05:57:37 -07:00
EGLSurface ret = reinterpret_cast < EGLSurface > ( env - > GetIntField ( eglSurface , jEGLSurfacePointerField ) ) ;
env - > DeleteLocalRef ( eglSurface ) ;
return ret ;
2012-01-26 11:23:13 -08:00
}
2011-02-28 08:32:05 -08:00
bool
2013-09-09 05:57:36 -07:00
AndroidBridge : : GetStaticIntField ( const char * className , const char * fieldName , int32_t * aInt , JNIEnv * jEnv /* = nullptr */ )
2011-02-28 08:32:05 -08:00
{
2011-02-28 20:25:11 -08:00
ALOG_BRIDGE ( " AndroidBridge::GetStaticIntField %s " , fieldName ) ;
2012-04-27 13:04:47 -07:00
2013-09-09 05:57:36 -07:00
if ( ! jEnv ) {
jEnv = GetJNIEnv ( ) ;
if ( ! jEnv )
2012-04-27 13:04:47 -07:00
return false ;
}
2012-01-29 12:39:30 -08:00
2013-09-09 05:57:36 -07:00
initInit ( ) ;
getClassGlobalRef ( className ) ;
jfieldID field = getStaticField ( fieldName , " I " ) ;
2011-02-28 08:32:05 -08:00
2013-09-09 05:57:36 -07:00
if ( ! field ) {
jEnv - > DeleteGlobalRef ( jClass ) ;
2011-02-28 08:32:05 -08:00
return false ;
2013-09-09 05:57:36 -07:00
}
2011-02-28 08:32:05 -08:00
2013-09-09 05:57:36 -07:00
* aInt = static_cast < int32_t > ( jEnv - > GetStaticIntField ( jClass , field ) ) ;
2011-02-28 08:32:05 -08:00
2013-09-09 05:57:36 -07:00
jEnv - > DeleteGlobalRef ( jClass ) ;
2011-02-28 08:32:05 -08:00
return true ;
}
2010-09-11 06:20:20 -07:00
bool
2013-09-09 05:57:36 -07:00
AndroidBridge : : GetStaticStringField ( const char * className , const char * fieldName , nsAString & result , JNIEnv * jEnv /* = nullptr */ )
2010-09-11 06:20:20 -07:00
{
2012-05-04 08:08:47 -07:00
ALOG_BRIDGE ( " AndroidBridge::GetStaticStringField %s " , fieldName ) ;
2011-02-28 20:25:11 -08:00
2013-09-09 05:57:36 -07:00
if ( ! jEnv ) {
jEnv = GetJNIEnv ( ) ;
if ( ! jEnv )
2012-04-27 13:04:47 -07:00
return false ;
}
2012-01-29 12:39:30 -08:00
2013-09-09 05:57:36 -07:00
initInit ( ) ;
getClassGlobalRef ( className ) ;
jfieldID field = getStaticField ( fieldName , " Ljava/lang/String; " ) ;
2010-09-11 06:20:20 -07:00
2013-09-09 05:57:36 -07:00
if ( ! field ) {
jEnv - > DeleteGlobalRef ( jClass ) ;
2010-09-11 06:20:20 -07:00
return false ;
2013-09-09 05:57:36 -07:00
}
2010-09-11 06:20:20 -07:00
2013-09-09 05:57:36 -07:00
jstring jstr = ( jstring ) jEnv - > GetStaticObjectField ( jClass , field ) ;
jEnv - > DeleteGlobalRef ( jClass ) ;
2010-09-11 06:20:20 -07:00
if ( ! jstr )
return false ;
2013-09-09 05:57:36 -07:00
result . Assign ( nsJNIString ( jstr , jEnv ) ) ;
2013-09-09 05:57:37 -07:00
jEnv - > DeleteLocalRef ( jstr ) ;
2010-09-11 06:20:20 -07:00
return true ;
}
2010-06-03 13:56:36 -07:00
// Available for places elsewhere in the code to link to.
2011-09-28 23:19:26 -07:00
bool
2013-09-09 05:57:37 -07:00
mozilla_AndroidBridge_SetMainThread ( pthread_t thr )
2010-06-03 13:56:36 -07:00
{
return AndroidBridge : : Bridge ( ) - > SetMainThread ( thr ) ;
}
2010-10-15 11:16:45 -07:00
jclass GetGeckoAppShellClass ( )
{
return mozilla : : AndroidBridge : : GetGeckoAppShellClass ( ) ;
}
2011-04-08 10:52:13 -07:00
2012-04-27 13:04:47 -07:00
void *
AndroidBridge : : GetNativeSurface ( JNIEnv * env , jobject surface ) {
2013-02-26 06:28:57 -08:00
if ( ! env | | ! mHasNativeWindowFallback | | ! jSurfacePointerField )
2012-07-30 07:20:58 -07:00
return nullptr ;
2012-04-27 13:04:47 -07:00
return ( void * ) env - > GetIntField ( surface , jSurfacePointerField ) ;
}
2011-09-21 09:46:00 -07:00
void
AndroidBridge : : OpenGraphicsLibraries ( )
2011-06-16 02:03:00 -07:00
{
2011-09-21 09:46:00 -07:00
if ( ! mOpenedGraphicsLibraries ) {
2011-06-16 02:03:00 -07:00
// Try to dlopen libjnigraphics.so for direct bitmap access on
// Android 2.2+ (API level 8)
2011-09-21 09:46:00 -07:00
mOpenedGraphicsLibraries = true ;
2011-09-28 11:43:02 -07:00
mHasNativeWindowAccess = false ;
2012-04-27 13:04:47 -07:00
mHasNativeWindowFallback = false ;
2011-09-28 11:43:02 -07:00
mHasNativeBitmapAccess = false ;
2011-06-16 02:03:00 -07:00
2012-01-12 22:23:02 -08:00
void * handle = dlopen ( " libjnigraphics.so " , RTLD_LAZY | RTLD_LOCAL ) ;
2011-09-21 09:46:00 -07:00
if ( handle ) {
AndroidBitmap_getInfo = ( int ( * ) ( JNIEnv * , jobject , void * ) ) dlsym ( handle , " AndroidBitmap_getInfo " ) ;
AndroidBitmap_lockPixels = ( int ( * ) ( JNIEnv * , jobject , void * * ) ) dlsym ( handle , " AndroidBitmap_lockPixels " ) ;
AndroidBitmap_unlockPixels = ( int ( * ) ( JNIEnv * , jobject ) ) dlsym ( handle , " AndroidBitmap_unlockPixels " ) ;
2011-06-16 02:03:00 -07:00
2011-09-28 11:43:02 -07:00
mHasNativeBitmapAccess = AndroidBitmap_getInfo & & AndroidBitmap_lockPixels & & AndroidBitmap_unlockPixels ;
ALOG_BRIDGE ( " Successfully opened libjnigraphics.so, have native bitmap access? %d " , mHasNativeBitmapAccess ) ;
2011-09-21 09:46:00 -07:00
}
2011-06-16 02:03:00 -07:00
2011-09-21 09:46:00 -07:00
// Try to dlopen libandroid.so for and native window access on
// Android 2.3+ (API level 9)
2012-01-12 22:23:02 -08:00
handle = dlopen ( " libandroid.so " , RTLD_LAZY | RTLD_LOCAL ) ;
2011-09-21 09:46:00 -07:00
if ( handle ) {
ANativeWindow_fromSurface = ( void * ( * ) ( JNIEnv * , jobject ) ) dlsym ( handle , " ANativeWindow_fromSurface " ) ;
ANativeWindow_release = ( void ( * ) ( void * ) ) dlsym ( handle , " ANativeWindow_release " ) ;
ANativeWindow_setBuffersGeometry = ( int ( * ) ( void * , int , int , int ) ) dlsym ( handle , " ANativeWindow_setBuffersGeometry " ) ;
ANativeWindow_lock = ( int ( * ) ( void * , void * , void * ) ) dlsym ( handle , " ANativeWindow_lock " ) ;
ANativeWindow_unlockAndPost = ( int ( * ) ( void * ) ) dlsym ( handle , " ANativeWindow_unlockAndPost " ) ;
2011-09-21 09:46:00 -07:00
2012-07-20 12:20:51 -07:00
// This is only available in Honeycomb and ICS. It was removed in Jelly Bean
ANativeWindow_fromSurfaceTexture = ( void * ( * ) ( JNIEnv * , jobject ) ) dlsym ( handle , " ANativeWindow_fromSurfaceTexture " ) ;
2011-09-28 11:43:02 -07:00
mHasNativeWindowAccess = ANativeWindow_fromSurface & & ANativeWindow_release & & ANativeWindow_lock & & ANativeWindow_unlockAndPost ;
ALOG_BRIDGE ( " Successfully opened libandroid.so, have native window access? %d " , mHasNativeWindowAccess ) ;
}
2012-04-27 13:04:47 -07:00
2012-07-20 12:20:51 -07:00
// We need one symbol from here on Jelly Bean
handle = dlopen ( " libandroid_runtime.so " , RTLD_LAZY | RTLD_LOCAL ) ;
if ( handle ) {
android_SurfaceTexture_getNativeWindow = ( android : : sp < AndroidRefable > ( * ) ( JNIEnv * , jobject ) ) dlsym ( handle , " _ZN7android38android_SurfaceTexture_getNativeWindowEP7_JNIEnvP8_jobject " ) ;
}
2012-04-27 13:04:47 -07:00
if ( mHasNativeWindowAccess )
return ;
// Look up Surface functions, used for native window (surface) fallback
handle = dlopen ( " libsurfaceflinger_client.so " , RTLD_LAZY ) ;
if ( handle ) {
Surface_lock = ( int ( * ) ( void * , void * , void * , bool ) ) dlsym ( handle , " _ZN7android7Surface4lockEPNS0_11SurfaceInfoEPNS_6RegionEb " ) ;
Surface_unlockAndPost = ( int ( * ) ( void * ) ) dlsym ( handle , " _ZN7android7Surface13unlockAndPostEv " ) ;
handle = dlopen ( " libui.so " , RTLD_LAZY ) ;
if ( handle ) {
Region_constructor = ( void ( * ) ( void * ) ) dlsym ( handle , " _ZN7android6RegionC1Ev " ) ;
Region_set = ( void ( * ) ( void * , void * ) ) dlsym ( handle , " _ZN7android6Region3setERKNS_4RectE " ) ;
mHasNativeWindowFallback = Surface_lock & & Surface_unlockAndPost & & Region_constructor & & Region_set ;
}
}
2011-09-24 08:51:46 -07:00
}
2011-09-21 09:46:00 -07:00
}
2011-08-04 00:32:57 -07:00
namespace mozilla {
class TracerRunnable : public nsRunnable {
public :
TracerRunnable ( ) {
mTracerLock = new Mutex ( " TracerRunnable " ) ;
mTracerCondVar = new CondVar ( * mTracerLock , " TracerRunnable " ) ;
mMainThread = do_GetMainThread ( ) ;
2012-07-02 12:32:34 -07:00
2011-08-04 00:32:57 -07:00
}
~ TracerRunnable ( ) {
delete mTracerCondVar ;
delete mTracerLock ;
2012-07-30 07:20:58 -07:00
mTracerLock = nullptr ;
mTracerCondVar = nullptr ;
2011-08-04 00:32:57 -07:00
}
virtual nsresult Run ( ) {
MutexAutoLock lock ( * mTracerLock ) ;
if ( ! AndroidBridge : : Bridge ( ) )
return NS_OK ;
2012-07-02 12:32:34 -07:00
2012-04-04 02:15:10 -07:00
mHasRun = true ;
2011-08-04 00:32:57 -07:00
mTracerCondVar - > Notify ( ) ;
return NS_OK ;
}
2012-07-02 12:32:34 -07:00
2011-08-04 00:32:57 -07:00
bool Fire ( ) {
if ( ! mTracerLock | | ! mTracerCondVar )
return false ;
MutexAutoLock lock ( * mTracerLock ) ;
2012-04-04 02:15:10 -07:00
mHasRun = false ;
2011-08-04 00:32:57 -07:00
mMainThread - > Dispatch ( this , NS_DISPATCH_NORMAL ) ;
while ( ! mHasRun )
mTracerCondVar - > Wait ( ) ;
return true ;
}
void Signal ( ) {
MutexAutoLock lock ( * mTracerLock ) ;
2012-04-04 02:15:10 -07:00
mHasRun = true ;
2011-08-04 00:32:57 -07:00
mTracerCondVar - > Notify ( ) ;
}
private :
Mutex * mTracerLock ;
CondVar * mTracerCondVar ;
2012-04-04 02:15:10 -07:00
bool mHasRun ;
2011-08-04 00:32:57 -07:00
nsCOMPtr < nsIThread > mMainThread ;
} ;
2013-08-12 07:58:36 -07:00
StaticRefPtr < TracerRunnable > sTracerRunnable ;
2011-08-04 00:32:57 -07:00
bool InitWidgetTracing ( ) {
if ( ! sTracerRunnable )
sTracerRunnable = new TracerRunnable ( ) ;
return true ;
}
void CleanUpWidgetTracing ( ) {
2012-07-30 07:20:58 -07:00
sTracerRunnable = nullptr ;
2011-08-04 00:32:57 -07:00
}
bool FireAndWaitForTracerEvent ( ) {
if ( sTracerRunnable )
return sTracerRunnable - > Fire ( ) ;
return false ;
}
2012-07-02 12:32:34 -07:00
void SignalTracerThread ( )
{
if ( sTracerRunnable )
return sTracerRunnable - > Signal ( ) ;
}
2011-08-04 00:32:57 -07:00
}
2011-09-21 09:46:00 -07:00
bool
AndroidBridge : : HasNativeBitmapAccess ( )
{
OpenGraphicsLibraries ( ) ;
2011-06-16 02:03:00 -07:00
return mHasNativeBitmapAccess ;
}
bool
AndroidBridge : : ValidateBitmap ( jobject bitmap , int width , int height )
{
// This structure is defined in Android API level 8's <android/bitmap.h>
// Because we can't depend on this, we get the function pointers via dlsym
// and define this struct ourselves.
struct BitmapInfo {
uint32_t width ;
uint32_t height ;
uint32_t stride ;
uint32_t format ;
uint32_t flags ;
} ;
int err ;
struct BitmapInfo info = { 0 , } ;
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return false ;
if ( ( err = AndroidBitmap_getInfo ( env , bitmap , & info ) ) ! = 0 ) {
2011-06-16 02:03:00 -07:00
ALOG_BRIDGE ( " AndroidBitmap_getInfo failed! (error %d) " , err ) ;
return false ;
}
2012-07-12 09:52:52 -07:00
if ( ( int ) info . width ! = width | | ( int ) info . height ! = height )
2011-06-16 02:03:00 -07:00
return false ;
return true ;
}
2011-09-26 17:25:41 -07:00
bool
2012-08-22 08:56:38 -07:00
AndroidBridge : : InitCamera ( const nsCString & contentType , uint32_t camera , uint32_t * width , uint32_t * height , uint32_t * fps )
2011-09-26 17:25:41 -07:00
{
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return false ;
2012-07-02 12:32:34 -07:00
AutoLocalJNIFrame jniFrame ( env ) ;
2013-09-09 05:57:37 -07:00
jintArray arr = InitCameraWrapper ( NS_ConvertUTF8toUTF16 ( contentType ) , ( int32_t ) camera , ( int32_t ) width , ( int32_t ) height ) ;
2011-09-26 17:25:41 -07:00
if ( ! arr )
return false ;
2012-01-29 12:39:30 -08:00
jint * elements = env - > GetIntArrayElements ( arr , 0 ) ;
2011-09-26 17:25:41 -07:00
* width = elements [ 1 ] ;
* height = elements [ 2 ] ;
* fps = elements [ 3 ] ;
bool res = elements [ 0 ] = = 1 ;
2012-01-29 12:39:30 -08:00
env - > ReleaseIntArrayElements ( arr , elements , 0 ) ;
2011-09-26 17:25:41 -07:00
return res ;
}
2011-11-02 08:35:11 -07:00
void
AndroidBridge : : GetCurrentBatteryInformation ( hal : : BatteryInformation * aBatteryInfo )
{
ALOG_BRIDGE ( " AndroidBridge::GetCurrentBatteryInformation " ) ;
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return ;
2012-07-02 12:32:34 -07:00
AutoLocalJNIFrame jniFrame ( env ) ;
2011-11-02 08:35:11 -07:00
// To prevent calling too many methods through JNI, the Java method returns
2011-11-09 00:56:37 -08:00
// an array of double even if we actually want a double and a boolean.
2013-09-09 05:57:37 -07:00
jdoubleArray arr = GetCurrentBatteryInformationWrapper ( ) ;
2012-01-29 12:39:30 -08:00
if ( ! arr | | env - > GetArrayLength ( arr ) ! = 3 ) {
2011-11-02 08:35:11 -07:00
return ;
}
2012-01-29 12:39:30 -08:00
jdouble * info = env - > GetDoubleArrayElements ( arr , 0 ) ;
2011-11-02 08:35:11 -07:00
aBatteryInfo - > level ( ) = info [ 0 ] ;
aBatteryInfo - > charging ( ) = info [ 1 ] = = 1.0f ;
2011-11-09 06:13:37 -08:00
aBatteryInfo - > remainingTime ( ) = info [ 2 ] ;
2011-11-02 08:35:11 -07:00
2012-01-29 12:39:30 -08:00
env - > ReleaseDoubleArrayElements ( arr , info , 0 ) ;
2011-11-02 08:35:11 -07:00
}
2011-11-14 19:12:14 -08:00
void
AndroidBridge : : HandleGeckoMessage ( const nsAString & aMessage , nsAString & aRet )
{
ALOG_BRIDGE ( " %s " , __PRETTY_FUNCTION__ ) ;
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
2011-11-14 19:12:14 -08:00
return ;
2012-05-04 08:08:47 -07:00
AutoLocalJNIFrame jniFrame ( env ) ;
2013-09-09 05:57:37 -07:00
jstring returnMessage = HandleGeckoMessageWrapper ( aMessage ) ;
if ( ! returnMessage )
2012-05-04 08:08:47 -07:00
return ;
2011-11-14 19:12:14 -08:00
2012-04-16 14:25:04 -07:00
nsJNIString jniStr ( returnMessage , env ) ;
2011-11-14 19:12:14 -08:00
aRet . Assign ( jniStr ) ;
ALOG_BRIDGE ( " leaving %s " , __PRETTY_FUNCTION__ ) ;
}
2013-01-03 22:26:27 -08:00
nsresult
AndroidBridge : : GetSegmentInfoForText ( const nsAString & aText ,
2013-08-09 06:25:53 -07:00
nsIMobileMessageCallback * aRequest )
2011-11-25 01:48:51 -08:00
{
2013-05-28 21:52:40 -07:00
# ifndef MOZ_WEBSMS_BACKEND
return NS_ERROR_FAILURE ;
# else
2013-01-03 22:26:27 -08:00
ALOG_BRIDGE ( " AndroidBridge::GetSegmentInfoForText " ) ;
2013-08-09 06:25:53 -07:00
dom : : mobilemessage : : SmsSegmentInfoData data ;
data . segments ( ) = 0 ;
data . charsPerSegment ( ) = 0 ;
data . charsAvailableInLastSegment ( ) = 0 ;
2011-11-25 01:48:51 -08:00
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
2013-01-03 22:26:27 -08:00
return NS_ERROR_FAILURE ;
2012-01-29 12:39:30 -08:00
2012-07-02 12:32:34 -07:00
AutoLocalJNIFrame jniFrame ( env ) ;
2012-12-13 14:03:44 -08:00
jstring jText = NewJavaString ( & jniFrame , aText ) ;
2013-01-03 22:26:27 -08:00
jobject obj = env - > CallStaticObjectMethod ( mAndroidSmsMessageClass ,
jCalculateLength , jText , JNI_FALSE ) ;
2012-05-04 08:08:47 -07:00
if ( jniFrame . CheckForException ( ) )
2013-01-03 22:26:27 -08:00
return NS_ERROR_FAILURE ;
2012-05-04 08:08:47 -07:00
2013-01-03 22:26:27 -08:00
jintArray arr = static_cast < jintArray > ( obj ) ;
if ( ! arr | | env - > GetArrayLength ( arr ) ! = 4 )
return NS_ERROR_FAILURE ;
jint * info = env - > GetIntArrayElements ( arr , JNI_FALSE ) ;
2013-08-09 06:25:53 -07:00
data . segments ( ) = info [ 0 ] ; // msgCount
data . charsPerSegment ( ) = info [ 2 ] ; // codeUnitsRemaining
2013-01-03 22:26:27 -08:00
// segmentChars = (codeUnitCount + codeUnitsRemaining) / msgCount
2013-08-09 06:25:53 -07:00
data . charsAvailableInLastSegment ( ) = ( info [ 1 ] + info [ 2 ] ) / info [ 0 ] ;
2013-01-03 22:26:27 -08:00
env - > ReleaseIntArrayElements ( arr , info , JNI_ABORT ) ;
2013-08-09 06:25:53 -07:00
// TODO Bug 908598 - Should properly use |QueueSmsRequest(...)| to queue up
// the nsIMobileMessageCallback just like other functions.
nsCOMPtr < nsIDOMMozSmsSegmentInfo > info = new SmsSegmentInfo ( data ) ;
return aRequest - > NotifySegmentInfoForTextGot ( info ) ;
2013-05-28 21:52:40 -07:00
# endif
2011-11-25 01:48:51 -08:00
}
2011-11-20 15:00:46 -08:00
void
2013-03-08 23:22:02 -08:00
AndroidBridge : : SendMessage ( const nsAString & aNumber ,
const nsAString & aMessage ,
nsIMobileMessageCallback * aRequest )
2011-11-20 15:00:46 -08:00
{
ALOG_BRIDGE ( " AndroidBridge::SendMessage " ) ;
2013-01-25 11:00:00 -08:00
uint32_t requestId ;
if ( ! QueueSmsRequest ( aRequest , & requestId ) )
return ;
2012-11-06 13:32:07 -08:00
2013-09-09 05:57:37 -07:00
SendMessageWrapper ( aNumber , aMessage , requestId ) ;
2011-11-20 15:00:46 -08:00
}
2011-12-22 14:08:58 -08:00
void
2013-03-08 23:22:02 -08:00
AndroidBridge : : GetMessage ( int32_t aMessageId , nsIMobileMessageCallback * aRequest )
2011-12-22 14:08:58 -08:00
{
ALOG_BRIDGE ( " AndroidBridge::GetMessage " ) ;
2013-01-25 11:00:00 -08:00
uint32_t requestId ;
if ( ! QueueSmsRequest ( aRequest , & requestId ) )
return ;
2012-11-06 13:32:07 -08:00
2013-09-09 05:57:37 -07:00
GetMessageWrapper ( aMessageId , requestId ) ;
2011-12-22 14:08:58 -08:00
}
2011-12-22 14:15:28 -08:00
void
2013-03-08 23:22:02 -08:00
AndroidBridge : : DeleteMessage ( int32_t aMessageId , nsIMobileMessageCallback * aRequest )
2011-12-22 14:15:28 -08:00
{
ALOG_BRIDGE ( " AndroidBridge::DeleteMessage " ) ;
2013-01-25 11:00:00 -08:00
uint32_t requestId ;
if ( ! QueueSmsRequest ( aRequest , & requestId ) )
return ;
2012-11-06 13:32:07 -08:00
2013-09-09 05:57:37 -07:00
DeleteMessageWrapper ( aMessageId , requestId ) ;
2011-12-22 14:15:28 -08:00
}
2011-12-20 00:07:25 -08:00
void
2013-03-01 00:38:47 -08:00
AndroidBridge : : CreateMessageList ( const dom : : mobilemessage : : SmsFilterData & aFilter , bool aReverse ,
2013-03-08 23:22:02 -08:00
nsIMobileMessageCallback * aRequest )
2011-12-20 00:07:25 -08:00
{
ALOG_BRIDGE ( " AndroidBridge::CreateMessageList " ) ;
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return ;
2013-01-25 11:00:00 -08:00
uint32_t requestId ;
if ( ! QueueSmsRequest ( aRequest , & requestId ) )
return ;
2012-11-06 13:32:07 -08:00
2012-07-02 12:32:34 -07:00
AutoLocalJNIFrame jniFrame ( env ) ;
2011-12-20 00:07:25 -08:00
jobjectArray numbers =
2012-05-04 08:08:45 -07:00
( jobjectArray ) env - > NewObjectArray ( aFilter . numbers ( ) . Length ( ) ,
2012-07-02 12:32:34 -07:00
jStringClass ,
2012-12-13 14:03:44 -08:00
NewJavaString ( & jniFrame , EmptyString ( ) ) ) ;
2011-12-20 00:07:25 -08:00
2013-09-09 05:57:37 -07:00
for ( uint32_t i = 0 ; i < aFilter . numbers ( ) . Length ( ) ; + + i ) {
env - > SetObjectArrayElement ( numbers , i ,
NewJavaString ( & jniFrame , aFilter . numbers ( ) [ i ] ) ) ;
}
2012-11-06 13:32:07 -08:00
2013-09-09 05:57:37 -07:00
CreateMessageListWrapper ( aFilter . startDate ( ) , aFilter . endDate ( ) ,
numbers , aFilter . numbers ( ) . Length ( ) ,
aFilter . delivery ( ) , aReverse , requestId ) ;
2011-12-22 14:16:59 -08:00
}
2012-01-17 10:43:08 -08:00
void
2013-09-09 05:57:37 -07:00
AndroidBridge : : GetNextMessageInList ( int32_t aListId , nsIMobileMessageCallback * aRequest )
2012-01-17 10:43:08 -08:00
{
2013-09-09 05:57:37 -07:00
ALOG_BRIDGE ( " AndroidBridge::GetNextMessageInList " ) ;
2012-01-17 10:43:08 -08:00
2013-09-09 05:57:37 -07:00
uint32_t requestId ;
if ( ! QueueSmsRequest ( aRequest , & requestId ) )
2012-01-29 12:39:30 -08:00
return ;
2013-09-09 05:57:37 -07:00
GetNextMessageInListWrapper ( aListId , requestId ) ;
2012-01-17 10:43:08 -08:00
}
2013-01-25 11:00:00 -08:00
bool
2013-03-08 23:22:02 -08:00
AndroidBridge : : QueueSmsRequest ( nsIMobileMessageCallback * aRequest , uint32_t * aRequestIdOut )
2012-11-06 13:32:07 -08:00
{
2013-01-25 11:00:00 -08:00
MOZ_ASSERT ( NS_IsMainThread ( ) , " Wrong thread! " ) ;
MOZ_ASSERT ( aRequest & & aRequestIdOut ) ;
2012-11-08 08:37:13 -08:00
2013-04-08 07:29:34 -07:00
const uint32_t length = mSmsRequests . Length ( ) ;
2013-01-25 11:00:00 -08:00
for ( uint32_t i = 0 ; i < length ; i + + ) {
2013-04-08 07:29:34 -07:00
if ( ! ( mSmsRequests ) [ i ] ) {
( mSmsRequests ) [ i ] = aRequest ;
2013-01-25 11:00:00 -08:00
* aRequestIdOut = i ;
return true ;
2012-11-06 13:32:07 -08:00
}
}
2013-04-08 07:29:34 -07:00
mSmsRequests . AppendElement ( aRequest ) ;
2012-11-06 13:32:07 -08:00
2013-01-25 11:00:00 -08:00
// After AppendElement(), previous `length` points to the new tail element.
* aRequestIdOut = length ;
return true ;
2012-11-06 13:32:07 -08:00
}
2013-03-08 23:22:02 -08:00
already_AddRefed < nsIMobileMessageCallback >
2013-01-25 11:00:00 -08:00
AndroidBridge : : DequeueSmsRequest ( uint32_t aRequestId )
2012-11-06 13:32:07 -08:00
{
2013-01-25 11:00:00 -08:00
MOZ_ASSERT ( NS_IsMainThread ( ) , " Wrong thread! " ) ;
2013-04-08 07:29:34 -07:00
MOZ_ASSERT ( aRequestId < mSmsRequests . Length ( ) ) ;
if ( aRequestId > = mSmsRequests . Length ( ) ) {
2012-11-06 13:32:07 -08:00
return nullptr ;
}
2013-04-08 07:29:34 -07:00
return mSmsRequests [ aRequestId ] . forget ( ) ;
2012-11-06 13:32:07 -08:00
}
2012-01-16 05:44:07 -08:00
void
AndroidBridge : : GetCurrentNetworkInformation ( hal : : NetworkInformation * aNetworkInfo )
{
ALOG_BRIDGE ( " AndroidBridge::GetCurrentNetworkInformation " ) ;
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return ;
2012-07-02 12:32:34 -07:00
AutoLocalJNIFrame jniFrame ( env ) ;
2012-01-16 05:44:07 -08:00
// To prevent calling too many methods through JNI, the Java method returns
2013-07-11 08:39:36 -07:00
// an array of double even if we actually want a double, two booleans, and an integer.
2012-05-04 08:08:47 -07:00
2013-09-09 05:57:37 -07:00
jdoubleArray arr = GetCurrentNetworkInformationWrapper ( ) ;
2013-07-11 08:39:36 -07:00
if ( ! arr | | env - > GetArrayLength ( arr ) ! = 4 ) {
2012-01-16 05:44:07 -08:00
return ;
}
2012-01-29 12:39:30 -08:00
jdouble * info = env - > GetDoubleArrayElements ( arr , 0 ) ;
2012-01-16 05:44:07 -08:00
aNetworkInfo - > bandwidth ( ) = info [ 0 ] ;
aNetworkInfo - > canBeMetered ( ) = info [ 1 ] = = 1.0f ;
2013-07-11 08:39:36 -07:00
aNetworkInfo - > isWifi ( ) = info [ 2 ] = = 1.0f ;
aNetworkInfo - > dhcpGateway ( ) = info [ 3 ] ;
2012-01-16 05:44:07 -08:00
2012-01-29 12:39:30 -08:00
env - > ReleaseDoubleArrayElements ( arr , info , 0 ) ;
2012-01-16 05:44:07 -08:00
}
2011-06-16 02:03:00 -07:00
void *
AndroidBridge : : LockBitmap ( jobject bitmap )
{
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
2012-07-30 07:20:58 -07:00
return nullptr ;
2012-01-29 12:39:30 -08:00
2012-05-04 08:08:47 -07:00
AutoLocalJNIFrame jniFrame ( env ) ;
int err ;
void * buf ;
2012-01-29 12:39:30 -08:00
if ( ( err = AndroidBitmap_lockPixels ( env , bitmap , & buf ) ) ! = 0 ) {
2011-06-16 02:03:00 -07:00
ALOG_BRIDGE ( " AndroidBitmap_lockPixels failed! (error %d) " , err ) ;
2012-07-30 07:20:58 -07:00
buf = nullptr ;
2011-06-16 02:03:00 -07:00
}
return buf ;
}
void
AndroidBridge : : UnlockBitmap ( jobject bitmap )
{
2012-01-29 12:39:30 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return ;
2012-05-04 08:08:47 -07:00
AutoLocalJNIFrame jniFrame ( env ) ;
int err ;
2012-01-29 12:39:30 -08:00
if ( ( err = AndroidBitmap_unlockPixels ( env , bitmap ) ) ! = 0 )
2011-06-16 02:03:00 -07:00
ALOG_BRIDGE ( " AndroidBitmap_unlockPixels failed! (error %d) " , err ) ;
}
2011-09-21 09:46:00 -07:00
bool
AndroidBridge : : HasNativeWindowAccess ( )
{
OpenGraphicsLibraries ( ) ;
2012-04-27 13:04:47 -07:00
// We have a fallback hack in place, so return true if that will work as well
return mHasNativeWindowAccess | | mHasNativeWindowFallback ;
2011-09-21 09:46:00 -07:00
}
void *
2012-04-27 13:04:47 -07:00
AndroidBridge : : AcquireNativeWindow ( JNIEnv * aEnv , jobject aSurface )
2011-09-21 09:46:00 -07:00
{
2012-04-27 13:04:47 -07:00
OpenGraphicsLibraries ( ) ;
2011-09-21 09:46:00 -07:00
2012-04-27 13:04:47 -07:00
if ( mHasNativeWindowAccess )
return ANativeWindow_fromSurface ( aEnv , aSurface ) ;
2012-07-20 12:20:51 -07:00
if ( mHasNativeWindowFallback )
2012-04-27 13:04:47 -07:00
return GetNativeSurface ( aEnv , aSurface ) ;
2012-07-20 12:20:51 -07:00
2012-07-30 07:20:58 -07:00
return nullptr ;
2011-09-21 09:46:00 -07:00
}
void
AndroidBridge : : ReleaseNativeWindow ( void * window )
{
if ( ! window )
return ;
2012-04-27 13:04:47 -07:00
if ( mHasNativeWindowAccess )
ANativeWindow_release ( window ) ;
// XXX: we don't ref the pointer we get from the fallback (GetNativeSurface), so we
// have nothing to do here. We should probably ref it.
2011-09-21 09:46:00 -07:00
}
2012-07-20 12:20:51 -07:00
void *
AndroidBridge : : AcquireNativeWindowFromSurfaceTexture ( JNIEnv * aEnv , jobject aSurfaceTexture )
{
OpenGraphicsLibraries ( ) ;
if ( mHasNativeWindowAccess & & ANativeWindow_fromSurfaceTexture )
return ANativeWindow_fromSurfaceTexture ( aEnv , aSurfaceTexture ) ;
if ( mHasNativeWindowAccess & & android_SurfaceTexture_getNativeWindow ) {
android : : sp < AndroidRefable > window = android_SurfaceTexture_getNativeWindow ( aEnv , aSurfaceTexture ) ;
return window . get ( ) ;
}
2012-07-30 07:20:58 -07:00
return nullptr ;
2012-07-20 12:20:51 -07:00
}
void
AndroidBridge : : ReleaseNativeWindowForSurfaceTexture ( void * window )
{
if ( ! window )
return ;
// FIXME: we don't ref the pointer we get, so nothing to do currently. We should ref it.
}
2011-09-21 09:46:00 -07:00
bool
AndroidBridge : : LockWindow ( void * window , unsigned char * * bits , int * width , int * height , int * format , int * stride )
{
/* Copied from native_window.h in Android NDK (platform-9) */
typedef struct ANativeWindow_Buffer {
// The number of pixels that are show horizontally.
int32_t width ;
// The number of pixels that are shown vertically.
int32_t height ;
// The number of *pixels* that a line in the buffer takes in
// memory. This may be >= width.
int32_t stride ;
// The format of the buffer. One of WINDOW_FORMAT_*
int32_t format ;
// The actual bits.
void * bits ;
// Do not touch.
uint32_t reserved [ 6 ] ;
} ANativeWindow_Buffer ;
2012-04-27 13:04:47 -07:00
// Very similar to the above, but the 'usage' field is included. We use this
// in the fallback case when NDK support is not available
2012-07-12 09:52:52 -07:00
struct SurfaceInfo {
2012-04-27 13:04:47 -07:00
uint32_t w ;
uint32_t h ;
uint32_t s ;
uint32_t usage ;
uint32_t format ;
unsigned char * bits ;
uint32_t reserved [ 2 ] ;
} ;
2011-09-21 09:46:00 -07:00
2012-04-27 13:04:47 -07:00
int err ;
2011-09-21 09:46:00 -07:00
* bits = NULL ;
* width = * height = * format = 0 ;
2012-07-02 12:32:34 -07:00
2012-04-27 13:04:47 -07:00
if ( mHasNativeWindowAccess ) {
ANativeWindow_Buffer buffer ;
2011-09-21 09:46:00 -07:00
2012-04-27 13:04:47 -07:00
if ( ( err = ANativeWindow_lock ( window , ( void * ) & buffer , NULL ) ) ! = 0 ) {
ALOG_BRIDGE ( " ANativeWindow_lock failed! (error %d) " , err ) ;
return false ;
}
* bits = ( unsigned char * ) buffer . bits ;
* width = buffer . width ;
* height = buffer . height ;
* format = buffer . format ;
* stride = buffer . stride ;
} else if ( mHasNativeWindowFallback ) {
SurfaceInfo info ;
if ( ( err = Surface_lock ( window , & info , NULL , true ) ) ! = 0 ) {
ALOG_BRIDGE ( " Surface_lock failed! (error %d) " , err ) ;
return false ;
}
* bits = info . bits ;
* width = info . w ;
* height = info . h ;
* format = info . format ;
* stride = info . s ;
} else return false ;
2011-09-21 09:46:00 -07:00
return true ;
}
2013-05-28 09:49:04 -07:00
jobject
AndroidBridge : : GetGlobalContextRef ( ) {
2013-09-24 23:06:21 -07:00
if ( sGlobalContext = = nullptr ) {
JNIEnv * env = GetJNIForThread ( ) ;
if ( ! env )
return 0 ;
2013-05-28 09:49:04 -07:00
2013-09-24 23:06:21 -07:00
AutoLocalJNIFrame jniFrame ( env , 4 ) ;
2013-05-28 09:49:04 -07:00
2013-09-24 23:06:21 -07:00
jobject context = GetContext ( ) ;
if ( ! context ) {
ALOG_BRIDGE ( " %s: Could not GetContext() " , __FUNCTION__ ) ;
return 0 ;
}
jclass contextClass = env - > FindClass ( " android/content/Context " ) ;
if ( ! contextClass ) {
ALOG_BRIDGE ( " %s: Could not find Context class. " , __FUNCTION__ ) ;
return 0 ;
}
jmethodID mid = env - > GetMethodID ( contextClass , " getApplicationContext " ,
" ()Landroid/content/Context; " ) ;
if ( ! mid ) {
ALOG_BRIDGE ( " %s: Could not find getApplicationContext. " , __FUNCTION__ ) ;
return 0 ;
}
jobject appContext = env - > CallObjectMethod ( context , mid ) ;
if ( ! appContext ) {
ALOG_BRIDGE ( " %s: getApplicationContext failed. " , __FUNCTION__ ) ;
return 0 ;
}
2013-05-28 09:49:04 -07:00
2013-09-24 23:06:21 -07:00
sGlobalContext = env - > NewGlobalRef ( appContext ) ;
MOZ_ASSERT ( sGlobalContext ) ;
}
2013-02-09 13:38:08 -08:00
2013-09-24 23:06:21 -07:00
return sGlobalContext ;
2013-02-09 13:38:08 -08:00
}
2011-09-21 09:46:00 -07:00
bool
AndroidBridge : : UnlockWindow ( void * window )
{
int err ;
2012-04-27 13:04:47 -07:00
if ( ! HasNativeWindowAccess ( ) )
return false ;
if ( mHasNativeWindowAccess & & ( err = ANativeWindow_unlockAndPost ( window ) ) ! = 0 ) {
2011-09-21 09:46:00 -07:00
ALOG_BRIDGE ( " ANativeWindow_unlockAndPost failed! (error %d) " , err ) ;
return false ;
2012-04-27 13:04:47 -07:00
} else if ( mHasNativeWindowFallback & & ( err = Surface_unlockAndPost ( window ) ) ! = 0 ) {
ALOG_BRIDGE ( " Surface_unlockAndPost failed! (error %d) " , err ) ;
return false ;
2011-09-21 09:46:00 -07:00
}
return true ;
}
2011-10-10 17:40:17 -07:00
2012-03-12 08:50:21 -07:00
void
2013-06-21 14:03:56 -07:00
AndroidBridge : : SetFirstPaintViewport ( const LayerIntPoint & aOffset , const CSSToLayerScale & aZoom , const CSSRect & aCssPageRect )
2012-03-12 08:50:21 -07:00
{
AndroidGeckoLayerClient * client = mLayerClient ;
if ( ! client )
return ;
2013-06-11 06:46:51 -07:00
client - > SetFirstPaintViewport ( aOffset , aZoom , aCssPageRect ) ;
2012-03-12 08:50:21 -07:00
}
void
2013-06-03 06:52:44 -07:00
AndroidBridge : : SetPageRect ( const CSSRect & aCssPageRect )
2012-03-12 08:50:21 -07:00
{
AndroidGeckoLayerClient * client = mLayerClient ;
if ( ! client )
return ;
2012-06-13 10:49:40 -07:00
client - > SetPageRect ( aCssPageRect ) ;
2012-03-12 08:50:21 -07:00
}
2012-02-03 18:35:58 -08:00
void
2013-06-21 14:03:56 -07:00
AndroidBridge : : SyncViewportInfo ( const LayerIntRect & aDisplayPort , const CSSToLayerScale & aDisplayResolution ,
bool aLayersUpdated , ScreenPoint & aScrollOffset , CSSToScreenScale & aScale ,
2013-07-22 01:50:13 -07:00
LayerMargin & aFixedLayerMargins , ScreenPoint & aOffset )
2012-02-03 18:35:58 -08:00
{
2012-03-13 21:15:11 -07:00
AndroidGeckoLayerClient * client = mLayerClient ;
if ( ! client )
return ;
2013-03-07 02:17:33 -08:00
client - > SyncViewportInfo ( aDisplayPort , aDisplayResolution , aLayersUpdated ,
2013-06-21 14:03:56 -07:00
aScrollOffset , aScale , aFixedLayerMargins ,
2013-05-01 11:12:08 -07:00
aOffset ) ;
2012-02-03 18:35:58 -08:00
}
2013-06-14 13:11:29 -07:00
void AndroidBridge : : SyncFrameMetrics ( const ScreenPoint & aScrollOffset , float aZoom , const CSSRect & aCssPageRect ,
2013-06-21 14:03:56 -07:00
bool aLayersUpdated , const CSSRect & aDisplayPort , const CSSToLayerScale & aDisplayResolution ,
2013-07-22 01:50:13 -07:00
bool aIsFirstPaint , LayerMargin & aFixedLayerMargins , ScreenPoint & aOffset )
2013-04-26 10:26:39 -07:00
{
AndroidGeckoLayerClient * client = mLayerClient ;
if ( ! client )
return ;
2013-05-01 11:12:08 -07:00
client - > SyncFrameMetrics ( aScrollOffset , aZoom , aCssPageRect ,
2013-04-26 10:26:39 -07:00
aLayersUpdated , aDisplayPort , aDisplayResolution ,
2013-05-01 11:12:08 -07:00
aIsFirstPaint , aFixedLayerMargins , aOffset ) ;
2013-04-26 10:26:39 -07:00
}
2012-07-13 14:34:58 -07:00
AndroidBridge : : AndroidBridge ( )
2013-04-26 10:24:28 -07:00
: mLayerClient ( NULL ) ,
mNativePanZoomController ( NULL )
2012-07-13 14:34:58 -07:00
{
}
AndroidBridge : : ~ AndroidBridge ( )
{
}
2011-10-10 17:40:17 -07:00
/* Implementation file */
NS_IMPL_ISUPPORTS1 ( nsAndroidBridge , nsIAndroidBridge )
nsAndroidBridge : : nsAndroidBridge ( )
{
}
nsAndroidBridge : : ~ nsAndroidBridge ( )
{
}
/* void handleGeckoEvent (in AString message); */
2012-07-06 13:14:07 -07:00
NS_IMETHODIMP nsAndroidBridge : : HandleGeckoMessage ( const nsAString & message , nsAString & aRet )
2011-10-10 17:40:17 -07:00
{
2011-10-24 10:05:18 -07:00
AndroidBridge : : Bridge ( ) - > HandleGeckoMessage ( message , aRet ) ;
2011-10-10 17:40:17 -07:00
return NS_OK ;
}
2011-11-17 19:20:29 -08:00
2013-05-30 06:55:08 -07:00
/* nsIAndroidDisplayport getDisplayPort(in boolean aPageSizeUpdate, in boolean isBrowserContentDisplayed, in int32_t tabId, in nsIAndroidViewport metrics); */
NS_IMETHODIMP nsAndroidBridge : : GetDisplayPort ( bool aPageSizeUpdate , bool aIsBrowserContentDisplayed , int32_t tabId , nsIAndroidViewport * metrics , nsIAndroidDisplayport * * displayPort )
{
AndroidBridge : : Bridge ( ) - > GetDisplayPort ( aPageSizeUpdate , aIsBrowserContentDisplayed , tabId , metrics , displayPort ) ;
return NS_OK ;
}
2013-05-30 06:55:23 -07:00
/* void displayedDocumentChanged(); */
NS_IMETHODIMP nsAndroidBridge : : ContentDocumentChanged ( )
{
AndroidBridge : : Bridge ( ) - > ContentDocumentChanged ( ) ;
return NS_OK ;
}
/* boolean isContentDocumentDisplayed(); */
NS_IMETHODIMP nsAndroidBridge : : IsContentDocumentDisplayed ( bool * aRet )
{
* aRet = AndroidBridge : : Bridge ( ) - > IsContentDocumentDisplayed ( ) ;
return NS_OK ;
}
2012-01-29 12:39:30 -08:00
// DO NOT USE THIS unless you need to access JNI from
// non-main threads. This is probably not what you want.
// Questions, ask blassey or dougt.
static void
JavaThreadDetachFunc ( void * arg )
{
JNIEnv * env = ( JNIEnv * ) arg ;
JavaVM * vm = NULL ;
env - > GetJavaVM ( & vm ) ;
vm - > DetachCurrentThread ( ) ;
}
extern " C " {
__attribute__ ( ( visibility ( " default " ) ) )
JNIEnv * GetJNIForThread ( )
{
JNIEnv * jEnv = NULL ;
JavaVM * jVm = mozilla : : AndroidBridge : : GetVM ( ) ;
if ( ! jVm ) {
__android_log_print ( ANDROID_LOG_INFO , " GetJNIForThread " , " Returned a null VM " ) ;
return NULL ;
}
2012-07-17 07:25:48 -07:00
jEnv = static_cast < JNIEnv * > ( PR_GetThreadPrivate ( sJavaEnvThreadIndex ) ) ;
if ( jEnv )
return jEnv ;
2012-01-29 12:39:30 -08:00
int status = jVm - > GetEnv ( ( void * * ) & jEnv , JNI_VERSION_1_2 ) ;
2012-07-17 07:25:48 -07:00
if ( status ) {
2012-01-29 12:39:30 -08:00
status = jVm - > AttachCurrentThread ( & jEnv , NULL ) ;
2012-07-17 07:25:48 -07:00
if ( status ) {
2012-01-29 12:39:30 -08:00
__android_log_print ( ANDROID_LOG_INFO , " GetJNIForThread " , " Could not attach " ) ;
return NULL ;
}
2012-07-17 07:25:48 -07:00
2012-01-29 12:39:30 -08:00
PR_SetThreadPrivate ( sJavaEnvThreadIndex , jEnv ) ;
}
if ( ! jEnv ) {
__android_log_print ( ANDROID_LOG_INFO , " GetJNIForThread " , " returning NULL " ) ;
}
return jEnv ;
}
}
2012-01-31 06:40:58 -08:00
2012-05-08 14:36:07 -07:00
uint32_t
AndroidBridge : : GetScreenOrientation ( )
2012-03-20 06:09:45 -07:00
{
ALOG_BRIDGE ( " AndroidBridge::GetScreenOrientation " ) ;
2012-05-04 08:08:47 -07:00
2013-09-09 05:57:37 -07:00
int16_t orientation = GetScreenOrientationWrapper ( ) ;
2012-05-04 08:08:47 -07:00
2013-09-09 05:57:37 -07:00
if ( ! orientation )
2012-05-08 14:36:07 -07:00
return dom : : eScreenOrientation_None ;
2012-05-04 08:08:47 -07:00
2012-05-08 14:36:07 -07:00
return static_cast < dom : : ScreenOrientation > ( orientation ) ;
2012-03-20 06:09:45 -07:00
}
2012-07-20 12:20:51 -07:00
void
AndroidBridge : : ScheduleComposite ( )
{
nsWindow : : ScheduleComposite ( ) ;
}
2012-07-05 07:12:10 -07:00
void
AndroidBridge : : GetGfxInfoData ( nsACString & aRet )
{
ALOG_BRIDGE ( " AndroidBridge::GetGfxInfoData " ) ;
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return ;
AutoLocalJNIFrame jniFrame ( env ) ;
2013-09-09 05:57:37 -07:00
jstring jstrRet = GetGfxInfoDataWrapper ( ) ;
if ( ! jstrRet )
2012-07-05 07:12:10 -07:00
return ;
nsJNIString jniStr ( jstrRet , env ) ;
CopyUTF16toUTF8 ( jniStr , aRet ) ;
}
2012-11-13 11:25:18 -08:00
nsresult
AndroidBridge : : GetProxyForURI ( const nsACString & aSpec ,
const nsACString & aScheme ,
const nsACString & aHost ,
const int32_t aPort ,
nsACString & aResult )
{
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
return NS_ERROR_FAILURE ;
AutoLocalJNIFrame jniFrame ( env ) ;
2013-09-09 05:57:37 -07:00
jstring jstrRet = GetProxyForURIWrapper ( NS_ConvertUTF8toUTF16 ( aSpec ) ,
NS_ConvertUTF8toUTF16 ( aScheme ) ,
NS_ConvertUTF8toUTF16 ( aHost ) ,
aPort ) ;
2012-11-13 11:25:18 -08:00
2013-09-09 05:57:37 -07:00
if ( ! jstrRet )
2012-11-13 11:25:18 -08:00
return NS_ERROR_FAILURE ;
nsJNIString jniStr ( jstrRet , env ) ;
CopyUTF16toUTF8 ( jniStr , aResult ) ;
return NS_OK ;
}
2012-02-17 10:52:26 -08:00
/* attribute nsIAndroidBrowserApp browserApp; */
NS_IMETHODIMP nsAndroidBridge : : GetBrowserApp ( nsIAndroidBrowserApp * * aBrowserApp )
{
if ( nsAppShell : : gAppShell )
nsAppShell : : gAppShell - > GetBrowserApp ( aBrowserApp ) ;
return NS_OK ;
}
2012-05-04 08:08:47 -07:00
2012-02-17 10:52:26 -08:00
NS_IMETHODIMP nsAndroidBridge : : SetBrowserApp ( nsIAndroidBrowserApp * aBrowserApp )
{
if ( nsAppShell : : gAppShell )
nsAppShell : : gAppShell - > SetBrowserApp ( aBrowserApp ) ;
return NS_OK ;
}
2012-03-26 22:31:57 -07:00
void
2013-08-13 08:49:21 -07:00
AndroidBridge : : AddPluginView ( jobject view , const LayoutDeviceRect & rect , bool isFullScreen ) {
nsWindow * win = nsWindow : : TopWindow ( ) ;
if ( ! win )
return ;
2013-09-17 17:45:19 -07:00
CSSRect cssRect = rect / win - > GetDefaultScale ( ) ;
2013-09-09 05:57:37 -07:00
AddPluginViewWrapper ( view , cssRect . x , cssRect . y , cssRect . width , cssRect . height , isFullScreen ) ;
2012-03-26 22:31:57 -07:00
}
2012-02-17 10:52:26 -08:00
extern " C "
__attribute__ ( ( visibility ( " default " ) ) )
jobject JNICALL
2012-05-04 08:08:47 -07:00
Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer ( JNIEnv * env , jclass , jlong size ) ;
2012-02-17 10:52:26 -08:00
2013-04-23 10:10:29 -07:00
bool
AndroidBridge : : GetThreadNameJavaProfiling ( uint32_t aThreadId , nsCString & aResult )
{
JNIEnv * env = GetJNIForThread ( ) ;
if ( ! env )
return false ;
AutoLocalJNIFrame jniFrame ( env ) ;
2013-09-09 05:57:37 -07:00
jstring jstrThreadName = GetThreadNameJavaProfilingWrapper ( aThreadId ) ;
2013-04-23 10:10:29 -07:00
if ( ! jstrThreadName )
return false ;
nsJNIString jniStr ( jstrThreadName , env ) ;
CopyUTF16toUTF8 ( jniStr . get ( ) , aResult ) ;
return true ;
}
bool
AndroidBridge : : GetFrameNameJavaProfiling ( uint32_t aThreadId , uint32_t aSampleId ,
uint32_t aFrameId , nsCString & aResult )
{
JNIEnv * env = GetJNIForThread ( ) ;
if ( ! env )
return false ;
AutoLocalJNIFrame jniFrame ( env ) ;
2013-09-09 05:57:37 -07:00
jstring jstrSampleName = GetFrameNameJavaProfilingWrapper ( aThreadId , aSampleId , aFrameId ) ;
2013-04-23 10:10:29 -07:00
if ( ! jstrSampleName )
return false ;
nsJNIString jniStr ( jstrSampleName , env ) ;
CopyUTF16toUTF8 ( jniStr . get ( ) , aResult ) ;
2013-09-09 05:57:37 -07:00
env - > DeleteLocalRef ( jstrSampleName ) ;
2013-04-23 10:10:29 -07:00
return true ;
}
2012-12-15 07:43:52 -08:00
nsresult AndroidBridge : : CaptureThumbnail ( nsIDOMWindow * window , int32_t bufW , int32_t bufH , int32_t tabId , jobject buffer )
2012-02-03 22:48:26 -08:00
{
2012-05-03 16:29:59 -07:00
nsresult rv ;
2012-06-14 09:08:51 -07:00
float scale = 1.0 ;
2012-07-02 12:32:34 -07:00
2012-06-14 09:08:51 -07:00
if ( ! buffer )
2013-01-23 09:18:05 -08:00
return NS_ERROR_FAILURE ;
2012-05-03 16:29:59 -07:00
// take a screenshot, as wide as possible, proportional to the destination size
2012-12-15 07:43:52 -08:00
nsCOMPtr < nsIDOMWindowUtils > utils = do_GetInterface ( window ) ;
if ( ! utils )
return NS_ERROR_FAILURE ;
nsCOMPtr < nsIDOMClientRect > rect ;
rv = utils - > GetRootBounds ( getter_AddRefs ( rect ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
if ( ! rect )
return NS_ERROR_FAILURE ;
2012-06-01 20:50:57 -07:00
2012-12-15 07:43:52 -08:00
float left , top , width , height ;
rect - > GetLeft ( & left ) ;
rect - > GetTop ( & top ) ;
rect - > GetWidth ( & width ) ;
rect - > GetHeight ( & height ) ;
if ( width = = 0 | | height = = 0 )
return NS_ERROR_FAILURE ;
int32_t srcX = left ;
int32_t srcY = top ;
int32_t srcW ;
int32_t srcH ;
float aspectRatio = ( ( float ) bufW ) / bufH ;
if ( width / aspectRatio < height ) {
srcW = width ;
srcH = width / aspectRatio ;
} else {
srcW = height * aspectRatio ;
srcH = height ;
2012-05-03 16:29:59 -07:00
}
2012-05-04 08:08:47 -07:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env )
2013-01-23 09:18:05 -08:00
return NS_ERROR_FAILURE ;
2012-05-04 08:08:47 -07:00
2013-01-23 09:18:05 -08:00
AutoLocalJNIFrame jniFrame ( env , 0 ) ;
2012-05-04 08:08:47 -07:00
2012-02-03 22:48:26 -08:00
nsCOMPtr < nsPIDOMWindow > win = do_QueryInterface ( window ) ;
if ( ! win )
return NS_ERROR_FAILURE ;
nsRefPtr < nsPresContext > presContext ;
nsIDocShell * docshell = win - > GetDocShell ( ) ;
if ( docshell ) {
docshell - > GetPresContext ( getter_AddRefs ( presContext ) ) ;
}
if ( ! presContext )
return NS_ERROR_FAILURE ;
nscolor bgColor = NS_RGB ( 255 , 255 , 255 ) ;
2012-10-26 18:02:57 -07:00
nsCOMPtr < nsIPresShell > presShell = presContext - > PresShell ( ) ;
2012-08-22 08:56:38 -07:00
uint32_t renderDocFlags = ( nsIPresShell : : RENDER_IGNORE_VIEWPORT_SCROLLING |
2012-02-03 22:48:26 -08:00
nsIPresShell : : RENDER_DOCUMENT_RELATIVE ) ;
2012-03-14 21:43:53 -07:00
nsRect r ( nsPresContext : : CSSPixelsToAppUnits ( srcX / scale ) ,
nsPresContext : : CSSPixelsToAppUnits ( srcY / scale ) ,
nsPresContext : : CSSPixelsToAppUnits ( srcW / scale ) ,
nsPresContext : : CSSPixelsToAppUnits ( srcH / scale ) ) ;
2012-02-03 22:48:26 -08:00
2013-07-04 06:53:25 -07:00
bool is24bit = ( GetScreenDepth ( ) = = 24 ) ;
uint32_t stride = bufW * ( is24bit ? 4 : 2 ) ;
2012-02-17 10:52:26 -08:00
2012-05-04 08:08:47 -07:00
void * data = env - > GetDirectBufferAddress ( buffer ) ;
2012-09-25 12:46:17 -07:00
if ( ! data )
return NS_ERROR_FAILURE ;
2013-07-04 06:53:25 -07:00
nsRefPtr < gfxImageSurface > surf =
new gfxImageSurface ( static_cast < unsigned char * > ( data ) , nsIntSize ( bufW , bufH ) , stride ,
2013-09-24 13:45:13 -07:00
is24bit ? gfxImageFormatRGB24 :
gfxImageFormatRGB16_565 ) ;
2012-08-13 17:01:31 -07:00
if ( surf - > CairoStatus ( ) ! = 0 ) {
ALOG_BRIDGE ( " Error creating gfxImageSurface " ) ;
return NS_ERROR_FAILURE ;
}
2012-02-03 22:48:26 -08:00
nsRefPtr < gfxContext > context = new gfxContext ( surf ) ;
2012-12-15 07:43:52 -08:00
gfxPoint pt ( 0 , 0 ) ;
2012-06-14 09:08:51 -07:00
context - > Translate ( pt ) ;
2012-12-15 07:43:52 -08:00
context - > Scale ( scale * bufW / srcW , scale * bufH / srcH ) ;
2012-05-03 16:29:59 -07:00
rv = presShell - > RenderDocument ( r , renderDocFlags , bgColor , context ) ;
2013-07-24 06:18:05 -07:00
if ( is24bit ) {
gfxUtils : : ConvertBGRAtoRGBA ( surf ) ;
}
2012-02-03 22:48:26 -08:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
return NS_OK ;
}
2012-04-24 12:13:36 -07:00
2013-05-30 06:55:08 -07:00
void
2012-09-12 14:47:08 -07:00
AndroidBridge : : GetDisplayPort ( bool aPageSizeUpdate , bool aIsBrowserContentDisplayed , int32_t tabId , nsIAndroidViewport * metrics , nsIAndroidDisplayport * * displayPort )
{
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env | | ! mLayerClient )
2013-05-30 06:55:08 -07:00
return ;
2012-09-12 14:47:08 -07:00
AutoLocalJNIFrame jniFrame ( env , 0 ) ;
mLayerClient - > GetDisplayPort ( & jniFrame , aPageSizeUpdate , aIsBrowserContentDisplayed , tabId , metrics , displayPort ) ;
}
2013-05-30 06:55:23 -07:00
void
AndroidBridge : : ContentDocumentChanged ( )
{
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env | | ! mLayerClient )
return ;
AutoLocalJNIFrame jniFrame ( env , 0 ) ;
mLayerClient - > ContentDocumentChanged ( & jniFrame ) ;
}
bool
AndroidBridge : : IsContentDocumentDisplayed ( )
{
JNIEnv * env = GetJNIEnv ( ) ;
if ( ! env | | ! mLayerClient )
return false ;
AutoLocalJNIFrame jniFrame ( env , 0 ) ;
return mLayerClient - > IsContentDocumentDisplayed ( & jniFrame ) ;
}
2012-10-04 11:45:16 -07:00
bool
2013-06-10 06:05:42 -07:00
AndroidBridge : : ProgressiveUpdateCallback ( bool aHasPendingNewThebesContent , const LayerRect & aDisplayPort , float aDisplayResolution , bool aDrawingCritical , gfx : : Rect & aViewport , float & aScaleX , float & aScaleY )
2012-10-04 11:45:16 -07:00
{
2012-10-05 07:41:03 -07:00
AndroidGeckoLayerClient * client = mLayerClient ;
if ( ! client )
2012-10-04 11:45:16 -07:00
return false ;
2012-11-21 14:34:19 -08:00
return client - > ProgressiveUpdateCallback ( aHasPendingNewThebesContent , aDisplayPort , aDisplayResolution , aDrawingCritical , aViewport , aScaleX , aScaleY ) ;
2012-10-04 11:45:16 -07:00
}
2013-04-26 10:24:28 -07:00
jobject
AndroidBridge : : SetNativePanZoomController ( jobject obj )
{
jobject old = mNativePanZoomController ;
mNativePanZoomController = obj ;
return old ;
}
void
AndroidBridge : : RequestContentRepaint ( const mozilla : : layers : : FrameMetrics & aFrameMetrics )
{
2013-04-26 10:26:46 -07:00
ALOG_BRIDGE ( " AndroidBridge::RequestContentRepaint " ) ;
2013-08-26 07:34:56 -07:00
CSSToScreenScale resolution = aFrameMetrics . mZoom ;
2013-06-14 13:11:44 -07:00
ScreenRect dp = ( aFrameMetrics . mDisplayPort + aFrameMetrics . mScrollOffset ) * resolution ;
2013-04-26 10:26:46 -07:00
2013-09-09 05:57:37 -07:00
RequestContentRepaintWrapper ( mNativePanZoomController ,
2013-06-14 13:11:44 -07:00
dp . x , dp . y , dp . width , dp . height , resolution . scale ) ;
2013-04-26 10:24:28 -07:00
}
void
2013-06-10 06:05:44 -07:00
AndroidBridge : : HandleDoubleTap ( const CSSIntPoint & aPoint )
2013-04-26 10:24:28 -07:00
{
2013-04-26 10:26:46 -07:00
nsCString data = nsPrintfCString ( " { \" x \" : %d, \" y \" : %d } " , aPoint . x , aPoint . y ) ;
nsAppShell : : gAppShell - > PostEvent ( AndroidGeckoEvent : : MakeBroadcastEvent (
NS_LITERAL_CSTRING ( " Gesture:DoubleTap " ) , data ) ) ;
2013-04-26 10:24:28 -07:00
}
void
2013-06-10 06:05:44 -07:00
AndroidBridge : : HandleSingleTap ( const CSSIntPoint & aPoint )
2013-04-26 10:24:28 -07:00
{
2013-04-26 10:26:46 -07:00
nsCString data = nsPrintfCString ( " { \" x \" : %d, \" y \" : %d } " , aPoint . x , aPoint . y ) ;
nsAppShell : : gAppShell - > PostEvent ( AndroidGeckoEvent : : MakeBroadcastEvent (
NS_LITERAL_CSTRING ( " Gesture:SingleTap " ) , data ) ) ;
2013-04-26 10:24:28 -07:00
}
void
2013-06-10 06:05:44 -07:00
AndroidBridge : : HandleLongTap ( const CSSIntPoint & aPoint )
2013-04-26 10:24:28 -07:00
{
2013-04-26 10:26:46 -07:00
nsCString data = nsPrintfCString ( " { \" x \" : %d, \" y \" : %d } " , aPoint . x , aPoint . y ) ;
nsAppShell : : gAppShell - > PostEvent ( AndroidGeckoEvent : : MakeBroadcastEvent (
NS_LITERAL_CSTRING ( " Gesture:LongPress " ) , data ) ) ;
2013-04-26 10:24:28 -07:00
}
void
2013-07-30 11:03:42 -07:00
AndroidBridge : : SendAsyncScrollDOMEvent ( mozilla : : layers : : FrameMetrics : : ViewID aScrollId ,
const CSSRect & aContentRect ,
const CSSSize & aScrollableSize )
2013-04-26 10:24:28 -07:00
{
// FIXME implement this
}
void
2013-04-26 10:26:46 -07:00
AndroidBridge : : PostDelayedTask ( Task * aTask , int aDelayMs )
2013-04-26 10:24:28 -07:00
{
2013-04-26 10:26:46 -07:00
// add the new task into the mDelayedTaskQueue, sorted with
// the earliest task first in the queue
DelayedTask * newTask = new DelayedTask ( aTask , aDelayMs ) ;
uint32_t i = 0 ;
while ( i < mDelayedTaskQueue . Length ( ) ) {
if ( newTask - > IsEarlierThan ( mDelayedTaskQueue [ i ] ) ) {
mDelayedTaskQueue . InsertElementAt ( i , newTask ) ;
break ;
}
i + + ;
}
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
2013-09-09 05:57:37 -07:00
PostDelayedCallbackWrapper ( mNativePanZoomController , ( int64_t ) aDelayMs ) ;
2013-04-26 10:26:46 -07:00
}
}
int64_t
AndroidBridge : : RunDelayedTasks ( )
{
while ( mDelayedTaskQueue . Length ( ) > 0 ) {
DelayedTask * nextTask = mDelayedTaskQueue [ 0 ] ;
int64_t timeLeft = nextTask - > MillisecondsToRunTime ( ) ;
if ( timeLeft > 0 ) {
// this task (and therefore all remaining tasks)
// have not yet reached their runtime. return the
// time left until we should be called again
return timeLeft ;
}
// we have a delayed task to run. extract it from
// the wrapper and free the wrapper
mDelayedTaskQueue . RemoveElementAt ( 0 ) ;
Task * task = nextTask - > GetTask ( ) ;
delete nextTask ;
task - > Run ( ) ;
}
return - 1 ;
2013-04-26 10:24:28 -07:00
}