OSDN Git Service

d98ccef04458a5173440dc82d94312a0d3a3c112
[android-x86/external-webkit.git] / WebCore / plugins / android / PluginViewAndroid.cpp
1 /*
2  * Copyright 2009, The Android Open Source Project
3  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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.
25  */
26 #define LOG_TAG "WebCore"
27
28 #include "config.h"
29 #include "PluginView.h"
30
31 #include "Document.h"
32 #include "Element.h"
33 #include "EventNames.h"
34 #include "FrameLoader.h"
35 #include "FrameLoadRequest.h"
36 #include "FrameTree.h"
37 #include "Frame.h"
38 #include "FrameView.h"
39 #include "GraphicsContext.h"
40 #include "HTMLNames.h"
41 #include "HTMLPlugInElement.h"
42 #include "Image.h"
43 #include "KeyboardEvent.h"
44 #include "MIMETypeRegistry.h"
45 #include "MouseEvent.h"
46 #include "NetworkStateNotifier.h"
47 #include "NotImplemented.h"
48 #include "Page.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"
55 #include "SkCanvas.h"
56 #include "npruntime_impl.h"
57 // #include "runtime_root.h"
58 #include "utils/SystemClock.h"
59 #include "ScriptController.h"
60 #include "Settings.h"
61
62 #if USE(JSC)
63 #include <runtime/JSLock.h>
64 #endif
65
66 #include <wtf/ASCIICType.h>
67 // #include "runtime.h"
68 #include "WebViewCore.h"
69
70 #include "PluginDebug.h"
71 #include "PluginDebugAndroid.h"
72 #include "PluginViewBridgeAndroid.h"
73 #include "PluginWidgetAndroid.h"
74
75 #include "android_npapi.h"
76 #include "ANPSurface_npapi.h"
77 #include "SkANP.h"
78 #include "SkFlipPixelRef.h"
79
80 ///////////////////////////////////////////////////////////////////////////////
81
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);
94
95 struct VarProcPair {
96     int         enumValue;
97     size_t      size;
98     void        (*proc)(ANPInterface*);
99 };
100
101 #define VARPROCLINE(name)   \
102     k##name##_ANPGetValue, sizeof(ANP##name), ANP##name##_Init
103
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)        },
116 };
117
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)
120  */
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;
131             } else {
132                 iter->proc(i);
133                 *error = NPERR_NO_ERROR;
134             }
135             return true;
136         }
137         iter += 1;
138     }
139     SkDebugf("------ unknown NPNVariable %d\n", var);
140     return false;
141 }
142
143 ///////////////////////////////////////////////////////////////////////////////
144
145 using std::min;
146
147 using namespace WTF;
148
149 namespace WebCore {
150
151 using namespace HTMLNames;
152
153 void PluginView::platformInit()
154 {
155     setPlatformWidget(new PluginViewBridgeAndroid());
156
157     m_isWindowed = false;   // we don't support windowed yet
158
159     m_window = new PluginWidgetAndroid(this);
160
161     m_npWindow.type = NPWindowTypeDrawable;
162     m_npWindow.window = 0;
163 }
164
165 void PluginView::platformStart()
166 {
167     notImplemented();
168 }
169
170 PluginView::~PluginView()
171 {
172     stop();
173
174     deleteAllValues(m_requests);
175
176     freeStringArray(m_paramNames, m_paramCount);
177     freeStringArray(m_paramValues, m_paramCount);
178
179     m_parentFrame->script()->cleanupScriptObjectsForPlugin(this);
180
181 // Since we have no legacy plugins to check, we ignore the quirks check
182 //    if (m_plugin && !m_plugin->quirks().contains(PluginQuirkDontUnloadPlugin))
183     if (m_plugin) {
184         m_plugin->unload();
185     }
186     delete m_window;
187 }
188
189 void PluginView::init()
190 {
191     if (m_haveInitialized)
192         return;
193     m_haveInitialized = true;
194
195     android::WebViewCore* c = android::WebViewCore::getWebViewCore(this->parent());
196     m_window->init(c);
197
198     if (!m_plugin) {
199         ASSERT(m_status == PluginStatusCanNotFindPlugin);
200         return;
201     }
202
203     if (!m_plugin->load()) {
204         m_plugin = 0;
205         m_status = PluginStatusCanNotLoadPlugin;
206         return;
207     }
208
209     if (!start()) {
210         m_status = PluginStatusCanNotLoadPlugin;
211         return;
212     }
213
214     m_status = PluginStatusLoadedSuccessfully;
215 }
216
217 void PluginView::handleTouchEvent(TouchEvent* event)
218 {
219     if (!m_window->isAcceptingEvent(kTouch_ANPEventFlag))
220         return;
221
222     ANPEvent evt;
223     SkANP::InitEvent(&evt, kTouch_ANPEventType);
224
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;
234     else
235         return;
236
237     evt.data.touch.modifiers = 0;   // todo
238
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;
244
245     if (m_plugin->pluginFuncs()->event(m_instance, &evt)) {
246         event->setDefaultPrevented(true);
247     }
248 }
249
250 void PluginView::handleMouseEvent(MouseEvent* event)
251 {
252     const AtomicString& type = event->type();
253     bool isUp = (eventNames().mouseupEvent == type);
254     bool isDown = (eventNames().mousedownEvent == type);
255
256     ANPEvent    evt;
257
258     if (isUp || isDown) {
259         SkANP::InitEvent(&evt, kMouse_ANPEventType);
260         evt.data.mouse.action = isUp ? kUp_ANPMouseAction : kDown_ANPMouseAction;
261
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;
267     }
268     else {
269       return;
270     }
271
272     if (m_plugin->pluginFuncs()->event(m_instance, &evt)) {
273         event->setDefaultHandled();
274     }
275 }
276
277 static ANPKeyModifier make_modifiers(bool shift, bool alt) {
278     ANPKeyModifier mod = 0;
279     if (shift) {
280         mod |= kShift_ANPKeyModifier;
281     }
282     if (alt) {
283         mod |= kAlt_ANPKeyModifier;
284     }
285     return mod;
286 }
287
288 void PluginView::handleKeyboardEvent(KeyboardEvent* event)
289 {
290     if (!m_window->isAcceptingEvent(kKey_ANPEventFlag))
291         return;
292
293     const PlatformKeyboardEvent* pke = event->keyEvent();
294     if (NULL == pke) {
295         return;
296     }
297
298     bool ignoreEvent = false;
299
300     ANPEvent evt;
301     SkANP::InitEvent(&evt, kKey_ANPEventType);
302
303     switch (pke->type()) {
304         case PlatformKeyboardEvent::KeyDown:
305 #ifdef TRACE_KEY_EVENTS
306             SkDebugf("--------- KeyDown, ignore\n");
307 #endif
308             ignoreEvent = true;
309             break;
310         case PlatformKeyboardEvent::RawKeyDown:
311             evt.data.key.action = kDown_ANPKeyAction;
312             break;
313         case PlatformKeyboardEvent::Char:
314 #ifdef TRACE_KEY_EVENTS
315             SkDebugf("--------- Char, ignore\n");
316 #endif
317             ignoreEvent = true;
318             break;
319         case PlatformKeyboardEvent::KeyUp:
320             evt.data.key.action = kUp_ANPKeyAction;
321             break;
322         default:
323 #ifdef TRACE_KEY_EVENTS
324             SkDebugf("------ unexpected keyevent type %d\n", pke->type());
325 #endif
326             ignoreEvent = true;
327             break;
328     }
329
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.
333      */
334     if (ignoreEvent) {
335         int keyCode = pke->nativeVirtualKeyCode();
336         if (keyCode >= kDpadUp_ANPKeyCode && keyCode <= kDpadCenter_ANPKeyCode)
337             event->setDefaultHandled();
338         return;
339     }
340
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();
346
347     if (m_plugin->pluginFuncs()->event(m_instance, &evt)) {
348         event->setDefaultHandled();
349     }
350 }
351
352 NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32 len, const char* buf)
353 {
354     notImplemented();
355     return NPERR_GENERIC_ERROR;
356 }
357
358 NPError PluginView::getValueStatic(NPNVariable variable, void* value)
359 {
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;
366     }
367     (void)anp_getInterface(variable, value, &error);
368     return error;
369 }
370
371 void PluginView::setParent(ScrollView* parent)
372 {
373     Widget::setParent(parent);
374
375     if (parent)
376         init();
377 }
378
379 void PluginView::setNPWindowRect(const IntRect& rect)
380 {
381     if (!m_isStarted)
382         return;
383
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();
389
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();
394
395     if (m_plugin->pluginFuncs()->setwindow) {
396 #if USE(JSC)
397         JSC::JSLock::DropAllLocks dropAllLocks(false);
398 #endif
399         setCallingPlugin(true);
400         m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow);
401         setCallingPlugin(false);
402     }
403
404     m_window->setWindow(&m_npWindow, m_isTransparent);
405 }
406
407 NPError PluginView::getValue(NPNVariable variable, void* value)
408 {
409     switch (variable) {
410         case NPNVWindowNPObject: {
411             NPObject* windowScriptObject =
412                     m_parentFrame->script()->windowScriptNPObject();
413
414             // Return value is expected to be retained, as described
415             // here:
416             // <http://www.mozilla.org/projects/plugin/npruntime.html>
417             if (windowScriptObject)
418                 _NPN_RetainObject(windowScriptObject);
419
420             void** v = (void**)value;
421             *v = windowScriptObject;
422
423             return NPERR_NO_ERROR;
424         }
425
426         case NPNVPluginElementNPObject: {
427             NPObject* pluginScriptObject = 0;
428
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();
435             }
436
437             // Return value is expected to be retained, as described
438             // here:
439             // <http://www.mozilla.org/projects/plugin/npruntime.html>
440             if (pluginScriptObject)
441                 _NPN_RetainObject(pluginScriptObject);
442
443             void** v = (void**)value;
444             *v = pluginScriptObject;
445
446             return NPERR_NO_ERROR;
447         }
448
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;
455         }
456
457         case NPNVisOfflineBool: {
458             if (value == NULL) {
459               return NPERR_GENERIC_ERROR;
460             }
461             bool* retValue = static_cast<bool*>(value);
462             *retValue = !networkStateNotifier().onLine();
463             return NPERR_NO_ERROR;
464         }
465
466         case kSupportedDrawingModel_ANPGetValue: {
467             uint32_t* bits = reinterpret_cast<uint32_t*>(value);
468             *bits = (1 << kBitmap_ANPDrawingModel);
469             return NPERR_NO_ERROR;
470         }
471
472         default: {
473             NPError error = NPERR_GENERIC_ERROR;
474             (void)anp_getInterface(variable, value, &error);
475             return error;
476         }
477     }
478 }
479
480 NPError PluginView::platformSetValue(NPPVariable variable, void* value)
481 {
482     NPError error = NPERR_GENERIC_ERROR;
483
484     switch (variable) {
485         case kSetPluginStubJavaClassName_ANPSetValue: {
486             char* className = reinterpret_cast<char*>(value);
487             if (m_window->setPluginStubJavaClassName(className))
488                 error = NPERR_NO_ERROR;
489             break;
490         }
491         case kRequestDrawingModel_ANPSetValue: {
492             ANPDrawingModel model = reinterpret_cast<ANPDrawingModel>(value);
493             if (m_window->setDrawingModel(model))
494                 error = NPERR_NO_ERROR;
495             break;
496         }
497         case kAcceptEvents_ANPSetValue : {
498             if(value) {
499                 ANPEventFlags flags = *reinterpret_cast<ANPEventFlags*>(value);
500                 m_window->updateEventFlags(flags);
501                 error = NPERR_NO_ERROR;
502             }
503             break;
504         }
505         default:
506             break;
507     }
508     return error;
509 }
510
511 void PluginView::invalidateRect(const IntRect& r)
512 {
513     m_window->inval(r, true);
514 }
515
516 void PluginView::invalidateRect(NPRect* rect)
517 {
518     IntRect r;
519
520     if (rect) {
521         r = IntRect(rect->left, rect->top,
522                     rect->right - rect->left, rect->bottom - rect->top);
523     } else {
524         r = IntRect(0, 0, m_npWindow.width, m_npWindow.height);
525     }
526
527     m_window->inval(r, true);
528 //    android::WebViewCore::getWebViewCore(parent())->contentInvalidate(r);
529 }
530
531 void PluginView::invalidateRegion(NPRegion region)
532 {
533     // we don't support/define regions (yet), so do nothing
534 }
535
536 void PluginView::forceRedraw()
537 {
538     this->invalidateRect(0);
539 }
540
541 void PluginView::setFocus()
542 {
543     Widget::setFocus();
544 //    SkDebugf("------------- setFocus %p\n", this);
545 }
546
547 void PluginView::show()
548 {
549     setSelfVisible(true);
550     Widget::show();
551 }
552
553 void PluginView::hide()
554 {
555     setSelfVisible(false);
556     Widget::hide();
557 }
558
559 void PluginView::paint(GraphicsContext* context, const IntRect& rect)
560 {
561     if (!m_isStarted) {
562         // Draw the "missing plugin" image
563         paintMissingPluginIcon(context, rect);
564         return;
565     }
566
567     IntRect frame = frameRect();
568     if (!frame.width() || !frame.height()) {
569         return;
570     }
571
572     m_window->inval(rect, false);
573     m_window->draw(android_gc2canvas(context));
574 }
575
576 // new as of SVN 38068, Nov 5 2008
577 void PluginView::updatePluginWidget()
578 {
579     // I bet/hope we can move all of setNPWindowRect() into here
580     FrameView* frameView = static_cast<FrameView*>(parent());
581     if (frameView) {
582         m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size());
583     }
584 }
585
586 // new as of SVN 38068, Nov 5 2008
587 void PluginView::setParentVisible(bool) {
588     notImplemented();
589 }
590
591 } // namespace WebCore