/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */#include"mozilla/Hal.h"#include"nsIFile.h"#include"nsString.h"#include"AndroidBridge.h"#include"AndroidGraphicBuffer.h"#include<jni.h>#include<pthread.h>#include<dlfcn.h>#include<stdio.h>#include<unistd.h>#include"nsAppShell.h"#include"nsWindow.h"#include<android/log.h>#include"nsIObserverService.h"#include"mozilla/Services.h"#include"nsINetworkLinkService.h"#ifdef MOZ_CRASHREPORTER#include"nsICrashReporter.h"#include"nsExceptionHandler.h"#endif#include"mozilla/unused.h"#include"mozilla/dom/sms/SmsMessage.h"#include"mozilla/dom/sms/Constants.h"#include"mozilla/dom/sms/Types.h"#include"mozilla/dom/sms/PSms.h"#include"mozilla/dom/sms/SmsParent.h"#include"nsISmsRequestManager.h"#include"nsISmsDatabaseService.h"#include"nsPluginInstanceOwner.h"usingnamespacemozilla;usingnamespacemozilla::dom::sms;/* Forward declare all the JNI methods as extern "C" */extern"C"{/* * Incoming JNI methods */NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_nativeInit(JNIEnv*jenv,jclassjc){AndroidBridge::ConstructBridge(jenv,jc);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_notifyGeckoOfEvent(JNIEnv*jenv,jclassjc,jobjectevent){// poke the appshellif(nsAppShell::gAppShell)nsAppShell::gAppShell->PostEvent(newAndroidGeckoEvent(jenv,event));}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_processNextNativeEvent(JNIEnv*jenv,jclass){// poke the appshellif(nsAppShell::gAppShell)nsAppShell::gAppShell->ProcessNextNativeEvent(false);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_setSurfaceView(JNIEnv*jenv,jclass,jobjectobj){AndroidBridge::Bridge()->SetSurfaceView(jenv->NewGlobalRef(obj));}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_setLayerClient(JNIEnv*jenv,jclass,jobjectobj){AndroidBridge::Bridge()->SetLayerClient(jenv,obj);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_onLowMemory(JNIEnv*jenv,jclassjc){if(nsAppShell::gAppShell){nsAppShell::gAppShell->NotifyObservers(nsnull,"memory-pressure",NS_LITERAL_STRING("low-memory").get());}}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_onResume(JNIEnv*jenv,jclassjc){if(nsAppShell::gAppShell)nsAppShell::gAppShell->OnResume();}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_callObserver(JNIEnv*jenv,jclass,jstringjObserverKey,jstringjTopic,jstringjData){if(!nsAppShell::gAppShell)return;nsJNIStringsObserverKey(jObserverKey,jenv);nsJNIStringsTopic(jTopic,jenv);nsJNIStringsData(jData,jenv);nsAppShell::gAppShell->CallObserver(sObserverKey,sTopic,sData);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_removeObserver(JNIEnv*jenv,jclass,jstringjObserverKey){if(!nsAppShell::gAppShell)return;constjchar*observerKey=jenv->GetStringChars(jObserverKey,NULL);nsStringsObserverKey(observerKey);sObserverKey.SetLength(jenv->GetStringLength(jObserverKey));jenv->ReleaseStringChars(jObserverKey,observerKey);nsAppShell::gAppShell->RemoveObserver(sObserverKey);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus(JNIEnv*jenv,jclass,jstringjStatus){if(!nsAppShell::gAppShell)return;nsJNIStringsStatus(jStatus,jenv);nsAppShell::gAppShell->NotifyObservers(nsnull,NS_NETWORK_LINK_TOPIC,sStatus.get());}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_reportJavaCrash(JNIEnv*jenv,jclass,jstringjStackTrace){#ifdef MOZ_CRASHREPORTERconstnsJNIStringstackTrace16(jStackTrace,jenv);constNS_ConvertUTF16toUTF8stackTrace8(stackTrace16);CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("JavaStackTrace"),stackTrace8);#endif // MOZ_CRASHREPORTERabort();}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_executeNextRunnable(JNIEnv*jenv,jclass){__android_log_print(ANDROID_LOG_INFO,"GeckoJNI","%s",__PRETTY_FUNCTION__);if(!AndroidBridge::Bridge()){__android_log_print(ANDROID_LOG_INFO,"GeckoJNI","no bridge in %s!!!!",__PRETTY_FUNCTION__);return;}AndroidBridge::Bridge()->ExecuteNextRunnable(jenv);__android_log_print(ANDROID_LOG_INFO,"GeckoJNI","leaving %s",__PRETTY_FUNCTION__);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_notifyBatteryChange(JNIEnv*jenv,jclass,jdoubleaLevel,jbooleanaCharging,jdoubleaRemainingTime){classNotifyBatteryChangeRunnable:publicnsRunnable{public:NotifyBatteryChangeRunnable(doubleaLevel,boolaCharging,doubleaRemainingTime):mLevel(aLevel),mCharging(aCharging),mRemainingTime(aRemainingTime){}NS_IMETHODIMPRun(){hal::NotifyBatteryChange(hal::BatteryInformation(mLevel,mCharging,mRemainingTime));returnNS_OK;}private:doublemLevel;boolmCharging;doublemRemainingTime;};nsCOMPtr<nsIRunnable>runnable=newNotifyBatteryChangeRunnable(aLevel,aCharging,aRemainingTime);NS_DispatchToMainThread(runnable);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_notifySmsReceived(JNIEnv*jenv,jclass,jstringaSender,jstringaBody,jlongaTimestamp){classNotifySmsReceivedRunnable:publicnsRunnable{public:NotifySmsReceivedRunnable(constSmsMessageData&aMessageData)\:mMessageData(aMessageData){}NS_IMETHODIMPRun(){nsCOMPtr<nsIObserverService>obs=services::GetObserverService();if(!obs){returnNS_OK;}nsCOMPtr<nsIDOMMozSmsMessage>message=newSmsMessage(mMessageData);obs->NotifyObservers(message,kSmsReceivedObserverTopic,nsnull);returnNS_OK;}private:SmsMessageDatamMessageData;};SmsMessageDatamessage(0,eDeliveryState_Received,nsJNIString(aSender,jenv),EmptyString(),nsJNIString(aBody,jenv),aTimestamp,false);nsCOMPtr<nsIRunnable>runnable=newNotifySmsReceivedRunnable(message);NS_DispatchToMainThread(runnable);}NS_EXPORTPRInt32JNICALLJava_org_mozilla_gecko_GeckoAppShell_saveMessageInSentbox(JNIEnv*jenv,jclass,jstringaReceiver,jstringaBody,jlongaTimestamp){nsCOMPtr<nsISmsDatabaseService>smsDBService=do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);if(!smsDBService){NS_ERROR("Sms Database Service not available!");return-1;}PRInt32id;smsDBService->SaveSentMessage(nsJNIString(aReceiver,jenv),nsJNIString(aBody,jenv),aTimestamp,&id);returnid;}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_notifySmsSent(JNIEnv*jenv,jclass,jintaId,jstringaReceiver,jstringaBody,jlongaTimestamp,jintaRequestId,jlongaProcessId){classNotifySmsSentRunnable:publicnsRunnable{public:NotifySmsSentRunnable(constSmsMessageData&aMessageData,PRInt32aRequestId,PRUint64aProcessId):mMessageData(aMessageData),mRequestId(aRequestId),mProcessId(aProcessId){}NS_IMETHODIMPRun(){/* * First, we are going to notify all SmsManager that a message has * been sent. Then, we will notify the SmsRequest object about it. */nsCOMPtr<nsIObserverService>obs=services::GetObserverService();if(!obs){returnNS_OK;}nsCOMPtr<nsIDOMMozSmsMessage>message=newSmsMessage(mMessageData);obs->NotifyObservers(message,kSmsSentObserverTopic,nsnull);if(mProcessId==0){// Parent process.nsCOMPtr<nsISmsRequestManager>requestManager=do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);if(requestManager){requestManager->NotifySmsSent(mRequestId,message);}}else{// Content process.nsTArray<SmsParent*>spList;SmsParent::GetAll(spList);for(PRUint32i=0;i<spList.Length();++i){unused<<spList[i]->SendNotifyRequestSmsSent(mMessageData,mRequestId,mProcessId);}}returnNS_OK;}private:SmsMessageDatamMessageData;PRInt32mRequestId;PRUint64mProcessId;};SmsMessageDatamessage(aId,eDeliveryState_Sent,EmptyString(),nsJNIString(aReceiver,jenv),nsJNIString(aBody,jenv),aTimestamp,true);nsCOMPtr<nsIRunnable>runnable=newNotifySmsSentRunnable(message,aRequestId,aProcessId);NS_DispatchToMainThread(runnable);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_notifySmsDelivered(JNIEnv*jenv,jclass,jintaId,jstringaReceiver,jstringaBody,jlongaTimestamp){classNotifySmsDeliveredRunnable:publicnsRunnable{public:NotifySmsDeliveredRunnable(constSmsMessageData&aMessageData):mMessageData(aMessageData){}NS_IMETHODIMPRun(){nsCOMPtr<nsIObserverService>obs=services::GetObserverService();if(!obs){returnNS_OK;}nsCOMPtr<nsIDOMMozSmsMessage>message=newSmsMessage(mMessageData);obs->NotifyObservers(message,kSmsDeliveredObserverTopic,nsnull);returnNS_OK;}private:SmsMessageDatamMessageData;};SmsMessageDatamessage(aId,eDeliveryState_Sent,EmptyString(),nsJNIString(aReceiver,jenv),nsJNIString(aBody,jenv),aTimestamp,true);nsCOMPtr<nsIRunnable>runnable=newNotifySmsDeliveredRunnable(message);NS_DispatchToMainThread(runnable);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_notifySmsSendFailed(JNIEnv*jenv,jclass,jintaError,jintaRequestId,jlongaProcessId){classNotifySmsSendFailedRunnable:publicnsRunnable{public:NotifySmsSendFailedRunnable(PRInt32aError,PRInt32aRequestId,PRUint64aProcessId):mError(aError),mRequestId(aRequestId),mProcessId(aProcessId){}NS_IMETHODIMPRun(){if(mProcessId==0){// Parent process.nsCOMPtr<nsISmsRequestManager>requestManager=do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);if(requestManager){requestManager->NotifySmsSendFailed(mRequestId,mError);}}else{// Content process.nsTArray<SmsParent*>spList;SmsParent::GetAll(spList);for(PRUint32i=0;i<spList.Length();++i){unused<<spList[i]->SendNotifyRequestSmsSendFailed(mError,mRequestId,mProcessId);}}returnNS_OK;}private:PRInt32mError;PRInt32mRequestId;PRUint64mProcessId;};nsCOMPtr<nsIRunnable>runnable=newNotifySmsSendFailedRunnable(aError,aRequestId,aProcessId);NS_DispatchToMainThread(runnable);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_notifyGetSms(JNIEnv*jenv,jclass,jintaId,jstringaReceiver,jstringaSender,jstringaBody,jlongaTimestamp,jintaRequestId,jlongaProcessId){classNotifyGetSmsRunnable:publicnsRunnable{public:NotifyGetSmsRunnable(constSmsMessageData&aMessageData,PRInt32aRequestId,PRUint64aProcessId):mMessageData(aMessageData),mRequestId(aRequestId),mProcessId(aProcessId){}NS_IMETHODIMPRun(){if(mProcessId==0){// Parent process.nsCOMPtr<nsIDOMMozSmsMessage>message=newSmsMessage(mMessageData);nsCOMPtr<nsISmsRequestManager>requestManager=do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);if(requestManager){requestManager->NotifyGotSms(mRequestId,message);}}else{// Content process.nsTArray<SmsParent*>spList;SmsParent::GetAll(spList);for(PRUint32i=0;i<spList.Length();++i){unused<<spList[i]->SendNotifyRequestGotSms(mMessageData,mRequestId,mProcessId);}}returnNS_OK;}private:SmsMessageDatamMessageData;PRInt32mRequestId;PRUint64mProcessId;};nsJNIStringreceiver=nsJNIString(aReceiver,jenv);DeliveryStatestate=receiver.IsEmpty()?eDeliveryState_Received:eDeliveryState_Sent;// TODO Need to add the message `read` parameter value. Bug 748391SmsMessageDatamessage(aId,state,nsJNIString(aSender,jenv),receiver,nsJNIString(aBody,jenv),aTimestamp,true);nsCOMPtr<nsIRunnable>runnable=newNotifyGetSmsRunnable(message,aRequestId,aProcessId);NS_DispatchToMainThread(runnable);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_notifyGetSmsFailed(JNIEnv*jenv,jclass,jintaError,jintaRequestId,jlongaProcessId){classNotifyGetSmsFailedRunnable:publicnsRunnable{public:NotifyGetSmsFailedRunnable(PRInt32aError,PRInt32aRequestId,PRUint64aProcessId):mError(aError),mRequestId(aRequestId),mProcessId(aProcessId){}NS_IMETHODIMPRun(){if(mProcessId==0){// Parent process.nsCOMPtr<nsISmsRequestManager>requestManager=do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);if(requestManager){requestManager->NotifyGetSmsFailed(mRequestId,mError);}}else{// Content process.nsTArray<SmsParent*>spList;SmsParent::GetAll(spList);for(PRUint32i=0;i<spList.Length();++i){unused<<spList[i]->SendNotifyRequestGetSmsFailed(mError,mRequestId,mProcessId);}}returnNS_OK;}private:PRInt32mError;PRInt32mRequestId;PRUint64mProcessId;};nsCOMPtr<nsIRunnable>runnable=newNotifyGetSmsFailedRunnable(aError,aRequestId,aProcessId);NS_DispatchToMainThread(runnable);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_notifySmsDeleted(JNIEnv*jenv,jclass,jbooleanaDeleted,jintaRequestId,jlongaProcessId){classNotifySmsDeletedRunnable:publicnsRunnable{public:NotifySmsDeletedRunnable(boolaDeleted,PRInt32aRequestId,PRUint64aProcessId):mDeleted(aDeleted),mRequestId(aRequestId),mProcessId(aProcessId){}NS_IMETHODIMPRun(){if(mProcessId==0){// Parent process.nsCOMPtr<nsISmsRequestManager>requestManager=do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);if(requestManager){requestManager->NotifySmsDeleted(mRequestId,mDeleted);}}else{// Content process.nsTArray<SmsParent*>spList;SmsParent::GetAll(spList);for(PRUint32i=0;i<spList.Length();++i){unused<<spList[i]->SendNotifyRequestSmsDeleted(mDeleted,mRequestId,mProcessId);}}returnNS_OK;}private:boolmDeleted;PRInt32mRequestId;PRUint64mProcessId;};nsCOMPtr<nsIRunnable>runnable=newNotifySmsDeletedRunnable(aDeleted,aRequestId,aProcessId);NS_DispatchToMainThread(runnable);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_notifySmsDeleteFailed(JNIEnv*jenv,jclass,jintaError,jintaRequestId,jlongaProcessId){classNotifySmsDeleteFailedRunnable:publicnsRunnable{public:NotifySmsDeleteFailedRunnable(PRInt32aError,PRInt32aRequestId,PRUint64aProcessId):mError(aError),mRequestId(aRequestId),mProcessId(aProcessId){}NS_IMETHODIMPRun(){if(mProcessId==0){// Parent process.nsCOMPtr<nsISmsRequestManager>requestManager=do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);if(requestManager){requestManager->NotifySmsDeleteFailed(mRequestId,mError);}}else{// Content process.nsTArray<SmsParent*>spList;SmsParent::GetAll(spList);for(PRUint32i=0;i<spList.Length();++i){unused<<spList[i]->SendNotifyRequestSmsDeleteFailed(mError,mRequestId,mProcessId);}}returnNS_OK;}private:PRInt32mError;PRInt32mRequestId;PRUint64mProcessId;};nsCOMPtr<nsIRunnable>runnable=newNotifySmsDeleteFailedRunnable(aError,aRequestId,aProcessId);NS_DispatchToMainThread(runnable);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_notifyNoMessageInList(JNIEnv*jenv,jclass,jintaRequestId,jlongaProcessId){classNotifyNoMessageInListRunnable:publicnsRunnable{public:NotifyNoMessageInListRunnable(PRInt32aRequestId,PRUint64aProcessId):mRequestId(aRequestId),mProcessId(aProcessId){}NS_IMETHODIMPRun(){if(mProcessId==0){// Parent process.nsCOMPtr<nsISmsRequestManager>requestManager=do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);if(requestManager){requestManager->NotifyNoMessageInList(mRequestId);}}else{// Content process.nsTArray<SmsParent*>spList;SmsParent::GetAll(spList);for(PRUint32i=0;i<spList.Length();++i){unused<<spList[i]->SendNotifyRequestNoMessageInList(mRequestId,mProcessId);}}returnNS_OK;}private:PRInt32mRequestId;PRUint64mProcessId;};nsCOMPtr<nsIRunnable>runnable=newNotifyNoMessageInListRunnable(aRequestId,aProcessId);NS_DispatchToMainThread(runnable);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_notifyListCreated(JNIEnv*jenv,jclass,jintaListId,jintaMessageId,jstringaReceiver,jstringaSender,jstringaBody,jlongaTimestamp,jintaRequestId,jlongaProcessId){classNotifyCreateMessageListRunnable:publicnsRunnable{public:NotifyCreateMessageListRunnable(PRInt32aListId,constSmsMessageData&aMessage,PRInt32aRequestId,PRUint64aProcessId):mListId(aListId),mMessage(aMessage),mRequestId(aRequestId),mProcessId(aProcessId){}NS_IMETHODIMPRun(){if(mProcessId==0){// Parent process.nsCOMPtr<nsIDOMMozSmsMessage>message=newSmsMessage(mMessage);nsCOMPtr<nsISmsRequestManager>requestManager=do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);if(requestManager){requestManager->NotifyCreateMessageList(mRequestId,mListId,message);}}else{// Content process.nsTArray<SmsParent*>spList;SmsParent::GetAll(spList);for(PRUint32i=0;i<spList.Length();++i){unused<<spList[i]->SendNotifyRequestCreateMessageList(mListId,mMessage,mRequestId,mProcessId);}}returnNS_OK;}private:PRInt32mListId;SmsMessageDatamMessage;PRInt32mRequestId;PRUint64mProcessId;};nsJNIStringreceiver=nsJNIString(aReceiver,jenv);DeliveryStatestate=receiver.IsEmpty()?eDeliveryState_Received:eDeliveryState_Sent;// TODO Need to add the message `read` parameter value. Bug 748391SmsMessageDatamessage(aMessageId,state,nsJNIString(aSender,jenv),receiver,nsJNIString(aBody,jenv),aTimestamp,true);nsCOMPtr<nsIRunnable>runnable=newNotifyCreateMessageListRunnable(aListId,message,aRequestId,aProcessId);NS_DispatchToMainThread(runnable);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_notifyGotNextMessage(JNIEnv*jenv,jclass,jintaMessageId,jstringaReceiver,jstringaSender,jstringaBody,jlongaTimestamp,jintaRequestId,jlongaProcessId){classNotifyGotNextMessageRunnable:publicnsRunnable{public:NotifyGotNextMessageRunnable(constSmsMessageData&aMessage,PRInt32aRequestId,PRUint64aProcessId):mMessage(aMessage),mRequestId(aRequestId),mProcessId(aProcessId){}NS_IMETHODIMPRun(){if(mProcessId==0){// Parent process.nsCOMPtr<nsIDOMMozSmsMessage>message=newSmsMessage(mMessage);nsCOMPtr<nsISmsRequestManager>requestManager=do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);if(requestManager){requestManager->NotifyGotNextMessage(mRequestId,message);}}else{// Content process.nsTArray<SmsParent*>spList;SmsParent::GetAll(spList);for(PRUint32i=0;i<spList.Length();++i){unused<<spList[i]->SendNotifyRequestGotNextMessage(mMessage,mRequestId,mProcessId);}}returnNS_OK;}private:SmsMessageDatamMessage;PRInt32mRequestId;PRUint64mProcessId;};nsJNIStringreceiver=nsJNIString(aReceiver,jenv);DeliveryStatestate=receiver.IsEmpty()?eDeliveryState_Received:eDeliveryState_Sent;// TODO Need to add the message `read` parameter value. Bug 748391SmsMessageDatamessage(aMessageId,state,nsJNIString(aSender,jenv),receiver,nsJNIString(aBody,jenv),aTimestamp,true);nsCOMPtr<nsIRunnable>runnable=newNotifyGotNextMessageRunnable(message,aRequestId,aProcessId);NS_DispatchToMainThread(runnable);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_notifyReadingMessageListFailed(JNIEnv*jenv,jclass,jintaError,jintaRequestId,jlongaProcessId){classNotifyReadListFailedRunnable:publicnsRunnable{public:NotifyReadListFailedRunnable(PRInt32aError,PRInt32aRequestId,PRUint64aProcessId):mError(aError),mRequestId(aRequestId),mProcessId(aProcessId){}NS_IMETHODIMPRun(){if(mProcessId==0){// Parent process.nsCOMPtr<nsISmsRequestManager>requestManager=do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);if(requestManager){requestManager->NotifyReadMessageListFailed(mRequestId,mError);}}else{// Content process.nsTArray<SmsParent*>spList;SmsParent::GetAll(spList);for(PRUint32i=0;i<spList.Length();++i){unused<<spList[i]->SendNotifyRequestReadListFailed(mError,mRequestId,mProcessId);}}returnNS_OK;}private:PRInt32mError;PRInt32mRequestId;PRUint64mProcessId;};nsCOMPtr<nsIRunnable>runnable=newNotifyReadListFailedRunnable(aError,aRequestId,aProcessId);NS_DispatchToMainThread(runnable);}#ifdef MOZ_JAVA_COMPOSITORNS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_scheduleComposite(JNIEnv*,jclass){nsWindow::ScheduleComposite();}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_schedulePauseComposition(JNIEnv*,jclass){nsWindow::SchedulePauseComposition();}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_scheduleResumeComposition(JNIEnv*,jclass,jintwidth,jintheight){nsWindow::ScheduleResumeComposition(width,height);}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_notifyFilePickerResult(JNIEnv*jenv,jclass,jstringfilePath,jlongcallback){classNotifyFilePickerResultRunnable:publicnsRunnable{public:NotifyFilePickerResultRunnable(nsString&fileDir,longcallback):mFileDir(fileDir),mCallback(callback){}NS_IMETHODIMPRun(){nsFilePickerCallback*handler=(nsFilePickerCallback*)mCallback;handler->handleResult(mFileDir);handler->Release();returnNS_OK;}private:nsStringmFileDir;longmCallback;};nsStringpath=nsJNIString(filePath,jenv);nsCOMPtr<nsIRunnable>runnable=newNotifyFilePickerResultRunnable(path,(long)callback);NS_DispatchToMainThread(runnable);}staticintNextPowerOfTwo(intvalue){// code taken from http://acius2.blogspot.com/2007/11/calculating-next-power-of-2.htmlif(0==value--){return1;}value=(value>>1)|value;value=(value>>2)|value;value=(value>>4)|value;value=(value>>8)|value;value=(value>>16)|value;returnvalue+1;}#define MAX_LOCK_ATTEMPTS 10staticboolLockWindowWithRetry(void*window,unsignedchar**bits,int*width,int*height,int*format,int*stride){intcount=0;while(count<MAX_LOCK_ATTEMPTS){if(AndroidBridge::Bridge()->LockWindow(window,bits,width,height,format,stride))returntrue;count++;usleep(500);}returnfalse;}NS_EXPORTjobjectJNICALLJava_org_mozilla_gecko_GeckoAppShell_getSurfaceBits(JNIEnv*jenv,jclass,jobjectsurface){staticjclassjSurfaceBitsClass=nsnull;staticjmethodIDjSurfaceBitsCtor=0;staticjfieldIDjSurfaceBitsWidth,jSurfaceBitsHeight,jSurfaceBitsFormat,jSurfaceBitsBuffer;jobjectsurfaceBits=nsnull;unsignedchar*bitsCopy=nsnull;intdstWidth,dstHeight,dstSize;void*window=AndroidBridge::Bridge()->AcquireNativeWindow(jenv,surface);if(!window)returnnsnull;unsignedchar*bits;intsrcWidth,srcHeight,format,srcStride;// So we lock/unlock once here in order to get whatever is currently the front buffer. It sucks.if(!LockWindowWithRetry(window,&bits,&srcWidth,&srcHeight,&format,&srcStride))returnnsnull;AndroidBridge::Bridge()->UnlockWindow(window);// This is lock will result in the front buffer, since the last unlock rotated it to the back. Probably.if(!LockWindowWithRetry(window,&bits,&srcWidth,&srcHeight,&format,&srcStride))returnnsnull;// These are from android.graphics.PixelFormatintbpp;switch(format){case1:// RGBA_8888bpp=4;break;case4:// RGB_565bpp=2;break;default:gotocleanup;}dstWidth=NextPowerOfTwo(srcWidth);dstHeight=NextPowerOfTwo(srcHeight);dstSize=dstWidth*dstHeight*bpp;bitsCopy=(unsignedchar*)malloc(dstSize);bzero(bitsCopy,dstSize);for(inti=0;i<srcHeight;i++){memcpy(bitsCopy+((dstHeight-i-1)*dstWidth*bpp),bits+(i*srcStride*bpp),srcStride*bpp);}if(!jSurfaceBitsClass){jSurfaceBitsClass=(jclass)jenv->NewGlobalRef(jenv->FindClass("org/mozilla/gecko/SurfaceBits"));jSurfaceBitsCtor=jenv->GetMethodID(jSurfaceBitsClass,"<init>","()V");jSurfaceBitsWidth=jenv->GetFieldID(jSurfaceBitsClass,"width","I");jSurfaceBitsHeight=jenv->GetFieldID(jSurfaceBitsClass,"height","I");jSurfaceBitsFormat=jenv->GetFieldID(jSurfaceBitsClass,"format","I");jSurfaceBitsBuffer=jenv->GetFieldID(jSurfaceBitsClass,"buffer","Ljava/nio/ByteBuffer;");}surfaceBits=jenv->NewObject(jSurfaceBitsClass,jSurfaceBitsCtor);jenv->SetIntField(surfaceBits,jSurfaceBitsWidth,dstWidth);jenv->SetIntField(surfaceBits,jSurfaceBitsHeight,dstHeight);jenv->SetIntField(surfaceBits,jSurfaceBitsFormat,format);jenv->SetObjectField(surfaceBits,jSurfaceBitsBuffer,jenv->NewDirectByteBuffer(bitsCopy,dstSize));cleanup:AndroidBridge::Bridge()->UnlockWindow(window);AndroidBridge::Bridge()->ReleaseNativeWindow(window);returnsurfaceBits;}NS_EXPORTvoidJNICALLJava_org_mozilla_gecko_GeckoAppShell_onFullScreenPluginHidden(JNIEnv*jenv,jclass,jobjectview){classExitFullScreenRunnable:publicnsRunnable{public:ExitFullScreenRunnable(jobjectview):mView(view){}NS_IMETHODIMPRun(){JNIEnv*env=AndroidBridge::GetJNIEnv();if(!env){NS_WARNING("Failed to acquire JNI env, can't exit plugin fullscreen mode");returnNS_OK;}nsPluginInstanceOwner::ExitFullScreen(mView);env->DeleteGlobalRef(mView);returnNS_OK;}private:jobjectmView;};nsCOMPtr<nsIRunnable>runnable=newExitFullScreenRunnable(jenv->NewGlobalRef(view));NS_DispatchToMainThread(runnable);}NS_EXPORTjobjectJNICALLJava_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue(JNIEnv*jenv,jclass,jobjectqueue){staticjclassjMessageQueueCls=nsnull;staticjfieldIDjMessagesField;staticjmethodIDjNextMethod;if(!jMessageQueueCls){jMessageQueueCls=(jclass)jenv->NewGlobalRef(jenv->FindClass("android/os/MessageQueue"));jMessagesField=jenv->GetFieldID(jMessageQueueCls,"mMessages","Landroid/os/Message;");jNextMethod=jenv->GetMethodID(jMessageQueueCls,"next","()Landroid/os/Message;");}if(!jMessageQueueCls||!jMessagesField||!jNextMethod)returnNULL;jobjectmsg=jenv->GetObjectField(queue,jMessagesField);// if queue.mMessages is null, queue.next() will block, which we don't wantif(!msg)returnmsg;msg=jenv->CallObjectMethod(queue,jNextMethod);returnmsg;}#endif}