2010-06-03 20:56:36 +00:00
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
2012-05-21 11:12:37 +00: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 20:56:36 +00:00
2012-02-04 02:35:58 +00:00
# include "mozilla/layers/CompositorChild.h"
# include "mozilla/layers/CompositorParent.h"
2010-06-03 20:56:36 +00:00
# include <android/log.h>
2011-06-16 09:03:00 +00:00
# include <dlfcn.h>
2014-05-06 05:33:29 +00:00
# include <math.h>
2010-06-03 20:56:36 +00:00
2011-11-02 15:35:11 +00:00
# include "mozilla/Hal.h"
2010-08-17 08:07:45 +00:00
# include "nsXULAppAPI.h"
2010-06-03 20:56:36 +00:00
# include <prthread.h>
2010-06-30 02:22:08 +00:00
# include "nsXPCOMStrings.h"
2010-06-03 20:56:36 +00:00
# include "AndroidBridge.h"
2013-02-09 23:50:28 +00:00
# include "AndroidJNIWrapper.h"
2013-09-09 12:57:36 +00:00
# include "AndroidBridgeUtilities.h"
2010-06-15 02:17:37 +00:00
# include "nsAppShell.h"
2010-09-30 15:37:36 +00:00
# include "nsOSHelperAppService.h"
2011-04-11 20:41:03 +00:00
# include "nsWindow.h"
2011-06-07 07:38:00 +00:00
# include "mozilla/Preferences.h"
2011-08-04 07:32:57 +00:00
# include "nsThreadUtils.h"
2012-01-29 20:39:30 +00:00
# include "nsIThreadManager.h"
2013-03-01 08:38:47 +00:00
# include "mozilla/dom/mobilemessage/PSms.h"
2013-10-15 03:23:20 +00:00
# include "gfxPlatform.h"
2012-02-04 06:48:26 +00:00
# include "gfxContext.h"
2013-10-15 03:23:20 +00:00
# include "mozilla/gfx/2D.h"
2013-07-24 13:18:05 +00:00
# include "gfxUtils.h"
2012-02-04 06:48:26 +00:00
# include "nsPresContext.h"
# include "nsIDocShell.h"
# include "nsPIDOMWindow.h"
2012-03-20 13:09:45 +00:00
# include "mozilla/dom/ScreenOrientation.h"
2012-06-02 03:50:57 +00:00
# include "nsIDOMWindowUtils.h"
# include "nsIDOMClientRect.h"
2012-07-20 19:20:51 +00:00
# include "StrongPointer.h"
2012-11-06 21:32:07 +00:00
# include "mozilla/ClearOnShutdown.h"
2013-04-26 17:26:46 +00:00
# include "nsPrintfCString.h"
2014-04-04 16:33:49 +00:00
# include "NativeJSContainer.h"
# include "nsContentUtils.h"
# include "nsIScriptError.h"
2014-05-06 05:33:29 +00:00
# include "nsIHttpChannel.h"
2014-11-13 18:47:24 +00:00
# include "MediaCodec.h"
# include "SurfaceTexture.h"
2015-04-11 02:14:00 +00:00
# include "GLContextProvider.h"
2010-06-03 20:56:36 +00:00
using namespace mozilla ;
2013-10-15 03:23:20 +00:00
using namespace mozilla : : gfx ;
2015-01-10 00:33:57 +00:00
using namespace mozilla : : jni ;
using namespace mozilla : : widget ;
2010-06-03 20:56:36 +00:00
2015-02-18 21:50:31 +00:00
AndroidBridge * AndroidBridge : : sBridge = nullptr ;
2014-08-08 22:15:38 +00:00
pthread_t AndroidBridge : : sJavaUiThread = - 1 ;
2012-08-22 15:56:38 +00:00
static unsigned sJavaEnvThreadIndex = 0 ;
2013-09-25 06:06:21 +00:00
static jobject sGlobalContext = nullptr ;
2012-07-17 14:25:48 +00:00
static void JavaThreadDetachFunc ( void * arg ) ;
2010-06-03 20:56:36 +00:00
2012-07-20 19:20:51 +00: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 14:20:58 +00:00
static android : : sp < AndroidRefable > ( * android_SurfaceTexture_getNativeWindow ) ( JNIEnv * env , jobject surfaceTexture ) = nullptr ;
2012-07-20 19:20:51 +00:00
2013-09-09 12:57:36 +00:00
jclass AndroidBridge : : GetClassGlobalRef ( JNIEnv * env , const char * className )
{
2015-01-10 00:33:57 +00:00
// First try the default class loader.
auto classRef = ClassObject : : LocalRef : : Adopt (
env , env - > FindClass ( className ) ) ;
if ( ! classRef & & sBridge & & sBridge - > mClassLoader ) {
// If the default class loader failed but we have an app class loader, try that.
// Clear the pending exception from failed FindClass call above.
env - > ExceptionClear ( ) ;
classRef = ClassObject : : LocalRef : : Adopt ( env ,
env - > CallObjectMethod ( sBridge - > mClassLoader . Get ( ) ,
sBridge - > mClassLoaderLoadClass ,
2015-07-11 03:41:35 +00:00
Param < String > ( className , env ) . Get ( ) ) ) ;
2013-09-09 12:57:36 +00:00
}
2015-01-10 00:33:57 +00:00
if ( ! classRef ) {
ALOG ( " >>> FATAL JNI ERROR! FindClass(className= \" %s \" ) failed. "
" Did ProGuard optimize away something it shouldn't have? " ,
className ) ;
2013-09-09 12:57:36 +00:00
env - > ExceptionDescribe ( ) ;
MOZ_CRASH ( ) ;
}
2015-01-10 00:33:57 +00:00
return ClassObject : : GlobalRef ( env , classRef ) . Forget ( ) ;
2013-09-09 12:57:36 +00:00
}
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 \" , "
2013-11-19 01:30:00 +00:00
" methodType= \" %s \" ) failed. Did ProGuard optimize away something it shouldn't have? " ,
methodName , methodType ) ;
2013-09-09 12:57:36 +00:00
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 \" , "
2013-11-19 01:30:00 +00:00
" methodType= \" %s \" ) failed. Did ProGuard optimize away something it shouldn't have? " ,
methodName , methodType ) ;
2013-09-09 12:57:36 +00:00
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 \" , "
2013-11-19 01:30:00 +00:00
" fieldType= \" %s \" ) failed. Did ProGuard optimize away something it shouldn't have? " ,
fieldName , fieldType ) ;
2013-09-09 12:57:36 +00:00
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 \" , "
2013-11-19 01:30:00 +00:00
" fieldType= \" %s \" ) failed. Did ProGuard optimize away something it shouldn't have? " ,
fieldName , fieldType ) ;
2013-09-09 12:57:36 +00:00
env - > ExceptionDescribe ( ) ;
MOZ_CRASH ( ) ;
}
return fieldID ;
}
2012-07-31 21:34:06 +00:00
void
2015-04-28 00:52:52 +00:00
AndroidBridge : : ConstructBridge ( JNIEnv * jEnv , Object : : Param clsLoader , Object : : Param msgQueue )
2010-06-03 20:56:36 +00: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 19:32:34 +00:00
putenv ( " NSS_DISABLE_UNLOAD=1 " ) ;
2010-06-03 20:56:36 +00:00
2012-07-17 14:25:48 +00:00
PR_NewThreadPrivateIndex ( & sJavaEnvThreadIndex , JavaThreadDetachFunc ) ;
2015-02-18 21:50:31 +00:00
MOZ_ASSERT ( ! sBridge ) ;
sBridge = new AndroidBridge ;
sBridge - > Init ( jEnv , clsLoader ) ; // Success or crash
2015-04-28 00:52:52 +00:00
auto msgQueueClass = ClassObject : : LocalRef : : Adopt (
jEnv , jEnv - > GetObjectClass ( msgQueue . Get ( ) ) ) ;
sBridge - > mMessageQueue = msgQueue ;
// mMessageQueueNext must not be null
sBridge - > mMessageQueueNext = GetMethodID (
jEnv , msgQueueClass . Get ( ) , " next " , " ()Landroid/os/Message; " ) ;
// mMessageQueueMessages may be null (e.g. due to proguard optimization)
sBridge - > mMessageQueueMessages = jEnv - > GetFieldID (
msgQueueClass . Get ( ) , " mMessages " , " Landroid/os/Message; " ) ;
2010-06-03 20:56:36 +00:00
}
2015-02-18 21:50:31 +00:00
void
2015-01-10 00:33:57 +00:00
AndroidBridge : : Init ( JNIEnv * jEnv , Object : : Param clsLoader )
2010-06-03 20:56:36 +00:00
{
2011-12-06 06:56:04 +00:00
ALOG_BRIDGE ( " AndroidBridge::Init " ) ;
2010-06-03 20:56:36 +00:00
jEnv - > GetJavaVM ( & mJavaVM ) ;
2014-01-18 05:32:24 +00:00
if ( ! mJavaVM ) {
MOZ_CRASH ( ) ; // Nothing we can do here
}
2010-06-03 20:56:36 +00:00
2012-05-04 15:08:47 +00:00
AutoLocalJNIFrame jniFrame ( jEnv ) ;
2012-04-27 20:04:47 +00:00
2015-01-10 00:33:57 +00:00
mClassLoader = Object : : GlobalRef ( jEnv , clsLoader ) ;
mClassLoaderLoadClass = GetMethodID (
jEnv , jEnv - > GetObjectClass ( clsLoader . Get ( ) ) ,
" loadClass " , " (Ljava/lang/String;)Ljava/lang/Class; " ) ;
2012-07-30 14:20:58 +00:00
mJNIEnv = nullptr ;
2015-04-17 16:22:47 +00:00
mThread = pthread_t ( ) ;
2014-01-06 15:06:04 +00:00
mGLControllerObj = nullptr ;
2011-09-21 16:46:00 +00:00
mOpenedGraphicsLibraries = false ;
2011-06-16 09:03:00 +00:00
mHasNativeBitmapAccess = false ;
2011-09-21 16:46:00 +00:00
mHasNativeWindowAccess = false ;
2012-04-27 20:04:47 +00:00
mHasNativeWindowFallback = false ;
2010-06-03 20:56:36 +00:00
2013-05-29 04:52:40 +00:00
# ifdef MOZ_WEBSMS_BACKEND
2015-01-10 00:33:56 +00:00
AutoJNIClass smsMessage ( jEnv , " android/telephony/SmsMessage " ) ;
mAndroidSmsMessageClass = smsMessage . getGlobalRef ( ) ;
jCalculateLength = smsMessage . getStaticMethod ( " calculateLength " , " (Ljava/lang/CharSequence;Z)[I " ) ;
2013-05-29 04:52:40 +00:00
# endif
2013-01-04 06:26:27 +00:00
2015-01-10 00:33:56 +00:00
AutoJNIClass string ( jEnv , " java/lang/String " ) ;
jStringClass = string . getGlobalRef ( ) ;
2013-09-09 12:57:36 +00:00
if ( ! GetStaticIntField ( " android/os/Build$VERSION " , " SDK_INT " , & mAPIVersion , jEnv ) ) {
2012-04-27 20:04:47 +00:00
ALOG_BRIDGE ( " Failed to find API version " ) ;
2013-09-09 12:57:36 +00:00
}
2012-04-27 20:04:47 +00:00
2015-01-10 00:33:56 +00:00
AutoJNIClass surface ( jEnv , " android/view/Surface " ) ;
jSurfaceClass = surface . getGlobalRef ( ) ;
2013-02-26 14:28:57 +00:00
if ( mAPIVersion < = 8 /* Froyo */ ) {
2015-01-10 00:33:56 +00:00
jSurfacePointerField = surface . getField ( " mSurface " , " I " ) ;
2013-11-04 18:07:03 +00:00
} else if ( mAPIVersion > 8 & & mAPIVersion < 19 /* KitKat */ ) {
2015-01-10 00:33:56 +00:00
jSurfacePointerField = surface . getField ( " mNativeSurface " , " I " ) ;
2013-11-04 18:07:03 +00:00
} else {
// We don't know how to get this, just set it to 0
jSurfacePointerField = 0 ;
2013-02-26 14:28:57 +00:00
}
2015-01-10 00:33:56 +00:00
AutoJNIClass egl ( jEnv , " com/google/android/gles_jni/EGLSurfaceImpl " ) ;
jclass eglClass = egl . getGlobalRef ( ) ;
2013-02-28 18:28:24 +00:00
if ( eglClass ) {
2014-07-01 16:43:27 +00:00
// The pointer type moved to a 'long' in Android L, API version 20
const char * jniType = mAPIVersion > = 20 ? " J " : " I " ;
2015-01-10 00:33:56 +00:00
jEGLSurfacePointerField = egl . getField ( " mEGLSurface " , jniType ) ;
2013-02-28 18:28:24 +00:00
} else {
jEGLSurfacePointerField = 0 ;
}
2012-03-08 15:22:42 +00:00
2015-01-10 00:33:56 +00:00
AutoJNIClass channels ( jEnv , " java/nio/channels/Channels " ) ;
jChannels = channels . getGlobalRef ( ) ;
jChannelCreate = channels . getStaticMethod ( " newChannel " , " (Ljava/io/InputStream;)Ljava/nio/channels/ReadableByteChannel; " ) ;
2014-06-04 19:28:04 +00:00
2015-01-10 00:33:56 +00:00
AutoJNIClass readableByteChannel ( jEnv , " java/nio/channels/ReadableByteChannel " ) ;
jReadableByteChannel = readableByteChannel . getGlobalRef ( ) ;
jByteBufferRead = readableByteChannel . getMethod ( " read " , " (Ljava/nio/ByteBuffer;)I " ) ;
2014-06-04 19:28:04 +00:00
2015-01-10 00:33:56 +00:00
AutoJNIClass inputStream ( jEnv , " java/io/InputStream " ) ;
jInputStream = inputStream . getGlobalRef ( ) ;
jClose = inputStream . getMethod ( " close " , " ()V " ) ;
jAvailable = inputStream . getMethod ( " available " , " ()I " ) ;
2014-06-04 19:28:04 +00:00
2010-06-03 20:56:36 +00: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-09-29 06:19:26 +00:00
bool
2013-09-09 12:57:37 +00:00
AndroidBridge : : SetMainThread ( pthread_t thr )
2010-06-03 20:56:36 +00:00
{
2011-03-01 04:25:11 +00:00
ALOG_BRIDGE ( " AndroidBridge::SetMainThread " ) ;
2010-06-03 20:56:36 +00:00
if ( thr ) {
mThread = thr ;
2012-01-29 20:39:30 +00:00
mJavaVM - > GetEnv ( ( void * * ) & mJNIEnv , JNI_VERSION_1_2 ) ;
return ( bool ) mJNIEnv ;
2010-06-03 20:56:36 +00:00
}
2012-07-30 14:20:58 +00:00
mJNIEnv = nullptr ;
2015-04-17 16:22:47 +00:00
mThread = pthread_t ( ) ;
// SetMainThread(0) is called on Gecko shutdown,
// so we should clean up the bridge here.
if ( sBridge ) {
delete sBridge ;
// AndroidBridge destruction requires sBridge to still be valid,
// so we set sBridge to nullptr after deleting it.
sBridge = nullptr ;
}
2011-10-17 14:59:28 +00:00
return true ;
2010-06-03 20:56:36 +00:00
}
2013-09-09 12:57:37 +00:00
// Raw JNIEnv variants.
2014-01-04 15:02:17 +00:00
jstring AndroidBridge : : NewJavaString ( JNIEnv * env , const char16_t * string , uint32_t len ) {
2013-10-08 18:00:40 +00:00
jstring ret = env - > NewString ( reinterpret_cast < const jchar * > ( string ) , len ) ;
2013-09-09 12:57:37 +00:00
if ( env - > ExceptionCheck ( ) ) {
ALOG_BRIDGE ( " Exceptional exit of: %s " , __PRETTY_FUNCTION__ ) ;
env - > ExceptionDescribe ( ) ;
env - > ExceptionClear ( ) ;
2013-10-10 20:42:52 +00:00
return nullptr ;
2013-09-09 12:57:37 +00:00
}
2012-09-05 04:23:02 +00:00
return ret ;
}
2013-09-09 12:57:37 +00:00
jstring AndroidBridge : : NewJavaString ( JNIEnv * env , const nsAString & string ) {
return NewJavaString ( env , string . BeginReading ( ) , string . Length ( ) ) ;
2011-03-02 17:23:02 +00:00
}
2013-09-09 12:57:37 +00:00
jstring AndroidBridge : : NewJavaString ( JNIEnv * env , const char * string ) {
return NewJavaString ( env , NS_ConvertUTF8toUTF16 ( string ) ) ;
2010-06-04 21:14:43 +00:00
}
2013-09-09 12:57:37 +00:00
jstring AndroidBridge : : NewJavaString ( JNIEnv * env , const nsACString & string ) {
return NewJavaString ( env , NS_ConvertUTF8toUTF16 ( string ) ) ;
2012-03-21 17:52:35 +00:00
}
2013-09-09 12:57:37 +00:00
// AutoLocalJNIFrame variants..
2014-01-04 15:02:17 +00:00
jstring AndroidBridge : : NewJavaString ( AutoLocalJNIFrame * frame , const char16_t * string , uint32_t len ) {
2013-09-09 12:57:37 +00:00
return NewJavaString ( frame - > GetEnv ( ) , string , len ) ;
2012-02-05 19:51:05 +00:00
}
2013-09-09 12:57:37 +00:00
jstring AndroidBridge : : NewJavaString ( AutoLocalJNIFrame * frame , const nsAString & string ) {
return NewJavaString ( frame , string . BeginReading ( ) , string . Length ( ) ) ;
2012-02-05 19:51:05 +00:00
}
2013-09-09 12:57:37 +00:00
jstring AndroidBridge : : NewJavaString ( AutoLocalJNIFrame * frame , const char * string ) {
return NewJavaString ( frame , NS_ConvertUTF8toUTF16 ( string ) ) ;
2010-06-03 20:56:36 +00:00
}
2013-09-09 12:57:37 +00:00
jstring AndroidBridge : : NewJavaString ( AutoLocalJNIFrame * frame , const nsACString & string ) {
return NewJavaString ( frame , NS_ConvertUTF8toUTF16 ( string ) ) ;
2010-06-03 20:56:36 +00:00
}
2013-11-12 18:41:01 +00:00
extern " C " {
__attribute__ ( ( visibility ( " default " ) ) )
JNIEnv * GetJNIForThread ( )
{
2014-01-18 05:32:24 +00:00
JNIEnv * jEnv = static_cast < JNIEnv * > ( PR_GetThreadPrivate ( sJavaEnvThreadIndex ) ) ;
if ( jEnv ) {
2013-11-12 18:41:01 +00:00
return jEnv ;
}
2014-01-18 05:32:24 +00:00
JavaVM * jVm = mozilla : : AndroidBridge : : GetVM ( ) ;
2014-01-29 00:32:28 +00:00
if ( ! jVm - > GetEnv ( reinterpret_cast < void * * > ( & jEnv ) , JNI_VERSION_1_2 ) ) {
MOZ_ASSERT ( jEnv ) ;
return jEnv ;
}
if ( ! jVm - > AttachCurrentThread ( & jEnv , nullptr ) ) {
2014-01-18 05:32:24 +00:00
MOZ_ASSERT ( jEnv ) ;
PR_SetThreadPrivate ( sJavaEnvThreadIndex , jEnv ) ;
return jEnv ;
2013-11-12 18:41:01 +00:00
}
2014-01-18 05:32:24 +00:00
MOZ_CRASH ( ) ;
return nullptr ; // unreachable
2013-11-12 18:41:01 +00:00
}
}
void AutoGlobalWrappedJavaObject : : Dispose ( ) {
if ( isNull ( ) ) {
return ;
}
GetJNIForThread ( ) - > DeleteGlobalRef ( wrapped_obj ) ;
2014-01-06 15:06:04 +00:00
wrapped_obj = nullptr ;
2013-11-12 18:41:01 +00:00
}
AutoGlobalWrappedJavaObject : : ~ AutoGlobalWrappedJavaObject ( ) {
Dispose ( ) ;
}
2014-05-06 05:33:29 +00:00
// Decides if we should store thumbnails for a given docshell based on the presence
// of a Cache-Control: no-store header and the "browser.cache.disk_cache_ssl" pref.
static bool ShouldStoreThumbnail ( nsIDocShell * docshell ) {
if ( ! docshell ) {
return false ;
}
nsresult rv ;
nsCOMPtr < nsIChannel > channel ;
docshell - > GetCurrentDocumentChannel ( getter_AddRefs ( channel ) ) ;
if ( ! channel ) {
return false ;
}
nsCOMPtr < nsIHttpChannel > httpChannel ;
rv = channel - > QueryInterface ( NS_GET_IID ( nsIHttpChannel ) , getter_AddRefs ( httpChannel ) ) ;
if ( ! NS_SUCCEEDED ( rv ) ) {
return false ;
}
// Don't store thumbnails for sites that didn't load
uint32_t responseStatus ;
rv = httpChannel - > GetResponseStatus ( & responseStatus ) ;
if ( ! NS_SUCCEEDED ( rv ) | | floor ( ( double ) ( responseStatus / 100 ) ) ! = 2 ) {
return false ;
}
// Cache-Control: no-store.
bool isNoStoreResponse = false ;
httpChannel - > IsNoStoreResponse ( & isNoStoreResponse ) ;
if ( isNoStoreResponse ) {
return false ;
}
// Deny storage if we're viewing a HTTPS page with a
// 'Cache-Control' header having a value that is not 'public'.
nsCOMPtr < nsIURI > uri ;
rv = channel - > GetURI ( getter_AddRefs ( uri ) ) ;
if ( ! NS_SUCCEEDED ( rv ) ) {
return false ;
}
// Don't capture HTTPS pages unless the user enabled it
// or the page has a Cache-Control:public header.
bool isHttps = false ;
uri - > SchemeIs ( " https " , & isHttps ) ;
if ( isHttps & & ! Preferences : : GetBool ( " browser.cache.disk_cache_ssl " , false ) ) {
nsAutoCString cacheControl ;
rv = httpChannel - > GetResponseHeader ( NS_LITERAL_CSTRING ( " Cache-Control " ) , cacheControl ) ;
if ( ! NS_SUCCEEDED ( rv ) ) {
return false ;
}
if ( ! cacheControl . IsEmpty ( ) & & ! cacheControl . LowerCaseEqualsLiteral ( " public " ) ) {
return false ;
}
}
return true ;
}
2012-07-02 19:32:34 +00:00
static void
2010-09-30 15:37:36 +00: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 ) {
2014-01-06 17:54:22 +00:00
AutoLocalJNIFrame jniFrame ( aJNIEnv , 4 ) ;
2012-07-02 19:32:34 +00:00
nsJNIString name (
2012-04-16 22:31:05 +00:00
static_cast < jstring > ( aJNIEnv - > GetObjectArrayElement ( jArr , i ) ) , aJNIEnv ) ;
2010-09-30 15:37:36 +00:00
nsJNIString isDefault (
2012-04-16 22:31:05 +00:00
static_cast < jstring > ( aJNIEnv - > GetObjectArrayElement ( jArr , i + 1 ) ) , aJNIEnv ) ;
2012-07-02 19:32:34 +00:00
nsJNIString packageName (
2012-04-16 22:31:05 +00:00
static_cast < jstring > ( aJNIEnv - > GetObjectArrayElement ( jArr , i + 2 ) ) , aJNIEnv ) ;
2012-07-02 19:32:34 +00:00
nsJNIString className (
2012-04-16 22:31:05 +00:00
static_cast < jstring > ( aJNIEnv - > GetObjectArrayElement ( jArr , i + 3 ) ) , aJNIEnv ) ;
2010-09-30 15:37:36 +00:00
nsIHandlerApp * app = nsOSHelperAppService : :
CreateAndroidHandlerApp ( name , className , packageName ,
className , aMimeType , aAction ) ;
2012-07-02 19:32:34 +00:00
2011-10-17 14:59:28 +00:00
aHandlersArray - > AppendElement ( app , false ) ;
2010-09-30 15:37:36 +00:00
if ( aDefaultApp & & isDefault . Length ( ) > 0 )
* aDefaultApp = app ;
}
}
2011-09-29 06:19:26 +00:00
bool
2013-09-09 12:57:36 +00:00
AndroidBridge : : GetHandlersForMimeType ( const nsAString & aMimeType ,
2010-09-30 15:37:36 +00:00
nsIMutableArray * aHandlersArray ,
nsIHandlerApp * * aDefaultApp ,
const nsAString & aAction )
2010-06-14 19:04:16 +00:00
{
2011-03-01 04:25:11 +00:00
ALOG_BRIDGE ( " AndroidBridge::GetHandlersForMimeType " ) ;
2015-01-10 00:33:57 +00:00
auto arr = GeckoAppShell : : GetHandlersForMimeTypeWrapper ( aMimeType , aAction ) ;
2010-06-15 23:39:43 +00:00
if ( ! arr )
2011-10-17 14:59:28 +00:00
return false ;
2010-06-30 02:22:08 +00:00
2015-01-10 00:33:57 +00:00
JNIEnv * const env = arr . Env ( ) ;
jsize len = env - > GetArrayLength ( arr . Get ( ) ) ;
2010-06-30 02:22:08 +00:00
2010-09-30 15:37:36 +00:00
if ( ! aHandlersArray )
2010-06-30 02:22:08 +00:00
return len > 0 ;
2015-01-10 00:33:57 +00:00
getHandlersFromStringArray ( env , arr . Get ( ) , len , aHandlersArray ,
2010-09-30 15:37:36 +00:00
aDefaultApp , aAction ,
2013-09-09 12:57:36 +00:00
NS_ConvertUTF16toUTF8 ( aMimeType ) ) ;
2011-10-17 14:59:28 +00:00
return true ;
2010-06-30 02:22:08 +00:00
}
2011-09-29 06:19:26 +00:00
bool
2013-09-09 12:57:36 +00:00
AndroidBridge : : GetHandlersForURL ( const nsAString & aURL ,
2011-09-30 07:00:48 +00:00
nsIMutableArray * aHandlersArray ,
nsIHandlerApp * * aDefaultApp ,
const nsAString & aAction )
2010-06-30 02:22:08 +00:00
{
2011-03-01 04:25:11 +00:00
ALOG_BRIDGE ( " AndroidBridge::GetHandlersForURL " ) ;
2015-01-10 00:33:57 +00:00
auto arr = GeckoAppShell : : GetHandlersForURLWrapper ( aURL , aAction ) ;
2010-06-30 02:22:08 +00:00
if ( ! arr )
2011-10-17 14:59:28 +00:00
return false ;
2010-06-30 02:22:08 +00:00
2015-01-10 00:33:57 +00:00
JNIEnv * const env = arr . Env ( ) ;
jsize len = env - > GetArrayLength ( arr . Get ( ) ) ;
2010-06-30 02:22:08 +00:00
2010-09-30 15:37:36 +00:00
if ( ! aHandlersArray )
2010-06-30 02:22:08 +00:00
return len > 0 ;
2015-01-10 00:33:57 +00:00
getHandlersFromStringArray ( env , arr . Get ( ) , len , aHandlersArray ,
2010-09-30 15:37:36 +00:00
aDefaultApp , aAction ) ;
2013-09-09 12:57:37 +00:00
return true ;
2010-06-14 19:04:16 +00:00
}
void
2011-03-01 04:25:11 +00:00
AndroidBridge : : GetMimeTypeFromExtensions ( const nsACString & aFileExt , nsCString & aMimeType )
{
ALOG_BRIDGE ( " AndroidBridge::GetMimeTypeFromExtensions " ) ;
2015-01-10 00:33:57 +00:00
auto jstrType = GeckoAppShell : : GetMimeTypeFromExtensionsWrapper ( aFileExt ) ;
2012-01-29 20:39:30 +00:00
2015-01-10 00:33:57 +00:00
if ( jstrType ) {
aMimeType = jstrType ;
2013-09-09 12:57:37 +00:00
}
2010-06-14 19:04:16 +00:00
}
2011-03-08 05:45:43 +00:00
void
2011-09-15 07:40:17 +00:00
AndroidBridge : : GetExtensionFromMimeType ( const nsACString & aMimeType , nsACString & aFileExt )
2011-03-08 05:45:43 +00:00
{
ALOG_BRIDGE ( " AndroidBridge::GetExtensionFromMimeType " ) ;
2015-01-10 00:33:57 +00:00
auto jstrExt = GeckoAppShell : : GetExtensionFromMimeTypeWrapper ( aMimeType ) ;
2012-01-29 20:39:30 +00:00
2015-01-10 00:33:57 +00:00
if ( jstrExt ) {
aFileExt = nsCString ( jstrExt ) ;
2013-09-09 12:57:37 +00:00
}
2010-06-16 17:20:54 +00:00
}
2010-08-26 23:43:23 +00:00
bool
AndroidBridge : : GetClipboardText ( nsAString & aText )
{
2011-03-01 04:25:11 +00:00
ALOG_BRIDGE ( " AndroidBridge::GetClipboardText " ) ;
2015-01-10 00:33:57 +00:00
auto text = Clipboard : : GetClipboardTextWrapper ( ) ;
2012-01-29 20:39:30 +00:00
2015-01-10 00:33:57 +00:00
if ( text ) {
aText = nsString ( text ) ;
}
return ! ! text ;
2010-08-26 23:43:23 +00:00
}
2010-06-15 02:17:37 +00:00
void
AndroidBridge : : ShowAlertNotification ( const nsAString & aImageUrl ,
const nsAString & aAlertTitle ,
const nsAString & aAlertText ,
const nsAString & aAlertCookie ,
nsIObserver * aAlertListener ,
const nsAString & aAlertName )
{
2013-08-02 18:04:49 +00:00
if ( nsAppShell : : gAppShell & & aAlertListener ) {
// This will remove any observers already registered for this id
2013-09-05 19:32:04 +00:00
nsAppShell : : gAppShell - > PostEvent ( AndroidGeckoEvent : : MakeAddObserver ( aAlertName , aAlertListener ) ) ;
2013-08-02 18:04:49 +00:00
}
2010-06-15 02:17:37 +00:00
2015-01-10 00:33:57 +00:00
GeckoAppShell : : ShowAlertNotificationWrapper
2014-04-01 12:29:25 +00:00
( aImageUrl , aAlertTitle , aAlertText , aAlertCookie , aAlertName ) ;
2010-06-15 02:17:37 +00:00
}
2010-10-07 17:28:27 +00:00
int
AndroidBridge : : GetDPI ( )
{
2012-09-28 19:05:50 +00:00
static int sDPI = 0 ;
if ( sDPI )
return sDPI ;
const int DEFAULT_DPI = 160 ;
2012-01-29 20:39:30 +00:00
2015-01-10 00:33:57 +00:00
sDPI = GeckoAppShell : : GetDpiWrapper ( ) ;
2013-09-09 12:57:37 +00:00
if ( ! sDPI ) {
2012-05-04 15:08:47 +00:00
return DEFAULT_DPI ;
2012-09-28 19:05:50 +00:00
}
2012-05-04 15:08:47 +00:00
2012-09-28 19:05:50 +00:00
return sDPI ;
2010-10-07 17:28:27 +00:00
}
2013-07-04 13:53:25 +00:00
int
AndroidBridge : : GetScreenDepth ( )
{
2013-09-09 12:57:37 +00:00
ALOG_BRIDGE ( " %s " , __PRETTY_FUNCTION__ ) ;
2013-07-04 13:53:25 +00:00
static int sDepth = 0 ;
if ( sDepth )
return sDepth ;
const int DEFAULT_DEPTH = 16 ;
2014-01-18 05:32:24 +00:00
if ( HasEnv ( ) ) {
2015-01-10 00:33:57 +00:00
sDepth = GeckoAppShell : : GetScreenDepthWrapper ( ) ;
2014-01-18 05:32:24 +00:00
}
2013-09-09 12:57:37 +00:00
if ( ! sDepth )
2013-07-04 13:53:25 +00:00
return DEFAULT_DEPTH ;
return sDepth ;
}
2010-11-22 16:38:02 +00:00
void
2013-09-09 12:57:37 +00:00
AndroidBridge : : Vibrate ( const nsTArray < uint32_t > & aPattern )
2010-11-22 16:38:02 +00:00
{
2013-09-09 12:57:37 +00:00
ALOG_BRIDGE ( " %s " , __PRETTY_FUNCTION__ ) ;
2012-01-29 20:39:30 +00:00
2013-09-09 12:57:37 +00:00
uint32_t len = aPattern . Length ( ) ;
if ( ! len ) {
ALOG_BRIDGE ( " invalid 0-length array " ) ;
2012-01-29 20:39:30 +00:00
return ;
2013-09-09 12:57:37 +00:00
}
2012-01-29 20:39:30 +00:00
2011-09-30 07:00:48 +00: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 ;
}
2015-01-10 00:33:57 +00:00
GeckoAppShell : : Vibrate1 ( d ) ;
2012-05-04 15:08:45 +00:00
return ;
2011-09-30 07:00:48 +00:00
}
// First element of the array vibrate() expects is how long to wait
// *before* vibrating. For us, this is always 0.
2015-01-10 00:33:57 +00:00
JNIEnv * env = GetJNIEnv ( ) ;
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2012-01-29 20:39:30 +00:00
jlongArray array = env - > NewLongArray ( len + 1 ) ;
2011-09-30 07:00:48 +00:00
if ( ! array ) {
ALOG_BRIDGE ( " failed to allocate array " ) ;
return ;
}
2012-07-30 14:20:58 +00:00
jlong * elts = env - > GetLongArrayElements ( array , nullptr ) ;
2011-09-30 07:00:48 +00:00
elts [ 0 ] = 0 ;
2012-08-22 15:56:38 +00:00
for ( uint32_t i = 0 ; i < aPattern . Length ( ) ; + + i ) {
2011-09-30 07:00:48 +00:00
jlong d = aPattern [ i ] ;
if ( d < 0 ) {
ALOG_BRIDGE ( " invalid vibration duration < 0 " ) ;
2012-01-29 20:39:30 +00:00
env - > ReleaseLongArrayElements ( array , elts , JNI_ABORT ) ;
2011-09-30 07:00:48 +00:00
return ;
}
elts [ i + 1 ] = d ;
}
2012-01-29 20:39:30 +00:00
env - > ReleaseLongArrayElements ( array , elts , 0 ) ;
2011-09-30 07:00:48 +00:00
2015-01-10 00:33:57 +00:00
GeckoAppShell : : VibrateA ( LongArray : : Ref : : From ( array ) , - 1 /* don't repeat */ ) ;
2011-02-27 15:50:56 +00:00
}
2011-03-30 18:04:41 +00:00
void
AndroidBridge : : GetSystemColors ( AndroidSystemColors * aColors )
{
2012-07-30 14:20:58 +00:00
NS_ASSERTION ( aColors ! = nullptr , " AndroidBridge::GetSystemColors: aColors is null! " ) ;
2011-03-30 18:04:41 +00:00
if ( ! aColors )
return ;
2015-01-10 00:33:57 +00:00
auto arr = GeckoAppShell : : GetSystemColoursWrapper ( ) ;
2011-03-30 18:04:41 +00:00
if ( ! arr )
return ;
2015-01-10 00:33:57 +00:00
JNIEnv * const env = arr . Env ( ) ;
uint32_t len = static_cast < uint32_t > ( env - > GetArrayLength ( arr . Get ( ) ) ) ;
jint * elements = env - > GetIntArrayElements ( arr . Get ( ) , 0 ) ;
2011-03-30 18:04:41 +00:00
2012-08-22 15:56:38 +00:00
uint32_t colorsCount = sizeof ( AndroidSystemColors ) / sizeof ( nscolor ) ;
2011-03-30 18:04:41 +00: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 15:56:38 +00: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 16:52:52 +00:00
colors [ i ] = ( androidColor & 0xff00ff00 ) | ( b < < 16 ) | r ;
2011-03-30 18:04:41 +00:00
}
2015-01-10 00:33:57 +00:00
env - > ReleaseIntArrayElements ( arr . Get ( ) , elements , 0 ) ;
2011-03-30 18:04:41 +00:00
}
2011-06-13 21:02:13 +00:00
void
2012-08-22 15:56:38 +00:00
AndroidBridge : : GetIconForExtension ( const nsACString & aFileExt , uint32_t aIconSize , uint8_t * const aBuf )
2011-06-13 21:02:13 +00:00
{
ALOG_BRIDGE ( " AndroidBridge::GetIconForExtension " ) ;
2012-07-30 14:20:58 +00:00
NS_ASSERTION ( aBuf ! = nullptr , " AndroidBridge::GetIconForExtension: aBuf is null! " ) ;
2011-06-13 21:02:13 +00:00
if ( ! aBuf )
return ;
2015-01-10 00:33:57 +00:00
auto arr = GeckoAppShell : : GetIconForExtensionWrapper
2014-04-01 12:29:25 +00:00
( NS_ConvertUTF8toUTF16 ( aFileExt ) , aIconSize ) ;
2012-05-04 15:08:47 +00:00
2012-07-30 14:20:58 +00:00
NS_ASSERTION ( arr ! = nullptr , " AndroidBridge::GetIconForExtension: Returned pixels array is null! " ) ;
2011-06-13 21:02:13 +00:00
if ( ! arr )
return ;
2015-01-10 00:33:57 +00:00
JNIEnv * const env = arr . Env ( ) ;
uint32_t len = static_cast < uint32_t > ( env - > GetArrayLength ( arr . Get ( ) ) ) ;
jbyte * elements = env - > GetByteArrayElements ( arr . Get ( ) , 0 ) ;
2011-06-13 21:02:13 +00:00
2012-08-22 15:56:38 +00:00
uint32_t bufSize = aIconSize * aIconSize * 4 ;
2011-06-13 21:02:13 +00:00
NS_ASSERTION ( len = = bufSize , " AndroidBridge::GetIconForExtension: Pixels array is incomplete! " ) ;
if ( len = = bufSize )
memcpy ( aBuf , elements , bufSize ) ;
2015-01-10 00:33:57 +00:00
env - > ReleaseByteArrayElements ( arr . Get ( ) , elements , 0 ) ;
2011-06-13 21:02:13 +00:00
}
2010-06-03 20:56:36 +00:00
void
2015-01-10 00:33:57 +00:00
AndroidBridge : : SetLayerClient ( GeckoLayerClient : : Param jobj )
2012-02-17 14:16:14 +00:00
{
2012-07-13 14:19:46 +00: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.
2013-10-10 20:42:52 +00:00
bool resetting = ( mLayerClient ! = nullptr ) ;
2012-07-13 14:19:46 +00:00
2015-01-10 00:33:57 +00:00
mLayerClient = jobj ;
2012-07-13 14:19:46 +00:00
if ( resetting ) {
2013-02-04 20:13:17 +00: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 14:19:46 +00:00
}
2010-06-03 20:56:36 +00:00
}
2012-02-06 21:53:09 +00:00
void
2013-02-28 18:28:23 +00:00
AndroidBridge : : RegisterCompositor ( JNIEnv * env )
2012-01-26 19:23:13 +00:00
{
2015-01-10 00:33:57 +00:00
if ( mGLControllerObj ! = nullptr ) {
2013-02-28 18:28:24 +00:00
// we already have this set up, no need to do it again
return ;
}
2015-01-10 00:33:57 +00:00
mGLControllerObj = GLController : : LocalRef (
LayerView : : RegisterCompositorWrapper ( ) ) ;
2012-02-06 21:53:09 +00:00
}
EGLSurface
2013-11-15 16:28:59 +00:00
AndroidBridge : : CreateEGLSurfaceForCompositor ( )
2012-02-06 21:53:09 +00:00
{
2013-02-28 18:28:24 +00:00
if ( ! jEGLSurfacePointerField ) {
2013-10-10 20:42:52 +00:00
return nullptr ;
2013-02-28 18:28:24 +00:00
}
2013-11-15 16:28:59 +00:00
MOZ_ASSERT ( mGLControllerObj , " AndroidBridge::CreateEGLSurfaceForCompositor called with a null GL controller ref " ) ;
2013-02-28 18:28:24 +00:00
2015-01-10 00:33:57 +00:00
auto eglSurface = mGLControllerObj - > CreateEGLSurfaceForCompositorWrapper ( ) ;
if ( ! eglSurface ) {
2013-10-10 20:42:52 +00:00
return nullptr ;
2015-01-10 00:33:57 +00:00
}
2013-02-28 18:28:24 +00:00
2015-01-10 00:33:57 +00:00
JNIEnv * const env = GetJNIForThread ( ) ; // called on the compositor thread
return reinterpret_cast < EGLSurface > (
env - > GetIntField ( eglSurface . Get ( ) , jEGLSurfacePointerField ) ) ;
2012-01-26 19:23:13 +00:00
}
2011-02-28 16:32:05 +00:00
bool
2013-09-09 12:57:36 +00:00
AndroidBridge : : GetStaticIntField ( const char * className , const char * fieldName , int32_t * aInt , JNIEnv * jEnv /* = nullptr */ )
2011-02-28 16:32:05 +00:00
{
2011-03-01 04:25:11 +00:00
ALOG_BRIDGE ( " AndroidBridge::GetStaticIntField %s " , fieldName ) ;
2012-04-27 20:04:47 +00:00
2013-09-09 12:57:36 +00:00
if ( ! jEnv ) {
2014-01-18 05:32:24 +00:00
if ( ! HasEnv ( ) ) {
return false ;
}
2013-09-09 12:57:36 +00:00
jEnv = GetJNIEnv ( ) ;
2012-04-27 20:04:47 +00:00
}
2012-01-29 20:39:30 +00:00
2015-01-10 00:33:56 +00:00
AutoJNIClass cls ( jEnv , className ) ;
jfieldID field = cls . getStaticField ( fieldName , " I " ) ;
2011-02-28 16:32:05 +00:00
2013-09-09 12:57:36 +00:00
if ( ! field ) {
2011-02-28 16:32:05 +00:00
return false ;
2013-09-09 12:57:36 +00:00
}
2011-02-28 16:32:05 +00:00
2015-01-10 00:33:56 +00:00
* aInt = static_cast < int32_t > ( jEnv - > GetStaticIntField ( cls . getRawRef ( ) , field ) ) ;
2011-02-28 16:32:05 +00:00
return true ;
}
2010-09-11 13:20:20 +00:00
bool
2013-09-09 12:57:36 +00:00
AndroidBridge : : GetStaticStringField ( const char * className , const char * fieldName , nsAString & result , JNIEnv * jEnv /* = nullptr */ )
2010-09-11 13:20:20 +00:00
{
2012-05-04 15:08:47 +00:00
ALOG_BRIDGE ( " AndroidBridge::GetStaticStringField %s " , fieldName ) ;
2011-03-01 04:25:11 +00:00
2013-09-09 12:57:36 +00:00
if ( ! jEnv ) {
2014-01-18 05:32:24 +00:00
if ( ! HasEnv ( ) ) {
return false ;
}
2013-09-09 12:57:36 +00:00
jEnv = GetJNIEnv ( ) ;
2012-04-27 20:04:47 +00:00
}
2012-01-29 20:39:30 +00:00
2014-01-06 17:54:22 +00:00
AutoLocalJNIFrame jniFrame ( jEnv , 1 ) ;
2015-01-10 00:33:56 +00:00
AutoJNIClass cls ( jEnv , className ) ;
jfieldID field = cls . getStaticField ( fieldName , " Ljava/lang/String; " ) ;
2010-09-11 13:20:20 +00:00
2013-09-09 12:57:36 +00:00
if ( ! field ) {
2010-09-11 13:20:20 +00:00
return false ;
2013-09-09 12:57:36 +00:00
}
2010-09-11 13:20:20 +00:00
2015-01-10 00:33:56 +00:00
jstring jstr = ( jstring ) jEnv - > GetStaticObjectField ( cls . getRawRef ( ) , field ) ;
2010-09-11 13:20:20 +00:00
if ( ! jstr )
return false ;
2013-09-09 12:57:36 +00:00
result . Assign ( nsJNIString ( jstr , jEnv ) ) ;
2010-09-11 13:20:20 +00:00
return true ;
}
2010-06-03 20:56:36 +00:00
// Available for places elsewhere in the code to link to.
2011-09-29 06:19:26 +00:00
bool
2013-09-09 12:57:37 +00:00
mozilla_AndroidBridge_SetMainThread ( pthread_t thr )
2010-06-03 20:56:36 +00:00
{
return AndroidBridge : : Bridge ( ) - > SetMainThread ( thr ) ;
}
2012-04-27 20:04:47 +00:00
void *
AndroidBridge : : GetNativeSurface ( JNIEnv * env , jobject surface ) {
2013-02-26 14:28:57 +00:00
if ( ! env | | ! mHasNativeWindowFallback | | ! jSurfacePointerField )
2012-07-30 14:20:58 +00:00
return nullptr ;
2012-04-27 20:04:47 +00:00
return ( void * ) env - > GetIntField ( surface , jSurfacePointerField ) ;
}
2011-09-21 16:46:00 +00:00
void
AndroidBridge : : OpenGraphicsLibraries ( )
2011-06-16 09:03:00 +00:00
{
2011-09-21 16:46:00 +00:00
if ( ! mOpenedGraphicsLibraries ) {
2011-06-16 09:03:00 +00:00
// Try to dlopen libjnigraphics.so for direct bitmap access on
// Android 2.2+ (API level 8)
2011-09-21 16:46:00 +00:00
mOpenedGraphicsLibraries = true ;
2011-09-28 18:43:02 +00:00
mHasNativeWindowAccess = false ;
2012-04-27 20:04:47 +00:00
mHasNativeWindowFallback = false ;
2011-09-28 18:43:02 +00:00
mHasNativeBitmapAccess = false ;
2011-06-16 09:03:00 +00:00
2012-01-13 06:23:02 +00:00
void * handle = dlopen ( " libjnigraphics.so " , RTLD_LAZY | RTLD_LOCAL ) ;
2011-09-21 16:46:00 +00: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 09:03:00 +00:00
2011-09-28 18:43:02 +00:00
mHasNativeBitmapAccess = AndroidBitmap_getInfo & & AndroidBitmap_lockPixels & & AndroidBitmap_unlockPixels ;
ALOG_BRIDGE ( " Successfully opened libjnigraphics.so, have native bitmap access? %d " , mHasNativeBitmapAccess ) ;
2011-09-21 16:46:00 +00:00
}
2011-06-16 09:03:00 +00:00
2011-09-21 16:46:00 +00:00
// Try to dlopen libandroid.so for and native window access on
// Android 2.3+ (API level 9)
2012-01-13 06:23:02 +00:00
handle = dlopen ( " libandroid.so " , RTLD_LAZY | RTLD_LOCAL ) ;
2011-09-21 16:46:00 +00: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 " ) ;
2015-04-11 02:14:00 +00:00
ANativeWindow_getWidth = ( int ( * ) ( void * ) ) dlsym ( handle , " ANativeWindow_getWidth " ) ;
ANativeWindow_getHeight = ( int ( * ) ( void * ) ) dlsym ( handle , " ANativeWindow_getHeight " ) ;
2011-09-21 16:46:00 +00:00
2012-07-20 19:20:51 +00: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 18:43:02 +00: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 20:04:47 +00:00
2012-07-20 19:20:51 +00: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 20:04:47 +00: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 15:51:46 +00:00
}
2011-09-21 16:46:00 +00:00
}
2011-08-04 07:32:57 +00:00
namespace mozilla {
class TracerRunnable : public nsRunnable {
public :
TracerRunnable ( ) {
mTracerLock = new Mutex ( " TracerRunnable " ) ;
mTracerCondVar = new CondVar ( * mTracerLock , " TracerRunnable " ) ;
mMainThread = do_GetMainThread ( ) ;
2012-07-02 19:32:34 +00:00
2011-08-04 07:32:57 +00:00
}
~ TracerRunnable ( ) {
delete mTracerCondVar ;
delete mTracerLock ;
2012-07-30 14:20:58 +00:00
mTracerLock = nullptr ;
mTracerCondVar = nullptr ;
2011-08-04 07:32:57 +00:00
}
virtual nsresult Run ( ) {
MutexAutoLock lock ( * mTracerLock ) ;
if ( ! AndroidBridge : : Bridge ( ) )
return NS_OK ;
2012-07-02 19:32:34 +00:00
2012-04-04 09:15:10 +00:00
mHasRun = true ;
2011-08-04 07:32:57 +00:00
mTracerCondVar - > Notify ( ) ;
return NS_OK ;
}
2012-07-02 19:32:34 +00:00
2011-08-04 07:32:57 +00:00
bool Fire ( ) {
if ( ! mTracerLock | | ! mTracerCondVar )
return false ;
MutexAutoLock lock ( * mTracerLock ) ;
2012-04-04 09:15:10 +00:00
mHasRun = false ;
2011-08-04 07:32:57 +00:00
mMainThread - > Dispatch ( this , NS_DISPATCH_NORMAL ) ;
while ( ! mHasRun )
mTracerCondVar - > Wait ( ) ;
return true ;
}
void Signal ( ) {
MutexAutoLock lock ( * mTracerLock ) ;
2012-04-04 09:15:10 +00:00
mHasRun = true ;
2011-08-04 07:32:57 +00:00
mTracerCondVar - > Notify ( ) ;
}
private :
Mutex * mTracerLock ;
CondVar * mTracerCondVar ;
2012-04-04 09:15:10 +00:00
bool mHasRun ;
2011-08-04 07:32:57 +00:00
nsCOMPtr < nsIThread > mMainThread ;
} ;
2013-08-12 14:58:36 +00:00
StaticRefPtr < TracerRunnable > sTracerRunnable ;
2011-08-04 07:32:57 +00:00
bool InitWidgetTracing ( ) {
if ( ! sTracerRunnable )
sTracerRunnable = new TracerRunnable ( ) ;
return true ;
}
void CleanUpWidgetTracing ( ) {
2012-07-30 14:20:58 +00:00
sTracerRunnable = nullptr ;
2011-08-04 07:32:57 +00:00
}
bool FireAndWaitForTracerEvent ( ) {
if ( sTracerRunnable )
return sTracerRunnable - > Fire ( ) ;
return false ;
}
2012-07-02 19:32:34 +00:00
void SignalTracerThread ( )
{
if ( sTracerRunnable )
return sTracerRunnable - > Signal ( ) ;
}
2011-08-04 07:32:57 +00:00
}
2011-09-21 16:46:00 +00:00
bool
AndroidBridge : : HasNativeBitmapAccess ( )
{
OpenGraphicsLibraries ( ) ;
2011-06-16 09:03:00 +00: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 20:39:30 +00:00
JNIEnv * env = GetJNIEnv ( ) ;
if ( ( err = AndroidBitmap_getInfo ( env , bitmap , & info ) ) ! = 0 ) {
2011-06-16 09:03:00 +00:00
ALOG_BRIDGE ( " AndroidBitmap_getInfo failed! (error %d) " , err ) ;
return false ;
}
2012-07-12 16:52:52 +00:00
if ( ( int ) info . width ! = width | | ( int ) info . height ! = height )
2011-06-16 09:03:00 +00:00
return false ;
return true ;
}
2011-09-27 00:25:41 +00:00
bool
2012-08-22 15:56:38 +00:00
AndroidBridge : : InitCamera ( const nsCString & contentType , uint32_t camera , uint32_t * width , uint32_t * height , uint32_t * fps )
2011-09-27 00:25:41 +00:00
{
2015-01-10 00:33:57 +00:00
auto arr = GeckoAppShell : : InitCameraWrapper
2014-07-30 18:08:26 +00:00
( NS_ConvertUTF8toUTF16 ( contentType ) , ( int32_t ) camera , ( int32_t ) * width , ( int32_t ) * height ) ;
2011-09-27 00:25:41 +00:00
if ( ! arr )
return false ;
2015-01-10 00:33:57 +00:00
JNIEnv * const env = arr . Env ( ) ;
jint * elements = env - > GetIntArrayElements ( arr . Get ( ) , 0 ) ;
2011-09-27 00:25:41 +00:00
* width = elements [ 1 ] ;
* height = elements [ 2 ] ;
* fps = elements [ 3 ] ;
bool res = elements [ 0 ] = = 1 ;
2015-01-10 00:33:57 +00:00
env - > ReleaseIntArrayElements ( arr . Get ( ) , elements , 0 ) ;
2011-09-27 00:25:41 +00:00
return res ;
}
2011-11-02 15:35:11 +00:00
void
AndroidBridge : : GetCurrentBatteryInformation ( hal : : BatteryInformation * aBatteryInfo )
{
ALOG_BRIDGE ( " AndroidBridge::GetCurrentBatteryInformation " ) ;
// To prevent calling too many methods through JNI, the Java method returns
2011-11-09 08:56:37 +00:00
// an array of double even if we actually want a double and a boolean.
2015-01-10 00:33:57 +00:00
auto arr = GeckoAppShell : : GetCurrentBatteryInformationWrapper ( ) ;
JNIEnv * const env = arr . Env ( ) ;
if ( ! arr | | env - > GetArrayLength ( arr . Get ( ) ) ! = 3 ) {
2011-11-02 15:35:11 +00:00
return ;
}
2015-01-10 00:33:57 +00:00
jdouble * info = env - > GetDoubleArrayElements ( arr . Get ( ) , 0 ) ;
2011-11-02 15:35:11 +00:00
aBatteryInfo - > level ( ) = info [ 0 ] ;
aBatteryInfo - > charging ( ) = info [ 1 ] = = 1.0f ;
2011-11-09 14:13:37 +00:00
aBatteryInfo - > remainingTime ( ) = info [ 2 ] ;
2011-11-02 15:35:11 +00:00
2015-01-10 00:33:57 +00:00
env - > ReleaseDoubleArrayElements ( arr . Get ( ) , info , 0 ) ;
2011-11-02 15:35:11 +00:00
}
2011-11-15 03:12:14 +00:00
void
2014-04-04 16:33:49 +00:00
AndroidBridge : : HandleGeckoMessage ( JSContext * cx , JS : : HandleObject object )
2011-11-15 03:12:14 +00:00
{
ALOG_BRIDGE ( " %s " , __PRETTY_FUNCTION__ ) ;
2012-01-29 20:39:30 +00:00
2014-04-04 16:33:49 +00:00
JNIEnv * const env = GetJNIEnv ( ) ;
2015-01-10 00:33:57 +00:00
auto message = Object : : LocalRef : : Adopt ( env ,
mozilla : : widget : : CreateNativeJSContainer ( env , cx , object ) ) ;
2014-04-04 16:33:49 +00:00
GeckoAppShell : : HandleGeckoMessageWrapper ( message ) ;
2011-11-15 03:12:14 +00:00
}
2013-01-04 06:26:27 +00:00
nsresult
AndroidBridge : : GetSegmentInfoForText ( const nsAString & aText ,
2013-08-09 13:25:53 +00:00
nsIMobileMessageCallback * aRequest )
2011-11-25 09:48:51 +00:00
{
2013-05-29 04:52:40 +00:00
# ifndef MOZ_WEBSMS_BACKEND
return NS_ERROR_FAILURE ;
# else
2013-01-04 06:26:27 +00:00
ALOG_BRIDGE ( " AndroidBridge::GetSegmentInfoForText " ) ;
2014-08-04 09:01:36 +00:00
int32_t segments , charsPerSegment , charsAvailableInLastSegment ;
2011-11-25 09:48:51 +00:00
2012-01-29 20:39:30 +00:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 17:54:22 +00:00
AutoLocalJNIFrame jniFrame ( env , 2 ) ;
2012-12-13 22:03:44 +00:00
jstring jText = NewJavaString ( & jniFrame , aText ) ;
2013-01-04 06:26:27 +00:00
jobject obj = env - > CallStaticObjectMethod ( mAndroidSmsMessageClass ,
jCalculateLength , jText , JNI_FALSE ) ;
2012-05-04 15:08:47 +00:00
if ( jniFrame . CheckForException ( ) )
2013-01-04 06:26:27 +00:00
return NS_ERROR_FAILURE ;
2012-05-04 15:08:47 +00:00
2013-01-04 06:26:27 +00:00
jintArray arr = static_cast < jintArray > ( obj ) ;
if ( ! arr | | env - > GetArrayLength ( arr ) ! = 4 )
return NS_ERROR_FAILURE ;
jint * info = env - > GetIntArrayElements ( arr , JNI_FALSE ) ;
2014-08-04 09:01:36 +00:00
segments = info [ 0 ] ; // msgCount
charsPerSegment = info [ 2 ] ; // codeUnitsRemaining
2013-01-04 06:26:27 +00:00
// segmentChars = (codeUnitCount + codeUnitsRemaining) / msgCount
2014-08-04 09:01:36 +00:00
charsAvailableInLastSegment = ( info [ 1 ] + info [ 2 ] ) / info [ 0 ] ;
2013-01-04 06:26:27 +00:00
env - > ReleaseIntArrayElements ( arr , info , JNI_ABORT ) ;
2013-08-09 13:25:53 +00:00
// TODO Bug 908598 - Should properly use |QueueSmsRequest(...)| to queue up
// the nsIMobileMessageCallback just like other functions.
2014-08-04 09:01:36 +00:00
return aRequest - > NotifySegmentInfoForTextGot ( segments ,
charsPerSegment ,
charsAvailableInLastSegment ) ;
2013-05-29 04:52:40 +00:00
# endif
2011-11-25 09:48:51 +00:00
}
2011-11-20 23:00:46 +00:00
void
2013-03-09 07:22:02 +00:00
AndroidBridge : : SendMessage ( const nsAString & aNumber ,
const nsAString & aMessage ,
nsIMobileMessageCallback * aRequest )
2011-11-20 23:00:46 +00:00
{
ALOG_BRIDGE ( " AndroidBridge::SendMessage " ) ;
2013-01-25 19:00:00 +00:00
uint32_t requestId ;
if ( ! QueueSmsRequest ( aRequest , & requestId ) )
return ;
2012-11-06 21:32:07 +00:00
2015-01-10 00:33:57 +00:00
GeckoAppShell : : SendMessageWrapper ( aNumber , aMessage , requestId ) ;
2011-11-20 23:00:46 +00:00
}
2011-12-22 22:08:58 +00:00
void
2013-03-09 07:22:02 +00:00
AndroidBridge : : GetMessage ( int32_t aMessageId , nsIMobileMessageCallback * aRequest )
2011-12-22 22:08:58 +00:00
{
ALOG_BRIDGE ( " AndroidBridge::GetMessage " ) ;
2013-01-25 19:00:00 +00:00
uint32_t requestId ;
if ( ! QueueSmsRequest ( aRequest , & requestId ) )
return ;
2012-11-06 21:32:07 +00:00
2015-01-10 00:33:57 +00:00
GeckoAppShell : : GetMessageWrapper ( aMessageId , requestId ) ;
2011-12-22 22:08:58 +00:00
}
2011-12-22 22:15:28 +00:00
void
2013-03-09 07:22:02 +00:00
AndroidBridge : : DeleteMessage ( int32_t aMessageId , nsIMobileMessageCallback * aRequest )
2011-12-22 22:15:28 +00:00
{
ALOG_BRIDGE ( " AndroidBridge::DeleteMessage " ) ;
2013-01-25 19:00:00 +00:00
uint32_t requestId ;
if ( ! QueueSmsRequest ( aRequest , & requestId ) )
return ;
2012-11-06 21:32:07 +00:00
2015-01-10 00:33:57 +00:00
GeckoAppShell : : DeleteMessageWrapper ( aMessageId , requestId ) ;
2011-12-22 22:15:28 +00:00
}
2011-12-20 08:07:25 +00:00
void
2013-03-01 08:38:47 +00:00
AndroidBridge : : CreateMessageList ( const dom : : mobilemessage : : SmsFilterData & aFilter , bool aReverse ,
2013-03-09 07:22:02 +00:00
nsIMobileMessageCallback * aRequest )
2011-12-20 08:07:25 +00:00
{
ALOG_BRIDGE ( " AndroidBridge::CreateMessageList " ) ;
2012-01-29 20:39:30 +00:00
JNIEnv * env = GetJNIEnv ( ) ;
2013-01-25 19:00:00 +00:00
uint32_t requestId ;
if ( ! QueueSmsRequest ( aRequest , & requestId ) )
return ;
2012-11-06 21:32:07 +00:00
2014-01-06 17:54:22 +00:00
AutoLocalJNIFrame jniFrame ( env , 2 ) ;
2011-12-20 08:07:25 +00:00
jobjectArray numbers =
2012-05-04 15:08:45 +00:00
( jobjectArray ) env - > NewObjectArray ( aFilter . numbers ( ) . Length ( ) ,
2012-07-02 19:32:34 +00:00
jStringClass ,
2012-12-13 22:03:44 +00:00
NewJavaString ( & jniFrame , EmptyString ( ) ) ) ;
2011-12-20 08:07:25 +00:00
2013-09-09 12:57:37 +00:00
for ( uint32_t i = 0 ; i < aFilter . numbers ( ) . Length ( ) ; + + i ) {
2014-01-06 17:54:22 +00:00
jstring elem = NewJavaString ( & jniFrame , aFilter . numbers ( ) [ i ] ) ;
env - > SetObjectArrayElement ( numbers , i , elem ) ;
env - > DeleteLocalRef ( elem ) ;
2013-09-09 12:57:37 +00:00
}
2012-11-06 21:32:07 +00:00
2014-08-28 03:00:03 +00:00
int64_t startDate = aFilter . hasStartDate ( ) ? aFilter . startDate ( ) : - 1 ;
int64_t endDate = aFilter . hasEndDate ( ) ? aFilter . endDate ( ) : - 1 ;
GeckoAppShell : : CreateMessageListWrapper ( startDate , endDate ,
2015-01-10 00:33:57 +00:00
ObjectArray : : Ref : : From ( numbers ) ,
aFilter . numbers ( ) . Length ( ) ,
2014-08-28 03:00:03 +00:00
aFilter . delivery ( ) ,
aFilter . hasRead ( ) , aFilter . read ( ) ,
aFilter . threadId ( ) ,
aReverse , requestId ) ;
2011-12-22 22:16:59 +00:00
}
2012-01-17 18:43:08 +00:00
void
2013-09-09 12:57:37 +00:00
AndroidBridge : : GetNextMessageInList ( int32_t aListId , nsIMobileMessageCallback * aRequest )
2012-01-17 18:43:08 +00:00
{
2013-09-09 12:57:37 +00:00
ALOG_BRIDGE ( " AndroidBridge::GetNextMessageInList " ) ;
2012-01-17 18:43:08 +00:00
2013-09-09 12:57:37 +00:00
uint32_t requestId ;
if ( ! QueueSmsRequest ( aRequest , & requestId ) )
2012-01-29 20:39:30 +00:00
return ;
2015-01-10 00:33:57 +00:00
GeckoAppShell : : GetNextMessageInListWrapper ( aListId , requestId ) ;
2012-01-17 18:43:08 +00:00
}
2013-01-25 19:00:00 +00:00
bool
2013-03-09 07:22:02 +00:00
AndroidBridge : : QueueSmsRequest ( nsIMobileMessageCallback * aRequest , uint32_t * aRequestIdOut )
2012-11-06 21:32:07 +00:00
{
2013-01-25 19:00:00 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) , " Wrong thread! " ) ;
MOZ_ASSERT ( aRequest & & aRequestIdOut ) ;
2012-11-08 16:37:13 +00:00
2013-04-08 14:29:34 +00:00
const uint32_t length = mSmsRequests . Length ( ) ;
2013-01-25 19:00:00 +00:00
for ( uint32_t i = 0 ; i < length ; i + + ) {
2013-04-08 14:29:34 +00:00
if ( ! ( mSmsRequests ) [ i ] ) {
( mSmsRequests ) [ i ] = aRequest ;
2013-01-25 19:00:00 +00:00
* aRequestIdOut = i ;
return true ;
2012-11-06 21:32:07 +00:00
}
}
2013-04-08 14:29:34 +00:00
mSmsRequests . AppendElement ( aRequest ) ;
2012-11-06 21:32:07 +00:00
2013-01-25 19:00:00 +00:00
// After AppendElement(), previous `length` points to the new tail element.
* aRequestIdOut = length ;
return true ;
2012-11-06 21:32:07 +00:00
}
2013-03-09 07:22:02 +00:00
already_AddRefed < nsIMobileMessageCallback >
2013-01-25 19:00:00 +00:00
AndroidBridge : : DequeueSmsRequest ( uint32_t aRequestId )
2012-11-06 21:32:07 +00:00
{
2013-01-25 19:00:00 +00:00
MOZ_ASSERT ( NS_IsMainThread ( ) , " Wrong thread! " ) ;
2013-04-08 14:29:34 +00:00
MOZ_ASSERT ( aRequestId < mSmsRequests . Length ( ) ) ;
if ( aRequestId > = mSmsRequests . Length ( ) ) {
2012-11-06 21:32:07 +00:00
return nullptr ;
}
2013-04-08 14:29:34 +00:00
return mSmsRequests [ aRequestId ] . forget ( ) ;
2012-11-06 21:32:07 +00:00
}
2012-01-16 13:44:07 +00:00
void
AndroidBridge : : GetCurrentNetworkInformation ( hal : : NetworkInformation * aNetworkInfo )
{
ALOG_BRIDGE ( " AndroidBridge::GetCurrentNetworkInformation " ) ;
// To prevent calling too many methods through JNI, the Java method returns
2014-03-05 09:42:42 +00:00
// an array of double even if we actually want an integer, a boolean, and an integer.
2012-05-04 15:08:47 +00:00
2015-01-10 00:33:57 +00:00
auto arr = GeckoAppShell : : GetCurrentNetworkInformationWrapper ( ) ;
JNIEnv * const env = arr . Env ( ) ;
if ( ! arr | | env - > GetArrayLength ( arr . Get ( ) ) ! = 3 ) {
2012-01-16 13:44:07 +00:00
return ;
}
2015-01-10 00:33:57 +00:00
jdouble * info = env - > GetDoubleArrayElements ( arr . Get ( ) , 0 ) ;
2012-01-16 13:44:07 +00:00
2014-03-05 09:42:42 +00:00
aNetworkInfo - > type ( ) = info [ 0 ] ;
aNetworkInfo - > isWifi ( ) = info [ 1 ] = = 1.0f ;
aNetworkInfo - > dhcpGateway ( ) = info [ 2 ] ;
2012-01-16 13:44:07 +00:00
2015-01-10 00:33:57 +00:00
env - > ReleaseDoubleArrayElements ( arr . Get ( ) , info , 0 ) ;
2012-01-16 13:44:07 +00:00
}
2011-06-16 09:03:00 +00:00
void *
AndroidBridge : : LockBitmap ( jobject bitmap )
{
2012-01-29 20:39:30 +00:00
JNIEnv * env = GetJNIEnv ( ) ;
2012-05-04 15:08:47 +00:00
int err ;
void * buf ;
2012-01-29 20:39:30 +00:00
if ( ( err = AndroidBitmap_lockPixels ( env , bitmap , & buf ) ) ! = 0 ) {
2011-06-16 09:03:00 +00:00
ALOG_BRIDGE ( " AndroidBitmap_lockPixels failed! (error %d) " , err ) ;
2012-07-30 14:20:58 +00:00
buf = nullptr ;
2011-06-16 09:03:00 +00:00
}
return buf ;
}
void
AndroidBridge : : UnlockBitmap ( jobject bitmap )
{
2012-01-29 20:39:30 +00:00
JNIEnv * env = GetJNIEnv ( ) ;
2012-05-04 15:08:47 +00:00
int err ;
2012-01-29 20:39:30 +00:00
if ( ( err = AndroidBitmap_unlockPixels ( env , bitmap ) ) ! = 0 )
2011-06-16 09:03:00 +00:00
ALOG_BRIDGE ( " AndroidBitmap_unlockPixels failed! (error %d) " , err ) ;
}
2011-09-21 16:46:00 +00:00
bool
AndroidBridge : : HasNativeWindowAccess ( )
{
OpenGraphicsLibraries ( ) ;
2012-04-27 20:04:47 +00:00
// We have a fallback hack in place, so return true if that will work as well
return mHasNativeWindowAccess | | mHasNativeWindowFallback ;
2011-09-21 16:46:00 +00:00
}
void *
2012-04-27 20:04:47 +00:00
AndroidBridge : : AcquireNativeWindow ( JNIEnv * aEnv , jobject aSurface )
2011-09-21 16:46:00 +00:00
{
2012-04-27 20:04:47 +00:00
OpenGraphicsLibraries ( ) ;
2011-09-21 16:46:00 +00:00
2012-04-27 20:04:47 +00:00
if ( mHasNativeWindowAccess )
return ANativeWindow_fromSurface ( aEnv , aSurface ) ;
2012-07-20 19:20:51 +00:00
if ( mHasNativeWindowFallback )
2012-04-27 20:04:47 +00:00
return GetNativeSurface ( aEnv , aSurface ) ;
2012-07-20 19:20:51 +00:00
2012-07-30 14:20:58 +00:00
return nullptr ;
2011-09-21 16:46:00 +00:00
}
void
AndroidBridge : : ReleaseNativeWindow ( void * window )
{
if ( ! window )
return ;
2012-04-27 20:04:47 +00: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 16:46:00 +00:00
}
2015-04-11 02:14:00 +00:00
IntSize
AndroidBridge : : GetNativeWindowSize ( void * window )
{
if ( ! window | | ! ANativeWindow_getWidth | | ! ANativeWindow_getHeight ) {
return IntSize ( 0 , 0 ) ;
}
return IntSize ( ANativeWindow_getWidth ( window ) , ANativeWindow_getHeight ( window ) ) ;
}
2012-07-20 19:20:51 +00: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 14:20:58 +00:00
return nullptr ;
2012-07-20 19:20:51 +00: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 16:46:00 +00: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 20:04:47 +00: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 16:52:52 +00:00
struct SurfaceInfo {
2012-04-27 20:04:47 +00: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 16:46:00 +00:00
2012-04-27 20:04:47 +00:00
int err ;
2013-10-10 20:42:52 +00:00
* bits = nullptr ;
2011-09-21 16:46:00 +00:00
* width = * height = * format = 0 ;
2012-07-02 19:32:34 +00:00
2012-04-27 20:04:47 +00:00
if ( mHasNativeWindowAccess ) {
ANativeWindow_Buffer buffer ;
2011-09-21 16:46:00 +00:00
2013-10-10 20:42:52 +00:00
if ( ( err = ANativeWindow_lock ( window , ( void * ) & buffer , nullptr ) ) ! = 0 ) {
2012-04-27 20:04:47 +00:00
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 ;
2013-10-10 20:42:52 +00:00
if ( ( err = Surface_lock ( window , & info , nullptr , true ) ) ! = 0 ) {
2012-04-27 20:04:47 +00:00
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 16:46:00 +00:00
return true ;
}
2013-05-28 16:49:04 +00:00
jobject
AndroidBridge : : GetGlobalContextRef ( ) {
2015-01-10 00:33:57 +00:00
if ( sGlobalContext ) {
return sGlobalContext ;
}
2013-05-28 16:49:04 +00:00
2015-01-10 00:33:57 +00:00
JNIEnv * const env = GetJNIForThread ( ) ;
AutoLocalJNIFrame jniFrame ( env , 4 ) ;
2013-05-28 16:49:04 +00:00
2015-01-10 00:33:57 +00:00
auto 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 ;
}
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 . Get ( ) , mid ) ;
if ( ! appContext ) {
ALOG_BRIDGE ( " %s: getApplicationContext failed. " , __FUNCTION__ ) ;
return 0 ;
2013-09-25 06:06:21 +00:00
}
2013-02-09 21:38:08 +00:00
2015-01-10 00:33:57 +00:00
sGlobalContext = env - > NewGlobalRef ( appContext ) ;
MOZ_ASSERT ( sGlobalContext ) ;
2013-09-25 06:06:21 +00:00
return sGlobalContext ;
2013-02-09 21:38:08 +00:00
}
2011-09-21 16:46:00 +00:00
bool
AndroidBridge : : UnlockWindow ( void * window )
{
int err ;
2012-04-27 20:04:47 +00:00
if ( ! HasNativeWindowAccess ( ) )
return false ;
if ( mHasNativeWindowAccess & & ( err = ANativeWindow_unlockAndPost ( window ) ) ! = 0 ) {
2011-09-21 16:46:00 +00:00
ALOG_BRIDGE ( " ANativeWindow_unlockAndPost failed! (error %d) " , err ) ;
return false ;
2012-04-27 20:04:47 +00:00
} else if ( mHasNativeWindowFallback & & ( err = Surface_unlockAndPost ( window ) ) ! = 0 ) {
ALOG_BRIDGE ( " Surface_unlockAndPost failed! (error %d) " , err ) ;
return false ;
2011-09-21 16:46:00 +00:00
}
return true ;
}
2011-10-11 00:40:17 +00:00
2012-03-12 15:50:21 +00:00
void
2013-06-21 21:03:56 +00:00
AndroidBridge : : SetFirstPaintViewport ( const LayerIntPoint & aOffset , const CSSToLayerScale & aZoom , const CSSRect & aCssPageRect )
2012-03-12 15:50:21 +00:00
{
2015-01-10 00:33:57 +00:00
if ( ! mLayerClient ) {
2012-03-12 15:50:21 +00:00
return ;
2015-01-10 00:33:57 +00:00
}
2012-03-12 15:50:21 +00:00
2015-01-10 00:33:57 +00:00
mLayerClient - > SetFirstPaintViewport ( float ( aOffset . x ) , float ( aOffset . y ) , aZoom . scale ,
aCssPageRect . x , aCssPageRect . y , aCssPageRect . XMost ( ) , aCssPageRect . YMost ( ) ) ;
2012-03-12 15:50:21 +00:00
}
void
2013-06-03 13:52:44 +00:00
AndroidBridge : : SetPageRect ( const CSSRect & aCssPageRect )
2012-03-12 15:50:21 +00:00
{
2015-01-10 00:33:57 +00:00
if ( ! mLayerClient ) {
2012-03-12 15:50:21 +00:00
return ;
2015-01-10 00:33:57 +00:00
}
2012-03-12 15:50:21 +00:00
2015-01-10 00:33:57 +00:00
mLayerClient - > SetPageRect ( aCssPageRect . x , aCssPageRect . y ,
aCssPageRect . XMost ( ) , aCssPageRect . YMost ( ) ) ;
2012-03-12 15:50:21 +00:00
}
2012-02-04 02:35:58 +00:00
void
2013-06-21 21:03:56 +00:00
AndroidBridge : : SyncViewportInfo ( const LayerIntRect & aDisplayPort , const CSSToLayerScale & aDisplayResolution ,
2014-11-10 19:35:11 +00:00
bool aLayersUpdated , ParentLayerPoint & aScrollOffset , CSSToParentLayerScale & aScale ,
2013-07-22 08:50:13 +00:00
LayerMargin & aFixedLayerMargins , ScreenPoint & aOffset )
2012-02-04 02:35:58 +00:00
{
2015-01-10 00:33:57 +00:00
if ( ! mLayerClient ) {
2013-11-12 18:41:01 +00:00
ALOG_BRIDGE ( " Exceptional Exit: %s " , __PRETTY_FUNCTION__ ) ;
return ;
}
2015-01-10 00:33:57 +00:00
ViewTransform : : LocalRef viewTransform = mLayerClient - > SyncViewportInfo (
aDisplayPort . x , aDisplayPort . y ,
aDisplayPort . width , aDisplayPort . height ,
aDisplayResolution . scale , aLayersUpdated ) ;
2013-11-12 18:41:01 +00:00
2015-02-09 22:34:50 +00:00
MOZ_ASSERT ( viewTransform , " No view transform object! " ) ;
2012-03-14 04:15:11 +00:00
2015-01-10 00:33:57 +00:00
aScrollOffset = ParentLayerPoint ( viewTransform - > X ( ) , viewTransform - > Y ( ) ) ;
aScale . scale = viewTransform - > Scale ( ) ;
aFixedLayerMargins . top = viewTransform - > FixedLayerMarginTop ( ) ;
aFixedLayerMargins . right = viewTransform - > FixedLayerMarginRight ( ) ;
aFixedLayerMargins . bottom = viewTransform - > FixedLayerMarginBottom ( ) ;
aFixedLayerMargins . left = viewTransform - > FixedLayerMarginLeft ( ) ;
aOffset . x = viewTransform - > OffsetX ( ) ;
aOffset . y = viewTransform - > OffsetY ( ) ;
2012-02-04 02:35:58 +00:00
}
2014-11-10 19:35:11 +00:00
void AndroidBridge : : SyncFrameMetrics ( const ParentLayerPoint & aScrollOffset , float aZoom , const CSSRect & aCssPageRect ,
2013-06-21 21:03:56 +00:00
bool aLayersUpdated , const CSSRect & aDisplayPort , const CSSToLayerScale & aDisplayResolution ,
2013-07-22 08:50:13 +00:00
bool aIsFirstPaint , LayerMargin & aFixedLayerMargins , ScreenPoint & aOffset )
2013-04-26 17:26:39 +00:00
{
2015-01-10 00:33:57 +00:00
if ( ! mLayerClient ) {
2013-11-12 18:41:01 +00:00
ALOG_BRIDGE ( " Exceptional Exit: %s " , __PRETTY_FUNCTION__ ) ;
2013-04-26 17:26:39 +00:00
return ;
2013-11-12 18:41:01 +00:00
}
2013-04-26 17:26:39 +00:00
2013-11-12 18:41:01 +00:00
// 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 ) ;
2015-01-10 00:33:57 +00:00
ViewTransform : : LocalRef viewTransform = mLayerClient - > 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 ) ;
2013-11-12 18:41:01 +00:00
2015-02-09 22:34:50 +00:00
MOZ_ASSERT ( viewTransform , " No view transform object! " ) ;
2013-11-12 18:41:01 +00:00
2015-01-10 00:33:57 +00:00
aFixedLayerMargins . top = viewTransform - > FixedLayerMarginTop ( ) ;
aFixedLayerMargins . right = viewTransform - > FixedLayerMarginRight ( ) ;
aFixedLayerMargins . bottom = viewTransform - > FixedLayerMarginBottom ( ) ;
aFixedLayerMargins . left = viewTransform - > FixedLayerMarginLeft ( ) ;
2013-11-12 18:41:01 +00:00
2015-01-10 00:33:57 +00:00
aOffset . x = viewTransform - > OffsetX ( ) ;
aOffset . y = viewTransform - > OffsetY ( ) ;
2013-04-26 17:26:39 +00:00
}
2012-07-13 21:34:58 +00:00
AndroidBridge : : AndroidBridge ( )
2015-04-11 02:14:00 +00:00
: mLayerClient ( nullptr ) ,
mPresentationWindow ( nullptr ) ,
mPresentationSurface ( nullptr )
2012-07-13 21:34:58 +00:00
{
}
AndroidBridge : : ~ AndroidBridge ( )
{
}
2011-10-11 00:40:17 +00:00
/* Implementation file */
2014-04-27 07:06:00 +00:00
NS_IMPL_ISUPPORTS ( nsAndroidBridge , nsIAndroidBridge )
2011-10-11 00:40:17 +00:00
nsAndroidBridge : : nsAndroidBridge ( )
{
}
nsAndroidBridge : : ~ nsAndroidBridge ( )
{
}
/* void handleGeckoEvent (in AString message); */
2014-04-04 16:33:49 +00:00
NS_IMETHODIMP nsAndroidBridge : : HandleGeckoMessage ( JS : : HandleValue val ,
JSContext * cx )
2011-10-11 00:40:17 +00:00
{
2014-04-04 16:33:49 +00:00
if ( val . isObject ( ) ) {
JS : : RootedObject object ( cx , & val . toObject ( ) ) ;
AndroidBridge : : Bridge ( ) - > HandleGeckoMessage ( cx , object ) ;
return NS_OK ;
}
// Now handle legacy JSON messages.
if ( ! val . isString ( ) ) {
return NS_ERROR_INVALID_ARG ;
}
JS : : RootedString jsonStr ( cx , val . toString ( ) ) ;
JS : : RootedValue jsonVal ( cx ) ;
2014-07-14 13:01:32 +00:00
if ( ! JS_ParseJSON ( cx , jsonStr , & jsonVal ) | | ! jsonVal . isObject ( ) ) {
2014-04-04 16:33:49 +00:00
return NS_ERROR_INVALID_ARG ;
}
// Spit out a warning before sending the message.
nsContentUtils : : ReportToConsoleNonLocalized (
NS_LITERAL_STRING ( " Use of JSON is deprecated. "
" Please pass Javascript objects directly to handleGeckoMessage. " ) ,
nsIScriptError : : warningFlag ,
NS_LITERAL_CSTRING ( " nsIAndroidBridge " ) ,
nullptr ) ;
JS : : RootedObject object ( cx , & jsonVal . toObject ( ) ) ;
AndroidBridge : : Bridge ( ) - > HandleGeckoMessage ( cx , object ) ;
2011-10-11 00:40:17 +00:00
return NS_OK ;
}
2011-11-18 03:20:29 +00:00
2013-05-30 13:55:08 +00: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 13:55:23 +00: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 20:39:30 +00: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 ;
2014-01-24 17:04:15 +00:00
MOZ_ASSERT ( env , " No JNIEnv on Gecko thread " ) ;
if ( ! env ) {
return ;
}
2013-10-10 20:42:52 +00:00
JavaVM * vm = nullptr ;
2012-01-29 20:39:30 +00:00
env - > GetJavaVM ( & vm ) ;
2014-01-24 17:04:15 +00:00
MOZ_ASSERT ( vm , " No JavaVM on Gecko thread " ) ;
if ( ! vm ) {
return ;
}
2012-01-29 20:39:30 +00:00
vm - > DetachCurrentThread ( ) ;
}
2012-05-08 21:36:07 +00:00
uint32_t
AndroidBridge : : GetScreenOrientation ( )
2012-03-20 13:09:45 +00:00
{
ALOG_BRIDGE ( " AndroidBridge::GetScreenOrientation " ) ;
2012-05-04 15:08:47 +00:00
2015-01-10 00:33:57 +00:00
int16_t orientation = GeckoAppShell : : GetScreenOrientationWrapper ( ) ;
2012-05-04 15:08:47 +00:00
2013-09-09 12:57:37 +00:00
if ( ! orientation )
2012-05-08 21:36:07 +00:00
return dom : : eScreenOrientation_None ;
2012-05-04 15:08:47 +00:00
2012-05-08 21:36:07 +00:00
return static_cast < dom : : ScreenOrientation > ( orientation ) ;
2012-03-20 13:09:45 +00:00
}
2012-07-20 19:20:51 +00:00
void
2015-06-11 15:20:04 +00:00
AndroidBridge : : InvalidateAndScheduleComposite ( )
2012-07-20 19:20:51 +00:00
{
2015-06-11 15:20:04 +00:00
nsWindow : : InvalidateAndScheduleComposite ( ) ;
2012-07-20 19:20:51 +00:00
}
2012-11-13 19:25:18 +00:00
nsresult
AndroidBridge : : GetProxyForURI ( const nsACString & aSpec ,
const nsACString & aScheme ,
const nsACString & aHost ,
const int32_t aPort ,
nsACString & aResult )
{
2014-01-18 05:32:24 +00:00
if ( ! HasEnv ( ) ) {
return NS_ERROR_FAILURE ;
}
2012-11-13 19:25:18 +00:00
2015-01-10 00:33:57 +00:00
auto jstrRet = GeckoAppShell : : GetProxyForURIWrapper ( aSpec , aScheme , aHost , aPort ) ;
2012-11-13 19:25:18 +00:00
2013-09-09 12:57:37 +00:00
if ( ! jstrRet )
2012-11-13 19:25:18 +00:00
return NS_ERROR_FAILURE ;
2015-01-10 00:33:57 +00:00
aResult = nsCString ( jstrRet ) ;
2012-11-13 19:25:18 +00:00
return NS_OK ;
}
2015-04-28 00:52:52 +00:00
bool
AndroidBridge : : PumpMessageLoop ( )
{
JNIEnv * const env = GetJNIEnv ( ) ;
if ( mMessageQueueMessages ) {
auto msg = Object : : LocalRef : : Adopt ( env ,
env - > GetObjectField ( mMessageQueue . Get ( ) ,
mMessageQueueMessages ) ) ;
// if queue.mMessages is null, queue.next() will block, which we don't
// want. It turns out to be an order of magnitude more performant to do
// this extra check here and block less vs. one fewer checks here and
// more blocking.
if ( ! msg ) {
return false ;
}
}
auto msg = Object : : LocalRef : : Adopt (
env , env - > CallObjectMethod ( mMessageQueue . Get ( ) , mMessageQueueNext ) ) ;
if ( ! msg ) {
return false ;
}
return GeckoAppShell : : PumpMessageLoop ( msg ) ;
}
2012-11-13 19:25:18 +00:00
2012-02-17 18:52:26 +00:00
/* attribute nsIAndroidBrowserApp browserApp; */
NS_IMETHODIMP nsAndroidBridge : : GetBrowserApp ( nsIAndroidBrowserApp * * aBrowserApp )
{
if ( nsAppShell : : gAppShell )
nsAppShell : : gAppShell - > GetBrowserApp ( aBrowserApp ) ;
return NS_OK ;
}
2012-05-04 15:08:47 +00:00
2012-02-17 18:52:26 +00:00
NS_IMETHODIMP nsAndroidBridge : : SetBrowserApp ( nsIAndroidBrowserApp * aBrowserApp )
{
if ( nsAppShell : : gAppShell )
nsAppShell : : gAppShell - > SetBrowserApp ( aBrowserApp ) ;
return NS_OK ;
}
2012-03-27 05:31:57 +00:00
void
2013-08-13 15:49:21 +00:00
AndroidBridge : : AddPluginView ( jobject view , const LayoutDeviceRect & rect , bool isFullScreen ) {
nsWindow * win = nsWindow : : TopWindow ( ) ;
if ( ! win )
return ;
2013-09-18 00:45:19 +00:00
CSSRect cssRect = rect / win - > GetDefaultScale ( ) ;
2015-01-10 00:33:57 +00:00
GeckoAppShell : : AddPluginViewWrapper ( Object : : Ref : : From ( view ) , cssRect . x , cssRect . y ,
cssRect . width , cssRect . height , isFullScreen ) ;
2012-03-27 05:31:57 +00:00
}
2012-02-17 18:52:26 +00:00
extern " C "
__attribute__ ( ( visibility ( " default " ) ) )
jobject JNICALL
2012-05-04 15:08:47 +00:00
Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer ( JNIEnv * env , jclass , jlong size ) ;
2012-02-17 18:52:26 +00:00
2013-04-23 17:10:29 +00:00
bool
AndroidBridge : : GetThreadNameJavaProfiling ( uint32_t aThreadId , nsCString & aResult )
{
2015-01-10 00:33:57 +00:00
auto jstrThreadName = GeckoJavaSampler : : GetThreadNameJavaProfilingWrapper ( aThreadId ) ;
2013-04-23 17:10:29 +00:00
if ( ! jstrThreadName )
return false ;
2015-01-10 00:33:57 +00:00
aResult = nsCString ( jstrThreadName ) ;
2013-04-23 17:10:29 +00:00
return true ;
}
bool
AndroidBridge : : GetFrameNameJavaProfiling ( uint32_t aThreadId , uint32_t aSampleId ,
uint32_t aFrameId , nsCString & aResult )
{
2015-01-10 00:33:57 +00:00
auto jstrSampleName = GeckoJavaSampler : : GetFrameNameJavaProfilingWrapper
( aThreadId , aSampleId , aFrameId ) ;
2013-04-23 17:10:29 +00:00
if ( ! jstrSampleName )
return false ;
2015-01-10 00:33:57 +00:00
aResult = nsCString ( jstrSampleName ) ;
2013-04-23 17:10:29 +00:00
return true ;
}
2015-01-21 04:59:23 +00:00
static float
2015-02-01 11:19:48 +00:00
GetScaleFactor ( nsPresContext * aPresContext ) {
nsIPresShell * presShell = aPresContext - > PresShell ( ) ;
2015-03-06 23:07:59 +00:00
LayoutDeviceToLayerScale cumulativeResolution ( presShell - > GetCumulativeResolution ( ) ) ;
2015-02-01 11:19:48 +00:00
return cumulativeResolution . scale ;
2015-01-21 04:59:23 +00:00
}
nsresult
2015-02-01 11:19:48 +00:00
AndroidBridge : : CaptureZoomedView ( nsIDOMWindow * window , nsIntRect zoomedViewRect , Object : : Param buffer ,
2015-01-21 04:59:23 +00:00
float zoomFactor ) {
2015-02-01 11:19:48 +00:00
nsresult rv ;
2015-01-21 04:59:23 +00:00
2015-02-01 11:19:48 +00:00
if ( ! buffer )
return NS_ERROR_FAILURE ;
2015-01-21 04:59:23 +00:00
2015-02-01 11:19:48 +00:00
nsCOMPtr < nsIDOMWindowUtils > utils = do_GetInterface ( window ) ;
if ( ! utils )
return NS_ERROR_FAILURE ;
2015-01-21 04:59:23 +00:00
2015-02-01 11:19:48 +00:00
JNIEnv * env = GetJNIEnv ( ) ;
2015-01-21 04:59:23 +00:00
2015-02-01 11:19:48 +00:00
AutoLocalJNIFrame jniFrame ( env , 0 ) ;
2015-01-21 04:59:23 +00:00
2015-02-01 11:19:48 +00:00
nsCOMPtr < nsPIDOMWindow > win = do_QueryInterface ( window ) ;
if ( ! win ) {
return NS_ERROR_FAILURE ;
}
nsRefPtr < nsPresContext > presContext ;
2015-01-21 04:59:23 +00:00
2015-02-01 11:19:48 +00:00
nsIDocShell * docshell = win - > GetDocShell ( ) ;
2015-01-21 04:59:23 +00:00
2015-02-01 11:19:48 +00:00
if ( docshell ) {
docshell - > GetPresContext ( getter_AddRefs ( presContext ) ) ;
}
2015-01-21 04:59:23 +00:00
2015-02-01 11:19:48 +00:00
if ( ! presContext ) {
return NS_ERROR_FAILURE ;
}
nsCOMPtr < nsIPresShell > presShell = presContext - > PresShell ( ) ;
2015-01-21 04:59:23 +00:00
2015-02-01 11:19:48 +00:00
float scaleFactor = GetScaleFactor ( presContext ) ;
2015-01-21 04:59:23 +00:00
2015-02-01 11:19:48 +00:00
nscolor bgColor = NS_RGB ( 255 , 255 , 255 ) ;
uint32_t renderDocFlags = ( nsIPresShell : : RENDER_IGNORE_VIEWPORT_SCROLLING | nsIPresShell : : RENDER_DOCUMENT_RELATIVE ) ;
nsRect r ( presContext - > DevPixelsToAppUnits ( zoomedViewRect . x / scaleFactor ) ,
presContext - > DevPixelsToAppUnits ( zoomedViewRect . y / scaleFactor ) ,
presContext - > DevPixelsToAppUnits ( zoomedViewRect . width / scaleFactor ) ,
presContext - > DevPixelsToAppUnits ( zoomedViewRect . height / scaleFactor ) ) ;
2015-01-21 04:59:23 +00:00
2015-02-01 11:19:48 +00:00
bool is24bit = ( GetScreenDepth ( ) = = 24 ) ;
SurfaceFormat format = is24bit ? SurfaceFormat : : B8G8R8X8 : SurfaceFormat : : R5G6B5 ;
gfxImageFormat iFormat = gfx : : SurfaceFormatToImageFormat ( format ) ;
uint32_t stride = gfxASurface : : FormatStrideForWidth ( iFormat , zoomedViewRect . width ) ;
2015-01-21 04:59:23 +00:00
2015-02-01 11:19:48 +00:00
uint8_t * data = static_cast < uint8_t * > ( env - > GetDirectBufferAddress ( buffer . Get ( ) ) ) ;
if ( ! data ) {
return NS_ERROR_FAILURE ;
}
2015-01-21 04:59:23 +00:00
2015-02-01 11:19:48 +00:00
MOZ_ASSERT ( gfxPlatform : : GetPlatform ( ) - > SupportsAzureContentForType ( BackendType : : CAIRO ) ,
2015-01-21 04:59:23 +00:00
" Need BackendType::CAIRO support " ) ;
2015-02-01 11:19:48 +00:00
RefPtr < DrawTarget > dt = Factory : : CreateDrawTargetForData (
BackendType : : CAIRO , data , IntSize ( zoomedViewRect . width , zoomedViewRect . height ) , stride ,
format ) ;
if ( ! dt ) {
ALOG_BRIDGE ( " Error creating DrawTarget " ) ;
return NS_ERROR_FAILURE ;
}
nsRefPtr < gfxContext > context = new gfxContext ( dt ) ;
context - > SetMatrix ( context - > CurrentMatrix ( ) . Scale ( zoomFactor , zoomFactor ) ) ;
2015-01-21 04:59:23 +00:00
2015-02-01 11:19:48 +00:00
rv = presShell - > RenderDocument ( r , renderDocFlags , bgColor , context ) ;
2015-01-21 04:59:23 +00:00
2015-02-01 11:19:48 +00:00
if ( is24bit ) {
gfxUtils : : ConvertBGRAtoRGBA ( data , stride * zoomedViewRect . height ) ;
}
2015-01-21 04:59:23 +00:00
2015-02-01 11:19:48 +00:00
LayerView : : updateZoomedView ( buffer ) ;
2015-01-21 04:59:23 +00:00
2015-02-01 11:19:48 +00:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
return NS_OK ;
2015-01-21 04:59:23 +00:00
}
2015-01-10 00:33:57 +00:00
nsresult AndroidBridge : : CaptureThumbnail ( nsIDOMWindow * window , int32_t bufW , int32_t bufH , int32_t tabId , Object : : Param buffer , bool & shouldStore )
2012-02-04 06:48:26 +00:00
{
2012-05-03 23:29:59 +00:00
nsresult rv ;
2012-06-14 16:08:51 +00:00
float scale = 1.0 ;
2012-07-02 19:32:34 +00:00
2012-06-14 16:08:51 +00:00
if ( ! buffer )
2013-01-23 17:18:05 +00:00
return NS_ERROR_FAILURE ;
2012-05-03 23:29:59 +00:00
// take a screenshot, as wide as possible, proportional to the destination size
2012-12-15 15:43:52 +00: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-02 03:50:57 +00:00
2012-12-15 15:43:52 +00: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 23:29:59 +00:00
}
2012-05-04 15:08:47 +00:00
JNIEnv * env = GetJNIEnv ( ) ;
2013-01-23 17:18:05 +00:00
AutoLocalJNIFrame jniFrame ( env , 0 ) ;
2012-05-04 15:08:47 +00:00
2012-02-04 06:48:26 +00:00
nsCOMPtr < nsPIDOMWindow > win = do_QueryInterface ( window ) ;
if ( ! win )
return NS_ERROR_FAILURE ;
nsRefPtr < nsPresContext > presContext ;
2014-05-06 05:33:29 +00:00
2012-02-04 06:48:26 +00:00
nsIDocShell * docshell = win - > GetDocShell ( ) ;
2014-05-06 05:33:29 +00:00
// Decide if callers should store this thumbnail for later use.
shouldStore = ShouldStoreThumbnail ( docshell ) ;
2012-02-04 06:48:26 +00:00
if ( docshell ) {
docshell - > GetPresContext ( getter_AddRefs ( presContext ) ) ;
}
2014-05-06 05:33:29 +00:00
2012-02-04 06:48:26 +00:00
if ( ! presContext )
return NS_ERROR_FAILURE ;
nscolor bgColor = NS_RGB ( 255 , 255 , 255 ) ;
2012-10-27 01:02:57 +00:00
nsCOMPtr < nsIPresShell > presShell = presContext - > PresShell ( ) ;
2012-08-22 15:56:38 +00:00
uint32_t renderDocFlags = ( nsIPresShell : : RENDER_IGNORE_VIEWPORT_SCROLLING |
2012-02-04 06:48:26 +00:00
nsIPresShell : : RENDER_DOCUMENT_RELATIVE ) ;
2012-03-15 04:43:53 +00:00
nsRect r ( nsPresContext : : CSSPixelsToAppUnits ( srcX / scale ) ,
nsPresContext : : CSSPixelsToAppUnits ( srcY / scale ) ,
nsPresContext : : CSSPixelsToAppUnits ( srcW / scale ) ,
nsPresContext : : CSSPixelsToAppUnits ( srcH / scale ) ) ;
2012-02-04 06:48:26 +00:00
2013-07-04 13:53:25 +00:00
bool is24bit = ( GetScreenDepth ( ) = = 24 ) ;
uint32_t stride = bufW * ( is24bit ? 4 : 2 ) ;
2012-02-17 18:52:26 +00:00
2015-01-10 00:33:57 +00:00
uint8_t * data = static_cast < uint8_t * > ( env - > GetDirectBufferAddress ( buffer . Get ( ) ) ) ;
2012-09-25 19:46:17 +00:00
if ( ! data )
return NS_ERROR_FAILURE ;
2014-06-03 11:31:42 +00:00
MOZ_ASSERT ( gfxPlatform : : GetPlatform ( ) - > SupportsAzureContentForType ( BackendType : : CAIRO ) ,
" Need BackendType::CAIRO support " ) ;
RefPtr < DrawTarget > dt =
Factory : : CreateDrawTargetForData ( BackendType : : CAIRO ,
data ,
IntSize ( bufW , bufH ) ,
stride ,
is24bit ? SurfaceFormat : : B8G8R8X8 :
SurfaceFormat : : R5G6B5 ) ;
if ( ! dt ) {
ALOG_BRIDGE ( " Error creating DrawTarget " ) ;
2012-08-14 00:01:31 +00:00
return NS_ERROR_FAILURE ;
}
2014-06-03 11:31:42 +00:00
nsRefPtr < gfxContext > context = new gfxContext ( dt ) ;
2014-09-11 06:57:38 +00:00
context - > SetMatrix (
context - > CurrentMatrix ( ) . Scale ( scale * bufW / srcW ,
scale * bufH / srcH ) ) ;
2012-05-03 23:29:59 +00:00
rv = presShell - > RenderDocument ( r , renderDocFlags , bgColor , context ) ;
2013-07-24 13:18:05 +00:00
if ( is24bit ) {
2014-06-03 11:31:42 +00:00
gfxUtils : : ConvertBGRAtoRGBA ( data , stride * bufH ) ;
2013-07-24 13:18:05 +00:00
}
2012-02-04 06:48:26 +00:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
return NS_OK ;
}
2012-04-24 19:13:36 +00:00
2013-05-30 13:55:08 +00:00
void
2012-09-12 21:47:08 +00:00
AndroidBridge : : GetDisplayPort ( bool aPageSizeUpdate , bool aIsBrowserContentDisplayed , int32_t tabId , nsIAndroidViewport * metrics , nsIAndroidDisplayport * * displayPort )
{
2013-11-12 18:41:01 +00:00
ALOG_BRIDGE ( " Enter: %s " , __PRETTY_FUNCTION__ ) ;
2015-01-10 00:33:57 +00:00
if ( ! mLayerClient ) {
2013-11-12 18:41:01 +00:00
ALOG_BRIDGE ( " Exceptional Exit: %s " , __PRETTY_FUNCTION__ ) ;
2013-05-30 13:55:08 +00:00
return ;
2013-11-12 18:41:01 +00:00
}
2015-01-10 00:33:57 +00:00
JNIEnv * const env = GetJNIEnv ( ) ;
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-11-12 18:41:01 +00:00
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 ) ;
2015-01-10 00:33:57 +00:00
auto jmetrics = ImmutableViewportMetrics : : New (
pageLeft , pageTop , pageRight , pageBottom ,
cssPageLeft , cssPageTop , cssPageRight , cssPageBottom ,
x , y , x + width , y + height ,
zoom ) ;
2013-11-12 18:41:01 +00:00
2015-01-10 00:33:57 +00:00
DisplayPortMetrics : : LocalRef displayPortMetrics = mLayerClient - > GetDisplayPort (
aPageSizeUpdate , aIsBrowserContentDisplayed , tabId , jmetrics ) ;
2013-11-12 18:41:01 +00:00
2015-01-10 00:33:57 +00:00
if ( ! displayPortMetrics ) {
2013-11-12 18:41:01 +00:00
ALOG_BRIDGE ( " Exceptional Exit: %s " , __PRETTY_FUNCTION__ ) ;
return ;
}
2015-01-10 00:33:57 +00:00
AndroidRectF rect ( env , displayPortMetrics - > MPosition ( ) . Get ( ) ) ;
float resolution = displayPortMetrics - > Resolution ( ) ;
2013-11-12 18:41:01 +00:00
* displayPort = new nsAndroidDisplayport ( rect , resolution ) ;
( * displayPort ) - > AddRef ( ) ;
ALOG_BRIDGE ( " Exit: %s " , __PRETTY_FUNCTION__ ) ;
2012-09-12 21:47:08 +00:00
}
2013-05-30 13:55:23 +00:00
void
AndroidBridge : : ContentDocumentChanged ( )
{
2013-11-12 18:41:01 +00:00
if ( ! mLayerClient ) {
2013-05-30 13:55:23 +00:00
return ;
2013-11-12 18:41:01 +00:00
}
mLayerClient - > ContentDocumentChanged ( ) ;
2013-05-30 13:55:23 +00:00
}
bool
AndroidBridge : : IsContentDocumentDisplayed ( )
{
2014-01-18 05:32:24 +00:00
if ( ! mLayerClient )
2013-05-30 13:55:23 +00:00
return false ;
2013-11-12 18:41:01 +00:00
return mLayerClient - > IsContentDocumentDisplayed ( ) ;
2013-05-30 13:55:23 +00:00
}
2012-10-04 18:45:16 +00:00
bool
2015-01-10 00:33:57 +00:00
AndroidBridge : : ProgressiveUpdateCallback ( bool aHasPendingNewThebesContent ,
const LayerRect & aDisplayPort , float aDisplayResolution ,
bool aDrawingCritical , ParentLayerPoint & aScrollOffset ,
CSSToParentLayerScale & aZoom )
2012-10-04 18:45:16 +00:00
{
2015-01-10 00:33:57 +00:00
if ( ! mLayerClient ) {
2013-11-12 18:41:01 +00:00
ALOG_BRIDGE ( " Exceptional Exit: %s " , __PRETTY_FUNCTION__ ) ;
2012-10-04 18:45:16 +00:00
return false ;
2013-11-12 18:41:01 +00:00
}
2015-01-10 00:33:57 +00:00
ProgressiveUpdateData : : LocalRef progressiveUpdateData =
mLayerClient - > ProgressiveUpdateCallback ( aHasPendingNewThebesContent ,
( float ) aDisplayPort . x ,
( float ) aDisplayPort . y ,
( float ) aDisplayPort . width ,
( float ) aDisplayPort . height ,
aDisplayResolution ,
! aDrawingCritical ) ;
2013-11-12 18:41:01 +00:00
2015-01-10 00:33:57 +00:00
aScrollOffset . x = progressiveUpdateData - > X ( ) ;
aScrollOffset . y = progressiveUpdateData - > Y ( ) ;
aZoom . scale = progressiveUpdateData - > Scale ( ) ;
2013-11-12 18:41:01 +00:00
2015-01-10 00:33:57 +00:00
return progressiveUpdateData - > Abort ( ) ;
2012-10-04 18:45:16 +00:00
}
2013-04-26 17:24:28 +00:00
void
2014-08-08 21:42:20 +00:00
AndroidBridge : : PostTaskToUiThread ( Task * aTask , int aDelayMs )
2013-04-26 17:24:28 +00:00
{
2013-04-26 17:26:46 +00: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
2014-08-08 21:42:20 +00:00
GeckoAppShell : : RequestUiThreadCallback ( ( int64_t ) aDelayMs ) ;
2013-04-26 17:26:46 +00:00
}
}
int64_t
2014-08-08 21:42:20 +00:00
AndroidBridge : : RunDelayedUiThreadTasks ( )
2013-04-26 17:26:46 +00:00
{
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 17:24:28 +00:00
}
2014-06-04 19:28:04 +00:00
2015-04-11 02:14:00 +00:00
void *
AndroidBridge : : GetPresentationWindow ( )
{
return mPresentationWindow ;
}
void
AndroidBridge : : SetPresentationWindow ( void * aPresentationWindow )
{
if ( mPresentationWindow ) {
const bool wasAlreadyPaused = nsWindow : : IsCompositionPaused ( ) ;
if ( ! wasAlreadyPaused ) {
nsWindow : : SchedulePauseComposition ( ) ;
}
mPresentationWindow = aPresentationWindow ;
if ( mPresentationSurface ) {
// destroy the egl surface!
// The compositor is paused so it should be okay to destroy
// the surface here.
mozilla : : gl : : GLContextProvider : : DestroyEGLSurface ( mPresentationSurface ) ;
mPresentationSurface = nullptr ;
}
if ( ! wasAlreadyPaused ) {
nsWindow : : ScheduleResumeComposition ( ) ;
}
}
else {
mPresentationWindow = aPresentationWindow ;
}
}
EGLSurface
AndroidBridge : : GetPresentationSurface ( )
{
return mPresentationSurface ;
}
void
AndroidBridge : : SetPresentationSurface ( EGLSurface aPresentationSurface )
{
mPresentationSurface = aPresentationSurface ;
}
2015-01-10 00:33:57 +00:00
Object : : LocalRef AndroidBridge : : ChannelCreate ( Object : : Param stream ) {
JNIEnv * const env = GetJNIForThread ( ) ;
auto rv = Object : : LocalRef : : Adopt ( env , env - > CallStaticObjectMethod (
sBridge - > jReadableByteChannel , sBridge - > jChannelCreate , stream . Get ( ) ) ) ;
HandleUncaughtException ( env ) ;
return rv ;
2014-06-04 19:28:04 +00:00
}
2015-01-10 00:33:57 +00:00
void AndroidBridge : : InputStreamClose ( Object : : Param obj ) {
JNIEnv * const env = GetJNIForThread ( ) ;
env - > CallVoidMethod ( obj . Get ( ) , sBridge - > jClose ) ;
HandleUncaughtException ( env ) ;
2014-06-04 19:28:04 +00:00
}
2015-01-10 00:33:57 +00:00
uint32_t AndroidBridge : : InputStreamAvailable ( Object : : Param obj ) {
JNIEnv * const env = GetJNIForThread ( ) ;
auto rv = env - > CallIntMethod ( obj . Get ( ) , sBridge - > jAvailable ) ;
HandleUncaughtException ( env ) ;
return rv ;
2014-06-04 19:28:04 +00:00
}
2015-01-10 00:33:57 +00:00
nsresult AndroidBridge : : InputStreamRead ( Object : : Param obj , char * aBuf , uint32_t aCount , uint32_t * aRead ) {
JNIEnv * const env = GetJNIForThread ( ) ;
auto arr = Object : : LocalRef : : Adopt ( env , env - > NewDirectByteBuffer ( aBuf , aCount ) ) ;
jint read = env - > CallIntMethod ( obj . Get ( ) , sBridge - > jByteBufferRead , arr . Get ( ) ) ;
2014-06-04 19:28:04 +00:00
if ( env - > ExceptionCheck ( ) ) {
env - > ExceptionClear ( ) ;
return NS_ERROR_FAILURE ;
}
if ( read < = 0 ) {
* aRead = 0 ;
return NS_OK ;
}
* aRead = read ;
return NS_OK ;
}
2014-07-24 20:42:50 +00:00
nsresult AndroidBridge : : GetExternalPublicDirectory ( const nsAString & aType , nsAString & aPath ) {
2015-01-10 00:33:57 +00:00
auto path = GeckoAppShell : : GetExternalPublicDirectory ( aType ) ;
2014-07-24 20:42:50 +00:00
if ( ! path ) {
return NS_ERROR_NOT_AVAILABLE ;
}
2015-01-10 00:33:57 +00:00
aPath = nsString ( path ) ;
2014-07-24 20:42:50 +00:00
return NS_OK ;
}