1 /*
   2  * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 #include "config.h"
   5 #include "WebPage.h"
   6 #include "DbgUtils.h"
   7 
   8 #include "AdjustViewSizeOrNot.h"
   9 #include "BridgeUtils.h"
  10 //#include "Cache.h"
  11 #include "CharacterData.h"
  12 #include "Chrome.h"
  13 #include "ChromeClientJava.h"
  14 #include "ContextMenu.h"
  15 #include "ContextMenuClientJava.h"
  16 #include "ContextMenuController.h"
  17 #include "Document.h"
  18 #include "DragClientJava.h"
  19 #include "DragController.h"
  20 #include "DragData.h"
  21 #include "DragSession.h"
  22 #include "Editor.h"
  23 #include "EditorClientJava.h"
  24 #include "EventHandler.h"
  25 #include "FloatRect.h"
  26 #include "FloatSize.h"
  27 #include "FocusController.h"
  28 #include "Font.h"
  29 #include "FontPlatformData.h"
  30 #include "Frame.h"
  31 #include "FrameTree.h"
  32 #include "FrameLoadRequest.h"
  33 #include "FrameLoaderClientJava.h"
  34 #include "FrameView.h"
  35 #include "GraphicsContext.h"
  36 #include "HTMLFormElement.h"
  37 #include "IconController.h"
  38 #include "InspectorClientJava.h"
  39 #include "InspectorController.h"
  40 #include "InitializeLogging.h"
  41 #include "JSContextRefPrivate.h"
  42 #include "JavaEnv.h"
  43 #include "JavaRef.h"
  44 #include "Logging.h"
  45 #include "NodeTraversal.h"
  46 #include "Page.h"
  47 #include "PageGroup.h"
  48 #include "PlatformKeyboardEvent.h"
  49 #include "PlatformMouseEvent.h"
  50 #include "PlatformTouchEvent.h"
  51 #include "PlatformStrategiesJava.h"
  52 #include "PlatformWheelEvent.h"
  53 #include "RenderPart.h"
  54 #include "RenderThemeJava.h"
  55 #include "RenderTreeAsText.h"
  56 #include "RenderView.h"
  57 #include "ResourceRequest.h"
  58 #include "ScriptValue.h"
  59 #include "SecurityPolicy.h"
  60 #include "Settings.h"
  61 #include "ScriptController.h"
  62 #include "Text.h"
  63 #include "TextIterator.h"
  64 #if USE(ACCELERATED_COMPOSITING)
  65 #include "TextureMapper.h"
  66 #include "TextureMapperLayer.h"
  67 #include "GraphicsLayerTextureMapper.h"
  68 #endif
  69 #include "WebKitVersion.h" //generated
  70 #include "Widget.h"
  71 #include "WorkerThread.h"
  72 
  73 #include <wtf/text/WTFString.h>
  74 #include <runtime/InitializeThreading.h>
  75 #include <runtime/JSObject.h>
  76 #include <runtime/JSCJSValue.h>
  77 #include <API/APIShims.h>
  78 #include <API/APICast.h>
  79 
  80 #include "runtime_root.h"
  81 #if OS(UNIX)
  82 #include <sys/utsname.h>
  83 #endif
  84 
  85 #include "com_sun_webkit_WebPage.h"
  86 #include "com_sun_webkit_event_WCFocusEvent.h"
  87 #include "com_sun_webkit_event_WCKeyEvent.h"
  88 #include "com_sun_webkit_event_WCMouseEvent.h"
  89 
  90 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
  91 #include "NotificationController.h"
  92 #include "NotificationClientJava.h"
  93 #endif
  94 
  95 namespace WebCore {
  96 
  97 WebPage::WebPage(PassOwnPtr<Page> page)
  98     : m_page(page)
  99     , m_suppressNextKeypressEvent(false)
 100     , m_isDebugging(false)
 101 #if USE(ACCELERATED_COMPOSITING)
 102     , m_syncLayers(false)
 103 #endif
 104 {
 105 #if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
 106     if(!NotificationController::clientFrom(m_page.get())) {
 107         provideNotification(m_page.get(), NotificationClientJava::instance());
 108     }
 109 #endif
 110 }
 111 
 112 WebPage::~WebPage()
 113 {
 114     debugEnded();
 115 }
 116 
 117 WebPage* WebPage::webPageFromJObject(const JLObject& oWebPage)
 118 {
 119     JNIEnv* env = WebCore_GetJavaEnv();
 120 
 121     static jmethodID midGetPageMethod = env->GetMethodID(
 122         PG_GetWebPageClass(env),
 123         "getPage",
 124         "()J");
 125     ASSERT(midGetPageMethod);
 126 
 127     jlong p = env->CallLongMethod(oWebPage, midGetPageMethod);
 128     CheckAndClearException(env);
 129 
 130     return webPageFromJLong(p);
 131 }
 132 
 133 JLObject WebPage::jobjectFromPage(Page* page)
 134 {
 135     if (!page)
 136         return NULL;
 137 
 138     ChromeClientJava* client = dynamic_cast<ChromeClientJava*>(page->chrome().client());
 139     return client
 140         ? client->platformPage()
 141         : NULL;
 142 }
 143 
 144 void WebPage::setSize(const IntSize& size)
 145 {
 146     Frame* mainFrame = m_page->mainFrame();
 147 
 148     FrameView* frameView = mainFrame->view();
 149     if (!frameView) {
 150         return;
 151     }
 152 
 153     frameView->resize(size);
 154     frameView->scheduleRelayout();
 155 
 156 #if USE(ACCELERATED_COMPOSITING)
 157     if (m_rootLayer) {
 158         m_rootLayer->setSize(size);
 159         m_rootLayer->setNeedsDisplay();
 160     }
 161 #endif
 162 }
 163 
 164 static void drawDebugLed(GraphicsContext& context,
 165                          const IntRect& rect,
 166                          const Color& color)
 167 {
 168     const int w = 50;
 169     const int h = 50;
 170     FloatRect ledRect(
 171             rect.x() + rect.width() / 2 - w / 2,
 172             rect.y() + rect.height() / 2 - h / 2,
 173             w,
 174             h);
 175     context.fillRect(ledRect, color, ColorSpaceDeviceRGB);
 176 }
 177 
 178 static void drawDebugBorder(GraphicsContext& context,
 179                             const IntRect& rect,
 180                             const Color& color,
 181                             int width)
 182 {
 183     int x = rect.x();
 184     int y = rect.y();
 185     int w = rect.width();
 186     int h = rect.height();
 187     ColorSpace cs(ColorSpaceDeviceRGB);
 188     context.fillRect(FloatRect(x, y, w, width), color, cs);
 189     context.fillRect(FloatRect(x, y + h - width, w, width), color, cs);
 190     context.fillRect(FloatRect(x, y, width, h), color, cs);
 191     context.fillRect(FloatRect(x + w - width, y, width, h), color, cs);
 192 }
 193 
 194 void WebPage::prePaint() {
 195 #if USE(ACCELERATED_COMPOSITING)
 196     if (m_rootLayer) {
 197         if (m_syncLayers) {
 198             m_syncLayers = false;
 199             syncLayers();
 200         }
 201         return;
 202     }
 203 #endif
 204     Frame* mainFrame = m_page->mainFrame();
 205     FrameView* frameView = mainFrame->view();
 206     if (frameView) {
 207         // Updating layout & styles precedes normal painting.
 208         frameView->updateLayoutAndStyleIfNeededRecursive();
 209     }
 210 }
 211 
 212 void WebPage::paint(jobject rq, jint x, jint y, jint w, jint h)
 213 {
 214 #if USE(ACCELERATED_COMPOSITING)
 215     if (m_rootLayer) {
 216         return;
 217     }
 218 #endif
 219 
 220     DBG_CHECKPOINTEX("twkUpdateContent", 15, 100);
 221 
 222     RefPtr<Frame> mainFrame(m_page->mainFrame());
 223     RefPtr<FrameView> frameView(mainFrame->view());
 224     if (!frameView) {
 225         return;
 226     }
 227 
 228     // Will be deleted by GraphicsContext destructor
 229     PlatformContextJava* ppgc = new PlatformContextJava(rq);
 230     GraphicsContext gc(ppgc);
 231 
 232     // TODO: Following JS synchronization is not necessary for single thread model
 233     JSGlobalContextRef globalContext = toGlobalRef(mainFrame->script()->globalObject(mainThreadNormalWorld())->globalExec());
 234     JSC::APIEntryShim sw( toJS(globalContext) );
 235 
 236     frameView->paint(&gc, IntRect(x, y, w, h));
 237     if (m_page->settings()->showDebugBorders()) {
 238         drawDebugLed(gc, IntRect(x, y, w, h), Color(0, 0, 255, 128));
 239     }
 240 
 241     gc.platformContext()->rq().flushBuffer();
 242 }
 243 
 244 void WebPage::postPaint(jobject rq, jint x, jint y, jint w, jint h)
 245 {
 246     if (!m_page->inspectorController()->highlightedNode()
 247 #if USE(ACCELERATED_COMPOSITING)
 248             && !m_rootLayer
 249 #endif
 250     ) {
 251         return;
 252     }
 253 
 254     // Will be deleted by GraphicsContext destructor
 255     PlatformContextJava* ppgc = new PlatformContextJava(rq);
 256     GraphicsContext gc(ppgc);
 257 
 258 #if USE(ACCELERATED_COMPOSITING)
 259     if (m_rootLayer) {
 260         renderCompositedLayers(gc, IntRect(x, y, w, h));
 261         if (m_page->settings()->showDebugBorders()) {
 262             drawDebugLed(gc, IntRect(x, y, w, h), Color(0, 192, 0, 128));
 263         }
 264         if (toTextureMapperLayer(m_rootLayer.get())->descendantsOrSelfHaveRunningAnimations()) {
 265             requestJavaRepaint(pageRect());
 266         }
 267     }
 268 #endif
 269 
 270     if (m_page->inspectorController()->highlightedNode()) {
 271         m_page->inspectorController()->drawHighlight(gc);
 272     }
 273 
 274     gc.platformContext()->rq().flushBuffer();
 275 }
 276 
 277 void WebPage::scroll(const IntSize& scrollDelta,
 278                      const IntRect& rectToScroll,
 279                      const IntRect& clipRect)
 280 {
 281 #if USE(ACCELERATED_COMPOSITING)
 282     if (m_rootLayer) {
 283         m_rootLayer->setNeedsDisplayInRect(rectToScroll);
 284         return;
 285     }
 286 #endif
 287 
 288     JNIEnv* env = WebCore_GetJavaEnv();
 289 
 290     static jmethodID mid = env->GetMethodID(
 291             PG_GetWebPageClass(env),
 292             "fwkScroll",
 293             "(IIIIII)V");
 294     ASSERT(mid);
 295 
 296     env->CallVoidMethod(
 297             jobjectFromPage(m_page.get()),
 298             mid,
 299             rectToScroll.x(),
 300             rectToScroll.y(),
 301             rectToScroll.width(),
 302             rectToScroll.height(),
 303             scrollDelta.width(),
 304             scrollDelta.height());
 305     CheckAndClearException(env);
 306 }
 307 
 308 void WebPage::repaint(const IntRect& rect)
 309 {
 310 #if USE(ACCELERATED_COMPOSITING)
 311     if (m_rootLayer) {
 312         m_rootLayer->setNeedsDisplayInRect(rect);
 313     }
 314 #endif
 315     requestJavaRepaint(rect);
 316 }
 317 
 318 #if USE(ACCELERATED_COMPOSITING)
 319 void WebPage::setRootChildLayer(GraphicsLayer* layer)
 320 {
 321     if (layer) {
 322         m_rootLayer = GraphicsLayer::create(this);
 323         m_rootLayer->setDrawsContent(true);
 324         m_rootLayer->setContentsOpaque(true);
 325         m_rootLayer->setSize(pageRect().size());
 326         m_rootLayer->setNeedsDisplay();
 327         m_rootLayer->addChild(layer);
 328 
 329         m_textureMapper = TextureMapper::create();
 330         toTextureMapperLayer(m_rootLayer.get())
 331                 ->setTextureMapper(m_textureMapper.get());
 332     } else {
 333         m_rootLayer.clear();
 334         m_textureMapper.clear();
 335     }
 336 }
 337 
 338 void WebPage::setNeedsOneShotDrawingSynchronization()
 339 {
 340 }
 341 
 342 void WebPage::scheduleCompositingLayerSync()
 343 {
 344     markForSync();
 345 }
 346 
 347 void WebPage::markForSync()
 348 {
 349     if (!m_rootLayer) {
 350         return;
 351     }
 352     m_syncLayers = true;
 353     requestJavaRepaint(pageRect());
 354 }
 355 
 356 void WebPage::syncLayers()
 357 {
 358     if (!m_rootLayer) {
 359         return;
 360     }
 361 
 362     m_page->mainFrame()->view()->updateLayoutAndStyleIfNeededRecursive();
 363 
 364     // Updating layout might have taken us out of compositing mode
 365     if (m_rootLayer) {
 366         m_rootLayer->flushCompositingStateForThisLayerOnly();
 367                     //syncCompositingStateForThisLayerOnly();
 368     }
 369 
 370     m_page->mainFrame()->view()->flushCompositingStateIncludingSubframes();
 371                                 //syncCompositingStateIncludingSubframes();
 372 }
 373 
 374 void WebPage::requestJavaRepaint(const IntRect& rect)
 375 {
 376     JNIEnv* env = WebCore_GetJavaEnv();
 377 
 378     static jmethodID mid = env->GetMethodID(
 379             PG_GetWebPageClass(env),
 380             "fwkRepaint",
 381             "(IIII)V");
 382     ASSERT(mid);
 383 
 384     env->CallVoidMethod(
 385             jobjectFromPage(m_page.get()),
 386             mid,
 387             rect.x(),
 388             rect.y(),
 389             rect.width(),
 390             rect.height());
 391     CheckAndClearException(env);
 392 }
 393 
 394 IntRect WebPage::pageRect()
 395 {
 396     ChromeClient *client = m_page->chrome().client();
 397     if (client) {
 398         return IntRect(client->pageRect());
 399     } else {
 400         return IntRect();
 401     }
 402 }
 403 
 404 void WebPage::renderCompositedLayers(GraphicsContext& context, const IntRect& clip)
 405 {
 406     ASSERT(m_rootLayer);
 407     ASSERT(m_textureMapper);
 408 
 409     TextureMapperLayer* rootTextureMapperLayer = toTextureMapperLayer(m_rootLayer.get());
 410 
 411     m_textureMapper->setGraphicsContext(&context);
 412     m_textureMapper->setImageInterpolationQuality(context.imageInterpolationQuality());
 413     m_textureMapper->setTextDrawingMode(context.textDrawingMode());
 414     TransformationMatrix matrix;
 415     rootTextureMapperLayer->setTransform(matrix);
 416     m_textureMapper->beginPainting();
 417     m_textureMapper->beginClip(matrix, clip);
 418     //rootTextureMapperLayer->syncAnimationsRecursive();
 419     rootTextureMapperLayer->applyAnimationsRecursively();
 420     rootTextureMapperLayer->paint();
 421     m_textureMapper->endClip();
 422     m_textureMapper->endPainting();
 423 }
 424 
 425 void WebPage::notifyAnimationStarted(const GraphicsLayer*, double)
 426 {
 427     ASSERT_NOT_REACHED();
 428 }
 429 
 430 void WebPage::notifyFlushRequired(const GraphicsLayer*)
 431 {
 432     markForSync();
 433 }
 434 
 435 void WebPage::paintContents(const GraphicsLayer*,
 436                             GraphicsContext& context,
 437                             GraphicsLayerPaintingPhase,
 438                             const IntRect& inClip)
 439 {
 440     context.save();
 441     context.clip(inClip);
 442     m_page->mainFrame()->view()->paint(&context, inClip);
 443     if (m_page->settings()->showDebugBorders()) {
 444         drawDebugBorder(context, inClip, Color(0, 192, 0), 20);
 445     }
 446     context.restore();
 447 }
 448 
 449 bool WebPage::showDebugBorders(const GraphicsLayer*) const
 450 {
 451     return m_page->settings()->showDebugBorders();
 452 }
 453 
 454 bool WebPage::showRepaintCounter(const GraphicsLayer*) const
 455 {
 456     return m_page->settings()->showRepaintCounter();
 457 }
 458 
 459 #endif // USE(ACCELERATED_COMPOSITING)
 460 
 461 bool WebPage::processKeyEvent(const PlatformKeyboardEvent& event)
 462 {
 463     return event.type() == PlatformKeyboardEvent::Char
 464         ? charEvent(event)
 465         : keyEvent(event);
 466 }
 467 
 468 //
 469 // The below keyboard event handling code was adapted from
 470 // WebKit/chromium/src/WebViewImpl.cpp
 471 //
 472 
 473 static const int VKEY_PRIOR = com_sun_webkit_event_WCKeyEvent_VK_PRIOR;
 474 static const int VKEY_NEXT = com_sun_webkit_event_WCKeyEvent_VK_NEXT;
 475 static const int VKEY_END = com_sun_webkit_event_WCKeyEvent_VK_END;
 476 static const int VKEY_HOME = com_sun_webkit_event_WCKeyEvent_VK_HOME;
 477 static const int VKEY_LEFT = com_sun_webkit_event_WCKeyEvent_VK_LEFT;
 478 static const int VKEY_UP = com_sun_webkit_event_WCKeyEvent_VK_UP;
 479 static const int VKEY_RIGHT = com_sun_webkit_event_WCKeyEvent_VK_RIGHT;
 480 static const int VKEY_DOWN = com_sun_webkit_event_WCKeyEvent_VK_DOWN;
 481 
 482 bool WebPage::keyEvent(const PlatformKeyboardEvent& event)
 483 {
 484     ASSERT((event.type() == PlatformKeyboardEvent::RawKeyDown)
 485         || (event.type() == PlatformKeyboardEvent::KeyDown)
 486         || (event.type() == PlatformKeyboardEvent::KeyUp));
 487 
 488     // Please refer to the comments explaining the m_suppressNextKeypressEvent
 489     // member.
 490     // The m_suppressNextKeypressEvent is set if the KeyDown is handled by
 491     // Webkit. A keyDown event is typically associated with a keyPress(char)
 492     // event and a keyUp event. We reset this flag here as this is a new keyDown
 493     // event.
 494     m_suppressNextKeypressEvent = false;
 495 
 496     RefPtr<Frame> frame = focusedWebCoreFrame();
 497     if (!frame)
 498         return false;
 499 
 500     EventHandler* handler = frame->eventHandler();
 501     if (!handler)
 502         return keyEventDefault(event);
 503 
 504     if (handler->keyEvent(event)) {
 505         if (event.type() == PlatformKeyboardEvent::RawKeyDown) {
 506             // Suppress the next keypress event unless the focused node
 507             // is a plug-in node. (Flash needs these keypress events to
 508             // handle non-US keyboards.)
 509             Node* node = focusedWebCoreNode();
 510             if (!node || !node->renderer()
 511                     || !node->renderer()->isEmbeddedObject())
 512                 m_suppressNextKeypressEvent = true;
 513         }
 514         return true;
 515     }
 516 
 517     return keyEventDefault(event);
 518 }
 519 
 520 bool WebPage::charEvent(const PlatformKeyboardEvent& event)
 521 {
 522     ASSERT(event.type() == PlatformKeyboardEvent::Char);
 523 
 524     // Please refer to the comments explaining the m_suppressNextKeypressEvent
 525     // member.  The m_suppressNextKeypressEvent is set if the KeyDown is
 526     // handled by Webkit. A keyDown event is typically associated with a
 527     // keyPress(char) event and a keyUp event. We reset this flag here as it
 528     // only applies to the current keyPress event.
 529     bool suppress = m_suppressNextKeypressEvent;
 530     m_suppressNextKeypressEvent = false;
 531 
 532     Frame* frame = focusedWebCoreFrame();
 533     if (!frame)
 534         return suppress;
 535 
 536     EventHandler* handler = frame->eventHandler();
 537     if (!handler)
 538         return suppress || keyEventDefault(event);
 539 
 540     if (!suppress && !handler->keyEvent(event))
 541         return keyEventDefault(event);
 542 
 543     return true;
 544 }
 545 
 546 bool WebPage::keyEventDefault(const PlatformKeyboardEvent& event)
 547 {
 548     Frame* frame = focusedWebCoreFrame();
 549     if (!frame)
 550         return false;
 551 
 552     switch (event.type()) {
 553     case PlatformKeyboardEvent::RawKeyDown:
 554         if (event.modifiers() == PlatformKeyboardEvent::CtrlKey) {
 555             switch (event.windowsVirtualKeyCode()) {
 556             // Match FF behavior in the sense that Ctrl+home/end are the only
 557             // Ctrl // key combinations which affect scrolling. Safari is buggy
 558             // in the sense that it scrolls the page for all Ctrl+scrolling key
 559             // combinations. For e.g. Ctrl+pgup/pgdn/up/down, etc.
 560             case VKEY_HOME:
 561             case VKEY_END:
 562                 break;
 563             default:
 564                 return false;
 565             }
 566         }
 567         if (!event.shiftKey())
 568             return scrollViewWithKeyboard(event.windowsVirtualKeyCode(),
 569                                           event.modifiers());
 570         break;
 571     default:
 572         break;
 573     }
 574     return false;
 575 }
 576 
 577 bool WebPage::scrollViewWithKeyboard(int keyCode, int modifiers)
 578 {
 579     ScrollDirection scrollDirection;
 580     ScrollGranularity scrollGranularity;
 581 #if OS(DARWIN)
 582     if (modifiers & PlatformKeyboardEvent::MetaKey) {
 583         if (keyCode == VKEY_UP)
 584             keyCode = VKEY_HOME;
 585         else if (keyCode == VKEY_DOWN)
 586             keyCode = VKEY_END;
 587     }
 588     if (modifiers & PlatformKeyboardEvent::AltKey) {
 589         if (keyCode == VKEY_UP)
 590             keyCode = VKEY_PRIOR;
 591         else if (keyCode == VKEY_DOWN)
 592             keyCode = VKEY_NEXT;
 593     }
 594 #endif
 595     if (!mapKeyCodeForScroll(keyCode, &scrollDirection, &scrollGranularity))
 596         return false;
 597     return propagateScroll(scrollDirection, scrollGranularity);
 598 }
 599 
 600 bool WebPage::mapKeyCodeForScroll(int keyCode,
 601                                   ScrollDirection* scrollDirection,
 602                                   ScrollGranularity* scrollGranularity)
 603 {
 604     switch (keyCode) {
 605     case VKEY_LEFT:
 606         *scrollDirection = ScrollLeft;
 607         *scrollGranularity = ScrollByLine;
 608         break;
 609     case VKEY_RIGHT:
 610         *scrollDirection = ScrollRight;
 611         *scrollGranularity = ScrollByLine;
 612         break;
 613     case VKEY_UP:
 614         *scrollDirection = ScrollUp;
 615         *scrollGranularity = ScrollByLine;
 616         break;
 617     case VKEY_DOWN:
 618         *scrollDirection = ScrollDown;
 619         *scrollGranularity = ScrollByLine;
 620         break;
 621     case VKEY_HOME:
 622         *scrollDirection = ScrollUp;
 623         *scrollGranularity = ScrollByDocument;
 624         break;
 625     case VKEY_END:
 626         *scrollDirection = ScrollDown;
 627         *scrollGranularity = ScrollByDocument;
 628         break;
 629     case VKEY_PRIOR:  // page up
 630         *scrollDirection = ScrollUp;
 631         *scrollGranularity = ScrollByPage;
 632         break;
 633     case VKEY_NEXT:  // page down
 634         *scrollDirection = ScrollDown;
 635         *scrollGranularity = ScrollByPage;
 636         break;
 637     default:
 638         return false;
 639     }
 640 
 641     return true;
 642 }
 643 
 644 bool WebPage::propagateScroll(ScrollDirection scrollDirection,
 645                               ScrollGranularity scrollGranularity)
 646 {
 647     Frame* frame = focusedWebCoreFrame();
 648     if (!frame)
 649         return false;
 650 
 651     bool scrollHandled = frame->eventHandler()->scrollOverflow(
 652             scrollDirection,
 653             scrollGranularity);
 654     Frame* currentFrame = frame;
 655     while (!scrollHandled && currentFrame) {
 656         scrollHandled = currentFrame->view()->scroll(scrollDirection,
 657                                                      scrollGranularity);
 658         currentFrame = currentFrame->tree()->parent();
 659     }
 660     return scrollHandled;
 661 }
 662 
 663 Frame* WebPage::focusedWebCoreFrame()
 664 {
 665     return m_page->focusController()->focusedOrMainFrame();
 666 }
 667 
 668 Node* WebPage::focusedWebCoreNode()
 669 {
 670     Frame* frame = m_page->focusController()->focusedFrame();
 671     if (!frame)
 672         return 0;
 673 
 674     Document* document = frame->document();
 675     if (!document)
 676         return 0;
 677 
 678     return document->focusedNode();
 679 }
 680 
 681 //implemented in customized WebCore/page/java/DragControllerJava.cpp
 682 void setCopyKeyState(bool _copyKeyIsDown);
 683 
 684 static String agentOS()
 685 {
 686 #if OS(DARWIN)
 687 #if CPU(X86) || CPU(X86_64)
 688     return "Macintosh; Intel Mac OS X";
 689 #else
 690     return "Macintosh; PPC Mac OS X";
 691 #endif
 692 #elif OS(UNIX)
 693     struct utsname name;
 694     if (uname(&name) != -1)
 695         return makeString(name.sysname, ' ', name.machine);
 696 #elif OS(WINDOWS)
 697     return windowsVersionForUAString();
 698 #else
 699     notImplemented();
 700 #endif
 701     return "Unknown";
 702 }
 703 
 704 static String defaultUserAgent()
 705 {
 706     DEFINE_STATIC_LOCAL(String, userAgentString, ());
 707     if (userAgentString.isNull()) {
 708         String wkVersion = String::format("%d.%d", WEBKIT_MAJOR_VERSION, WEBKIT_MINOR_VERSION);
 709         userAgentString = makeString("Mozilla/5.0 (", agentOS(),
 710                                      ") AppleWebKit/", wkVersion,
 711                                      " (KHTML, like Gecko) JavaFX/8.0 Safari/", wkVersion);
 712     }
 713     return userAgentString;
 714 }
 715 
 716 int WebPage::beginPrinting(float width, float height)
 717 {
 718     Frame* frame = m_page->mainFrame();
 719     if (!frame->document() || !frame->view() || !frame->document()->renderer())
 720         return 0;
 721     frame->document()->updateLayout();
 722 
 723     ASSERT(!m_printContext);
 724     m_printContext = adoptPtr(new PrintContext(frame));
 725     m_printContext->begin(width, height);
 726     m_printContext->computePageRects(FloatRect(0, 0, width, height), 0, 0, 1, height);
 727     return m_printContext->pageCount();
 728 }
 729 
 730 void WebPage::endPrinting()
 731 {
 732     ASSERT(m_printContext);
 733     if (!m_printContext)
 734         return;
 735 
 736     m_printContext->end();
 737     m_printContext.clear();
 738 }
 739 
 740 void WebPage::print(GraphicsContext& gc, int pageIndex, float pageWidth)
 741 {
 742     ASSERT(m_printContext);
 743     ASSERT(pageIndex >= 0 && pageIndex < m_printContext->pageCount());
 744 
 745     if (!m_printContext || pageIndex < 0 || pageIndex >= m_printContext->pageCount())
 746         return;
 747 
 748     gc.save();
 749     gc.translate(0, 0);
 750     m_printContext->spoolPage(gc, pageIndex, pageWidth);
 751     gc.restore();
 752     gc.platformContext()->rq().flushBuffer();
 753 }
 754 
 755 int WebPage::globalDebugSessionCounter = 0;
 756 
 757 void WebPage::debugStarted() {
 758     if (!m_isDebugging) {
 759         m_isDebugging = true;
 760         globalDebugSessionCounter++;
 761 
 762         disableWatchdog();
 763     }
 764 }
 765 void WebPage::debugEnded() {
 766     if (m_isDebugging) {
 767         m_isDebugging = false;
 768         globalDebugSessionCounter--;
 769 
 770         enableWatchdog();
 771     }
 772 }
 773 void WebPage::enableWatchdog() {
 774     if (globalDebugSessionCounter == 0) {
 775         JSContextGroupRef contextGroup = toRef(mainThreadNormalWorld()->vm());
 776         JSContextGroupSetExecutionTimeLimit(contextGroup, 10, 0, 0);
 777     }
 778 }
 779 
 780 void WebPage::disableWatchdog() {
 781     if (globalDebugSessionCounter > 0) {
 782         JSContextGroupRef contextGroup = toRef(mainThreadNormalWorld()->vm());
 783             JSContextGroupClearExecutionTimeLimit(contextGroup);
 784         }
 785 }
 786 
 787 
 788 } // namespace WebCore
 789 
 790 using namespace WebCore;
 791 using namespace WTF;
 792 
 793 #ifdef __cplusplus
 794 extern "C" {
 795 #endif
 796 
 797 JNIEXPORT jlong JNICALL Java_com_sun_webkit_WebPage_twkCreatePage
 798     (JNIEnv* env, jobject self, jboolean editable)
 799 {
 800     JSC::initializeThreading();
 801     WTF::initializeMainThread();
 802     // RT-17330: Allow local loads for substitute data, that is,
 803     // for content loaded with twkLoad
 804     WebCore::SecurityPolicy::setLocalLoadPolicy(
 805             WebCore::SecurityPolicy::AllowLocalLoadsForLocalAndSubstituteData);
 806 
 807     //DBG_CHECKPOINTEX("twkCreatePage", 3, 5);
 808 
 809 
 810     PageGroup::setShouldTrackVisitedLinks(true);
 811 
 812 #if !LOG_DISABLED
 813     initializeLoggingChannelsIfNecessary();
 814 #endif
 815     PlatformStrategiesJava::initialize();
 816 
 817     JLObject jlself(self, true);
 818 
 819     //utaTODO: history agent implementation
 820     Page::PageClients pc;
 821     pc.chromeClient = new ChromeClientJava(jlself);
 822     pc.contextMenuClient = new ContextMenuClientJava(jlself);
 823     pc.editorClient = new EditorClientJava(jlself);
 824     pc.dragClient = new DragClientJava(jlself);
 825     pc.inspectorClient = new InspectorClientJava(jlself);
 826 
 827     return ptr_to_jlong(new WebPage(adoptPtr(new Page(pc))));
 828 }
 829 
 830 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkInit
 831     (JNIEnv* env, jobject self, jlong pPage, jboolean usePlugins)
 832 {
 833     Page* page = WebPage::pageFromJLong(pPage);
 834 
 835     /* Initialization of the default settings */
 836     Settings* settings = page->settings();
 837     settings->setTextAreasAreResizable(true);
 838     settings->setLoadsImagesAutomatically(true);
 839     settings->setMinimumFontSize(0);
 840     settings->setMinimumLogicalFontSize(5);
 841     settings->setScriptEnabled(true);
 842     settings->setJavaScriptCanOpenWindowsAutomatically(true);
 843     settings->setPluginsEnabled(usePlugins);
 844     settings->setDefaultFixedFontSize(13);
 845     settings->setDefaultFontSize(16);
 846     settings->setContextMenuEnabled(true);
 847     settings->setUserAgent(defaultUserAgent());
 848     settings->setMaximumHTMLParserDOMTreeDepth(180);
 849     settings->setXSSAuditorEnabled(true);
 850 
 851     /* Using java logical fonts as defaults */
 852     settings->setSerifFontFamily("Serif");
 853     settings->setSansSerifFontFamily("SansSerif");
 854     settings->setFixedFontFamily("Monospaced");
 855 //    settings->setShowsURLsInToolTips(true);
 856 
 857     JLObject jlself(self, true);
 858     FrameLoaderClientJava* frameLoaderClient = new FrameLoaderClientJava(jlself);
 859     RefPtr<Frame> frame = Frame::create(page, 0 /* ownerFrameElement */, frameLoaderClient);
 860     frameLoaderClient->setFrame(frame.get());
 861 
 862     frame->init();
 863 
 864     WebPage::webPageFromJLong(pPage)->enableWatchdog();
 865 }
 866 
 867 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkDestroyPage
 868     (JNIEnv* env, jobject self, jlong pPage)
 869 {
 870     WebPage* webPage = WebPage::webPageFromJLong(pPage);
 871     if (!webPage) {
 872         return;
 873     }
 874 
 875     Frame* mainFrame = webPage->page()->mainFrame();
 876     if (mainFrame) {
 877         mainFrame->loader()->stopAllLoaders();
 878         mainFrame->loader()->detachFromParent();
 879     }
 880 
 881     delete webPage;
 882 }
 883 
 884 JNIEXPORT jlong JNICALL Java_com_sun_webkit_WebPage_twkGetMainFrame
 885     (JNIEnv* env, jobject self, jlong pPage)
 886 {
 887     Page* page = WebPage::pageFromJLong(pPage);
 888     if (!page) {
 889         return 0;
 890     }
 891     Frame* mainFrame = page->mainFrame();
 892     if (!mainFrame) {
 893         return 0;
 894     }
 895     return ptr_to_jlong(mainFrame);
 896 }
 897 
 898 JNIEXPORT jlong JNICALL Java_com_sun_webkit_WebPage_twkGetParentFrame
 899     (JNIEnv* env, jobject self, jlong pFrame)
 900 {
 901     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
 902     if (!frame) {
 903         return 0;
 904     }
 905     Frame* parentFrame = frame->tree()->parent();
 906     if (!parentFrame) {
 907         return 0;
 908     }
 909     return ptr_to_jlong(parentFrame);
 910 }
 911 
 912 JNIEXPORT jlongArray JNICALL Java_com_sun_webkit_WebPage_twkGetChildFrames
 913     (JNIEnv* env, jobject self, jlong pFrame)
 914 {
 915     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
 916     if (!frame) {
 917         return 0;
 918     }
 919 
 920     FrameTree* tree = frame->tree();
 921 
 922     jlongArray jArray = env->NewLongArray(tree->childCount());
 923     jlong *arr = env->GetLongArrayElements(jArray, 0);
 924     int i = 0;
 925     for (Frame* child = tree->firstChild(); child; child = child->tree()->nextSibling()) {
 926         arr[i++] = ptr_to_jlong(child);
 927     }
 928     env->ReleaseLongArrayElements(jArray, arr, 0);
 929 
 930     return jArray;
 931 }
 932 
 933 JNIEXPORT jstring JNICALL Java_com_sun_webkit_WebPage_twkGetName
 934     (JNIEnv* env, jobject self, jlong pFrame)
 935 {
 936     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
 937     if (!frame || !frame->tree()) {
 938         return 0;
 939     }
 940     return frame->tree()->uniqueName().string().toJavaString(env).releaseLocal();
 941 }
 942 
 943 JNIEXPORT jstring JNICALL Java_com_sun_webkit_WebPage_twkGetURL
 944     (JNIEnv* env, jobject self, jlong pFrame)
 945 {
 946     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
 947     if (!frame || !frame->document()) {
 948         return 0;
 949     }
 950     Document* doc = frame->document();
 951     if (!doc) {
 952         return 0;
 953     }
 954     return doc->url().string().toJavaString(env).releaseLocal();
 955 }
 956 
 957 JNIEXPORT jstring JNICALL Java_com_sun_webkit_WebPage_twkGetInnerText
 958     (JNIEnv* env, jobject self, jlong pFrame)
 959 {
 960     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
 961     if (!frame) {
 962         return 0;
 963     }
 964 
 965     Document* document = frame->document();
 966     if (!document) {
 967         return 0;
 968     }
 969 
 970     Element* documentElement = document->documentElement();
 971     if (!documentElement) {
 972         return 0;
 973     }
 974 
 975     FrameView* frameView = frame->view();
 976     if (frameView && frameView->layoutPending()) {
 977         frameView->layout();
 978     }
 979 
 980     return documentElement->innerText().toJavaString(env).releaseLocal();
 981 }
 982 
 983 JNIEXPORT jstring JNICALL Java_com_sun_webkit_WebPage_twkGetRenderTree
 984     (JNIEnv* env, jobject self, jlong pFrame)
 985 {
 986     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
 987     if (!frame || !frame->contentRenderer()) {
 988         return 0;
 989     }
 990 
 991     FrameView* frameView = frame->view();
 992     if (frameView && frameView->layoutPending()) {
 993         frameView->layout();
 994     }
 995 
 996     return externalRepresentation(frame).toJavaString(env).releaseLocal();
 997 }
 998 
 999 JNIEXPORT jstring JNICALL Java_com_sun_webkit_WebPage_twkGetContentType
