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/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>
2014-05-05 22:33:29 -07:00
# include <math.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"
2013-10-14 20:23:20 -07:00
# include "gfxPlatform.h"
2012-02-03 22:48:26 -08:00
# include "gfxContext.h"
2013-10-14 20:23:20 -07:00
# include "mozilla/gfx/2D.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"
2014-04-04 09:33:49 -07:00
# include "NativeJSContainer.h"
# include "nsContentUtils.h"
# include "nsIScriptError.h"
2014-05-05 22:33:29 -07:00
# include "nsIHttpChannel.h"
2010-06-03 13:56:36 -07:00
using namespace mozilla ;
2013-11-12 10:41:01 -08:00
using namespace mozilla : : widget : : android ;
2013-10-14 20:23:20 -07:00
using namespace mozilla : : gfx ;
2010-06-03 13:56:36 -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 ) {
2013-11-18 17:30:00 -08:00
ALOG ( " >>> FATAL JNI ERROR! FindClass(className= \" %s \" ) failed. Did ProGuard optimize away something it shouldn't have? " ,
className ) ;
2013-09-09 05:57:36 -07:00
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 ) ;
2013-10-10 13:42:52 -07:00
classLocalRef = nullptr ;
2013-09-09 05:57:36 -07:00
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 \" , "
2013-11-18 17:30:00 -08:00
" methodType= \" %s \" ) failed. Did ProGuard optimize away something it shouldn't have? " ,
methodName , methodType ) ;
2013-09-09 05:57:36 -07: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-18 17:30:00 -08:00
" methodType= \" %s \" ) failed. Did ProGuard optimize away something it shouldn't have? " ,
methodName , methodType ) ;
2013-09-09 05:57:36 -07: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-18 17:30:00 -08:00
" fieldType= \" %s \" ) failed. Did ProGuard optimize away something it shouldn't have? " ,
fieldName , fieldType ) ;
2013-09-09 05:57:36 -07: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-18 17:30:00 -08:00
" fieldType= \" %s \" ) failed. Did ProGuard optimize away something it shouldn't have? " ,
fieldName , fieldType ) ;
2013-09-09 05:57:36 -07:00
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 ) ;
2014-01-17 21:32:24 -08:00
if ( ! mJavaVM ) {
MOZ_CRASH ( ) ; // Nothing we can do here
}
2010-06-03 13:56:36 -07:00
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 ;
2014-01-06 07:06:04 -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 ( ) ;
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-11-04 10:07:03 -08:00
} else if ( mAPIVersion > 8 & & mAPIVersion < 19 /* KitKat */ ) {
2013-09-09 05:57:36 -07:00
jSurfacePointerField = getField ( " mNativeSurface " , " I " ) ;
2013-11-04 10:07:03 -08:00
} else {
// We don't know how to get this, just set it to 0
jSurfacePointerField = 0 ;
2013-02-26 06:28:57 -08:00
}
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
2014-06-04 12:28:04 -07:00
jChannels = getClassGlobalRef ( " java/nio/channels/Channels " ) ;
jChannelCreate = jEnv - > GetStaticMethodID ( jChannels , " newChannel " , " (Ljava/io/InputStream;)Ljava/nio/channels/ReadableByteChannel; " ) ;
jReadableByteChannel = getClassGlobalRef ( " java/nio/channels/ReadableByteChannel " ) ;
jByteBufferRead = jEnv - > GetMethodID ( jReadableByteChannel , " read " , " (Ljava/nio/ByteBuffer;)I " ) ;
jInputStream = getClassGlobalRef ( " java/io/InputStream " ) ;
jClose = jEnv - > GetMethodID ( jInputStream , " close " , " ()V " ) ;
jAvailable = jEnv - > GetMethodID ( jInputStream , " available " , " ()I " ) ;
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.
2014-01-04 07:02:17 -08:00
jstring AndroidBridge : : NewJavaString ( JNIEnv * env , const char16_t * string , uint32_t len ) {
2013-10-08 11:00:40 -07:00
jstring ret = env - > NewString ( reinterpret_cast < const jchar * > ( string ) , len ) ;
2013-09-09 05:57:37 -07:00
if ( env - > ExceptionCheck ( ) ) {
ALOG_BRIDGE ( " Exceptional exit of: %s " , __PRETTY_FUNCTION__ ) ;
env - > ExceptionDescribe ( ) ;
env - > ExceptionClear ( ) ;
2013-10-10 13:42:52 -07:00
return nullptr ;
2013-09-09 05:57:37 -07:00
}
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..
2014-01-04 07:02:17 -08:00
jstring AndroidBridge : : NewJavaString ( AutoLocalJNIFrame * frame , const char16_t * string , uint32_t len ) {
2013-09-09 05:57:37 -07:00
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
}
2013-11-12 10:41:01 -08:00
extern " C " {
__attribute__ ( ( visibility ( " default " ) ) )
JNIEnv * GetJNIForThread ( )
{
2014-01-17 21:32:24 -08:00
JNIEnv * jEnv = static_cast < JNIEnv * > ( PR_GetThreadPrivate ( sJavaEnvThreadIndex ) ) ;
if ( jEnv ) {
2013-11-12 10:41:01 -08:00
return jEnv ;
}
2014-01-17 21:32:24 -08:00
JavaVM * jVm = mozilla : : AndroidBridge : : GetVM ( ) ;
2014-01-28 16:32:28 -08:00
if ( ! jVm - > GetEnv ( reinterpret_cast < void * * > ( & jEnv ) , JNI_VERSION_1_2 ) ) {
MOZ_ASSERT ( jEnv ) ;
return jEnv ;
}
if ( ! jVm - > AttachCurrentThread ( & jEnv , nullptr ) ) {
2014-01-17 21:32:24 -08:00
MOZ_ASSERT ( jEnv ) ;
PR_SetThreadPrivate ( sJavaEnvThreadIndex , jEnv ) ;
return jEnv ;
2013-11-12 10:41:01 -08:00
}
2014-01-17 21:32:24 -08:00
MOZ_CRASH ( ) ;
return nullptr ; // unreachable
2013-11-12 10:41:01 -08:00
}
}
void AutoGlobalWrappedJavaObject : : Dispose ( ) {
if ( isNull ( ) ) {
return ;
}
GetJNIForThread ( ) - > DeleteGlobalRef ( wrapped_obj ) ;
2014-01-06 07:06:04 -08:00
wrapped_obj = nullptr ;
2013-11-12 10:41:01 -08:00
}
AutoGlobalWrappedJavaObject : : ~ AutoGlobalWrappedJavaObject ( ) {
Dispose ( ) ;
}
2014-05-05 22:33:29 -07: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 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 ) {
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( aJNIEnv , 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 ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2014-04-01 05:29:25 -07:00
jobjectArray arr =
mozilla : : widget : : android : : GeckoAppShell : : 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 ) ) ;
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 ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2014-04-01 05:29:25 -07:00
jobjectArray arr = mozilla : : widget : : android : : GeckoAppShell : : 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 ) ;
2013-09-09 05:57:37 -07:00
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 ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2014-04-01 05:29:25 -07:00
jstring jstrType = mozilla : : widget : : android : : GeckoAppShell : : GetMimeTypeFromExtensionsWrapper
( NS_ConvertUTF8toUTF16 ( aFileExt ) ) ;
2013-09-09 05:57:37 -07:00
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 ) ;
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 ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2014-04-01 05:29:25 -07:00
jstring jstrExt = mozilla : : widget : : android : : GeckoAppShell : : GetExtensionFromMimeTypeWrapper
( NS_ConvertUTF8toUTF16 ( aMimeType ) ) ;
2013-09-09 05:57:37 -07:00
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 ) ;
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 ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-11-12 10:41:01 -08:00
jstring result = Clipboard : : GetClipboardTextWrapper ( ) ;
2013-09-09 05:57:37 -07:00
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 ) ;
2013-09-09 05:57:37 -07:00
return true ;
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
2014-04-01 05:29:25 -07:00
mozilla : : widget : : android : : GeckoAppShell : : 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
2014-04-01 05:29:25 -07:00
sDPI = mozilla : : widget : : android : : GeckoAppShell : : GetDpiWrapper ( ) ;
2013-09-09 05:57:37 -07:00
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 ;
2014-01-17 21:32:24 -08:00
if ( HasEnv ( ) ) {
2014-04-01 05:29:25 -07:00
sDepth = mozilla : : widget : : android : : GeckoAppShell : : GetScreenDepthWrapper ( ) ;
2014-01-17 21:32:24 -08:00
}
2013-09-09 05:57:37 -07:00
if ( ! sDepth )
2013-07-04 06:53:25 -07:00
return DEFAULT_DEPTH ;
return sDepth ;
}
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 ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
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 ;
}
2014-04-01 05:29:25 -07:00
mozilla : : widget : : android : : GeckoAppShell : : 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
2014-04-01 05:29:25 -07:00
mozilla : : widget : : android : : GeckoAppShell : : 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 ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2011-03-30 11:04:41 -07:00
2014-04-01 05:29:25 -07:00
jintArray arr = mozilla : : widget : : android : : GeckoAppShell : : 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 ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2011-06-13 14:02:13 -07:00
2014-04-01 05:29:25 -07:00
jbyteArray arr = mozilla : : widget : : android : : GeckoAppShell : : 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.
2013-10-10 13:42:52 -07:00
bool resetting = ( mLayerClient ! = nullptr ) ;
2012-07-13 07:19:46 -07:00
if ( resetting ) {
// clear out the old layer client
delete mLayerClient ;
2013-10-10 13:42:52 -07:00
mLayerClient = nullptr ;
2012-07-13 07:19:46 -07:00
}
2014-04-01 05:29:25 -07:00
mLayerClient = mozilla : : widget : : android : : GeckoLayerClient : : Wrap ( jobj ) ;
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
{
2014-01-06 07:06:04 -08:00
if ( mGLControllerObj ! = nullptr & & ! mGLControllerObj - > isNull ( ) ) {
2013-02-28 10:28:24 -08:00
// we already have this set up, no need to do it again
return ;
}
2013-11-12 10:41:01 -08:00
jobject glController = LayerView : : RegisterCompositorWrapper ( ) ;
2013-09-09 05:57:37 -07:00
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-11-12 10:41:01 -08:00
mGLControllerObj = GLController : : Wrap ( glController ) ;
2012-02-06 13:53:09 -08:00
}
EGLSurface
2013-11-15 08:28:59 -08:00
AndroidBridge : : CreateEGLSurfaceForCompositor ( )
2012-02-06 13:53:09 -08:00
{
2013-02-28 10:28:24 -08:00
if ( ! jEGLSurfacePointerField ) {
2013-10-10 13:42:52 -07:00
return nullptr ;
2013-02-28 10:28:24 -08:00
}
2013-11-15 08:28:59 -08:00
MOZ_ASSERT ( mGLControllerObj , " AndroidBridge::CreateEGLSurfaceForCompositor called with a null GL controller ref " ) ;
2013-02-28 10:28:24 -08:00
JNIEnv * env = GetJNIForThread ( ) ; // called on the compositor thread
2013-09-09 05:57:37 -07:00
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-11-12 10:41:01 -08:00
jobject eglSurface = mGLControllerObj - > CreateEGLSurfaceForCompositorWrapper ( ) ;
2013-09-09 05:57:37 -07:00
if ( ! eglSurface )
2013-10-10 13:42:52 -07:00
return nullptr ;
2013-02-28 10:28:24 -08:00
2013-09-09 05:57:37 -07:00
EGLSurface ret = reinterpret_cast < EGLSurface > ( env - > GetIntField ( eglSurface , jEGLSurfacePointerField ) ) ;
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 ) {
2014-01-17 21:32:24 -08:00
if ( ! HasEnv ( ) ) {
return false ;
}
2013-09-09 05:57:36 -07:00
jEnv = GetJNIEnv ( ) ;
2012-04-27 13:04:47 -07:00
}
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 ) {
2014-01-17 21:32:24 -08:00
if ( ! HasEnv ( ) ) {
return false ;
}
2013-09-09 05:57:36 -07:00
jEnv = GetJNIEnv ( ) ;
2012-04-27 13:04:47 -07:00
}
2012-01-29 12:39:30 -08:00
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( jEnv , 1 ) ;
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 ) ) ;
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 ) ;
}
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 ( ( 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 ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2014-04-01 05:29:25 -07:00
jintArray arr = mozilla : : widget : : android : : GeckoAppShell : : 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 ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
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.
2014-04-01 05:29:25 -07:00
jdoubleArray arr = mozilla : : widget : : android : : GeckoAppShell : : 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
2014-04-04 09:33:49 -07:00
AndroidBridge : : HandleGeckoMessage ( JSContext * cx , JS : : HandleObject object )
2011-11-14 19:12:14 -08:00
{
ALOG_BRIDGE ( " %s " , __PRETTY_FUNCTION__ ) ;
2012-01-29 12:39:30 -08:00
2014-04-04 09:33:49 -07:00
JNIEnv * const env = GetJNIEnv ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2014-04-04 09:33:49 -07:00
const jobject message =
mozilla : : widget : : CreateNativeJSContainer ( env , cx , object ) ;
GeckoAppShell : : HandleGeckoMessageWrapper ( message ) ;
2011-11-14 19:12:14 -08:00
}
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 ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 2 ) ;
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
2014-04-01 05:29:25 -07:00
mozilla : : widget : : android : : GeckoAppShell : : 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
2014-04-01 05:29:25 -07:00
mozilla : : widget : : android : : GeckoAppShell : : 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
2014-04-01 05:29:25 -07:00
mozilla : : widget : : android : : GeckoAppShell : : 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 ( ) ;
2013-01-25 11:00:00 -08:00
uint32_t requestId ;
if ( ! QueueSmsRequest ( aRequest , & requestId ) )
return ;
2012-11-06 13:32:07 -08:00
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 2 ) ;
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 ) {
2014-01-06 09:54:22 -08:00
jstring elem = NewJavaString ( & jniFrame , aFilter . numbers ( ) [ i ] ) ;
env - > SetObjectArrayElement ( numbers , i , elem ) ;
env - > DeleteLocalRef ( elem ) ;
2013-09-09 05:57:37 -07:00
}
2012-11-06 13:32:07 -08:00
2014-04-01 05:29:25 -07:00
mozilla : : widget : : android : : GeckoAppShell : : CreateMessageListWrapper ( aFilter . startDate ( ) ,
aFilter . endDate ( ) , numbers , aFilter . numbers ( ) . Length ( ) ,
2013-09-09 05:57:37 -07:00
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 ;
2014-04-01 05:29:25 -07:00
mozilla : : widget : : android : : GeckoAppShell : : 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 ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2012-01-16 05:44:07 -08:00
// To prevent calling too many methods through JNI, the Java method returns
2014-03-05 01:42:42 -08:00
// an array of double even if we actually want an integer, a boolean, and an integer.
2012-05-04 08:08:47 -07:00
2014-04-01 05:29:25 -07:00
jdoubleArray arr = mozilla : : widget : : android : : GeckoAppShell : : GetCurrentNetworkInformationWrapper ( ) ;
2014-03-05 01:42:42 -08:00
if ( ! arr | | env - > GetArrayLength ( arr ) ! = 3 ) {
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
2014-03-05 01:42:42 -08:00
aNetworkInfo - > type ( ) = info [ 0 ] ;
aNetworkInfo - > isWifi ( ) = info [ 1 ] = = 1.0f ;
aNetworkInfo - > dhcpGateway ( ) = info [ 2 ] ;
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 ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 0 ) ;
2012-05-04 08:08:47 -07:00
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 ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 0 ) ;
2012-05-04 08:08:47 -07:00
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 ;
2013-10-10 13:42:52 -07:00
* bits = nullptr ;
2011-09-21 09:46:00 -07:00
* 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
2013-10-10 13:42:52 -07:00
if ( ( err = ANativeWindow_lock ( window , ( void * ) & buffer , nullptr ) ) ! = 0 ) {
2012-04-27 13:04:47 -07: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 13:42:52 -07:00
if ( ( err = Surface_lock ( window , & info , nullptr , true ) ) ! = 0 ) {
2012-04-27 13:04:47 -07: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 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 ( ) ;
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
2014-04-01 05:29:25 -07:00
jobject context = mozilla : : widget : : android : : GeckoAppShell : : GetContext ( ) ;
2013-09-24 23:06:21 -07:00
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
{
2014-04-01 05:29:25 -07:00
mozilla : : widget : : android : : GeckoLayerClient * client = mLayerClient ;
2012-03-12 08:50:21 -07:00
if ( ! client )
return ;
2013-11-12 10:41:01 -08:00
client - > SetFirstPaintViewport ( ( float ) aOffset . x , ( float ) aOffset . y , aZoom . scale ,
aCssPageRect . x , aCssPageRect . y , aCssPageRect . XMost ( ) , aCssPageRect . YMost ( ) ) ;
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
{
2014-04-01 05:29:25 -07:00
mozilla : : widget : : android : : GeckoLayerClient * client = mLayerClient ;
2012-03-12 08:50:21 -07:00
if ( ! client )
return ;
2013-11-12 10:41:01 -08:00
client - > SetPageRect ( aCssPageRect . x , aCssPageRect . y , aCssPageRect . XMost ( ) , aCssPageRect . YMost ( ) ) ;
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
{
2014-04-01 05:29:25 -07:00
mozilla : : widget : : android : : GeckoLayerClient * client = mLayerClient ;
2013-11-12 10:41:01 -08:00
if ( ! client ) {
ALOG_BRIDGE ( " Exceptional Exit: %s " , __PRETTY_FUNCTION__ ) ;
return ;
}
jobject viewTransformJObj = client - > SyncViewportInfo ( aDisplayPort . x , aDisplayPort . y ,
aDisplayPort . width , aDisplayPort . height ,
aDisplayResolution . scale , aLayersUpdated ) ;
NS_ABORT_IF_FALSE ( viewTransformJObj , " No view transform object! " ) ;
if ( ! viewTransformJObj ) {
2012-03-13 21:15:11 -07:00
return ;
2013-11-12 10:41:01 -08:00
}
2012-03-13 21:15:11 -07:00
2013-11-12 10:41:01 -08:00
ViewTransform * viewTransform = ViewTransform : : Wrap ( viewTransformJObj ) ;
aScrollOffset = ScreenPoint ( viewTransform - > getx ( ) , viewTransform - > gety ( ) ) ;
aScale . scale = viewTransform - > getscale ( ) ;
aFixedLayerMargins . top = viewTransform - > getfixedLayerMarginTop ( ) ;
aFixedLayerMargins . right = viewTransform - > getfixedLayerMarginRight ( ) ;
aFixedLayerMargins . bottom = viewTransform - > getfixedLayerMarginBottom ( ) ;
aFixedLayerMargins . left = viewTransform - > getfixedLayerMarginLeft ( ) ;
aOffset . x = viewTransform - > getoffsetX ( ) ;
aOffset . y = viewTransform - > getoffsetY ( ) ;
delete viewTransform ;
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
{
2014-04-01 05:29:25 -07:00
mozilla : : widget : : android : : GeckoLayerClient * client = mLayerClient ;
2013-11-12 10:41:01 -08:00
if ( ! client ) {
ALOG_BRIDGE ( " Exceptional Exit: %s " , __PRETTY_FUNCTION__ ) ;
2013-04-26 10:26:39 -07:00
return ;
2013-11-12 10:41:01 -08:00
}
2013-04-26 10:26:39 -07:00
2013-11-12 10:41:01 -08: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 ) ;
jobject viewTransformJObj = client - > SyncFrameMetrics ( aScrollOffset . x , aScrollOffset . y , aZoom ,
aCssPageRect . x , aCssPageRect . y , aCssPageRect . XMost ( ) , aCssPageRect . YMost ( ) ,
aLayersUpdated , dp . x , dp . y , dp . width , dp . height , aDisplayResolution . scale ,
aIsFirstPaint ) ;
NS_ABORT_IF_FALSE ( viewTransformJObj , " No view transform object! " ) ;
if ( ! viewTransformJObj ) {
return ;
}
ViewTransform * viewTransform = ViewTransform : : Wrap ( viewTransformJObj ) ;
aFixedLayerMargins . top = viewTransform - > getfixedLayerMarginTop ( ) ;
aFixedLayerMargins . right = viewTransform - > getfixedLayerMarginRight ( ) ;
aFixedLayerMargins . bottom = viewTransform - > getfixedLayerMarginBottom ( ) ;
aFixedLayerMargins . left = viewTransform - > getfixedLayerMarginLeft ( ) ;
aOffset . x = viewTransform - > getoffsetX ( ) ;
aOffset . y = viewTransform - > getoffsetY ( ) ;
delete viewTransform ;
2013-04-26 10:26:39 -07:00
}
2012-07-13 14:34:58 -07:00
AndroidBridge : : AndroidBridge ( )
2013-10-10 13:42:52 -07:00
: mLayerClient ( nullptr ) ,
mNativePanZoomController ( nullptr )
2012-07-13 14:34:58 -07:00
{
}
AndroidBridge : : ~ AndroidBridge ( )
{
}
2011-10-10 17:40:17 -07:00
/* Implementation file */
2014-04-27 00:06:00 -07:00
NS_IMPL_ISUPPORTS ( nsAndroidBridge , nsIAndroidBridge )
2011-10-10 17:40:17 -07:00
nsAndroidBridge : : nsAndroidBridge ( )
{
}
nsAndroidBridge : : ~ nsAndroidBridge ( )
{
}
/* void handleGeckoEvent (in AString message); */
2014-04-04 09:33:49 -07:00
NS_IMETHODIMP nsAndroidBridge : : HandleGeckoMessage ( JS : : HandleValue val ,
JSContext * cx )
2011-10-10 17:40:17 -07:00
{
2014-04-04 09:33:49 -07: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 ( ) ) ;
size_t strLen = 0 ;
const jschar * strChar = JS_GetStringCharsAndLength ( cx , jsonStr , & strLen ) ;
if ( ! strChar ) {
return NS_ERROR_UNEXPECTED ;
}
JS : : RootedValue jsonVal ( cx ) ;
if ( ! JS_ParseJSON ( cx , strChar , strLen , & jsonVal ) | | ! jsonVal . isObject ( ) ) {
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-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 ;
2014-01-24 09:04:15 -08:00
MOZ_ASSERT ( env , " No JNIEnv on Gecko thread " ) ;
if ( ! env ) {
return ;
}
2013-10-10 13:42:52 -07:00
JavaVM * vm = nullptr ;
2012-01-29 12:39:30 -08:00
env - > GetJavaVM ( & vm ) ;
2014-01-24 09:04:15 -08:00
MOZ_ASSERT ( vm , " No JavaVM on Gecko thread " ) ;
if ( ! vm ) {
return ;
}
2012-01-29 12:39:30 -08:00
vm - > DetachCurrentThread ( ) ;
}
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
2014-04-01 05:29:25 -07:00
int16_t orientation = mozilla : : widget : : android : : GeckoAppShell : : 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-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 )
{
2014-01-17 21:32:24 -08:00
if ( ! HasEnv ( ) ) {
return NS_ERROR_FAILURE ;
}
2012-11-13 11:25:18 -08:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2014-04-01 05:29:25 -07:00
jstring jstrRet =
mozilla : : widget : : android : : GeckoAppShell : : 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 ( ) ;
2014-04-01 05:29:25 -07:00
mozilla : : widget : : android : : GeckoAppShell : : 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 ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-04-23 10:10:29 -07:00
2014-04-01 05:29:25 -07:00
jstring jstrThreadName =
mozilla : : widget : : android : : GeckoJavaSampler : : 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 ( ) ;
2014-01-06 09:54:22 -08:00
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
2013-04-23 10:10:29 -07:00
2014-04-01 05:29:25 -07:00
jstring jstrSampleName = mozilla : : widget : : android : : GeckoJavaSampler : : GetFrameNameJavaProfilingWrapper
( aThreadId , aSampleId , aFrameId ) ;
2013-04-23 10:10:29 -07:00
if ( ! jstrSampleName )
return false ;
nsJNIString jniStr ( jstrSampleName , env ) ;
CopyUTF16toUTF8 ( jniStr . get ( ) , aResult ) ;
return true ;
}
2014-05-05 22:33:29 -07:00
nsresult AndroidBridge : : CaptureThumbnail ( nsIDOMWindow * window , int32_t bufW , int32_t bufH , int32_t tabId , jobject buffer , bool & shouldStore )
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 ( ) ;
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 ;
2014-05-05 22:33:29 -07:00
2012-02-03 22:48:26 -08:00
nsIDocShell * docshell = win - > GetDocShell ( ) ;
2014-05-05 22:33:29 -07:00
// Decide if callers should store this thumbnail for later use.
shouldStore = ShouldStoreThumbnail ( docshell ) ;
2012-02-03 22:48:26 -08:00
if ( docshell ) {
docshell - > GetPresContext ( getter_AddRefs ( presContext ) ) ;
}
2014-05-05 22:33:29 -07:00
2012-02-03 22:48:26 -08:00
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
2014-06-03 04:31:42 -07:00
uint8_t * data = static_cast < uint8_t * > ( env - > GetDirectBufferAddress ( buffer ) ) ;
2012-09-25 12:46:17 -07:00
if ( ! data )
return NS_ERROR_FAILURE ;
2014-06-03 04:31:42 -07: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-13 17:01:31 -07:00
return NS_ERROR_FAILURE ;
}
2014-06-03 04:31:42 -07:00
nsRefPtr < gfxContext > context = new gfxContext ( dt ) ;
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 ) {
2014-06-03 04:31:42 -07:00
gfxUtils : : ConvertBGRAtoRGBA ( data , stride * bufH ) ;
2013-07-24 06:18:05 -07:00
}
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 )
{
2013-11-12 10:41:01 -08:00
ALOG_BRIDGE ( " Enter: %s " , __PRETTY_FUNCTION__ ) ;
2012-09-12 14:47:08 -07:00
JNIEnv * env = GetJNIEnv ( ) ;
2014-01-17 21:32:24 -08:00
if ( ! mLayerClient | | mLayerClient - > isNull ( ) ) {
2013-11-12 10:41:01 -08:00
ALOG_BRIDGE ( " Exceptional Exit: %s " , __PRETTY_FUNCTION__ ) ;
2013-05-30 06:55:08 -07:00
return ;
2013-11-12 10:41:01 -08:00
}
2012-09-12 14:47:08 -07:00
AutoLocalJNIFrame jniFrame ( env , 0 ) ;
2013-11-12 10:41:01 -08: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 ) ;
ImmutableViewportMetrics jmetrics = ImmutableViewportMetrics ( pageLeft , pageTop , pageRight , pageBottom ,
cssPageLeft , cssPageTop , cssPageRight , cssPageBottom ,
x , y , x + width , y + height ,
zoom ) ;
jobject jobj = mLayerClient - > GetDisplayPort ( aPageSizeUpdate , aIsBrowserContentDisplayed , tabId , jmetrics . wrappedObject ( ) ) ;
if ( ! jobj ) {
ALOG_BRIDGE ( " Exceptional Exit: %s " , __PRETTY_FUNCTION__ ) ;
return ;
}
DisplayPortMetrics * displayPortMetrics = DisplayPortMetrics : : Wrap ( jobj ) ;
AndroidRectF rect ( env , displayPortMetrics - > getMPosition ( ) ) ;
if ( jniFrame . CheckForException ( ) ) {
ALOG_BRIDGE ( " Exceptional Exit: %s " , __PRETTY_FUNCTION__ ) ;
return ;
}
float resolution = displayPortMetrics - > getResolution ( ) ;
if ( jniFrame . CheckForException ( ) ) {
ALOG_BRIDGE ( " Exceptional Exit: %s " , __PRETTY_FUNCTION__ ) ;
return ;
}
* displayPort = new nsAndroidDisplayport ( rect , resolution ) ;
( * displayPort ) - > AddRef ( ) ;
delete displayPortMetrics ;
ALOG_BRIDGE ( " Exit: %s " , __PRETTY_FUNCTION__ ) ;
2012-09-12 14:47:08 -07:00
}
2013-05-30 06:55:23 -07:00
void
AndroidBridge : : ContentDocumentChanged ( )
{
2013-11-12 10:41:01 -08:00
if ( ! mLayerClient ) {
2013-05-30 06:55:23 -07:00
return ;
2013-11-12 10:41:01 -08:00
}
mLayerClient - > ContentDocumentChanged ( ) ;
2013-05-30 06:55:23 -07:00
}
bool
AndroidBridge : : IsContentDocumentDisplayed ( )
{
2014-01-17 21:32:24 -08:00
if ( ! mLayerClient )
2013-05-30 06:55:23 -07:00
return false ;
2013-11-12 10:41:01 -08:00
return mLayerClient - > IsContentDocumentDisplayed ( ) ;
2013-05-30 06:55:23 -07:00
}
2012-10-04 11:45:16 -07:00
bool
2014-03-10 14:56:59 -07:00
AndroidBridge : : ProgressiveUpdateCallback ( bool aHasPendingNewThebesContent , const LayerRect & aDisplayPort , float aDisplayResolution , bool aDrawingCritical , ParentLayerRect & aCompositionBounds , CSSToParentLayerScale & aZoom )
2012-10-04 11:45:16 -07:00
{
2014-04-01 05:29:25 -07:00
mozilla : : widget : : android : : GeckoLayerClient * client = mLayerClient ;
2013-11-12 10:41:01 -08:00
if ( ! client ) {
ALOG_BRIDGE ( " Exceptional Exit: %s " , __PRETTY_FUNCTION__ ) ;
2012-10-04 11:45:16 -07:00
return false ;
2013-11-12 10:41:01 -08:00
}
jobject progressiveUpdateDataJObj = client - > ProgressiveUpdateCallback ( aHasPendingNewThebesContent ,
( float ) aDisplayPort . x ,
( float ) aDisplayPort . y ,
( float ) aDisplayPort . width ,
( float ) aDisplayPort . height ,
aDisplayResolution ,
! aDrawingCritical ) ;
NS_ABORT_IF_FALSE ( progressiveUpdateDataJObj , " No progressive update data! " ) ;
ProgressiveUpdateData * progressiveUpdateData = ProgressiveUpdateData : : Wrap ( progressiveUpdateDataJObj ) ;
2012-10-04 11:45:16 -07:00
2013-11-27 09:33:27 -08:00
aCompositionBounds . x = progressiveUpdateData - > getx ( ) ;
aCompositionBounds . y = progressiveUpdateData - > gety ( ) ;
aCompositionBounds . width = progressiveUpdateData - > getwidth ( ) ;
aCompositionBounds . height = progressiveUpdateData - > getheight ( ) ;
aZoom . scale = progressiveUpdateData - > getscale ( ) ;
2013-11-12 10:41:01 -08:00
bool ret = progressiveUpdateData - > getabort ( ) ;
delete progressiveUpdateData ;
return ret ;
2012-10-04 11:45:16 -07:00
}
2014-04-01 05:29:25 -07:00
mozilla : : widget : : android : : NativePanZoomController *
2013-04-26 10:24:28 -07:00
AndroidBridge : : SetNativePanZoomController ( jobject obj )
{
2014-04-01 05:29:25 -07:00
mozilla : : widget : : android : : NativePanZoomController * old = mNativePanZoomController ;
mNativePanZoomController = mozilla : : widget : : android : : NativePanZoomController : : Wrap ( obj ) ;
2013-04-26 10:24:28 -07:00
return old ;
}
void
AndroidBridge : : RequestContentRepaint ( const mozilla : : layers : : FrameMetrics & aFrameMetrics )
{
2013-04-26 10:26:46 -07:00
ALOG_BRIDGE ( " AndroidBridge::RequestContentRepaint " ) ;
2014-04-10 00:15:09 -07:00
// FIXME implement this
2013-04-26 10:24:28 -07:00
}
2014-02-05 14:43:20 -08:00
void
AndroidBridge : : AcknowledgeScrollUpdate ( const mozilla : : layers : : FrameMetrics : : ViewID & aScrollId ,
const uint32_t & aScrollGeneration )
{
// FIXME implement this
}
2013-04-26 10:24:28 -07:00
void
2014-03-12 12:27:45 -07:00
AndroidBridge : : HandleDoubleTap ( const CSSPoint & aPoint ,
2014-02-07 09:13:50 -08:00
int32_t aModifiers ,
const mozilla : : layers : : ScrollableLayerGuid & aGuid )
2013-04-26 10:24:28 -07:00
{
2014-04-01 05:29:25 -07:00
nsCString data = nsPrintfCString ( " { \" x \" : %d, \" y \" : %d } " , aPoint . x , aPoint . y ) ;
2013-04-26 10:26:46 -07:00
nsAppShell : : gAppShell - > PostEvent ( AndroidGeckoEvent : : MakeBroadcastEvent (
NS_LITERAL_CSTRING ( " Gesture:DoubleTap " ) , data ) ) ;
2013-04-26 10:24:28 -07:00
}
void
2014-03-12 12:27:45 -07:00
AndroidBridge : : HandleSingleTap ( const CSSPoint & aPoint ,
2014-02-07 09:13:50 -08:00
int32_t aModifiers ,
const mozilla : : layers : : ScrollableLayerGuid & aGuid )
2013-04-26 10:24:28 -07:00
{
2013-11-25 20:30:26 -08:00
// TODO Send the modifier data to Gecko for use in mouse events.
2014-04-01 05:29:25 -07:00
nsCString data = nsPrintfCString ( " { \" x \" : %d, \" y \" : %d } " , aPoint . x , aPoint . y ) ;
2013-04-26 10:26:46 -07:00
nsAppShell : : gAppShell - > PostEvent ( AndroidGeckoEvent : : MakeBroadcastEvent (
NS_LITERAL_CSTRING ( " Gesture:SingleTap " ) , data ) ) ;
2013-04-26 10:24:28 -07:00
}
void
2014-03-12 12:27:45 -07:00
AndroidBridge : : HandleLongTap ( const CSSPoint & aPoint ,
2014-02-07 09:13:50 -08:00
int32_t aModifiers ,
const mozilla : : layers : : ScrollableLayerGuid & aGuid )
2013-04-26 10:24:28 -07:00
{
2014-04-01 05:29:25 -07:00
nsCString data = nsPrintfCString ( " { \" x \" : %d, \" y \" : %d } " , aPoint . x , aPoint . y ) ;
2013-04-26 10:26:46 -07:00
nsAppShell : : gAppShell - > PostEvent ( AndroidGeckoEvent : : MakeBroadcastEvent (
NS_LITERAL_CSTRING ( " Gesture:LongPress " ) , data ) ) ;
2013-04-26 10:24:28 -07:00
}
2013-12-11 16:39:06 -08:00
void
2014-03-12 12:27:45 -07:00
AndroidBridge : : HandleLongTapUp ( const CSSPoint & aPoint ,
2014-02-07 09:13:50 -08:00
int32_t aModifiers ,
const mozilla : : layers : : ScrollableLayerGuid & aGuid )
2013-12-11 16:39:06 -08:00
{
}
2013-04-26 10:24:28 -07:00
void
2013-11-08 16:07:00 -08:00
AndroidBridge : : SendAsyncScrollDOMEvent ( bool aIsRoot ,
2013-07-30 11:03:42 -07:00
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-11-12 10:41:01 -08:00
mNativePanZoomController - > PostDelayedCallbackWrapper ( ( 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
}
2014-06-04 12:28:04 -07:00
jobject AndroidBridge : : ChannelCreate ( jobject stream ) {
JNIEnv * env = GetJNIForThread ( ) ;
env - > PushLocalFrame ( 1 ) ;
jobject channel = env - > CallStaticObjectMethod ( sBridge - > jReadableByteChannel , sBridge - > jChannelCreate , stream ) ;
return env - > PopLocalFrame ( channel ) ;
}
void AndroidBridge : : InputStreamClose ( jobject obj ) {
JNIEnv * env = GetJNIForThread ( ) ;
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
env - > CallVoidMethod ( obj , sBridge - > jClose ) ;
}
uint32_t AndroidBridge : : InputStreamAvailable ( jobject obj ) {
JNIEnv * env = GetJNIForThread ( ) ;
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
return env - > CallIntMethod ( obj , sBridge - > jAvailable ) ;
}
nsresult AndroidBridge : : InputStreamRead ( jobject obj , char * aBuf , uint32_t aCount , uint32_t * aRead ) {
JNIEnv * env = GetJNIForThread ( ) ;
AutoLocalJNIFrame jniFrame ( env , 1 ) ;
jobject arr = env - > NewDirectByteBuffer ( aBuf , aCount ) ;
jint read = env - > CallIntMethod ( obj , sBridge - > jByteBufferRead , arr ) ;
if ( env - > ExceptionCheck ( ) ) {
env - > ExceptionClear ( ) ;
return NS_ERROR_FAILURE ;
}
if ( read < = 0 ) {
* aRead = 0 ;
return NS_OK ;
}
* aRead = read ;
return NS_OK ;
}