2 * Copyright 2009, The Android Open Source Project
3 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #define LOG_TAG "WebCore"
29 #include "PluginView.h"
33 #include "EventNames.h"
34 #include "FrameLoader.h"
35 #include "FrameLoadRequest.h"
36 #include "FrameTree.h"
38 #include "FrameView.h"
39 #include "GraphicsContext.h"
40 #include "HTMLNames.h"
41 #include "HTMLPlugInElement.h"
43 #include "KeyboardEvent.h"
44 #include "MIMETypeRegistry.h"
45 #include "MouseEvent.h"
46 #include "NetworkStateNotifier.h"
47 #include "NotImplemented.h"
49 #include "PlatformGraphicsContext.h"
50 #include "PlatformKeyboardEvent.h"
51 #include "PluginMainThreadScheduler.h"
52 #include "PluginPackage.h"
53 #include "TouchEvent.h"
54 #include "android_graphics.h"
56 #include "npruntime_impl.h"
57 // #include "runtime_root.h"
58 #include "utils/SystemClock.h"
59 #include "ScriptController.h"
63 #include <runtime/JSLock.h>
66 #include <wtf/ASCIICType.h>
67 // #include "runtime.h"
68 #include "WebViewCore.h"
70 #include "PluginDebug.h"
71 #include "PluginDebugAndroid.h"
72 #include "PluginViewBridgeAndroid.h"
73 #include "PluginWidgetAndroid.h"
75 #include "android_npapi.h"
76 #include "ANPSurface_npapi.h"
78 #include "SkFlipPixelRef.h"
80 ///////////////////////////////////////////////////////////////////////////////
82 extern void ANPAudioTrackInterfaceV0_Init(ANPInterface* value);
83 extern void ANPBitmapInterfaceV0_Init(ANPInterface* value);
84 extern void ANPCanvasInterfaceV0_Init(ANPInterface* value);
85 extern void ANPLogInterfaceV0_Init(ANPInterface* value);
86 extern void ANPMatrixInterfaceV0_Init(ANPInterface* value);
87 extern void ANPOffscreenInterfaceV0_Init(ANPInterface* value);
88 extern void ANPPaintInterfaceV0_Init(ANPInterface* value);
89 extern void ANPPathInterfaceV0_Init(ANPInterface* value);
90 extern void ANPSurfaceInterfaceV0_Init(ANPInterface* value);
91 extern void ANPTypefaceInterfaceV0_Init(ANPInterface* value);
92 extern void ANPWindowInterfaceV0_Init(ANPInterface* value);
93 extern void ANPSystemInterfaceV0_Init(ANPInterface* value);
98 void (*proc)(ANPInterface*);
101 #define VARPROCLINE(name) \
102 k##name##_ANPGetValue, sizeof(ANP##name), ANP##name##_Init
104 static const VarProcPair gVarProcs[] = {
105 { VARPROCLINE(AudioTrackInterfaceV0) },
106 { VARPROCLINE(BitmapInterfaceV0) },
107 { VARPROCLINE(CanvasInterfaceV0) },
108 { VARPROCLINE(LogInterfaceV0) },
109 { VARPROCLINE(MatrixInterfaceV0) },
110 { VARPROCLINE(PaintInterfaceV0) },
111 { VARPROCLINE(PathInterfaceV0) },
112 { VARPROCLINE(SurfaceInterfaceV0) },
113 { VARPROCLINE(TypefaceInterfaceV0) },
114 { VARPROCLINE(WindowInterfaceV0) },
115 { VARPROCLINE(SystemInterfaceV0) },
118 /* return true if var was an interface request (error will be set accordingly)
119 return false if var is not a recognized interface (and ignore error param)
121 static bool anp_getInterface(NPNVariable var, void* value, NPError* error) {
122 const VarProcPair* iter = gVarProcs;
123 const VarProcPair* stop = gVarProcs + SK_ARRAY_COUNT(gVarProcs);
124 while (iter < stop) {
125 if (iter->enumValue == var) {
126 ANPInterface* i = reinterpret_cast<ANPInterface*>(value);
127 if (i->inSize < iter->size) {
128 SkDebugf("------- interface %d, expected size %d, allocated %d\n",
129 var, iter->size, i->inSize);
130 *error = NPERR_INCOMPATIBLE_VERSION_ERROR;
133 *error = NPERR_NO_ERROR;
139 SkDebugf("------ unknown NPNVariable %d\n", var);
143 ///////////////////////////////////////////////////////////////////////////////
151 using namespace HTMLNames;
153 void PluginView::platformInit()
155 setPlatformWidget(new PluginViewBridgeAndroid());
157 m_isWindowed = false; // we don't support windowed yet
159 m_window = new PluginWidgetAndroid(this);
161 m_npWindow.type = NPWindowTypeDrawable;
162 m_npWindow.window = 0;
165 void PluginView::platformStart()
170 PluginView::~PluginView()
174 deleteAllValues(m_requests);
176 freeStringArray(m_paramNames, m_paramCount);
177 freeStringArray(m_paramValues, m_paramCount);
179 m_parentFrame->script()->cleanupScriptObjectsForPlugin(this);
181 // Since we have no legacy plugins to check, we ignore the quirks check
182 // if (m_plugin && !m_plugin->quirks().contains(PluginQuirkDontUnloadPlugin))
189 void PluginView::init()
191 if (m_haveInitialized)
193 m_haveInitialized = true;
195 android::WebViewCore* c = android::WebViewCore::getWebViewCore(this->parent());
199 ASSERT(m_status == PluginStatusCanNotFindPlugin);
203 if (!m_plugin->load()) {
205 m_status = PluginStatusCanNotLoadPlugin;
210 m_status = PluginStatusCanNotLoadPlugin;
214 m_status = PluginStatusLoadedSuccessfully;
217 void PluginView::handleTouchEvent(TouchEvent* event)
219 if (!m_window->isAcceptingEvent(kTouch_ANPEventFlag))
223 SkANP::InitEvent(&evt, kTouch_ANPEventType);
225 const AtomicString& type = event->type();
226 if (eventNames().touchstartEvent == type)
227 evt.data.touch.action = kDown_ANPTouchAction;
228 else if (eventNames().touchendEvent == type)
229 evt.data.touch.action = kUp_ANPTouchAction;
230 else if (eventNames().touchmoveEvent == type)
231 evt.data.touch.action = kMove_ANPTouchAction;
232 else if (eventNames().touchcancelEvent == type)
233 evt.data.touch.action = kCancel_ANPTouchAction;
237 evt.data.touch.modifiers = 0; // todo
239 // convert to coordinates that are relative to the plugin. The pageX / pageY
240 // values are the only values in the event that are consistently in frame
241 // coordinates despite their misleading name.
242 evt.data.touch.x = event->pageX() - m_npWindow.x;
243 evt.data.touch.y = event->pageY() - m_npWindow.y;
245 if (m_plugin->pluginFuncs()->event(m_instance, &evt)) {
246 event->setDefaultPrevented(true);
250 void PluginView::handleMouseEvent(MouseEvent* event)
252 const AtomicString& type = event->type();
253 bool isUp = (eventNames().mouseupEvent == type);
254 bool isDown = (eventNames().mousedownEvent == type);
258 if (isUp || isDown) {
259 SkANP::InitEvent(&evt, kMouse_ANPEventType);
260 evt.data.mouse.action = isUp ? kUp_ANPMouseAction : kDown_ANPMouseAction;
262 // convert to coordinates that are relative to the plugin. The pageX / pageY
263 // values are the only values in the event that are consistently in frame
264 // coordinates despite their misleading name.
265 evt.data.mouse.x = event->pageX() - m_npWindow.x;
266 evt.data.mouse.y = event->pageY() - m_npWindow.y;
272 if (m_plugin->pluginFuncs()->event(m_instance, &evt)) {
273 event->setDefaultHandled();
277 static ANPKeyModifier make_modifiers(bool shift, bool alt) {
278 ANPKeyModifier mod = 0;
280 mod |= kShift_ANPKeyModifier;
283 mod |= kAlt_ANPKeyModifier;
288 void PluginView::handleKeyboardEvent(KeyboardEvent* event)
290 if (!m_window->isAcceptingEvent(kKey_ANPEventFlag))
293 const PlatformKeyboardEvent* pke = event->keyEvent();
298 bool ignoreEvent = false;
301 SkANP::InitEvent(&evt, kKey_ANPEventType);
303 switch (pke->type()) {
304 case PlatformKeyboardEvent::KeyDown:
305 #ifdef TRACE_KEY_EVENTS
306 SkDebugf("--------- KeyDown, ignore\n");
310 case PlatformKeyboardEvent::RawKeyDown:
311 evt.data.key.action = kDown_ANPKeyAction;
313 case PlatformKeyboardEvent::Char:
314 #ifdef TRACE_KEY_EVENTS
315 SkDebugf("--------- Char, ignore\n");
319 case PlatformKeyboardEvent::KeyUp:
320 evt.data.key.action = kUp_ANPKeyAction;
323 #ifdef TRACE_KEY_EVENTS
324 SkDebugf("------ unexpected keyevent type %d\n", pke->type());
330 /* the plugin should be the only party able to return nav control to the
331 * browser UI. Therefore, if we discard an event on behalf of the plugin
332 * we should mark the event as being handled.
335 int keyCode = pke->nativeVirtualKeyCode();
336 if (keyCode >= kDpadUp_ANPKeyCode && keyCode <= kDpadCenter_ANPKeyCode)
337 event->setDefaultHandled();
341 evt.data.key.nativeCode = pke->nativeVirtualKeyCode();
342 evt.data.key.virtualCode = pke->windowsVirtualKeyCode();
343 evt.data.key.repeatCount = pke->repeatCount();
344 evt.data.key.modifiers = make_modifiers(pke->shiftKey(), pke->altKey());
345 evt.data.key.unichar = pke->unichar();
347 if (m_plugin->pluginFuncs()->event(m_instance, &evt)) {
348 event->setDefaultHandled();
352 NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32 len, const char* buf)
355 return NPERR_GENERIC_ERROR;
358 NPError PluginView::getValueStatic(NPNVariable variable, void* value)
360 // our interface query is valid with no NPP instance
361 NPError error = NPERR_GENERIC_ERROR;
362 if ((value != NULL) && (variable == NPNVisOfflineBool)) {
363 bool* retValue = static_cast<bool*>(value);
364 *retValue = !networkStateNotifier().onLine();
365 return NPERR_NO_ERROR;
367 (void)anp_getInterface(variable, value, &error);
371 void PluginView::setParent(ScrollView* parent)
373 Widget::setParent(parent);
379 void PluginView::setNPWindowRect(const IntRect& rect)
384 // the rect is relative to the frameview's (0,0)
385 m_npWindow.x = rect.x();
386 m_npWindow.y = rect.y();
387 m_npWindow.width = rect.width();
388 m_npWindow.height = rect.height();
390 m_npWindow.clipRect.left = 0;
391 m_npWindow.clipRect.top = 0;
392 m_npWindow.clipRect.right = rect.width();
393 m_npWindow.clipRect.bottom = rect.height();
395 if (m_plugin->pluginFuncs()->setwindow) {
397 JSC::JSLock::DropAllLocks dropAllLocks(false);
399 setCallingPlugin(true);
400 m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow);
401 setCallingPlugin(false);
404 m_window->setWindow(&m_npWindow, m_isTransparent);
407 NPError PluginView::getValue(NPNVariable variable, void* value)
410 case NPNVWindowNPObject: {
411 NPObject* windowScriptObject =
412 m_parentFrame->script()->windowScriptNPObject();
414 // Return value is expected to be retained, as described
416 // <http://www.mozilla.org/projects/plugin/npruntime.html>
417 if (windowScriptObject)
418 _NPN_RetainObject(windowScriptObject);
420 void** v = (void**)value;
421 *v = windowScriptObject;
423 return NPERR_NO_ERROR;
426 case NPNVPluginElementNPObject: {
427 NPObject* pluginScriptObject = 0;
429 if (m_element->hasTagName(appletTag) ||
430 m_element->hasTagName(embedTag) ||
431 m_element->hasTagName(objectTag)) {
432 HTMLPlugInElement* pluginElement =
433 static_cast<HTMLPlugInElement*>(m_element);
434 pluginScriptObject = pluginElement->getNPObject();
437 // Return value is expected to be retained, as described
439 // <http://www.mozilla.org/projects/plugin/npruntime.html>
440 if (pluginScriptObject)
441 _NPN_RetainObject(pluginScriptObject);
443 void** v = (void**)value;
444 *v = pluginScriptObject;
446 return NPERR_NO_ERROR;
449 case NPNVnetscapeWindow: {
450 // Return the top level WebView Java object associated
451 // with this instance.
452 jobject *retObject = static_cast<jobject*>(value);
453 *retObject = android::WebViewCore::getWebViewCore(parent())->getWebViewJavaObject();
454 return NPERR_NO_ERROR;
457 case NPNVisOfflineBool: {
459 return NPERR_GENERIC_ERROR;
461 bool* retValue = static_cast<bool*>(value);
462 *retValue = !networkStateNotifier().onLine();
463 return NPERR_NO_ERROR;
466 case kSupportedDrawingModel_ANPGetValue: {
467 uint32_t* bits = reinterpret_cast<uint32_t*>(value);
468 *bits = (1 << kBitmap_ANPDrawingModel);
469 return NPERR_NO_ERROR;
473 NPError error = NPERR_GENERIC_ERROR;
474 (void)anp_getInterface(variable, value, &error);
480 NPError PluginView::platformSetValue(NPPVariable variable, void* value)
482 NPError error = NPERR_GENERIC_ERROR;
485 case kSetPluginStubJavaClassName_ANPSetValue: {
486 char* className = reinterpret_cast<char*>(value);
487 if (m_window->setPluginStubJavaClassName(className))
488 error = NPERR_NO_ERROR;
491 case kRequestDrawingModel_ANPSetValue: {
492 ANPDrawingModel model = reinterpret_cast<ANPDrawingModel>(value);
493 if (m_window->setDrawingModel(model))
494 error = NPERR_NO_ERROR;
497 case kAcceptEvents_ANPSetValue : {
499 ANPEventFlags flags = *reinterpret_cast<ANPEventFlags*>(value);
500 m_window->updateEventFlags(flags);
501 error = NPERR_NO_ERROR;
511 void PluginView::invalidateRect(const IntRect& r)
513 m_window->inval(r, true);
516 void PluginView::invalidateRect(NPRect* rect)
521 r = IntRect(rect->left, rect->top,
522 rect->right - rect->left, rect->bottom - rect->top);
524 r = IntRect(0, 0, m_npWindow.width, m_npWindow.height);
527 m_window->inval(r, true);
528 // android::WebViewCore::getWebViewCore(parent())->contentInvalidate(r);
531 void PluginView::invalidateRegion(NPRegion region)
533 // we don't support/define regions (yet), so do nothing
536 void PluginView::forceRedraw()
538 this->invalidateRect(0);
541 void PluginView::setFocus()
544 // SkDebugf("------------- setFocus %p\n", this);
547 void PluginView::show()
549 setSelfVisible(true);
553 void PluginView::hide()
555 setSelfVisible(false);
559 void PluginView::paint(GraphicsContext* context, const IntRect& rect)
562 // Draw the "missing plugin" image
563 paintMissingPluginIcon(context, rect);
567 IntRect frame = frameRect();
568 if (!frame.width() || !frame.height()) {
572 m_window->inval(rect, false);
573 m_window->draw(android_gc2canvas(context));
576 // new as of SVN 38068, Nov 5 2008
577 void PluginView::updatePluginWidget()
579 // I bet/hope we can move all of setNPWindowRect() into here
580 FrameView* frameView = static_cast<FrameView*>(parent());
582 m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size());
586 // new as of SVN 38068, Nov 5 2008
587 void PluginView::setParentVisible(bool) {
591 } // namespace WebCore