1000     (JNIEnv* env, jobject self, jlong pFrame)
1001 {
1002     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1003     if (!frame || !frame->loader() || !frame->loader()->documentLoader()) {
1004         return 0;
1005     }
1006     return frame->loader()->documentLoader()->responseMIMEType().toJavaString(env).releaseLocal();
1007 }
1008 
1009 JNIEXPORT jstring JNICALL Java_com_sun_webkit_WebPage_twkGetTitle
1010     (JNIEnv* env, jobject self, jlong pFrame)
1011 {
1012     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1013     if (!frame || !frame->document()) {
1014         return 0;
1015     }
1016     return frame->document()->title().toJavaString(env).releaseLocal();
1017 }
1018 
1019 JNIEXPORT jstring JNICALL Java_com_sun_webkit_WebPage_twkGetIconURL
1020     (JNIEnv* env, jobject self, jlong pFrame)
1021 {
1022     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1023     if (!frame || !frame->loader()) {
1024         return 0;
1025     }
1026 #if ENABLE(ICONDATABASE)
1027     return frame->loader()->icon()->url().string().toJavaString(env).releaseLocal();
1028 #else
1029     return 0;
1030 #endif
1031 }
1032 
1033 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkOpen
1034     (JNIEnv* env, jobject self, jlong pFrame, jstring url)
1035 {
1036     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1037     if (!frame || !frame->loader()) {
1038         return;
1039     }
1040 
1041     static const KURL emptyParent;
1042     frame->loader()->load(FrameLoadRequest(
1043         frame,
1044         ResourceRequest(KURL(emptyParent, String(env, url)))
1045     ));
1046 }
1047 
1048 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkLoad
1049     (JNIEnv* env, jobject self, jlong pFrame, jstring text, jstring contentType)
1050 {
1051     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1052     if (!frame || !frame->loader()) {
1053         return;
1054     }
1055 
1056     const char* stringChars = env->GetStringUTFChars(text, JNI_FALSE);
1057     size_t stringLen = (size_t)env->GetStringUTFLength(text);
1058     RefPtr<SharedBuffer> buffer = SharedBuffer::create(stringChars, (int)stringLen);
1059 
1060     static const KURL emptyUrl(ParsedURLString, "");
1061     frame->loader()->load(FrameLoadRequest(
1062         frame,
1063         ResourceRequest(emptyUrl),
1064         SubstituteData(
1065             buffer,
1066             String(env, contentType),
1067             "UTF-8",
1068             emptyUrl)
1069     ));
1070 
1071     env->ReleaseStringUTFChars(text, stringChars);
1072 }
1073 
1074 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkStop
1075     (JNIEnv* env, jobject self, jlong pFrame)
1076 {
1077     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1078     if (!frame || !frame->loader()) {
1079         return;
1080     }
1081 
1082     frame->loader()->stopAllLoaders();
1083 }
1084 
1085 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkStopAll
1086     (JNIEnv* env, jobject self, jlong pPage)
1087 {
1088     Page* page = WebPage::pageFromJLong(pPage);
1089     if (!page || !page->mainFrame()) {
1090         return;
1091     }
1092 
1093     page->mainFrame()->loader()->stopAllLoaders();
1094 }
1095 
1096 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkRefresh
1097     (JNIEnv* env, jobject self, jlong pFrame)
1098 {
1099     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1100     if (!frame || !frame->loader()) {
1101         return;
1102     }
1103 
1104     frame->loader()->reload(true);
1105 }
1106 
1107 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkGoBackForward
1108     (JNIEnv* env, jobject self, jlong pPage, jint distance)
1109 {
1110     Page* page = WebPage::pageFromJLong(pPage);
1111     if (!page) {
1112         return JNI_FALSE;
1113     }
1114 
1115     if (page->canGoBackOrForward(distance)) {
1116         page->goBackOrForward(distance);
1117         return JNI_TRUE;
1118     }
1119 
1120     return JNI_FALSE;
1121 }
1122 
1123 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkCopy
1124     (JNIEnv* env, jobject self, jlong pFrame)
1125 {
1126     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1127     if (!frame) {
1128         return JNI_FALSE;
1129     }
1130 
1131     if (frame->editor().canCopy()) {
1132         frame->editor().copy();
1133         return JNI_TRUE;
1134     }
1135 
1136     return JNI_FALSE;
1137 }
1138 
1139 
1140 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkFindInPage
1141     (JNIEnv* env, jobject self, jlong pPage,
1142      jstring toFind, jboolean forward, jboolean wrap, jboolean matchCase)
1143 {
1144     Page* page = WebPage::pageFromJLong(pPage);
1145     if (page) {
1146         return bool_to_jbool(page->findString(String(env, toFind),
1147                                               matchCase ? TextCaseSensitive : TextCaseInsensitive,
1148                                               forward ? FindDirectionForward : FindDirectionBackward,
1149                                               bool_to_jbool(wrap)));
1150     }
1151     return JNI_FALSE;
1152 }
1153 
1154 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkFindInFrame
1155     (JNIEnv* env, jobject self, jlong pFrame,
1156      jstring toFind, jboolean forward, jboolean wrap, jboolean matchCase)
1157 {
1158     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1159     if (frame) {
1160         //utatodo: support for the rest of FindOptionFlag
1161         return bool_to_jbool(frame->page()->findString(
1162             String(env, toFind),
1163             (forward ? 0 : Backwards)
1164             || (wrap ? WrapAround : 0)
1165             || (matchCase ? 0 : CaseInsensitive)
1166             || ( true ? StartInSelection : 0)));
1167     }
1168     return JNI_FALSE;
1169 }
1170 
1171 JNIEXPORT jfloat JNICALL Java_com_sun_webkit_WebPage_twkGetZoomFactor
1172     (JNIEnv* env, jobject self, jlong pFrame, jboolean textOnly)
1173 {
1174     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1175     ASSERT(frame);
1176     if (!frame) {
1177         return 1.0;
1178     }
1179     return textOnly
1180         ? frame->textZoomFactor()
1181         : frame->pageZoomFactor();
1182 }
1183 
1184 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkSetZoomFactor
1185     (JNIEnv* env, jobject self, jlong pFrame, jfloat zoomFactor, jboolean textOnly)
1186 {
1187     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1188     ASSERT(frame);
1189     if (!frame) {
1190         return;
1191     }
1192     if (textOnly) {
1193         frame->setTextZoomFactor(zoomFactor);
1194     } else {
1195         frame->setPageZoomFactor(zoomFactor);
1196     }
1197 }
1198 
1199 JNIEXPORT jobject JNICALL Java_com_sun_webkit_WebPage_twkExecuteScript
1200     (JNIEnv* env, jobject self, jlong pFrame, jstring script)
1201 {
1202     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1203     if (!frame || !frame->script()) {
1204         return NULL;
1205     }
1206     JSGlobalContextRef globalContext = getGlobalContext(frame->script());
1207     RefPtr<JSC::Bindings::RootObject> rootObject(frame->script()->createRootObject(frame));
1208     return WebCore::executeScript(
1209         env,
1210         NULL,
1211         globalContext,
1212         rootObject.get(),
1213         script);
1214 }
1215 
1216 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkAddJavaScriptBinding
1217     (JNIEnv* env, jobject self, jlong pFrame, jstring name, jobject value, jobject accessControlContext)
1218 {
1219     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1220     if (!frame || !frame->script()) {
1221         return;
1222     }
1223     JSGlobalContextRef globalContext = getGlobalContext(frame->script());
1224     JSObjectRef window = JSContextGetGlobalObject(globalContext);
1225     RefPtr<JSC::Bindings::RootObject> rootObject(frame->script()->createRootObject(frame));
1226 
1227     JSValueRef jsval = WebCore::Java_Object_to_JSValue(
1228         env,
1229         globalContext,
1230         rootObject.get(),
1231         value, accessControlContext);
1232 
1233     JSStringRef jsname = asJSStringRef(env, name);
1234     JSValueRef exception;
1235     if (JSValueIsUndefined(globalContext, jsval)) {
1236         JSObjectDeleteProperty(globalContext, window, jsname, &exception);
1237     } else {
1238         JSPropertyAttributes attributes = 0;
1239         JSObjectSetProperty(globalContext, window, jsname, jsval, attributes, &exception);
1240     }
1241 }
1242 
1243 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkReset
1244     (JNIEnv* env, jobject self, jlong pFrame)
1245 {
1246     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1247     if (!frame || !frame->tree()) {
1248         return;
1249     }
1250 
1251     frame->tree()->clearName();
1252 }
1253 
1254 JNIEXPORT jint JNICALL Java_com_sun_webkit_WebPage_twkBeginPrinting
1255     (JNIEnv* env, jobject self, jlong pPage, jfloat width, jfloat height)
1256 {
1257     return WebPage::webPageFromJLong(pPage)->beginPrinting(width, height);
1258 }
1259 
1260 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkEndPrinting
1261     (JNIEnv* env, jobject self, jlong pPage)
1262 {
1263     return WebPage::webPageFromJLong(pPage)->endPrinting();
1264 }
1265 
1266 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkPrint
1267     (JNIEnv* env, jobject self, jlong pPage, jobject rq, jint pageIndex, jfloat width)
1268 {
1269     PlatformContextJava* ppgc = new PlatformContextJava(rq);
1270     GraphicsContext gc(ppgc);
1271     WebPage::webPageFromJLong(pPage)->print(gc, pageIndex, width);
1272 }
1273 
1274 JNIEXPORT jint JNICALL Java_com_sun_webkit_WebPage_twkGetFrameHeight
1275     (JNIEnv* env, jobject self, jlong pFrame)
1276 {
1277     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1278     if (!frame || !frame->contentRenderer()) {
1279         return 0;
1280     }
1281 
1282     return frame->contentRenderer()->viewLogicalHeight();
1283 /*
1284     bool isFrameSet = frame->document() && frame->document()->isFrameSet();
1285     if (isFrameSet) {
1286         RenderView* root = static_cast<RenderView*>(frame->document()->renderer());
1287         return root->bottomLayoutOverflow();
1288     } else {
1289         return frame->contentRenderer()->bottomLayoutOverflow();
1290     }
1291 */
1292 }
1293 
1294 JNIEXPORT jfloat JNICALL Java_com_sun_webkit_WebPage_twkAdjustFrameHeight
1295     (JNIEnv* env, jobject self, jlong pFrame,
1296      jfloat oldTop, jfloat oldBottom, jfloat bottomLimit)
1297 {
1298     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1299     if (!frame || !frame->view()) {
1300         return oldBottom;
1301     }
1302 
1303     float result;
1304     frame->view()->adjustPageHeightDeprecated(&result, oldTop, oldBottom, bottomLimit);
1305     return result;
1306 }
1307 
1308 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkSetBounds
1309     (JNIEnv* env, jobject self, jlong pPage, jint x, jint y, jint w, jint h)
1310 {
1311     WebPage::webPageFromJLong(pPage)->setSize(IntSize(w, h));
1312 }
1313 
1314 JNIEXPORT jintArray JNICALL Java_com_sun_webkit_WebPage_twkGetVisibleRect
1315     (JNIEnv* env, jobject self, jlong pFrame)
1316 {
1317     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1318     if (!frame || !frame->view()) {
1319         return NULL;
1320     }
1321     IntRect rect = frame->view()->visibleContentRect();
1322 
1323     jintArray result = env->NewIntArray(4);
1324     CheckAndClearException(env);
1325 
1326     jint* arr = (jint*)env->GetPrimitiveArrayCritical(result, NULL);
1327     arr[0] = rect.x();
1328     arr[1] = rect.y();
1329     arr[2] = rect.width();
1330     arr[3] = rect.height();
1331     env->ReleasePrimitiveArrayCritical(result, arr, 0);
1332 
1333     return result;
1334 }
1335 
1336 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkScrollToPosition
1337     (JNIEnv* env, jobject self, jlong pFrame, jint x, jint y)
1338 {
1339     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1340     if (!frame || !frame->view()) {
1341         return;
1342     }
1343     frame->view()->setScrollPosition(IntPoint(x, y));
1344 }
1345 
1346 JNIEXPORT jintArray JNICALL Java_com_sun_webkit_WebPage_twkGetContentSize
1347     (JNIEnv* env, jobject self, jlong pFrame)
1348 {
1349     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1350     if (!frame || !frame->view()) {
1351         return NULL;
1352     }
1353     IntSize size = frame->view()->contentsSize();
1354 
1355     jintArray result = env->NewIntArray(2);
1356     CheckAndClearException(env);
1357 
1358     jint* arr = (jint*)env->GetPrimitiveArrayCritical(result, NULL);
1359     arr[0] = size.width();
1360     arr[1] = size.height();
1361     env->ReleasePrimitiveArrayCritical(result, arr, 0);
1362 
1363     return result;
1364 }
1365 
1366 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkSetTransparent
1367 (JNIEnv* env, jobject self, jlong pFrame, jboolean isTransparent)
1368 {
1369     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1370     if (!frame || !frame->view()) {
1371         return;
1372     }
1373     frame->view()->setTransparent(isTransparent);
1374 }
1375 
1376 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkSetBackgroundColor
1377 (JNIEnv* env, jobject self, jlong pFrame, jint backgroundColor)
1378 {
1379     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
1380     if (!frame || !frame->view()) {
1381         return;
1382     }
1383     frame->view()->setBaseBackgroundColor(Color(RGBA32(backgroundColor)));
1384 }
1385 
1386 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkPrePaint
1387   (JNIEnv*, jobject, jlong pPage)
1388 {
1389     WebPage::webPageFromJLong(pPage)->prePaint();
1390 }
1391 
1392 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkUpdateContent
1393     (JNIEnv* env, jobject self, jlong pPage, jobject rq, jint x, jint y, jint w, jint h)
1394 {
1395     WebPage::webPageFromJLong(pPage)->paint(rq, x, y, w, h);
1396 }
1397 
1398 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkPostPaint
1399   (JNIEnv*, jobject, jlong pPage, jobject rq, jint x, jint y, jint w, jint h)
1400 {
1401     WebPage::webPageFromJLong(pPage)->postPaint(rq, x, y, w, h);
1402 }
1403 
1404 JNIEXPORT jstring JNICALL Java_com_sun_webkit_WebPage_twkGetEncoding
1405     (JNIEnv* env, jobject self, jlong pPage)
1406 {
1407     Page* p = WebPage::pageFromJLong(pPage);
1408     ASSERT(p);
1409     Frame* mainFrame = p->mainFrame();
1410     ASSERT(mainFrame);
1411 
1412     if (mainFrame->loader()) {
1413         return mainFrame->document()->charset().toJavaString(env).releaseLocal();
1414     }
1415     return NULL;
1416 }
1417 
1418 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkSetEncoding
1419     (JNIEnv* env, jobject self, jlong pPage, jstring encoding)
1420 {
1421     Page* p = WebPage::pageFromJLong(pPage);
1422     ASSERT(p);
1423     Frame* mainFrame = p->mainFrame();
1424     ASSERT(mainFrame);
1425 
1426     if (mainFrame->loader()) {
1427         mainFrame->loader()->reloadWithOverrideEncoding(String(env, encoding));
1428     }
1429 }
1430 
1431 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkProcessFocusEvent
1432     (JNIEnv* env, jobject self, jlong pPage,
1433      jint id, jint direction)
1434 {
1435     Page* page = WebPage::pageFromJLong(pPage);
1436     Frame* mainFrame = page->mainFrame();
1437 
1438     FocusController* focusController = page->focusController();
1439     ASSERT(focusController);
1440     if (!focusController) {
1441         return;
1442     }
1443 
1444     Frame* focusedFrame = focusController->focusedFrame();
1445     switch (id) {
1446         case com_sun_webkit_event_WCFocusEvent_FOCUS_GAINED:
1447             focusController->setActive(true); // window activation
1448             focusController->setFocused(true); // focus gained
1449             if (!focusedFrame) {
1450                 focusController->setFocusedFrame(mainFrame);
1451                 focusedFrame = mainFrame;
1452             }
1453             if (direction == com_sun_webkit_event_WCFocusEvent_FORWARD) {
1454                 // comment out the following line to get focus to the last
1455                 // focused node instead of the first focusable one
1456                 focusedFrame->document()->setFocusedNode(0);
1457                 focusController->advanceFocus(FocusDirectionForward, 0);
1458             } else if (direction == com_sun_webkit_event_WCFocusEvent_BACKWARD) {
1459                 // comment out the following line to get focus to the last
1460                 // focused node instead of the last focusable one
1461                 focusedFrame->document()->setFocusedNode(0);
1462                 focusController->advanceFocus(FocusDirectionBackward, 0);
1463             }
1464             break;
1465         case com_sun_webkit_event_WCFocusEvent_FOCUS_LOST:
1466             focusController->setFocused(false); // focus lost
1467             focusController->setActive(false); // window deactivation
1468             break;
1469     }
1470 }
1471 
1472 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkProcessKeyEvent
1473     (JNIEnv* env, jobject self, jlong pPage,
1474      jint type, jstring text, jstring keyIdentifier, jint windowsVirtualKeyCode,
1475      jboolean shift, jboolean ctrl, jboolean alt, jboolean meta)
1476 {
1477     WebPage* webPage = WebPage::webPageFromJLong(pPage);
1478 
1479     PlatformKeyboardEvent event(type, text, keyIdentifier,
1480                                 windowsVirtualKeyCode,
1481                                 shift, ctrl, alt, meta);
1482 
1483     return bool_to_jbool(webPage->processKeyEvent(event));
1484 }
1485 
1486 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkProcessMouseEvent
1487     (JNIEnv* env, jobject self, jlong pPage,
1488      jint id, jint button, jint clickCount,
1489      jint x, jint y, jint screenX, jint screenY,
1490      jboolean shift, jboolean ctrl, jboolean alt, jboolean meta,
1491      jboolean popupTrigger, jfloat timestamp)
1492 {
1493     Page* page = WebPage::pageFromJLong(pPage);
1494     Frame* frame = page->mainFrame();
1495 
1496     // Uncomment to debug mouse events
1497     // fprintf(stderr, "twkProcessKeyEvent: "
1498     //         "id=%d button=%d clickCount=%d x=%d y=%d"
1499     //         "screenX=%d screenY=%d \n",
1500     //         id, button, clickCount, x, y, screenX, screenY);
1501 
1502     EventHandler* eventHandler = frame->eventHandler();
1503     ASSERT(eventHandler);
1504     if (!eventHandler) {
1505         return false;
1506     }
1507 
1508     FrameView* frameView = frame->view();
1509     if (!frameView) {
1510         return false;
1511     }
1512 
1513     bool consumeEvent = false;
1514     IntPoint loc(x, y);
1515     PlatformMouseEvent mouseEvent = PlatformMouseEvent(loc,
1516                                                        IntPoint(screenX, screenY),
1517                                                        getWebCoreMouseButton(button),
1518                                                        getWebCoreMouseEventType(id),
1519                                                        clickCount,
1520                                                        shift, ctrl, alt, meta,
1521                                                        timestamp);
1522     switch (id) {
1523     case com_sun_webkit_event_WCMouseEvent_MOUSE_PRESSED:
1524         //frame->focusWindow();
1525         page->chrome().focus();
1526         consumeEvent = eventHandler->handleMousePressEvent(mouseEvent);
1527         break;
1528     case com_sun_webkit_event_WCMouseEvent_MOUSE_RELEASED:
1529         consumeEvent = eventHandler->handleMouseReleaseEvent(mouseEvent);
1530         break;
1531     case com_sun_webkit_event_WCMouseEvent_MOUSE_MOVED:
1532     case com_sun_webkit_event_WCMouseEvent_MOUSE_DRAGGED:
1533         consumeEvent = eventHandler->mouseMoved(mouseEvent);
1534         break;
1535     }
1536 
1537     if (popupTrigger && page->settings()->isContextMenuEnabled()) {
1538         ContextMenuController* cmc = page->contextMenuController();
1539         cmc->clearContextMenu();
1540         bool handleEvent = eventHandler->sendContextMenuEvent(mouseEvent);
1541         if (!handleEvent) {
1542             return consumeEvent;
1543         }
1544 
1545         ContextMenu* contextMenu = cmc->contextMenu();
1546         // right-click in disabled text area (and probably many other
1547         // scenarios) result in NULL contextMenu here
1548         if (!contextMenu) {
1549             return consumeEvent;
1550         }
1551 
1552         Node* node = cmc->hitTestResult().innerNonSharedNode();
1553         if (!node) {
1554             return consumeEvent;
1555         }
1556 
1557         Frame* frame = node->document()->frame();
1558         // we do not want to show context menu for frameset (see 6648628)
1559         if (frame && !frame->document()->isFrameSet()) {
1560             contextMenu->show(cmc, loc);
1561         }
1562         return JNI_TRUE;
1563     }
1564 
1565     return bool_to_jbool(consumeEvent);
1566 }
1567 
1568 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkProcessMouseWheelEvent
1569     (JNIEnv* env, jobject self, jlong pPage,
1570      jint x, jint y, jint screenX, jint screenY,
1571      jfloat deltaX, jfloat deltaY,
1572      jboolean shift, jboolean ctrl, jboolean alt, jboolean meta,
1573      jfloat timestamp)
1574 {
1575     Page* page = WebPage::pageFromJLong(pPage);
1576     Frame* frame = page->mainFrame();
1577 
1578     ASSERT(frame->eventHandler());
1579     if (!frame->eventHandler()) {
1580         return JNI_FALSE;
1581     }
1582 
1583     PlatformWheelEvent wheelEvent = PlatformWheelEvent(IntPoint(x, y),
1584                                                        IntPoint(screenX, screenY),
1585                                                        deltaX, deltaY,
1586                                                        shift, ctrl, alt, meta);
1587     bool consumeEvent = frame->eventHandler()->handleWheelEvent(wheelEvent);
1588 
1589     return bool_to_jbool(consumeEvent);
1590 }
1591 
1592 #if ENABLE(TOUCH_EVENTS)
1593 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkProcessTouchEvent
1594     (JNIEnv* env, jobject self, jlong pPage, jint id, jobject touchData,
1595      jboolean shift, jboolean ctrl, jboolean alt, jboolean meta, jfloat timestamp)
1596 {
1597     Page* page = WebPage::pageFromJLong(pPage);
1598     Frame* frame = page->mainFrame();
1599 
1600     ASSERT(frame->eventHandler());
1601     if (!frame->eventHandler()) {
1602         return JNI_FALSE;
1603     }
1604 
1605     PlatformTouchEvent ev(env, id, touchData, shift, ctrl, alt, meta, timestamp);
1606     bool consumeEvent = frame->eventHandler()->handleTouchEvent(ev);
1607     return bool_to_jbool(consumeEvent);
1608 }
1609 #endif
1610 
1611 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkProcessInputTextChange
1612     (JNIEnv* env, jobject self, jlong pPage,
1613      jstring jcommitted, jstring jcomposed, jintArray jattributes, jint caretPosition)
1614 {
1615     Page* page = WebPage::pageFromJLong(pPage);
1616 
1617     ASSERT(page->focusController());
1618     Frame* frame = page->focusController()->focusedOrMainFrame();
1619     ASSERT(frame && frame->eventHandler());
1620 
1621     if (!frame || !frame->eventHandler() || !frame->editor().canEdit()) {
1622         // There's no client to deliver the event. Consume the event
1623         // so that it won't be delivered to a wrong webkit client.
1624         return JNI_TRUE;
1625     }
1626 
1627     // Process committed text first
1628     if (env->GetStringLength(jcommitted) > 0 ||
1629             // if both committed and composed are empty, confirm with an empty text
1630             (env->GetStringLength(jcomposed) == 0)) {
1631         String committed = String(env, jcommitted);
1632         frame->editor().confirmComposition(committed);
1633     }
1634 
1635     // Process composed (composition) text here
1636     if (env->GetStringLength(jcomposed) > 0) {
1637         jsize length = env->GetArrayLength(jattributes);
1638         Vector<CompositionUnderline> underlines;
1639         underlines.resize(length / 3); // 3 members per element
1640         jint* attrs = env->GetIntArrayElements(jattributes, NULL);
1641         if (attrs) {
1642             for (int i = 0; i < length;) {
1643                 int x = i / 3;
1644                 underlines[x].startOffset = attrs[i++];
1645                 underlines[x].endOffset = attrs[i++];
1646                 underlines[x].thick = (attrs[i++] == 1);
1647                 underlines[x].color = Color(0, 0, 0);
1648             }
1649             env->ReleaseIntArrayElements(jattributes, attrs, JNI_ABORT);
1650         }
1651         String composed = String(env, jcomposed);
1652         frame->editor().setComposition(composed, underlines, caretPosition, 0);
1653     }
1654     return JNI_TRUE;
1655 }
1656 
1657 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkProcessCaretPositionChange
1658     (JNIEnv* env, jobject self, jlong pPage,
1659      jint caretPosition)
1660 {
1661     Page* page = WebPage::pageFromJLong(pPage);
1662 
1663     ASSERT(page->focusController());
1664     Frame* frame = page->focusController()->focusedOrMainFrame();
1665 
1666     ASSERT(frame && frame->eventHandler());
1667     if (!frame->eventHandler()) {
1668         return JNI_FALSE;
1669     }
1670 
1671     RefPtr<Text> text = frame->editor().compositionNode();
1672     if (!text) {
1673         return JNI_FALSE;
1674     }
1675 
1676     // FIXME: the following code may not work with having committed text
1677     Position position(text, caretPosition);
1678     VisibleSelection selection(position, DOWNSTREAM);
1679     frame->selection()->setSelection(selection, CharacterGranularity);//true, false, false
1680     return JNI_TRUE;
1681 }
1682 
1683 JNIEXPORT jintArray JNICALL Java_com_sun_webkit_WebPage_twkGetTextLocation
1684     (JNIEnv* env, jobject self, jlong pPage, jint charindex)
1685 {
1686     Page* page = WebPage::pageFromJLong(pPage);
1687     Frame* frame = page->mainFrame();
1688 
1689     jintArray result = env->NewIntArray(4);
1690     CheckAndClearException(env); // OOME
1691 
1692     FrameView* frameView = frame->view();
1693     if (frameView) {
1694         IntRect caret = frame->selection()->absoluteCaretBounds();
1695         caret = frameView->contentsToWindow(caret);
1696         jint* ints = (jint*) env->GetPrimitiveArrayCritical(result, NULL);
1697         ints[0] = caret.x();
1698         ints[1] = caret.y();
1699         ints[2] = caret.width();
1700         ints[3] = caret.height();
1701         env->ReleasePrimitiveArrayCritical(result, ints, JNI_ABORT);
1702     }
1703 
1704     return result;
1705 }
1706 
1707 JNIEXPORT jint JNICALL Java_com_sun_webkit_WebPage_twkGetLocationOffset
1708     (JNIEnv* env, jobject self, jlong pPage, jint x, jint y)
1709 {
1710     // Returns -1 if there's no composition text or the given
1711     // coordinate is out of the composition text range.
1712 
1713     Page* page = WebPage::pageFromJLong(pPage);
1714     Frame* frame = page->mainFrame();
1715 
1716     FrameView* frameView = frame->view();
1717     if (!frameView) {
1718         return 0;
1719     }
1720 
1721     jint offset = -1;
1722     IntPoint point = IntPoint(x, y);
1723     point = frameView->windowToContents(point);
1724 
1725     Editor &editor = frame->editor();
1726     if (editor.hasComposition()) {
1727         RefPtr<Range> range = editor.compositionRange();
1728         ExceptionCode ec = 0;
1729         for (Node* node = range.get()->startContainer(ec); node; node = NodeTraversal::next(node)) {
1730             RenderObject* renderer = node->renderer();
1731             IntRect content = renderer->absoluteBoundingBoxRect();
1732             VisiblePosition targetPosition(renderer->positionForPoint(LayoutPoint(point.x() - content.x(),
1733                                                                             point.y() - content.y())));
1734             offset = targetPosition.deepEquivalent().offsetInContainerNode();
1735             if (offset >= editor.compositionStart() && offset < editor.compositionEnd()) {
1736                 offset -= editor.compositionStart();
1737                 break;
1738             }
1739         }
1740     }
1741     return offset;
1742 }
1743 
1744 JNIEXPORT jint JNICALL Java_com_sun_webkit_WebPage_twkGetInsertPositionOffset
1745     (JNIEnv *env, jobject self, jlong pPage)
1746 {
1747     Page* page = WebPage::pageFromJLong(pPage);
1748     Frame* frame = page->mainFrame();
1749 
1750     jint position = 0;
1751     Editor &editor = frame->editor();
1752     if (editor.canEdit()) {
1753         VisibleSelection selection = frame->selection()->selection();
1754         if (selection.isCaret()) {
1755             VisiblePosition caret = selection.visibleStart();
1756             position = caret.deepEquivalent().offsetInContainerNode();
1757             if (editor.hasComposition()) {
1758                 int start = editor.compositionStart();
1759                 int end = editor.compositionEnd();
1760                 if (start < position && position <= end) {
1761                     position = start;
1762                 } else if (position > end) {
1763                     position -= end - start;
1764                 }
1765             }
1766         }
1767     }
1768     return position;
1769 }
1770 
1771 JNIEXPORT jint JNICALL Java_com_sun_webkit_WebPage_twkGetCommittedTextLength
1772     (JNIEnv *env, jobject self, jlong pPage)
1773 {
1774     Page* page = WebPage::pageFromJLong(pPage);
1775     Frame* frame = page->mainFrame();
1776 
1777     jint length = 0;
1778     Editor &editor = frame->editor();
1779     if (editor.canEdit()) {
1780         RefPtr<Range> range = rangeOfContents(frame->selection()->start().element());
1781         // Code derived from Range::toString
1782         Node* pastLast = range.get()->pastLastNode();
1783         for (Node* n = range.get()->firstNode(); n != pastLast; n = NodeTraversal::next(n)) {
1784             if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SECTION_NODE) {
1785                 length += static_cast<CharacterData*>(n)->data().length();
1786             }
1787         }
1788         // Exclude the composition part if any
1789         if (editor.hasComposition()) {
1790             int start = editor.compositionStart();
1791             int end = editor.compositionEnd();
1792             length -= end - start;
1793         }
1794     }
1795     return length;
1796 }
1797 
1798 JNIEXPORT jstring JNICALL Java_com_sun_webkit_WebPage_twkGetCommittedText
1799     (JNIEnv *env, jobject self, jlong pPage)
1800 {
1801     Page* page = WebPage::pageFromJLong(pPage);
1802     Frame* frame = page->mainFrame();
1803 
1804     jstring text = 0;
1805 
1806     Editor &editor = frame->editor();
1807     if (editor.canEdit()) {
1808         RefPtr<Range> range = rangeOfContents(frame->selection()->start().element());
1809         if (range) {
1810             String t = plainText(range.get());
1811             // Exclude the composition text if any
1812             if (editor.hasComposition()) {
1813                 String s;
1814                 int start = editor.compositionStart();
1815                 int end = editor.compositionEnd();
1816                 int length = t.length() - (end - start);
1817                 if (start > 0) {
1818                     s = t.substring(0, start);
1819                 }
1820                 if (s.length() == length) {
1821                     t = s;
1822                 } else {
1823                     t = s + t.substring(end, length - start);
1824                 }
1825             }
1826             text = env->NewString(reinterpret_cast<const jchar *>(t.characters()), t.length());
1827             CheckAndClearException(env); // OOME
1828         }
1829     }
1830     return text;
1831 }
1832 
1833 JNIEXPORT jstring JNICALL Java_com_sun_webkit_WebPage_twkGetSelectedText
1834     (JNIEnv *env, jobject self, jlong pPage)
1835 {
1836     Page* page = WebPage::pageFromJLong(pPage);
1837     Frame* frame = page->mainFrame();
1838 
1839     jstring text = 0;
1840 
1841     String t = frame->editor().selectedText();
1842     text = env->NewString(reinterpret_cast<const jchar *>(t.characters()), t.length());
1843     CheckAndClearException(env); // OOME
1844 
1845     return text;
1846 }
1847 
1848 //java.awt.dnd.DConstants
1849 enum JAVA_DND_ACTION {
1850     ACTION_NONE = 0x0,
1851     ACTION_COPY = 0x1,
1852     ACTION_MOVE = 0x2,
1853     ACTION_LINK = 0x40000000
1854 };
1855 
1856 static jint dragOperationToDragCursor(DragOperation op) {
1857     unsigned int res = ACTION_NONE;
1858     if (op & DragOperationCopy)
1859         res = ACTION_COPY;
1860     else if (op & DragOperationLink)
1861         res = ACTION_LINK;
1862     else if (op & DragOperationMove)
1863         res = ACTION_MOVE;
1864     else if (op & DragOperationGeneric)
1865         res = ACTION_MOVE; //This appears to be the Firefox behaviour
1866     return res;
1867 }
1868 
1869 static DragOperation keyStateToDragOperation(jint javaAction) {
1870     unsigned int action = DragOperationNone;
1871     if(javaAction & ACTION_COPY)
1872         action = DragOperationCopy;
1873     else if(javaAction & ACTION_LINK)
1874         action = DragOperationLink;
1875     else if(javaAction & ACTION_MOVE)
1876         action = DragOperationMove;
1877     return static_cast<DragOperation>(action);
1878 }
1879 
1880 JNIEXPORT jint JNICALL Java_com_sun_webkit_WebPage_twkProcessDrag
1881 (JNIEnv* env,
1882  jobject self,
1883  jlong pPage,
1884  jint actionId,
1885  jobjectArray jMimes, jobjectArray jValues,
1886  jint x, jint y,
1887  jint screenX, jint screenY,
1888  jint javaAction)
1889 {
1890     if (jMimes) {
1891         //TRAGET
1892         PassRefPtr<DataObjectJava> pr( DataObjectJava::create() );
1893         jint n = env->GetArrayLength(jMimes);
1894         for( jint j=0; j<n; ++j ){
1895             jstring value = (jstring)env->GetObjectArrayElement(jValues, j);
1896             if(value){
1897                 pr->setData(
1898                     String(env, JLString((jstring)env->GetObjectArrayElement(jMimes, j))),
1899                     String(env, JLString(value)));
1900             }
1901         }
1902         DragData dragData(
1903             pr.get(),
1904             IntPoint(x, y),
1905             IntPoint(screenX, screenY),
1906             keyStateToDragOperation(javaAction));
1907         DragController *dc = WebPage::pageFromJLong(pPage)->dragController();
1908 
1909         setCopyKeyState(ACTION_COPY == javaAction);
1910         switch(actionId){
1911         case com_sun_webkit_WebPage_DND_DST_EXIT:
1912             dc->dragExited(&dragData);
1913             return 0;
1914         case com_sun_webkit_WebPage_DND_DST_ENTER:
1915             return dragOperationToDragCursor( dc->dragEntered(&dragData).operation);
1916         case com_sun_webkit_WebPage_DND_DST_OVER:
1917         case com_sun_webkit_WebPage_DND_DST_CHANGE:
1918             return dragOperationToDragCursor(dc->dragUpdated(&dragData).operation);
1919         case com_sun_webkit_WebPage_DND_DST_DROP:
1920             {
1921                 int ret = dc->performDrag(&dragData) ? 1 : 0;
1922                 WebPage::pageFromJLong(pPage)->dragController()->dragEnded();
1923                 return ret;
1924             }
1925         }
1926     } else {
1927         //SOURCE
1928         EventHandler* eventHandler =
1929                 WebPage::pageFromJLong(pPage)->mainFrame()->eventHandler();
1930         PlatformMouseEvent mouseEvent = PlatformMouseEvent(
1931             IntPoint(x, y),
1932             IntPoint(screenX, screenY),
1933             com_sun_webkit_WebPage_DND_SRC_DROP!=actionId
1934                 ? LeftButton
1935                 : NoButton,
1936             PlatformEvent::MouseMoved,
1937             0,
1938             false, false, false, false, 0.0);
1939         switch(actionId){
1940         case com_sun_webkit_WebPage_DND_SRC_EXIT:
1941         case com_sun_webkit_WebPage_DND_SRC_ENTER:
1942         case com_sun_webkit_WebPage_DND_SRC_OVER:
1943         case com_sun_webkit_WebPage_DND_SRC_CHANGE:
1944 //            The method has been removed. See the changeset #de77cc97972d for the details.
1945 //            eventHandler->dragSourceMovedTo(mouseEvent);
1946             break;
1947         case com_sun_webkit_WebPage_DND_SRC_DROP:
1948             eventHandler->dragSourceEndedAt(mouseEvent, keyStateToDragOperation(javaAction));
1949             break;
1950         }
1951     }
1952     return 0;
1953 }
1954 
1955 static Editor* getEditor(Page* page) {
1956     ASSERT(page);
1957     ASSERT(page->focusController());
1958     Frame* frame = page->focusController()->focusedOrMainFrame();
1959     if (frame) {
1960         return &frame->editor();
1961     } else {
1962         return NULL;
1963     }
1964 }
1965 
1966 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkExecuteCommand
1967     (JNIEnv* env, jobject self, jlong pPage, jstring command, jstring value)
1968 {
1969     Page* page = WebPage::pageFromJLong(pPage);
1970     ASSERT(page);
1971     Editor* editor = getEditor(page);
1972     if (!editor) {
1973         return JNI_FALSE;
1974     }
1975     Editor::Command cmd = editor->command(String(env, command));
1976     return bool_to_jbool(cmd.execute(value ? String(env, value) : String()));
1977 }
1978 
1979 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkQueryCommandEnabled
1980     (JNIEnv* env, jobject self, jlong pPage, jstring command)
1981 {
1982     Page* page = WebPage::pageFromJLong(pPage);
1983     ASSERT(page);
1984     Editor* editor = getEditor(page);
1985     if (!editor) {
1986         return JNI_FALSE;
1987     }
1988     Editor::Command cmd = editor->command(String(env, command));
1989     return bool_to_jbool(cmd.isEnabled());
1990 }
1991 
1992 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkQueryCommandState
1993     (JNIEnv* env, jobject self, jlong pPage, jstring command)
1994 {
1995     Page* page = WebPage::pageFromJLong(pPage);
1996     ASSERT(page);
1997     Editor* editor = getEditor(page);
1998     if (!editor) {
1999         return JNI_FALSE;
2000     }
2001     Editor::Command cmd = editor->command(String(env, command));
2002     return bool_to_jbool(cmd.state() == TrueTriState);
2003 }
2004 
2005 JNIEXPORT jstring JNICALL Java_com_sun_webkit_WebPage_twkQueryCommandValue
2006     (JNIEnv* env, jobject self, jlong pPage, jstring command)
2007 {
2008     Page* page = WebPage::pageFromJLong(pPage);
2009     ASSERT(page);
2010     Editor* editor = getEditor(page);
2011     if (!editor) {
2012         return NULL;
2013     }
2014     Editor::Command cmd = editor->command(String(env, command));
2015     return cmd.value().toJavaString(env).releaseLocal();
2016 }
2017 
2018 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkIsEditable
2019     (JNIEnv* env, jobject self, jlong pPage)
2020 {
2021     Page* page = WebPage::pageFromJLong(pPage);
2022     ASSERT(page);
2023     if (!page) {
2024         return JNI_FALSE;
2025     }
2026     return bool_to_jbool(page->isEditable());
2027 }
2028 
2029 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkSetEditable
2030     (JNIEnv* env, jobject self, jlong pPage, jboolean editable)
2031 {
2032     Page* page = WebPage::pageFromJLong(pPage);
2033     ASSERT(page);
2034     if (!page) {
2035         return;
2036     }
2037     page->setEditable(jbool_to_bool(editable));
2038 }
2039 
2040 JNIEXPORT jstring JNICALL Java_com_sun_webkit_WebPage_twkGetHtml
2041     (JNIEnv* env, jobject self, jlong pFrame)
2042 {
2043     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
2044     if (!frame) {
2045         return 0;
2046     }
2047 
2048     Document* document = frame->document();
2049     if (!document || !document->isHTMLDocument()) {
2050         return 0;
2051     }
2052 
2053     HTMLElement* documentElement =
2054             static_cast<HTMLElement*>(document->documentElement());
2055     if (!documentElement) {
2056         return 0;
2057     }
2058 
2059     return documentElement->outerHTML().toJavaString(env).releaseLocal();
2060 }
2061 
2062 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkGetUsePageCache
2063     (JNIEnv*, jobject, jlong pPage)
2064 {
2065     ASSERT(pPage);
2066     Page* page = WebPage::pageFromJLong(pPage);
2067     ASSERT(page);
2068     return bool_to_jbool(page->settings()->usesPageCache());
2069 }
2070 
2071 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkSetUsePageCache
2072     (JNIEnv*, jobject, jlong pPage, jboolean usePageCache)
2073 {
2074     ASSERT(pPage);
2075     Page* page = WebPage::pageFromJLong(pPage);
2076     ASSERT(page);
2077     page->settings()->setUsesPageCache(jbool_to_bool(usePageCache));
2078 }
2079 
2080 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkIsJavaScriptEnabled
2081     (JNIEnv*, jobject, jlong pPage)
2082 {
2083     ASSERT(pPage);
2084     Page* page = WebPage::pageFromJLong(pPage);
2085     ASSERT(page);
2086     return bool_to_jbool(page->mainFrame()->script()->canExecuteScripts(NotAboutToExecuteScript));
2087 }
2088 
2089 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkSetJavaScriptEnabled
2090     (JNIEnv*, jobject, jlong pPage, jboolean enable)
2091 {
2092     ASSERT(pPage);
2093     Page* page = WebPage::pageFromJLong(pPage);
2094     ASSERT(page);
2095     page->settings()->setScriptEnabled(jbool_to_bool(enable));
2096 }
2097 
2098 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkIsContextMenuEnabled
2099     (JNIEnv*, jobject, jlong pPage)
2100 {
2101     ASSERT(pPage);
2102     Page* page = WebPage::pageFromJLong(pPage);
2103     ASSERT(page);
2104     return bool_to_jbool(page->settings()->isContextMenuEnabled());
2105 }
2106 
2107 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkSetContextMenuEnabled
2108     (JNIEnv*, jobject, jlong pPage, jboolean enable)
2109 {
2110     ASSERT(pPage);
2111     Page* page = WebPage::pageFromJLong(pPage);
2112     ASSERT(page);
2113     page->settings()->setContextMenuEnabled(jbool_to_bool(enable));
2114 }
2115 
2116 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkSetUserStyleSheetLocation
2117     (JNIEnv* env, jobject, jlong pPage, jstring url)
2118 {
2119     ASSERT(pPage);
2120     Page* page = WebPage::pageFromJLong(pPage);
2121     ASSERT(page);
2122     page->settings()->setUserStyleSheetLocation(KURL(KURL(), String(env, url)));
2123 }
2124 
2125 JNIEXPORT jstring JNICALL Java_com_sun_webkit_WebPage_twkGetUserAgent
2126     (JNIEnv* env, jobject, jlong pPage)
2127 {
2128     ASSERT(pPage);
2129     Page* page = WebPage::pageFromJLong(pPage);
2130     ASSERT(page);
2131     return page->settings()->userAgent().toJavaString(env).releaseLocal();
2132 }
2133 
2134 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkSetUserAgent
2135     (JNIEnv* env, jobject, jlong pPage, jstring userAgent)
2136 {
2137     ASSERT(pPage);
2138     Page* page = WebPage::pageFromJLong(pPage);
2139     ASSERT(page);
2140     page->settings()->setUserAgent(String(env, userAgent));
2141 }
2142 
2143 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkSetLocalStorageDatabasePath
2144   (JNIEnv* env, jobject, jlong pPage, jstring path)
2145 {
2146     ASSERT(pPage);
2147     Page* page = WebPage::pageFromJLong(pPage);
2148     ASSERT(page);
2149     Settings* settings = page->settings();
2150     settings->setLocalStorageDatabasePath(String(env, path));
2151 }
2152 
2153 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkSetLocalStorageEnabled
2154   (JNIEnv*, jobject, jlong pPage, jboolean enabled)
2155 {
2156     ASSERT(pPage);
2157     Page* page = WebPage::pageFromJLong(pPage);
2158     ASSERT(page);
2159     Settings* settings = page->settings();
2160     settings->setLocalStorageEnabled(jbool_to_bool(enabled));
2161 }
2162 
2163 JNIEXPORT jboolean JNICALL Java_com_sun_webkit_WebPage_twkGetDeveloperExtrasEnabled
2164   (JNIEnv *, jobject, jlong pPage)
2165 {
2166     ASSERT(pPage);
2167     Page* page = WebPage::pageFromJLong(pPage);
2168     ASSERT(page);
2169     return bool_to_jbool(page->settings()->developerExtrasEnabled());
2170 }
2171 
2172 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkSetDeveloperExtrasEnabled
2173   (JNIEnv *, jobject, jlong pPage, jboolean enabled)
2174 {
2175     ASSERT(pPage);
2176     Page* page = WebPage::pageFromJLong(pPage);
2177     ASSERT(page);
2178     page->settings()->setDeveloperExtrasEnabled(jbool_to_bool(enabled));
2179 }
2180 
2181 JNIEXPORT jint JNICALL Java_com_sun_webkit_WebPage_twkGetUnloadEventListenersCount
2182     (JNIEnv*, jobject, jlong pFrame)
2183 {
2184     ASSERT(pFrame);
2185     Frame* frame = static_cast<Frame*>(jlong_to_ptr(pFrame));
2186     ASSERT(frame);
2187     return (jint)frame->document()->domWindow()->pendingUnloadEventListeners();
2188 }
2189 
2190 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkConnectInspectorFrontend
2191   (JNIEnv *, jobject, jlong pPage)
2192 {
2193     Page *page = WebPage::pageFromJLong(pPage);
2194     if (page) {
2195         InspectorController *ic = page->inspectorController();
2196         if (ic) {
2197             InspectorClientJava *icj = static_cast<InspectorClientJava *>(ic->inspectorClient());
2198             if (icj) {
2199                 ic->connectFrontend(icj);
2200             }
2201         }
2202     }
2203     WebPage::webPageFromJLong(pPage)->debugStarted();
2204 }
2205 
2206 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkDisconnectInspectorFrontend
2207   (JNIEnv *, jobject, jlong pPage)
2208 {
2209     Page* page = WebPage::pageFromJLong(pPage);
2210     if (!page) {
2211         return;
2212     }
2213     page->inspectorController()->disconnectFrontend();
2214     WebPage::webPageFromJLong(pPage)->debugEnded();
2215 }
2216 
2217 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkDispatchInspectorMessageFromFrontend
2218   (JNIEnv* env, jobject, jlong pPage, jstring message)
2219 {
2220     Page* page = WebPage::pageFromJLong(pPage);
2221     if (!page) {
2222         return;
2223     }
2224     //utatodo: seems that RT-21428 will back again
2225     //JSDOMWindowBase::commonVM()->timeoutChecker.reset(); // RT-21428
2226     page->inspectorController()->dispatchMessageFromFrontend(
2227             String(env, message));
2228 }
2229 
2230 JNIEXPORT jint JNICALL Java_com_sun_webkit_WebPage_twkWorkerThreadCount
2231   (JNIEnv* env, jclass)
2232 {
2233     return WorkerThread::workerThreadCount();
2234 }
2235 
2236 #ifdef __cplusplus
2237 }
2238 #endif