diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:05:15 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:05:15 -0800 |
commit | 1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353 (patch) | |
tree | 4457a7306ea5acb43fe05bfe0973b1f7faf97ba2 /WebKit/android/plugins | |
parent | 9364f22aed35e1a1e9d07c121510f80be3ab0502 (diff) | |
download | external_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')
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 |