From 3b3622d5ae66f4627d91106c89ed412e64066c1a Mon Sep 17 00:00:00 2001 From: Doug Turner Date: Fri, 16 Sep 2011 14:34:31 -0700 Subject: [PATCH 1/5] Bug 630007 - Minimal support NPAPI on ANDROID. Pre-Honeycomb inproccess support only. r=josh. --- dom/plugins/base/Makefile.in | 7 +- dom/plugins/base/PluginPRLibrary.cpp | 34 +- dom/plugins/base/PluginPRLibrary.h | 8 +- dom/plugins/base/android/ANPAudio.cpp | 361 ++++++++ dom/plugins/base/android/ANPBase.h | 90 ++ dom/plugins/base/android/ANPBitmap.cpp | 118 +++ dom/plugins/base/android/ANPCanvas.cpp | 373 ++++++++ dom/plugins/base/android/ANPEvent.cpp | 84 ++ dom/plugins/base/android/ANPKeyCodes.h | 152 ++++ dom/plugins/base/android/ANPLog.cpp | 59 ++ dom/plugins/base/android/ANPMatrix.cpp | 197 +++++ dom/plugins/base/android/ANPPaint.cpp | 454 ++++++++++ dom/plugins/base/android/ANPPath.cpp | 171 ++++ dom/plugins/base/android/ANPSurface.cpp | 189 ++++ dom/plugins/base/android/ANPSystem.cpp | 86 ++ dom/plugins/base/android/ANPTypeface.cpp | 151 ++++ dom/plugins/base/android/ANPWindow.cpp | 91 ++ dom/plugins/base/android/Makefile.in | 81 ++ dom/plugins/base/android/android_npapi.h | 979 +++++++++++++++++++++ dom/plugins/base/android_npapi.h | 0 dom/plugins/base/npfunctions.h | 13 +- dom/plugins/base/nsNPAPIPlugin.cpp | 125 ++- dom/plugins/base/nsNPAPIPluginInstance.cpp | 114 ++- dom/plugins/base/nsNPAPIPluginInstance.h | 16 + dom/plugins/base/nsPluginHost.cpp | 11 +- dom/plugins/base/nsPluginInstanceOwner.cpp | 313 ++++++- dom/plugins/base/nsPluginInstanceOwner.h | 7 +- dom/plugins/base/nsPluginsDirUnix.cpp | 10 + embedding/android/AndroidManifest.xml.in | 7 + embedding/android/GeckoApp.java | 162 +++- embedding/android/GeckoAppShell.java | 197 +++++ embedding/android/Makefile.in | 1 + embedding/android/SurfaceLockInfo.java | 18 + layout/build/Makefile.in | 1 + layout/generic/nsObjectFrame.cpp | 16 + other-licenses/android/APKOpen.cpp | 2 + widget/src/android/AndroidBridge.cpp | 50 +- widget/src/android/AndroidBridge.h | 8 + widget/src/android/AndroidJNI.cpp | 13 + 39 files changed, 4745 insertions(+), 24 deletions(-) create mode 100644 dom/plugins/base/android/ANPAudio.cpp create mode 100644 dom/plugins/base/android/ANPBase.h create mode 100644 dom/plugins/base/android/ANPBitmap.cpp create mode 100644 dom/plugins/base/android/ANPCanvas.cpp create mode 100644 dom/plugins/base/android/ANPEvent.cpp create mode 100644 dom/plugins/base/android/ANPKeyCodes.h create mode 100644 dom/plugins/base/android/ANPLog.cpp create mode 100644 dom/plugins/base/android/ANPMatrix.cpp create mode 100644 dom/plugins/base/android/ANPPaint.cpp create mode 100644 dom/plugins/base/android/ANPPath.cpp create mode 100644 dom/plugins/base/android/ANPSurface.cpp create mode 100644 dom/plugins/base/android/ANPSystem.cpp create mode 100644 dom/plugins/base/android/ANPTypeface.cpp create mode 100644 dom/plugins/base/android/ANPWindow.cpp create mode 100644 dom/plugins/base/android/Makefile.in create mode 100644 dom/plugins/base/android/android_npapi.h create mode 100644 dom/plugins/base/android_npapi.h create mode 100644 embedding/android/SurfaceLockInfo.java diff --git a/dom/plugins/base/Makefile.in b/dom/plugins/base/Makefile.in index 4c7a50e0ba0..402fe776554 100644 --- a/dom/plugins/base/Makefile.in +++ b/dom/plugins/base/Makefile.in @@ -99,6 +99,11 @@ CPPSRCS = \ nsPluginInstanceOwner.cpp \ $(NULL) +ifeq ($(MOZ_WIDGET_TOOLKIT),android) +DIRS += android +LOCAL_INCLUDES += -I$(topsrcdir)/dom/plugins/base/android +endif + ifeq ($(OS_ARCH),WINNT) CPPSRCS += nsPluginsDirWin.cpp CPPSRCS += nsPluginNativeWindowWin.cpp @@ -127,7 +132,7 @@ endif endif endif -LOCAL_INCLUDES = \ +LOCAL_INCLUDES += \ -I$(topsrcdir)/xpcom/base/ \ $(MOZ_CAIRO_CFLAGS) \ $(NULL) diff --git a/dom/plugins/base/PluginPRLibrary.cpp b/dom/plugins/base/PluginPRLibrary.cpp index 2eeeb53bec1..8fbbb3c345a 100644 --- a/dom/plugins/base/PluginPRLibrary.cpp +++ b/dom/plugins/base/PluginPRLibrary.cpp @@ -37,7 +37,6 @@ * ***** END LICENSE BLOCK ***** */ #include "mozilla/PluginPRLibrary.h" - // Some plugins on Windows, notably Quake Live, implement NP_Initialize using // cdecl instead of the documented stdcall. In order to work around this, // we force the caller to use a frame pointer. @@ -52,9 +51,38 @@ static int gNotOptimized; #define CALLING_CONVENTION_HACK #endif -namespace mozilla { +#ifdef ANDROID +#include "AndroidBridge.h" +#include "android_npapi.h" +#include +#define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoJavaEnv", ## args) +#endif -#if defined(XP_UNIX) && !defined(XP_MACOSX) +namespace mozilla { +#ifdef ANDROID +nsresult +PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs, + NPPluginFuncs* pFuncs, NPError* error) +{ + if (mNP_Initialize) { + *error = mNP_Initialize(bFuncs, pFuncs, GetJNIForThread()); + } else { + NP_InitializeFunc pfNP_Initialize = (NP_InitializeFunc) + PR_FindFunctionSymbol(mLibrary, "NP_Initialize"); + if (!pfNP_Initialize) + return NS_ERROR_FAILURE; + *error = pfNP_Initialize(bFuncs, pFuncs, GetJNIForThread()); + } + + + // Save pointers to functions that get called through PluginLibrary itself. + mNPP_New = pFuncs->newp; + mNPP_GetValue = pFuncs->getvalue; + mNPP_ClearSiteData = pFuncs->clearsitedata; + mNPP_GetSitesWithData = pFuncs->getsiteswithdata; + return NS_OK; +} +#elif defined(XP_UNIX) && !defined(XP_MACOSX) nsresult PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error) diff --git a/dom/plugins/base/PluginPRLibrary.h b/dom/plugins/base/PluginPRLibrary.h index 250d1ac92bb..2dbcb5ec2df 100644 --- a/dom/plugins/base/PluginPRLibrary.h +++ b/dom/plugins/base/PluginPRLibrary.h @@ -63,9 +63,11 @@ public: mNP_GetEntryPoints(nsnull), #endif mNPP_New(nsnull), + mNPP_GetValue(nsnull), mNPP_ClearSiteData(nsnull), mNPP_GetSitesWithData(nsnull), - mLibrary(aLibrary) + mLibrary(aLibrary), + mFilePath(aFilePath) { NS_ASSERTION(mLibrary, "need non-null lib"); // addref here?? @@ -159,6 +161,8 @@ public: const nsGUIEvent& anEvent, bool* handled); #endif + virtual void GetLibraryPath(nsACString& aPath) { aPath.Assign(mFilePath); } + private: NP_InitializeFunc mNP_Initialize; NP_ShutdownFunc mNP_Shutdown; @@ -170,9 +174,11 @@ private: NP_GetEntryPointsFunc mNP_GetEntryPoints; #endif NPP_NewProcPtr mNPP_New; + NPP_GetValueProcPtr mNPP_GetValue; NPP_ClearSiteDataPtr mNPP_ClearSiteData; NPP_GetSitesWithDataPtr mNPP_GetSitesWithData; PRLibrary* mLibrary; + nsCString mFilePath; }; diff --git a/dom/plugins/base/android/ANPAudio.cpp b/dom/plugins/base/android/ANPAudio.cpp new file mode 100644 index 00000000000..d8f84ef4652 --- /dev/null +++ b/dom/plugins/base/android/ANPAudio.cpp @@ -0,0 +1,361 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Android NPAPI support code + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Doug Turner + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "base/basictypes.h" +#include "AndroidBridge.h" + +#include +#include +#include + +#include "assert.h" +#include "ANPBase.h" +#include "nsIThread.h" +#include "nsThreadUtils.h" + +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPluginsAudio" , ## args) +#define ASSIGN(obj, name) (obj)->name = anp_audio_##name + +/* android.media.AudioTrack */ +struct AudioTrack { + jclass at_class; + jmethodID constructor; + jmethodID flush; + jmethodID pause; + jmethodID play; + jmethodID setvol; + jmethodID stop; + jmethodID write; + jmethodID getpos; +}; + +enum AudioTrackMode { + MODE_STATIC = 0, + MODE_STREAM = 1 +}; + +/* android.media.AudioManager */ +enum AudioManagerStream { + STREAM_VOICE_CALL = 0, + STREAM_SYSTEM = 1, + STREAM_RING = 2, + STREAM_MUSIC = 3, + STREAM_ALARM = 4, + STREAM_NOTIFICATION = 5, + STREAM_DTMF = 8 +}; + +/* android.media.AudioFormat */ +enum AudioFormatChannel { + CHANNEL_OUT_MONO = 4, + CHANNEL_OUT_STEREO = 12 +}; + +enum AudioFormatEncoding { + ENCODING_PCM_16BIT = 2, + ENCODING_PCM_8BIT = 3 +}; + +static struct AudioTrack at; + +static jclass +init_jni_bindings(JNIEnv *jenv) { + jclass jc = jenv->FindClass("android/media/AudioTrack"); + + at.constructor = jenv->GetMethodID(jc, "", "(IIIIII)V"); + at.flush = jenv->GetMethodID(jc, "flush", "()V"); + at.pause = jenv->GetMethodID(jc, "pause", "()V"); + at.play = jenv->GetMethodID(jc, "play", "()V"); + at.setvol = jenv->GetMethodID(jc, "setStereoVolume", "(FF)I"); + at.stop = jenv->GetMethodID(jc, "stop", "()V"); + at.write = jenv->GetMethodID(jc, "write", "([BII)I"); + at.getpos = jenv->GetMethodID(jc, "getPlaybackHeadPosition", "()I"); + + return jc; +} + +struct ANPAudioTrack { + jobject output_unit; + jclass at_class; + + unsigned int rate; + unsigned int channels; + unsigned int bufferSize; + unsigned int isStopped; + unsigned int keepGoing; + + void* user; + ANPAudioCallbackProc proc; + ANPSampleFormat format; +}; + +class AudioRunnable : public nsRunnable +{ +public: + NS_DECL_NSIRUNNABLE + + AudioRunnable(ANPAudioTrack* aAudioTrack) { + mTrack = aAudioTrack; + } + + ANPAudioTrack* mTrack; +}; + +NS_IMETHODIMP +AudioRunnable::Run() +{ + JNIEnv* jenv = GetJNIForThread(); + + if (jenv->PushLocalFrame(128)) { + return NS_ERROR_FAILURE; + } + + jbyteArray bytearray = jenv->NewByteArray(mTrack->bufferSize); + if (!bytearray) { + LOG("AudioRunnable:: Run. Could not create bytearray"); + return NS_ERROR_FAILURE; + } + + jbyte *byte = jenv->GetByteArrayElements(bytearray, NULL); + if (!byte) { + LOG("AudioRunnable:: Run. Could not create bytearray"); + return NS_ERROR_FAILURE; + } + + ANPAudioBuffer buffer; + buffer.channelCount = mTrack->channels; + buffer.format = mTrack->format; + buffer.bufferData = (void*) byte; + + while (mTrack->keepGoing) + { + // reset the buffer size + buffer.size = mTrack->bufferSize; + + // Get data from the plugin + mTrack->proc(kMoreData_ANPAudioEvent, mTrack->user, &buffer); + + if (buffer.size == 0) { + LOG("%p - kMoreData_ANPAudioEvent", mTrack); + continue; + } + + size_t wroteSoFar = 0; + jint retval; + do { + retval = jenv->CallIntMethod(mTrack->output_unit, + at.write, + bytearray, + wroteSoFar, + buffer.size - wroteSoFar); + if (retval < 0) { + LOG("%p - Write failed %d", mTrack, retval); + break; + } + + wroteSoFar += retval; + + } while(wroteSoFar < buffer.size); + } + + jenv->DeleteGlobalRef(mTrack->output_unit); + jenv->DeleteGlobalRef(mTrack->at_class); + + free(mTrack); + + jenv->ReleaseByteArrayElements(bytearray, byte, 0); + jenv->PopLocalFrame(NULL); + + return NS_OK; +} + +ANPAudioTrack* +anp_audio_newTrack(uint32_t sampleRate, // sampling rate in Hz + ANPSampleFormat format, + int channelCount, // MONO=1, STEREO=2 + ANPAudioCallbackProc proc, + void* user) +{ + ANPAudioTrack *s = (ANPAudioTrack*) malloc(sizeof(ANPAudioTrack)); + if (s == NULL) { + return NULL; + } + + JNIEnv *jenv = GetJNIForThread(); + if (!jenv) + return NULL; + + s->at_class = init_jni_bindings(jenv); + s->rate = sampleRate; + s->channels = channelCount; + s->bufferSize = s->rate * s->channels; + s->isStopped = true; + s->keepGoing = false; + s->user = user; + s->proc = proc; + s->format = format; + + int jformat; + switch (format) { + case kPCM16Bit_ANPSampleFormat: + jformat = ENCODING_PCM_16BIT; + break; + case kPCM8Bit_ANPSampleFormat: + jformat = ENCODING_PCM_8BIT; + break; + default: + LOG("Unknown audio format. defaulting to 16bit."); + jformat = ENCODING_PCM_16BIT; + break; + } + + int jChannels; + switch (channelCount) { + case 1: + jChannels = CHANNEL_OUT_MONO; + break; + case 2: + jChannels = CHANNEL_OUT_STEREO; + break; + default: + LOG("Unknown channel count. defaulting to mono."); + jChannels = CHANNEL_OUT_MONO; + break; + } + + jobject obj = jenv->NewObject(s->at_class, + at.constructor, + STREAM_MUSIC, + s->rate, + jChannels, + jformat, + s->bufferSize, + MODE_STREAM); + + jthrowable exception = jenv->ExceptionOccurred(); + if (exception) { + LOG("%s fAILED ", __PRETTY_FUNCTION__); + jenv->ExceptionDescribe(); + jenv->ExceptionClear(); + jenv->DeleteGlobalRef(s->at_class); + free(s); + return NULL; + } + + s->output_unit = jenv->NewGlobalRef(obj); + return s; +} + +void +anp_audio_deleteTrack(ANPAudioTrack* s) +{ + if (s == NULL) { + return; + } + + s->keepGoing = false; + + // deallocation happens in the AudioThread. There is a + // potential leak if anp_audio_start is never called, but + // we do not see that from flash. +} + +void +anp_audio_start(ANPAudioTrack* s) +{ + if (s == NULL || s->output_unit == NULL) { + return; + } + + if (s->keepGoing) { + // we are already playing. Ignore. + LOG("anp_audio_start called twice!"); + return; + } + + JNIEnv *jenv = GetJNIForThread(); + jenv->CallVoidMethod(s->output_unit, at.play); + + s->isStopped = false; + s->keepGoing = true; + + // AudioRunnable now owns the ANPAudioTrack + nsRefPtr runnable = new AudioRunnable(s); + + nsCOMPtr thread; + NS_NewThread(getter_AddRefs(thread), runnable); +} + +void +anp_audio_pause(ANPAudioTrack* s) +{ + if (s == NULL || s->output_unit == NULL) { + return; + } + + JNIEnv *jenv = GetJNIForThread(); + jenv->CallVoidMethod(s->output_unit, at.pause); +} + +void +anp_audio_stop(ANPAudioTrack* s) +{ + if (s == NULL || s->output_unit == NULL) { + return; + } + + s->isStopped = true; + JNIEnv *jenv = GetJNIForThread(); + jenv->CallVoidMethod(s->output_unit, at.stop); +} + +bool +anp_audio_isStopped(ANPAudioTrack* s) +{ + return s->isStopped; +} + +void InitAudioTrackInterface(ANPAudioTrackInterfaceV0 *i) { + _assert(i->inSize == sizeof(*i)); + ASSIGN(i, newTrack); + ASSIGN(i, deleteTrack); + ASSIGN(i, start); + ASSIGN(i, pause); + ASSIGN(i, stop); + ASSIGN(i, isStopped); +} diff --git a/dom/plugins/base/android/ANPBase.h b/dom/plugins/base/android/ANPBase.h new file mode 100644 index 00000000000..ebbde892df5 --- /dev/null +++ b/dom/plugins/base/android/ANPBase.h @@ -0,0 +1,90 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Android NPAPI support code + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Doug Turner + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "android_npapi.h" +#include +#include "nsAutoPtr.h" +#include "gfxFont.h" + +#define NOT_IMPLEMENTED_FATAL() do { \ + __android_log_print(ANDROID_LOG_ERROR, "GeckoPlugins", \ + "%s not implemented %s, %d", \ + __PRETTY_FUNCTION__, __FILE__, __LINE__); \ + abort(); \ + } while(0) + +#define NOT_IMPLEMENTED() \ + __android_log_print(ANDROID_LOG_ERROR, "GeckoPlugins", \ + "!!!!!!!!!!!!!! %s not implemented %s, %d", \ + __PRETTY_FUNCTION__, __FILE__, __LINE__); \ + +class gfxFont; + +void InitAudioTrackInterface(ANPAudioTrackInterfaceV0 *i); +void InitBitmapInterface(ANPBitmapInterfaceV0 *i); +void InitCanvasInterface(ANPCanvasInterfaceV0 *i); +void InitEventInterface(ANPEventInterfaceV0 *i); +void InitLogInterface(ANPLogInterfaceV0 *i); +void InitMatrixInterface(ANPMatrixInterfaceV0 *i); +void InitPaintInterface(ANPPaintInterfaceV0 *i); +void InitPathInterface(ANPPathInterfaceV0 *i); +void InitSurfaceInterface(ANPSurfaceInterfaceV0 *i); +void InitSystemInterface(ANPSystemInterfaceV0 *i); +void InitTypeFaceInterface(ANPTypefaceInterfaceV0 *i); +void InitWindowInterface(ANPWindowInterfaceV0 *i); + +struct ANPTypeface { + nsRefPtr mFont; +}; + + +typedef struct { + ANPMatrixFlag flags; + ANPColor color; + ANPPaintStyle style; + float strokeWidth; + float strokeMiter; + ANPPaintCap paintCap; + ANPPaintJoin paintJoin; + ANPTextEncoding textEncoding; + ANPPaintAlign paintAlign; + float textSize; + float textScaleX; + float textSkewX; + ANPTypeface typeface; +} ANPPaintPrivate; diff --git a/dom/plugins/base/android/ANPBitmap.cpp b/dom/plugins/base/android/ANPBitmap.cpp new file mode 100644 index 00000000000..f398fe76b92 --- /dev/null +++ b/dom/plugins/base/android/ANPBitmap.cpp @@ -0,0 +1,118 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Android NPAPI support code + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Doug Turner + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "assert.h" +#include "ANPBase.h" +#include + +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) +#define ASSIGN(obj, name) (obj)->name = anp_bitmap_##name + + +#define SK_A32_BITS 8 +#define SK_R32_BITS 8 +#define SK_G32_BITS 8 +#define SK_B32_BITS 8 + +#ifdef IS_BIG_ENDIAN +#define SK_R32_SHIFT 24 +#define SK_G32_SHIFT 16 +#define SK_B32_SHIFT 8 +#define SK_A32_SHIFT 0 +#else +#define SK_R32_SHIFT 0 +#define SK_G32_SHIFT 8 +#define SK_B32_SHIFT 16 +#define SK_A32_SHIFT 24 +#endif + +#define SK_A32_MASK ((1 << SK_A32_BITS) - 1) +#define SK_R32_MASK ((1 << SK_R32_BITS) - 1) +#define SK_G32_MASK ((1 << SK_G32_BITS) - 1) +#define SK_B32_MASK ((1 << SK_B32_BITS) - 1) + +#define SK_R16_BITS 5 +#define SK_G16_BITS 6 +#define SK_B16_BITS 5 + +#define SK_R16_SHIFT (SK_B16_BITS + SK_G16_BITS) +#define SK_G16_SHIFT (SK_B16_BITS) +#define SK_B16_SHIFT 0 + +#define SK_R16_MASK ((1 << SK_R16_BITS) - 1) +#define SK_G16_MASK ((1 << SK_G16_BITS) - 1) +#define SK_B16_MASK ((1 << SK_B16_BITS) - 1) + +bool +anp_bitmap_getPixelPacking(ANPBitmapFormat fmt, ANPPixelPacking* packing) { + LOG("%s", __PRETTY_FUNCTION__); + switch (fmt) { + case kRGBA_8888_ANPBitmapFormat: + if (packing) { + packing->AShift = SK_A32_SHIFT; + packing->ABits = SK_A32_BITS; + packing->RShift = SK_R32_SHIFT; + packing->RBits = SK_R32_BITS; + packing->GShift = SK_G32_SHIFT; + packing->GBits = SK_G32_BITS; + packing->BShift = SK_B32_SHIFT; + packing->BBits = SK_B32_BITS; + } + return true; + case kRGB_565_ANPBitmapFormat: + if (packing) { + packing->AShift = 0; + packing->ABits = 0; + packing->RShift = SK_R16_SHIFT; + packing->RBits = SK_R16_BITS; + packing->GShift = SK_G16_SHIFT; + packing->GBits = SK_G16_BITS; + packing->BShift = SK_B16_SHIFT; + packing->BBits = SK_B16_BITS; + } + return true; + default: + break; + } + return false; +} + +void InitBitmapInterface(ANPBitmapInterfaceV0 *i) { + _assert(i->inSize == sizeof(*i)); + ASSIGN(i, getPixelPacking); +} diff --git a/dom/plugins/base/android/ANPCanvas.cpp b/dom/plugins/base/android/ANPCanvas.cpp new file mode 100644 index 00000000000..30c953e4635 --- /dev/null +++ b/dom/plugins/base/android/ANPCanvas.cpp @@ -0,0 +1,373 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Android NPAPI support code + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Doug Turner + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "assert.h" +#include "ANPBase.h" +#include + +#include "cairo.h" +#include "gfxPlatform.h" +#include "gfxASurface.h" +#include "gfxImageSurface.h" +#include "gfxUtils.h" +#include "gfxContext.h" + +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) +#define ASSIGN(obj, name) (obj)->name = anp_canvas_##name + + +ANPCanvas* +anp_canvas_newCanvas(const ANPBitmap* bitmap) +{ + PRUint32 stride; + gfxASurface::gfxImageFormat format; + + if (bitmap->format == ANPBitmapFormats::kRGBA_8888_ANPBitmapFormat) { + stride = bitmap->width * 4; + format = gfxImageSurface::ImageFormatARGB32; + } + else if (bitmap->format == ANPBitmapFormats::kRGB_565_ANPBitmapFormat) { + stride = bitmap->width * 2; + format = gfxImageSurface::ImageFormatRGB16_565; + } + else { + LOG("%s -- Unknown format", __PRETTY_FUNCTION__); + return nsnull; + } + + gfxImageSurface* pluginSurface = new gfxImageSurface(static_cast(bitmap->baseAddr), + gfxIntSize(bitmap->width, bitmap->height), + stride, + format); + if (pluginSurface->CairoStatus()) { + LOG("%s -- %d x %d FAILED to create gfxImageSurface", __PRETTY_FUNCTION__, bitmap->width, bitmap->height); + return nsnull; + } + + gfxContext *pluginContext = new gfxContext(pluginSurface); + NS_ADDREF(pluginContext); + return (ANPCanvas*) pluginContext; +} + +void +anp_canvas_deleteCanvas(ANPCanvas* canvas) +{ + if (!canvas) + return; + gfxContext *ctx = (gfxContext*)canvas; + NS_RELEASE( ctx ); +} + +void +anp_canvas_save(ANPCanvas* canvas) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + ctx->Save(); +} + +void +anp_canvas_restore(ANPCanvas* canvas) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + ctx->Restore(); +} + +void +anp_canvas_translate(ANPCanvas* canvas, float tx, float ty) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + ctx->Translate(gfxPoint(tx,ty)); +} + +void +anp_canvas_scale(ANPCanvas* canvas, float sx, float sy) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + ctx->Scale(sx, sy); +} + +void +anp_canvas_rotate(ANPCanvas* canvas, float degrees) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + ctx->Rotate(degrees); +} + +void +anp_canvas_skew(ANPCanvas* canvas, float kx, float ky) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + LOG("%s is not impl.", __PRETTY_FUNCTION__); +} + +void +anp_canvas_concat(ANPCanvas* canvas, const ANPMatrix*) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + LOG("%s is not impl.", __PRETTY_FUNCTION__); +} + +void +anp_canvas_clipRect(ANPCanvas* canvas, const ANPRectF* r) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + ctx->Clip(gfxRect(r->left, + r->top, + r->right - r->left, + r->bottom - r->top)); +} + +void +anp_canvas_clipPath(ANPCanvas* canvas, const ANPPath*) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + LOG("%s is not impl.", __PRETTY_FUNCTION__); +} + +void +anp_canvas_getTotalMatrix(ANPCanvas* canvas, ANPMatrix*) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + LOG("%s is not impl.", __PRETTY_FUNCTION__); +} + +bool +anp_canvas_getLocalClipBounds(ANPCanvas* canvas, ANPRectF* bounds, bool aa) +{ + if (!canvas) + return false; + + gfxContext* ctx = (gfxContext*)canvas; + LOG("%s is not impl.", __PRETTY_FUNCTION__); + return false; +} + +bool +anp_canvas_getDeviceClipBounds(ANPCanvas* canvas, ANPRectI* bounds) +{ + if (!canvas) + return false; + + gfxContext* ctx = (gfxContext*)canvas; + LOG("%s is not impl.", __PRETTY_FUNCTION__); + return false; +} + +void +anp_canvas_drawColor(ANPCanvas* canvas, ANPColor c) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + ctx->SetDeviceColor(gfxRGBA(c, gfxRGBA::PACKED_ARGB)); + LOG("returning from %s", __PRETTY_FUNCTION__); +} + +void +anp_canvas_drawPaint(ANPCanvas* canvas, const ANPPaint* paint) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + LOG("%s", " ************** NOT IMPLEMENTED!!!"); +} + +void +anp_canvas_drawLine(ANPCanvas* canvas, float x0, float y0, float x1, float y1, + const ANPPaint* paint) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + ctx->NewPath(); + ctx->SetColor(((ANPPaintPrivate*)paint)->color); + ctx->Line(gfxPoint(x0, y0), gfxPoint(x1, y1)); + ctx->Fill(); +} + +void +anp_canvas_drawRect(ANPCanvas* canvas, const ANPRectF* r, const ANPPaint* paint) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + + ctx->NewPath(); + ctx->SetColor(((ANPPaintPrivate*)paint)->color); + ctx->Rectangle(gfxRect(r->left, + r->top, + r->right - r->left, + r->bottom - r->top)); + ctx->Fill(); +} + +void +anp_canvas_drawOval(ANPCanvas* canvas, const ANPRectF* r, const ANPPaint* paint) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + + ctx->NewPath(); + ctx->SetColor(((ANPPaintPrivate*)paint)->color); + + float sizeX = (r->right - r->left); + float sizeY = (r->bottom - r->top); + + ctx->Ellipse(gfxPoint(r->left + ( sizeX / 2), r->top + ( sizeY / 2)), + gfxSize(sizeX, sizeY)); + ctx->Fill(); +} + +void +anp_canvas_drawPath(ANPCanvas* canvas, const ANPPath*, const ANPPaint* paint) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + LOG("%s is not impl.", __PRETTY_FUNCTION__); +} + +void +anp_canvas_drawText(ANPCanvas* canvas, const void* text, uint32_t byteLength, + float x, float y, const ANPPaint* paint) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + LOG("%s is not impl.", __PRETTY_FUNCTION__); +} + +void +anp_canvas_drawPosText(ANPCanvas* canvas, const void* text, uint32_t byteLength, + const float xy[], const ANPPaint* paint) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + LOG("%s is not impl.", __PRETTY_FUNCTION__); +} + +void +anp_canvas_drawBitmap(ANPCanvas* canvas, const ANPBitmap*, float x, float y, + const ANPPaint* paint) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + LOG("%s is not impl.", __PRETTY_FUNCTION__); +} + +void +anp_canvas_drawBitmapRect(ANPCanvas* canvas, const ANPBitmap*, + const ANPRectI* src, const ANPRectF* dst, + const ANPPaint* paint) +{ + if (!canvas) + return; + + gfxContext* ctx = (gfxContext*)canvas; + LOG("%s is not impl.", __PRETTY_FUNCTION__); +} + +void InitCanvasInterface(ANPCanvasInterfaceV0 *i) { + _assert(i->inSize == sizeof(*i)); + ASSIGN(i, newCanvas); + ASSIGN(i, deleteCanvas); + ASSIGN(i, save); + ASSIGN(i, restore); + ASSIGN(i, translate); + ASSIGN(i, scale); + ASSIGN(i, rotate); + ASSIGN(i, skew); + ASSIGN(i, concat); + ASSIGN(i, clipRect); + ASSIGN(i, clipPath); + ASSIGN(i, getTotalMatrix); + ASSIGN(i, getLocalClipBounds); + ASSIGN(i, getDeviceClipBounds); + ASSIGN(i, drawColor); + ASSIGN(i, drawPaint); + ASSIGN(i, drawLine); + ASSIGN(i, drawRect); + ASSIGN(i, drawOval); + ASSIGN(i, drawPath); + ASSIGN(i, drawText); + ASSIGN(i, drawPosText); + ASSIGN(i, drawBitmap); + ASSIGN(i, drawBitmapRect); +} diff --git a/dom/plugins/base/android/ANPEvent.cpp b/dom/plugins/base/android/ANPEvent.cpp new file mode 100644 index 00000000000..44998ffcb51 --- /dev/null +++ b/dom/plugins/base/android/ANPEvent.cpp @@ -0,0 +1,84 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Android NPAPI support code + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Doug Turner + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "assert.h" +#include "ANPBase.h" +#include +#include "nsThreadUtils.h" +#include "nsNPAPIPluginInstance.h" +#include "AndroidBridge.h" +#include "nsNPAPIPlugin.h" + +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) +#define ASSIGN(obj, name) (obj)->name = anp_event_##name + +class PluginEventRunnable : public nsRunnable +{ +public: + PluginEventRunnable(NPP inst, ANPEvent* event, NPPluginFuncs* aFuncs) + : mInstance(inst), mEvent(*event), mFuncs(aFuncs) {} + virtual nsresult Run() { + (*mFuncs->event)(mInstance, &mEvent); + return NS_OK; + } +private: + NPP mInstance; + ANPEvent mEvent; + NPPluginFuncs* mFuncs; +}; + +void +anp_event_postEvent(NPP inst, const ANPEvent* event) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!mozilla::AndroidBridge::Bridge()) { + LOG("no bridge in %s!!!!", __PRETTY_FUNCTION__); + return; + } + nsNPAPIPluginInstance* pinst = static_cast(inst->ndata); + NPPluginFuncs* pluginFunctions = pinst->GetPlugin()->PluginFuncs(); + mozilla::AndroidBridge::Bridge()->PostToJavaThread( + new PluginEventRunnable(inst, const_cast(event), pluginFunctions), PR_TRUE); + LOG("returning from %s", __PRETTY_FUNCTION__); +} + + +void InitEventInterface(ANPEventInterfaceV0 *i) { + _assert(i->inSize == sizeof(*i)); + ASSIGN(i, postEvent); +} diff --git a/dom/plugins/base/android/ANPKeyCodes.h b/dom/plugins/base/android/ANPKeyCodes.h new file mode 100644 index 00000000000..edfe2b95cdb --- /dev/null +++ b/dom/plugins/base/android/ANPKeyCodes.h @@ -0,0 +1,152 @@ +/* + * Copyright 2008, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ANPKeyCodes_DEFINED +#define ANPKeyCodes_DEFINED + +/* List the key codes that are set to a plugin in the ANPKeyEvent. + + These exactly match the values in android/view/KeyEvent.java and the + corresponding .h file android/keycodes.h. +*/ +enum ANPKeyCodes { + kUnknown_ANPKeyCode = 0, + + kSoftLeft_ANPKeyCode = 1, + kSoftRight_ANPKeyCode = 2, + kHome_ANPKeyCode = 3, + kBack_ANPKeyCode = 4, + kCall_ANPKeyCode = 5, + kEndCall_ANPKeyCode = 6, + k0_ANPKeyCode = 7, + k1_ANPKeyCode = 8, + k2_ANPKeyCode = 9, + k3_ANPKeyCode = 10, + k4_ANPKeyCode = 11, + k5_ANPKeyCode = 12, + k6_ANPKeyCode = 13, + k7_ANPKeyCode = 14, + k8_ANPKeyCode = 15, + k9_ANPKeyCode = 16, + kStar_ANPKeyCode = 17, + kPound_ANPKeyCode = 18, + kDpadUp_ANPKeyCode = 19, + kDpadDown_ANPKeyCode = 20, + kDpadLeft_ANPKeyCode = 21, + kDpadRight_ANPKeyCode = 22, + kDpadCenter_ANPKeyCode = 23, + kVolumeUp_ANPKeyCode = 24, + kVolumeDown_ANPKeyCode = 25, + kPower_ANPKeyCode = 26, + kCamera_ANPKeyCode = 27, + kClear_ANPKeyCode = 28, + kA_ANPKeyCode = 29, + kB_ANPKeyCode = 30, + kC_ANPKeyCode = 31, + kD_ANPKeyCode = 32, + kE_ANPKeyCode = 33, + kF_ANPKeyCode = 34, + kG_ANPKeyCode = 35, + kH_ANPKeyCode = 36, + kI_ANPKeyCode = 37, + kJ_ANPKeyCode = 38, + kK_ANPKeyCode = 39, + kL_ANPKeyCode = 40, + kM_ANPKeyCode = 41, + kN_ANPKeyCode = 42, + kO_ANPKeyCode = 43, + kP_ANPKeyCode = 44, + kQ_ANPKeyCode = 45, + kR_ANPKeyCode = 46, + kS_ANPKeyCode = 47, + kT_ANPKeyCode = 48, + kU_ANPKeyCode = 49, + kV_ANPKeyCode = 50, + kW_ANPKeyCode = 51, + kX_ANPKeyCode = 52, + kY_ANPKeyCode = 53, + kZ_ANPKeyCode = 54, + kComma_ANPKeyCode = 55, + kPeriod_ANPKeyCode = 56, + kAltLeft_ANPKeyCode = 57, + kAltRight_ANPKeyCode = 58, + kShiftLeft_ANPKeyCode = 59, + kShiftRight_ANPKeyCode = 60, + kTab_ANPKeyCode = 61, + kSpace_ANPKeyCode = 62, + kSym_ANPKeyCode = 63, + kExplorer_ANPKeyCode = 64, + kEnvelope_ANPKeyCode = 65, + kNewline_ANPKeyCode = 66, + kDel_ANPKeyCode = 67, + kGrave_ANPKeyCode = 68, + kMinus_ANPKeyCode = 69, + kEquals_ANPKeyCode = 70, + kLeftBracket_ANPKeyCode = 71, + kRightBracket_ANPKeyCode = 72, + kBackslash_ANPKeyCode = 73, + kSemicolon_ANPKeyCode = 74, + kApostrophe_ANPKeyCode = 75, + kSlash_ANPKeyCode = 76, + kAt_ANPKeyCode = 77, + kNum_ANPKeyCode = 78, + kHeadSetHook_ANPKeyCode = 79, + kFocus_ANPKeyCode = 80, + kPlus_ANPKeyCode = 81, + kMenu_ANPKeyCode = 82, + kNotification_ANPKeyCode = 83, + kSearch_ANPKeyCode = 84, + kMediaPlayPause_ANPKeyCode = 85, + kMediaStop_ANPKeyCode = 86, + kMediaNext_ANPKeyCode = 87, + kMediaPrevious_ANPKeyCode = 88, + kMediaRewind_ANPKeyCode = 89, + kMediaFastForward_ANPKeyCode = 90, + kMute_ANPKeyCode = 91, + kPageUp_ANPKeyCode = 92, + kPageDown_ANPKeyCode = 93, + kPictsymbols_ANPKeyCode = 94, + kSwitchCharset_ANPKeyCode = 95, + kButtonA_ANPKeyCode = 96, + kButtonB_ANPKeyCode = 97, + kButtonC_ANPKeyCode = 98, + kButtonX_ANPKeyCode = 99, + kButtonY_ANPKeyCode = 100, + kButtonZ_ANPKeyCode = 101, + kButtonL1_ANPKeyCode = 102, + kButtonR1_ANPKeyCode = 103, + kButtonL2_ANPKeyCode = 104, + kButtonR2_ANPKeyCode = 105, + kButtonThumbL_ANPKeyCode = 106, + kButtonThumbR_ANPKeyCode = 107, + kButtonStart_ANPKeyCode = 108, + kButtonSelect_ANPKeyCode = 109, + kButtonMode_ANPKeyCode = 110, + + // NOTE: If you add a new keycode here you must also add it to several other files. + // Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list. +}; + +#endif diff --git a/dom/plugins/base/android/ANPLog.cpp b/dom/plugins/base/android/ANPLog.cpp new file mode 100644 index 00000000000..68c9ad91cb6 --- /dev/null +++ b/dom/plugins/base/android/ANPLog.cpp @@ -0,0 +1,59 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Android NPAPI support code + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Doug Turner + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "assert.h" +#include "ANPBase.h" +#include + +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) +#define ASSIGN(obj, name) (obj)->name = anp_log_##name + +void +anp_log_log(ANPLogType type, const char format[], ...) { + + va_list argp; + va_start(argp,format); + __android_log_vprint(type == kError_ANPLogType ? ANDROID_LOG_ERROR : type == kWarning_ANPLogType ? + ANDROID_LOG_WARN : ANDROID_LOG_INFO, "GeckoPluginLog", format, argp); + va_end(argp); +} + +void InitLogInterface(ANPLogInterfaceV0 *i) { + _assert(i->inSize == sizeof(*i)); + ASSIGN(i, log); +} diff --git a/dom/plugins/base/android/ANPMatrix.cpp b/dom/plugins/base/android/ANPMatrix.cpp new file mode 100644 index 00000000000..b1274d853ed --- /dev/null +++ b/dom/plugins/base/android/ANPMatrix.cpp @@ -0,0 +1,197 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Android NPAPI support code + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Doug Turner + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "assert.h" +#include "ANPBase.h" +#include + +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) +#define ASSIGN(obj, name) (obj)->name = anp_matrix_##name + +/** Return a new identity matrix + */ +ANPMatrix* +anp_matrix_newMatrix() +{ + NOT_IMPLEMENTED(); + return 0; +} + +/** Delete a matrix previously allocated by newMatrix() + */ +void +anp_matrix_deleteMatrix(ANPMatrix*) +{ + NOT_IMPLEMENTED(); +} + + +ANPMatrixFlag +anp_matrix_getFlags(const ANPMatrix*) +{ + NOT_IMPLEMENTED(); + return 0; +} + + +void +anp_matrix_copy(ANPMatrix* dst, const ANPMatrix* src) +{ + NOT_IMPLEMENTED(); +} + + +void +anp_matrix_get3x3(const ANPMatrix*, float[9]) +{ + NOT_IMPLEMENTED(); +} + +void +anp_matrix_set3x3(ANPMatrix*, const float[9]) +{ + NOT_IMPLEMENTED(); +} + + +void +anp_matrix_setIdentity(ANPMatrix*) +{ + NOT_IMPLEMENTED(); +} + +void +anp_matrix_preTranslate(ANPMatrix*, float tx, float ty) +{ + NOT_IMPLEMENTED(); +} + +void +anp_matrix_postTranslate(ANPMatrix*, float tx, float ty) +{ + NOT_IMPLEMENTED(); +} + +void +anp_matrix_preScale(ANPMatrix*, float sx, float sy) +{ + NOT_IMPLEMENTED(); +} + +void +anp_matrix_postScale(ANPMatrix*, float sx, float sy) +{ + NOT_IMPLEMENTED(); +} + +void +anp_matrix_preSkew(ANPMatrix*, float kx, float ky) +{ + NOT_IMPLEMENTED(); +} + +void +anp_matrix_postSkew(ANPMatrix*, float kx, float ky) +{ + NOT_IMPLEMENTED(); +} + +void +anp_matrix_preRotate(ANPMatrix*, float degrees) +{ + NOT_IMPLEMENTED(); +} + +void +anp_matrix_postRotate(ANPMatrix*, float degrees) +{ + NOT_IMPLEMENTED(); +} + +void +anp_matrix_preConcat(ANPMatrix*, const ANPMatrix*) +{ + NOT_IMPLEMENTED(); +} + +void +anp_matrix_postConcat(ANPMatrix*, const ANPMatrix*) +{ + NOT_IMPLEMENTED(); +} + + +bool +anp_matrix_invert(ANPMatrix* dst, const ANPMatrix* src) +{ + NOT_IMPLEMENTED(); + return false; +} + +void +anp_matrix_mapPoints(ANPMatrix*, float dst[], const float src[], + int32_t count) +{ + NOT_IMPLEMENTED(); +} + + +void InitMatrixInterface(ANPMatrixInterfaceV0 *i) { + _assert(i->inSize == sizeof(*i)); + ASSIGN(i, newMatrix); + ASSIGN(i, deleteMatrix); + ASSIGN(i, getFlags); + ASSIGN(i, copy); + ASSIGN(i, get3x3); + ASSIGN(i, set3x3); + ASSIGN(i, setIdentity); + ASSIGN(i, preTranslate); + ASSIGN(i, postTranslate); + ASSIGN(i, preScale); + ASSIGN(i, postScale); + ASSIGN(i, preSkew); + ASSIGN(i, postSkew); + ASSIGN(i, preRotate); + ASSIGN(i, postRotate); + ASSIGN(i, preConcat); + ASSIGN(i, postConcat); + ASSIGN(i, invert); + ASSIGN(i, mapPoints); +} + + diff --git a/dom/plugins/base/android/ANPPaint.cpp b/dom/plugins/base/android/ANPPaint.cpp new file mode 100644 index 00000000000..9dc5d4c271b --- /dev/null +++ b/dom/plugins/base/android/ANPPaint.cpp @@ -0,0 +1,454 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Android NPAPI support code + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Doug Turner + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include +#include +#include "ANPBase.h" + +#define LOG(args...) +//__android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) +#define ASSIGN(obj, name) (obj)->name = anp_paint_##name + +ANPPaint* +anp_paint_newPaint() +{ + LOG("%s", __PRETTY_FUNCTION__); + + ANPPaintPrivate* p = (ANPPaintPrivate*) calloc(1, sizeof(ANPPaintPrivate)); + return (ANPPaint*) p; +} + +void +anp_paint_deletePaint(ANPPaint* paint) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + free((void*)p); +} + + +ANPPaintFlags +anp_paint_getFlags(const ANPPaint* paint) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return kAntiAlias_ANPPaintFlag; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + return p->flags; +} + +void +anp_paint_setFlags(ANPPaint* paint, ANPPaintFlags flags) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + p->flags = flags; +} + + +ANPColor +anp_paint_getColor(const ANPPaint* paint) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return ANP_MAKE_COLOR(1, 255, 255, 255); + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + return p->color; +} + +void +anp_paint_setColor(ANPPaint* paint, ANPColor color) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + p->color = color; +} + + +ANPPaintStyle +anp_paint_getStyle(const ANPPaint* paint) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return kFill_ANPPaintStyle; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + return p->style; +} + +void +anp_paint_setStyle(ANPPaint* paint, ANPPaintStyle style) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + p->style = style; +} + +float +anp_paint_getStrokeWidth(const ANPPaint* paint) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return 0; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + return p->strokeWidth; +} + +float +anp_paint_getStrokeMiter(const ANPPaint* paint) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return 0; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + return p->strokeMiter; +} + +ANPPaintCap +anp_paint_getStrokeCap(const ANPPaint* paint) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return kButt_ANPPaintCap; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + return p->paintCap; +} + +ANPPaintJoin +anp_paint_getStrokeJoin(const ANPPaint* paint) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return kMiter_ANPPaintJoin; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + return p->paintJoin; +} + +void +anp_paint_setStrokeWidth(ANPPaint* paint, float width) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + p->strokeWidth = width; +} + +void +anp_paint_setStrokeMiter(ANPPaint* paint, float miter) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + p->strokeMiter = miter; +} + +void +anp_paint_setStrokeCap(ANPPaint* paint, ANPPaintCap cap) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + p->paintCap = cap; +} + +void +anp_paint_setStrokeJoin(ANPPaint* paint, ANPPaintJoin join) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + p->paintJoin = join; +} + + +ANPTextEncoding +anp_paint_getTextEncoding(const ANPPaint* paint) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return kUTF8_ANPTextEncoding; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + return p->textEncoding; +} + +ANPPaintAlign +anp_paint_getTextAlign(const ANPPaint* paint) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return kLeft_ANPPaintAlign; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + return p->paintAlign; +} + +float +anp_paint_getTextSize(const ANPPaint* paint) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return 0; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + return p->textSize; +} + +float +anp_paint_getTextScaleX(const ANPPaint* paint) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return 0; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + return p->textScaleX; +} + +float +anp_paint_getTextSkewX(const ANPPaint* paint) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return 0; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + return p->textSkewX; +} + +void +anp_paint_setTextEncoding(ANPPaint* paint, ANPTextEncoding encoding) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + p->textEncoding = encoding; +} + +void +anp_paint_setTextAlign(ANPPaint* paint, ANPPaintAlign align) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + p->paintAlign = align; +} + +void +anp_paint_setTextSize(ANPPaint* paint, float size) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + p->textSize = size; +} + +void +anp_paint_setTextScaleX(ANPPaint* paint, float scale) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + p->textScaleX = scale; +} + +void +anp_paint_setTextSkewX(ANPPaint* paint, float skew) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + p->textSkewX = skew; +} + + +/** Return the typeface in paint, or null if there is none. This does not + modify the owner count of the returned typeface. +*/ +ANPTypeface* +anp_paint_getTypeface(const ANPPaint* paint) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return NULL; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + return &p->typeface; +} + + +/** Set the paint's typeface. If the paint already had a non-null typeface, + its owner count is decremented. If the new typeface is non-null, its + owner count is incremented. +*/ +void +anp_paint_setTypeface(ANPPaint* paint, ANPTypeface* typeface) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + LOG("%s is not impl.", __PRETTY_FUNCTION__); +} + +/** Return the width of the text. If bounds is not null, return the bounds + of the text in that rectangle. +*/ +float +anp_paint_measureText(ANPPaint* paint, const void* text, uint32_t byteLength, + ANPRectF* bounds) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return 0; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + + LOG("%s is not impl.", __PRETTY_FUNCTION__); + return 0; +} + + +/** Return the number of unichars specifed by the text. + If widths is not null, returns the array of advance widths for each + unichar. + If bounds is not null, returns the array of bounds for each unichar. +*/ +int +anp_paint_getTextWidths(ANPPaint* paint, const void* text, uint32_t byteLength, + float widths[], ANPRectF bounds[]) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return 0; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + LOG("%s is not impl.", __PRETTY_FUNCTION__); + return 0; +} + + +/** Return in metrics the spacing values for text, respecting the paint's + typeface and pointsize, and return the spacing between lines + (descent - ascent + leading). If metrics is NULL, it will be ignored. +*/ +float +anp_paint_getFontMetrics(ANPPaint* paint, ANPFontMetrics* metrics) +{ + LOG("%s", __PRETTY_FUNCTION__); + if (!paint) + return 0; + + ANPPaintPrivate* p = (ANPPaintPrivate*) paint; + LOG("%s is not impl.", __PRETTY_FUNCTION__); + return 0; +} + + +void InitPaintInterface(ANPPaintInterfaceV0 *i) { + _assert(i->inSize == sizeof(*i)); + ASSIGN(i, newPaint); + ASSIGN(i, deletePaint); + ASSIGN(i, getFlags); + ASSIGN(i, setFlags); + ASSIGN(i, getColor); + ASSIGN(i, setColor); + ASSIGN(i, getStyle); + ASSIGN(i, setStyle); + ASSIGN(i, getStrokeWidth); + ASSIGN(i, getStrokeMiter); + ASSIGN(i, getStrokeCap); + ASSIGN(i, getStrokeJoin); + ASSIGN(i, setStrokeWidth); + ASSIGN(i, setStrokeMiter); + ASSIGN(i, setStrokeCap); + ASSIGN(i, setStrokeJoin); + ASSIGN(i, getTextEncoding); + ASSIGN(i, getTextAlign); + ASSIGN(i, getTextSize); + ASSIGN(i, getTextScaleX); + ASSIGN(i, getTextSkewX); + ASSIGN(i, setTextEncoding); + ASSIGN(i, setTextAlign); + ASSIGN(i, setTextSize); + ASSIGN(i, setTextScaleX); + ASSIGN(i, setTextSkewX); + ASSIGN(i, getTypeface); + ASSIGN(i, setTypeface); + ASSIGN(i, measureText); + ASSIGN(i, getTextWidths); + ASSIGN(i, getFontMetrics); +} diff --git a/dom/plugins/base/android/ANPPath.cpp b/dom/plugins/base/android/ANPPath.cpp new file mode 100644 index 00000000000..ca1dbe9d48d --- /dev/null +++ b/dom/plugins/base/android/ANPPath.cpp @@ -0,0 +1,171 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Android NPAPI support code + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Doug Turner + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "assert.h" +#include "ANPBase.h" +#include + +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) +#define ASSIGN(obj, name) (obj)->name = anp_path_##name + + +// maybe this should store a list of actions (lineTo, +// moveTo), and when canvas_drawPath() we apply all of these +// actions to the gfxContext. + +ANPPath* +anp_path_newPath() +{ + LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__); + return 0; +} + + +void +anp_path_deletePath(ANPPath* p) +{ + LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__); +} + + +void +anp_path_copy(ANPPath* dst, const ANPPath* src) +{ + LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__); +} + + +bool +anp_path_equal(const ANPPath* path0, const ANPPath* path1) +{ + LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__); + return false; +} + + +void +anp_path_reset(ANPPath* p) +{ + LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__); +} + + +bool +anp_path_isEmpty(const ANPPath* p) +{ + LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__); + return false; +} + + +void +anp_path_getBounds(const ANPPath* p, ANPRectF* bounds) +{ + LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__); + + bounds->left = 0; + bounds->top = 0; + bounds->right = 1000; + bounds->left = 1000; +} + + +void +anp_path_moveTo(ANPPath* p, float x, float y) +{ + LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__); +} + +void +anp_path_lineTo(ANPPath* p, float x, float y) +{ + LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__); +} + +void +anp_path_quadTo(ANPPath* p, float x0, float y0, float x1, float y1) +{ + LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__); +} + +void +anp_path_cubicTo(ANPPath* p, float x0, float y0, float x1, float y1, + float x2, float y2) +{ + LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__); +} + +void +anp_path_close(ANPPath* p) +{ + LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__); +} + + +void +anp_path_offset(ANPPath* src, float dx, float dy, ANPPath* dst) +{ + LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__); +} + + +void +anp_path_transform(ANPPath* src, const ANPMatrix*, ANPPath* dst) +{ + LOG("%s - NOT IMPL.", __PRETTY_FUNCTION__); +} + + + +void InitPathInterface(ANPPathInterfaceV0 *i) { + _assert(i->inSize == sizeof(*i)); + ASSIGN(i, newPath); + ASSIGN(i, deletePath); + ASSIGN(i, copy); + ASSIGN(i, equal); + ASSIGN(i, reset); + ASSIGN(i, isEmpty); + ASSIGN(i, getBounds); + ASSIGN(i, moveTo); + ASSIGN(i, lineTo); + ASSIGN(i, quadTo); + ASSIGN(i, cubicTo); + ASSIGN(i, close); + ASSIGN(i, offset); + ASSIGN(i, transform); +} diff --git a/dom/plugins/base/android/ANPSurface.cpp b/dom/plugins/base/android/ANPSurface.cpp new file mode 100644 index 00000000000..f4984b1d286 --- /dev/null +++ b/dom/plugins/base/android/ANPSurface.cpp @@ -0,0 +1,189 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Android NPAPI support code + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Doug Turner + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "assert.h" +#include "ANPBase.h" +#include +#include "AndroidBridge.h" +#include "gfxImageSurface.h" +#include "gfxContext.h" + +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) +#define ASSIGN(obj, name) (obj)->name = anp_surface_##name + + +// used to cache JNI method and field IDs for Surface Objects +static struct ANPSurfaceInterfaceJavaGlue { + bool initialized; + jclass geckoAppShellClass; + jclass lockInfoCls; + jmethodID lockSurfaceANP; + jmethodID jUnlockSurfaceANP; + jfieldID jDirtyTop; + jfieldID jDirtyLeft; + jfieldID jDirtyBottom; + jfieldID jDirtyRight; + jfieldID jFormat; + jfieldID jWidth ; + jfieldID jHeight; + jfieldID jBuffer; +} gSurfaceJavaGlue; + +#define getClassGlobalRef(env, cname) \ + (jClass = jclass(env->NewGlobalRef(env->FindClass(cname)))) + +static void init(JNIEnv* env) { + if (gSurfaceJavaGlue.initialized) + return; + + gSurfaceJavaGlue.geckoAppShellClass = mozilla::AndroidBridge::GetGeckoAppShellClass(); + + jmethodID getClass = env->GetStaticMethodID(gSurfaceJavaGlue.geckoAppShellClass, + "getSurfaceLockInfoClass", + "()Ljava/lang/Class;"); + + gSurfaceJavaGlue.lockInfoCls = (jclass) env->NewGlobalRef(env->CallStaticObjectMethod(gSurfaceJavaGlue.geckoAppShellClass, getClass)); + + gSurfaceJavaGlue.jDirtyTop = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "dirtyTop", "I"); + gSurfaceJavaGlue.jDirtyLeft = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "dirtyLeft", "I"); + gSurfaceJavaGlue.jDirtyBottom = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "dirtyBottom", "I"); + gSurfaceJavaGlue.jDirtyRight = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "dirtyRight", "I"); + + gSurfaceJavaGlue.jFormat = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "format", "I"); + gSurfaceJavaGlue.jWidth = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "width", "I"); + gSurfaceJavaGlue.jHeight = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "height", "I"); + + gSurfaceJavaGlue.jBuffer = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "buffer", "Ljava/nio/Buffer;"); + gSurfaceJavaGlue.lockSurfaceANP = env->GetStaticMethodID(gSurfaceJavaGlue.geckoAppShellClass, "lockSurfaceANP", "(Landroid/view/SurfaceView;IIII)Lorg/mozilla/gecko/SurfaceLockInfo;"); + gSurfaceJavaGlue.jUnlockSurfaceANP = env->GetStaticMethodID(gSurfaceJavaGlue.geckoAppShellClass, "unlockSurfaceANP", "(Landroid/view/SurfaceView;)V"); + gSurfaceJavaGlue.initialized = true; +} + +static bool anp_lock(JNIEnv* env, jobject surfaceView, ANPBitmap* bitmap, ANPRectI* dirtyRect) { + LOG("%s", __PRETTY_FUNCTION__); + if (!bitmap || !surfaceView) { + LOG("%s, null bitmap or surface, exiting", __PRETTY_FUNCTION__); + return false; + } + + init(env); + + jvalue args[5]; + args[0].l = surfaceView; + if (dirtyRect) { + args[1].i = dirtyRect->top; + args[2].i = dirtyRect->left; + args[3].i = dirtyRect->bottom; + args[4].i = dirtyRect->right; + LOG("dirty rect: %d, %d, %d, %d", dirtyRect->top, dirtyRect->left, dirtyRect->bottom, dirtyRect->right); + } else { + args[1].i = args[2].i = args[3].i = args[4].i = 0; + } + + jobject info = env->CallStaticObjectMethod(gSurfaceJavaGlue.geckoAppShellClass, + gSurfaceJavaGlue.lockSurfaceANP, + surfaceView, args[1].i, args[2].i, args[3].i, args[4].i); + + LOG("info: %p", info); + if (!info) + return false; + + // the surface may have expanded the dirty region so we must to pass that + // information back to the plugin. + if (dirtyRect) { + dirtyRect->left = env->GetIntField(info, gSurfaceJavaGlue.jDirtyLeft); + dirtyRect->right = env->GetIntField(info, gSurfaceJavaGlue.jDirtyRight); + dirtyRect->top = env->GetIntField(info, gSurfaceJavaGlue.jDirtyTop); + dirtyRect->bottom = env->GetIntField(info, gSurfaceJavaGlue.jDirtyBottom); + LOG("dirty rect: %d, %d, %d, %d", dirtyRect->top, dirtyRect->left, dirtyRect->bottom, dirtyRect->right); + } + + bitmap->width = env->GetIntField(info, gSurfaceJavaGlue.jWidth); + bitmap->height = env->GetIntField(info, gSurfaceJavaGlue.jHeight); + + int format = env->GetIntField(info, gSurfaceJavaGlue.jFormat); + + // format is PixelFormat + if (format & 0x00000001) { + bitmap->format = kRGBA_8888_ANPBitmapFormat; + bitmap->rowBytes = bitmap->width * 4; + } + else if (format & 0x00000004) { + bitmap->format = kRGB_565_ANPBitmapFormat; + bitmap->rowBytes = bitmap->width * 2; + } + else { + LOG("format from glue is unknown %d\n", format); + return false; + } + + jobject buf = env->GetObjectField(info, gSurfaceJavaGlue.jBuffer); + bitmap->baseAddr = env->GetDirectBufferAddress(buf); + + LOG("format: %d, width: %d, height: %d", bitmap->format, bitmap->width, bitmap->height); + env->DeleteLocalRef(info); + env->DeleteLocalRef(buf); + return ( bitmap->width > 0 && bitmap->height > 0 ); +} + +static void anp_unlock(JNIEnv* env, jobject surfaceView) { + LOG("%s", __PRETTY_FUNCTION__); + + if (!surfaceView) { + LOG("null surface, exiting %s", __PRETTY_FUNCTION__); + return; + } + + init(env); + env->CallStaticVoidMethod(gSurfaceJavaGlue.geckoAppShellClass, gSurfaceJavaGlue.jUnlockSurfaceANP, surfaceView); + LOG("returning from %s", __PRETTY_FUNCTION__); + +} + +/////////////////////////////////////////////////////////////////////////////// + +#define ASSIGN(obj, name) (obj)->name = anp_##name + +void InitSurfaceInterface(ANPSurfaceInterfaceV0 *i) { + + ASSIGN(i, lock); + ASSIGN(i, unlock); + + // setup the java glue struct + gSurfaceJavaGlue.initialized = false; +} diff --git a/dom/plugins/base/android/ANPSystem.cpp b/dom/plugins/base/android/ANPSystem.cpp new file mode 100644 index 00000000000..70085217328 --- /dev/null +++ b/dom/plugins/base/android/ANPSystem.cpp @@ -0,0 +1,86 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Android NPAPI support code + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Doug Turner + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "base/basictypes.h" + +#include "assert.h" +#include "ANPBase.h" +#include +#include "nsNPAPIPluginInstance.h" +#include "AndroidBridge.h" +#include "nsNPAPIPlugin.h" +#include "PluginPRLibrary.h" + +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) +#define ASSIGN(obj, name) (obj)->name = anp_system_##name + +const char* +anp_system_getApplicationDataDirectory() +{ + LOG("getApplicationDataDirectory return /data/data/org.mozilla.%s", MOZ_APP_NAME); + return "/data/data/org.mozilla." MOZ_APP_NAME; +} + +jclass anp_system_loadJavaClass(NPP instance, const char* className) +{ + LOG("%s", __PRETTY_FUNCTION__); + + JNIEnv* env = GetJNIForThread(); + jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell"); + jmethodID method = env->GetStaticMethodID(cls, + "loadPluginClass", + "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Class;"); + + // pass libname and classname, gotta create java strings + nsNPAPIPluginInstance* pinst = static_cast(instance->ndata); + mozilla::PluginPRLibrary* lib = static_cast(pinst->GetPlugin()->GetLibrary()); + + nsCString libName; + lib->GetLibraryPath(libName); + + jstring jclassName = env->NewStringUTF(className); + jstring jlibName = env->NewStringUTF(libName.get()); + jobject obj = env->CallStaticObjectMethod(cls, method, jclassName, jlibName); + return reinterpret_cast(obj); +} + +void InitSystemInterface(ANPSystemInterfaceV0 *i) { + _assert(i->inSize == sizeof(*i)); + ASSIGN(i, getApplicationDataDirectory); + ASSIGN(i, loadJavaClass); +} diff --git a/dom/plugins/base/android/ANPTypeface.cpp b/dom/plugins/base/android/ANPTypeface.cpp new file mode 100644 index 00000000000..85b8d7b8fe9 --- /dev/null +++ b/dom/plugins/base/android/ANPTypeface.cpp @@ -0,0 +1,151 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Android NPAPI support code + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Doug Turner + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "assert.h" +#include "ANPBase.h" +#include +#include "gfxAndroidPlatform.h" + +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) +#define ASSIGN(obj, name) (obj)->name = anp_typeface_##name + +ANPTypeface* +anp_typeface_createFromName(const char name[], ANPTypefaceStyle aStyle) +{ + LOG("%s - %s\n", __PRETTY_FUNCTION__, name); + + gfxFontStyle style (aStyle == kItalic_ANPTypefaceStyle ? FONT_STYLE_ITALIC : + FONT_STYLE_NORMAL, + NS_FONT_STRETCH_NORMAL, + aStyle == kBold_ANPTypefaceStyle ? 700 : 400, + 16.0, + NS_NewPermanentAtom(NS_LITERAL_STRING("en")), + 0.0, + PR_FALSE, PR_FALSE, + NS_LITERAL_STRING(""), + NS_LITERAL_STRING("")); + ANPTypeface* tf = new ANPTypeface; + gfxAndroidPlatform * p = (gfxAndroidPlatform*)gfxPlatform::GetPlatform(); + tf->mFont = gfxFT2Font::GetOrMakeFont(NS_ConvertASCIItoUTF16(name), &style); + return tf; +} + +ANPTypeface* +anp_typeface_createFromTypeface(const ANPTypeface* family, + ANPTypefaceStyle) +{ + NOT_IMPLEMENTED(); + return 0; +} + +int32_t +anp_typeface_getRefCount(const ANPTypeface*) +{ + NOT_IMPLEMENTED(); + return 0; +} + +void +anp_typeface_ref(ANPTypeface* tf) +{ + LOG("%s\n", __PRETTY_FUNCTION__); + if (tf->mFont) + tf->mFont->AddRef(); + +} + +void +anp_typeface_unref(ANPTypeface* tf) +{ + LOG("%s\n", __PRETTY_FUNCTION__); + if (tf->mFont) + tf->mFont->Release(); +} + +ANPTypefaceStyle +anp_typeface_getStyle(const ANPTypeface* ft) +{ + LOG("%s\n", __PRETTY_FUNCTION__); + return kBold_ANPTypefaceStyle; +} + +int32_t +anp_typeface_getFontPath(const ANPTypeface*, char path[], int32_t length, + int32_t* index) +{ + NOT_IMPLEMENTED(); + return 0; +} + +static const char* gFontDir; +#define FONT_DIR_SUFFIX "/fonts/" + +const char* +anp_typeface_getFontDirectoryPath() +{ + LOG("%s\n", __PRETTY_FUNCTION__); + if (NULL == gFontDir) { + const char* root = getenv("ANDROID_ROOT"); + size_t len = strlen(root); + char* storage = (char*)malloc(len + sizeof(FONT_DIR_SUFFIX)); + if (NULL == storage) { + return NULL; + } + memcpy(storage, root, len); + memcpy(storage + len, FONT_DIR_SUFFIX, sizeof(FONT_DIR_SUFFIX)); + // save this assignment for last, so that if multiple threads call us + // (which should never happen), we never return an incomplete global. + // At worst, we would allocate storage for the path twice. + gFontDir = storage; + } + + return 0; +} + +void InitTypeFaceInterface(ANPTypefaceInterfaceV0 *i) { + _assert(i->inSize == sizeof(*i)); + ASSIGN(i, createFromName); + ASSIGN(i, createFromTypeface); + ASSIGN(i, getRefCount); + ASSIGN(i, ref); + ASSIGN(i, unref); + ASSIGN(i, getStyle); + ASSIGN(i, getFontPath); + ASSIGN(i, getFontDirectoryPath); +} + diff --git a/dom/plugins/base/android/ANPWindow.cpp b/dom/plugins/base/android/ANPWindow.cpp new file mode 100644 index 00000000000..c26790054b2 --- /dev/null +++ b/dom/plugins/base/android/ANPWindow.cpp @@ -0,0 +1,91 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Android NPAPI support code + * + * The Initial Developer of the Original Code is + * the Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Doug Turner + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "assert.h" +#include "ANPBase.h" +#include + +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) +#define ASSIGN(obj, name) (obj)->name = anp_window_##name + +void +anp_window_setVisibleRects(NPP instance, const ANPRectI rects[], int32_t count) +{ + NOT_IMPLEMENTED(); +} + +void +anp_window_clearVisibleRects(NPP instance) +{ + NOT_IMPLEMENTED(); +} + +void +anp_window_showKeyboard(NPP instance, bool value) +{ + NOT_IMPLEMENTED(); +} + +void +anp_window_requestFullScreen(NPP instance) +{ + NOT_IMPLEMENTED(); +} + +void +anp_window_exitFullScreen(NPP instance) +{ + NOT_IMPLEMENTED(); +} + +void +anp_window_requestCenterFitZoom(NPP instance) +{ + NOT_IMPLEMENTED(); +} + +void InitWindowInterface(ANPWindowInterfaceV0 *i) { + _assert(i->inSize == sizeof(*i)); + ASSIGN(i, setVisibleRects); + ASSIGN(i, clearVisibleRects); + ASSIGN(i, showKeyboard); + ASSIGN(i, requestFullScreen); + ASSIGN(i, exitFullScreen); + ASSIGN(i, requestCenterFitZoom); +} + diff --git a/dom/plugins/base/android/Makefile.in b/dom/plugins/base/android/Makefile.in new file mode 100644 index 00000000000..42e5067f3ae --- /dev/null +++ b/dom/plugins/base/android/Makefile.in @@ -0,0 +1,81 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +DEPTH = ../../../.. +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE = plugin +LIBRARY_NAME = gkpluginandroid_s + +LIBXUL_LIBRARY = 1 +FORCE_STATIC_LIB = 1 +EXPORT_LIBRARY = 1 + +include $(topsrcdir)/config/config.mk +include $(topsrcdir)/ipc/chromium/chromium-config.mk + +EXPORTS = \ + android_npapi.h \ + $(NULL) + +CPPSRCS += ANPAudio.cpp \ + ANPCanvas.cpp \ + ANPEvent.cpp \ + ANPMatrix.cpp \ + ANPPath.cpp \ + ANPSystem.cpp \ + ANPWindow.cpp \ + ANPBitmap.cpp \ + ANPLog.cpp \ + ANPPaint.cpp \ + ANPSurface.cpp \ + ANPTypeface.cpp \ + $(NULL) + +LOCAL_INCLUDES += \ + -I$(topsrcdir)/dom/plugins/base \ + $(MOZ_CAIRO_CFLAGS) \ + $(NULL) + +DEFINES += -DMOZ_APP_NAME='"$(MOZ_APP_NAME)"' + +include $(topsrcdir)/config/rules.mk + diff --git a/dom/plugins/base/android/android_npapi.h b/dom/plugins/base/android/android_npapi.h new file mode 100644 index 00000000000..27b0c0c9fab --- /dev/null +++ b/dom/plugins/base/android/android_npapi.h @@ -0,0 +1,979 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Defines the android-specific types and functions as part of npapi + + In particular, defines the window and event types that are passed to + NPN_GetValue, NPP_SetWindow and NPP_HandleEvent. + + To minimize what native libraries the plugin links against, some + functionality is provided via function-ptrs (e.g. time, sound) + */ + +#ifndef android_npapi_H +#define android_npapi_H + +#include +#include "npapi.h" +#include + +/////////////////////////////////////////////////////////////////////////////// +// General types + +enum ANPBitmapFormats { + kUnknown_ANPBitmapFormat = 0, + kRGBA_8888_ANPBitmapFormat = 1, + kRGB_565_ANPBitmapFormat = 2 +}; +typedef int32_t ANPBitmapFormat; + +struct ANPPixelPacking { + uint8_t AShift; + uint8_t ABits; + uint8_t RShift; + uint8_t RBits; + uint8_t GShift; + uint8_t GBits; + uint8_t BShift; + uint8_t BBits; +}; + +struct ANPBitmap { + void* baseAddr; + ANPBitmapFormat format; + int32_t width; + int32_t height; + int32_t rowBytes; +}; + +struct ANPRectF { + float left; + float top; + float right; + float bottom; +}; + +struct ANPRectI { + int32_t left; + int32_t top; + int32_t right; + int32_t bottom; +}; + +struct ANPCanvas; +struct ANPMatrix; +struct ANPPaint; +struct ANPPath; +struct ANPRegion; +struct ANPTypeface; + +enum ANPMatrixFlags { + kIdentity_ANPMatrixFlag = 0, + kTranslate_ANPMatrixFlag = 0x01, + kScale_ANPMatrixFlag = 0x02, + kAffine_ANPMatrixFlag = 0x04, + kPerspective_ANPMatrixFlag = 0x08, +}; +typedef uint32_t ANPMatrixFlag; + +/////////////////////////////////////////////////////////////////////////////// +// NPN_GetValue + +/** queries for a specific ANPInterface. + + Maybe called with NULL for the NPP instance + + NPN_GetValue(inst, interface_enum, ANPInterface*) + */ +#define kLogInterfaceV0_ANPGetValue ((NPNVariable)1000) +#define kAudioTrackInterfaceV0_ANPGetValue ((NPNVariable)1001) +#define kCanvasInterfaceV0_ANPGetValue ((NPNVariable)1002) +#define kMatrixInterfaceV0_ANPGetValue ((NPNVariable)1003) +#define kPaintInterfaceV0_ANPGetValue ((NPNVariable)1004) +#define kPathInterfaceV0_ANPGetValue ((NPNVariable)1005) +#define kTypefaceInterfaceV0_ANPGetValue ((NPNVariable)1006) +#define kWindowInterfaceV0_ANPGetValue ((NPNVariable)1007) +#define kBitmapInterfaceV0_ANPGetValue ((NPNVariable)1008) +#define kSurfaceInterfaceV0_ANPGetValue ((NPNVariable)1009) +#define kSystemInterfaceV0_ANPGetValue ((NPNVariable)1010) +#define kEventInterfaceV0_ANPGetValue ((NPNVariable)1011) + +/** queries for the drawing models supported on this device. + + NPN_GetValue(inst, kSupportedDrawingModel_ANPGetValue, uint32_t* bits) + */ +#define kSupportedDrawingModel_ANPGetValue ((NPNVariable)2000) + +/** queries for the context (android.content.Context) of the plugin. If no + instance is specified the application's context is returned. If the instance + is given then the context returned is identical to the context used to + create the webview in which that instance resides. + + NOTE: Holding onto a non-application context after your instance has been + destroyed will cause a memory leak. Refer to the android documentation to + determine what context is best suited for your particular scenario. + + NPN_GetValue(inst, kJavaContext_ANPGetValue, jobject context) + */ +#define kJavaContext_ANPGetValue ((NPNVariable)2001) + +/////////////////////////////////////////////////////////////////////////////// +// NPN_SetValue + +/** Request to set the drawing model. SetValue will return false if the drawing + model is not supported or has insufficient information for configuration. + + NPN_SetValue(inst, kRequestDrawingModel_ANPSetValue, (void*)foo_ANPDrawingModel) + */ +#define kRequestDrawingModel_ANPSetValue ((NPPVariable)1000) + +/** These are used as bitfields in ANPSupportedDrawingModels_EnumValue, + and as-is in ANPRequestDrawingModel_EnumValue. The drawing model determines + how to interpret the ANPDrawingContext provided in the Draw event and how + to interpret the NPWindow->window field. + */ +enum ANPDrawingModels { + /** Draw into a bitmap from the browser thread in response to a Draw event. + NPWindow->window is reserved (ignore) + */ + kBitmap_ANPDrawingModel = 1 << 0, + /** Draw into a surface (e.g. raster, openGL, etc.) using the Java surface + interface. When this model is used the browser will invoke the Java + class specified in the plugin's apk manifest. From that class the browser + will invoke the appropriate method to return an an instance of a android + Java View. The instance is then embedded in the html. The plugin can then + manipulate the view as it would any normal Java View in android. + + Unlike the bitmap model, a surface model is opaque so no html content + behind the plugin will be visible. Unless the plugin needs to be + transparent the surface model should be chosen over the bitmap model as + it will have better performance. + + Further, a plugin can manipulate some surfaces in native code using the + ANPSurfaceInterface. This interface can be used to manipulate Java + objects that extend Surface.class by allowing them to access the + surface's underlying bitmap in native code. For instance, if a raster + surface is used the plugin can lock, draw directly into the bitmap, and + unlock the surface in native code without making JNI calls to the Java + surface object. + */ + kSurface_ANPDrawingModel = 1 << 1, +}; +typedef int32_t ANPDrawingModel; + +/** Request to receive/disable events. If the pointer is NULL then all flags will + be disabled. Otherwise, the event type will be enabled iff its corresponding + bit in the EventFlags bit field is set. + + NPN_SetValue(inst, ANPAcceptEvents, (void*)EventFlags) + */ +#define kAcceptEvents_ANPSetValue ((NPPVariable)1001) + +/** The EventFlags are a set of bits used to determine which types of events the + plugin wishes to receive. For example, if the value is 0x03 then both key + and touch events will be provided to the plugin. + */ +enum ANPEventFlag { + kKey_ANPEventFlag = 0x01, + kTouch_ANPEventFlag = 0x02, +}; +typedef uint32_t ANPEventFlags; + +/////////////////////////////////////////////////////////////////////////////// +// NPP_GetValue + +/** Requests that the plugin return a java surface to be displayed. This will + only be used if the plugin has choosen the kSurface_ANPDrawingModel. + + NPP_GetValue(inst, kJavaSurface_ANPGetValue, jobject surface) + */ +#define kJavaSurface_ANPGetValue ((NPPVariable)2000) + + +/////////////////////////////////////////////////////////////////////////////// +// ANDROID INTERFACE DEFINITIONS + +/** Interfaces provide additional functionality to the plugin via function ptrs. + Once an interface is retrieved, it is valid for the lifetime of the plugin + (just like browserfuncs). + + All ANPInterfaces begin with an inSize field, which must be set by the + caller (plugin) with the number of bytes allocated for the interface. + e.g. SomeInterface si; si.inSize = sizeof(si); browser->getvalue(..., &si); + */ +struct ANPInterface { + uint32_t inSize; // size (in bytes) of this struct +}; + +enum ANPLogTypes { + kError_ANPLogType = 0, // error + kWarning_ANPLogType = 1, // warning + kDebug_ANPLogType = 2 // debug only (informational) +}; +typedef int32_t ANPLogType; + +struct ANPLogInterfaceV0 : ANPInterface { + /** dumps printf messages to the log file + e.g. interface->log(instance, kWarning_ANPLogType, "value is %d", value); + */ + void (*log)(ANPLogType, const char format[], ...); +}; + +struct ANPBitmapInterfaceV0 : ANPInterface { + /** Returns true if the specified bitmap format is supported, and if packing + is non-null, sets it to the packing info for that format. + */ + bool (*getPixelPacking)(ANPBitmapFormat, ANPPixelPacking* packing); +}; + +struct ANPMatrixInterfaceV0 : ANPInterface { + /** Return a new identity matrix + */ + ANPMatrix* (*newMatrix)(); + /** Delete a matrix previously allocated by newMatrix() + */ + void (*deleteMatrix)(ANPMatrix*); + + ANPMatrixFlag (*getFlags)(const ANPMatrix*); + + void (*copy)(ANPMatrix* dst, const ANPMatrix* src); + + /** Return the matrix values in a float array (allcoated by the caller), + where the values are treated as follows: + w = x * [6] + y * [7] + [8]; + x' = (x * [0] + y * [1] + [2]) / w; + y' = (x * [3] + y * [4] + [5]) / w; + */ + void (*get3x3)(const ANPMatrix*, float[9]); + /** Initialize the matrix from values in a float array, + where the values are treated as follows: + w = x * [6] + y * [7] + [8]; + x' = (x * [0] + y * [1] + [2]) / w; + y' = (x * [3] + y * [4] + [5]) / w; + */ + void (*set3x3)(ANPMatrix*, const float[9]); + + void (*setIdentity)(ANPMatrix*); + void (*preTranslate)(ANPMatrix*, float tx, float ty); + void (*postTranslate)(ANPMatrix*, float tx, float ty); + void (*preScale)(ANPMatrix*, float sx, float sy); + void (*postScale)(ANPMatrix*, float sx, float sy); + void (*preSkew)(ANPMatrix*, float kx, float ky); + void (*postSkew)(ANPMatrix*, float kx, float ky); + void (*preRotate)(ANPMatrix*, float degrees); + void (*postRotate)(ANPMatrix*, float degrees); + void (*preConcat)(ANPMatrix*, const ANPMatrix*); + void (*postConcat)(ANPMatrix*, const ANPMatrix*); + + /** Return true if src is invertible, and if so, return its inverse in dst. + If src is not invertible, return false and ignore dst. + */ + bool (*invert)(ANPMatrix* dst, const ANPMatrix* src); + + /** Transform the x,y pairs in src[] by this matrix, and store the results + in dst[]. The count parameter is treated as the number of pairs in the + array. It is legal for src and dst to point to the same memory, but + illegal for the two arrays to partially overlap. + */ + void (*mapPoints)(ANPMatrix*, float dst[], const float src[], + int32_t count); +}; + +struct ANPPathInterfaceV0 : ANPInterface { + /** Return a new path */ + ANPPath* (*newPath)(); + + /** Delete a path previously allocated by ANPPath() */ + void (*deletePath)(ANPPath*); + + /** Make a deep copy of the src path, into the dst path (already allocated + by the caller). + */ + void (*copy)(ANPPath* dst, const ANPPath* src); + + /** Returns true if the two paths are the same (i.e. have the same points) + */ + bool (*equal)(const ANPPath* path0, const ANPPath* path1); + + /** Remove any previous points, initializing the path back to empty. */ + void (*reset)(ANPPath*); + + /** Return true if the path is empty (has no lines, quads or cubics). */ + bool (*isEmpty)(const ANPPath*); + + /** Return the path's bounds in bounds. */ + void (*getBounds)(const ANPPath*, ANPRectF* bounds); + + void (*moveTo)(ANPPath*, float x, float y); + void (*lineTo)(ANPPath*, float x, float y); + void (*quadTo)(ANPPath*, float x0, float y0, float x1, float y1); + void (*cubicTo)(ANPPath*, float x0, float y0, float x1, float y1, + float x2, float y2); + void (*close)(ANPPath*); + + /** Offset the src path by [dx, dy]. If dst is null, apply the + change directly to the src path. If dst is not null, write the + changed path into dst, and leave the src path unchanged. In that case + dst must have been previously allocated by the caller. + */ + void (*offset)(ANPPath* src, float dx, float dy, ANPPath* dst); + + /** Transform the path by the matrix. If dst is null, apply the + change directly to the src path. If dst is not null, write the + changed path into dst, and leave the src path unchanged. In that case + dst must have been previously allocated by the caller. + */ + void (*transform)(ANPPath* src, const ANPMatrix*, ANPPath* dst); +}; + +/** ANPColor is always defined to have the same packing on all platforms, and + it is always unpremultiplied. + + This is in contrast to 32bit format(s) in bitmaps, which are premultiplied, + and their packing may vary depending on the platform, hence the need for + ANPBitmapInterface::getPixelPacking() + */ +typedef uint32_t ANPColor; +#define ANPColor_ASHIFT 24 +#define ANPColor_RSHIFT 16 +#define ANPColor_GSHIFT 8 +#define ANPColor_BSHIFT 0 +#define ANP_MAKE_COLOR(a, r, g, b) \ + (((a) << ANPColor_ASHIFT) | \ + ((r) << ANPColor_RSHIFT) | \ + ((g) << ANPColor_GSHIFT) | \ + ((b) << ANPColor_BSHIFT)) + +enum ANPPaintFlag { + kAntiAlias_ANPPaintFlag = 1 << 0, + kFilterBitmap_ANPPaintFlag = 1 << 1, + kDither_ANPPaintFlag = 1 << 2, + kUnderlineText_ANPPaintFlag = 1 << 3, + kStrikeThruText_ANPPaintFlag = 1 << 4, + kFakeBoldText_ANPPaintFlag = 1 << 5, +}; +typedef uint32_t ANPPaintFlags; + +enum ANPPaintStyles { + kFill_ANPPaintStyle = 0, + kStroke_ANPPaintStyle = 1, + kFillAndStroke_ANPPaintStyle = 2 +}; +typedef int32_t ANPPaintStyle; + +enum ANPPaintCaps { + kButt_ANPPaintCap = 0, + kRound_ANPPaintCap = 1, + kSquare_ANPPaintCap = 2 +}; +typedef int32_t ANPPaintCap; + +enum ANPPaintJoins { + kMiter_ANPPaintJoin = 0, + kRound_ANPPaintJoin = 1, + kBevel_ANPPaintJoin = 2 +}; +typedef int32_t ANPPaintJoin; + +enum ANPPaintAligns { + kLeft_ANPPaintAlign = 0, + kCenter_ANPPaintAlign = 1, + kRight_ANPPaintAlign = 2 +}; +typedef int32_t ANPPaintAlign; + +enum ANPTextEncodings { + kUTF8_ANPTextEncoding = 0, + kUTF16_ANPTextEncoding = 1, +}; +typedef int32_t ANPTextEncoding; + +enum ANPTypefaceStyles { + kBold_ANPTypefaceStyle = 1 << 0, + kItalic_ANPTypefaceStyle = 1 << 1 +}; +typedef uint32_t ANPTypefaceStyle; + +typedef uint32_t ANPFontTableTag; + +struct ANPFontMetrics { + /** The greatest distance above the baseline for any glyph (will be <= 0) */ + float fTop; + /** The recommended distance above the baseline (will be <= 0) */ + float fAscent; + /** The recommended distance below the baseline (will be >= 0) */ + float fDescent; + /** The greatest distance below the baseline for any glyph (will be >= 0) */ + float fBottom; + /** The recommended distance to add between lines of text (will be >= 0) */ + float fLeading; +}; + +struct ANPTypefaceInterfaceV0 : ANPInterface { + /** Return a new reference to the typeface that most closely matches the + requested name and style. Pass null as the name to return + the default font for the requested style. Will never return null + + The 5 generic font names "serif", "sans-serif", "monospace", "cursive", + "fantasy" are recognized, and will be mapped to their logical font + automatically by this call. + + @param name May be NULL. The name of the font family. + @param style The style (normal, bold, italic) of the typeface. + @return reference to the closest-matching typeface. Caller must call + unref() when they are done with the typeface. + */ + ANPTypeface* (*createFromName)(const char name[], ANPTypefaceStyle); + + /** Return a new reference to the typeface that most closely matches the + requested typeface and specified Style. Use this call if you want to + pick a new style from the same family of the existing typeface. + If family is NULL, this selects from the default font's family. + + @param family May be NULL. The name of the existing type face. + @param s The style (normal, bold, italic) of the type face. + @return reference to the closest-matching typeface. Call must call + unref() when they are done. + */ + ANPTypeface* (*createFromTypeface)(const ANPTypeface* family, + ANPTypefaceStyle); + + /** Return the owner count of the typeface. A newly created typeface has an + owner count of 1. When the owner count is reaches 0, the typeface is + deleted. + */ + int32_t (*getRefCount)(const ANPTypeface*); + + /** Increment the owner count on the typeface + */ + void (*ref)(ANPTypeface*); + + /** Decrement the owner count on the typeface. When the count goes to 0, + the typeface is deleted. + */ + void (*unref)(ANPTypeface*); + + /** Return the style bits for the specified typeface + */ + ANPTypefaceStyle (*getStyle)(const ANPTypeface*); + + /** Some fonts are stored in files. If that is true for the fontID, then + this returns the byte length of the full file path. If path is not null, + then the full path is copied into path (allocated by the caller), up to + length bytes. If index is not null, then it is set to the truetype + collection index for this font, or 0 if the font is not in a collection. + + Note: getFontPath does not assume that path is a null-terminated string, + so when it succeeds, it only copies the bytes of the file name and + nothing else (i.e. it copies exactly the number of bytes returned by the + function. If the caller wants to treat path[] as a C string, it must be + sure that it is allocated at least 1 byte larger than the returned size, + and it must copy in the terminating 0. + + If the fontID does not correspond to a file, then the function returns + 0, and the path and index parameters are ignored. + + @param fontID The font whose file name is being queried + @param path Either NULL, or storage for receiving up to length bytes + of the font's file name. Allocated by the caller. + @param length The maximum space allocated in path (by the caller). + Ignored if path is NULL. + @param index Either NULL, or receives the TTC index for this font. + If the font is not a TTC, then will be set to 0. + @return The byte length of th font's file name, or 0 if the font is not + baked by a file. + */ + int32_t (*getFontPath)(const ANPTypeface*, char path[], int32_t length, + int32_t* index); + + /** Return a UTF8 encoded path name for the font directory, or NULL if not + supported. If returned, this string address will be valid for the life + of the plugin instance. It will always end with a '/' character. + */ + const char* (*getFontDirectoryPath)(); +}; + +struct ANPPaintInterfaceV0 : ANPInterface { + /** Return a new paint object, which holds all of the color and style + attributes that affect how things (geometry, text, bitmaps) are drawn + in a ANPCanvas. + + The paint that is returned is not tied to any particular plugin + instance, but it must only be accessed from one thread at a time. + */ + ANPPaint* (*newPaint)(); + void (*deletePaint)(ANPPaint*); + + ANPPaintFlags (*getFlags)(const ANPPaint*); + void (*setFlags)(ANPPaint*, ANPPaintFlags); + + ANPColor (*getColor)(const ANPPaint*); + void (*setColor)(ANPPaint*, ANPColor); + + ANPPaintStyle (*getStyle)(const ANPPaint*); + void (*setStyle)(ANPPaint*, ANPPaintStyle); + + float (*getStrokeWidth)(const ANPPaint*); + float (*getStrokeMiter)(const ANPPaint*); + ANPPaintCap (*getStrokeCap)(const ANPPaint*); + ANPPaintJoin (*getStrokeJoin)(const ANPPaint*); + void (*setStrokeWidth)(ANPPaint*, float); + void (*setStrokeMiter)(ANPPaint*, float); + void (*setStrokeCap)(ANPPaint*, ANPPaintCap); + void (*setStrokeJoin)(ANPPaint*, ANPPaintJoin); + + ANPTextEncoding (*getTextEncoding)(const ANPPaint*); + ANPPaintAlign (*getTextAlign)(const ANPPaint*); + float (*getTextSize)(const ANPPaint*); + float (*getTextScaleX)(const ANPPaint*); + float (*getTextSkewX)(const ANPPaint*); + void (*setTextEncoding)(ANPPaint*, ANPTextEncoding); + void (*setTextAlign)(ANPPaint*, ANPPaintAlign); + void (*setTextSize)(ANPPaint*, float); + void (*setTextScaleX)(ANPPaint*, float); + void (*setTextSkewX)(ANPPaint*, float); + + /** Return the typeface ine paint, or null if there is none. This does not + modify the owner count of the returned typeface. + */ + ANPTypeface* (*getTypeface)(const ANPPaint*); + + /** Set the paint's typeface. If the paint already had a non-null typeface, + its owner count is decremented. If the new typeface is non-null, its + owner count is incremented. + */ + void (*setTypeface)(ANPPaint*, ANPTypeface*); + + /** Return the width of the text. If bounds is not null, return the bounds + of the text in that rectangle. + */ + float (*measureText)(ANPPaint*, const void* text, uint32_t byteLength, + ANPRectF* bounds); + + /** Return the number of unichars specifed by the text. + If widths is not null, returns the array of advance widths for each + unichar. + If bounds is not null, returns the array of bounds for each unichar. + */ + int (*getTextWidths)(ANPPaint*, const void* text, uint32_t byteLength, + float widths[], ANPRectF bounds[]); + + /** Return in metrics the spacing values for text, respecting the paint's + typeface and pointsize, and return the spacing between lines + (descent - ascent + leading). If metrics is NULL, it will be ignored. + */ + float (*getFontMetrics)(ANPPaint*, ANPFontMetrics* metrics); +}; + +struct ANPCanvasInterfaceV0 : ANPInterface { + /** Return a canvas that will draw into the specified bitmap. Note: the + canvas copies the fields of the bitmap, so it need not persist after + this call, but the canvas DOES point to the same pixel memory that the + bitmap did, so the canvas should not be used after that pixel memory + goes out of scope. In the case of creating a canvas to draw into the + pixels provided by kDraw_ANPEventType, those pixels are only while + handling that event. + + The canvas that is returned is not tied to any particular plugin + instance, but it must only be accessed from one thread at a time. + */ + ANPCanvas* (*newCanvas)(const ANPBitmap*); + void (*deleteCanvas)(ANPCanvas*); + + void (*save)(ANPCanvas*); + void (*restore)(ANPCanvas*); + void (*translate)(ANPCanvas*, float tx, float ty); + void (*scale)(ANPCanvas*, float sx, float sy); + void (*rotate)(ANPCanvas*, float degrees); + void (*skew)(ANPCanvas*, float kx, float ky); + void (*concat)(ANPCanvas*, const ANPMatrix*); + void (*clipRect)(ANPCanvas*, const ANPRectF*); + void (*clipPath)(ANPCanvas*, const ANPPath*); + + /** Return the current matrix on the canvas + */ + void (*getTotalMatrix)(ANPCanvas*, ANPMatrix*); + /** Return the current clip bounds in local coordinates, expanding it to + account for antialiasing edge effects if aa is true. If the + current clip is empty, return false and ignore the bounds argument. + */ + bool (*getLocalClipBounds)(ANPCanvas*, ANPRectF* bounds, bool aa); + /** Return the current clip bounds in device coordinates in bounds. If the + current clip is empty, return false and ignore the bounds argument. + */ + bool (*getDeviceClipBounds)(ANPCanvas*, ANPRectI* bounds); + + void (*drawColor)(ANPCanvas*, ANPColor); + void (*drawPaint)(ANPCanvas*, const ANPPaint*); + void (*drawLine)(ANPCanvas*, float x0, float y0, float x1, float y1, + const ANPPaint*); + void (*drawRect)(ANPCanvas*, const ANPRectF*, const ANPPaint*); + void (*drawOval)(ANPCanvas*, const ANPRectF*, const ANPPaint*); + void (*drawPath)(ANPCanvas*, const ANPPath*, const ANPPaint*); + void (*drawText)(ANPCanvas*, const void* text, uint32_t byteLength, + float x, float y, const ANPPaint*); + void (*drawPosText)(ANPCanvas*, const void* text, uint32_t byteLength, + const float xy[], const ANPPaint*); + void (*drawBitmap)(ANPCanvas*, const ANPBitmap*, float x, float y, + const ANPPaint*); + void (*drawBitmapRect)(ANPCanvas*, const ANPBitmap*, + const ANPRectI* src, const ANPRectF* dst, + const ANPPaint*); +}; + +struct ANPWindowInterfaceV0 : ANPInterface { + /** Registers a set of rectangles that the plugin would like to keep on + screen. The rectangles are listed in order of priority with the highest + priority rectangle in location rects[0]. The browser will attempt to keep + as many of the rectangles on screen as possible and will scroll them into + view in response to the invocation of this method and other various events. + The count specifies how many rectangles are in the array. If the count is + zero it signals the browser that any existing rectangles should be cleared + and no rectangles will be tracked. + */ + void (*setVisibleRects)(NPP instance, const ANPRectI rects[], int32_t count); + /** Clears any rectangles that are being tracked as a result of a call to + setVisibleRects. This call is equivalent to setVisibleRect(inst, NULL, 0). + */ + void (*clearVisibleRects)(NPP instance); + /** Given a boolean value of true the device will be requested to provide + a keyboard. A value of false will result in a request to hide the + keyboard. Further, the on-screen keyboard will not be displayed if a + physical keyboard is active. + */ + void (*showKeyboard)(NPP instance, bool value); + /** Called when a plugin wishes to enter into full screen mode. The plugin's + Java class (defined in the plugin's apk manifest) will be called + asynchronously to provide a View object to be displayed full screen. + */ + void (*requestFullScreen)(NPP instance); + /** Called when a plugin wishes to exit from full screen mode. As a result, + the plugin's full screen view will be discarded by the view system. + */ + void (*exitFullScreen)(NPP instance); + /** Called when a plugin wishes to be zoomed and centered in the current view. + */ + void (*requestCenterFitZoom)(NPP instance); +}; + +/////////////////////////////////////////////////////////////////////////////// + +enum ANPSampleFormats { + kUnknown_ANPSamleFormat = 0, + kPCM16Bit_ANPSampleFormat = 1, + kPCM8Bit_ANPSampleFormat = 2 +}; +typedef int32_t ANPSampleFormat; + +/** The audio buffer is passed to the callback proc to request more samples. + It is owned by the system, and the callback may read it, but should not + maintain a pointer to it outside of the scope of the callback proc. + */ +struct ANPAudioBuffer { + // RO - repeat what was specified in newTrack() + int32_t channelCount; + // RO - repeat what was specified in newTrack() + ANPSampleFormat format; + /** This buffer is owned by the caller. Inside the callback proc, up to + "size" bytes of sample data should be written into this buffer. The + address is only valid for the scope of a single invocation of the + callback proc. + */ + void* bufferData; + /** On input, specifies the maximum number of bytes that can be written + to "bufferData". On output, specifies the actual number of bytes that + the callback proc wrote into "bufferData". + */ + uint32_t size; +}; + +enum ANPAudioEvents { + /** This event is passed to the callback proc when the audio-track needs + more sample data written to the provided buffer parameter. + */ + kMoreData_ANPAudioEvent = 0, + /** This event is passed to the callback proc if the audio system runs out + of sample data. In this event, no buffer parameter will be specified + (i.e. NULL will be passed to the 3rd parameter). + */ + kUnderRun_ANPAudioEvent = 1 +}; +typedef int32_t ANPAudioEvent; + +/** Called to feed sample data to the track. This will be called in a separate + thread. However, you may call trackStop() from the callback (but you + cannot delete the track). + + For example, when you have written the last chunk of sample data, you can + immediately call trackStop(). This will take effect after the current + buffer has been played. + + The "user" parameter is the same value that was passed to newTrack() + */ +typedef void (*ANPAudioCallbackProc)(ANPAudioEvent event, void* user, + ANPAudioBuffer* buffer); + +struct ANPAudioTrack; // abstract type for audio tracks + +struct ANPAudioTrackInterfaceV0 : ANPInterface { + /** Create a new audio track, or NULL on failure. The track is initially in + the stopped state and therefore ANPAudioCallbackProc will not be called + until the track is started. + */ + ANPAudioTrack* (*newTrack)(uint32_t sampleRate, // sampling rate in Hz + ANPSampleFormat, + int channelCount, // MONO=1, STEREO=2 + ANPAudioCallbackProc, + void* user); + /** Deletes a track that was created using newTrack. The track can be + deleted in any state and it waits for the ANPAudioCallbackProc thread + to exit before returning. + */ + void (*deleteTrack)(ANPAudioTrack*); + + void (*start)(ANPAudioTrack*); + void (*pause)(ANPAudioTrack*); + void (*stop)(ANPAudioTrack*); + /** Returns true if the track is not playing (e.g. pause or stop was called, + or start was never called. + */ + bool (*isStopped)(ANPAudioTrack*); +}; + +/////////////////////////////////////////////////////////////////////////////// +// DEFINITION OF VALUES PASSED THROUGH NPP_HandleEvent + +enum ANPEventTypes { + kNull_ANPEventType = 0, + kKey_ANPEventType = 1, + /** Mouse events are triggered by either clicking with the navigational pad + or by tapping the touchscreen (if the kDown_ANPTouchAction is handled by + the plugin then no mouse event is generated). The kKey_ANPEventFlag has + to be set to true in order to receive these events. + */ + kMouse_ANPEventType = 2, + /** Touch events are generated when the user touches on the screen. The + kTouch_ANPEventFlag has to be set to true in order to receive these + events. + */ + kTouch_ANPEventType = 3, + /** Only triggered by a plugin using the kBitmap_ANPDrawingModel. This event + signals that the plugin needs to redraw itself into the provided bitmap. + */ + kDraw_ANPEventType = 4, + kLifecycle_ANPEventType = 5, + + /** This event type is completely defined by the plugin. + When creating an event, the caller must always set the first + two fields, the remaining data is optional. + ANPEvent evt; + evt.inSize = sizeof(ANPEvent); + evt.eventType = kCustom_ANPEventType + // other data slots are optional + evt.other[] = ...; + To post a copy of the event, call + eventInterface->postEvent(myNPPInstance, &evt); + That call makes a copy of the event struct, and post that on the event + queue for the plugin. + */ + kCustom_ANPEventType = 6, +}; +typedef int32_t ANPEventType; + +enum ANPKeyActions { + kDown_ANPKeyAction = 0, + kUp_ANPKeyAction = 1, +}; +typedef int32_t ANPKeyAction; + +#include "ANPKeyCodes.h" +typedef int32_t ANPKeyCode; + +enum ANPKeyModifiers { + kAlt_ANPKeyModifier = 1 << 0, + kShift_ANPKeyModifier = 1 << 1, +}; +// bit-field containing some number of ANPKeyModifier bits +typedef uint32_t ANPKeyModifier; + +enum ANPMouseActions { + kDown_ANPMouseAction = 0, + kUp_ANPMouseAction = 1, +}; +typedef int32_t ANPMouseAction; + +enum ANPTouchActions { + /** This occurs when the user first touches on the screen. As such, this + action will always occur prior to any of the other touch actions. If + the plugin chooses to not handle this action then no other events + related to that particular touch gesture will be generated. + */ + kDown_ANPTouchAction = 0, + kUp_ANPTouchAction = 1, + kMove_ANPTouchAction = 2, + kCancel_ANPTouchAction = 3, + // The web view will ignore the return value from the following actions + kLongPress_ANPTouchAction = 4, + kDoubleTap_ANPTouchAction = 5, +}; +typedef int32_t ANPTouchAction; + +enum ANPLifecycleActions { + /** The web view containing this plugin has been paused. See documentation + on the android activity lifecycle for more information. + */ + kPause_ANPLifecycleAction = 0, + /** The web view containing this plugin has been resumed. See documentation + on the android activity lifecycle for more information. + */ + kResume_ANPLifecycleAction = 1, + /** The plugin has focus and is now the recipient of input events (e.g. key, + touch, etc.) + */ + kGainFocus_ANPLifecycleAction = 2, + /** The plugin has lost focus and will not receive any input events until it + regains focus. This event is always preceded by a GainFocus action. + */ + kLoseFocus_ANPLifecycleAction = 3, + /** The browser is running low on available memory and is requesting that + the plugin free any unused/inactive resources to prevent a performance + degradation. + */ + kFreeMemory_ANPLifecycleAction = 4, + /** The page has finished loading. This happens when the page's top level + frame reports that it has completed loading. + */ + kOnLoad_ANPLifecycleAction = 5, + /** The browser is honoring the plugin's request to go full screen. Upon + returning from this event the browser will resize the plugin's java + surface to full-screen coordinates. + */ + kEnterFullScreen_ANPLifecycleAction = 6, + /** The browser has exited from full screen mode. Immediately prior to + sending this event the browser has resized the plugin's java surface to + its original coordinates. + */ + kExitFullScreen_ANPLifecycleAction = 7, + /** The plugin is visible to the user on the screen. This event will always + occur after a kOffScreen_ANPLifecycleAction event. + */ + kOnScreen_ANPLifecycleAction = 8, + /** The plugin is no longer visible to the user on the screen. This event + will always occur prior to an kOnScreen_ANPLifecycleAction event. + */ + kOffScreen_ANPLifecycleAction = 9, +}; +typedef uint32_t ANPLifecycleAction; + +/* This is what is passed to NPP_HandleEvent() */ +struct ANPEvent { + uint32_t inSize; // size of this struct in bytes + ANPEventType eventType; + // use based on the value in eventType + union { + struct { + ANPKeyAction action; + ANPKeyCode nativeCode; + int32_t virtualCode; // windows virtual key code + ANPKeyModifier modifiers; + int32_t repeatCount; // 0 for initial down (or up) + int32_t unichar; // 0 if there is no value + } key; + struct { + ANPMouseAction action; + int32_t x; // relative to your "window" (0...width) + int32_t y; // relative to your "window" (0...height) + } mouse; + struct { + ANPTouchAction action; + ANPKeyModifier modifiers; + int32_t x; // relative to your "window" (0...width) + int32_t y; // relative to your "window" (0...height) + } touch; + struct { + ANPLifecycleAction action; + } lifecycle; + struct { + ANPDrawingModel model; + // relative to (0,0) in top-left of your plugin + ANPRectI clip; + // use based on the value in model + union { + ANPBitmap bitmap; + } data; + } draw; + int32_t other[8]; + } data; +}; + +struct ANPEventInterfaceV0 : ANPInterface { + /** Post a copy of the specified event to the plugin. The event will be + delivered to the plugin in its main thread (the thread that receives + other ANPEvents). If, after posting before delivery, the NPP instance + is torn down, the event will be discarded. + */ + void (*postEvent)(NPP inst, const ANPEvent* event); +}; + +struct ANPSystemInterfaceV0 : ANPInterface { + /** Return the path name for the current Application's plugin data directory, + or NULL if not supported + */ + const char* (*getApplicationDataDirectory)(); + + /** A helper function to load java classes from the plugin's apk. The + function looks for a class given the fully qualified and null terminated + string representing the className. For example, + + const char* className = "com.android.mypackage.MyClass"; + + If the class cannot be found or there is a problem loading the class + NULL will be returned. + */ + jclass (*loadJavaClass)(NPP instance, const char* className); +}; + +struct ANPSurfaceInterfaceV0 : ANPInterface { + /** Locks the surface from manipulation by other threads and provides a bitmap + to be written to. The dirtyRect param specifies which portion of the + bitmap will be written to. If the dirtyRect is NULL then the entire + surface will be considered dirty. If the lock was successful the function + will return true and the bitmap will be set to point to a valid bitmap. + If not the function will return false and the bitmap will be set to NULL. + */ + bool (*lock)(JNIEnv* env, jobject surface, ANPBitmap* bitmap, ANPRectI* dirtyRect); + /** Given a locked surface handle (i.e. result of a successful call to lock) + the surface is unlocked and the contents of the bitmap, specifically + those inside the dirtyRect are written to the screen. + */ + void (*unlock)(JNIEnv* env, jobject surface); +}; + +typedef int32_t int32; +typedef uint32_t uint32; +typedef int16_t int16; +typedef uint16_t uint16; + +#endif diff --git a/dom/plugins/base/android_npapi.h b/dom/plugins/base/android_npapi.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dom/plugins/base/npfunctions.h b/dom/plugins/base/npfunctions.h index 3b70a39419d..fe32ce557ee 100644 --- a/dom/plugins/base/npfunctions.h +++ b/dom/plugins/base/npfunctions.h @@ -48,6 +48,10 @@ #include "npapi.h" #include "npruntime.h" +#ifdef ANDROID +#include +#endif + typedef NPError (* NP_LOADDS NPP_NewProcPtr)(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved); typedef NPError (* NP_LOADDS NPP_DestroyProcPtr)(NPP instance, NPSavedData** save); typedef NPError (* NP_LOADDS NPP_SetWindowProcPtr)(NPP instance, NPWindow* window); @@ -307,8 +311,13 @@ NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs); typedef NPError (*NP_GetEntryPointsFunc)(NPPluginFuncs*); NP_EXPORT(NPError) NP_GetEntryPoints(NPPluginFuncs* pFuncs); #else -typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*, NPPluginFuncs*); -NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs); +#ifdef ANDROID +typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*, NPPluginFuncs*, JNIEnv* pEnv); +NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, JNIEnv* pEnv); +#else +typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*, NPPluginFuncs*); +NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs); +#endif #endif typedef NPError (*NP_ShutdownFunc)(void); NP_EXPORT(NPError) NP_Shutdown(void); diff --git a/dom/plugins/base/nsNPAPIPlugin.cpp b/dom/plugins/base/nsNPAPIPlugin.cpp index fc6788d6d9a..a360f29b703 100644 --- a/dom/plugins/base/nsNPAPIPlugin.cpp +++ b/dom/plugins/base/nsNPAPIPlugin.cpp @@ -127,6 +127,13 @@ using mozilla::plugins::PluginModuleParent; #include #endif +#ifdef ANDROID +#include "ANPBase.h" +#include "AndroidBridge.h" +#include +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) +#endif + using namespace mozilla; using namespace mozilla::plugins::parent; @@ -477,7 +484,7 @@ nsNPAPIPlugin::CreatePlugin(nsPluginTag *aPluginTag, nsNPAPIPlugin** aResult) return NS_ERROR_FAILURE; } -#ifdef XP_MACOSX +#if defined(XP_MACOSX) || defined(ANDROID) if (!pluginLib->HasRequiredFunctions()) { NS_WARNING("Not all necessary functions exposed by plugin, it will not load."); return NS_ERROR_FAILURE; @@ -2264,6 +2271,112 @@ _getvalue(NPP npp, NPNVariable variable, void *result) } #endif +#ifdef ANDROID + case kLogInterfaceV0_ANPGetValue: { + LOG("get log interface"); + ANPLogInterfaceV0 *i = (ANPLogInterfaceV0 *) result; + InitLogInterface(i); + return NPERR_NO_ERROR; + } + + case kBitmapInterfaceV0_ANPGetValue: { + LOG("get bitmap interface"); + ANPBitmapInterfaceV0 *i = (ANPBitmapInterfaceV0 *) result; + InitBitmapInterface(i); + return NPERR_NO_ERROR; + } + + case kMatrixInterfaceV0_ANPGetValue: { + LOG("get matrix interface"); + ANPMatrixInterfaceV0 *i = (ANPMatrixInterfaceV0 *) result; + InitMatrixInterface(i); + return NPERR_NO_ERROR; + } + + case kPathInterfaceV0_ANPGetValue: { + LOG("get path interface"); + ANPPathInterfaceV0 *i = (ANPPathInterfaceV0 *) result; + InitPathInterface(i); + return NPERR_NO_ERROR; + } + + case kTypefaceInterfaceV0_ANPGetValue: { + LOG("get typeface interface"); + ANPTypefaceInterfaceV0 *i = (ANPTypefaceInterfaceV0 *) result; + InitTypeFaceInterface(i); + return NPERR_NO_ERROR; + } + + case kPaintInterfaceV0_ANPGetValue: { + LOG("get paint interface"); + ANPPaintInterfaceV0 *i = (ANPPaintInterfaceV0 *) result; + InitPaintInterface(i); + return NPERR_NO_ERROR; + } + + case kCanvasInterfaceV0_ANPGetValue: { + LOG("get canvas interface"); + ANPCanvasInterfaceV0 *i = (ANPCanvasInterfaceV0 *) result; + InitCanvasInterface(i); + return NPERR_NO_ERROR; + } + + case kWindowInterfaceV0_ANPGetValue: { + LOG("get window interface"); + ANPWindowInterfaceV0 *i = (ANPWindowInterfaceV0 *) result; + InitWindowInterface(i); + return NPERR_NO_ERROR; + } + + case kAudioTrackInterfaceV0_ANPGetValue: { + LOG("get audio interface"); + ANPAudioTrackInterfaceV0 *i = (ANPAudioTrackInterfaceV0 *) result; + InitAudioTrackInterface(i); + return NPERR_NO_ERROR; + } + + case kEventInterfaceV0_ANPGetValue: { + LOG("get event interface"); + ANPEventInterfaceV0 *i = (ANPEventInterfaceV0 *) result; + InitEventInterface(i); + return NPERR_NO_ERROR; + } + + case kSystemInterfaceV0_ANPGetValue: { + LOG("get system interface"); + ANPSystemInterfaceV0* i = reinterpret_cast(result); + InitSystemInterface(i); + LOG("done system interface"); + return NPERR_NO_ERROR; + } + + case kSurfaceInterfaceV0_ANPGetValue: { + LOG("get surface interface"); + ANPSurfaceInterfaceV0 *i = (ANPSurfaceInterfaceV0 *) result; + InitSurfaceInterface(i); + return NPERR_NO_ERROR; + } + + case kSupportedDrawingModel_ANPGetValue: { + LOG("get supported drawing model"); + uint32_t* bits = reinterpret_cast(result); + *bits = kBitmap_ANPDrawingModel && kSurface_ANPDrawingModel; + return NPERR_NO_ERROR; + } + + case kJavaContext_ANPGetValue: { + LOG("get context"); + JNIEnv* env = GetJNIForThread(); + jclass cls = env->FindClass("org/mozilla/gecko/GeckoApp"); + jfieldID field = env->GetStaticFieldID(cls, "mAppContext", + "Lorg/mozilla/gecko/GeckoApp;"); + jobject ret = env->GetStaticObjectField(cls, field); + int32_t* i = reinterpret_cast(result); + *i = reinterpret_cast(ret); + return NPERR_NO_ERROR; + } +#endif + // we no longer hand out any XPCOM objects case NPNVDOMElement: // fall through @@ -2275,6 +2388,7 @@ _getvalue(NPP npp, NPNVariable variable, void *result) *(nsISupports**)result = nsnull; // fall through default: + NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_getvalue unhandled get value: %d\n", variable)); return NPERR_GENERIC_ERROR; } } @@ -2374,7 +2488,14 @@ _setvalue(NPP npp, NPPVariable variable, void *result) } } #endif - +#ifdef ANDROID + case kRequestDrawingModel_ANPSetValue: + if (inst) + inst->SetDrawingModel(NS_PTR_TO_INT32(result)); + return NPERR_NO_ERROR; + case kAcceptEvents_ANPSetValue: + return NPERR_NO_ERROR; +#endif default: return NPERR_GENERIC_ERROR; } diff --git a/dom/plugins/base/nsNPAPIPluginInstance.cpp b/dom/plugins/base/nsNPAPIPluginInstance.cpp index e104f07fc78..aa3f398acba 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.cpp +++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp @@ -61,13 +61,22 @@ #include "nsNetCID.h" #include "nsIContent.h" +#ifdef ANDROID +#include "ANPBase.h" +#include +#include "android_npapi.h" +#include "mozilla/Mutex.h" +#include "mozilla/CondVar.h" +#include "AndroidBridge.h" +#endif + using namespace mozilla; using namespace mozilla::plugins::parent; static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID); static NS_DEFINE_IID(kIPluginStreamListenerIID, NS_IPLUGINSTREAMLISTENER_IID); -NS_IMPL_ISUPPORTS0(nsNPAPIPluginInstance) +NS_IMPL_THREADSAFE_ISUPPORTS0(nsNPAPIPluginInstance) nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin) : @@ -77,6 +86,10 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin) #else mDrawingModel(NPDrawingModelQuickDraw), #endif +#endif +#ifdef ANDROID + mSurface(nsnull), + mDrawingModel(0), #endif mRunning(NOT_STARTED), mWindowless(PR_FALSE), @@ -684,7 +697,7 @@ nsNPAPIPluginInstance::UsesDOMForCursor() return mUsesDOMForCursor; } -#ifdef XP_MACOSX +#if defined(XP_MACOSX) void nsNPAPIPluginInstance::SetDrawingModel(NPDrawingModel aModel) { mDrawingModel = aModel; @@ -702,12 +715,69 @@ void nsNPAPIPluginInstance::SetEventModel(NPEventModel aModel) owner->SetEventModel(aModel); } +#endif + +#if defined(ANDROID) +void nsNPAPIPluginInstance::SetDrawingModel(PRUint32 aModel) +{ + mDrawingModel = aModel; +} + +class SurfaceGetter : public nsRunnable { +public: + SurfaceGetter(NPPluginFuncs* aPluginFunctions, NPP_t aNPP) : + mHaveSurface(PR_FALSE), mPluginFunctions(aPluginFunctions), mNPP(aNPP) { + mLock = new Mutex("SurfaceGetter::Lock"); + mCondVar = new CondVar(*mLock, "SurfaceGetter::CondVar"); + + } + ~SurfaceGetter() { + delete mLock; + delete mCondVar; + } + nsresult Run() { + MutexAutoLock lock(*mLock); + (*mPluginFunctions->getvalue)(&mNPP, kJavaSurface_ANPGetValue, &mSurface); + mHaveSurface = PR_TRUE; + mCondVar->Notify(); + return NS_OK; + } + void* GetSurface() { + MutexAutoLock lock(*mLock); + mHaveSurface = PR_FALSE; + AndroidBridge::Bridge()->PostToJavaThread(this); + while (!mHaveSurface) + mCondVar->Wait(); + return mSurface; + } +private: + NPP_t mNPP; + void* mSurface; + Mutex* mLock; + CondVar* mCondVar; + PRBool mHaveSurface; + NPPluginFuncs* mPluginFunctions; +}; + + +void* nsNPAPIPluginInstance::GetJavaSurface() +{ + if (mDrawingModel != kSurface_ANPDrawingModel) + return nsnull; + + if (mSurface) + return mSurface; + + nsCOMPtr sg = new SurfaceGetter(mPlugin->PluginFuncs(), mNPP); + mSurface = sg->GetSurface(); + return mSurface; +} #endif nsresult nsNPAPIPluginInstance::GetDrawingModel(PRInt32* aModel) { -#ifdef XP_MACOSX +#if defined(XP_MACOSX) || defined(ANDROID) *aModel = (PRInt32)mDrawingModel; return NS_OK; #else @@ -806,7 +876,12 @@ nsNPAPIPluginInstance::DefineJavaProperties() nsresult nsNPAPIPluginInstance::IsWindowless(PRBool* isWindowless) { +#ifdef ANDROID + // On android, pre-honeycomb, all plugins are treated as windowless. + *isWindowless = PR_TRUE; +#else *isWindowless = mWindowless; +#endif return NS_OK; } @@ -1066,6 +1141,28 @@ nsNPAPIPluginInstance::PrivateModeStateChanged() return NS_ERROR_FAILURE; } +class DelayUnscheduleEvent : public nsRunnable { +public: + nsRefPtr mInstance; + uint32_t mTimerID; + DelayUnscheduleEvent(nsNPAPIPluginInstance* aInstance, uint32_t aTimerId) + : mInstance(aInstance) + , mTimerID(aTimerId) + {} + + ~DelayUnscheduleEvent() {} + + NS_IMETHOD Run(); +}; + +NS_IMETHODIMP +DelayUnscheduleEvent::Run() +{ + mInstance->UnscheduleTimer(mTimerID); + return NS_OK; +} + + static void PluginTimerCallback(nsITimer *aTimer, void *aClosure) { @@ -1073,7 +1170,11 @@ PluginTimerCallback(nsITimer *aTimer, void *aClosure) NPP npp = t->npp; uint32_t id = t->id; + // Some plugins (Flash on Android) calls unscheduletimer + // from this callback. + t->inCallback = PR_TRUE; (*(t->callback))(npp, id); + t->inCallback = PR_FALSE; // Make sure we still have an instance and the timer is still alive // after the callback. @@ -1107,6 +1208,7 @@ nsNPAPIPluginInstance::ScheduleTimer(uint32_t interval, NPBool repeat, void (*ti { nsNPAPITimer *newTimer = new nsNPAPITimer(); + newTimer->inCallback = PR_FALSE; newTimer->npp = &mNPP; // generate ID that is unique to this instance @@ -1144,6 +1246,12 @@ nsNPAPIPluginInstance::UnscheduleTimer(uint32_t timerID) if (!t) return; + if (t->inCallback) { + nsCOMPtr e = new DelayUnscheduleEvent(this, timerID); + NS_DispatchToCurrentThread(e); + return; + } + // cancel the timer t->timer->Cancel(); diff --git a/dom/plugins/base/nsNPAPIPluginInstance.h b/dom/plugins/base/nsNPAPIPluginInstance.h index 555ef755718..ef7cedd4e1a 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.h +++ b/dom/plugins/base/nsNPAPIPluginInstance.h @@ -68,6 +68,7 @@ public: uint32_t id; nsCOMPtr timer; void (*callback)(NPP npp, uint32_t timerID); + PRBool inCallback; }; class nsNPAPIPluginInstance : public nsISupports @@ -85,6 +86,9 @@ public: nsresult NewStreamToPlugin(nsIPluginStreamListener** listener); nsresult NewStreamFromPlugin(const char* type, const char* target, nsIOutputStream* *result); nsresult Print(NPPrint* platformPrint); +#ifdef ANDROID + nsresult PostEvent(void* event) { return 0; }; +#endif nsresult HandleEvent(void* event, PRInt16* result); nsresult GetValueFromPlugin(NPPVariable variable, void* value); nsresult GetDrawingModel(PRInt32* aModel); @@ -141,6 +145,11 @@ public: void SetEventModel(NPEventModel aModel); #endif +#ifdef ANDROID + void SetDrawingModel(PRUint32 aModel); + void* GetJavaSurface(); +#endif + nsresult NewStreamListener(const char* aURL, void* notifyData, nsIPluginStreamListener** listener); @@ -207,6 +216,10 @@ protected: NPDrawingModel mDrawingModel; #endif +#ifdef ANDROID + PRUint32 mDrawingModel; +#endif + enum { NOT_STARTED, RUNNING, @@ -250,6 +263,9 @@ private: nsCOMPtr mURI; PRPackedBool mUsePluginLayersPref; +#ifdef ANDROID + void* mSurface; +#endif }; #endif // nsNPAPIPluginInstance_h_ diff --git a/dom/plugins/base/nsPluginHost.cpp b/dom/plugins/base/nsPluginHost.cpp index 7c2c5d13f45..689e01b6874 100644 --- a/dom/plugins/base/nsPluginHost.cpp +++ b/dom/plugins/base/nsPluginHost.cpp @@ -159,6 +159,11 @@ #include "winbase.h" #endif +#ifdef ANDROID +#include +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) +#endif + using namespace mozilla; using mozilla::TimeStamp; @@ -2229,7 +2234,7 @@ nsresult nsPluginHost::ScanPluginsDirectoryList(nsISimpleEnumerator *dirEnum, nsCOMPtr nextDir(do_QueryInterface(supports, &rv)); if (NS_FAILED(rv)) continue; - + // don't pass aPluginsChanged directly to prevent it from been reset PRBool pluginschanged = PR_FALSE; ScanPluginsDirectory(nextDir, aCreatePluginList, &pluginschanged); @@ -2324,6 +2329,10 @@ nsresult nsPluginHost::FindPlugins(PRBool aCreatePluginList, PRBool * aPluginsCh NS_ITERATIVE_UNREF_LIST(nsRefPtr, mInvalidPlugins, mNext); return NS_OK; } + } else { +#ifdef ANDROID + LOG("getting plugins dir failed"); +#endif } mPluginsLoaded = PR_TRUE; // at this point 'some' plugins have been loaded, diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp index 54d98a6df3b..a41d4909d9c 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -118,6 +118,16 @@ static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); #include "gfxXlibNativeRenderer.h" #endif +#ifdef ANDROID +#include "ANPBase.h" +#include "android_npapi.h" +#include "AndroidBridge.h" +using namespace mozilla::dom; + +#include +#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args) +#endif + using namespace mozilla; // special class for handeling DOM context menu events because for @@ -1255,7 +1265,12 @@ nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays() // Add PARAM and null separator. mCachedAttrParamNames [nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("PARAM")); +#ifdef ANDROID + // Flash expects an empty string on android + mCachedAttrParamValues[nextAttrParamIndex] = ToNewUTF8String(NS_LITERAL_STRING("")); +#else mCachedAttrParamValues[nextAttrParamIndex] = nsnull; +#endif nextAttrParamIndex++; // Add PARAM name/value pairs. @@ -1640,8 +1655,48 @@ void nsPluginInstanceOwner::ScrollPositionDidChange(nscoord aX, nscoord aY) #endif } +#ifdef ANDROID +void nsPluginInstanceOwner::RemovePluginView() +{ + if (mInstance && mObjectFrame) { + void* surface = mInstance->GetJavaSurface(); + if (surface) { + JNIEnv* env = GetJNIForThread(); + if (env) { + jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell"); + jmethodID method = env->GetStaticMethodID(cls, + "removePluginView", + "(Landroid/view/View;)V"); + env->CallStaticVoidMethod(cls, method, surface); + } + } + } +} +#endif + nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent) { +#ifdef ANDROID + { + ANPEvent event; + event.inSize = sizeof(ANPEvent); + event.eventType = kLifecycle_ANPEventType; + + nsAutoString eventType; + aFocusEvent->GetType(eventType); + if (eventType.EqualsLiteral("focus")) { + event.data.lifecycle.action = kGainFocus_ANPLifecycleAction; + } + else if (eventType.EqualsLiteral("blur")) { + event.data.lifecycle.action = kLoseFocus_ANPLifecycleAction; + } + else { + NS_ASSERTION(PR_FALSE, "nsPluginInstanceOwner::DispatchFocusToPlugin, wierd eventType"); + } + mInstance->HandleEvent(&event, nsnull); + } +#endif + #ifndef XP_MACOSX if (!mPluginWindow || (mPluginWindow->type == NPWindowTypeWindow)) { // continue only for cases without child window @@ -1912,8 +1967,6 @@ static unsigned int XInputEventState(const nsInputEvent& anEvent) nsEventStatus nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent) { - // printf("nsGUIEvent.message: %d\n", anEvent.message); - nsEventStatus rv = nsEventStatus_eIgnore; if (!mInstance || !mObjectFrame) // if mInstance is null, we shouldn't be here @@ -2436,6 +2489,107 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent) rv = nsEventStatus_eConsumeNoDefault; #endif +#ifdef ANDROID + // this code supports windowless plugins + { + // The plugin needs focus to receive keyboard and touch events + nsIFocusManager* fm = nsFocusManager::GetFocusManager(); + if (fm) { + nsCOMPtr elem = do_QueryInterface(mContent); + fm->SetFocus(elem, 0); + } + } + switch(anEvent.eventStructType) + { + case NS_MOUSE_EVENT: + { + switch (anEvent.message) + { + case NS_MOUSE_CLICK: + case NS_MOUSE_DOUBLECLICK: + // Button up/down events sent instead. + return rv; + } + + // Get reference point relative to plugin origin. + const nsPresContext* presContext = mObjectFrame->PresContext(); + nsPoint appPoint = + nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mObjectFrame) - + mObjectFrame->GetContentRectRelativeToSelf().TopLeft(); + nsIntPoint pluginPoint(presContext->AppUnitsToDevPixels(appPoint.x), + presContext->AppUnitsToDevPixels(appPoint.y)); + + switch (anEvent.message) + { + case NS_MOUSE_MOVE: + { + // are these going to be touch events? + // pluginPoint.x; + // pluginPoint.y; + } + break; + case NS_MOUSE_BUTTON_DOWN: + { + ANPEvent event; + event.inSize = sizeof(ANPEvent); + event.eventType = kMouse_ANPEventType; + event.data.mouse.action = kDown_ANPMouseAction; + event.data.mouse.x = pluginPoint.x; + event.data.mouse.y = pluginPoint.y; + mInstance->HandleEvent(&event, nsnull); + } + break; + case NS_MOUSE_BUTTON_UP: + { + ANPEvent event; + event.inSize = sizeof(ANPEvent); + event.eventType = kMouse_ANPEventType; + event.data.mouse.action = kUp_ANPMouseAction; + event.data.mouse.x = pluginPoint.x; + event.data.mouse.y = pluginPoint.y; + mInstance->HandleEvent(&event, nsnull); + } + break; + } + } + break; + + case NS_KEY_EVENT: + { + const nsKeyEvent& keyEvent = static_cast(anEvent); + LOG("Firing NS_KEY_EVENT %d %d\n", keyEvent.keyCode, keyEvent.charCode); + + int modifiers = 0; + if (keyEvent.isShift) + modifiers |= kShift_ANPKeyModifier; + if (keyEvent.isAlt) + modifiers |= kAlt_ANPKeyModifier; + + ANPEvent event; + event.inSize = sizeof(ANPEvent); + event.eventType = kKey_ANPEventType; + event.data.key.nativeCode = keyEvent.keyCode; + event.data.key.virtualCode = keyEvent.charCode; + event.data.key.modifiers = modifiers; + event.data.key.repeatCount = 0; + event.data.key.unichar = 0; + switch (anEvent.message) + { + case NS_KEY_DOWN: + event.data.key.action = kDown_ANPKeyAction; + mInstance->HandleEvent(&event, nsnull); + break; + + case NS_KEY_UP: + event.data.key.action = kUp_ANPKeyAction; + mInstance->HandleEvent(&event, nsnull); + break; + } + } + } + rv = nsEventStatus_eConsumeNoDefault; +#endif + return rv; } @@ -2541,6 +2695,10 @@ nsPluginInstanceOwner::PrepareToStop(PRBool aDelayedStop) } #endif +#ifdef ANDROID + RemovePluginView(); +#endif + // Unregister scroll position listeners for (nsIFrame* f = mObjectFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) { nsIScrollableFrame* sf = do_QueryFrame(f); @@ -2637,6 +2795,138 @@ void nsPluginInstanceOwner::Paint(const nsRect& aDirtyRect, HPS aHPS) } #endif +#ifdef ANDROID + +class AndroidPaintEventRunnable : public nsRunnable +{ +public: + AndroidPaintEventRunnable(void* aSurface, nsNPAPIPluginInstance* inst, const gfxRect& aFrameRect) + : mSurface(aSurface), mInstance(inst), mFrameRect(aFrameRect) { + } + + ~AndroidPaintEventRunnable() { + } + + NS_IMETHOD Run() + { + LOG("%p - AndroidPaintEventRunnable::Run\n", this); + + if (!mInstance || !mSurface) + return NS_OK; + + // This needs to happen on the gecko main thread. + JNIEnv* env = GetJNIForThread(); + jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell"); + jmethodID method = env->GetStaticMethodID(cls, + "addPluginView", + "(Landroid/view/View;DDDD)V"); + env->CallStaticVoidMethod(cls, + method, + mSurface, + mFrameRect.x, + mFrameRect.y, + mFrameRect.width, + mFrameRect.height); + return NS_OK; + } +private: + void* mSurface; + nsCOMPtr mInstance; + gfxRect mFrameRect; +}; + + +void nsPluginInstanceOwner::Paint(gfxContext* aContext, + const gfxRect& aFrameRect, + const gfxRect& aDirtyRect) +{ + if (!mInstance || !mObjectFrame) + return; + + PRInt32 model; + mInstance->GetDrawingModel(&model); + + if (model == kSurface_ANPDrawingModel) { + + { + ANPEvent event; + event.inSize = sizeof(ANPEvent); + event.eventType = kLifecycle_ANPEventType; + event.data.lifecycle.action = kOnScreen_ANPLifecycleAction; + mInstance->HandleEvent(&event, nsnull); + } + + /* + gfxMatrix currentMatrix = aContext->CurrentMatrix(); + gfxSize scale = currentMatrix.ScaleFactors(PR_TRUE); + printf_stderr("!!!!!!!! scale!!: %f x %f\n", scale.width, scale.height); + */ + + JNIEnv* env = GetJNIForThread(); + jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell"); + jmethodID method = env->GetStaticMethodID(cls, + "addPluginView", + "(Landroid/view/View;DDDD)V"); + env->CallStaticVoidMethod(cls, + method, + mInstance->GetJavaSurface(), + aFrameRect.x, + aFrameRect.y, + aFrameRect.width, + aFrameRect.height); + return; + } + + if (model != kBitmap_ANPDrawingModel) + return; + +#ifdef ANP_BITMAP_DRAWING_MODEL + static nsRefPtr pluginSurface; + + if (pluginSurface == nsnull || + aFrameRect.width != pluginSurface->Width() || + aFrameRect.height != pluginSurface->Height()) { + + pluginSurface = new gfxImageSurface(gfxIntSize(aFrameRect.width, aFrameRect.height), + gfxImageSurface::ImageFormatARGB32); + if (!pluginSurface) + return; + } + + // Clears buffer. I think this is needed. + nsRefPtr ctx = new gfxContext(pluginSurface); + ctx->SetOperator(gfxContext::OPERATOR_CLEAR); + ctx->Paint(); + + ANPEvent event; + event.inSize = sizeof(ANPEvent); + event.eventType = 4; + event.data.draw.model = 1; + + event.data.draw.clip.top = 0; + event.data.draw.clip.left = 0; + event.data.draw.clip.bottom = aFrameRect.width; + event.data.draw.clip.right = aFrameRect.height; + + event.data.draw.data.bitmap.format = kRGBA_8888_ANPBitmapFormat; + event.data.draw.data.bitmap.width = aFrameRect.width; + event.data.draw.data.bitmap.height = aFrameRect.height; + event.data.draw.data.bitmap.baseAddr = pluginSurface->Data(); + event.data.draw.data.bitmap.rowBytes = aFrameRect.width * 4; + + if (!mInstance) + return; + + mInstance->HandleEvent(&event, nsnull); + + aContext->SetOperator(gfxContext::OPERATOR_SOURCE); + aContext->SetSource(pluginSurface, gfxPoint(aFrameRect.x, aFrameRect.y)); + aContext->Clip(aFrameRect); + aContext->Paint(); +#endif +} +#endif + #if defined(MOZ_X11) void nsPluginInstanceOwner::Paint(gfxContext* aContext, const gfxRect& aFrameRect, @@ -3274,9 +3564,28 @@ void nsPluginInstanceOwner::UpdateWindowPositionAndClipRect(PRBool aSetWindow) if (mPluginWindowVisible && mPluginDocumentActiveState) { mPluginWindow->clipRect.right = mPluginWindow->width; mPluginWindow->clipRect.bottom = mPluginWindow->height; +#ifdef ANDROID + if (mInstance) { + ANPEvent event; + event.inSize = sizeof(ANPEvent); + event.eventType = kLifecycle_ANPEventType; + event.data.lifecycle.action = kOnScreen_ANPLifecycleAction; + mInstance->HandleEvent(&event, nsnull); + } +#endif } else { mPluginWindow->clipRect.right = 0; mPluginWindow->clipRect.bottom = 0; +#ifdef ANDROID + if (mInstance) { + ANPEvent event; + event.inSize = sizeof(ANPEvent); + event.eventType = kLifecycle_ANPEventType; + event.data.lifecycle.action = kOffScreen_ANPLifecycleAction; + mInstance->HandleEvent(&event, nsnull); + } + RemovePluginView(); +#endif } if (!aSetWindow) diff --git a/dom/plugins/base/nsPluginInstanceOwner.h b/dom/plugins/base/nsPluginInstanceOwner.h index 682087105d9..f5f23ddb07f 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.h +++ b/dom/plugins/base/nsPluginInstanceOwner.h @@ -144,7 +144,7 @@ public: void Paint(const gfxRect& aDirtyRect, CGContextRef cgContext); void RenderCoreAnimation(CGContextRef aCGContext, int aWidth, int aHeight); void DoCocoaEventDrawRect(const gfxRect& aDrawRect, CGContextRef cgContext); -#elif defined(MOZ_X11) +#elif defined(MOZ_X11) || defined(ANDROID) void Paint(gfxContext* aContext, const gfxRect& aFrameRect, const gfxRect& aDirtyRect); @@ -308,7 +308,10 @@ private: } void FixUpURLS(const nsString &name, nsAString &value); - +#ifdef ANDROID + void RemovePluginView(); +#endif + nsPluginNativeWindow *mPluginWindow; nsRefPtr mInstance; nsObjectFrame *mObjectFrame; // owns nsPluginInstanceOwner diff --git a/dom/plugins/base/nsPluginsDirUnix.cpp b/dom/plugins/base/nsPluginsDirUnix.cpp index ea8170a938b..f761d1d2a15 100644 --- a/dom/plugins/base/nsPluginsDirUnix.cpp +++ b/dom/plugins/base/nsPluginsDirUnix.cpp @@ -247,6 +247,16 @@ PRBool nsPluginsDir::IsPluginFile(nsIFile* file) if (NS_FAILED(file->GetNativeLeafName(filename))) return PR_FALSE; +#ifdef ANDROID + // It appears that if you load + // 'libstagefright_honeycomb.so' on froyo, or + // 'libstagefright_froyo.so' on honeycomb, we will abort. + // Since these are just helper libs, we can ignore. + const char *cFile = filename.get(); + if (strstr(cFile, "libstagefright") != NULL) + return PR_FALSE; +#endif + NS_NAMED_LITERAL_CSTRING(dllSuffix, LOCAL_PLUGIN_DLL_SUFFIX); if (filename.Length() > dllSuffix.Length() && StringEndsWith(filename, dllSuffix)) diff --git a/embedding/android/AndroidManifest.xml.in b/embedding/android/AndroidManifest.xml.in index 3b7eb366196..240f516be1d 100644 --- a/embedding/android/AndroidManifest.xml.in +++ b/embedding/android/AndroidManifest.xml.in @@ -19,6 +19,13 @@ + + + + + + + diff --git a/embedding/android/GeckoApp.java b/embedding/android/GeckoApp.java index d4b1c5c9f98..02765866361 100644 --- a/embedding/android/GeckoApp.java +++ b/embedding/android/GeckoApp.java @@ -45,6 +45,7 @@ import java.util.zip.*; import java.nio.*; import java.nio.channels.FileChannel; import java.util.concurrent.*; +import java.lang.reflect.*; import android.os.*; import android.app.*; @@ -62,6 +63,9 @@ import android.net.*; import android.database.*; import android.provider.*; import android.telephony.*; +import android.content.pm.*; +import android.content.pm.PackageManager.*; +import dalvik.system.*; abstract public class GeckoApp extends Activity @@ -74,7 +78,7 @@ abstract public class GeckoApp public static final String ACTION_DEBUG = "org.mozilla.gecko.DEBUG"; public static final String ACTION_BOOKMARK = "org.mozilla.gecko.BOOKMARK"; - public static FrameLayout mainLayout; + public static AbsoluteLayout mainLayout; public static GeckoSurfaceView surfaceView; public static GeckoApp mAppContext; public static boolean mFullscreen = false; @@ -130,6 +134,151 @@ abstract public class GeckoApp }).show(); } + public static final String PLUGIN_ACTION = "android.webkit.PLUGIN"; + + /** + * A plugin that wish to be loaded in the WebView must provide this permission + * in their AndroidManifest.xml. + */ + public static final String PLUGIN_PERMISSION = "android.webkit.permission.PLUGIN"; + + private static final String LOGTAG = "PluginManager"; + + private static final String PLUGIN_SYSTEM_LIB = "/system/lib/plugins/"; + + private static final String PLUGIN_TYPE = "type"; + private static final String TYPE_NATIVE = "native"; + public ArrayList mPackageInfoCache = new ArrayList(); + + String[] getPluginDirectories() { + + ArrayList directories = new ArrayList(); + PackageManager pm = this.mAppContext.getPackageManager(); + List plugins = pm.queryIntentServices(new Intent(PLUGIN_ACTION), + PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); + + synchronized(mPackageInfoCache) { + + // clear the list of existing packageInfo objects + mPackageInfoCache.clear(); + + + for (ResolveInfo info : plugins) { + + // retrieve the plugin's service information + ServiceInfo serviceInfo = info.serviceInfo; + if (serviceInfo == null) { + Log.w(LOGTAG, "Ignore bad plugin"); + continue; + } + + Log.w(LOGTAG, "Loading plugin: " + serviceInfo.packageName); + + + // retrieve information from the plugin's manifest + PackageInfo pkgInfo; + try { + pkgInfo = pm.getPackageInfo(serviceInfo.packageName, + PackageManager.GET_PERMISSIONS + | PackageManager.GET_SIGNATURES); + } catch (Exception e) { + Log.w(LOGTAG, "Can't find plugin: " + serviceInfo.packageName); + continue; + } + if (pkgInfo == null) { + Log.w(LOGTAG, "Loading plugin: " + serviceInfo.packageName + ". Could not load package information."); + continue; + } + + /* + * find the location of the plugin's shared library. The default + * is to assume the app is either a user installed app or an + * updated system app. In both of these cases the library is + * stored in the app's data directory. + */ + String directory = pkgInfo.applicationInfo.dataDir + "/lib"; + final int appFlags = pkgInfo.applicationInfo.flags; + final int updatedSystemFlags = ApplicationInfo.FLAG_SYSTEM | + ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; + // preloaded system app with no user updates + if ((appFlags & updatedSystemFlags) == ApplicationInfo.FLAG_SYSTEM) { + directory = PLUGIN_SYSTEM_LIB + pkgInfo.packageName; + } + + // check if the plugin has the required permissions + String permissions[] = pkgInfo.requestedPermissions; + if (permissions == null) { + Log.w(LOGTAG, "Loading plugin: " + serviceInfo.packageName + ". Does not have required permission."); + continue; + } + boolean permissionOk = false; + for (String permit : permissions) { + if (PLUGIN_PERMISSION.equals(permit)) { + permissionOk = true; + break; + } + } + if (!permissionOk) { + Log.w(LOGTAG, "Loading plugin: " + serviceInfo.packageName + ". Does not have required permission (2)."); + continue; + } + + // check to ensure the plugin is properly signed + Signature signatures[] = pkgInfo.signatures; + if (signatures == null) { + Log.w(LOGTAG, "Loading plugin: " + serviceInfo.packageName + ". Not signed."); + continue; + } + + // determine the type of plugin from the manifest + if (serviceInfo.metaData == null) { + Log.e(LOGTAG, "The plugin '" + serviceInfo.name + "' has no type defined"); + continue; + } + + String pluginType = serviceInfo.metaData.getString(PLUGIN_TYPE); + if (!TYPE_NATIVE.equals(pluginType)) { + Log.e(LOGTAG, "Unrecognized plugin type: " + pluginType); + continue; + } + + try { + Class cls = getPluginClass(serviceInfo.packageName, serviceInfo.name); + + //TODO implement any requirements of the plugin class here! + boolean classFound = true; + + if (!classFound) { + Log.e(LOGTAG, "The plugin's class' " + serviceInfo.name + "' does not extend the appropriate class."); + continue; + } + + } catch (NameNotFoundException e) { + Log.e(LOGTAG, "Can't find plugin: " + serviceInfo.packageName); + continue; + } catch (ClassNotFoundException e) { + Log.e(LOGTAG, "Can't find plugin's class: " + serviceInfo.name); + continue; + } + + // if all checks have passed then make the plugin available + mPackageInfoCache.add(pkgInfo); + directories.add(directory); + } + } + + return directories.toArray(new String[directories.size()]); + } + + Class getPluginClass(String packageName, String className) + throws NameNotFoundException, ClassNotFoundException { + Context pluginContext = this.mAppContext.createPackageContext(packageName, + Context.CONTEXT_INCLUDE_CODE | + Context.CONTEXT_IGNORE_SECURITY); + ClassLoader pluginCL = pluginContext.getClassLoader(); + return pluginCL.loadClass(className); + } + // Returns true when the intent is going to be handled by gecko launch boolean launch(Intent intent) { @@ -229,13 +378,14 @@ abstract public class GeckoApp if (surfaceView == null) surfaceView = new GeckoSurfaceView(this); else - mainLayout.removeView(surfaceView); + mainLayout.removeAllViews(); - mainLayout = new FrameLayout(this); + mainLayout = new AbsoluteLayout(this); mainLayout.addView(surfaceView, - new FrameLayout.LayoutParams(FrameLayout.LayoutParams.FILL_PARENT, - FrameLayout.LayoutParams.FILL_PARENT)); - + new AbsoluteLayout.LayoutParams(AbsoluteLayout.LayoutParams.MATCH_PARENT, // level 8 + AbsoluteLayout.LayoutParams.MATCH_PARENT, + 0, + 0)); setContentView(mainLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT)); diff --git a/embedding/android/GeckoAppShell.java b/embedding/android/GeckoAppShell.java index e0957678c42..7625e9d0dc1 100644 --- a/embedding/android/GeckoAppShell.java +++ b/embedding/android/GeckoAppShell.java @@ -308,6 +308,19 @@ public class GeckoAppShell if (intHome != null && intProf != null && intProf.exists()) moveDir(intProf, profileDir); } + try { + String[] dirs = GeckoApp.mAppContext.getPluginDirectories(); + StringBuffer pluginSearchPath = new StringBuffer(); + for (int i = 0; i < dirs.length; i++) { + Log.i("GeckoPlugins", "dir: " + dirs[i]); + pluginSearchPath.append(dirs[i]); + pluginSearchPath.append(":"); + } + GeckoAppShell.putenv("MOZ_PLUGIN_PATH="+pluginSearchPath); + } catch (Exception ex) { + Log.i("GeckoPlugins", "exception getting plugin dirs", ex); + } + GeckoAppShell.putenv("HOME=" + homeDir); GeckoAppShell.putenv("GRE_HOME=" + GeckoApp.sGREDir.getPath()); Intent i = geckoApp.getIntent(); @@ -395,6 +408,7 @@ public class GeckoAppShell combinedArgs += " " + args; if (url != null) combinedArgs += " " + url; + // and go GeckoAppShell.nativeRun(combinedArgs); } @@ -1385,4 +1399,187 @@ public class GeckoAppShell return false; } } + public static void addPluginView(final View view, + final double x, final double y, + final double w, final double h) { + + Log.i("GeckoAppShell", "addPluginView:" + view + " @ x:" + x + " y:" + y + " w:" + w + " h:" + h ) ; + + getMainHandler().post(new Runnable() { + public void run() { + AbsoluteLayout.LayoutParams lp = new AbsoluteLayout.LayoutParams((int)w, + (int)h, + (int)x, + (int)y); + + if (GeckoApp.mainLayout.indexOfChild(view) == -1) { + view.setWillNotDraw(false); + if(view instanceof SurfaceView) + ((SurfaceView)view).setZOrderOnTop(true); + + GeckoApp.mainLayout.addView(view, lp); + } + else + { + try { + GeckoApp.mainLayout.updateViewLayout(view, lp); + } catch (IllegalArgumentException e) { + Log.i("updateViewLayout - IllegalArgumentException", "e:" + e); + // it can be the case where we + // get an update before the view + // is actually attached. + } + } + } + }); + } + + public static void removePluginView(final View view) { + Log.i("GeckoAppShell", "remove view:" + view); + getMainHandler().post(new Runnable() { + public void run() { + try { + GeckoApp.mainLayout.removeView(view); + } catch (Exception e) {} + } + }); + } + + public static Class loadPluginClass(String className, String libName) { + Log.i("GeckoAppShell", "in loadPluginClass... attempting to access className, then libName....."); + Log.i("GeckoAppShell", "className: " + className); + Log.i("GeckoAppShell", "libName: " + libName); + + try { + String[] split = libName.split("/"); + String packageName = split[split.length - 3]; + Log.i("GeckoAppShell", "load \"" + className + "\" from \"" + packageName + + "\" for \"" + libName + "\""); + Context pluginContext = + GeckoApp.mAppContext.createPackageContext(packageName, + Context.CONTEXT_INCLUDE_CODE | + Context.CONTEXT_IGNORE_SECURITY); + ClassLoader pluginCL = pluginContext.getClassLoader(); + return pluginCL.loadClass(className); + } catch (java.lang.ClassNotFoundException cnfe) { + Log.i("GeckoAppShell", "class not found", cnfe); + } catch (android.content.pm.PackageManager.NameNotFoundException nnfe) { + Log.i("GeckoAppShell", "package not found", nnfe); + } + Log.e("GeckoAppShell", "couldn't find class"); + return null; + } + + static HashMap sSufaceMap = new HashMap(); + + public static void lockSurfaceANP() + { + Log.i("GeckoAppShell", "other lockSurfaceANP"); + } + + public static org.mozilla.gecko.SurfaceLockInfo lockSurfaceANP(android.view.SurfaceView sview, int top, int left, int bottom, int right) + { + Log.i("GeckoAppShell", "real lockSurfaceANP " + sview + ", " + top + ", " + left + ", " + bottom + ", " + right); + if (sview == null) + return null; + + int format = -1; + try { + Field privateFormatField = SurfaceView.class.getDeclaredField("mFormat"); + privateFormatField.setAccessible(true); + format = privateFormatField.getInt(sview); + } catch (Exception e) { + Log.i("GeckoAppShell", "mFormat is not a field of sview: ", e); + } + + int n = 0; + if (format == PixelFormat.RGB_565) + n = 2; + else if (format == PixelFormat.RGBA_8888) + n = 4; + + if (n == 0) + return null; + + SurfaceLockInfo info = sSufaceMap.get(sview); + if (info == null) { + info = new SurfaceLockInfo(); + sSufaceMap.put(sview, info); + } + + Rect r = new Rect(left, top, right, bottom); + + info.canvas = sview.getHolder().lockCanvas(r); + int bufSizeRequired = info.canvas.getWidth() * info.canvas.getHeight() * n; + Log.i("GeckoAppShell", "lockSurfaceANP - bufSizeRequired: " + n + " " + info.canvas.getHeight() + " " + info.canvas.getWidth()); + + if (info.width != info.canvas.getWidth() || info.height != info.canvas.getHeight() || info.buffer == null || info.buffer.capacity() < bufSizeRequired) { + info.width = info.canvas.getWidth(); + info.height = info.canvas.getHeight(); + + // XXX Bitmaps instead of ByteBuffer + info.buffer = ByteBuffer.allocateDirect(bufSizeRequired); //leak + Log.i("GeckoAppShell", "!!!!!!!!!!! lockSurfaceANP - Allocating buffer! " + bufSizeRequired); + + } + + info.canvas.drawColor(Color.WHITE, PorterDuff.Mode.CLEAR); + + info.format = format; + info.dirtyTop = top; + info.dirtyBottom = bottom; + info.dirtyLeft = left; + info.dirtyRight = right; + + return info; + } + + public static void unlockSurfaceANP(SurfaceView sview) { + SurfaceLockInfo info = sSufaceMap.get(sview); + + int n = 0; + Bitmap.Config config; + if (info.format == PixelFormat.RGB_565) { + n = 2; + config = Bitmap.Config.RGB_565; + } else { + n = 4; + config = Bitmap.Config.ARGB_8888; + } + + Log.i("GeckoAppShell", "unlockSurfaceANP: " + (info.width * info.height * n)); + + Bitmap bm = Bitmap.createBitmap(info.width, info.height, config); + bm.copyPixelsFromBuffer(info.buffer); + info.canvas.drawBitmap(bm, 0, 0, null); + sview.getHolder().unlockCanvasAndPost(info.canvas); + } + + public static Class getSurfaceLockInfoClass() { + Log.i("GeckoAppShell", "class name: " + SurfaceLockInfo.class.getName()); + return SurfaceLockInfo.class; + } + + public static Method getSurfaceLockMethod() { + Method[] m = GeckoAppShell.class.getMethods(); + for (int i = 0; i < m.length; i++) { + if (m[i].getName().equals("lockSurfaceANP")) + return m[i]; + } + return null; + } + + static native void executeNextRunnable(); + + static class GeckoRunnableCallback implements Runnable { + public void run() { + Log.i("GeckoShell", "run GeckoRunnableCallback"); + GeckoAppShell.executeNextRunnable(); + } + } + + public static void postToJavaThread(boolean mainThread) { + Log.i("GeckoShell", "post to " + (mainThread ? "main " : "") + "java thread"); + getMainHandler().post(new GeckoRunnableCallback()); + } } diff --git a/embedding/android/Makefile.in b/embedding/android/Makefile.in index ebda01b067b..c6a4101e37f 100644 --- a/embedding/android/Makefile.in +++ b/embedding/android/Makefile.in @@ -54,6 +54,7 @@ JAVAFILES = \ GeckoInputConnection.java \ GeckoPhoneStateListener.java \ AlertNotification.java \ + SurfaceLockInfo.java \ $(NULL) PROCESSEDJAVAFILES = \ diff --git a/embedding/android/SurfaceLockInfo.java b/embedding/android/SurfaceLockInfo.java new file mode 100644 index 00000000000..4dcb7dc2b6a --- /dev/null +++ b/embedding/android/SurfaceLockInfo.java @@ -0,0 +1,18 @@ +package org.mozilla.gecko; + +import android.graphics.Canvas; +import java.nio.Buffer; + +public class SurfaceLockInfo { + public int dirtyTop; + public int dirtyLeft; + public int dirtyRight; + public int dirtyBottom; + + public int bpr; + public int format; + public int width; + public int height; + public Buffer buffer; + public Canvas canvas; +} diff --git a/layout/build/Makefile.in b/layout/build/Makefile.in index 03fc6bfb757..4da911a5725 100644 --- a/layout/build/Makefile.in +++ b/layout/build/Makefile.in @@ -135,6 +135,7 @@ LOCAL_INCLUDES += \ else ifneq (,$(filter android,$(MOZ_WIDGET_TOOLKIT))) SHARED_LIBRARY_LIBS += \ $(DEPTH)/dom/system/android/$(LIB_PREFIX)domsystemandroid_s.$(LIB_SUFFIX) \ + $(DEPTH)/dom/plugins/base/android/$(LIB_PREFIX)gkpluginandroid_s.$(LIB_SUFFIX) \ $(NULL) LOCAL_INCLUDES += \ -I$(topsrcdir)/dom/system/android \ diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index ad1503ae984..09e3b6f654c 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -1683,6 +1683,22 @@ nsObjectFrame::PaintPlugin(nsDisplayListBuilder* aBuilder, nsRenderingContext& aRenderingContext, const nsRect& aDirtyRect, const nsRect& aPluginRect) { +#if defined(ANDROID) + if (mInstanceOwner) { + NPWindow *window; + mInstanceOwner->GetWindow(window); + + gfxRect frameGfxRect = + PresContext()->AppUnitsToGfxUnits(aPluginRect); + gfxRect dirtyGfxRect = + PresContext()->AppUnitsToGfxUnits(aDirtyRect); + gfxContext* ctx = aRenderingContext.ThebesContext(); + + mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect); + return; + } +#endif + // Screen painting code #if defined(XP_MACOSX) // delegate all painting to the plugin instance. diff --git a/other-licenses/android/APKOpen.cpp b/other-licenses/android/APKOpen.cpp index a917703a751..d70efc30633 100644 --- a/other-licenses/android/APKOpen.cpp +++ b/other-licenses/android/APKOpen.cpp @@ -241,6 +241,7 @@ SHELL_WRAPPER3(callObserver, jstring, jstring, jstring) SHELL_WRAPPER1(removeObserver, jstring) SHELL_WRAPPER2(onChangeNetworkLinkStatus, jstring, jstring) SHELL_WRAPPER1(reportJavaCrash, jstring) +SHELL_WRAPPER0(executeNextRunnable) static void * xul_handle = NULL; static time_t apk_mtime = 0; @@ -667,6 +668,7 @@ loadLibs(const char *apkName) GETFUNC(removeObserver); GETFUNC(onChangeNetworkLinkStatus); GETFUNC(reportJavaCrash); + GETFUNC(executeNextRunnable); #undef GETFUNC gettimeofday(&t1, 0); struct rusage usage2; diff --git a/widget/src/android/AndroidBridge.cpp b/widget/src/android/AndroidBridge.cpp index 972bd4bb0f0..b1b6a638a1b 100644 --- a/widget/src/android/AndroidBridge.cpp +++ b/widget/src/android/AndroidBridge.cpp @@ -149,6 +149,7 @@ AndroidBridge::Init(JNIEnv *jEnv, jGetIconForExtension = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getIconForExtension", "(Ljava/lang/String;I)[B"); jCreateShortcut = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "createShortcut", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); jGetShowPasswordSetting = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getShowPasswordSetting", "()Z"); + jPostToJavaThread = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "postToJavaThread", "(Z)V"); jEGLContextClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGLContext")); jEGL10Class = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGL10")); @@ -169,8 +170,14 @@ AndroidBridge::Init(JNIEnv *jEnv, JNIEnv * AndroidBridge::AttachThread(PRBool asDaemon) { + // If we already have a env, return it + JNIEnv *jEnv = NULL; + mJavaVM->GetEnv((void**) &jEnv, JNI_VERSION_1_2); + if (jEnv) + return jEnv; + ALOG_BRIDGE("AndroidBridge::AttachThread"); - JNIEnv *jEnv = (JNIEnv*) PR_GetThreadPrivate(sJavaEnvThreadIndex); + jEnv = (JNIEnv*) PR_GetThreadPrivate(sJavaEnvThreadIndex); if (jEnv) return jEnv; @@ -195,6 +202,8 @@ AndroidBridge::AttachThread(PRBool asDaemon) PR_SetThreadPrivate(sJavaEnvThreadIndex, jEnv); + PR_NewThreadPrivateIndex(&sJavaEnvThreadIndex, JavaThreadDetachFunc); + return jEnv; } @@ -926,6 +935,45 @@ AndroidBridge::CreateShortcut(const nsAString& aTitle, const nsAString& aURI, co mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jCreateShortcut, jstrTitle, jstrURI, jstrIconData, jstrIntent); } +void +AndroidBridge::PostToJavaThread(nsIRunnable* aRunnable, PRBool aMainThread) +{ + __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "%s", __PRETTY_FUNCTION__); + JNIEnv* env = AndroidBridge::AttachThread(false); + if (!env) { + __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "no jni env in %s!!", __PRETTY_FUNCTION__); + return; + } + mRunnableQueue.AppendObject(aRunnable); + env->CallStaticVoidMethod(mGeckoAppShellClass, jPostToJavaThread, (jboolean)aMainThread); + + jthrowable ex = env->ExceptionOccurred(); + if (ex) { + env->ExceptionDescribe(); + env->ExceptionClear(); + } + __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "leaving %s", __PRETTY_FUNCTION__); +} + +void +AndroidBridge::ExecuteNextRunnable() +{ + __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "%s", __PRETTY_FUNCTION__); + + JNIEnv* env = AndroidBridge::AttachThread(false); + if (!env) { + __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "no jni env in %s!!", __PRETTY_FUNCTION__); + return; + } + + if (mRunnableQueue.Count() > 0) { + nsIRunnable* r = mRunnableQueue[0]; + __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "going to run %p", r); + r->Run(); + mRunnableQueue.RemoveObjectAt(0); + } + __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "leaving %s", __PRETTY_FUNCTION__); +} bool AndroidBridge::HasNativeBitmapAccess() { diff --git a/widget/src/android/AndroidBridge.h b/widget/src/android/AndroidBridge.h index cfb79eae1d9..4de9750482c 100644 --- a/widget/src/android/AndroidBridge.h +++ b/widget/src/android/AndroidBridge.h @@ -42,6 +42,7 @@ #include #include "nsCOMPtr.h" +#include "nsCOMArray.h" #include "nsIRunnable.h" #include "nsIObserver.h" @@ -262,6 +263,10 @@ public: void UnlockBitmap(jobject bitmap); + void PostToJavaThread(nsIRunnable* aRunnable, PRBool aMainThread = PR_FALSE); + + void ExecuteNextRunnable(); + protected: static AndroidBridge *sBridge; @@ -286,6 +291,8 @@ protected: bool mOpenedBitmapLibrary; bool mHasNativeBitmapAccess; + nsCOMArray mRunnableQueue; + // other things jmethodID jNotifyIME; jmethodID jNotifyIMEEnabled; @@ -325,6 +332,7 @@ protected: jmethodID jGetIconForExtension; jmethodID jCreateShortcut; jmethodID jGetShowPasswordSetting; + jmethodID jPostToJavaThread; // stuff we need for CallEglCreateWindowSurface jclass jEGLSurfaceImplClass; diff --git a/widget/src/android/AndroidJNI.cpp b/widget/src/android/AndroidJNI.cpp index 6aadc8e85e9..4bce698eed4 100644 --- a/widget/src/android/AndroidJNI.cpp +++ b/widget/src/android/AndroidJNI.cpp @@ -72,6 +72,7 @@ extern "C" { NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_removeObserver(JNIEnv *jenv, jclass, jstring jObserverKey); NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus(JNIEnv *, jclass, jstring status, jstring type); NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_reportJavaCrash(JNIEnv *, jclass, jstring stack); + NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_executeNextRunnable(JNIEnv *, jclass); } @@ -179,3 +180,15 @@ Java_org_mozilla_gecko_GeckoAppShell_reportJavaCrash(JNIEnv *jenv, jclass, jstri #endif abort(); } + +NS_EXPORT void JNICALL +Java_org_mozilla_gecko_GeckoAppShell_executeNextRunnable(JNIEnv *, 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(); + __android_log_print(ANDROID_LOG_INFO, "GeckoJNI", "leaving %s", __PRETTY_FUNCTION__); +} From 9c015b9b38a466c3e9ad8a9d90d7a983a6a8f900 Mon Sep 17 00:00:00 2001 From: "Robert O'Callahan ext:(.)" Date: Sat, 17 Sep 2011 09:29:51 +0100 Subject: [PATCH 2/5] Bug 647687 - Fix filter SourceImage bounds. r=longsonr --- layout/reftests/svg/filter-bounds-01.svg | 24 ++++++++++++++++++++ layout/reftests/svg/filter-bounds-02.svg | 25 +++++++++++++++++++++ layout/reftests/svg/reftest.list | 2 ++ layout/svg/base/src/nsSVGFilterFrame.cpp | 10 ++++++++- layout/svg/base/src/nsSVGFilterInstance.cpp | 1 + layout/svg/base/src/nsSVGFilterInstance.h | 4 ++++ 6 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 layout/reftests/svg/filter-bounds-01.svg create mode 100644 layout/reftests/svg/filter-bounds-02.svg diff --git a/layout/reftests/svg/filter-bounds-01.svg b/layout/reftests/svg/filter-bounds-01.svg new file mode 100644 index 00000000000..17bfeb60c1e --- /dev/null +++ b/layout/reftests/svg/filter-bounds-01.svg @@ -0,0 +1,24 @@ + + + + Testcase for checking that filter bounds include stroke width + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/filter-bounds-02.svg b/layout/reftests/svg/filter-bounds-02.svg new file mode 100644 index 00000000000..d9c0d474c9c --- /dev/null +++ b/layout/reftests/svg/filter-bounds-02.svg @@ -0,0 +1,25 @@ + + + + Testcase for checking that filter bounds include stroke width + + + + + + + + + + + + + + + + diff --git a/layout/reftests/svg/reftest.list b/layout/reftests/svg/reftest.list index 2a424a1e858..e7c4c3b46c9 100644 --- a/layout/reftests/svg/reftest.list +++ b/layout/reftests/svg/reftest.list @@ -111,6 +111,8 @@ random == dynamic-use-nested-01.svg dynamic-use-nested-01-ref.svg # bug 467498 == filter-basic-01.svg pass.svg == filter-basic-02.svg pass.svg == filter-basic-03.svg pass.svg +== filter-bounds-01.svg pass.svg +== filter-bounds-02.svg pass.svg == filter-foreignObject-01.svg pass.svg == filter-invalidation-01.svg pass.svg == filter-scaled-01.svg pass.svg diff --git a/layout/svg/base/src/nsSVGFilterFrame.cpp b/layout/svg/base/src/nsSVGFilterFrame.cpp index 214b3bd80e5..4d0efabff20 100644 --- a/layout/svg/base/src/nsSVGFilterFrame.cpp +++ b/layout/svg/base/src/nsSVGFilterFrame.cpp @@ -206,11 +206,19 @@ nsAutoFilterInstance::nsAutoFilterInstance(nsIFrame *aTarget, MapDeviceRectToFilterSpace(deviceToFilterSpace, filterRes, aDirtyOutputRect); nsIntRect dirtyInputRect = MapDeviceRectToFilterSpace(deviceToFilterSpace, filterRes, aDirtyInputRect); + nsIntRect targetBoundsDeviceSpace; + nsISVGChildFrame* svgTarget = do_QueryFrame(aTarget); + if (svgTarget) { + targetBoundsDeviceSpace.UnionRect(targetBoundsDeviceSpace, + svgTarget->GetCoveredRegion().ToOutsidePixels(aTarget->PresContext()->AppUnitsPerDevPixel())); + } + nsIntRect targetBoundsFilterSpace = + MapDeviceRectToFilterSpace(deviceToFilterSpace, filterRes, &targetBoundsDeviceSpace); // Setup instance data mInstance = new nsSVGFilterInstance(aTarget, aPaint, filter, bbox, filterRegion, nsIntSize(filterRes.width, filterRes.height), - filterToDeviceSpace, + filterToDeviceSpace, targetBoundsFilterSpace, dirtyOutputRect, dirtyInputRect, primitiveUnits); } diff --git a/layout/svg/base/src/nsSVGFilterInstance.cpp b/layout/svg/base/src/nsSVGFilterInstance.cpp index 84477da69ba..c91af0b5a4f 100644 --- a/layout/svg/base/src/nsSVGFilterInstance.cpp +++ b/layout/svg/base/src/nsSVGFilterInstance.cpp @@ -189,6 +189,7 @@ nsSVGFilterInstance::BuildSources() // Detect possible float->int overflow if (!gfxUtils::GfxRectToIntRect(sourceBounds, &sourceBoundsInt)) return NS_ERROR_FAILURE; + sourceBoundsInt.UnionRect(sourceBoundsInt, mTargetBounds); mSourceColorAlpha.mResultBoundingBox = sourceBoundsInt; mSourceAlpha.mResultBoundingBox = sourceBoundsInt; diff --git a/layout/svg/base/src/nsSVGFilterInstance.h b/layout/svg/base/src/nsSVGFilterInstance.h index b45708f6305..2d80d837672 100644 --- a/layout/svg/base/src/nsSVGFilterInstance.h +++ b/layout/svg/base/src/nsSVGFilterInstance.h @@ -70,6 +70,7 @@ public: const gfxRect& aFilterRect, const nsIntSize& aFilterSpaceSize, const gfxMatrix &aFilterSpaceToDeviceSpaceTransform, + const nsIntRect& aTargetBounds, const nsIntRect& aDirtyOutputRect, const nsIntRect& aDirtyInputRect, PRUint16 aPrimitiveUnits) : @@ -80,6 +81,7 @@ public: mFilterSpaceToDeviceSpaceTransform(aFilterSpaceToDeviceSpaceTransform), mFilterRect(aFilterRect), mFilterSpaceSize(aFilterSpaceSize), + mTargetBounds(aTargetBounds), mDirtyOutputRect(aDirtyOutputRect), mDirtyInputRect(aDirtyInputRect), mSurfaceRect(nsIntPoint(0, 0), aFilterSpaceSize), @@ -209,6 +211,8 @@ private: gfxMatrix mFilterSpaceToDeviceSpaceTransform; gfxRect mFilterRect; nsIntSize mFilterSpaceSize; + // Filter-space bounds of the target image (SourceAlpha/SourceGraphic) + nsIntRect mTargetBounds; nsIntRect mDirtyOutputRect; nsIntRect mDirtyInputRect; nsIntRect mSurfaceRect; From 2b98c400664d254ae707c18ce7fc905b119e1e1d Mon Sep 17 00:00:00 2001 From: Ed Morley Date: Sat, 17 Sep 2011 10:22:09 +0100 Subject: [PATCH 3/5] Bug 685084 - Remove unused variable 'lm' in mozilla::widget::PuppetWidget::DispatchPaintEvent(); r=roc --- widget/src/xpwidgets/PuppetWidget.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/widget/src/xpwidgets/PuppetWidget.cpp b/widget/src/xpwidgets/PuppetWidget.cpp index dc3f3346471..b9282c8bc0c 100644 --- a/widget/src/xpwidgets/PuppetWidget.cpp +++ b/widget/src/xpwidgets/PuppetWidget.cpp @@ -558,7 +558,6 @@ PuppetWidget::DispatchPaintEvent() nsCAutoString("PuppetWidget"), nsnull); #endif - LayerManager* lm = GetLayerManager(); if (LayerManager::LAYERS_D3D10 == mLayerManager->GetBackendType()) { DispatchEvent(&event, status); } else { From 41c3d0b2a76c274a192b53c8b564919bcf249500 Mon Sep 17 00:00:00 2001 From: Nick Hurley Date: Sat, 17 Sep 2011 10:22:09 +0100 Subject: [PATCH 4/5] Bug 686948 - Add telemetry for cache hit/miss with/without revalidation. r=mcmanus --- netwerk/protocol/http/nsHttpChannel.cpp | 21 +++++++++++++++++++ netwerk/protocol/http/nsHttpChannel.h | 9 ++++++++ .../telemetry/TelemetryHistograms.h | 3 +++ 3 files changed, 33 insertions(+) diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index bf0c6591191..d0594dd741d 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -66,6 +66,7 @@ #include "nsChannelClassifier.h" #include "nsIRedirectResultListener.h" #include "mozilla/TimeStamp.h" +#include "mozilla/Telemetry.h" // True if the local cache should be bypassed when processing a request. #define BYPASS_LOCAL_CACHE(loadFlags) \ @@ -128,6 +129,7 @@ nsHttpChannel::nsHttpChannel() , mFallingBack(PR_FALSE) , mWaitingForRedirectCallback(PR_FALSE) , mRequestTimeInitialized(PR_FALSE) + , mDidReval(false) { LOG(("Creating nsHttpChannel [this=%p]\n", this)); mChannelCreationTime = PR_Now(); @@ -267,6 +269,8 @@ nsHttpChannel::Connect(PRBool firstTime) if (NS_FAILED(rv) && event) { event->Revoke(); } + mozilla::Telemetry::Accumulate( + mozilla::Telemetry::HTTP_CACHE_DISPOSITION, kCacheHit); return rv; } else if (mLoadFlags & LOAD_ONLY_FROM_CACHE) { @@ -974,6 +978,8 @@ nsHttpChannel::ProcessResponse() LOG((" continuation state has been reset")); } + bool successfulReval = false; + // handle different server response categories. Note that we handle // caching or not caching of error pages in // nsHttpResponseHead::MustValidate; if you change this switch, update that @@ -1025,6 +1031,9 @@ nsHttpChannel::ProcessResponse() LOG(("ProcessNotModified failed [rv=%x]\n", rv)); rv = ProcessNormal(); } + else { + successfulReval = true; + } break; case 401: case 407: @@ -1060,6 +1069,17 @@ nsHttpChannel::ProcessResponse() break; } + if (!mDidReval) + mozilla::Telemetry::Accumulate( + mozilla::Telemetry::HTTP_CACHE_DISPOSITION, kCacheMissed); + else if (successfulReval) + mozilla::Telemetry::Accumulate( + mozilla::Telemetry::HTTP_CACHE_DISPOSITION, kCacheHitViaReval); + else + mozilla::Telemetry::Accumulate( + mozilla::Telemetry::HTTP_CACHE_DISPOSITION, + kCacheMissedViaReval); + return rv; } @@ -2666,6 +2686,7 @@ nsHttpChannel::CheckCache() if (val) mRequestHead.SetHeader(nsHttp::If_None_Match, nsDependentCString(val)); + mDidReval = true; } } diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h index a64ec07f383..6e0f3600807 100644 --- a/netwerk/protocol/http/nsHttpChannel.h +++ b/netwerk/protocol/http/nsHttpChannel.h @@ -366,6 +366,15 @@ private: protected: virtual void DoNotifyListenerCleanup(); + +private: // cache telemetry + enum { + kCacheHit = 1, + kCacheHitViaReval = 2, + kCacheMissedViaReval = 3, + kCacheMissed = 4 + }; + bool mDidReval; }; #endif // nsHttpChannel_h__ diff --git a/toolkit/components/telemetry/TelemetryHistograms.h b/toolkit/components/telemetry/TelemetryHistograms.h index a16c373cbf7..0f4cdf1cecf 100644 --- a/toolkit/components/telemetry/TelemetryHistograms.h +++ b/toolkit/components/telemetry/TelemetryHistograms.h @@ -132,6 +132,9 @@ HTTP_HISTOGRAMS(SUB, "subitem: ") #undef _HTTP_HIST #undef HTTP_HISTOGRAMS + +HISTOGRAM(HTTP_CACHE_DISPOSITION, 1, 5, 5, LINEAR, "HTTP Cache Hit, Reval, Failed-Reval, Miss") + HISTOGRAM(FIND_PLUGINS, 1, 3000, 10, EXPONENTIAL, "Time spent scanning filesystem for plugins (ms)") HISTOGRAM(CHECK_JAVA_ENABLED, 1, 3000, 10, EXPONENTIAL, "Time spent checking if Java is enabled (ms)") From 8d8b113f0bf2c94ef85ed70a693ad08925ff868d Mon Sep 17 00:00:00 2001 From: Jim Mathies Date: Sun, 18 Sep 2011 00:58:37 +0100 Subject: [PATCH 5/5] Bug 654891 - warning C4509: nonstandard extension used: 'PluginWindowEvent::Run' uses SEH and 'inst' has destructor; r=bsmedberg --- dom/plugins/base/nsPluginNativeWindowWin.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/dom/plugins/base/nsPluginNativeWindowWin.cpp b/dom/plugins/base/nsPluginNativeWindowWin.cpp index 47cad546d57..ef6df824bd0 100644 --- a/dom/plugins/base/nsPluginNativeWindowWin.cpp +++ b/dom/plugins/base/nsPluginNativeWindowWin.cpp @@ -184,8 +184,7 @@ static PRBool ProcessFlashMessageDelayed(nsPluginNativeWindowWin * aWin, nsNPAPI if (msg == sWM_FLASHBOUNCEMSG) { // See PluginWindowEvent::Run() below. NS_ASSERTION((sWM_FLASHBOUNCEMSG != 0), "RegisterWindowMessage failed in flash plugin WM_USER message handling!"); - NS_TRY_SAFE_CALL_VOID(::CallWindowProc((WNDPROC)aWin->GetWindowProc(), hWnd, WM_USER_FLASH, wParam, lParam), - aInst); + ::CallWindowProc((WNDPROC)aWin->GetWindowProc(), hWnd, WM_USER_FLASH, wParam, lParam); return TRUE; } @@ -577,12 +576,11 @@ NS_IMETHODIMP PluginWindowEvent::Run() else { // Currently not used, but added so that processing events here // is more generic. - NS_TRY_SAFE_CALL_VOID(::CallWindowProc(win->GetWindowProc(), - hWnd, - GetMsg(), - GetWParam(), - GetLParam()), - inst); + ::CallWindowProc(win->GetWindowProc(), + hWnd, + GetMsg(), + GetWParam(), + GetLParam()); } Clear();