summaryrefslogtreecommitdiffstats
path: root/WebKit/android/plugins
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
commit1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353 (patch)
tree4457a7306ea5acb43fe05bfe0973b1f7faf97ba2 /WebKit/android/plugins
parent9364f22aed35e1a1e9d07c121510f80be3ab0502 (diff)
downloadexternal_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.zip
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.gz
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.bz2
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'WebKit/android/plugins')
-rw-r--r--WebKit/android/plugins/ANPCanvasInterface.cpp150
-rw-r--r--WebKit/android/plugins/ANPKeyCodes.h116
-rw-r--r--WebKit/android/plugins/ANPLogInterface.cpp52
-rw-r--r--WebKit/android/plugins/ANPPaintInterface.cpp190
-rw-r--r--WebKit/android/plugins/ANPSoundInterface.cpp140
-rw-r--r--WebKit/android/plugins/ANPTypefaceInterface.cpp65
-rw-r--r--WebKit/android/plugins/ANPWindowInterface.cpp53
-rw-r--r--WebKit/android/plugins/PluginDataAndroid.cpp72
-rw-r--r--WebKit/android/plugins/PluginDebugAndroid.h38
-rw-r--r--WebKit/android/plugins/PluginPackageAndroid.cpp580
-rw-r--r--WebKit/android/plugins/PluginTimer.cpp111
-rw-r--r--WebKit/android/plugins/PluginTimer.h77
-rw-r--r--WebKit/android/plugins/PluginViewAndroid.cpp568
-rw-r--r--WebKit/android/plugins/PluginViewBridgeAndroid.cpp29
-rw-r--r--WebKit/android/plugins/PluginViewBridgeAndroid.h47
-rw-r--r--WebKit/android/plugins/PluginWidgetAndroid.cpp137
-rw-r--r--WebKit/android/plugins/PluginWidgetAndroid.h85
-rw-r--r--WebKit/android/plugins/SkANP.cpp89
-rw-r--r--WebKit/android/plugins/SkANP.h66
-rw-r--r--WebKit/android/plugins/android_npapi.h514
-rw-r--r--WebKit/android/plugins/sample/Android.mk41
-rw-r--r--WebKit/android/plugins/sample/PluginObject.cpp178
-rw-r--r--WebKit/android/plugins/sample/PluginObject.h70
-rw-r--r--WebKit/android/plugins/sample/main.cpp425
-rw-r--r--WebKit/android/plugins/sample/main.h21
-rw-r--r--WebKit/android/plugins/sample/pluginGraphics.cpp169
-rw-r--r--WebKit/android/plugins/sample/pluginGraphics.h31
27 files changed, 4114 insertions, 0 deletions
diff --git a/WebKit/android/plugins/ANPCanvasInterface.cpp b/WebKit/android/plugins/ANPCanvasInterface.cpp
new file mode 100644
index 0000000..fe7981a
--- /dev/null
+++ b/WebKit/android/plugins/ANPCanvasInterface.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// must include config.h first for webkit to fiddle with new/delete
+#include "config.h"
+#include "SkANP.h"
+
+static ANPCanvas* anp_newCanvas(const ANPBitmap* bitmap) {
+ SkBitmap bm;
+ return new ANPCanvas(*SkANP::SetBitmap(&bm, *bitmap));
+}
+
+static void anp_deleteCanvas(ANPCanvas* canvas) {
+ delete canvas;
+}
+
+static void anp_save(ANPCanvas* canvas) {
+ canvas->skcanvas->save();
+}
+
+static void anp_restore(ANPCanvas* canvas) {
+ canvas->skcanvas->restore();
+}
+
+static void anp_translate(ANPCanvas* canvas, float tx, float ty) {
+ canvas->skcanvas->translate(SkFloatToScalar(tx), SkFloatToScalar(ty));
+}
+
+static void anp_scale(ANPCanvas* canvas, float sx, float sy) {
+ canvas->skcanvas->scale(SkFloatToScalar(sx), SkFloatToScalar(sy));
+}
+
+static void anp_rotate(ANPCanvas* canvas, float degrees) {
+ canvas->skcanvas->rotate(SkFloatToScalar(degrees));
+}
+
+static void anp_skew(ANPCanvas* canvas, float kx, float ky) {
+ canvas->skcanvas->skew(SkFloatToScalar(kx), SkFloatToScalar(ky));
+}
+
+static void anp_clipRect(ANPCanvas* canvas, const ANPRectF* rect) {
+ SkRect r;
+ canvas->skcanvas->clipRect(*SkANP::SetRect(&r, *rect));
+}
+
+static void anp_clipPath(ANPCanvas* canvas, const ANPPath* path) {
+ canvas->skcanvas->clipPath(*path);
+}
+
+static void anp_drawColor(ANPCanvas* canvas, ANPColor color) {
+ canvas->skcanvas->drawColor(color);
+}
+
+static void anp_drawPaint(ANPCanvas* canvas, const ANPPaint* paint) {
+ canvas->skcanvas->drawPaint(*paint);
+}
+
+static void anp_drawRect(ANPCanvas* canvas, const ANPRectF* rect,
+ const ANPPaint* paint) {
+ SkRect r;
+ canvas->skcanvas->drawRect(*SkANP::SetRect(&r, *rect), *paint);
+}
+
+static void anp_drawOval(ANPCanvas* canvas, const ANPRectF* rect,
+ const ANPPaint* paint) {
+ SkRect r;
+ canvas->skcanvas->drawOval(*SkANP::SetRect(&r, *rect), *paint);
+}
+
+static void anp_drawPath(ANPCanvas* canvas, const ANPPath* path,
+ const ANPPaint* paint) {
+ canvas->skcanvas->drawPath(*path, *paint);
+}
+
+static void anp_drawText(ANPCanvas* canvas, const void* text, uint32_t length,
+ float x, float y, const ANPPaint* paint) {
+ canvas->skcanvas->drawText(text, length,
+ SkFloatToScalar(x), SkFloatToScalar(y),
+ *paint);
+}
+
+static void anp_drawPosText(ANPCanvas* canvas, const void* text,
+ uint32_t byteLength, const float xy[], const ANPPaint* paint) {
+ canvas->skcanvas->drawPosText(text, byteLength,
+ reinterpret_cast<const SkPoint*>(xy), *paint);
+}
+
+static void anp_drawBitmap(ANPCanvas* canvas, const ANPBitmap* bitmap,
+ float x, float y, const ANPPaint* paint) {
+ SkBitmap bm;
+ canvas->skcanvas->drawBitmap(*SkANP::SetBitmap(&bm, *bitmap),
+ SkFloatToScalar(x), SkFloatToScalar(y),
+ paint);
+}
+
+static void anp_drawBitmapRect(ANPCanvas* canvas, const ANPBitmap* bitmap,
+ const ANPRectI* src, const ANPRectF* dst,
+ const ANPPaint* paint) {
+ SkBitmap bm;
+ SkRect dstR;
+ SkIRect srcR, *srcPtr = NULL;
+
+ if (src) {
+ srcPtr = SkANP::SetRect(&srcR, *src);
+ }
+ canvas->skcanvas->drawBitmapRect(*SkANP::SetBitmap(&bm, *bitmap), srcPtr,
+ *SkANP::SetRect(&dstR, *dst), paint);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define ASSIGN(obj, name) (obj)->name = anp_##name
+
+void ANPCanvasInterfaceV0_Init(ANPInterface* value) {
+ ANPCanvasInterfaceV0* i = reinterpret_cast<ANPCanvasInterfaceV0*>(value);
+
+ 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, clipRect);
+ ASSIGN(i, clipPath);
+ ASSIGN(i, drawColor);
+ ASSIGN(i, drawPaint);
+ ASSIGN(i, drawRect);
+ ASSIGN(i, drawOval);
+ ASSIGN(i, drawPath);
+ ASSIGN(i, drawText);
+ ASSIGN(i, drawPosText);
+ ASSIGN(i, drawBitmap);
+ ASSIGN(i, drawBitmapRect);
+}
+
diff --git a/WebKit/android/plugins/ANPKeyCodes.h b/WebKit/android/plugins/ANPKeyCodes.h
new file mode 100644
index 0000000..0e58ef6
--- /dev/null
+++ b/WebKit/android/plugins/ANPKeyCodes.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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 include/ui/KeycodeLabels.h, which contains more than
+ I want to publish to plugin authors.
+*/
+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
+};
+
+#endif
+
diff --git a/WebKit/android/plugins/ANPLogInterface.cpp b/WebKit/android/plugins/ANPLogInterface.cpp
new file mode 100644
index 0000000..7604b5c
--- /dev/null
+++ b/WebKit/android/plugins/ANPLogInterface.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "plugin"
+
+#include "utils/Log.h"
+#include "android_npapi.h"
+#include <stdarg.h>
+
+static void anp_log(NPP inst, ANPLogType logType, const char format[], ...) {
+ va_list args;
+ va_start(args, format);
+
+ android_LogPriority priority;
+ switch (logType) {
+ case kError_ANPLogType:
+ priority = ANDROID_LOG_ERROR;
+ break;
+ case kWarning_ANPLogType:
+ priority = ANDROID_LOG_WARN;
+ break;
+ case kDebug_ANPLogType:
+ priority = ANDROID_LOG_DEBUG;
+ break;
+ default:
+ priority = ANDROID_LOG_UNKNOWN;
+ break;
+ }
+ LOG_PRI_VA(priority, "plugin", format, args);
+
+ va_end(args);
+}
+
+void ANPLogInterfaceV0_Init(ANPInterface* value) {
+ ANPLogInterfaceV0* i = reinterpret_cast<ANPLogInterfaceV0*>(value);
+
+ i->log = anp_log;
+}
+
diff --git a/WebKit/android/plugins/ANPPaintInterface.cpp b/WebKit/android/plugins/ANPPaintInterface.cpp
new file mode 100644
index 0000000..a539d4a
--- /dev/null
+++ b/WebKit/android/plugins/ANPPaintInterface.cpp
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// must include config.h first for webkit to fiddle with new/delete
+#include "config.h"
+#include "SkANP.h"
+#include "SkTypeface.h"
+
+static ANPPaint* anp_newPaint() {
+ return new ANPPaint;
+}
+
+static void anp_deletePaint(ANPPaint* paint) {
+ delete paint;
+}
+
+static ANPPaintFlags anp_getFlags(const ANPPaint* paint) {
+ return paint->getFlags();
+}
+
+static void anp_setFlags(ANPPaint* paint, ANPPaintFlags flags) {
+ paint->setFlags(flags);
+}
+
+static ANPColor anp_getColor(const ANPPaint* paint) {
+ return paint->getColor();
+}
+
+static void anp_setColor(ANPPaint* paint, ANPColor color) {
+ paint->setColor(color);
+}
+
+static ANPPaintStyle anp_getStyle(const ANPPaint* paint) {
+ return paint->getStyle();
+}
+
+static void anp_setStyle(ANPPaint* paint, ANPPaintStyle style) {
+ paint->setStyle(static_cast<SkPaint::Style>(style));
+}
+
+static float anp_getStrokeWidth(const ANPPaint* paint) {
+ return SkScalarToFloat(paint->getStrokeWidth());
+}
+
+static float anp_getStrokeMiter(const ANPPaint* paint) {
+ return SkScalarToFloat(paint->getStrokeMiter());
+}
+
+static ANPPaintCap anp_getStrokeCap(const ANPPaint* paint) {
+ return paint->getStrokeCap();
+}
+
+static ANPPaintJoin anp_getStrokeJoin(const ANPPaint* paint) {
+ return paint->getStrokeJoin();
+}
+
+static void anp_setStrokeWidth(ANPPaint* paint, float width) {
+ paint->setStrokeWidth(SkFloatToScalar(width));
+}
+
+static void anp_setStrokeMiter(ANPPaint* paint, float miter) {
+ paint->setStrokeMiter(SkFloatToScalar(miter));
+}
+
+static void anp_setStrokeCap(ANPPaint* paint, ANPPaintCap cap) {
+ paint->setStrokeCap(static_cast<SkPaint::Cap>(cap));
+}
+
+static void anp_setStrokeJoin(ANPPaint* paint, ANPPaintJoin join) {
+ paint->setStrokeJoin(static_cast<SkPaint::Join>(join));
+}
+
+static ANPTextEncoding anp_getTextEncoding(const ANPPaint* paint) {
+ return paint->getTextEncoding();
+}
+
+static ANPPaintAlign anp_getTextAlign(const ANPPaint* paint) {
+ return paint->getTextAlign();
+}
+
+static float anp_getTextSize(const ANPPaint* paint) {
+ return SkScalarToFloat(paint->getTextSize());
+}
+
+static float anp_getTextScaleX(const ANPPaint* paint) {
+ return SkScalarToFloat(paint->getTextScaleX());
+}
+
+static float anp_getTextSkewX(const ANPPaint* paint) {
+ return SkScalarToFloat(paint->getTextSkewX());
+}
+
+static ANPTypeface* anp_getTypeface(const ANPPaint* paint) {
+ return reinterpret_cast<ANPTypeface*>(paint->getTypeface());
+}
+
+static void anp_setTextEncoding(ANPPaint* paint, ANPTextEncoding encoding) {
+ paint->setTextEncoding(static_cast<SkPaint::TextEncoding>(encoding));
+}
+
+static void anp_setTextAlign(ANPPaint* paint, ANPPaintAlign align) {
+ paint->setTextAlign(static_cast<SkPaint::Align>(align));
+}
+
+static void anp_setTextSize(ANPPaint* paint, float textSize) {
+ paint->setTextSize(SkFloatToScalar(textSize));
+}
+
+static void anp_setTextScaleX(ANPPaint* paint, float scaleX) {
+ paint->setTextScaleX(SkFloatToScalar(scaleX));
+}
+
+static void anp_setTextSkewX(ANPPaint* paint, float skewX) {
+ paint->setTextSkewX(SkFloatToScalar(skewX));
+}
+
+static void anp_setTypeface(ANPPaint* paint, ANPTypeface* tf) {
+ paint->setTypeface(tf);
+}
+
+static float anp_measureText(ANPPaint* paint, const void* text,
+ uint32_t byteLength, ANPRectF* bounds) {
+ SkScalar w = paint->measureText(text, byteLength,
+ reinterpret_cast<SkRect*>(bounds));
+ return SkScalarToFloat(w);
+}
+
+/** 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.
+ */
+static int anp_getTextWidths(ANPPaint* paint, const void* text,
+ uint32_t byteLength, float widths[], ANPRectF bounds[]) {
+ return paint->getTextWidths(text, byteLength, widths,
+ reinterpret_cast<SkRect*>(bounds));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define ASSIGN(obj, name) (obj)->name = anp_##name
+
+void ANPPaintInterfaceV0_Init(ANPInterface* value) {
+ ANPPaintInterfaceV0* i = reinterpret_cast<ANPPaintInterfaceV0*>(value);
+
+ 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, getTypeface);
+ ASSIGN(i, setTextEncoding);
+ ASSIGN(i, setTextAlign);
+ ASSIGN(i, setTextSize);
+ ASSIGN(i, setTextScaleX);
+ ASSIGN(i, setTextSkewX);
+ ASSIGN(i, setTypeface);
+ ASSIGN(i, measureText);
+ ASSIGN(i, getTextWidths);
+}
+
diff --git a/WebKit/android/plugins/ANPSoundInterface.cpp b/WebKit/android/plugins/ANPSoundInterface.cpp
new file mode 100644
index 0000000..74735f8
--- /dev/null
+++ b/WebKit/android/plugins/ANPSoundInterface.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// must include config.h first for webkit to fiddle with new/delete
+#include "config.h"
+#include "android_npapi.h"
+
+#include "media/AudioTrack.h"
+
+struct ANPAudioTrack {
+ void* mUser;
+ ANPAudioCallbackProc mProc;
+ android::AudioTrack* mTrack;
+};
+
+static ANPSampleFormat toANPFormat(int fm) {
+ switch (fm) {
+ case android::AudioSystem::PCM_16_BIT:
+ return kPCM16Bit_ANPSampleFormat;
+ case android::AudioSystem::PCM_8_BIT:
+ return kPCM8Bit_ANPSampleFormat;
+ default:
+ return kUnknown_ANPSamleFormat;
+ }
+}
+
+static android::AudioSystem::audio_format fromANPFormat(ANPSampleFormat fm) {
+ switch (fm) {
+ case kPCM16Bit_ANPSampleFormat:
+ return android::AudioSystem::PCM_16_BIT;
+ case kPCM8Bit_ANPSampleFormat:
+ return android::AudioSystem::PCM_8_BIT;
+ default:
+ return android::AudioSystem::INVALID_FORMAT;
+ }
+}
+
+static void callbackProc(int event, void* user, void* info) {
+ ANPAudioTrack* track = reinterpret_cast<ANPAudioTrack*>(user);
+
+ switch (event) {
+ case android::AudioTrack::EVENT_MORE_DATA: {
+ ANPAudioBuffer dst;
+ android::AudioTrack::Buffer* src;
+
+ src = reinterpret_cast<android::AudioTrack::Buffer*>(info);
+ dst.bufferData = src->raw;
+ dst.channelCount = src->channelCount;
+ dst.format = toANPFormat(src->format);
+ dst.size = src->size;
+ track->mProc(kMoreData_ANPAudioEvent, track->mUser, &dst);
+ // return the updated size field
+ src->size = dst.size;
+ break;
+ }
+ case android::AudioTrack::EVENT_UNDERRUN:
+ track->mProc(kUnderRun_ANPAudioEvent, track->mUser, NULL);
+ break;
+ default:
+ SkDebugf("------ unknown audio event for plugin %d\n", event);
+ break;
+ }
+}
+
+static ANPAudioTrack* ANPCreateTrack(uint32_t sampleRate,
+ ANPSampleFormat format,
+ int channelCount,
+ ANPAudioCallbackProc proc,
+ void* user) {
+
+ ANPAudioTrack* track = new ANPAudioTrack;
+
+ track->mUser = user;
+ track->mProc = proc;
+ track->mTrack = new android::AudioTrack(android::AudioTrack::MUSIC,
+ sampleRate,
+ fromANPFormat(format),
+ channelCount,
+ 0, // frameCount
+ 0, // flags
+ callbackProc,
+ track,
+ 0);
+
+ if (track->mTrack->initCheck() != 0) { // failure
+ delete track->mTrack;
+ delete track;
+ track = NULL;
+ }
+ return track;
+}
+
+static void ANPDeleteTrack(ANPAudioTrack* track) {
+ if (track) {
+ delete track->mTrack;
+ delete track;
+ }
+}
+
+static void ANPTrackStart(ANPAudioTrack* track) {
+ track->mTrack->start();
+}
+
+static void ANPTrackPause(ANPAudioTrack* track) {
+ track->mTrack->pause();
+}
+
+static void ANPTrackStop(ANPAudioTrack* track) {
+ track->mTrack->stop();
+}
+
+static bool ANPTrackIsStopped(ANPAudioTrack* track) {
+ return track->mTrack->stopped();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ANPAudioTrackInterfaceV0_Init(ANPInterface* value) {
+ ANPAudioTrackInterfaceV0* si = reinterpret_cast<ANPAudioTrackInterfaceV0*>(value);
+ si->newTrack = ANPCreateTrack;
+ si->deleteTrack = ANPDeleteTrack;
+ si->start = ANPTrackStart;
+ si->pause = ANPTrackPause;
+ si->stop = ANPTrackStop;
+ si->isStopped = ANPTrackIsStopped;
+}
+
diff --git a/WebKit/android/plugins/ANPTypefaceInterface.cpp b/WebKit/android/plugins/ANPTypefaceInterface.cpp
new file mode 100644
index 0000000..b95ad58
--- /dev/null
+++ b/WebKit/android/plugins/ANPTypefaceInterface.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// must include config.h first for webkit to fiddle with new/delete
+#include "config.h"
+#include "SkANP.h"
+
+static ANPTypeface* anp_createFromName(const char name[], ANPTypefaceStyle s) {
+ SkTypeface* tf = SkTypeface::Create(name,
+ static_cast<SkTypeface::Style>(s));
+ return reinterpret_cast<ANPTypeface*>(tf);
+}
+
+static ANPTypeface* anp_createFromTypeface(const ANPTypeface* family,
+ ANPTypefaceStyle s) {
+ SkTypeface* tf = SkTypeface::CreateFromTypeface(family,
+ static_cast<SkTypeface::Style>(s));
+ return reinterpret_cast<ANPTypeface*>(tf);
+}
+
+static int32_t anp_getRefCount(const ANPTypeface* tf) {
+ return tf ? tf->getRefCnt() : 0;
+}
+
+static void anp_ref(ANPTypeface* tf) {
+ tf->safeRef();
+}
+
+static void anp_unref(ANPTypeface* tf) {
+ tf->safeUnref();
+}
+
+static ANPTypefaceStyle anp_getStyle(const ANPTypeface* tf) {
+ SkTypeface::Style s = tf ? tf->getStyle() : SkTypeface::kNormal;
+ return static_cast<ANPTypefaceStyle>(s);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define ASSIGN(obj, name) (obj)->name = anp_##name
+
+void ANPTypefaceInterfaceV0_Init(ANPInterface* v) {
+ ANPTypefaceInterfaceV0* i = reinterpret_cast<ANPTypefaceInterfaceV0*>(v);
+
+ ASSIGN(i, createFromName);
+ ASSIGN(i, createFromTypeface);
+ ASSIGN(i, getRefCount);
+ ASSIGN(i, ref);
+ ASSIGN(i, unref);
+ ASSIGN(i, getStyle);
+}
+
diff --git a/WebKit/android/plugins/ANPWindowInterface.cpp b/WebKit/android/plugins/ANPWindowInterface.cpp
new file mode 100644
index 0000000..d83d9db
--- /dev/null
+++ b/WebKit/android/plugins/ANPWindowInterface.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// must include config.h first for webkit to fiddle with new/delete
+#include "config.h"
+#include "SkANP.h"
+
+static bool anp_lockRect(void* window, const ANPRectI* inval,
+ ANPBitmap* bitmap) {
+ if (window) {
+ // todo
+ return true;
+ }
+ return false;
+}
+
+static bool anp_lockRegion(void* window, const ANPRegion* inval,
+ ANPBitmap* bitmap) {
+ if (window) {
+ // todo
+ return true;
+ }
+ return false;
+}
+
+static void anp_unlock(void* window) {
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define ASSIGN(obj, name) (obj)->name = anp_##name
+
+void ANPWindowInterfaceV0_Init(ANPInterface* value) {
+ ANPWindowInterfaceV0* i = reinterpret_cast<ANPWindowInterfaceV0*>(value);
+
+ ASSIGN(i, lockRect);
+ ASSIGN(i, lockRegion);
+ ASSIGN(i, unlock);
+}
+
diff --git a/WebKit/android/plugins/PluginDataAndroid.cpp b/WebKit/android/plugins/PluginDataAndroid.cpp
new file mode 100644
index 0000000..c3f3f3a
--- /dev/null
+++ b/WebKit/android/plugins/PluginDataAndroid.cpp
@@ -0,0 +1,72 @@
+/*
+ Copyright (C) 2008 Trolltech ASA
+ Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "PluginData.h"
+
+#include "PluginDatabase.h"
+#include "PluginPackage.h"
+
+namespace WebCore {
+
+void PluginData::initPlugins()
+{
+ PluginDatabase *db = PluginDatabase::installedPlugins();
+ const Vector<PluginPackage*> &plugins = db->plugins();
+
+ for (unsigned int i = 0; i < plugins.size(); ++i) {
+ PluginInfo* info = new PluginInfo;
+ PluginPackage* package = plugins[i];
+
+ info->name = package->name();
+ info->file = package->fileName();
+ info->desc = package->description();
+
+ const MIMEToDescriptionsMap& mimeToDescriptions = package->mimeToDescriptions();
+ MIMEToDescriptionsMap::const_iterator end = mimeToDescriptions.end();
+ for (MIMEToDescriptionsMap::const_iterator it = mimeToDescriptions.begin(); it != end; ++it) {
+ MimeClassInfo* mime = new MimeClassInfo;
+ info->mimes.append(mime);
+
+ mime->type = it->first;
+ mime->desc = it->second;
+ mime->plugin = info;
+
+ Vector<String> extensions = package->mimeToExtensions().get(mime->type);
+
+ for (unsigned i = 0; i < extensions.size(); i++) {
+ if (i > 0)
+ mime->suffixes += ",";
+
+ mime->suffixes += extensions[i];
+ }
+ }
+
+ m_plugins.append(info);
+ }
+}
+
+void PluginData::refresh()
+{
+ PluginDatabase *db = PluginDatabase::installedPlugins();
+ db->refresh();
+}
+
+};
diff --git a/WebKit/android/plugins/PluginDebugAndroid.h b/WebKit/android/plugins/PluginDebugAndroid.h
new file mode 100644
index 0000000..4bbe7a9
--- /dev/null
+++ b/WebKit/android/plugins/PluginDebugAndroid.h
@@ -0,0 +1,38 @@
+#ifdef ANDROID_PLUGINS
+
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef PLUGIN_DEBUG_ANDROID_H__
+#define PLUGIN_DEBUG_ANDROID_H__
+
+// Define PLUGIN_DEBUG_LOCAL in an individual C++ file to enable for
+// that file only.
+
+// Define PLUGIN_DEBUG_GLOBAL to 1 to turn plug-in debug for all
+// Android plug-in code in this direectory.
+#define PLUGIN_DEBUG_GLOBAL 0
+
+#if PLUGIN_DEBUG_GLOBAL || defined(PLUGIN_DEBUG_LOCAL)
+# define PLUGIN_LOG(A, B...) do { LOGI( A , ## B ); } while(0)
+#else
+# define PLUGIN_LOG(A, B...) do { } while(0)
+#endif
+
+#endif // defined(PLUGIN_DEBUG_ANDROID_H__)
+
+#endif
diff --git a/WebKit/android/plugins/PluginPackageAndroid.cpp b/WebKit/android/plugins/PluginPackageAndroid.cpp
new file mode 100644
index 0000000..5df7945
--- /dev/null
+++ b/WebKit/android/plugins/PluginPackageAndroid.cpp
@@ -0,0 +1,580 @@
+#ifdef ANDROID_PLUGINS
+
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
+ */
+#define LOG_TAG "WebKit"
+
+#include "config.h"
+#include "PluginDatabase.h"
+#include "PluginPackage.h"
+
+#include "Timer.h"
+#include "PlatformString.h"
+#include "PluginMainThreadScheduler.h"
+#include "CString.h"
+#include "jni_utility.h"
+#include "npruntime_impl.h"
+#include "npfunctions.h"
+#include <dlfcn.h>
+#include <errno.h>
+
+#include "PluginDebug.h"
+#include "PluginDebugAndroid.h"
+
+namespace WebCore {
+
+// Simple class which calls dlclose() on a dynamic library when going
+// out of scope. Call ok() if the handle should stay open.
+class DynamicLibraryCloser
+{
+ public:
+ DynamicLibraryCloser(PlatformModule *module) : m_module(module) { }
+ ~DynamicLibraryCloser()
+ {
+ // Close the library if non-NULL reference and open.
+ if (m_module && *m_module)
+ {
+ dlclose(*m_module);
+ *m_module = 0;
+ }
+ }
+ void ok() { m_module = NULL; }
+
+ private:
+ PlatformModule *m_module;
+};
+
+// A container for a dummy npp instance. This is used to allow
+// NPN_PluginThreadAsyncCall() to be used with NULL passed as the npp
+// instance. This is substituted instead, and is shared between all
+// plugins which behave in this way. This will be lazily created in
+// the first call to NPN_PluginThreadAsyncCall().
+class DummyNpp {
+ public:
+ DummyNpp() {
+ m_npp = new NPP_t();
+ m_npp->pdata = NULL;
+ m_npp->ndata = NULL;
+ PluginMainThreadScheduler::scheduler().registerPlugin(m_npp);
+ }
+ ~DummyNpp() {
+ PluginMainThreadScheduler::scheduler().unregisterPlugin(m_npp);
+ delete m_npp;
+ }
+ NPP_t *getInstance() { return m_npp; }
+
+ private:
+ NPP_t *m_npp;
+};
+
+static bool getEntryPoint(PlatformModule module,
+ const char *name,
+ void **entry_point)
+{
+ dlerror();
+ *entry_point = dlsym(module, name);
+ const char *error = dlerror();
+ if(error == NULL && *entry_point != NULL) {
+ return true;
+ } else {
+ PLUGIN_LOG("Couldn't get entry point \"%s\": %s\n",
+ name, error);
+ return false;
+ }
+}
+
+int PluginPackage::compareFileVersion(
+ const PlatformModuleVersion& compareVersion) const
+{
+ // return -1, 0, or 1 if plug-in version is less than, equal to,
+ // or greater than the passed version
+ if (m_moduleVersion != compareVersion)
+ return m_moduleVersion > compareVersion ? 1 : -1;
+ else
+ return 0;
+}
+
+bool PluginPackage::isPluginBlacklisted()
+{
+ // No blacklisted Android plugins... yet!
+ return false;
+}
+
+void PluginPackage::determineQuirks(const String& mimeType)
+{
+ // The Gears implementation relies on it being loaded *all the time*,
+ // so check to see if this package represents the Gears plugin and
+ // load it.
+ if (mimeType == "application/x-googlegears") {
+ m_quirks.add(PluginQuirkDontUnloadPlugin);
+ }
+}
+
+static void Android_NPN_PluginThreadAsyncCall(NPP instance,
+ void (*func) (void *),
+ void *userData)
+{
+ // Translate all instance == NULL to a dummy actual npp.
+ static DummyNpp dummyNpp;
+ if (instance == NULL) {
+ instance = dummyNpp.getInstance();
+ }
+ // Call through to the wrapped function.
+ NPN_PluginThreadAsyncCall(instance, func, userData);
+}
+
+static void initializeBrowserFuncs(NPNetscapeFuncs *funcs)
+{
+ // Initialize the NPN function pointers that we hand over to the
+ // plugin.
+ memset(funcs, 0, sizeof(*funcs));
+
+ funcs->size = sizeof(*funcs);
+ funcs->version = NP_VERSION_MINOR;
+ funcs->geturl = NPN_GetURL;
+ funcs->posturl = NPN_PostURL;
+ funcs->requestread = NPN_RequestRead;
+ funcs->newstream = NPN_NewStream;
+ funcs->write = NPN_Write;
+ funcs->destroystream = NPN_DestroyStream;
+ funcs->status = NPN_Status;
+ funcs->uagent = NPN_UserAgent;
+ funcs->memalloc = NPN_MemAlloc;
+ funcs->memfree = NPN_MemFree;
+ funcs->memflush = NPN_MemFlush;
+ funcs->reloadplugins = NPN_ReloadPlugins;
+ funcs->geturlnotify = NPN_GetURLNotify;
+ funcs->posturlnotify = NPN_PostURLNotify;
+ funcs->getvalue = NPN_GetValue;
+ funcs->setvalue = NPN_SetValue;
+ funcs->invalidaterect = NPN_InvalidateRect;
+ funcs->invalidateregion = NPN_InvalidateRegion;
+ funcs->forceredraw = NPN_ForceRedraw;
+ funcs->getJavaEnv = NPN_GetJavaEnv;
+ funcs->getJavaPeer = NPN_GetJavaPeer;
+ funcs->pushpopupsenabledstate = NPN_PushPopupsEnabledState;
+ funcs->poppopupsenabledstate = NPN_PopPopupsEnabledState;
+ funcs->pluginthreadasynccall = Android_NPN_PluginThreadAsyncCall;
+ funcs->scheduletimer = NPN_ScheduleTimer;
+ funcs->unscheduletimer = NPN_UnscheduleTimer;
+
+ funcs->releasevariantvalue = _NPN_ReleaseVariantValue;
+ funcs->getstringidentifier = _NPN_GetStringIdentifier;
+ funcs->getstringidentifiers = _NPN_GetStringIdentifiers;
+ funcs->getintidentifier = _NPN_GetIntIdentifier;
+ funcs->identifierisstring = _NPN_IdentifierIsString;
+ funcs->utf8fromidentifier = _NPN_UTF8FromIdentifier;
+ funcs->intfromidentifier = _NPN_IntFromIdentifier;
+ funcs->createobject = _NPN_CreateObject;
+ funcs->retainobject = _NPN_RetainObject;
+ funcs->releaseobject = _NPN_ReleaseObject;
+ funcs->invoke = _NPN_Invoke;
+ funcs->invokeDefault = _NPN_InvokeDefault;
+ funcs->evaluate = _NPN_Evaluate;
+ funcs->getproperty = _NPN_GetProperty;
+ funcs->setproperty = _NPN_SetProperty;
+ funcs->removeproperty = _NPN_RemoveProperty;
+ funcs->hasproperty = _NPN_HasProperty;
+ funcs->hasmethod = _NPN_HasMethod;
+ funcs->setexception = _NPN_SetException;
+ funcs->enumerate = _NPN_Enumerate;
+}
+
+static jobject createPluginObject(const char *name,
+ const char *path,
+ const char *fileName,
+ const char *description)
+{
+ JNIEnv *env = JSC::Bindings::getJNIEnv();
+ // Create a Java "class Plugin" object instance
+ jclass pluginClass = env->FindClass("android/webkit/Plugin");
+ if(!pluginClass) {
+ PLUGIN_LOG("Couldn't find class android.webkit.Plugin\n");
+ return 0;
+ }
+ // Get Plugin(String, String, String, String, Context)
+ jmethodID pluginConstructor = env->GetMethodID(
+ pluginClass,
+ "<init>",
+ "(Ljava/lang/String;"
+ "Ljava/lang/String;"
+ "Ljava/lang/String;"
+ "Ljava/lang/String;)V");
+ if(!pluginConstructor) {
+ PLUGIN_LOG("Couldn't get android.webkit.Plugin constructor\n");
+ return 0;
+ }
+ // Make Java strings of name, path, fileName, description
+ jstring javaName = env->NewStringUTF(name);
+ jstring javaPath = env->NewStringUTF(path);
+ jstring javaFileName = env->NewStringUTF(fileName);
+ jstring javaDescription = env->NewStringUTF(description);
+ // Make a plugin instance
+ jobject pluginObject = env->NewObject(pluginClass,
+ pluginConstructor,
+ javaName,
+ javaPath,
+ javaFileName,
+ javaDescription);
+ return pluginObject;
+}
+
+static jobject getPluginListObject()
+{
+ JNIEnv *env = JSC::Bindings::getJNIEnv();
+ // Get WebView.getPluginList()
+ jclass webViewClass = env->FindClass("android/webkit/WebView");
+ if(!webViewClass) {
+ PLUGIN_LOG("Couldn't find class android.webkit.WebView\n");
+ return 0;
+ }
+ jmethodID getPluginList = env->GetStaticMethodID(
+ webViewClass,
+ "getPluginList",
+ "()Landroid/webkit/PluginList;");
+ if(!getPluginList) {
+ PLUGIN_LOG("Couldn't find android.webkit.WebView.getPluginList()\n");
+ return 0;
+ }
+ // Get the PluginList instance
+ jobject pluginListObject = env->CallStaticObjectMethod(webViewClass,
+ getPluginList);
+ if(!pluginListObject) {
+ PLUGIN_LOG("Couldn't get PluginList object\n");
+ return 0;
+ }
+ return pluginListObject;
+}
+
+static bool addPluginObjectToList(jobject pluginList, jobject plugin)
+{
+ // Add the Plugin object
+ JNIEnv *env = JSC::Bindings::getJNIEnv();
+ jclass pluginListClass = env->FindClass("android/webkit/PluginList");
+ if(!pluginListClass) {
+ PLUGIN_LOG("Couldn't find class android.webkit.PluginList\n");
+ return false;
+ }
+ jmethodID addPlugin = env->GetMethodID(
+ pluginListClass,
+ "addPlugin",
+ "(Landroid/webkit/Plugin;)V");
+ if(!addPlugin) {
+ PLUGIN_LOG("Couldn't find android.webkit.PluginList.addPlugin()\n");
+ return false;
+ }
+ env->CallVoidMethod(pluginList, addPlugin, plugin);
+ return true;
+}
+
+static void removePluginObjectFromList(jobject pluginList, jobject plugin)
+{
+ // Remove the Plugin object
+ JNIEnv *env = JSC::Bindings::getJNIEnv();
+ jclass pluginListClass = env->FindClass("android/webkit/PluginList");
+ if(!pluginListClass) {
+ PLUGIN_LOG("Couldn't find class android.webkit.PluginList\n");
+ return;
+ }
+ jmethodID removePlugin = env->GetMethodID(
+ pluginListClass,
+ "removePlugin",
+ "(Landroid/webkit/Plugin;)V");
+ if(!removePlugin) {
+ PLUGIN_LOG("Couldn't find android.webkit.PluginList.removePlugin()\n");
+ return;
+ }
+ env->CallVoidMethod(pluginList, removePlugin, plugin);
+}
+
+bool PluginPackage::load()
+{
+ PLUGIN_LOG("tid:%d isActive:%d isLoaded:%d loadCount:%d\n",
+ gettid(),
+ m_freeLibraryTimer.isActive(),
+ m_isLoaded,
+ m_loadCount);
+ if (m_freeLibraryTimer.isActive()) {
+ ASSERT(m_module);
+ m_freeLibraryTimer.stop();
+ } else if (m_isLoaded) {
+ if (m_quirks.contains(PluginQuirkDontAllowMultipleInstances))
+ return false;
+ m_loadCount++;
+ PLUGIN_LOG("Already loaded, count now %d\n", m_loadCount);
+ return true;
+ }
+ ASSERT(m_loadCount == 0);
+ ASSERT(m_module == NULL);
+
+ PLUGIN_LOG("Loading \"%s\"\n", m_path.utf8().data());
+
+ // Open the library
+ void *handle = dlopen(m_path.utf8().data(), RTLD_NOW);
+ if(!handle) {
+ PLUGIN_LOG("Couldn't load plugin library \"%s\": %s\n",
+ m_path.utf8().data(), dlerror());
+ return false;
+ }
+ m_module = handle;
+ PLUGIN_LOG("Fetch Info Loaded %p\n", m_module);
+ // This object will call dlclose() and set m_module to NULL
+ // when going out of scope.
+ DynamicLibraryCloser dlCloser(&m_module);
+
+
+ NP_InitializeFuncPtr NP_Initialize;
+ if(!getEntryPoint(m_module, "NP_Initialize", (void **) &NP_Initialize) ||
+ !getEntryPoint(handle, "NP_Shutdown", (void **) &m_NPP_Shutdown)) {
+ PLUGIN_LOG("Couldn't find Initialize function\n");
+ return false;
+ }
+
+ // Provide the plugin with our browser function table and grab its
+ // plugin table. Provide the Java environment and the Plugin which
+ // can be used to override the defaults if the plugin wants.
+ initializeBrowserFuncs(&m_browserFuncs);
+ memset(&m_pluginFuncs, 0, sizeof(m_pluginFuncs));
+ m_pluginFuncs.size = sizeof(m_pluginFuncs);
+ if(NP_Initialize(&m_browserFuncs,
+ &m_pluginFuncs,
+ JSC::Bindings::getJNIEnv(),
+ m_pluginObject) != NPERR_NO_ERROR) {
+ PLUGIN_LOG("Couldn't initialize plugin\n");
+ return false;
+ }
+
+ // Don't close the library - loaded OK.
+ dlCloser.ok();
+ // Retain the handle so we can close it in the future.
+ m_module = handle;
+ m_isLoaded = true;
+ ++m_loadCount;
+ PLUGIN_LOG("Initial load ok, count now %d\n", m_loadCount);
+ return true;
+}
+
+void PluginPackage::unregisterPluginObject()
+{
+ PLUGIN_LOG("unregisterPluginObject\n");
+ // Called by unloadWithoutShutdown(). Remove the plugin from the
+ // PluginList
+ if(m_pluginObject) {
+ jobject pluginListObject = getPluginListObject();
+ if(pluginListObject) {
+ removePluginObjectFromList(pluginListObject, m_pluginObject);
+ }
+ // Remove a reference to the Plugin object so it can
+ // garbage collect.
+ JSC::Bindings::getJNIEnv()->DeleteGlobalRef(m_pluginObject);
+ m_pluginObject = 0;
+ }
+}
+
+bool PluginPackage::fetchInfo()
+{
+ PLUGIN_LOG("Fetch Info Loading \"%s\"\n", m_path.utf8().data());
+
+ // Open the library
+ void *handle = dlopen(m_path.utf8().data(), RTLD_NOW);
+ if(!handle) {
+ PLUGIN_LOG("Couldn't load plugin library \"%s\": %s\n",
+ m_path.utf8().data(), dlerror());
+ return false;
+ }
+ PLUGIN_LOG("Fetch Info Loaded %p\n", handle);
+
+ // This object will call dlclose() and set m_module to NULL
+ // when going out of scope.
+ DynamicLibraryCloser dlCloser(&handle);
+
+ // Get the three entry points we need for Linux Netscape Plug-ins
+ NP_GetMIMEDescriptionFuncPtr NP_GetMIMEDescription;
+ NPP_GetValueProcPtr NP_GetValue;
+ if(!getEntryPoint(handle, "NP_GetMIMEDescription",
+ (void **) &NP_GetMIMEDescription) ||
+ !getEntryPoint(handle, "NP_GetValue", (void **) &NP_GetValue)) {
+ // If any of those failed to resolve, fail the entire load
+ return false;
+ }
+
+ // Get the plugin name and description using NP_GetValue
+ const char *name;
+ const char *description;
+ if(NP_GetValue(NULL, NPPVpluginNameString, &name) != NPERR_NO_ERROR ||
+ NP_GetValue(NULL, NPPVpluginDescriptionString, &description) !=
+ NPERR_NO_ERROR) {
+ PLUGIN_LOG("Couldn't get name/description using NP_GetValue\n");
+ return false;
+ }
+
+ PLUGIN_LOG("Plugin name: \"%s\"\n", name);
+ PLUGIN_LOG("Plugin description: \"%s\"\n", description);
+ m_name = name;
+ m_description = description;
+
+ // fileName is just the trailing part of the path
+ int last_slash = m_path.reverseFind('/');
+ if(last_slash < 0)
+ m_fileName = m_path;
+ else
+ m_fileName = m_path.substring(last_slash + 1);
+
+ // Grab the MIME description. This is in the format, e.g:
+ // application/x-somescriptformat:ssf:Some Script Format
+ String mimeDescription(NP_GetMIMEDescription());
+ PLUGIN_LOG("MIME description: \"%s\"\n", mimeDescription.utf8().data());
+ // Clear out the current mappings.
+ m_mimeToDescriptions.clear();
+ m_mimeToExtensions.clear();
+ // Split the description into its component entries, separated by
+ // semicolons.
+ Vector<String> mimeEntries;
+ mimeDescription.split(';', true, mimeEntries);
+ // Iterate through the entries, adding them to the MIME mappings.
+ for(Vector<String>::const_iterator it = mimeEntries.begin();
+ it != mimeEntries.end(); ++it) {
+ // Each part is split into 3 fields separated by colons
+ // Field 1 is the MIME type (e.g "application/x-shockwave-flash").
+ // Field 2 is a comma separated list of file extensions.
+ // Field 3 is a human readable short description.
+ const String &mimeEntry = *it;
+ Vector<String> fields;
+ mimeEntry.split(':', true, fields);
+ if(fields.size() != 3) {
+ PLUGIN_LOG("Bad MIME entry \"%s\"\n", mimeEntry.utf8().data());
+ return false;
+ }
+
+ const String& mimeType = fields[0];
+ Vector<String> extensions;
+ fields[1].split(',', true, extensions);
+ const String& description = fields[2];
+
+ determineQuirks(mimeType);
+
+ PLUGIN_LOG("mime_type: \"%s\"\n", mimeType.utf8().data());
+ PLUGIN_LOG("extensions: \"%s\"\n", fields[1].utf8().data());
+ PLUGIN_LOG("description: \"%s\"\n", description.utf8().data());
+
+ // Map the mime type to the vector of extensions and the description
+ if(!extensions.isEmpty())
+ m_mimeToExtensions.set(mimeType, extensions);
+ if(!description.isEmpty())
+ m_mimeToDescriptions.set(mimeType, description);
+ }
+
+ // Create a new Java Plugin object, this object is an instance of
+ // android.os.WebView.Plugin
+ CString path = m_path.utf8();
+ CString filename = m_fileName.utf8();
+ jobject pluginObject = createPluginObject(name,
+ path.data(),
+ filename.data(),
+ description);
+ if(!pluginObject) {
+ PLUGIN_LOG("Couldn't create Java Plugin\n");
+ return false;
+ }
+
+ // Add the Plugin to the PluginList. This list is used to show the
+ // user the list of plugins installed in the webkit.
+
+ // The list of plugins are also available from the global static
+ // function PluginDatabase::installedPlugins(). However, the method
+ // on WebView to get the plugin list is a static method, and runs in the
+ // UI thread. We can not easily drop all the GlobalRefs this implementation
+ // has and switch to just calling through JNI to aforementioned API as
+ // WebKit runs in another thread and the WebView call would need to change
+ // to being async.
+ jobject pluginListObject = getPluginListObject();
+ if(!pluginListObject) {
+ PLUGIN_LOG("Couldn't get PluginList object\n");
+ return false;
+ }
+ if(!addPluginObjectToList(pluginListObject, pluginObject)) {
+ PLUGIN_LOG("Couldn't add Plugin to PluginList\n");
+ m_NPP_Shutdown();
+ return false;
+ }
+
+ // Retain the Java Plugin object
+ m_pluginObject = JSC::Bindings::getJNIEnv()->NewGlobalRef(pluginObject);
+
+ PLUGIN_LOG("Fetch Info Loaded plugin details ok \"%s\"\n",
+ m_path.utf8().data());
+
+ // If this plugin needs to be kept in memory, unload the module now
+ // and load it permanently.
+ if (m_quirks.contains(PluginQuirkDontUnloadPlugin)) {
+ dlCloser.ok();
+ dlclose(handle);
+ load();
+ }
+
+ // dlCloser will unload the plugin if required.
+ return true;
+}
+
+unsigned PluginPackage::hash() const
+{
+ const unsigned hashCodes[] = {
+ m_name.impl()->hash(),
+ m_description.impl()->hash(),
+ m_mimeToExtensions.size(),
+ };
+
+ return StringImpl::computeHash(reinterpret_cast<const UChar*>(hashCodes),
+ sizeof(hashCodes) / sizeof(UChar));
+}
+
+bool PluginPackage::equal(const PluginPackage& a, const PluginPackage& b)
+{
+ if (a.m_name != b.m_name)
+ return false;
+
+ if (a.m_description != b.m_description)
+ return false;
+
+ if (a.m_mimeToExtensions.size() != b.m_mimeToExtensions.size())
+ return false;
+
+ MIMEToExtensionsMap::const_iterator::Keys end =
+ a.m_mimeToExtensions.end().keys();
+ for (MIMEToExtensionsMap::const_iterator::Keys it =
+ a.m_mimeToExtensions.begin().keys();
+ it != end;
+ ++it) {
+ if (!b.m_mimeToExtensions.contains(*it)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/WebKit/android/plugins/PluginTimer.cpp b/WebKit/android/plugins/PluginTimer.cpp
new file mode 100644
index 0000000..ca24de0
--- /dev/null
+++ b/WebKit/android/plugins/PluginTimer.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2008 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
+ */
+
+#include "config.h"
+#include "PluginTimer.h"
+
+namespace WebCore {
+
+ static uint32 gTimerID;
+
+ PluginTimer::PluginTimer(PluginTimer** list, NPP instance, bool repeat,
+ void (*timerFunc)(NPP npp, uint32 timerID))
+ : m_list(list),
+ m_instance(instance),
+ m_timerFunc(timerFunc),
+ m_repeat(repeat)
+ {
+ m_timerID = ++gTimerID;
+
+ m_next = *list;
+ if (m_next) {
+ m_next->m_prev = this;
+ }
+ m_prev = 0;
+ *list = this;
+ }
+
+ PluginTimer::~PluginTimer()
+ {
+ if (m_next) {
+ m_next->m_prev = m_prev;
+ }
+ if (m_prev) {
+ m_prev->m_next = m_next;
+ } else {
+ *m_list = m_next;
+ }
+ }
+
+ void PluginTimer::fired()
+ {
+ m_timerFunc(m_instance, m_timerID);
+ if (!m_repeat) {
+ delete this;
+ }
+ }
+
+ // may return null if timerID is not found
+ PluginTimer* PluginTimer::Find(PluginTimer* list, uint32 timerID)
+ {
+ PluginTimer* curr = list;
+ while (curr) {
+ if (curr->m_timerID == timerID) {
+ break;
+ }
+ curr = curr->m_next;
+ }
+ return curr;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ PluginTimerList::~PluginTimerList()
+ {
+ while (m_list) {
+ delete m_list;
+ }
+ }
+
+ uint32 PluginTimerList::schedule(NPP instance, uint32 interval, bool repeat,
+ void (*proc)(NPP npp, uint32 timerID))
+ {
+ PluginTimer* timer = new PluginTimer(&m_list, instance, repeat, proc);
+
+ double dinterval = interval * 0.001; // milliseconds to seconds
+ if (repeat) {
+ timer->startRepeating(dinterval);
+ } else {
+ timer->startOneShot(dinterval);
+ }
+ return timer->timerID();
+ }
+
+ void PluginTimerList::unschedule(NPP instance, uint32 timerID)
+ {
+ delete PluginTimer::Find(m_list, timerID);
+ }
+
+} // namespace WebCore
diff --git a/WebKit/android/plugins/PluginTimer.h b/WebKit/android/plugins/PluginTimer.h
new file mode 100644
index 0000000..8570913
--- /dev/null
+++ b/WebKit/android/plugins/PluginTimer.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2008 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 PluginTimer_H
+#define PluginTimer_H
+
+#include "Timer.h"
+#include "npapi.h"
+
+namespace WebCore {
+
+ class PluginTimerList;
+
+ class PluginTimer : public TimerBase {
+ public:
+ PluginTimer(PluginTimer** list, NPP instance, bool repeat,
+ void (*proc)(NPP npp, uint32 timerID));
+ virtual ~PluginTimer();
+
+ uint32 timerID() const { return m_timerID; }
+
+ static PluginTimer* Find(PluginTimer* list, uint32 timerID);
+
+ private:
+ // override from TimerBase
+ virtual void fired();
+
+ PluginTimer* next() const { return m_next; }
+ friend class PluginTimerList;
+
+ PluginTimer** m_list;
+ PluginTimer* m_prev;
+ PluginTimer* m_next;
+ NPP m_instance;
+ void (*m_timerFunc)(NPP, uint32);
+ uint32 m_timerID;
+ bool m_repeat;
+ };
+
+ class PluginTimerList {
+ public:
+ PluginTimerList() : m_list(0) {}
+ ~PluginTimerList();
+
+ uint32 schedule(NPP instance, uint32 interval, bool repeat,
+ void (*proc)(NPP npp, uint32 timerID));
+ void unschedule(NPP instance, uint32 timerID);
+
+ private:
+ PluginTimer* m_list;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebKit/android/plugins/PluginViewAndroid.cpp b/WebKit/android/plugins/PluginViewAndroid.cpp
new file mode 100644
index 0000000..c20c0d8
--- /dev/null
+++ b/WebKit/android/plugins/PluginViewAndroid.cpp
@@ -0,0 +1,568 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
+ */
+#define LOG_TAG "WebCore"
+
+#include "config.h"
+#include "PluginView.h"
+
+#include "Document.h"
+#include "Element.h"
+#include "EventNames.h"
+#include "FrameLoader.h"
+#include "FrameLoadRequest.h"
+#include "FrameTree.h"
+#include "Frame.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "HTMLNames.h"
+#include "HTMLPlugInElement.h"
+#include "Image.h"
+#include "KeyboardEvent.h"
+#include "MIMETypeRegistry.h"
+#include "MouseEvent.h"
+#include "NotImplemented.h"
+#include "Page.h"
+#include "PlatformGraphicsContext.h"
+#include "PlatformKeyboardEvent.h"
+#include "PluginMainThreadScheduler.h"
+#include "PluginPackage.h"
+// #include "kjs_binding.h"
+// #include "kjs_proxy.h"
+#include "android_graphics.h"
+#include "SkCanvas.h"
+#include "npruntime_impl.h"
+#include "runtime_root.h"
+#include "utils/SystemClock.h"
+#include "ScriptController.h"
+#include "Settings.h"
+#include <runtime/JSLock.h>
+// #include <kjs/value.h>
+#include <wtf/ASCIICType.h>
+#include "runtime.h"
+#include "WebViewCore.h"
+
+#include "PluginDebug.h"
+#include "PluginDebugAndroid.h"
+#include "PluginViewBridgeAndroid.h"
+#include "PluginWidgetAndroid.h"
+
+#include "android_npapi.h"
+#include "SkANP.h"
+#include "SkFlipPixelRef.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern void ANPAudioTrackInterfaceV0_Init(ANPInterface* value);
+extern void ANPCanvasInterfaceV0_Init(ANPInterface* value);
+extern void ANPLogInterfaceV0_Init(ANPInterface* value);
+extern void ANPOffscreenInterfaceV0_Init(ANPInterface* value);
+extern void ANPPaintInterfaceV0_Init(ANPInterface* value);
+extern void ANPTypefaceInterfaceV0_Init(ANPInterface* value);
+extern void ANPWindowInterfaceV0_Init(ANPInterface* value);
+
+struct VarProcPair {
+ int enumValue;
+ size_t size;
+ void (*proc)(ANPInterface*);
+};
+
+#define VARPROCLINE(name) \
+ k##name##_ANPGetValue, sizeof(ANP##name), ANP##name##_Init
+
+static const VarProcPair gVarProcs[] = {
+ { VARPROCLINE(AudioTrackInterfaceV0) },
+ { VARPROCLINE(LogInterfaceV0) },
+ { VARPROCLINE(CanvasInterfaceV0) },
+ { VARPROCLINE(PaintInterfaceV0) },
+ { VARPROCLINE(TypefaceInterfaceV0) },
+ { VARPROCLINE(WindowInterfaceV0) },
+};
+
+/* return true if var was an interface request (error will be set accordingly)
+ return false if var is not a recognized interface (and ignore error param)
+ */
+static bool anp_getInterface(NPNVariable var, void* value, NPError* error) {
+ const VarProcPair* iter = gVarProcs;
+ const VarProcPair* stop = gVarProcs + SK_ARRAY_COUNT(gVarProcs);
+ while (iter < stop) {
+ if (iter->enumValue == var) {
+ ANPInterface* i = reinterpret_cast<ANPInterface*>(value);
+ if (i->inSize < iter->size) {
+ SkDebugf("------- interface %d, expected size %d, allocated %d\n",
+ var, iter->size, i->inSize);
+ *error = NPERR_INCOMPATIBLE_VERSION_ERROR;
+ } else {
+ iter->proc(i);
+ *error = NPERR_NO_ERROR;
+ }
+ return true;
+ }
+ iter += 1;
+ }
+ SkDebugf("------ unknown NPNVariable %d\n", var);
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+using JSC::ExecState;
+using JSC::Interpreter;
+using JSC::JSLock;
+using JSC::JSObject;
+using JSC::JSValue;
+using JSC::UString;
+
+using std::min;
+
+using namespace WTF;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+void PluginView::platformInit()
+{
+ setPlatformWidget(new PluginViewBridgeAndroid());
+
+ m_isWindowed = false; // we don't support windowed yet
+
+ m_window = new PluginWidgetAndroid(this);
+
+ m_npWindow.type = NPWindowTypeDrawable;
+ m_npWindow.window = 0;
+}
+
+PluginView::~PluginView()
+{
+ stop();
+
+ deleteAllValues(m_requests);
+
+ freeStringArray(m_paramNames, m_paramCount);
+ freeStringArray(m_paramValues, m_paramCount);
+
+ m_parentFrame->script()->cleanupScriptObjectsForPlugin(this);
+
+// Since we have no legacy plugins to check, we ignore the quirks check
+// if (m_plugin && !m_plugin->quirks().contains(PluginQuirkDontUnloadPlugin))
+ if (m_plugin) {
+ m_plugin->unload();
+ }
+ delete m_window;
+}
+
+void PluginView::init()
+{
+ if (m_haveInitialized)
+ return;
+ m_haveInitialized = true;
+
+ android::WebViewCore* c = android::WebViewCore::getWebViewCore(this->parent());
+ m_window->init(c);
+
+ if (!m_plugin) {
+ ASSERT(m_status == PluginStatusCanNotFindPlugin);
+ return;
+ }
+
+ if (!m_plugin->load()) {
+ m_plugin = 0;
+ m_status = PluginStatusCanNotLoadPlugin;
+ return;
+ }
+
+ if (!start()) {
+ m_status = PluginStatusCanNotLoadPlugin;
+ return;
+ }
+
+ m_status = PluginStatusLoadedSuccessfully;
+}
+
+void PluginView::handleMouseEvent(MouseEvent* event)
+{
+ const AtomicString& type = event->type();
+ bool isDown = (eventNames().mousedownEvent == type);
+ bool isUp = (eventNames().mouseupEvent == type);
+ if (!isDown && !isUp) {
+ return;
+ }
+
+ ANPEvent evt;
+ SkANP::InitEvent(&evt, kTouch_ANPEventType);
+
+ evt.data.touch.action = isDown ? kDown_ANPTouchAction : kUp_ANPTouchAction;
+ evt.data.touch.modifiers = 0; // todo
+ // these are relative to plugin
+ evt.data.touch.x = event->pageX() - m_npWindow.x;
+ evt.data.touch.y = event->pageY() - m_npWindow.y;
+ if (m_plugin->pluginFuncs()->event(m_instance, &evt)) {
+ event->setDefaultHandled();
+ }
+}
+
+static ANPKeyModifier make_modifiers(bool shift, bool alt) {
+ ANPKeyModifier mod = 0;
+ if (shift) {
+ mod |= kShift_ANPKeyModifier;
+ }
+ if (alt) {
+ mod |= kAlt_ANPKeyModifier;
+ }
+ return mod;
+}
+
+void PluginView::handleKeyboardEvent(KeyboardEvent* event)
+{
+ const PlatformKeyboardEvent* pke = event->keyEvent();
+ if (NULL == pke) {
+ return;
+ }
+
+ ANPEvent evt;
+ SkANP::InitEvent(&evt, kKey_ANPEventType);
+
+ switch (pke->type()) {
+ case PlatformKeyboardEvent::KeyDown:
+#ifdef TRACE_KEY_EVENTS
+ SkDebugf("--------- KeyDown, ignore\n");
+#endif
+ return;
+ case PlatformKeyboardEvent::RawKeyDown:
+ evt.data.key.action = kDown_ANPKeyAction;
+ break;
+ case PlatformKeyboardEvent::Char:
+#ifdef TRACE_KEY_EVENTS
+ SkDebugf("--------- Char, ignore\n");
+#endif
+ return;
+ case PlatformKeyboardEvent::KeyUp:
+ evt.data.key.action = kUp_ANPKeyAction;
+ break;
+ default:
+#ifdef TRACE_KEY_EVENTS
+ SkDebugf("------ unexpected keyevent type %d\n", pke->type());
+#endif
+ return;
+ }
+ evt.data.key.nativeCode = pke->nativeVirtualKeyCode();
+ evt.data.key.virtualCode = pke->windowsVirtualKeyCode();
+ evt.data.key.repeatCount = pke->repeatCount();
+ evt.data.key.modifiers = make_modifiers(pke->shiftKey(), pke->altKey());
+ evt.data.key.unichar = pke->unichar();
+
+ if (m_plugin->pluginFuncs()->event(m_instance, &evt)) {
+ event->setDefaultHandled();
+ }
+}
+
+NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32 len, const char* buf)
+{
+ notImplemented();
+ return NPERR_GENERIC_ERROR;
+}
+
+NPError PluginView::getValueStatic(NPNVariable variable, void* value)
+{
+ // our interface query is valid with no NPP instance
+ NPError error = NPERR_GENERIC_ERROR;
+ (void)anp_getInterface(variable, value, &error);
+ return error;
+}
+
+void PluginView::setParent(ScrollView* parent)
+{
+ Widget::setParent(parent);
+
+ if (parent)
+ init();
+}
+
+void PluginView::setNPWindowRect(const IntRect& rect)
+{
+ if (!m_isStarted)
+ return;
+
+ const int width = rect.width();
+ const int height = rect.height();
+
+ IntPoint p = static_cast<FrameView*>(parent())->contentsToWindow(rect.location());
+ m_npWindow.x = p.x();
+ m_npWindow.y = p.y();
+
+ m_npWindow.width = width;
+ m_npWindow.height = height;
+
+ m_npWindow.clipRect.left = 0;
+ m_npWindow.clipRect.top = 0;
+ m_npWindow.clipRect.right = width;
+ m_npWindow.clipRect.bottom = height;
+
+ if (m_plugin->pluginFuncs()->setwindow) {
+ JSC::JSLock::DropAllLocks dropAllLocks(false);
+ setCallingPlugin(true);
+ m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow);
+ setCallingPlugin(false);
+ }
+
+ m_window->setWindow(m_npWindow.x, m_npWindow.y, width, height,
+ m_isTransparent);
+}
+
+void PluginView::stop()
+{
+ if (!m_isStarted)
+ return;
+
+ HashSet<RefPtr<PluginStream> > streams = m_streams;
+ HashSet<RefPtr<PluginStream> >::iterator end = streams.end();
+ for (HashSet<RefPtr<PluginStream> >::iterator it = streams.begin(); it != end; ++it) {
+ (*it)->stop();
+ disconnectStream((*it).get());
+ }
+
+ ASSERT(m_streams.isEmpty());
+
+ m_isStarted = false;
+
+ JSC::JSLock::DropAllLocks dropAllLocks(false);
+
+ PluginMainThreadScheduler::scheduler().unregisterPlugin(m_instance);
+
+ // Destroy the plugin
+ NPSavedData* savedData = 0;
+ setCallingPlugin(true);
+ NPError npErr = m_plugin->pluginFuncs()->destroy(m_instance, &savedData);
+ setCallingPlugin(false);
+ LOG_NPERROR(npErr);
+
+ if (savedData) {
+ if (savedData->buf)
+ NPN_MemFree(savedData->buf);
+ NPN_MemFree(savedData);
+ }
+
+ m_instance->pdata = 0;
+}
+
+const char* PluginView::userAgentStatic()
+{
+ return 0;
+}
+
+const char* PluginView::userAgent()
+{
+ if (m_userAgent.isNull())
+ m_userAgent = m_parentFrame->loader()->userAgent(m_url).utf8();
+ return m_userAgent.data();
+}
+
+NPError PluginView::getValue(NPNVariable variable, void* value)
+{
+ switch (variable) {
+ case NPNVWindowNPObject: {
+ NPObject* windowScriptObject =
+ m_parentFrame->script()->windowScriptNPObject();
+
+ // Return value is expected to be retained, as described
+ // here:
+ // <http://www.mozilla.org/projects/plugin/npruntime.html>
+ if (windowScriptObject)
+ _NPN_RetainObject(windowScriptObject);
+
+ void** v = (void**)value;
+ *v = windowScriptObject;
+
+ return NPERR_NO_ERROR;
+ }
+
+ case NPNVPluginElementNPObject: {
+ NPObject* pluginScriptObject = 0;
+
+ if (m_element->hasTagName(appletTag) ||
+ m_element->hasTagName(embedTag) ||
+ m_element->hasTagName(objectTag)) {
+ HTMLPlugInElement* pluginElement =
+ static_cast<HTMLPlugInElement*>(m_element);
+ pluginScriptObject = pluginElement->getNPObject();
+ }
+
+ // Return value is expected to be retained, as described
+ // here:
+ // <http://www.mozilla.org/projects/plugin/npruntime.html>
+ if (pluginScriptObject)
+ _NPN_RetainObject(pluginScriptObject);
+
+ void** v = (void**)value;
+ *v = pluginScriptObject;
+
+ return NPERR_NO_ERROR;
+ }
+
+ case NPNVnetscapeWindow: {
+ // Return the top level WebView Java object associated
+ // with this instance.
+ jobject *retObject = static_cast<jobject*>(value);
+ *retObject = android::WebViewCore::getWebViewCore(parent())->getWebViewJavaObject();
+ return NPERR_NO_ERROR;
+ }
+
+ case kSupportedDrawingModel_ANPGetValue: {
+ uint32_t* bits = reinterpret_cast<uint32_t*>(value);
+ *bits = (1 << kBitmap_ANPDrawingModel);
+ return NPERR_NO_ERROR;
+ }
+
+ default: {
+ NPError error = NPERR_GENERIC_ERROR;
+ (void)anp_getInterface(variable, value, &error);
+ return error;
+ }
+ }
+}
+
+NPError PluginView::platformSetValue(NPPVariable variable, void* value)
+{
+ NPError error = NPERR_GENERIC_ERROR;
+
+ switch (variable) {
+ case kRequestDrawingModel_ANPSetValue: {
+ ANPDrawingModel model = reinterpret_cast<ANPDrawingModel>(value);
+ switch (model) {
+ case kBitmap_ANPDrawingModel:
+ m_window->setDrawingModel(model);
+ error = NPERR_NO_ERROR;
+ break;
+ default:
+ break;
+ }
+ }
+ default:
+ break;
+ }
+ return error;
+}
+
+void PluginView::invalidateRect(const IntRect& r)
+{
+ m_window->inval(r, true);
+}
+
+void PluginView::invalidateRect(NPRect* rect)
+{
+ IntRect r;
+
+ if (rect) {
+ r = IntRect(rect->left, rect->top,
+ rect->right - rect->left, rect->bottom - rect->top);
+ } else {
+ r = IntRect(0, 0, m_npWindow.width, m_npWindow.height);
+ }
+
+ m_window->inval(r, true);
+// android::WebViewCore::getWebViewCore(parent())->contentInvalidate(r);
+}
+
+void PluginView::invalidateRegion(NPRegion region)
+{
+ // we don't support/define regions (yet), so do nothing
+}
+
+void PluginView::forceRedraw()
+{
+ this->invalidateRect(0);
+}
+
+void PluginView::setFocus()
+{
+ Widget::setFocus();
+// SkDebugf("------------- setFocus %p\n", this);
+}
+
+void PluginView::show()
+{
+ setSelfVisible(true);
+ Widget::show();
+}
+
+void PluginView::hide()
+{
+ setSelfVisible(false);
+ Widget::hide();
+}
+
+void PluginView::paintMissingPluginIcon(GraphicsContext* context,
+ const IntRect& rect)
+{
+ static RefPtr<Image> gNullPluginImage;
+ if (!gNullPluginImage) {
+ gNullPluginImage = Image::loadPlatformResource("nullplugin");
+ }
+ Image* image = gNullPluginImage.get();
+
+ IntRect imageRect(frameRect().x(), frameRect().y(),
+ image->width(), image->height());
+
+ int xOffset = (frameRect().width() - imageRect.width()) / 2;
+ int yOffset = (frameRect().height() - imageRect.height()) / 2;
+
+ imageRect.move(xOffset, yOffset);
+
+ if (!rect.intersects(imageRect))
+ return;
+
+ context->drawImage(image, imageRect.location());
+}
+
+void PluginView::paint(GraphicsContext* context, const IntRect& rect)
+{
+ if (!m_isStarted) {
+ // Draw the "missing plugin" image
+ paintMissingPluginIcon(context, rect);
+ return;
+ }
+
+ IntRect frame = frameRect();
+ if (!frame.width() || !frame.height()) {
+ return;
+ }
+
+ m_window->inval(rect, false);
+ m_window->draw(android_gc2canvas(context));
+}
+
+// new as of SVN 38068, Nov 5 2008
+void PluginView::updatePluginWidget() const
+{
+ notImplemented();
+}
+
+// new as of SVN 38068, Nov 5 2008
+void PluginView::setParentVisible(bool) {
+ notImplemented();
+}
+
+} // namespace WebCore
+
diff --git a/WebKit/android/plugins/PluginViewBridgeAndroid.cpp b/WebKit/android/plugins/PluginViewBridgeAndroid.cpp
new file mode 100644
index 0000000..ba500da
--- /dev/null
+++ b/WebKit/android/plugins/PluginViewBridgeAndroid.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "PluginViewBridgeAndroid.h"
+
+namespace WebCore {
+
+ void PluginViewBridgeAndroid::draw(GraphicsContext* gc,
+ const IntRect& rect) {}
+
+ bool PluginViewBridgeAndroid::forPluginView() const {
+ return true;
+ }
+
+}
diff --git a/WebKit/android/plugins/PluginViewBridgeAndroid.h b/WebKit/android/plugins/PluginViewBridgeAndroid.h
new file mode 100644
index 0000000..6a5a46a
--- /dev/null
+++ b/WebKit/android/plugins/PluginViewBridgeAndroid.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Collabora Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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 APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 PluginViewBridgeAndroid_H
+#define PluginViewBridgeAndroid_H
+
+#include "PluginView.h"
+#include "WebCoreViewBridge.h"
+
+namespace WebCore {
+
+ // (Dummy for now) WebCoreViewBridge associated with a PluginView Widget.
+ class PluginViewBridgeAndroid : public WebCoreViewBridge {
+ public:
+ PluginViewBridgeAndroid() {}
+
+ // overrides
+ virtual void draw(GraphicsContext* gc, const IntRect& rect);
+ virtual bool forPluginView() const;
+ };
+
+} // namespace WebCore
+
+#endif
diff --git a/WebKit/android/plugins/PluginWidgetAndroid.cpp b/WebKit/android/plugins/PluginWidgetAndroid.cpp
new file mode 100644
index 0000000..9e28756
--- /dev/null
+++ b/WebKit/android/plugins/PluginWidgetAndroid.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include "android_graphics.h"
+#include "PluginPackage.h"
+#include "PluginView.h"
+#include "PluginWidgetAndroid.h"
+#include "SkANP.h"
+#include "SkFlipPixelRef.h"
+#include "WebViewCore.h"
+
+PluginWidgetAndroid::PluginWidgetAndroid(WebCore::PluginView* view)
+ : m_pluginView(view) {
+ m_flipPixelRef = NULL;
+ m_core = NULL;
+ m_drawingModel = kBitmap_ANPDrawingModel;
+ m_x = m_y = 0;
+}
+
+PluginWidgetAndroid::~PluginWidgetAndroid() {
+ if (m_core) {
+ m_core->removePlugin(this);
+ }
+ m_flipPixelRef->safeUnref();
+}
+
+void PluginWidgetAndroid::init(android::WebViewCore* core) {
+ m_core = core;
+ m_core->addPlugin(this);
+}
+
+static SkBitmap::Config computeConfig(bool isTransparent) {
+ return isTransparent ? SkBitmap::kARGB_8888_Config
+ : SkBitmap::kRGB_565_Config;
+}
+
+void PluginWidgetAndroid::setWindow(int x, int y, int width, int height,
+ bool isTransparent) {
+ m_x = x;
+ m_y = y;
+ m_flipPixelRef->safeUnref();
+ m_flipPixelRef = new SkFlipPixelRef(computeConfig(isTransparent),
+ width, height);
+}
+
+void PluginWidgetAndroid::setDrawingModel(ANPDrawingModel model) {
+ m_drawingModel = model;
+}
+
+void PluginWidgetAndroid::localToPageCoords(SkIRect* rect) const {
+ rect->offset(m_x, m_y);
+}
+
+bool PluginWidgetAndroid::isDirty(SkIRect* rect) const {
+ // nothing to report if we haven't had setWindow() called yet
+ if (NULL == m_flipPixelRef) {
+ return false;
+ }
+
+ const SkRegion& dirty = m_flipPixelRef->dirtyRgn();
+ if (dirty.isEmpty()) {
+ return false;
+ } else {
+ if (rect) {
+ *rect = dirty.getBounds();
+ }
+ return true;
+ }
+}
+
+void PluginWidgetAndroid::inval(const WebCore::IntRect& rect,
+ bool signalRedraw) {
+ // nothing to do if we haven't had setWindow() called yet
+ if (NULL == m_flipPixelRef) {
+ return;
+ }
+
+ SkIRect r;
+ m_flipPixelRef->inval(*android_setrect(&r, rect));
+
+ if (signalRedraw && m_flipPixelRef->isDirty()) {
+ m_core->invalPlugin(this);
+ }
+}
+
+void PluginWidgetAndroid::draw(SkCanvas* canvas) {
+ if (NULL == m_flipPixelRef || !m_flipPixelRef->isDirty()) {
+ return;
+ }
+
+ SkAutoFlipUpdate update(m_flipPixelRef);
+ const SkBitmap& bitmap = update.bitmap();
+ const SkRegion& dirty = update.dirty();
+
+ ANPEvent event;
+ SkANP::InitEvent(&event, kDraw_ANPEventType);
+
+ event.data.drawContext.model = m_drawingModel;
+ SkANP::SetRect(&event.data.drawContext.clip, dirty.getBounds());
+
+ switch (m_drawingModel) {
+ case kBitmap_ANPDrawingModel: {
+ WebCore::PluginPackage* pkg = m_pluginView->plugin();
+ NPP instance = m_pluginView->instance();
+
+ if (SkANP::SetBitmap(&event.data.drawContext.data.bitmap,
+ bitmap) &&
+ pkg->pluginFuncs()->event(instance, &event)) {
+
+ if (canvas) {
+ SkBitmap bm(bitmap);
+ bm.setPixelRef(m_flipPixelRef);
+ canvas->drawBitmap(bm, SkIntToScalar(m_x),
+ SkIntToScalar(m_y), NULL);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
diff --git a/WebKit/android/plugins/PluginWidgetAndroid.h b/WebKit/android/plugins/PluginWidgetAndroid.h
new file mode 100644
index 0000000..237b1ae
--- /dev/null
+++ b/WebKit/android/plugins/PluginWidgetAndroid.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PluginWidgetAndroid_H
+#define PluginWidgetAndroid_H
+
+#include "android_npapi.h"
+
+namespace WebCore {
+ class PluginView;
+}
+
+namespace android {
+ class WebViewCore;
+}
+
+class SkCanvas;
+class SkFlipPixelRef;
+
+/*
+ This is our extended state in a PluginView. This object is created and
+ kept insync with the PluginView, but is also available to WebViewCore
+ to allow its draw() method to be called from outside of the PluginView.
+ */
+struct PluginWidgetAndroid {
+ // initialize with our host pluginview. This will delete us when it is
+ // destroyed.
+ PluginWidgetAndroid(WebCore::PluginView* view);
+ ~PluginWidgetAndroid();
+
+ /* Can't determine our core at construction time, so PluginView calls this
+ as soon as it has a parent.
+ */
+ void init(android::WebViewCore*);
+ /* Called each time the PluginView gets a new size or position.
+ */
+ void setWindow(int x, int y, int width, int height, bool isTransparent);
+ /* Called whenever the plugin itself requests a new drawing model
+ */
+ void setDrawingModel(ANPDrawingModel);
+
+ /* Utility method to convert from local (plugin) coordinates to docuemnt
+ coordinates. Needed (for instance) to convert the dirty rectangle into
+ document coordinates to inturn inval the screen.
+ */
+ void localToPageCoords(SkIRect*) const;
+
+ /* Returns true (and optionally updates rect with the dirty bounds) if
+ the plugin has invalidate us.
+ */
+ bool isDirty(SkIRect* dirtyBounds = NULL) const;
+ /* Called by PluginView to invalidate a portion of the plugin area (in
+ local plugin coordinates). If signalRedraw is true, this also triggers
+ a subsequent call to draw(NULL).
+ */
+ void inval(const WebCore::IntRect&, bool signalRedraw);
+
+ /* Called to draw into the plugin's bitmap. If canvas is non-null, the
+ bitmap itself is then drawn into the canvas.
+ */
+ void draw(SkCanvas* canvas = NULL);
+
+private:
+ WebCore::PluginView* m_pluginView;
+ android::WebViewCore* m_core;
+ SkFlipPixelRef* m_flipPixelRef;
+ ANPDrawingModel m_drawingModel;
+ int m_x;
+ int m_y;
+};
+
+#endif
diff --git a/WebKit/android/plugins/SkANP.cpp b/WebKit/android/plugins/SkANP.cpp
new file mode 100644
index 0000000..e39d3eb
--- /dev/null
+++ b/WebKit/android/plugins/SkANP.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// must include config.h first for webkit to fiddle with new/delete
+#include "config.h"
+#include "SkANP.h"
+
+SkRect* SkANP::SetRect(SkRect* dst, const ANPRectF& src) {
+ dst->set(SkFloatToScalar(src.left),
+ SkFloatToScalar(src.top),
+ SkFloatToScalar(src.right),
+ SkFloatToScalar(src.bottom));
+ return dst;
+}
+
+SkIRect* SkANP::SetRect(SkIRect* dst, const ANPRectI& src) {
+ dst->set(src.left, src.top, src.right, src.bottom);
+ return dst;
+}
+
+ANPRectI* SkANP::SetRect(ANPRectI* dst, const SkIRect& src) {
+ dst->left = src.fLeft;
+ dst->top = src.fTop;
+ dst->right = src.fRight;
+ dst->bottom = src.fBottom;
+ return dst;
+}
+
+SkBitmap* SkANP::SetBitmap(SkBitmap* dst, const ANPBitmap& src) {
+ SkBitmap::Config config = SkBitmap::kNo_Config;
+
+ switch (src.format) {
+ case kRGBA_8888_ANPBitmapFormat:
+ config = SkBitmap::kARGB_8888_Config;
+ break;
+ case kRGB_565_ANPBitmapFormat:
+ config = SkBitmap::kRGB_565_Config;
+ break;
+ default:
+ break;
+ }
+
+ dst->setConfig(config, src.width, src.height, src.rowBytes);
+ dst->setPixels(src.baseAddr);
+ return dst;
+}
+
+bool SkANP::SetBitmap(ANPBitmap* dst, const SkBitmap& src) {
+ if (!(dst->baseAddr = src.getPixels())) {
+ SkDebugf("SkANP::SetBitmap - getPixels() returned null\n");
+ return false;
+ }
+
+ switch (src.config()) {
+ case SkBitmap::kARGB_8888_Config:
+ dst->format = kRGBA_8888_ANPBitmapFormat;
+ break;
+ case SkBitmap::kRGB_565_Config:
+ dst->format = kRGB_565_ANPBitmapFormat;
+ break;
+ default:
+ SkDebugf("SkANP::SetBitmap - unsupported src.config %d\n", src.config());
+ return false;
+ }
+
+ dst->width = src.width();
+ dst->height = src.height();
+ dst->rowBytes = src.rowBytes();
+ return true;
+}
+
+void SkANP::InitEvent(ANPEvent* event, ANPEventType et) {
+ event->inSize = sizeof(ANPEvent);
+ event->eventType = et;
+}
+
diff --git a/WebKit/android/plugins/SkANP.h b/WebKit/android/plugins/SkANP.h
new file mode 100644
index 0000000..0594c45
--- /dev/null
+++ b/WebKit/android/plugins/SkANP.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkANP_DEFINED
+#define SkANP_DEFINED
+
+#include "android_npapi.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkPath.h"
+#include "SkTypeface.h"
+
+struct ANPPath : SkPath {
+};
+
+struct ANPPaint : SkPaint {
+};
+
+struct ANPTypeface : SkTypeface {
+};
+
+struct ANPCanvas {
+ SkCanvas* skcanvas;
+
+ // draw into the specified bitmap
+ explicit ANPCanvas(const SkBitmap& bm) {
+ skcanvas = new SkCanvas(bm);
+ }
+
+ // redirect all drawing to the specific SkCanvas
+ explicit ANPCanvas(SkCanvas* other) {
+ skcanvas = other;
+ skcanvas->ref();
+ }
+
+ ~ANPCanvas() {
+ skcanvas->unref();
+ }
+};
+
+class SkANP {
+public:
+ static SkRect* SetRect(SkRect* dst, const ANPRectF& src);
+ static SkIRect* SetRect(SkIRect* dst, const ANPRectI& src);
+ static ANPRectI* SetRect(ANPRectI* dst, const SkIRect& src);
+ static SkBitmap* SetBitmap(SkBitmap* dst, const ANPBitmap& src);
+ static bool SetBitmap(ANPBitmap* dst, const SkBitmap& src);
+
+ static void InitEvent(ANPEvent* event, ANPEventType et);
+};
+
+#endif
+
diff --git a/WebKit/android/plugins/android_npapi.h b/WebKit/android/plugins/android_npapi.h
new file mode 100644
index 0000000..1640168
--- /dev/null
+++ b/WebKit/android/plugins/android_npapi.h
@@ -0,0 +1,514 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* 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 <stdint.h>
+
+#include "npapi.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// General types
+
+enum ANPBitmapFormats {
+ kUnknown_ANPBitmapFormat = 0,
+ kRGBA_8888_ANPBitmapFormat = 1,
+ kRGB_565_ANPBitmapFormat = 2
+};
+typedef int32_t ANPBitmapFormat;
+
+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 ANPPaint;
+struct ANPPath;
+struct ANPRegion;
+struct ANPTypeface;
+
+///////////////////////////////////////////////////////////////////////////////
+// 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 kPaintInterfaceV0_ANPGetValue ((NPNVariable)1003)
+#define kTypefaceInterfaceV0_ANPGetValue ((NPNVariable)1004)
+#define kWindowInterfaceV0_ANPGetValue ((NPNVariable)1005)
+
+/* queries for which drawing model is desired (for the draw event)
+
+ Should be called inside NPP_New(...)
+
+ NPN_GetValue(inst, ANPSupportedDrawingModel_EnumValue, uint32_t* bits)
+ */
+#define kSupportedDrawingModel_ANPGetValue ((NPNVariable)2000)
+
+///////////////////////////////////////////////////////////////////////////////
+// NPN_GetValue
+
+/** Reqeust to set the drawing model.
+
+ NPN_SetValue(inst, ANPRequestDrawingModel_EnumValue, (void*)foo_DrawingModel)
+ */
+#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 = 0,
+};
+typedef int32_t ANPDrawingModel;
+
+/* Interfaces provide additional functionality to the plugin via function ptrs.
+ Once an interface is retrived, 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)(NPP instance, ANPLogType, const char format[], ...);
+};
+
+typedef uint32_t ANPColor;
+#define ANP_MAKE_COLOR(a, r, g, b) \
+ (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
+
+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;
+
+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
+
+ @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*);
+};
+
+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[]);
+};
+
+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 (*clipRect)(ANPCanvas*, const ANPRectF*);
+ void (*clipPath)(ANPCanvas*, const ANPPath*);
+
+ void (*drawColor)(ANPCanvas*, ANPColor);
+ void (*drawPaint)(ANPCanvas*, 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 {
+ /** Given the window field from the NPWindow struct, and an optional rect
+ describing the subset of the window that will be drawn to (may be null)
+ return true if the bitmap for that window can be accessed, and if so,
+ fill out the specified ANPBitmap to point to the window's pixels.
+
+ When drawing is complete, call unlock(window)
+ */
+ bool (*lockRect)(void* window, const ANPRectI* inval, ANPBitmap*);
+ /** The same as lockRect, but takes a region instead of a rect to specify
+ the area that will be changed/drawn.
+ */
+ bool (*lockRegion)(void* window, const ANPRegion* inval, ANPBitmap*);
+ /** Given a successful call to lock(window, inval, &bitmap), call unlock
+ to release access to the pixels, and allow the browser to display the
+ results. If lock returned false, unlock should not be called.
+ */
+ void (*unlock)(void* window);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+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.
+ */
+ ANPAudioTrack* (*newTrack)(uint32_t sampleRate, // sampling rate in Hz
+ ANPSampleFormat,
+ int channelCount, // MONO=1, STEREO=2
+ ANPAudioCallbackProc,
+ void* user);
+ 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*);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// HandleEvent
+
+enum ANPEventTypes {
+ kNull_ANPEventType = 0,
+ kKey_ANPEventType = 1,
+ kTouch_ANPEventType = 2,
+ kDraw_ANPEventType = 3,
+};
+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 ANPTouchActions {
+ kDown_ANPTouchAction = 0,
+ kUp_ANPTouchAction = 1,
+};
+typedef int32_t ANPTouchAction;
+
+struct ANPDrawContext {
+ 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;
+};
+
+/* 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 {
+ ANPTouchAction action;
+ ANPKeyModifier modifiers;
+ int32_t x; // relative to your "window" (0...width)
+ int32_t y; // relative to your "window" (0...height)
+ } touch;
+ ANPDrawContext drawContext;
+ int32_t other[8];
+ } data;
+};
+
+#endif
+
diff --git a/WebKit/android/plugins/sample/Android.mk b/WebKit/android/plugins/sample/Android.mk
new file mode 100644
index 0000000..a2f7747
--- /dev/null
+++ b/WebKit/android/plugins/sample/Android.mk
@@ -0,0 +1,41 @@
+##
+##
+## Copyright 2008, The Android Open Source Project
+##
+## Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+##
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ main.cpp \
+ PluginObject.cpp \
+ pluginGraphics.cpp
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH) \
+ external/webkit/WebCore/bridge \
+ external/webkit/WebCore/plugins \
+ external/webkit/WebCore/platform/android/JavaVM \
+ external/webkit/WebKit/android/plugins
+
+LOCAL_SRC_FILES := $(LOCAL_SRC_FILES)
+LOCAL_CFLAGS += -fvisibility=hidden
+LOCAL_PRELINK_MODULE:=false
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+
+LOCAL_MODULE:= browsertestplugin
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/WebKit/android/plugins/sample/PluginObject.cpp b/WebKit/android/plugins/sample/PluginObject.cpp
new file mode 100644
index 0000000..5499072
--- /dev/null
+++ b/WebKit/android/plugins/sample/PluginObject.cpp
@@ -0,0 +1,178 @@
+/*
+ IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in
+ consideration of your agreement to the following terms, and your use, installation,
+ modification or redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject to these
+ terms, Apple grants you a personal, non-exclusive license, under AppleÕs copyrights in
+ this original Apple software (the "Apple Software"), to use, reproduce, modify and
+ redistribute the Apple Software, with or without modifications, in source and/or binary
+ forms; provided that if you redistribute the Apple Software in its entirety and without
+ modifications, you must retain this notice and the following text and disclaimers in all
+ such redistributions of the Apple Software. Neither the name, trademarks, service marks
+ or logos of Apple Computer, Inc. may be used to endorse or promote products derived from
+ the Apple Software without specific prior written permission from Apple. Except as expressly
+ stated in this notice, no other rights or licenses, express or implied, are granted by Apple
+ herein, including but not limited to any patent rights that may be infringed by your
+ derivative works or by other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES,
+ EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS
+ USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE,
+ REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND
+ WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
+ OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include "main.h"
+#include "PluginObject.h"
+
+static void pluginInvalidate(NPObject *obj);
+static bool pluginHasProperty(NPObject *obj, NPIdentifier name);
+static bool pluginHasMethod(NPObject *obj, NPIdentifier name);
+static bool pluginGetProperty(NPObject *obj, NPIdentifier name, NPVariant *variant);
+static bool pluginSetProperty(NPObject *obj, NPIdentifier name, const NPVariant *variant);
+static bool pluginInvoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);
+static bool pluginInvokeDefault(NPObject *obj, const NPVariant *args, uint32_t argCount, NPVariant *result);
+static NPObject *pluginAllocate(NPP npp, NPClass *theClass);
+static void pluginDeallocate(NPObject *obj);
+static bool pluginRemoveProperty(NPObject *npobj, NPIdentifier name);
+static bool pluginEnumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count);
+
+
+
+static NPClass pluginClass = {
+ NP_CLASS_STRUCT_VERSION,
+ pluginAllocate,
+ pluginDeallocate,
+ pluginInvalidate,
+ pluginHasMethod,
+ pluginInvoke,
+ pluginInvokeDefault,
+ pluginHasProperty,
+ pluginGetProperty,
+ pluginSetProperty,
+ pluginRemoveProperty,
+ pluginEnumerate
+};
+
+NPClass *getPluginClass(void)
+{
+ return &pluginClass;
+}
+
+static bool identifiersInitialized = false;
+
+#define ID_TESTFILE_PROPERTY 0
+#define NUM_PROPERTY_IDENTIFIERS 1
+
+static NPIdentifier pluginPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS];
+static const NPUTF8 *pluginPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = {
+ "testfile"
+};
+
+#define ID_GETTESTFILE_METHOD 0
+#define NUM_METHOD_IDENTIFIERS 1
+
+static NPIdentifier pluginMethodIdentifiers[NUM_METHOD_IDENTIFIERS];
+static const NPUTF8 *pluginMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = {
+ "getTestFile"
+};
+
+static void initializeIdentifiers(void)
+{
+ browser->getstringidentifiers(pluginPropertyIdentifierNames, NUM_PROPERTY_IDENTIFIERS, pluginPropertyIdentifiers);
+ browser->getstringidentifiers(pluginMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, pluginMethodIdentifiers);
+}
+
+static bool pluginHasProperty(NPObject *obj, NPIdentifier name)
+{
+ int i;
+ for (i = 0; i < NUM_PROPERTY_IDENTIFIERS; i++)
+ if (name == pluginPropertyIdentifiers[i])
+ return true;
+ return false;
+}
+
+static bool pluginHasMethod(NPObject *obj, NPIdentifier name)
+{
+ int i;
+ for (i = 0; i < NUM_METHOD_IDENTIFIERS; i++)
+ if (name == pluginMethodIdentifiers[i])
+ return true;
+ return false;
+}
+
+static bool pluginGetProperty(NPObject *obj, NPIdentifier name, NPVariant *variant)
+{
+ PluginObject *plugin = (PluginObject *)obj;
+ if (name == pluginPropertyIdentifiers[ID_TESTFILE_PROPERTY]) {
+ BOOLEAN_TO_NPVARIANT(true, *variant);
+ return true;
+ }
+ return false;
+}
+
+static bool pluginSetProperty(NPObject *obj, NPIdentifier name, const NPVariant *variant)
+{
+ return false;
+}
+
+static bool pluginInvoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result)
+{
+ PluginObject *plugin = (PluginObject *)obj;
+ if (name == pluginMethodIdentifiers[ID_GETTESTFILE_METHOD]) {
+ return true;
+ }
+ return false;
+}
+
+static bool pluginInvokeDefault(NPObject *obj, const NPVariant *args, uint32_t argCount, NPVariant *result)
+{
+ return false;
+}
+
+static void pluginInvalidate(NPObject *obj)
+{
+ // Release any remaining references to JavaScript objects.
+}
+
+static NPObject *pluginAllocate(NPP npp, NPClass *theClass)
+{
+ PluginObject *newInstance = (PluginObject*) malloc(sizeof(PluginObject));
+ newInstance->header._class = theClass;
+ newInstance->header.referenceCount = 1;
+
+ if (!identifiersInitialized) {
+ identifiersInitialized = true;
+ initializeIdentifiers();
+ }
+
+ newInstance->npp = npp;
+
+ return &newInstance->header;
+}
+
+static void pluginDeallocate(NPObject *obj)
+{
+ free(obj);
+}
+
+static bool pluginRemoveProperty(NPObject *npobj, NPIdentifier name)
+{
+ return false;
+}
+
+static bool pluginEnumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count)
+{
+ return false;
+}
+
diff --git a/WebKit/android/plugins/sample/PluginObject.h b/WebKit/android/plugins/sample/PluginObject.h
new file mode 100644
index 0000000..ae8963d
--- /dev/null
+++ b/WebKit/android/plugins/sample/PluginObject.h
@@ -0,0 +1,70 @@
+/*
+ IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in
+ consideration of your agreement to the following terms, and your use, installation,
+ modification or redistribution of this Apple software constitutes acceptance of these
+ terms. If you do not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and subject to these
+ terms, Apple grants you a personal, non-exclusive license, under AppleÕs copyrights in
+ this original Apple software (the "Apple Software"), to use, reproduce, modify and
+ redistribute the Apple Software, with or without modifications, in source and/or binary
+ forms; provided that if you redistribute the Apple Software in its entirety and without
+ modifications, you must retain this notice and the following text and disclaimers in all
+ such redistributions of the Apple Software. Neither the name, trademarks, service marks
+ or logos of Apple Computer, Inc. may be used to endorse or promote products derived from
+ the Apple Software without specific prior written permission from Apple. Except as expressly
+ stated in this notice, no other rights or licenses, express or implied, are granted by Apple
+ herein, including but not limited to any patent rights that may be infringed by your
+ derivative works or by other works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES,
+ EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS
+ USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE,
+ REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND
+ WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
+ OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PluginObject__DEFINED
+#define PluginObject__DEFINED
+
+#include "npapi.h"
+
+struct ANPCanvas;
+struct ANPAudioTrack;
+
+class Animation {
+public:
+ Animation(NPP inst) : m_inst(inst) {}
+ virtual ~Animation() {}
+ virtual void draw(ANPCanvas*) = 0;
+
+ NPP inst() const { return m_inst; }
+
+private:
+ NPP m_inst;
+};
+
+typedef struct PluginObject {
+ NPObject header;
+ NPP npp;
+ NPWindow* window;
+ Animation* anim;
+ ANPAudioTrack* track;
+ int32_t mUnichar;
+
+ bool mTestTimers;
+ uint32_t mStartTime;
+ uint32_t mPrevTime;
+ int mTimerCount;
+} PluginObject;
+
+NPClass *getPluginClass(void);
+
+#endif // PluginObject__DEFINED
diff --git a/WebKit/android/plugins/sample/main.cpp b/WebKit/android/plugins/sample/main.cpp
new file mode 100644
index 0000000..5d2b0b8
--- /dev/null
+++ b/WebKit/android/plugins/sample/main.cpp
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "main.h"
+#include "PluginObject.h"
+#include "pluginGraphics.h"
+#include "android_npapi.h"
+
+NPNetscapeFuncs* browser;
+#define EXPORT __attribute__((visibility("default")))
+
+NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
+ char* argn[], char* argv[], NPSavedData* saved);
+NPError NPP_Destroy(NPP instance, NPSavedData** save);
+NPError NPP_SetWindow(NPP instance, NPWindow* window);
+NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream,
+ NPBool seekable, uint16* stype);
+NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason);
+int32 NPP_WriteReady(NPP instance, NPStream* stream);
+int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len,
+ void* buffer);
+void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname);
+void NPP_Print(NPP instance, NPPrint* platformPrint);
+int16 NPP_HandleEvent(NPP instance, void* event);
+void NPP_URLNotify(NPP instance, const char* URL, NPReason reason,
+ void* notifyData);
+NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value);
+NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value);
+
+extern "C" {
+EXPORT NPError NP_Initialize(NPNetscapeFuncs* browserFuncs, NPPluginFuncs* pluginFuncs, void *java_env, void *application_context);
+EXPORT NPError NP_GetValue(NPP instance, NPPVariable variable, void *value);
+EXPORT const char* NP_GetMIMEDescription(void);
+EXPORT void NP_Shutdown(void);
+};
+
+ANPAudioTrackInterfaceV0 gSoundI;
+ANPCanvasInterfaceV0 gCanvasI;
+ANPLogInterfaceV0 gLogI;
+ANPPaintInterfaceV0 gPaintI;
+ANPTypefaceInterfaceV0 gTypefaceI;
+
+#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0]))
+
+NPError NP_Initialize(NPNetscapeFuncs* browserFuncs, NPPluginFuncs* pluginFuncs, void *java_env, void *application_context)
+{
+ // Make sure we have a function table equal or larger than we are built against.
+ if (browserFuncs->size < sizeof(NPNetscapeFuncs)) {
+ return NPERR_GENERIC_ERROR;
+ }
+
+ // Copy the function table (structure)
+ browser = (NPNetscapeFuncs*) malloc(sizeof(NPNetscapeFuncs));
+ memcpy(browser, browserFuncs, sizeof(NPNetscapeFuncs));
+
+ // Build the plugin function table
+ pluginFuncs->version = 11;
+ pluginFuncs->size = sizeof(pluginFuncs);
+ pluginFuncs->newp = NPP_New;
+ pluginFuncs->destroy = NPP_Destroy;
+ pluginFuncs->setwindow = NPP_SetWindow;
+ pluginFuncs->newstream = NPP_NewStream;
+ pluginFuncs->destroystream = NPP_DestroyStream;
+ pluginFuncs->asfile = NPP_StreamAsFile;
+ pluginFuncs->writeready = NPP_WriteReady;
+ pluginFuncs->write = (NPP_WriteProcPtr)NPP_Write;
+ pluginFuncs->print = NPP_Print;
+ pluginFuncs->event = NPP_HandleEvent;
+ pluginFuncs->urlnotify = NPP_URLNotify;
+ pluginFuncs->getvalue = NPP_GetValue;
+ pluginFuncs->setvalue = NPP_SetValue;
+
+ static const struct {
+ NPNVariable v;
+ uint32_t size;
+ ANPInterface* i;
+ } gPairs[] = {
+ { kLogInterfaceV0_ANPGetValue, sizeof(gLogI), &gLogI },
+ { kCanvasInterfaceV0_ANPGetValue, sizeof(gCanvasI), &gCanvasI },
+ { kPaintInterfaceV0_ANPGetValue, sizeof(gPaintI), &gPaintI },
+ { kTypefaceInterfaceV0_ANPGetValue, sizeof(gPaintI), &gTypefaceI },
+ { kAudioTrackInterfaceV0_ANPGetValue, sizeof(gSoundI), &gSoundI },
+ };
+ for (size_t i = 0; i < ARRAY_COUNT(gPairs); i++) {
+ gPairs[i].i->inSize = gPairs[i].size;
+ NPError err = browser->getvalue(NULL, gPairs[i].v, gPairs[i].i);
+ if (err) {
+ return err;
+ }
+ }
+
+ return NPERR_NO_ERROR;
+}
+
+void NP_Shutdown(void)
+{
+
+}
+
+const char *NP_GetMIMEDescription(void)
+{
+ return "application/x-testplugin:tst:Test plugin mimetype is application/x-testplugin";
+}
+
+NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
+ char* argn[], char* argv[], NPSavedData* saved)
+{
+ PluginObject *obj = NULL;
+
+ // Scripting functions appeared in NPAPI version 14
+ if (browser->version >= 14) {
+ instance->pdata = browser->createobject (instance, getPluginClass());
+ obj = static_cast<PluginObject*>(instance->pdata);
+ bzero(obj, sizeof(*obj));
+ }
+
+ uint32_t bits;
+ NPError err = browser->getvalue(instance, kSupportedDrawingModel_ANPGetValue, &bits);
+ if (err) {
+ gLogI.log(instance, kError_ANPLogType, "supported model err %d", err);
+ return err;
+ }
+
+ ANPDrawingModel model = kBitmap_ANPDrawingModel;
+
+ int count = argc;
+ for (int i = 0; i < count; i++) {
+ if (!strcmp(argn[i], "DrawingModel")) {
+ if (!strcmp(argv[i], "Bitmap")) {
+ model = kBitmap_ANPDrawingModel;
+ }
+ if (!strcmp(argv[i], "Canvas")) {
+ // obj->mTestTimers = true;
+ }
+ gLogI.log(instance, kDebug_ANPLogType, "------ %p DrawingModel is %d", instance, model);
+ break;
+ }
+ }
+
+ // comment this out to draw via bitmaps (the default)
+ err = browser->setvalue(instance, kRequestDrawingModel_ANPSetValue,
+ reinterpret_cast<void*>(model));
+ if (err) {
+ gLogI.log(instance, kError_ANPLogType, "request model %d err %d", model, err);
+ }
+ return err;
+}
+
+NPError NPP_Destroy(NPP instance, NPSavedData** save)
+{
+ PluginObject *obj = (PluginObject*) instance->pdata;
+ delete obj->anim;
+ gSoundI.deleteTrack(obj->track);
+
+ return NPERR_NO_ERROR;
+}
+
+static void timer_oneshot(NPP instance, uint32 timerID) {
+ gLogI.log(instance, kDebug_ANPLogType, "-------- oneshot timer\n");
+}
+
+static int gTimerRepeatCount;
+static void timer_repeat(NPP instance, uint32 timerID) {
+
+ gLogI.log(instance, kDebug_ANPLogType, "-------- repeat timer %d\n",
+ gTimerRepeatCount);
+ if (--gTimerRepeatCount == 0) {
+ browser->unscheduletimer(instance, timerID);
+ }
+}
+
+static void timer_neverfires(NPP instance, uint32 timerID) {
+ gLogI.log(instance, kError_ANPLogType, "-------- timer_neverfires!!!\n");
+}
+
+#define TIMER_INTERVAL 50
+
+static void timer_latency(NPP instance, uint32 timerID) {
+ PluginObject *obj = (PluginObject*) instance->pdata;
+
+ obj->mTimerCount += 1;
+
+ uint32_t now = getMSecs();
+ uint32_t interval = now - obj->mPrevTime;
+
+ uint32_t dur = now - obj->mStartTime;
+ uint32_t expectedDur = obj->mTimerCount * TIMER_INTERVAL;
+ int32_t drift = dur - expectedDur;
+ int32_t aveDrift = drift / obj->mTimerCount;
+
+ obj->mPrevTime = now;
+
+ gLogI.log(instance, kDebug_ANPLogType,
+ "-------- latency test: [%3d] interval %d expected %d, total %d expected %d, drift %d ave %d\n",
+ obj->mTimerCount, interval, TIMER_INTERVAL, dur, expectedDur,
+ drift, aveDrift);
+}
+
+NPError NPP_SetWindow(NPP instance, NPWindow* window)
+{
+ PluginObject *obj = (PluginObject*) instance->pdata;
+
+ // Do nothing if browser didn't support NPN_CreateObject which would have created the PluginObject.
+ if (obj != NULL) {
+ obj->window = window;
+ }
+
+ static bool gTestTimers;
+ if (!gTestTimers) {
+ gTestTimers = true;
+ // test for bogus timerID
+ browser->unscheduletimer(instance, 999999);
+ // test oneshot
+ browser->scheduletimer(instance, 100, false, timer_oneshot);
+ // test repeat
+ gTimerRepeatCount = 10;
+ browser->scheduletimer(instance, 50, true, timer_repeat);
+ // test unschedule immediately
+ uint32 id = browser->scheduletimer(instance, 100, false, timer_neverfires);
+ browser->unscheduletimer(instance, id);
+ // test double unschedlue (should be no-op)
+ browser->unscheduletimer(instance, id);
+ }
+
+ if (obj->mTestTimers) {
+ browser->scheduletimer(instance, TIMER_INTERVAL, true, timer_latency);
+ obj->mStartTime = obj->mPrevTime = getMSecs();
+ obj->mTestTimers = false;
+ }
+
+ browser->invalidaterect(instance, NULL);
+
+ return NPERR_NO_ERROR;
+}
+
+
+NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype)
+{
+ *stype = NP_ASFILEONLY;
+ return NPERR_NO_ERROR;
+}
+
+NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason)
+{
+ return NPERR_NO_ERROR;
+}
+
+int32 NPP_WriteReady(NPP instance, NPStream* stream)
+{
+ return 0;
+}
+
+int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer)
+{
+ return 0;
+}
+
+void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname)
+{
+}
+
+void NPP_Print(NPP instance, NPPrint* platformPrint)
+{
+
+}
+
+struct SoundPlay {
+ NPP instance;
+ ANPAudioTrack* track;
+ FILE* file;
+};
+
+static void audioCallback(ANPAudioEvent evt, void* user, ANPAudioBuffer* buffer) {
+ switch (evt) {
+ case kMoreData_ANPAudioEvent: {
+ SoundPlay* play = reinterpret_cast<SoundPlay*>(user);
+ size_t amount = fread(buffer->bufferData, 1, buffer->size, play->file);
+ buffer->size = amount;
+ if (amount == 0) {
+ gSoundI.stop(play->track);
+ fclose(play->file);
+ play->file = NULL;
+ // need to notify our main thread to delete the track now
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static ANPAudioTrack* createTrack(NPP instance, const char path[]) {
+ FILE* f = fopen(path, "r");
+ gLogI.log(instance, kWarning_ANPLogType, "--- path %s FILE %p", path, f);
+ if (NULL == f) {
+ return NULL;
+ }
+ SoundPlay* play = new SoundPlay;
+ play->file = f;
+ play->track = gSoundI.newTrack(44100, kPCM16Bit_ANPSampleFormat, 2, audioCallback, play);
+ if (NULL == play->track) {
+ fclose(f);
+ delete play;
+ return NULL;
+ }
+ return play->track;
+}
+
+int16 NPP_HandleEvent(NPP instance, void* event)
+{
+ PluginObject *obj = reinterpret_cast<PluginObject*>(instance->pdata);
+ const ANPEvent* evt = reinterpret_cast<const ANPEvent*>(event);
+
+ switch (evt->eventType) {
+ case kDraw_ANPEventType:
+ switch (evt->data.drawContext.model) {
+ case kBitmap_ANPDrawingModel:
+ drawPlugin(instance, evt->data.drawContext.data.bitmap,
+ evt->data.drawContext.clip);
+ return 1;
+ default:
+ break; // unknown drawing model
+ }
+
+ case kKey_ANPEventType:
+ gLogI.log(instance, kDebug_ANPLogType, "---- %p Key action=%d"
+ " code=%d vcode=%d unichar=%d repeat=%d mods=%x", instance,
+ evt->data.key.action,
+ evt->data.key.nativeCode,
+ evt->data.key.virtualCode,
+ evt->data.key.unichar,
+ evt->data.key.repeatCount,
+ evt->data.key.modifiers);
+ if (evt->data.key.action == kDown_ANPKeyAction) {
+ obj->mUnichar = evt->data.key.unichar;
+ }
+ return 1;
+
+ case kTouch_ANPEventType:
+ gLogI.log(instance, kDebug_ANPLogType, "---- %p Touch action=%d [%d %d]",
+ instance, evt->data.touch.action, evt->data.touch.x,
+ evt->data.touch.y);
+ if (kUp_ANPTouchAction == evt->data.touch.action) {
+ if (obj->track) {
+ if (gSoundI.isStopped(obj->track)) {
+ gSoundI.start(obj->track);
+ } else {
+ gSoundI.pause(obj->track);
+ }
+ } else {
+ obj->track = createTrack(instance, "/sdcard/sample.snd");
+ gLogI.log(instance, kDebug_ANPLogType, "track %p %d",
+ obj->track, gSoundI.isStopped(obj->track));
+ gSoundI.start(obj->track);
+ gLogI.log(instance, kDebug_ANPLogType, "track %p %d",
+ obj->track, gSoundI.isStopped(obj->track));
+ }
+ }
+ return 1;
+
+ default:
+ break;
+ }
+ return 0; // unknown or unhandled event
+}
+
+void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData)
+{
+
+}
+
+EXPORT NPError NP_GetValue(NPP instance, NPPVariable variable, void *value) {
+
+ if (variable == NPPVpluginNameString) {
+ const char **str = (const char **)value;
+ *str = "Test Plugin";
+ return NPERR_NO_ERROR;
+ }
+
+ if (variable == NPPVpluginDescriptionString) {
+ const char **str = (const char **)value;
+ *str = "Description of Test Plugin";
+ return NPERR_NO_ERROR;
+ }
+
+ return NPERR_GENERIC_ERROR;
+}
+
+NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value)
+{
+ if (variable == NPPVpluginScriptableNPObject) {
+ void **v = (void **)value;
+ PluginObject *obj = (PluginObject*) instance->pdata;
+
+ if (obj)
+ browser->retainobject((NPObject*)obj);
+
+ *v = obj;
+ return NPERR_NO_ERROR;
+ }
+
+ return NPERR_GENERIC_ERROR;
+}
+
+NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value)
+{
+ return NPERR_GENERIC_ERROR;
+}
+
diff --git a/WebKit/android/plugins/sample/main.h b/WebKit/android/plugins/sample/main.h
new file mode 100644
index 0000000..5add14d
--- /dev/null
+++ b/WebKit/android/plugins/sample/main.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <npapi.h>
+#include <npfunctions.h>
+#include <npruntime.h>
+
+extern NPNetscapeFuncs* browser;
diff --git a/WebKit/android/plugins/sample/pluginGraphics.cpp b/WebKit/android/plugins/sample/pluginGraphics.cpp
new file mode 100644
index 0000000..0ea6efe
--- /dev/null
+++ b/WebKit/android/plugins/sample/pluginGraphics.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "pluginGraphics.h"
+
+#include "android_npapi.h"
+#include <stdio.h>
+#include <sys/time.h>
+#include <time.h>
+#include <math.h>
+#include <string.h>
+
+extern NPNetscapeFuncs* browser;
+extern ANPLogInterfaceV0 gLogI;
+extern ANPCanvasInterfaceV0 gCanvasI;
+extern ANPPaintInterfaceV0 gPaintI;
+extern ANPTypefaceInterfaceV0 gTypefaceI;
+
+static void inval(NPP instance) {
+ browser->invalidaterect(instance, NULL);
+}
+
+static uint16 rnd16(float x, int inset) {
+ int ix = (int)roundf(x) + inset;
+ if (ix < 0) {
+ ix = 0;
+ }
+ return static_cast<uint16>(ix);
+}
+
+static void inval(NPP instance, const ANPRectF& r, bool doAA) {
+ const int inset = doAA ? -1 : 0;
+
+ PluginObject *obj = reinterpret_cast<PluginObject*>(instance->pdata);
+ NPRect inval;
+ inval.left = rnd16(r.left, inset);
+ inval.top = rnd16(r.top, inset);
+ inval.right = rnd16(r.right, -inset);
+ inval.bottom = rnd16(r.bottom, -inset);
+ browser->invalidaterect(instance, &inval);
+}
+
+uint32_t getMSecs() {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (uint32_t) (tv.tv_sec * 1000 + tv.tv_usec / 1000 ); // microseconds to milliseconds
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+class BallAnimation : public Animation {
+public:
+ BallAnimation(NPP inst);
+ virtual ~BallAnimation();
+ virtual void draw(ANPCanvas*);
+private:
+ float m_x;
+ float m_y;
+ float m_dx;
+ float m_dy;
+
+ ANPRectF m_oval;
+ ANPPaint* m_paint;
+
+ static const float SCALE = 0.1;
+};
+
+BallAnimation::BallAnimation(NPP inst) : Animation(inst) {
+ m_x = m_y = 0;
+ m_dx = 7 * SCALE;
+ m_dy = 5 * SCALE;
+
+ memset(&m_oval, 0, sizeof(m_oval));
+
+ m_paint = gPaintI.newPaint();
+ gPaintI.setFlags(m_paint, gPaintI.getFlags(m_paint) | kAntiAlias_ANPPaintFlag);
+ gPaintI.setColor(m_paint, 0xFFFF0000);
+ gPaintI.setTextSize(m_paint, 24);
+
+ ANPTypeface* tf = gTypefaceI.createFromName("serif", kItalic_ANPTypefaceStyle);
+ gPaintI.setTypeface(m_paint, tf);
+ gTypefaceI.unref(tf);
+}
+
+BallAnimation::~BallAnimation() {
+ gPaintI.deletePaint(m_paint);
+}
+
+static void bounce(float* x, float* dx, const float max) {
+ *x += *dx;
+ if (*x < 0) {
+ *x = 0;
+ if (*dx < 0) {
+ *dx = -*dx;
+ }
+ } else if (*x > max) {
+ *x = max;
+ if (*dx > 0) {
+ *dx = -*dx;
+ }
+ }
+}
+
+void BallAnimation::draw(ANPCanvas* canvas) {
+ NPP instance = this->inst();
+ PluginObject *obj = (PluginObject*) instance->pdata;
+ const float OW = 20;
+ const float OH = 20;
+
+ inval(instance, m_oval, true); // inval the old
+ m_oval.left = m_x;
+ m_oval.top = m_y;
+ m_oval.right = m_x + OW;
+ m_oval.bottom = m_y + OH;
+ inval(instance, m_oval, true); // inval the new
+
+ gCanvasI.drawColor(canvas, 0xFFFFFFFF);
+
+ gPaintI.setColor(m_paint, 0xFFFF0000);
+ gCanvasI.drawOval(canvas, &m_oval, m_paint);
+
+ bounce(&m_x, &m_dx, obj->window->width - OW);
+ bounce(&m_y, &m_dy, obj->window->height - OH);
+
+ if (obj->mUnichar) {
+ gPaintI.setColor(m_paint, 0xFF0000FF);
+ char c = static_cast<char>(obj->mUnichar);
+ gCanvasI.drawText(canvas, &c, 1, 10, 30, m_paint);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void drawPlugin(NPP instance, const ANPBitmap& bitmap, const ANPRectI& clip) {
+ ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap);
+
+ ANPRectF clipR;
+ clipR.left = clip.left;
+ clipR.top = clip.top;
+ clipR.right = clip.right;
+ clipR.bottom = clip.bottom;
+ gCanvasI.clipRect(canvas, &clipR);
+
+ drawPlugin(instance, canvas);
+
+ gCanvasI.deleteCanvas(canvas);
+}
+
+void drawPlugin(NPP instance, ANPCanvas* canvas) {
+ PluginObject *obj = (PluginObject*) instance->pdata;
+ if (obj->anim == NULL) {
+ obj->anim = new BallAnimation(instance);
+ }
+ obj->anim->draw(canvas);
+}
+
diff --git a/WebKit/android/plugins/sample/pluginGraphics.h b/WebKit/android/plugins/sample/pluginGraphics.h
new file mode 100644
index 0000000..6dd74ff
--- /dev/null
+++ b/WebKit/android/plugins/sample/pluginGraphics.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "main.h" // for NPAPI definitions
+#include "PluginObject.h"
+
+#ifndef pluginGraphics__DEFINED
+#define pluginGraphics__DEFINED
+
+struct ANPBitmap;
+struct ANPCanvas;
+struct ANPRectI;
+
+void drawPlugin(NPP instance, const ANPBitmap& bitmap, const ANPRectI& clip);
+void drawPlugin(NPP instance, ANPCanvas*);
+uint32_t getMSecs();
+
+#endif // pluginGraphics__DEFINED