1 /*
   2  * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include "config.h"
  27 #include "EventNames.h"
  28 #include "FocusController.h"
  29 #include "FrameView.h"
  30 #include "Image.h"
  31 #include <wtf/java/JavaEnv.h>
  32 #include "MouseEvent.h"
  33 #include "NotImplemented.h"
  34 #include "PluginWidgetJava.h"
  35 #include "RenderBox.h"
  36 #include "StringJava.h"
  37 
  38 #include "com_sun_webkit_WCPluginWidget.h"
  39 
  40 namespace WebCore {
  41 
  42 jmethodID pluginWidgetPaintMID;
  43 jmethodID pluginWidgetCreateMID;
  44 jmethodID pluginWidgetBlurMID;
  45 jmethodID pluginWidgetFWKHandleMouseEventMID;
  46 jmethodID pluginWidgetFWKSetNativeContainerBoundsMID;
  47 jfieldID  pluginWidgetPDataFID;
  48 
  49 /************************************************************************
  50  * WCRectangle fields
  51  */
  52 
  53 jfieldID xFID;
  54 jfieldID yFID;
  55 jfieldID widthFID;
  56 jfieldID heightFID;
  57 jmethodID wcRectCTOR;
  58 JGClass clwcRectangle;
  59 
  60 extern "C" {
  61 JNIEXPORT void JNICALL Java_com_sun_webkit_WCPluginWidget_initIDs(JNIEnv* env, jclass pluginWidgetClass)
  62 {
  63     pluginWidgetPaintMID = env->GetMethodID(pluginWidgetClass, "paint",
  64        "(Lcom/sun/webkit/graphics/WCGraphicsContext;IIII)V");
  65     ASSERT(pluginWidgetPaintMID);
  66 
  67     pluginWidgetCreateMID = env->GetStaticMethodID(pluginWidgetClass, "create",
  68        "(Lcom/sun/webkit/WebPage;IILjava/lang/String;"
  69        "Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)"
  70        "Lcom/sun/webkit/WCPluginWidget;");
  71     ASSERT(pluginWidgetCreateMID);
  72 
  73     pluginWidgetFWKSetNativeContainerBoundsMID = env->GetMethodID(
  74         pluginWidgetClass, "fwkSetNativeContainerBounds",
  75         "(IIII)V");
  76     ASSERT(pluginWidgetFWKSetNativeContainerBoundsMID);
  77 
  78     pluginWidgetFWKHandleMouseEventMID = env->GetMethodID(pluginWidgetClass,
  79         "fwkHandleMouseEvent", "(Ljava/lang/String;IIIIIZZZZZJ)Z");
  80     ASSERT(pluginWidgetFWKHandleMouseEventMID);
  81 
  82     pluginWidgetPDataFID = env->GetFieldID(pluginWidgetClass, "pData", "J");
  83     ASSERT(pluginWidgetPDataFID);
  84 
  85 
  86     clwcRectangle = JLClass(env->FindClass("com/sun/webkit/graphics/WCRectangle"));
  87     ASSERT(clwcRectangle);
  88 
  89     wcRectCTOR = env->GetMethodID(clwcRectangle, "<init>", "(FFFF)V");
  90     ASSERT(wcRectCTOR);
  91 
  92     xFID = env->GetFieldID(clwcRectangle, "x", "F");
  93     ASSERT(xFID);
  94 
  95     yFID = env->GetFieldID(clwcRectangle, "y", "F");
  96     ASSERT(yFID);
  97 
  98     widthFID = env->GetFieldID(clwcRectangle, "w", "F");
  99     ASSERT(widthFID);
 100 
 101     heightFID = env->GetFieldID(clwcRectangle, "h", "F");
 102     ASSERT(heightFID);
 103 }
 104 
 105 
 106 JNIEXPORT void JNICALL Java_com_sun_webkit_WCPluginWidget_twkInvalidateWindowlessPluginRect
 107     (JNIEnv* env,jobject self, jint x, jint y, jint width, jint height)
 108 {
 109     PluginWidgetJava *pThis = ((PluginWidgetJava *)jlong_to_ptr(env->GetLongField(self, pluginWidgetPDataFID)));
 110     if(pThis)
 111         pThis->invalidateWindowlessPluginRect( IntRect(x, y, width, height) );
 112 }
 113 
 114 JNIEXPORT void JNICALL Java_com_sun_webkit_WCPluginWidget_twkSetPlugunFocused
 115     (JNIEnv* env, jobject self, jboolean isFocused)
 116 {
 117     PluginWidgetJava *pThis = ((PluginWidgetJava *)jlong_to_ptr(env->GetLongField(self, pluginWidgetPDataFID)));
 118     if(pThis)
 119         pThis->focusPluginElement( isFocused );
 120 }
 121 
 122 JNIEXPORT jobject JNICALL Java_com_sun_webkit_WCPluginWidget_twkConvertToPage
 123     (JNIEnv* env, jobject self, jobject rc)
 124 {
 125     PluginWidgetJava *pThis = ((PluginWidgetJava *)jlong_to_ptr(env->GetLongField(self, pluginWidgetPDataFID)));
 126     if(pThis){
 127         IntRect irc(
 128             (int)env->GetFloatField(rc, xFID),
 129             (int)env->GetFloatField(rc, yFID),
 130             (int)env->GetFloatField(rc, widthFID),
 131             (int)env->GetFloatField(rc, heightFID));
 132         pThis->convertToPage(irc);
 133         return env->NewObject(
 134             clwcRectangle,
 135             wcRectCTOR,
 136             jdouble(irc.x()),
 137             jdouble(irc.y()),
 138             jdouble(irc.width()),
 139             jdouble(irc.height()));
 140     }
 141     return NULL;
 142 }
 143 
 144 
 145 } // extern "C"
 146 
 147 PluginWidgetJava::PluginWidgetJava(
 148     jobject wfh,
 149     HTMLPlugInElement* element,
 150     const IntSize& size,
 151     const String& url,
 152     const String& mimeType,
 153     const Vector<String>& paramNames,
 154     const Vector<String>& paramValues)
 155       : m_element(element),
 156         m_url(url),
 157         m_mimeType(mimeType),
 158         m_size(size),
 159         m_paramNames(paramNames),
 160         m_paramValues(paramValues)
 161 {
 162     //TODO: have to be moved into setParent(non-null)
 163     JNIEnv* env = WebCore_GetJavaEnv();
 164     JLString urlJavaString(url.toJavaString(env));
 165     JLString mimeTypeJavaString(mimeType.toJavaString(env));
 166 
 167     //better to delegate this upto org/webkit/webcore/platform/api/WebPage
 168     //as for "createScrollView"
 169     JLClass cls(env->FindClass("com/sun/webkit/WCPluginWidget"));
 170     ASSERT(cls);
 171 
 172     jobjectArray pNames = strVect2JArray(env, paramNames);
 173     jobjectArray pValues = strVect2JArray(env, paramValues);
 174 
 175     JLObject obj(env->CallStaticObjectMethod(
 176                                                        cls,
 177                                                        pluginWidgetCreateMID,
 178                                                        wfh,
 179                                                        size.width(), size.height(),
 180                                                        (jstring)urlJavaString,
 181                                                        (jstring)mimeTypeJavaString,
 182                                                        pNames, pValues));
 183     CheckAndClearException(env);
 184 
 185     ASSERT(obj);
 186     if (obj) {
 187         setPlatformWidget(obj);
 188         env->SetLongField(obj, pluginWidgetPDataFID, ptr_to_jlong(this));
 189         setSelfVisible(true);
 190         setParentVisible(true);
 191     }
 192 }
 193 
 194 void PluginWidgetJava::invalidateRect(const IntRect&)
 195 {
 196     notImplemented();
 197 }
 198 
 199 PluginWidgetJava::~PluginWidgetJava() {
 200 }
 201 
 202 void PluginWidgetJava::paint(
 203     GraphicsContext& context,
 204     const IntRect& rc /*page coordinates*/,
 205     SecurityOriginPaintPolicy) {
 206     //Widget::paint(context, rc);
 207     /*
 208     if (!m_isStarted) {
 209         // Draw the "missing plugin" image
 210         paintMissingPluginIcon(context, rect);
 211         return;
 212     }
 213     */
 214     if (context.paintingDisabled())
 215         return;
 216 
 217     JLObject obj = platformWidget();
 218     if (obj){
 219         JNIEnv *env = WebCore_GetJavaEnv();
 220         context.save();
 221         env->CallVoidMethod(
 222             jobject(obj),
 223             pluginWidgetPaintMID,
 224             context.platformContext(),
 225             rc.x(), rc.y(), rc.width(), rc.height());
 226         context.restore();
 227     }
 228 }
 229 
 230 
 231 void PluginWidgetJava::convertToPage(IntRect&)
 232 {
 233     if (!isVisible())
 234         return;
 235 
 236     if (!m_element || !m_element->renderer())
 237         return;
 238 
 239     RenderBox* renderer = downcast<RenderBox>(m_element->renderer()); // FIXME-java: recheck
 240     if(renderer){
 241         renderer->offsetFromContainer(*renderer->container(), LayoutPoint());
 242     }
 243 
 244 }
 245 
 246 void PluginWidgetJava::setFrameRect(const IntRect& rect)
 247 {
 248     if (m_element->document().printing())
 249         return;
 250 
 251     if (rect != frameRect())
 252         Widget::setFrameRect(rect);
 253 
 254     updatePluginWidget();
 255 }
 256 
 257 void PluginWidgetJava::frameRectsChanged()
 258 {
 259     updatePluginWidget();
 260 }
 261 
 262 void PluginWidgetJava::updatePluginWidget()
 263 {
 264     if (!parent())
 265         return;
 266 
 267     ASSERT(parent()->isFrameView());
 268 
 269     FrameView* frameView = static_cast<FrameView*>(parent());
 270     IntRect windowRect(frameView->contentsToWindow(frameRect().location()), frameRect().size());
 271     JLObject obj = platformWidget();
 272     if(obj){
 273         JNIEnv *env = WebCore_GetJavaEnv();
 274         env->CallVoidMethod(
 275             jobject(obj),
 276             pluginWidgetFWKSetNativeContainerBoundsMID,
 277             (jint)windowRect.x(),
 278             (jint)windowRect.y(),
 279             (jint)windowRect.width(),
 280             (jint)windowRect.height());
 281 
 282     }
 283 }
 284 
 285 
 286 void PluginWidgetJava::invalidateWindowlessPluginRect(
 287     const IntRect& rect //client coordinates
 288 ){
 289     if (!isVisible())
 290         return;
 291 
 292     if (!m_element || !m_element->renderer())
 293         return;
 294 
 295     RenderBox* renderer = downcast<RenderBox>(m_element->renderer()); //XXX: recheck
 296     if(renderer){
 297         renderer->repaintRectangle(rect);
 298     }
 299 }
 300 
 301 //look at "void PluginView::focusPluginElement()"
 302 void PluginWidgetJava::focusPluginElement(bool)
 303 {
 304 /*
 305     if( isFocused ){
 306         // Focus the plugin
 307         Frame *parentFrame = static_cast<FrameView*>(parent())->frame();
 308         if (Page* page = parentFrame->page())
 309             page->focusController()->setFocusedFrame(parentFrame);
 310         parentFrame->document()->setFocusedNode(m_element);
 311     }
 312 */
 313 }
 314 
 315 void PluginWidgetJava::handleEvent(Event& event)
 316 {
 317     JNIEnv* env = WebCore_GetJavaEnv();
 318     JLObject obj = platformWidget();
 319     jboolean cancelBubble = false;
 320     if (obj && event.isMouseEvent()) {
 321         MouseEvent* me = static_cast<MouseEvent*>(&event);
 322         //look at "void PluginView::handleMouseEvent(MouseEvent* event)"
 323         //takes into account zoomFactor for offsetX, offsetY
 324         IntPoint p = static_cast<FrameView*>(parent())->contentsToWindow(
 325             IntPoint(me->pageX(), me->pageY()));
 326         cancelBubble = env->CallBooleanMethod(
 327             jobject(obj),
 328             pluginWidgetFWKHandleMouseEventMID,
 329             (jstring)me->type().string().toJavaString(env),
 330             (jint)p.x(),
 331             (jint)p.y(),
 332             (jint)me->screenX(),
 333             (jint)me->screenY(),
 334             (jint)me->button(),
 335             (jboolean)me->buttonDown(),
 336             (jboolean)me->altKey(),
 337             (jboolean)me->metaKey(),
 338             (jboolean)me->ctrlKey(),
 339             (jboolean)me->shiftKey(),
 340             (jlong)me->timeStamp().approximateWallTime().secondsSinceEpoch().milliseconds());
 341     }
 342 
 343     if(cancelBubble) {
 344         event.setDefaultHandled();
 345         event.cancelBubble();
 346     } else {
 347         Widget::handleEvent(event);
 348     }
 349 }
 350 
 351 }