/*
 * Copyright 2006, The Android Open Source Project
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#define LOG_TAG "webcoreglue"

#include "config.h"
#include "WebViewCore.h"

#include "AccessibilityObject.h"
#include "AndroidHitTestResult.h"
#include "ApplicationCacheStorage.h"
#include "Attribute.h"
#include "content/address_detector.h"
#include "Chrome.h"
#include "ChromeClientAndroid.h"
#include "ChromiumIncludes.h"
#include "ClientRect.h"
#include "ClientRectList.h"
#include "Color.h"
#include "CSSPropertyNames.h"
#include "CSSValueKeywords.h"
#include "DatabaseTracker.h"
#include "Document.h"
#include "DocumentMarkerController.h"
#include "DOMWindow.h"
#include "DOMSelection.h"
#include "Element.h"
#include "Editor.h"
#include "EditorClientAndroid.h"
#include "EventHandler.h"
#include "EventNames.h"
#include "ExceptionCode.h"
#include "FocusController.h"
#include "Font.h"
#include "FontCache.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameLoaderClientAndroid.h"
#include "FrameTree.h"
#include "FrameView.h"
#include "Geolocation.h"
#include "GraphicsContext.h"
#include "GraphicsJNI.h"
#include "HTMLAnchorElement.h"
#include "HTMLAreaElement.h"
#include "HTMLElement.h"
#include "HTMLFormControlElement.h"
#include "HTMLImageElement.h"
#include "HTMLInputElement.h"
#include "HTMLLabelElement.h"
#include "HTMLMapElement.h"
#include "HTMLNames.h"
#include "HTMLOptGroupElement.h"
#include "HTMLOptionElement.h"
#include "HTMLSelectElement.h"
#include "HTMLTextAreaElement.h"
#include "HistoryItem.h"
#include "HitTestRequest.h"
#include "HitTestResult.h"
#include "InlineTextBox.h"
#include "KeyboardEvent.h"
#include "MemoryUsage.h"
#include "NamedNodeMap.h"
#include "Navigator.h"
#include "Node.h"
#include "NodeList.h"
#include "Page.h"
#include "PageGroup.h"
#include "PictureLayerContent.h"
#include "PicturePileLayerContent.h"
#include "PlatformKeyboardEvent.h"
#include "PlatformString.h"
#include "PluginWidgetAndroid.h"
#include "PluginView.h"
#include "Position.h"
#include "ProgressTracker.h"
#include "Range.h"
#include "RenderBox.h"
#include "RenderImage.h"
#include "RenderInline.h"
#include "RenderLayer.h"
#include "RenderPart.h"
#include "RenderText.h"
#include "RenderTextControl.h"
#include "RenderThemeAndroid.h"
#include "RenderView.h"
#include "ResourceRequest.h"
#include "RuntimeEnabledFeatures.h"
#include "SchemeRegistry.h"
#include "ScopedLocalRef.h"
#include "ScriptController.h"
#include "SelectionController.h"
#include "SelectText.h"
#include "Settings.h"
#include "SkANP.h"
#include "SkTemplates.h"
#include "SkTDArray.h"
#include "SkTypes.h"
#include "SkCanvas.h"
#include "SkGraphics.h"
#include "SkPicture.h"
#include "SkUtils.h"
#include "Text.h"
#include "TextIterator.h"
#include "TilesManager.h"
#include "TypingCommand.h"
#include "WebCache.h"
#include "WebCoreFrameBridge.h"
#include "WebCoreJni.h"
#include "WebFrameView.h"
#include "WindowsKeyboardCodes.h"
#include "autofill/WebAutofill.h"
#include "htmlediting.h"
#include "markup.h"
#include "unicode/uloc.h"
#include "visible_units.h"

#include <JNIHelp.h>
#include <JNIUtility.h>
#include <androidfw/KeycodeLabels.h>
#include <cutils/properties.h>
#include <v8.h>
#include <wtf/CurrentTime.h>
#include <wtf/text/AtomicString.h>
#include <wtf/text/CString.h>
#include <wtf/text/StringImpl.h>

#if DEBUG_NAV_UI
#include "SkTime.h"
#endif

#if ENABLE(TOUCH_EVENTS) // Android
#include "PlatformTouchEvent.h"
#endif

#ifdef ANDROID_DOM_LOGGING
#include "AndroidLog.h"
#include "RenderTreeAsText.h"
#include <wtf/text/CString.h>

FILE* gDomTreeFile = 0;
FILE* gRenderTreeFile = 0;
#endif

#include "BaseLayerAndroid.h"

#if USE(ACCELERATED_COMPOSITING)
#include "GraphicsLayerAndroid.h"
#include "RenderLayerCompositor.h"
#endif

#define FOREGROUND_TIMER_INTERVAL 0.004 // 4ms
#define BACKGROUND_TIMER_INTERVAL 1.0 // 1s

// How many ms to wait for the scroll to "settle" before we will consider doing
// prerenders
#define PRERENDER_AFTER_SCROLL_DELAY 750

#define TOUCH_FLAG_HIT_HANDLER 0x1
#define TOUCH_FLAG_PREVENT_DEFAULT 0x2

////////////////////////////////////////////////////////////////////////////////////////////////

namespace android {

// Copied from CacheBuilder, not sure if this is needed/correct
IntRect getAreaRect(const HTMLAreaElement* area)
{
    Node* node = area->document();
    while ((node = node->traverseNextNode()) != NULL) {
        RenderObject* renderer = node->renderer();
        if (renderer && renderer->isRenderImage()) {
            RenderImage* image = static_cast<RenderImage*>(renderer);
            HTMLMapElement* map = image->imageMap();
            if (map) {
                Node* n;
                for (n = map->firstChild(); n;
                        n = n->traverseNextNode(map)) {
                    if (n == area) {
                        if (area->isDefault())
                            return image->absoluteBoundingBoxRect();
                        return area->computeRect(image);
                    }
                }
            }
        }
    }
    return IntRect();
}

// Copied from CacheBuilder, not sure if this is needed/correct
// TODO: See if this is even needed (I suspect not), and if not remove it
bool validNode(Frame* startFrame, void* matchFrame,
        void* matchNode)
{
    if (matchFrame == startFrame) {
        if (matchNode == NULL)
            return true;
        Node* node = startFrame->document();
        while (node != NULL) {
            if (node == matchNode) {
                const IntRect& rect = node->hasTagName(HTMLNames::areaTag) ?
                    getAreaRect(static_cast<HTMLAreaElement*>(node)) : node->getRect();
                // Consider nodes with empty rects that are not at the origin
                // to be valid, since news.google.com has valid nodes like this
                if (rect.x() == 0 && rect.y() == 0 && rect.isEmpty())
                    return false;
                return true;
            }
            node = node->traverseNextNode();
        }
        return false;
    }
    Frame* child = startFrame->tree()->firstChild();
    while (child) {
        bool result = validNode(child, matchFrame, matchNode);
        if (result)
            return result;
        child = child->tree()->nextSibling();
    }
    return false;
}

static SkTDArray<WebViewCore*> gInstanceList;

void WebViewCore::addInstance(WebViewCore* inst) {
    *gInstanceList.append() = inst;
}

void WebViewCore::removeInstance(WebViewCore* inst) {
    int index = gInstanceList.find(inst);
    ALOG_ASSERT(index >= 0, "RemoveInstance inst not found");
    if (index >= 0) {
        gInstanceList.removeShuffle(index);
    }
}

bool WebViewCore::isInstance(WebViewCore* inst) {
    return gInstanceList.find(inst) >= 0;
}

jobject WebViewCore::getApplicationContext() {

    // check to see if there is a valid webviewcore object
    if (gInstanceList.isEmpty())
        return 0;

    // get the context from the webview
    jobject context = gInstanceList[0]->getContext();

    if (!context)
        return 0;

    // get the application context using JNI
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    jclass contextClass = env->GetObjectClass(context);
    jmethodID appContextMethod = env->GetMethodID(contextClass, "getApplicationContext", "()Landroid/content/Context;");
    env->DeleteLocalRef(contextClass);
    jobject result = env->CallObjectMethod(context, appContextMethod);
    checkException(env);
    return result;
}


struct WebViewCoreStaticMethods {
    jmethodID    m_isSupportedMediaMimeType;
} gWebViewCoreStaticMethods;

// Check whether a media mimeType is supported in Android media framework.
bool WebViewCore::isSupportedMediaMimeType(const WTF::String& mimeType) {
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    jstring jMimeType = wtfStringToJstring(env, mimeType);
    jclass webViewCore = env->FindClass("android/webkit/WebViewCore");
    bool val = env->CallStaticBooleanMethod(webViewCore,
          gWebViewCoreStaticMethods.m_isSupportedMediaMimeType, jMimeType);
    checkException(env);
    env->DeleteLocalRef(webViewCore);
    env->DeleteLocalRef(jMimeType);

    return val;
}

// ----------------------------------------------------------------------------

// Field ids for WebViewCore
struct WebViewCoreFields {
    jfieldID    m_nativeClass;
    jfieldID    m_viewportWidth;
    jfieldID    m_viewportHeight;
    jfieldID    m_viewportInitialScale;
    jfieldID    m_viewportMinimumScale;
    jfieldID    m_viewportMaximumScale;
    jfieldID    m_viewportUserScalable;
    jfieldID    m_viewportDensityDpi;
    jfieldID    m_drawIsPaused;
    jfieldID    m_lowMemoryUsageMb;
    jfieldID    m_highMemoryUsageMb;
    jfieldID    m_highUsageDeltaMb;
} gWebViewCoreFields;

// ----------------------------------------------------------------------------

struct WebViewCore::JavaGlue {
    jweak       m_obj;
    jmethodID   m_scrollTo;
    jmethodID   m_contentDraw;
    jmethodID   m_requestListBox;
    jmethodID   m_openFileChooser;
    jmethodID   m_requestSingleListBox;
    jmethodID   m_jsAlert;
    jmethodID   m_jsConfirm;
    jmethodID   m_jsPrompt;
    jmethodID   m_jsUnload;
    jmethodID   m_jsInterrupt;
    jmethodID   m_getWebView;
    jmethodID   m_didFirstLayout;
    jmethodID   m_updateViewport;
    jmethodID   m_sendNotifyProgressFinished;
    jmethodID   m_sendViewInvalidate;
    jmethodID   m_updateTextfield;
    jmethodID   m_updateTextSelection;
    jmethodID   m_updateTextSizeAndScroll;
    jmethodID   m_clearTextEntry;
    jmethodID   m_restoreScale;
    jmethodID   m_needTouchEvents;
    jmethodID   m_requestKeyboard;
    jmethodID   m_exceededDatabaseQuota;
    jmethodID   m_reachedMaxAppCacheSize;
    jmethodID   m_populateVisitedLinks;
    jmethodID   m_geolocationPermissionsShowPrompt;
    jmethodID   m_geolocationPermissionsHidePrompt;
    jmethodID   m_getDeviceMotionService;
    jmethodID   m_getDeviceOrientationService;
    jmethodID   m_addMessageToConsole;
    jmethodID   m_focusNodeChanged;
    jmethodID   m_getPluginClass;
    jmethodID   m_showFullScreenPlugin;
    jmethodID   m_hideFullScreenPlugin;
    jmethodID   m_createSurface;
    jmethodID   m_addSurface;
    jmethodID   m_updateSurface;
    jmethodID   m_destroySurface;
    jmethodID   m_getContext;
    jmethodID   m_keepScreenOn;
    jmethodID   m_showRect;
    jmethodID   m_centerFitRect;
    jmethodID   m_setScrollbarModes;
    jmethodID   m_exitFullscreenVideo;
    jmethodID   m_setWebTextViewAutoFillable;
    jmethodID   m_selectAt;
    jmethodID   m_initEditField;
    jmethodID   m_chromeCanTakeFocus;
    jmethodID   m_chromeTakeFocus;
    AutoJObject object(JNIEnv* env) {
        // We hold a weak reference to the Java WebViewCore to avoid memeory
        // leaks due to circular references when WebView.destroy() is not
        // called manually. The WebView and hence the WebViewCore could become
        // weakly reachable at any time, after which the GC could null our weak
        // reference, so we have to check the return value of this method at
        // every use. Note that our weak reference will be nulled before the
        // WebViewCore is finalized.
        return getRealObject(env, m_obj);
    }
};

struct WebViewCore::TextFieldInitDataGlue {
    jmethodID  m_constructor;
    jfieldID   m_fieldPointer;
    jfieldID   m_text;
    jfieldID   m_type;
    jfieldID   m_isSpellCheckEnabled;
    jfieldID   m_isTextFieldNext;
    jfieldID   m_isTextFieldPrev;
    jfieldID   m_isAutoCompleteEnabled;
    jfieldID   m_name;
    jfieldID   m_label;
    jfieldID   m_maxLength;
    jfieldID   m_contentBounds;
    jfieldID   m_nodeLayerId;
    jfieldID   m_clientRect;
};

/*
 * WebViewCore Implementation
 */

static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[], const char signature[])
{
    jmethodID m = env->GetMethodID(clazz, name, signature);
    ALOG_ASSERT(m, "Could not find method %s", name);
    return m;
}

WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* mainframe)
    : m_touchGeneration(0)
    , m_lastGeneration(0)
    , m_javaGlue(new JavaGlue)
    , m_textFieldInitDataGlue(new TextFieldInitDataGlue)
    , m_mainFrame(mainframe)
    , m_popupReply(0)
    , m_blockTextfieldUpdates(false)
    , m_skipContentDraw(false)
    , m_textGeneration(0)
    , m_maxXScroll(320/4)
    , m_maxYScroll(240/4)
    , m_scrollOffsetX(0)
    , m_scrollOffsetY(0)
    , m_scrollSetTime(0)
    , m_mousePos(WebCore::IntPoint(0,0))
    , m_screenWidth(320)
    , m_screenHeight(240)
    , m_textWrapWidth(320)
    , m_scale(1.0f)
    , m_groupForVisitedLinks(0)
    , m_cacheMode(0)
    , m_fullscreenVideoMode(false)
    , m_matchCount(0)
    , m_activeMatchIndex(0)
    , m_activeMatch(0)
    , m_pluginInvalTimer(this, &WebViewCore::pluginInvalTimerFired)
    , m_screenOnCounter(0)
    , m_currentNodeDomNavigationAxis(0)
    , m_deviceMotionAndOrientationManager(this)
    , m_geolocationManager(this)
#if ENABLE(TOUCH_EVENTS)
    , m_forwardingTouchEvents(false)
#endif
    , m_webRequestContext(0)
    , m_prerenderEnabled(false)
{
    ALOG_ASSERT(m_mainFrame, "Uh oh, somehow a frameview was made without an initial frame!");

    jclass clazz = env->GetObjectClass(javaWebViewCore);
    m_javaGlue->m_obj = env->NewWeakGlobalRef(javaWebViewCore);
    m_javaGlue->m_scrollTo = GetJMethod(env, clazz, "contentScrollTo", "(IIZZ)V");
    m_javaGlue->m_contentDraw = GetJMethod(env, clazz, "contentDraw", "()V");
    m_javaGlue->m_requestListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[I[I)V");
    m_javaGlue->m_openFileChooser = GetJMethod(env, clazz, "openFileChooser", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
    m_javaGlue->m_requestSingleListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[II)V");
    m_javaGlue->m_jsAlert = GetJMethod(env, clazz, "jsAlert", "(Ljava/lang/String;Ljava/lang/String;)V");
    m_javaGlue->m_jsConfirm = GetJMethod(env, clazz, "jsConfirm", "(Ljava/lang/String;Ljava/lang/String;)Z");
    m_javaGlue->m_jsPrompt = GetJMethod(env, clazz, "jsPrompt", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
    m_javaGlue->m_jsUnload = GetJMethod(env, clazz, "jsUnload", "(Ljava/lang/String;Ljava/lang/String;)Z");
    m_javaGlue->m_jsInterrupt = GetJMethod(env, clazz, "jsInterrupt", "()Z");
    m_javaGlue->m_getWebView = GetJMethod(env, clazz, "getWebView", "()Landroid/webkit/WebView;");
    m_javaGlue->m_didFirstLayout = GetJMethod(env, clazz, "didFirstLayout", "(Z)V");
    m_javaGlue->m_updateViewport = GetJMethod(env, clazz, "updateViewport", "()V");
    m_javaGlue->m_sendNotifyProgressFinished = GetJMethod(env, clazz, "sendNotifyProgressFinished", "()V");
    m_javaGlue->m_sendViewInvalidate = GetJMethod(env, clazz, "sendViewInvalidate", "(IIII)V");
    m_javaGlue->m_updateTextfield = GetJMethod(env, clazz, "updateTextfield", "(ILjava/lang/String;I)V");
    m_javaGlue->m_updateTextSelection = GetJMethod(env, clazz, "updateTextSelection", "(IIIII)V");
    m_javaGlue->m_updateTextSizeAndScroll = GetJMethod(env, clazz, "updateTextSizeAndScroll", "(IIIII)V");
    m_javaGlue->m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "()V");
    m_javaGlue->m_restoreScale = GetJMethod(env, clazz, "restoreScale", "(FF)V");
    m_javaGlue->m_needTouchEvents = GetJMethod(env, clazz, "needTouchEvents", "(Z)V");
    m_javaGlue->m_requestKeyboard = GetJMethod(env, clazz, "requestKeyboard", "(Z)V");
    m_javaGlue->m_exceededDatabaseQuota = GetJMethod(env, clazz, "exceededDatabaseQuota", "(Ljava/lang/String;Ljava/lang/String;JJ)V");
    m_javaGlue->m_reachedMaxAppCacheSize = GetJMethod(env, clazz, "reachedMaxAppCacheSize", "(JJ)V");
    m_javaGlue->m_populateVisitedLinks = GetJMethod(env, clazz, "populateVisitedLinks", "()V");
    m_javaGlue->m_geolocationPermissionsShowPrompt = GetJMethod(env, clazz, "geolocationPermissionsShowPrompt", "(Ljava/lang/String;)V");
    m_javaGlue->m_geolocationPermissionsHidePrompt = GetJMethod(env, clazz, "geolocationPermissionsHidePrompt", "()V");
    m_javaGlue->m_getDeviceMotionService = GetJMethod(env, clazz, "getDeviceMotionService", "()Landroid/webkit/DeviceMotionService;");
    m_javaGlue->m_getDeviceOrientationService = GetJMethod(env, clazz, "getDeviceOrientationService", "()Landroid/webkit/DeviceOrientationService;");
    m_javaGlue->m_addMessageToConsole = GetJMethod(env, clazz, "addMessageToConsole", "(Ljava/lang/String;ILjava/lang/String;I)V");
    m_javaGlue->m_focusNodeChanged = GetJMethod(env, clazz, "focusNodeChanged", "(ILandroid/webkit/WebViewCore$WebKitHitTest;)V");
    m_javaGlue->m_getPluginClass = GetJMethod(env, clazz, "getPluginClass", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Class;");
    m_javaGlue->m_showFullScreenPlugin = GetJMethod(env, clazz, "showFullScreenPlugin", "(Landroid/webkit/ViewManager$ChildView;II)V");
    m_javaGlue->m_hideFullScreenPlugin = GetJMethod(env, clazz, "hideFullScreenPlugin", "()V");
    m_javaGlue->m_createSurface = GetJMethod(env, clazz, "createSurface", "(Landroid/view/View;)Landroid/webkit/ViewManager$ChildView;");
    m_javaGlue->m_addSurface = GetJMethod(env, clazz, "addSurface", "(Landroid/view/View;IIII)Landroid/webkit/ViewManager$ChildView;");
    m_javaGlue->m_updateSurface = GetJMethod(env, clazz, "updateSurface", "(Landroid/webkit/ViewManager$ChildView;IIII)V");
    m_javaGlue->m_destroySurface = GetJMethod(env, clazz, "destroySurface", "(Landroid/webkit/ViewManager$ChildView;)V");
    m_javaGlue->m_getContext = GetJMethod(env, clazz, "getContext", "()Landroid/content/Context;");
    m_javaGlue->m_keepScreenOn = GetJMethod(env, clazz, "keepScreenOn", "(Z)V");
    m_javaGlue->m_showRect = GetJMethod(env, clazz, "showRect", "(IIIIIIFFFF)V");
    m_javaGlue->m_centerFitRect = GetJMethod(env, clazz, "centerFitRect", "(IIII)V");
    m_javaGlue->m_setScrollbarModes = GetJMethod(env, clazz, "setScrollbarModes", "(II)V");
#if ENABLE(VIDEO)
    m_javaGlue->m_exitFullscreenVideo = GetJMethod(env, clazz, "exitFullscreenVideo", "()V");
#endif
    m_javaGlue->m_setWebTextViewAutoFillable = GetJMethod(env, clazz, "setWebTextViewAutoFillable", "(ILjava/lang/String;)V");
    m_javaGlue->m_selectAt = GetJMethod(env, clazz, "selectAt", "(II)V");
    m_javaGlue->m_initEditField = GetJMethod(env, clazz, "initEditField", "(IIILandroid/webkit/WebViewCore$TextFieldInitData;)V");
    m_javaGlue->m_chromeCanTakeFocus = GetJMethod(env, clazz, "chromeCanTakeFocus", "(I)Z");
    m_javaGlue->m_chromeTakeFocus = GetJMethod(env, clazz, "chromeTakeFocus", "(I)V");
    env->DeleteLocalRef(clazz);

    env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this);

    jclass tfidClazz = env->FindClass("android/webkit/WebViewCore$TextFieldInitData");
    m_textFieldInitDataGlue->m_fieldPointer = env->GetFieldID(tfidClazz, "mFieldPointer", "I");
    m_textFieldInitDataGlue->m_text = env->GetFieldID(tfidClazz, "mText", "Ljava/lang/String;");
    m_textFieldInitDataGlue->m_type = env->GetFieldID(tfidClazz, "mType", "I");
    m_textFieldInitDataGlue->m_isSpellCheckEnabled = env->GetFieldID(tfidClazz, "mIsSpellCheckEnabled", "Z");
    m_textFieldInitDataGlue->m_isTextFieldNext = env->GetFieldID(tfidClazz, "mIsTextFieldNext", "Z");
    m_textFieldInitDataGlue->m_isTextFieldPrev = env->GetFieldID(tfidClazz, "mIsTextFieldPrev", "Z");
    m_textFieldInitDataGlue->m_isAutoCompleteEnabled = env->GetFieldID(tfidClazz, "mIsAutoCompleteEnabled", "Z");
    m_textFieldInitDataGlue->m_name = env->GetFieldID(tfidClazz, "mName", "Ljava/lang/String;");
    m_textFieldInitDataGlue->m_label = env->GetFieldID(tfidClazz, "mLabel", "Ljava/lang/String;");
    m_textFieldInitDataGlue->m_maxLength = env->GetFieldID(tfidClazz, "mMaxLength", "I");
    m_textFieldInitDataGlue->m_contentBounds = env->GetFieldID(tfidClazz, "mContentBounds", "Landroid/graphics/Rect;");
    m_textFieldInitDataGlue->m_nodeLayerId = env->GetFieldID(tfidClazz, "mNodeLayerId", "I");
    m_textFieldInitDataGlue->m_clientRect = env->GetFieldID(tfidClazz, "mClientRect", "Landroid/graphics/Rect;");
    m_textFieldInitDataGlue->m_constructor = GetJMethod(env, tfidClazz, "<init>", "()V");
    env->DeleteLocalRef(tfidClazz);

    PageGroup::setShouldTrackVisitedLinks(true);

    clearContent();

    MemoryUsage::setLowMemoryUsageMb(env->GetIntField(javaWebViewCore, gWebViewCoreFields.m_lowMemoryUsageMb));
    MemoryUsage::setHighMemoryUsageMb(env->GetIntField(javaWebViewCore, gWebViewCoreFields.m_highMemoryUsageMb));
    MemoryUsage::setHighUsageDeltaMb(env->GetIntField(javaWebViewCore, gWebViewCoreFields.m_highUsageDeltaMb));

    WebViewCore::addInstance(this);

    AndroidNetworkLibraryImpl::InitWithApplicationContext(env, 0);

    // increase the font cache size beyond the standard system setting
    SkGraphics::SetFontCacheLimit(1572864); // 1572864 bytes == 1.5 MB

    // Static initialisation of certain important V8 static data gets performed at system startup when
    // libwebcore gets loaded. We now need to associate the WebCore thread with V8 to complete
    // initialisation.
    v8::V8::Initialize();

    // Configure any RuntimeEnabled features that we need to change from their default now.
    // See WebCore/bindings/generic/RuntimeEnabledFeatures.h

    // HTML5 History API
    RuntimeEnabledFeatures::setPushStateEnabled(true);
    if (m_mainFrame)
        m_mainFrame->settings()->setMinDOMTimerInterval(FOREGROUND_TIMER_INTERVAL);
}

WebViewCore::~WebViewCore()
{
    WebViewCore::removeInstance(this);

    // Release the focused view
    ::Release(m_popupReply);

    if (m_javaGlue->m_obj) {
        JNIEnv* env = JSC::Bindings::getJNIEnv();
        env->DeleteWeakGlobalRef(m_javaGlue->m_obj);
        m_javaGlue->m_obj = 0;
    }
    delete m_javaGlue;
    delete m_textFieldInitDataGlue;
}

WebViewCore* WebViewCore::getWebViewCore(const WebCore::FrameView* view)
{
    if (!view)
        return 0;
    if (view->platformWidget())
        return static_cast<WebFrameView*>(view->platformWidget())->webViewCore();
    Frame* frame = view->frame();
    while (Frame* parent = frame->tree()->parent())
        frame = parent;
    WebFrameView* webFrameView = 0;
    if (frame && frame->view())
        webFrameView = static_cast<WebFrameView*>(frame->view()->platformWidget());
    if (!webFrameView)
        return 0;
    return webFrameView->webViewCore();
}

WebViewCore* WebViewCore::getWebViewCore(const WebCore::ScrollView* view)
{
    if (!view)
        return 0;
    if (view->platformWidget())
        return static_cast<WebFrameView*>(view->platformWidget())->webViewCore();
    const FrameView* frameView = 0;
    if (view->isFrameView())
        frameView = static_cast<const FrameView*>(view);
    else {
        frameView = static_cast<const FrameView*>(view->root());
        if (!frameView)
            return 0;
    }
    return getWebViewCore(frameView);
}

static bool layoutIfNeededRecursive(WebCore::Frame* f)
{
    if (!f)
        return true;

    WebCore::FrameView* v = f->view();
    if (!v)
        return true;
    v->updateLayoutAndStyleIfNeededRecursive();
    return !v->needsLayout();
}

WebCore::Node* WebViewCore::currentFocus()
{
    return focusedFrame()->document()->focusedNode();
}

void WebViewCore::layout()
{
    TRACE_METHOD();

    // if there is no document yet, just return
    if (!m_mainFrame->document()) {
        ALOGV("!m_mainFrame->document()");
        return;
    }

    // Call layout to ensure that the contentWidth and contentHeight are correct
    // it's fine for layout to gather invalidates, but defeat sending a message
    // back to java to call webkitDraw, since we're already in the middle of
    // doing that
    bool success = layoutIfNeededRecursive(m_mainFrame);

    // We may be mid-layout and thus cannot draw.
    if (!success)
        return;

    // if the webkit page dimensions changed, discard the pictureset and redraw.
    WebCore::FrameView* view = m_mainFrame->view();
    int width = view->contentsWidth();
    int height = view->contentsHeight();

    // Use the contents width and height as a starting point.
    SkIRect contentRect;
    contentRect.set(0, 0, width, height);
    SkIRect total(contentRect);

    // Traverse all the frames and add their sizes if they are in the visible
    // rectangle.
    for (WebCore::Frame* frame = m_mainFrame->tree()->traverseNext(); frame;
            frame = frame->tree()->traverseNext()) {
        // If the frame doesn't have an owner then it is the top frame and the
        // view size is the frame size.
        WebCore::RenderPart* owner = frame->ownerRenderer();
        if (owner && owner->style()->visibility() == VISIBLE) {
            int x = owner->x();
            int y = owner->y();

            // Traverse the tree up to the parent to find the absolute position
            // of this frame.
            WebCore::Frame* parent = frame->tree()->parent();
            while (parent) {
                WebCore::RenderPart* parentOwner = parent->ownerRenderer();
                if (parentOwner) {
                    x += parentOwner->x();
                    y += parentOwner->y();
                }
                parent = parent->tree()->parent();
            }
            // Use the owner dimensions so that padding and border are
            // included.
            int right = x + owner->width();
            int bottom = y + owner->height();
            SkIRect frameRect = {x, y, right, bottom};
            // Ignore a width or height that is smaller than 1. Some iframes
            // have small dimensions in order to be hidden. The iframe
            // expansion code does not expand in that case so we should ignore
            // them here.
            if (frameRect.width() > 1 && frameRect.height() > 1
                    && SkIRect::Intersects(total, frameRect))
                total.join(x, y, right, bottom);
        }
    }

    // If the new total is larger than the content, resize the view to include
    // all the content.
    if (!contentRect.contains(total)) {
        // TODO: Does this ever happen? Is this needed now that we don't flatten
        // frames?
        // Resize the view to change the overflow clip.
        view->resize(total.fRight, total.fBottom);

        // We have to force a layout in order for the clip to change.
        m_mainFrame->contentRenderer()->setNeedsLayoutAndPrefWidthsRecalc();
        view->forceLayout();

        // Relayout similar to above
        layoutIfNeededRecursive(m_mainFrame);
    }
}

void WebViewCore::recordPicturePile()
{
    // if the webkit page dimensions changed, discard the pictureset and redraw.
    WebCore::FrameView* view = m_mainFrame->view();
    int width = view ? view->contentsWidth() : 0;
    int height = view ? view->contentsHeight() : 0;

    m_content.setSize(IntSize(width, height));

    // Rebuild the pictureset (webkit repaint)
    m_content.updatePicturesIfNeeded(this);
}

void WebViewCore::clearContent()
{
    m_content.reset();
    updateLocale();
}

void WebViewCore::paintContents(WebCore::GraphicsContext* gc, WebCore::IntRect& dirty)
{
    WebCore::FrameView* view = m_mainFrame->view();
    if (!view) {
        gc->setFillColor(WebCore::Color::white, WebCore::ColorSpaceDeviceRGB);
        gc->fillColor();
        return;
    }

    IntPoint origin = view->minimumScrollPosition();
    IntRect drawArea = dirty;
    gc->translate(-origin.x(), -origin.y());
    drawArea.move(origin.x(), origin.y());
    view->platformWidget()->draw(gc, drawArea);
}

void WebViewCore::setPrerenderingEnabled(bool enable)
{
    MutexLocker locker(m_prerenderLock);
    m_prerenderEnabled = enable;
}

bool WebViewCore::prerenderingEnabled()
{
    MutexLocker locker(m_prerenderLock);
    return m_prerenderEnabled;
}

SkCanvas* WebViewCore::createPrerenderCanvas(PrerenderedInval* prerendered)
{
    // Has WebView disabled prerenders (not attached, etc...)?
    if (!prerenderingEnabled())
        return 0;
    // Does this WebView have focus?
    if (!m_mainFrame->page()->focusController()->isActive())
        return 0;
    // Are we scrolling?
    if (currentTimeMS() - m_scrollSetTime < PRERENDER_AFTER_SCROLL_DELAY)
        return 0;
    // Do we have anything to render?
    if (prerendered->area.isEmpty())
        return 0;
    FloatRect scaleTemp(m_scrollOffsetX, m_scrollOffsetY, m_screenWidth, m_screenHeight);
    scaleTemp.scale(m_scale);
    IntRect visibleTileClip = enclosingIntRect(scaleTemp);
    FloatRect scaledArea = prerendered->area;
    scaledArea.scale(m_scale);
    IntRect enclosingScaledArea = enclosingIntRect(scaledArea);
    if (enclosingScaledArea.isEmpty())
        return 0;
    // "round out" the screen to tile boundaries so that we can clip yet still
    // cover any visible tiles with the prerender
    int tw = TilesManager::tileWidth();
    int th = TilesManager::tileHeight();
    float left = tw * (int) (visibleTileClip.x() / tw);
    float top = th * (int) (visibleTileClip.y() / th);
    float right = tw * (int) ceilf(visibleTileClip.maxX() / (float) tw);
    float bottom = th * (int) ceilf(visibleTileClip.maxY() / (float) th);
    visibleTileClip = IntRect(left, top, right - left, bottom - top);
    enclosingScaledArea.intersect(visibleTileClip);
    if (enclosingScaledArea.isEmpty())
        return 0;
    prerendered->screenArea = enclosingScaledArea;
    FloatRect enclosingDocArea(enclosingScaledArea);
    enclosingDocArea.scale(1 / m_scale);
    prerendered->area = enclosingIntRect(enclosingDocArea);
    if (prerendered->area.isEmpty())
        return 0;
    prerendered->bitmap.setConfig(SkBitmap::kARGB_8888_Config,
                                  enclosingScaledArea.width(),
                                  enclosingScaledArea.height());
    prerendered->bitmap.allocPixels();
    SkCanvas* bitmapCanvas = new SkCanvas(prerendered->bitmap);
    bitmapCanvas->scale(m_scale, m_scale);
    bitmapCanvas->translate(-enclosingDocArea.x(), -enclosingDocArea.y());
    return bitmapCanvas;
}

void WebViewCore::notifyAnimationStarted()
{
    // We notify webkit that the animations have begun
    // TODO: handle case where not all have begun
    ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client());
    GraphicsLayerAndroid* root = static_cast<GraphicsLayerAndroid*>(chromeC->layersSync());
    if (root)
        root->notifyClientAnimationStarted();

}

BaseLayerAndroid* WebViewCore::createBaseLayer(GraphicsLayerAndroid* root)
{
    // We set the background color
    Color background = Color::white;

    bool bodyHasFixedBackgroundImage = false;
    bool bodyHasCSSBackground = false;

    if (m_mainFrame && m_mainFrame->document()
        && m_mainFrame->document()->body()) {

        Document* document = m_mainFrame->document();
        RefPtr<RenderStyle> style = document->styleForElementIgnoringPendingStylesheets(document->body());
        if (style->hasBackground()) {
            background = style->visitedDependentColor(CSSPropertyBackgroundColor);
            bodyHasCSSBackground = true;
        }
        WebCore::FrameView* view = m_mainFrame->view();
        if (view) {
            Color viewBackground = view->baseBackgroundColor();
            background = bodyHasCSSBackground ? viewBackground.blend(background) : viewBackground;
        }
        if (style->hasFixedBackgroundImage()) {
            Image* backgroundImage = FixedBackgroundImageLayerAndroid::GetCachedImage(style);
            if (backgroundImage && backgroundImage->width() > 1 && backgroundImage->height() > 1)
                bodyHasFixedBackgroundImage = true;
        }
    }

    PicturePileLayerContent* content = new PicturePileLayerContent(m_content);
    m_content.clearPrerenders();

    BaseLayerAndroid* realBase = 0;
    LayerAndroid* base = 0;

    //If we have a fixed background image on the body element, the fixed image
    // will be contained in the PictureSet (the content object), and the foreground
    //of the body element will be moved to a layer.
    //In that case, let's change the hierarchy to obtain:
    //
    //BaseLayerAndroid
    // \- FixedBackgroundBaseLayerAndroid (fixed positioning)
    // \- ForegroundBaseLayerAndroid
    //   \- root layer (webkit composited tree)

    if (bodyHasFixedBackgroundImage) {
        base = new ForegroundBaseLayerAndroid(0);
        base->setSize(content->width(), content->height());

        Document* document = m_mainFrame->document();
        RefPtr<RenderStyle> style = document->styleForElementIgnoringPendingStylesheets(document->body());

        FixedBackgroundImageLayerAndroid* baseBackground =
             new FixedBackgroundImageLayerAndroid(style, content->width(), content->height());

        realBase = new BaseLayerAndroid(0);
        realBase->setSize(content->width(), content->height());
        realBase->addChild(baseBackground);
        realBase->addChild(base);
        baseBackground->unref();
        base->unref();
    } else {
        realBase = new BaseLayerAndroid(content);
        base = realBase;
    }

    realBase->setBackgroundColor(background);

    SkSafeUnref(content);

    // We update the layers
    if (root) {
        LayerAndroid* copyLayer = new LayerAndroid(*root->contentLayer());
        base->addChild(copyLayer);
        copyLayer->unref();
        root->contentLayer()->clearDirtyRegion();
    }

    return realBase;
}

BaseLayerAndroid* WebViewCore::recordContent(SkIPoint* point)
{
    m_skipContentDraw = true;
    layout();
    ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client());
    GraphicsLayerAndroid* root = static_cast<GraphicsLayerAndroid*>(chromeC->layersSync());
    m_skipContentDraw = false;
    recordPicturePile();

    BaseLayerAndroid* baseLayer = createBaseLayer(root);

    baseLayer->markAsDirty(m_content.dirtyRegion());
    m_content.dirtyRegion().setEmpty();
#if USE(ACCELERATED_COMPOSITING)
#else
    baseLayer->markAsDirty(m_rebuildInval);
#endif
    point->fX = m_content.size().width();
    point->fY = m_content.size().height();

    return baseLayer;
}

void WebViewCore::scrollTo(int x, int y, bool animate)
{
    ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");

    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_scrollTo,
            x, y, animate, false);
    checkException(env);
}

void WebViewCore::sendNotifyProgressFinished()
{
    ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_sendNotifyProgressFinished);
    checkException(env);
}

void WebViewCore::viewInvalidate(const WebCore::IntRect& rect)
{
    ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    env->CallVoidMethod(javaObject.get(),
                        m_javaGlue->m_sendViewInvalidate,
                        rect.x(), rect.y(), rect.maxX(), rect.maxY());
    checkException(env);
}

void WebViewCore::contentDraw()
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_contentDraw);
    checkException(env);
}

void WebViewCore::contentInvalidate(const WebCore::IntRect &r)
{
    IntPoint origin = m_mainFrame->view()->minimumScrollPosition();
    IntRect dirty = r;
    dirty.move(-origin.x(), -origin.y());
    m_content.invalidate(dirty);
    if (!m_skipContentDraw)
        contentDraw();
}

void WebViewCore::contentInvalidateAll()
{
    WebCore::FrameView* view = m_mainFrame->view();
    contentInvalidate(WebCore::IntRect(0, 0,
        view->contentsWidth(), view->contentsHeight()));
}

void WebViewCore::offInvalidate(const WebCore::IntRect &r)
{
    // FIXME: these invalidates are offscreen, and can be throttled or
    // deferred until the area is visible. For now, treat them as
    // regular invals so that drawing happens (inefficiently) for now.
    contentInvalidate(r);
}

void WebViewCore::didFirstLayout()
{
    ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");

    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;

    const WebCore::KURL& url = m_mainFrame->document()->url();
    if (url.isEmpty())
        return;
    ALOGV("::WebCore:: didFirstLayout %s", url.string().ascii().data());

    WebCore::FrameLoadType loadType = m_mainFrame->loader()->loadType();

    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_didFirstLayout,
            loadType == WebCore::FrameLoadTypeStandard
            // When redirect with locked history, we would like to reset the
            // scale factor. This is important for www.yahoo.com as it is
            // redirected to www.yahoo.com/?rs=1 on load.
            || loadType == WebCore::FrameLoadTypeRedirectWithLockedBackForwardList
            // When "request desktop page" is used, we want to treat it as
            // a newly-loaded page.
            || loadType == WebCore::FrameLoadTypeSame);
    checkException(env);
}

void WebViewCore::updateViewport()
{
    ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");

    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_updateViewport);
    checkException(env);
}

void WebViewCore::restoreScale(float scale, float textWrapScale)
{
    ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");

    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_restoreScale, scale, textWrapScale);
    checkException(env);
}

void WebViewCore::needTouchEvents(bool need)
{
    ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");

#if ENABLE(TOUCH_EVENTS)
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;

    if (m_forwardingTouchEvents == need)
        return;

    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_needTouchEvents, need);
    checkException(env);

    m_forwardingTouchEvents = need;
#endif
}

void WebViewCore::requestKeyboard(bool showKeyboard)
{
    ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");

    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_requestKeyboard, showKeyboard);
    checkException(env);
}

void WebViewCore::notifyProgressFinished()
{
    sendNotifyProgressFinished();
}

void WebViewCore::setScrollOffset(bool sendScrollEvent, int dx, int dy)
{
    if (m_scrollOffsetX != dx || m_scrollOffsetY != dy) {
        m_scrollOffsetX = dx;
        m_scrollOffsetY = dy;
        m_scrollSetTime = currentTimeMS();
        // The visible rect is located within our coordinate space so it
        // contains the actual scroll position. Setting the location makes hit
        // testing work correctly.
        m_mainFrame->view()->platformWidget()->setLocation(m_scrollOffsetX,
                m_scrollOffsetY);
        if (sendScrollEvent) {
            m_mainFrame->eventHandler()->sendScrollEvent();

            // Only update history position if it's user scrolled.
            // Update history item to reflect the new scroll position.
            // This also helps save the history information when the browser goes to
            // background, so scroll position will be restored if browser gets
            // killed while in background.
            WebCore::HistoryController* history = m_mainFrame->loader()->history();
            // Because the history item saving could be heavy for large sites and
            // scrolling can generate lots of small scroll offset, the following code
            // reduces the saving frequency.
            static const int MIN_SCROLL_DIFF = 32;
            if (history->currentItem()) {
                WebCore::IntPoint currentPoint = history->currentItem()->scrollPoint();
                if (std::abs(currentPoint.x() - dx) >= MIN_SCROLL_DIFF ||
                    std::abs(currentPoint.y() - dy) >= MIN_SCROLL_DIFF) {
                    history->saveScrollPositionAndViewStateToItem(history->currentItem());
                }
            }
        }

        // update the currently visible screen
        sendPluginVisibleScreen();
    }
}

void WebViewCore::setGlobalBounds(int x, int y, int h, int v)
{
    m_mainFrame->view()->platformWidget()->setWindowBounds(x, y, h, v);
}

void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
    int textWrapWidth, float scale, int screenWidth, int screenHeight,
    int anchorX, int anchorY, bool ignoreHeight)
{
    // Ignore the initial empty document.
    const WebCore::KURL& url = m_mainFrame->document()->url();
    if (url.isEmpty())
        return;

    WebCoreViewBridge* window = m_mainFrame->view()->platformWidget();
    int ow = window->width();
    int oh = window->height();
    int osw = m_screenWidth;
    int osh = m_screenHeight;
    int otw = m_textWrapWidth;
    m_screenWidth = screenWidth;
    m_screenHeight = screenHeight;
    m_textWrapWidth = textWrapWidth;
    if (scale >= 0) // negative means keep the current scale
        m_scale = scale;
    m_maxXScroll = screenWidth >> 2;
    m_maxYScroll = m_maxXScroll * height / width;
    // Don't reflow if the diff is small.
    const bool reflow = otw && textWrapWidth &&
        ((float) abs(otw - textWrapWidth) / textWrapWidth) >= 0.01f;

    // When the screen size change, fixed positioned element should be updated.
    // This is supposed to be light weighted operation without a full layout.
    if (osh != screenHeight || osw != screenWidth)
        m_mainFrame->view()->updatePositionedObjects();

    if (ow != width || (!ignoreHeight && oh != height) || reflow) {
        WebCore::RenderObject *r = m_mainFrame->contentRenderer();
        if (r) {
            WebCore::IntPoint anchorPoint = WebCore::IntPoint(anchorX, anchorY);
            RefPtr<WebCore::Node> node;
            WebCore::IntRect bounds;
            WebCore::IntPoint offset;
            // If the text wrap changed, it is probably zoom change or
            // orientation change. Try to keep the anchor at the same place.
            if (otw && textWrapWidth && otw != textWrapWidth &&
                (anchorX != 0 || anchorY != 0)) {
                WebCore::HitTestResult hitTestResult =
                        m_mainFrame->eventHandler()->hitTestResultAtPoint(
                                anchorPoint, false);
                node = hitTestResult.innerNode();
                if (node && !node->isTextNode()) {
                    // If the hitTestResultAtPoint didn't find a suitable node
                    // for anchoring, try again with some slop.
                    static const int HIT_SLOP = 30;
                    anchorPoint.move(HIT_SLOP, HIT_SLOP);
                    hitTestResult =
                        m_mainFrame->eventHandler()->hitTestResultAtPoint(
                                anchorPoint, false);
                    node = hitTestResult.innerNode();
                }
            }
            if (node) {
                bounds = node->getRect();
                // sites like nytimes.com insert a non-standard tag <nyt_text>
                // in the html. If it is the HitTestResult, it may have zero
                // width and height. In this case, use its parent node.
                if (bounds.width() == 0) {
                    node = node->parentOrHostNode();
                    if (node) {
                        bounds = node->getRect();
                    }
                }
            }

            // Set the size after finding the old anchor point as
            // hitTestResultAtPoint causes a layout.
            window->setSize(width, height);
            window->setVisibleSize(screenWidth, screenHeight);
            if (width != screenWidth) {
                m_mainFrame->view()->setUseFixedLayout(true);
                m_mainFrame->view()->setFixedLayoutSize(IntSize(width, height));
            } else
                m_mainFrame->view()->setUseFixedLayout(false);
            r->setNeedsLayoutAndPrefWidthsRecalc();
            if (m_mainFrame->view()->didFirstLayout())
                m_mainFrame->view()->forceLayout();

            // scroll to restore current screen center
            if (node && node->inDocument()) {
                const WebCore::IntRect& newBounds = node->getRect();
                if ((osw && osh && bounds.width() && bounds.height())
                    && (bounds != newBounds)) {
                    WebCore::FrameView* view = m_mainFrame->view();
                    // force left align if width is not changed while height changed.
                    // the anchorPoint is probably at some white space in the node
                    // which is affected by text wrap around the screen width.
                    const bool leftAlign = (otw != textWrapWidth)
                        && (bounds.width() == newBounds.width())
                        && (bounds.height() != newBounds.height());
                    const float xPercentInDoc =
                        leftAlign ? 0.0 : (float) (anchorX - bounds.x()) / bounds.width();
                    const float xPercentInView =
                        leftAlign ? 0.0 : (float) (anchorX - m_scrollOffsetX) / osw;
                    const float yPercentInDoc = (float) (anchorY - bounds.y()) / bounds.height();
                    const float yPercentInView = (float) (anchorY - m_scrollOffsetY) / osh;
                    showRect(newBounds.x(), newBounds.y(), newBounds.width(),
                             newBounds.height(), view->contentsWidth(),
                             view->contentsHeight(),
                             xPercentInDoc, xPercentInView,
                             yPercentInDoc, yPercentInView);
                }
            }
        }
    } else {
        window->setSize(width, height);
        window->setVisibleSize(screenWidth, screenHeight);
        m_mainFrame->view()->resize(width, height);
        if (width != screenWidth) {
            m_mainFrame->view()->setUseFixedLayout(true);
            m_mainFrame->view()->setFixedLayoutSize(IntSize(width, height));
        } else
            m_mainFrame->view()->setUseFixedLayout(false);
    }

    // update the currently visible screen as perceived by the plugin
    sendPluginVisibleScreen();
}

void WebViewCore::dumpDomTree(bool useFile)
{
#ifdef ANDROID_DOM_LOGGING
    if (useFile)
        gDomTreeFile = fopen(DOM_TREE_LOG_FILE, "w");
    m_mainFrame->document()->showTreeForThis();
    if (gDomTreeFile) {
        fclose(gDomTreeFile);
        gDomTreeFile = 0;
    }
#endif
}

void WebViewCore::dumpRenderTree(bool useFile)
{
#ifdef ANDROID_DOM_LOGGING
    WTF::CString renderDump = WebCore::externalRepresentation(m_mainFrame).utf8();
    const char* data = renderDump.data();
    if (useFile) {
        gRenderTreeFile = fopen(RENDER_TREE_LOG_FILE, "w");
        DUMP_RENDER_LOGD("%s", data);
        fclose(gRenderTreeFile);
        gRenderTreeFile = 0;
    } else {
        // adb log can only output 1024 characters, so write out line by line.
        // exclude '\n' as adb log adds it for each output.
        int length = renderDump.length();
        for (int i = 0, last = 0; i < length; i++) {
            if (data[i] == '\n') {
                if (i != last)
                    DUMP_RENDER_LOGD("%.*s", (i - last), &(data[last]));
                last = i + 1;
            }
        }
    }
#endif
}

HTMLElement* WebViewCore::retrieveElement(int x, int y,
    const QualifiedName& tagName)
{
    HitTestResult hitTestResult = m_mainFrame->eventHandler()
        ->hitTestResultAtPoint(IntPoint(x, y), false, false,
        DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly,
        IntSize(1, 1));
    if (!hitTestResult.innerNode() || !hitTestResult.innerNode()->inDocument()) {
        ALOGE("Should not happen: no in document Node found");
        return 0;
    }
    const ListHashSet<RefPtr<Node> >& list = hitTestResult.rectBasedTestResult();
    if (list.isEmpty()) {
        ALOGE("Should not happen: no rect-based-test nodes found");
        return 0;
    }
    Node* node = hitTestResult.innerNode();
    Node* element = node;
    while (element && (!element->isElementNode()
        || !element->hasTagName(tagName))) {
        element = element->parentNode();
    }
    return static_cast<WebCore::HTMLElement*>(element);
}

HTMLAnchorElement* WebViewCore::retrieveAnchorElement(int x, int y)
{
    return static_cast<HTMLAnchorElement*>
        (retrieveElement(x, y, HTMLNames::aTag));
}

HTMLImageElement* WebViewCore::retrieveImageElement(int x, int y)
{
    return static_cast<HTMLImageElement*>
        (retrieveElement(x, y, HTMLNames::imgTag));
}

WTF::String WebViewCore::retrieveHref(int x, int y)
{
    // TODO: This is expensive, cache
    HitTestResult result = m_mainFrame->eventHandler()->hitTestResultAtPoint(IntPoint(x, y),
                false, false, DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly, IntSize(1, 1));
    return result.absoluteLinkURL();
}

WTF::String WebViewCore::retrieveAnchorText(int x, int y)
{
    WebCore::HTMLAnchorElement* anchor = retrieveAnchorElement(x, y);
    return anchor ? anchor->text() : WTF::String();
}

WTF::String WebViewCore::retrieveImageSource(int x, int y)
{
    // TODO: This is expensive, cache
    HitTestResult result = m_mainFrame->eventHandler()->hitTestResultAtPoint(IntPoint(x, y),
                false, false, DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly, IntSize(1, 1));
    return result.absoluteImageURL();
}

WTF::String WebViewCore::requestLabel(WebCore::Frame* frame,
        WebCore::Node* node)
{
    if (node && validNode(m_mainFrame, frame, node)) {
        RefPtr<WebCore::NodeList> list = node->document()->getElementsByTagName("label");
        unsigned length = list->length();
        for (unsigned i = 0; i < length; i++) {
            WebCore::HTMLLabelElement* label = static_cast<WebCore::HTMLLabelElement*>(
                    list->item(i));
            if (label->control() == node) {
                Node* node = label;
                String result;
                while ((node = node->traverseNextNode(label))) {
                    if (node->isTextNode()) {
                        Text* textNode = static_cast<Text*>(node);
                        result += textNode->dataImpl();
                    }
                }
                return result;
            }
        }
    }
    return WTF::String();
}

static bool isContentEditable(const WebCore::Node* node)
{
    if (!node)
        return false;
    return node->isContentEditable();
}

// Returns true if the node is a textfield, textarea, or contentEditable
static bool isTextInput(const WebCore::Node* node)
{
    if (!node)
        return false;
    if (isContentEditable(node))
        return true;
    WebCore::RenderObject* renderer = node->renderer();
    return renderer && (renderer->isTextField() || renderer->isTextArea());
}

void WebViewCore::revealSelection()
{
    WebCore::Node* focus = currentFocus();
    if (!focus)
        return;
    if (!isTextInput(focus))
        return;
    WebCore::Frame* focusedFrame = focus->document()->frame();
    if (!focusedFrame->page()->focusController()->isActive())
        return;
    focusedFrame->selection()->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
}

struct TouchNodeData {
    Node* mUrlNode;
    Node* mInnerNode;
    IntRect mBounds;
};

// get the bounding box of the Node
static IntRect getAbsoluteBoundingBox(Node* node) {
    IntRect rect;
    RenderObject* render = node->renderer();
    if (!render)
        return rect;
    if (render->isRenderInline())
        rect = toRenderInline(render)->linesVisualOverflowBoundingBox();
    else if (render->isBox())
        rect = toRenderBox(render)->visualOverflowRect();
    else if (render->isText())
        rect = toRenderText(render)->linesBoundingBox();
    else
        ALOGE("getAbsoluteBoundingBox failed for node %p, name %s", node, render->renderName());
    FloatPoint absPos = render->localToAbsolute(FloatPoint(), false, true);
    rect.move(absPos.x(), absPos.y());
    return rect;
}

WebCore::Frame* WebViewCore::focusedFrame() const
{
    return m_mainFrame->page()->focusController()->focusedOrMainFrame();
}

VisiblePosition WebViewCore::visiblePositionForContentPoint(int x, int y)
{
    return visiblePositionForContentPoint(IntPoint(x, y));
}

VisiblePosition WebViewCore::visiblePositionForContentPoint(const IntPoint& point)
{
    // Hit test of this kind required for this to work inside input fields
    HitTestRequest request(HitTestRequest::Active
                           | HitTestRequest::MouseMove
                           | HitTestRequest::ReadOnly
                           | HitTestRequest::IgnoreClipping);
    HitTestResult result(point);
    focusedFrame()->document()->renderView()->layer()->hitTest(request, result);

    // Matching the logic in MouseEventWithHitTestResults::targetNode()
    Node* node = result.innerNode();
    if (!node)
        return VisiblePosition();
    Element* element = node->parentElement();
    if (!node->inDocument() && element && element->inDocument())
        node = element;

    return node->renderer()->positionForPoint(result.localPoint());
}

bool WebViewCore::selectWordAt(int x, int y)
{
    HitTestResult hoverResult;
    moveMouse(x, y, &hoverResult);
    if (hoverResult.innerNode()) {
        Node* node = hoverResult.innerNode();
        Frame* frame = node->document()->frame();
        Page* page = m_mainFrame->document()->page();
        page->focusController()->setFocusedFrame(frame);
    }

    IntPoint point = convertGlobalContentToFrameContent(IntPoint(x, y));

    // Hit test of this kind required for this to work inside input fields
    HitTestRequest request(HitTestRequest::Active);
    HitTestResult result(point);

    focusedFrame()->document()->renderView()->layer()->hitTest(request, result);

    // Matching the logic in MouseEventWithHitTestResults::targetNode()
    Node* node = result.innerNode();
    if (!node)
        return false;
    Element* element = node->parentElement();
    if (!node->inDocument() && element && element->inDocument())
        node = element;

    SelectionController* sc = focusedFrame()->selection();
    bool wordSelected = false;
    if (!sc->contains(point) && (node->isContentEditable() || node->isTextNode()) && !result.isLiveLink()
            && node->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true))) {
        VisiblePosition pos(node->renderer()->positionForPoint(result.localPoint()));
        wordSelected = selectWordAroundPosition(node->document()->frame(), pos);
    }
    return wordSelected;
}

bool WebViewCore::selectWordAroundPosition(Frame* frame, VisiblePosition pos)
{
    VisibleSelection selection(pos);
    selection.expandUsingGranularity(WordGranularity);
    SelectionController* selectionController = frame->selection();
    selection = VisibleSelection(selection.start(), selection.end());

    bool wordSelected = false;
    if (selectionController->shouldChangeSelection(selection)) {
        bool allWhitespaces = true;
        RefPtr<Range> firstRange = selection.firstRange();
        String text = firstRange.get() ? firstRange->text() : "";
        for (size_t i = 0; i < text.length(); ++i) {
            if (!isSpaceOrNewline(text[i])) {
                allWhitespaces = false;
                break;
            }
        }
        if (allWhitespaces) {
            VisibleSelection emptySelection(pos);
            selectionController->setSelection(emptySelection);
        } else {
            selectionController->setSelection(selection);
            wordSelected = true;
        }
    }
    return wordSelected;
}

int WebViewCore::platformLayerIdFromNode(Node* node, LayerAndroid** outLayer)
{
    if (!node || !node->renderer())
        return -1;
    RenderLayer* renderLayer = node->renderer()->enclosingLayer();
    while (renderLayer && !renderLayer->isComposited())
        renderLayer = renderLayer->parent();
    if (!renderLayer || !renderLayer->isComposited())
        return -1;
    GraphicsLayer* graphicsLayer = renderLayer->backing()->graphicsLayer();
    if (!graphicsLayer)
        return -1;
    GraphicsLayerAndroid* agl = static_cast<GraphicsLayerAndroid*>(graphicsLayer);
    LayerAndroid* layer = agl->foregroundLayer();
    if (!layer)
        layer = agl->contentLayer();
    if (!layer)
        return -1;
    if (outLayer)
        *outLayer = layer;
    return layer->uniqueId();
}

void WebViewCore::layerToAbsoluteOffset(const LayerAndroid* layer, IntPoint& offset)
{
    while (layer) {
        const SkPoint& pos = layer->getPosition();
        offset.move(pos.fX, pos.fY);
        const IntPoint& scroll = layer->getScrollOffset();
        offset.move(-scroll.x(), -scroll.y());
        layer = static_cast<LayerAndroid*>(layer->getParent());
    }
}

void WebViewCore::setSelectionCaretInfo(SelectText* selectTextContainer,
        const WebCore::Position& pos, const IntPoint& frameOffset,
        SelectText::HandleId handleId, SelectText::HandleType handleType,
        int caretRectOffset, EAffinity affinity)
{
    Node* node = pos.anchorNode();
    LayerAndroid* layer = 0;
    int layerId = platformLayerIdFromNode(node, &layer);
    selectTextContainer->setCaretLayerId(handleId, layerId);
    IntPoint offset = frameOffset;
    layerToAbsoluteOffset(layer, offset);
    RenderObject* r = node->renderer();
    RenderText* renderText = toRenderText(r);
    int caretOffset;
    InlineBox* inlineBox;
    pos.getInlineBoxAndOffset(affinity, inlineBox, caretOffset);
    IntRect caretRect = renderText->localCaretRect(inlineBox, caretOffset);
    FloatPoint absoluteOffset = renderText->localToAbsolute(caretRect.location());
    caretRect.setX(absoluteOffset.x() - offset.x() + caretRectOffset);
    caretRect.setY(absoluteOffset.y() - offset.y());
    selectTextContainer->setCaretRect(handleId, caretRect);
    selectTextContainer->setHandleType(handleId, handleType);
    selectTextContainer->setTextRect(handleId,
            positionToTextRect(pos, affinity, offset, caretRect));
}

bool WebViewCore::isLtr(const Position& position)
{
    InlineBox* inlineBox = 0;
    int caretOffset = 0;
    position.getInlineBoxAndOffset(DOWNSTREAM, inlineBox, caretOffset);
    bool isLtr;
    if (inlineBox)
        isLtr = inlineBox->isLeftToRightDirection();
    else
        isLtr = position.primaryDirection() == LTR;
    return isLtr;
}

static Node* findInputParent(Node* node)
{
    Node* testNode = node;
    while (testNode) {
        RenderObject* renderer = testNode->renderer();
        if (renderer
                && (renderer->isTextArea() || renderer->isTextControl())) {
            return testNode;
        }
        testNode = testNode->parentOrHostNode();
    }
    return node;
}

SelectText* WebViewCore::createSelectText(const VisibleSelection& selection)
{
    bool isCaret = selection.isCaret();
    Position base = selection.base();
    Position extent = selection.extent();
    if (selection.isNone() || (!selection.isContentEditable() && isCaret)
            || !base.anchorNode() || !base.anchorNode()->renderer()
            || !extent.anchorNode() || !extent.anchorNode()->renderer())
        return 0;

    RefPtr<Range> range = selection.firstRange();
    Node* startContainer = range->startContainer();
    Node* endContainer = range->endContainer();

    if (!startContainer || !endContainer)
        return 0;
    if (!isCaret && startContainer == endContainer
            && range->startOffset() == range->endOffset())
        return 0;

    IntPoint frameOffset = convertGlobalContentToFrameContent(IntPoint());
    SelectText* selectTextContainer = new SelectText();
    if (isCaret) {
        setSelectionCaretInfo(selectTextContainer, base, frameOffset,
                SelectText::BaseHandle, SelectText::CenterHandle, 0,
                selection.affinity());
        setSelectionCaretInfo(selectTextContainer, base, frameOffset,
                SelectText::ExtentHandle, SelectText::CenterHandle, 0,
                selection.affinity());
    } else {
        bool isBaseLtr = isLtr(base);
        bool isBaseStart = comparePositions(base, extent) <= 0;
        int baseOffset = isBaseLtr ? 0 : -1;
        SelectText::HandleType baseHandleType = (isBaseLtr == isBaseStart)
                ? SelectText::LeftHandle : SelectText::RightHandle;
        EAffinity affinity = selection.affinity();
        setSelectionCaretInfo(selectTextContainer, base, frameOffset,
                SelectText::BaseHandle, baseHandleType, baseOffset, affinity);
        bool isExtentLtr = isLtr(extent);
        int extentOffset = isExtentLtr ? 0 : -1;
        SelectText::HandleType extentHandleType = (isExtentLtr == isBaseStart)
                ? SelectText::RightHandle : SelectText::LeftHandle;
        setSelectionCaretInfo(selectTextContainer, extent, frameOffset,
                SelectText::ExtentHandle, extentHandleType, extentOffset, affinity);
        IntRect clipRect;
        if (selection.isContentEditable()) {
            Node* editable = findInputParent(base.anchorNode());
            RenderObject* render = editable->renderer();
            if (render && render->isBox() && !render->isBody()) {
                RenderBox* renderBox = toRenderBox(render);
                clipRect = renderBox->clientBoxRect();
                FloatPoint pos = renderBox->localToAbsolute(clipRect.location());
                clipRect.setX(pos.x());
                clipRect.setY(pos.y());
            }
        }

        Node* stopNode = range->pastLastNode();
        for (Node* node = range->firstNode(); node != stopNode; node = node->traverseNextNode()) {
            RenderObject* r = node->renderer();
            if (!r || !r->isText() || r->style()->visibility() != VISIBLE)
                continue;
            RenderText* renderText = toRenderText(r);
            int startOffset = node == startContainer ? range->startOffset() : 0;
            int endOffset = node == endContainer ? range->endOffset() : numeric_limits<int>::max();
            LayerAndroid* layer = 0;
            int layerId = platformLayerIdFromNode(node, &layer);
            Vector<IntRect> rects;
            renderText->absoluteRectsForRange(rects, startOffset, endOffset, true);
            selectTextContainer->addHighlightRegion(layer, rects, frameOffset,
                    clipRect);
        }
    }
    selectTextContainer->setText(range->text());
    return selectTextContainer;
}

IntRect WebViewCore::positionToTextRect(const Position& position,
        EAffinity affinity, const WebCore::IntPoint& offset, const IntRect& caretRect)
{
    IntRect textRect = caretRect;
    InlineBox* inlineBox;
    int offsetIndex;
    position.getInlineBoxAndOffset(affinity, inlineBox, offsetIndex);
    if (inlineBox && inlineBox->isInlineTextBox()) {
        InlineTextBox* box = static_cast<InlineTextBox*>(inlineBox);
        RootInlineBox* root = box->root();
        RenderText* renderText = box->textRenderer();
        int left = root->logicalLeft();
        int width = root->logicalWidth();
        int top = root->selectionTop();
        int height = root->selectionHeight();

        if (!renderText->style()->isHorizontalWritingMode()) {
            swap(left, top);
            swap(width, height);
        }
        FloatPoint origin(left, top);
        FloatPoint absoluteOrigin = renderText->localToAbsolute(origin);

        textRect.setX(absoluteOrigin.x() - offset.x());
        textRect.setWidth(width);
        textRect.setY(absoluteOrigin.y() - offset.y());
        textRect.setHeight(height);
    }
    return textRect;
}

IntPoint WebViewCore::convertGlobalContentToFrameContent(const IntPoint& point, WebCore::Frame* frame)
{
    if (!frame) frame = focusedFrame();
    IntPoint frameOffset(-m_scrollOffsetX, -m_scrollOffsetY);
    frameOffset = frame->view()->windowToContents(frameOffset);
    return IntPoint(point.x() + frameOffset.x(), point.y() + frameOffset.y());
}

VisiblePosition WebViewCore::trimSelectionPosition(const VisiblePosition &start,
        const VisiblePosition& stop)
{
    int direction = comparePositions(start, stop);
    if (direction == 0)
        return start;
    bool forward = direction < 0;
    bool move;
    VisiblePosition pos = start;
    bool movedTooFar = false;
    do {
        move = true;
        Node* node = pos.deepEquivalent().anchorNode();
        if (node && node->isTextNode() && node->renderer()) {
            RenderText *textRenderer = toRenderText(node->renderer());
            move = !textRenderer->textLength();
        }
        if (move) {
            VisiblePosition nextPos = forward ? pos.next() : pos.previous();
            movedTooFar = nextPos.isNull() || pos == nextPos
                    || ((comparePositions(nextPos, stop) < 0) != forward);
            pos = nextPos;
        }
    } while (move && !movedTooFar);
    if (movedTooFar)
        pos = stop;
    return pos;
}

void WebViewCore::selectText(SelectText::HandleId handleId, int x, int y)
{
    SelectionController* sc = focusedFrame()->selection();
    VisibleSelection selection = sc->selection();
    Position base = selection.base();
    Position extent = selection.extent();
    IntPoint dragPoint = convertGlobalContentToFrameContent(IntPoint(x, y));
    VisiblePosition dragPosition(visiblePositionForContentPoint(dragPoint));

    if (base.isNull() || extent.isNull() || dragPosition.isNull())
        return;
    bool draggingBase = (handleId == SelectText::BaseHandle);
    if (draggingBase)
        base = dragPosition.deepEquivalent();
    else
        extent = dragPosition.deepEquivalent();

    bool baseIsStart = (comparePositions(base, extent) <= 0);
    Position& start = baseIsStart ? base : extent;
    Position& end = baseIsStart ? extent : base;
    VisiblePosition startPosition(start, selection.affinity());
    VisiblePosition endPosition(end, selection.affinity());
    bool draggingStart = (baseIsStart == draggingBase);

    if (draggingStart) {
        if (selection.isRange()) {
            startPosition = trimSelectionPosition(startPosition, endPosition);
            if ((startPosition != endPosition) && isEndOfBlock(startPosition)) {
                // Ensure startPosition is not at end of block
                VisiblePosition nextStartPosition(startPosition.next());
                if (nextStartPosition.isNotNull())
                    startPosition = nextStartPosition;
            }
        }
        startPosition = endPosition.honorEditableBoundaryAtOrAfter(startPosition);
        if (startPosition.isNull())
            return;
        start = startPosition.deepEquivalent();
        if (selection.isCaret())
            end = start;
    } else {
        if (selection.isRange()) {
            endPosition = trimSelectionPosition(endPosition, startPosition);
            if ((start != end) && isStartOfBlock(endPosition)) {
                // Ensure endPosition is not at start of block
                VisiblePosition prevEndPosition(endPosition.previous());
                if (!prevEndPosition.isNull())
                    endPosition = prevEndPosition;
            }
        }
        endPosition = startPosition.honorEditableBoundaryAtOrAfter(endPosition);
        if (endPosition.isNull())
            return;
        end = endPosition.deepEquivalent();
        if (selection.isCaret())
            start = end;
    }

    selection = VisibleSelection(base, extent);
    // Only allow changes between caret positions or to text selection.
    bool selectChangeAllowed = (!selection.isCaret() || sc->isCaret());
    if (selectChangeAllowed && sc->shouldChangeSelection(selection))
        sc->setSelection(selection);
}

bool WebViewCore::nodeIsClickableOrFocusable(Node* node)
{
    if (!node)
        return false;
    if (node->disabled())
        return false;
    if (!node->inDocument())
        return false;
    if (!node->renderer() || node->renderer()->style()->visibility() != VISIBLE)
        return false;
    return node->supportsFocus()
            || node->hasEventListeners(eventNames().clickEvent)
            || node->hasEventListeners(eventNames().mousedownEvent)
            || node->hasEventListeners(eventNames().mouseupEvent)
            || node->hasEventListeners(eventNames().mouseoverEvent);
}

// get the highlight rectangles for the touch point (x, y) with the slop
AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool doMoveMouse)
{
    if (doMoveMouse)
        moveMouse(x, y, 0, true);
    HitTestResult hitTestResult = m_mainFrame->eventHandler()->hitTestResultAtPoint(IntPoint(x, y),
            false, false, DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly, IntSize(slop, slop));
    AndroidHitTestResult androidHitResult(this, hitTestResult);
    if (!hitTestResult.innerNode() || !hitTestResult.innerNode()->inDocument()) {
        ALOGE("Should not happen: no in document Node found");
        return androidHitResult;
    }
    const ListHashSet<RefPtr<Node> >& list = hitTestResult.rectBasedTestResult();
    if (list.isEmpty()) {
        ALOGE("Should not happen: no rect-based-test nodes found");
        return androidHitResult;
    }
    Frame* frame = hitTestResult.innerNode()->document()->frame();
    Vector<TouchNodeData> nodeDataList;
    if (hitTestResult.innerNode() != hitTestResult.innerNonSharedNode()
            && hitTestResult.innerNode()->hasTagName(WebCore::HTMLNames::areaTag)) {
        HTMLAreaElement* area = static_cast<HTMLAreaElement*>(hitTestResult.innerNode());
        androidHitResult.hitTestResult().setURLElement(area);
        androidHitResult.highlightRects().append(area->computeRect(
                hitTestResult.innerNonSharedNode()->renderer()));
        return androidHitResult;
    }
    ListHashSet<RefPtr<Node> >::const_iterator last = list.end();
    for (ListHashSet<RefPtr<Node> >::const_iterator it = list.begin(); it != last; ++it) {
        // TODO: it seems reasonable to not search across the frame. Isn't it?
        // if the node is not in the same frame as the innerNode, skip it
        if (it->get()->document()->frame() != frame)
            continue;
        // traverse up the tree to find the first node that needs highlight
        bool found = false;
        Node* eventNode = it->get();
        Node* innerNode = eventNode;
        while (eventNode) {
            RenderObject* render = eventNode->renderer();
            if (render && (render->isBody() || render->isRenderView()))
                break;
            if (nodeIsClickableOrFocusable(eventNode)) {
                found = true;
                break;
            }
            // the nodes in the rectBasedTestResult() are ordered based on z-index during hit testing.
            // so do not search for the eventNode across explicit z-index border.
            // TODO: this is a hard one to call. z-index is quite complicated as its value only
            // matters when you compare two RenderLayer in the same hierarchy level. e.g. in
            // the following example, "b" is on the top as its z level is the highest. even "c"
            // has 100 as z-index, it is still below "d" as its parent has the same z-index as
            // "d" and logically before "d". Of course "a" is the lowest in the z level.
            //
            // z-index:auto "a"
            //   z-index:2 "b"
            //   z-index:1
            //     z-index:100 "c"
            //   z-index:1 "d"
            //
            // If the fat point touches everyone, the order in the list should be "b", "d", "c"
            // and "a". When we search for the event node for "b", we really don't want "a" as
            // in the z-order it is behind everything else.
            if (render && !render->style()->hasAutoZIndex())
                break;
            eventNode = eventNode->parentNode();
        }
        // didn't find any eventNode, skip it
        if (!found)
            continue;
        // first quick check whether it is a duplicated node before computing bounding box
        Vector<TouchNodeData>::const_iterator nlast = nodeDataList.end();
        for (Vector<TouchNodeData>::const_iterator n = nodeDataList.begin(); n != nlast; ++n) {
            // found the same node, skip it
            if (eventNode == n->mUrlNode) {
                found = false;
                break;
            }
        }
        if (!found)
            continue;
        // next check whether the node is fully covered by or fully covering another node.
        found = false;
        IntRect rect = getAbsoluteBoundingBox(eventNode);
        if (rect.isEmpty()) {
            // if the node's bounds is empty and it is not a ContainerNode, skip it.
            if (!eventNode->isContainerNode())
                continue;
            // if the node's children are all positioned objects, its bounds can be empty.
            // Walk through the children to find the bounding box.
            Node* child = static_cast<const ContainerNode*>(eventNode)->firstChild();
            while (child) {
                IntRect childrect;
                if (child->renderer())
                    childrect = getAbsoluteBoundingBox(child);
                if (!childrect.isEmpty()) {
                    rect.unite(childrect);
                    child = child->traverseNextSibling(eventNode);
                } else
                    child = child->traverseNextNode(eventNode);
            }
        }
        for (int i = nodeDataList.size() - 1; i >= 0; i--) {
            TouchNodeData n = nodeDataList.at(i);
            // the new node is enclosing an existing node, skip it
            if (rect.contains(n.mBounds)) {
                found = true;
                break;
            }
            // the new node is fully inside an existing node, remove the existing node
            if (n.mBounds.contains(rect))
                nodeDataList.remove(i);
        }
        if (!found) {
            TouchNodeData newNode;
            newNode.mUrlNode = eventNode;
            newNode.mBounds = rect;
            newNode.mInnerNode = innerNode;
            nodeDataList.append(newNode);
        }
    }
    if (!nodeDataList.size()) {
        androidHitResult.searchContentDetectors();
        return androidHitResult;
    }
    // finally select the node with the largest overlap with the fat point
    TouchNodeData final;
    final.mUrlNode = 0;
    IntPoint docPos = frame->view()->windowToContents(m_mousePos);
    IntRect testRect(docPos.x() - slop, docPos.y() - slop, 2 * slop + 1, 2 * slop + 1);
    int area = 0;
    Vector<TouchNodeData>::const_iterator nlast = nodeDataList.end();
    for (Vector<TouchNodeData>::const_iterator n = nodeDataList.begin(); n != nlast; ++n) {
        IntRect rect = n->mBounds;
        rect.intersect(testRect);
        int a = rect.width() * rect.height();
        if (a > area || !final.mUrlNode) {
            final = *n;
            area = a;
        }
    }
    // now get the node's highlight rectangles in the page coordinate system
    if (final.mUrlNode) {
        // Update innerNode and innerNonSharedNode
        androidHitResult.hitTestResult().setInnerNode(final.mInnerNode);
        androidHitResult.hitTestResult().setInnerNonSharedNode(final.mInnerNode);
        if (final.mUrlNode->isElementNode()) {
            // We found a URL element. Update the hitTestResult
            androidHitResult.setURLElement(static_cast<Element*>(final.mUrlNode));
        } else {
            androidHitResult.setURLElement(0);
        }
        Vector<IntRect>& highlightRects = androidHitResult.highlightRects();
        if (doMoveMouse && highlightRects.size() > 0) {
            // adjust m_mousePos if it is not inside the returned highlight
            // rectangles
            IntRect foundIntersection;
            IntRect inputRect = IntRect(x - slop, y - slop,
                                        slop * 2 + 1, slop * 2 + 1);
            for (size_t i = 0; i < highlightRects.size(); i++) {
                IntRect& hr = highlightRects[i];
                IntRect test = inputRect;
                test.intersect(hr);
                if (!test.isEmpty()) {
                    foundIntersection = test;
                    break;
                }
            }
            if (!foundIntersection.isEmpty() && !foundIntersection.contains(x, y)) {
                IntPoint pt = foundIntersection.center();
                moveMouse(pt.x(), pt.y(), 0, true);
            }
        }
    } else {
        androidHitResult.searchContentDetectors();
    }
    return androidHitResult;
}

///////////////////////////////////////////////////////////////////////////////

void WebViewCore::addPlugin(PluginWidgetAndroid* w)
{
//    SkDebugf("----------- addPlugin %p", w);
    /* The plugin must be appended to the end of the array. This ensures that if
       the plugin is added while iterating through the array (e.g. sendEvent(...))
       that the iteration process is not corrupted.
     */
    *m_plugins.append() = w;
}

void WebViewCore::removePlugin(PluginWidgetAndroid* w)
{
//    SkDebugf("----------- removePlugin %p", w);
    int index = m_plugins.find(w);
    if (index < 0) {
        SkDebugf("--------------- pluginwindow not found! %p\n", w);
    } else {
        m_plugins.removeShuffle(index);
    }
}

bool WebViewCore::isPlugin(PluginWidgetAndroid* w) const
{
    return m_plugins.find(w) >= 0;
}

void WebViewCore::invalPlugin(PluginWidgetAndroid* w)
{
    const double PLUGIN_INVAL_DELAY = 1.0 / 60;

    if (!m_pluginInvalTimer.isActive()) {
        m_pluginInvalTimer.startOneShot(PLUGIN_INVAL_DELAY);
    }
}

void WebViewCore::drawPlugins()
{
    SkRegion inval; // accumualte what needs to be redrawn
    PluginWidgetAndroid** iter = m_plugins.begin();
    PluginWidgetAndroid** stop = m_plugins.end();

    for (; iter < stop; ++iter) {
        PluginWidgetAndroid* w = *iter;
        SkIRect dirty;
        if (w->isDirty(&dirty)) {
            w->draw();
            inval.op(dirty, SkRegion::kUnion_Op);
        }
    }

    if (!inval.isEmpty()) {
        // inval.getBounds() is our rectangle
        const SkIRect& bounds = inval.getBounds();
        WebCore::IntRect r(bounds.fLeft, bounds.fTop,
                           bounds.width(), bounds.height());
        this->viewInvalidate(r);
    }
}

void WebViewCore::notifyPluginsOnFrameLoad(const Frame* frame) {
    // if frame is the parent then notify all plugins
    if (!frame->tree()->parent()) {
        // trigger an event notifying the plugins that the page has loaded
        ANPEvent event;
        SkANP::InitEvent(&event, kLifecycle_ANPEventType);
        event.data.lifecycle.action = kOnLoad_ANPLifecycleAction;
        sendPluginEvent(event);
        // trigger the on/off screen notification if the page was reloaded
        sendPluginVisibleScreen();
    }
    // else if frame's parent has completed
    else if (!frame->tree()->parent()->loader()->isLoading()) {
        // send to all plugins who have this frame in their heirarchy
        PluginWidgetAndroid** iter = m_plugins.begin();
        PluginWidgetAndroid** stop = m_plugins.end();
        for (; iter < stop; ++iter) {
            Frame* currentFrame = (*iter)->pluginView()->parentFrame();
            while (currentFrame) {
                if (frame == currentFrame) {
                    ANPEvent event;
                    SkANP::InitEvent(&event, kLifecycle_ANPEventType);
                    event.data.lifecycle.action = kOnLoad_ANPLifecycleAction;
                    (*iter)->sendEvent(event);

                    // trigger the on/off screen notification if the page was reloaded
                    ANPRectI visibleRect;
                    getVisibleScreen(visibleRect);
                    (*iter)->setVisibleScreen(visibleRect, m_scale);

                    break;
                }
                currentFrame = currentFrame->tree()->parent();
            }
        }
    }
}

void WebViewCore::getVisibleScreen(ANPRectI& visibleRect)
{
    visibleRect.left = m_scrollOffsetX;
    visibleRect.top = m_scrollOffsetY;
    visibleRect.right = m_scrollOffsetX + m_screenWidth;
    visibleRect.bottom = m_scrollOffsetY + m_screenHeight;
}

void WebViewCore::sendPluginVisibleScreen()
{
    /* We may want to cache the previous values and only send the notification
       to the plugin in the event that one of the values has changed.
     */

    ANPRectI visibleRect;
    getVisibleScreen(visibleRect);

    PluginWidgetAndroid** iter = m_plugins.begin();
    PluginWidgetAndroid** stop = m_plugins.end();
    for (; iter < stop; ++iter) {
        (*iter)->setVisibleScreen(visibleRect, m_scale);
    }
}

void WebViewCore::sendPluginSurfaceReady()
{
    PluginWidgetAndroid** iter = m_plugins.begin();
    PluginWidgetAndroid** stop = m_plugins.end();
    for (; iter < stop; ++iter) {
        (*iter)->checkSurfaceReady();
    }
}

void WebViewCore::sendPluginEvent(const ANPEvent& evt)
{
    /* The list of plugins may be manipulated as we iterate through the list.
       This implementation allows for the addition of new plugins during an
       iteration, but may fail if a plugin is removed. Currently, there are not
       any use cases where a plugin is deleted while processing this loop, but
       if it does occur we will have to use an alternate data structure and/or
       iteration mechanism.
     */
    for (int x = 0; x < m_plugins.count(); x++) {
        m_plugins[x]->sendEvent(evt);
    }
}

PluginWidgetAndroid* WebViewCore::getPluginWidget(NPP npp)
{
    PluginWidgetAndroid** iter = m_plugins.begin();
    PluginWidgetAndroid** stop = m_plugins.end();
    for (; iter < stop; ++iter) {
        if ((*iter)->pluginView()->instance() == npp) {
            return (*iter);
        }
    }
    return 0;
}

static PluginView* nodeIsPlugin(Node* node) {
    RenderObject* renderer = node->renderer();
    if (renderer && renderer->isWidget()) {
        Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
        if (widget && widget->isPluginView())
            return static_cast<PluginView*>(widget);
    }
    return 0;
}

///////////////////////////////////////////////////////////////////////////////

// Update mouse position
void WebViewCore::moveMouse(int x, int y, HitTestResult* hoveredNode, bool isClickCandidate)
{
    // mouse event expects the position in the window coordinate
    m_mousePos = WebCore::IntPoint(x - m_scrollOffsetX, y - m_scrollOffsetY);
    if (isClickCandidate)
        m_mouseClickPos = m_mousePos;
    // validNode will still return true if the node is null, as long as we have
    // a valid frame.  Do not want to make a call on frame unless it is valid.
    WebCore::PlatformMouseEvent mouseEvent(m_mousePos, m_mousePos,
        WebCore::NoButton, WebCore::MouseEventMoved, 1, false, false, false,
        false, WTF::currentTime());
    m_mainFrame->eventHandler()->handleMouseMoveEvent(mouseEvent, hoveredNode);
}

Position WebViewCore::getPositionForOffset(Node* node, int offset)
{
    Position start = firstPositionInNode(node);
    Position end = lastPositionInNode(node);
    Document* document = node->document();
    PassRefPtr<Range> range = Range::create(document, start, end);
    WebCore::CharacterIterator iterator(range.get());
    iterator.advance(offset);
    return iterator.range()->startPosition();
}

void WebViewCore::setSelection(Node* node, int start, int end)
{
    RenderTextControl* control = toRenderTextControl(node);
    if (control)
        setSelectionRange(node, start, end);
    else {
        Position startPosition = getPositionForOffset(node, start);
        Position endPosition = getPositionForOffset(node, end);
        VisibleSelection selection(startPosition, endPosition);
        SelectionController* selector = node->document()->frame()->selection();
        selector->setSelection(selection);
    }
}

void WebViewCore::setSelection(int start, int end)
{
    WebCore::Node* focus = currentFocus();
    if (!focus)
        return;
    if (start > end)
        swap(start, end);

    // Tell our EditorClient that this change was generated from the UI, so it
    // does not need to echo it to the UI.
    EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
            m_mainFrame->editor()->client());
    client->setUiGeneratedSelectionChange(true);
    setSelection(focus, start, end);
    RenderTextControl* control = toRenderTextControl(focus);
    if (start != end && control) {
        // Fire a select event. No event is sent when the selection reduces to
        // an insertion point
        control->selectionChanged(true);
    }
    client->setUiGeneratedSelectionChange(false);
    bool isPasswordField = false;
    if (focus->isElementNode()) {
        WebCore::Element* element = static_cast<WebCore::Element*>(focus);
        if (WebCore::InputElement* inputElement = element->toInputElement())
            isPasswordField = static_cast<WebCore::HTMLInputElement*>(inputElement)->isPasswordField();
    }
    // For password fields, this is done in the UI side via
    // bringPointIntoView, since the UI does the drawing.
    if ((control && control->isTextArea()) || !isPasswordField)
        revealSelection();
}

String WebViewCore::modifySelection(const int direction, const int axis)
{
    DOMSelection* selection = m_mainFrame->domWindow()->getSelection();
    ASSERT(selection);
    // We've seen crashes where selection is null, but we don't know why
    // See http://b/5244036
    if (!selection)
        return String();
    if (selection->rangeCount() > 1)
        selection->removeAllRanges();
    switch (axis) {
        case AXIS_CHARACTER:
        case AXIS_WORD:
        case AXIS_SENTENCE:
            return modifySelectionTextNavigationAxis(selection, direction, axis);
        case AXIS_HEADING:
        case AXIS_SIBLING:
        case AXIS_PARENT_FIRST_CHILD:
        case AXIS_DOCUMENT:
            return modifySelectionDomNavigationAxis(selection, direction, axis);
        default:
            ALOGE("Invalid navigation axis: %d", axis);
            return String();
    }
}

void WebViewCore::scrollNodeIntoView(Frame* frame, Node* node)
{
    if (!frame || !node)
        return;

    Element* elementNode = 0;

    // If not an Element, find a visible predecessor
    // Element to scroll into view.
    if (!node->isElementNode()) {
        HTMLElement* body = frame->document()->body();
        do {
            if (node == body)
                return;
            node = node->parentNode();
        } while (node && !node->isElementNode() && !isVisible(node));
    }

    // Couldn't find a visible predecessor.
    if (!node)
        return;

    elementNode = static_cast<Element*>(node);
    elementNode->scrollIntoViewIfNeeded(true);
}

String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, int direction, int axis)
{
    Node* body = m_mainFrame->document()->body();

    ExceptionCode ec = 0;
    String markup;

    // initialize the selection if necessary
    if (selection->rangeCount() == 0) {
        if (m_currentNodeDomNavigationAxis
                && validNode(m_mainFrame,
                m_mainFrame, m_currentNodeDomNavigationAxis)) {
            RefPtr<Range> rangeRef =
                selection->frame()->document()->createRange();
            rangeRef->selectNode(m_currentNodeDomNavigationAxis, ec);
            m_currentNodeDomNavigationAxis = 0;
            if (ec)
                return String();
            selection->addRange(rangeRef.get());
        } else if (currentFocus()) {
            selection->setPosition(currentFocus(), 0, ec);
        } else {
            selection->setPosition(body, 0, ec);
        }
        if (ec)
            return String();
    }

    // collapse the selection
    if (direction == DIRECTION_FORWARD)
        selection->collapseToEnd(ec);
    else
        selection->collapseToStart(ec);
    if (ec)
        return String();

    // Make sure the anchor node is a text node since we are generating
    // the markup of the selection which includes the anchor, the focus,
    // and any crossed nodes. Forcing the condition that the selection
    // starts and ends on text nodes guarantees symmetric selection markup.
    // Also this way the text content, rather its container, is highlighted.
    Node* anchorNode = selection->anchorNode();
    if (anchorNode->isElementNode()) {
        // Collapsed selection while moving forward points to the
        // next unvisited node and while moving backward to the
        // last visited node.
        if (direction == DIRECTION_FORWARD)
            advanceAnchorNode(selection, direction, markup, false, ec);
        else
            advanceAnchorNode(selection, direction, markup, true, ec);
        if (ec)
            return String();
        if (!markup.isEmpty())
            return markup;
    }

    // If the selection is at the end of a non white space text move
    // it to the next visible text node with non white space content.
    // This is a workaround for the selection getting stuck.
    anchorNode = selection->anchorNode();
    if (anchorNode->isTextNode()) {
        if (direction == DIRECTION_FORWARD) {
            String suffix = anchorNode->textContent().substring(
                    selection->anchorOffset(), caretMaxOffset(anchorNode));
            // If at the end of non white space text we advance the
            // anchor node to either an input element or non empty text.
            if (suffix.stripWhiteSpace().isEmpty()) {
                advanceAnchorNode(selection, direction, markup, true, ec);
            }
        } else {
            String prefix = anchorNode->textContent().substring(0,
                    selection->anchorOffset());
            // If at the end of non white space text we advance the
            // anchor node to either an input element or non empty text.
            if (prefix.stripWhiteSpace().isEmpty()) {
                advanceAnchorNode(selection, direction, markup, true, ec);
            }
        }
        if (ec)
            return String();
        if (!markup.isEmpty())
            return markup;
    }

    // extend the selection
    String directionStr;
    if (direction == DIRECTION_FORWARD)
        directionStr = "forward";
    else
        directionStr = "backward";

    String axisStr;
    if (axis == AXIS_CHARACTER)
        axisStr = "character";
    else if (axis == AXIS_WORD)
        axisStr = "word";
    else
        axisStr = "sentence";

    selection->modify("extend", directionStr, axisStr);

    // Make sure the focus node is a text node in order to have the
    // selection generate symmetric markup because the latter
    // includes all nodes crossed by the selection.  Also this way
    // the text content, rather its container, is highlighted.
    Node* focusNode = selection->focusNode();
    if (focusNode->isElementNode()) {
        focusNode = getImplicitBoundaryNode(selection->focusNode(),
                selection->focusOffset(), direction);
        if (!focusNode)
            return String();
        if (direction == DIRECTION_FORWARD) {
            focusNode = focusNode->traversePreviousSiblingPostOrder(body);
            if (focusNode && !isContentTextNode(focusNode)) {
                Node* textNode = traverseNextContentTextNode(focusNode,
                        anchorNode, DIRECTION_BACKWARD);
                if (textNode)
                    anchorNode = textNode;
            }
            if (focusNode && isContentTextNode(focusNode)) {
                selection->extend(focusNode, caretMaxOffset(focusNode), ec);
                if (ec)
                    return String();
            }
        } else {
            focusNode = focusNode->traverseNextSibling();
            if (focusNode && !isContentTextNode(focusNode)) {
                Node* textNode = traverseNextContentTextNode(focusNode,
                        anchorNode, DIRECTION_FORWARD);
                if (textNode)
                    anchorNode = textNode;
            }
            if (anchorNode && isContentTextNode(anchorNode)) {
                selection->extend(focusNode, 0, ec);
                if (ec)
                    return String();
            }
        }
    }

    // Enforce that the selection does not cross anchor boundaries. This is
    // a workaround for the asymmetric behavior of WebKit while crossing
    // anchors.
    anchorNode = getImplicitBoundaryNode(selection->anchorNode(),
            selection->anchorOffset(), direction);
    focusNode = getImplicitBoundaryNode(selection->focusNode(),
            selection->focusOffset(), direction);
    if (anchorNode && focusNode && anchorNode != focusNode) {
        Node* inputControl = getIntermediaryInputElement(anchorNode, focusNode,
                direction);
        if (inputControl) {
            if (direction == DIRECTION_FORWARD) {
                if (isDescendantOf(inputControl, anchorNode)) {
                    focusNode = inputControl;
                } else {
                    focusNode = inputControl->traversePreviousSiblingPostOrder(
                            body);
                    if (!focusNode)
                        focusNode = inputControl;
                }
                // We prefer a text node contained in the input element.
                if (!isContentTextNode(focusNode)) {
                    Node* textNode = traverseNextContentTextNode(focusNode,
                        anchorNode, DIRECTION_BACKWARD);
                    if (textNode)
                        focusNode = textNode;
                }
                // If we found text in the input select it.
                // Otherwise, select the input element itself.
                if (isContentTextNode(focusNode)) {
                    selection->extend(focusNode, caretMaxOffset(focusNode), ec);
                } else if (anchorNode != focusNode) {
                    // Note that the focusNode always has parent and that
                    // the offset can be one more that the index of the last
                    // element - this is how WebKit selects such elements.
                    selection->extend(focusNode->parentNode(),
                            focusNode->nodeIndex() + 1, ec);
                }
                if (ec)
                    return String();
            } else {
                if (isDescendantOf(inputControl, anchorNode)) {
                    focusNode = inputControl;
                } else {
                    focusNode = inputControl->traverseNextSibling();
                    if (!focusNode)
                        focusNode = inputControl;
                }
                // We prefer a text node contained in the input element.
                if (!isContentTextNode(focusNode)) {
                    Node* textNode = traverseNextContentTextNode(focusNode,
                            anchorNode, DIRECTION_FORWARD);
                    if (textNode)
                        focusNode = textNode;
                }
                // If we found text in the input select it.
                // Otherwise, select the input element itself.
                if (isContentTextNode(focusNode)) {
                    selection->extend(focusNode, caretMinOffset(focusNode), ec);
                } else if (anchorNode != focusNode) {
                    // Note that the focusNode always has parent and that
                    // the offset can be one more that the index of the last
                    // element - this is how WebKit selects such elements.
                    selection->extend(focusNode->parentNode(),
                            focusNode->nodeIndex() + 1, ec);
                }
                if (ec)
                   return String();
            }
        }
    }

    // make sure the selection is visible
    if (direction == DIRECTION_FORWARD)
        scrollNodeIntoView(m_mainFrame, selection->focusNode());
    else
        scrollNodeIntoView(m_mainFrame, selection->anchorNode());

    // format markup for the visible content
    RefPtr<Range> range = selection->getRangeAt(0, ec);
    if (ec)
        return String();
    IntRect bounds = range->boundingBox();
    selectAt(bounds.center().x(), bounds.center().y());
    markup = formatMarkup(selection);
    ALOGV("Selection markup: %s", markup.utf8().data());

    return markup;
}

Node* WebViewCore::getImplicitBoundaryNode(Node* node, unsigned offset, int direction)
{
    if (node->offsetInCharacters())
        return node;
    if (!node->hasChildNodes())
        return node;
    if (offset < node->childNodeCount())
        return node->childNode(offset);
    else
        if (direction == DIRECTION_FORWARD)
            return node->traverseNextSibling();
        else
            return node->traversePreviousNodePostOrder(
                    node->document()->body());
}

Node* WebViewCore::getNextAnchorNode(Node* anchorNode, bool ignoreFirstNode, int direction)
{
    Node* body = 0;
    Node* currentNode = 0;
    if (direction == DIRECTION_FORWARD) {
        if (ignoreFirstNode)
            currentNode = anchorNode->traverseNextNode(body);
        else
            currentNode = anchorNode;
    } else {
        body = anchorNode->document()->body();
        if (ignoreFirstNode)
            currentNode = anchorNode->traversePreviousSiblingPostOrder(body);
        else
            currentNode = anchorNode;
    }
    while (currentNode) {
        if (isContentTextNode(currentNode)
                || isContentInputElement(currentNode))
            return currentNode;
        if (direction == DIRECTION_FORWARD)
            currentNode = currentNode->traverseNextNode();
        else
            currentNode = currentNode->traversePreviousNodePostOrder(body);
    }
    return 0;
}

void WebViewCore::advanceAnchorNode(DOMSelection* selection, int direction,
        String& markup, bool ignoreFirstNode, ExceptionCode& ec)
{
    Node* anchorNode = getImplicitBoundaryNode(selection->anchorNode(),
            selection->anchorOffset(), direction);
    if (!anchorNode) {
        ec = NOT_FOUND_ERR;
        return;
    }
    // If the anchor offset is invalid i.e. the anchor node has no
    // child with that index getImplicitAnchorNode returns the next
    // logical node in the current direction. In such a case our
    // position in the DOM tree was has already been advanced,
    // therefore we there is no need to do that again.
    if (selection->anchorNode()->isElementNode()) {
        unsigned anchorOffset = selection->anchorOffset();
        unsigned childNodeCount = selection->anchorNode()->childNodeCount();
        if (anchorOffset >= childNodeCount)
            ignoreFirstNode = false;
    }
    // Find the next anchor node given our position in the DOM and
    // whether we want the current node to be considered as well.
    Node* nextAnchorNode = getNextAnchorNode(anchorNode, ignoreFirstNode,
            direction);
    if (!nextAnchorNode) {
        ec = NOT_FOUND_ERR;
        return;
    }
    if (nextAnchorNode->isElementNode()) {
        // If this is an input element tell the WebView thread
        // to set the cursor to that control.
        if (isContentInputElement(nextAnchorNode)) {
            IntRect bounds = nextAnchorNode->getRect();
            selectAt(bounds.center().x(), bounds.center().y());
        }
        Node* textNode = 0;
        // Treat the text content of links as any other text but
        // for the rest input elements select the control itself.
        if (nextAnchorNode->hasTagName(WebCore::HTMLNames::aTag))
            textNode = traverseNextContentTextNode(nextAnchorNode,
                    nextAnchorNode, direction);
        // We prefer to select the text content of the link if such,
        // otherwise just select the element itself.
        if (textNode) {
            nextAnchorNode = textNode;
        } else {
            if (direction == DIRECTION_FORWARD) {
                selection->setBaseAndExtent(nextAnchorNode,
                        caretMinOffset(nextAnchorNode), nextAnchorNode,
                        caretMaxOffset(nextAnchorNode), ec);
            } else {
                selection->setBaseAndExtent(nextAnchorNode,
                        caretMaxOffset(nextAnchorNode), nextAnchorNode,
                        caretMinOffset(nextAnchorNode), ec);
            }
            if (!ec)
                markup = formatMarkup(selection);
            // make sure the selection is visible
            scrollNodeIntoView(selection->frame(), nextAnchorNode);
            return;
        }
    }
    if (direction == DIRECTION_FORWARD)
        selection->setPosition(nextAnchorNode,
                caretMinOffset(nextAnchorNode), ec);
    else
        selection->setPosition(nextAnchorNode,
                caretMaxOffset(nextAnchorNode), ec);
}

bool WebViewCore::isContentInputElement(Node* node)
{
  return (isVisible(node)
          && (node->hasTagName(WebCore::HTMLNames::selectTag)
          || node->hasTagName(WebCore::HTMLNames::aTag)
          || node->hasTagName(WebCore::HTMLNames::inputTag)
          || node->hasTagName(WebCore::HTMLNames::buttonTag)));
}

bool WebViewCore::isContentTextNode(Node* node)
{
   if (!node || !node->isTextNode())
       return false;
   Text* textNode = static_cast<Text*>(node);
   return (isVisible(textNode) && textNode->length() > 0
       && !textNode->containsOnlyWhitespace());
}

Text* WebViewCore::traverseNextContentTextNode(Node* fromNode, Node* toNode, int direction)
{
    Node* currentNode = fromNode;
    do {
        if (direction == DIRECTION_FORWARD)
            currentNode = currentNode->traverseNextNode(toNode);
        else
            currentNode = currentNode->traversePreviousNodePostOrder(toNode);
    } while (currentNode && !isContentTextNode(currentNode));
    return static_cast<Text*>(currentNode);
}

Node* WebViewCore::getIntermediaryInputElement(Node* fromNode, Node* toNode, int direction)
{
    if (fromNode == toNode)
        return 0;
    if (direction == DIRECTION_FORWARD) {
        Node* currentNode = fromNode;
        while (currentNode && currentNode != toNode) {
            if (isContentInputElement(currentNode))
                return currentNode;
            currentNode = currentNode->traverseNextNodePostOrder();
        }
        currentNode = fromNode;
        while (currentNode && currentNode != toNode) {
            if (isContentInputElement(currentNode))
                return currentNode;
            currentNode = currentNode->traverseNextNode();
        }
    } else {
        Node* currentNode = fromNode->traversePreviousNode();
        while (currentNode && currentNode != toNode) {
            if (isContentInputElement(currentNode))
                return currentNode;
            currentNode = currentNode->traversePreviousNode();
        }
        currentNode = fromNode->traversePreviousNodePostOrder();
        while (currentNode && currentNode != toNode) {
            if (isContentInputElement(currentNode))
                return currentNode;
            currentNode = currentNode->traversePreviousNodePostOrder();
        }
    }
    return 0;
}

bool WebViewCore::isDescendantOf(Node* parent, Node* node)
{
    Node* currentNode = node;
    while (currentNode) {
        if (currentNode == parent) {
            return true;
        }
        currentNode = currentNode->parentNode();
    }
    return false;
}

String WebViewCore::modifySelectionDomNavigationAxis(DOMSelection* selection, int direction, int axis)
{
    HTMLElement* body = m_mainFrame->document()->body();
    if (!m_currentNodeDomNavigationAxis && selection->focusNode()) {
        m_currentNodeDomNavigationAxis = selection->focusNode();
        selection->empty();
        if (m_currentNodeDomNavigationAxis->isTextNode())
            m_currentNodeDomNavigationAxis =
                m_currentNodeDomNavigationAxis->parentNode();
    }
    if (!m_currentNodeDomNavigationAxis)
        m_currentNodeDomNavigationAxis = currentFocus();
    if (!m_currentNodeDomNavigationAxis
            || !validNode(m_mainFrame, m_mainFrame,
                                        m_currentNodeDomNavigationAxis))
        m_currentNodeDomNavigationAxis = body;
    Node* currentNode = m_currentNodeDomNavigationAxis;
    if (axis == AXIS_HEADING) {
        if (currentNode == body && direction == DIRECTION_BACKWARD)
            currentNode = currentNode->lastDescendant();
        do {
            if (direction == DIRECTION_FORWARD)
                currentNode = currentNode->traverseNextNode(body);
            else
                currentNode = currentNode->traversePreviousNode(body);
        } while (currentNode && (currentNode->isTextNode()
            || !isVisible(currentNode) || !isHeading(currentNode)));
    } else if (axis == AXIS_PARENT_FIRST_CHILD) {
        if (direction == DIRECTION_FORWARD) {
            currentNode = currentNode->firstChild();
            while (currentNode && (currentNode->isTextNode()
                    || !isVisible(currentNode)))
                currentNode = currentNode->nextSibling();
        } else {
            do {
                if (currentNode == body)
                    return String();
                currentNode = currentNode->parentNode();
            } while (currentNode && (currentNode->isTextNode()
                    || !isVisible(currentNode)));
        }
    } else if (axis == AXIS_SIBLING) {
        do {
            if (direction == DIRECTION_FORWARD)
                currentNode = currentNode->nextSibling();
            else {
                if (currentNode == body)
                    return String();
                currentNode = currentNode->previousSibling();
            }
        } while (currentNode && (currentNode->isTextNode()
                || !isVisible(currentNode)));
    } else if (axis == AXIS_DOCUMENT) {
        currentNode = body;
        if (direction == DIRECTION_FORWARD)
            currentNode = currentNode->lastDescendant();
    } else {
        ALOGE("Invalid axis: %d", axis);
        return String();
    }
    if (currentNode) {
        m_currentNodeDomNavigationAxis = currentNode;
        scrollNodeIntoView(m_mainFrame, currentNode);
        String selectionString = createMarkup(currentNode);
        ALOGV("Selection markup: %s", selectionString.utf8().data());
        return selectionString;
    }
    return String();
}

bool WebViewCore::isHeading(Node* node)
{
    if (node->hasTagName(WebCore::HTMLNames::h1Tag)
            || node->hasTagName(WebCore::HTMLNames::h2Tag)
            || node->hasTagName(WebCore::HTMLNames::h3Tag)
            || node->hasTagName(WebCore::HTMLNames::h4Tag)
            || node->hasTagName(WebCore::HTMLNames::h5Tag)
            || node->hasTagName(WebCore::HTMLNames::h6Tag)) {
        return true;
    }

    if (node->isElementNode()) {
        Element* element = static_cast<Element*>(node);
        String roleAttribute =
            element->getAttribute(WebCore::HTMLNames::roleAttr).string();
        if (equalIgnoringCase(roleAttribute, "heading"))
            return true;
    }

    return false;
}

bool WebViewCore::isVisible(Node* node)
{
    // start off an element
    Element* element = 0;
    if (node->isElementNode())
        element = static_cast<Element*>(node);
    else
        element = node->parentElement();
    // check renderer
    if (!element->renderer()) {
        return false;
    }
    // check size
    if (element->offsetHeight() == 0 || element->offsetWidth() == 0) {
        return false;
    }
    // check style
    Node* body = m_mainFrame->document()->body();
    Node* currentNode = element;
    while (currentNode && currentNode != body) {
        RenderStyle* style = currentNode->computedStyle();
        if (style &&
                (style->display() == WebCore::NONE || style->visibility() == WebCore::HIDDEN)) {
            return false;
        }
        currentNode = currentNode->parentNode();
    }
    return true;
}

String WebViewCore::formatMarkup(DOMSelection* selection)
{
    ExceptionCode ec = 0;
    String markup = String();
    RefPtr<Range> wholeRange = selection->getRangeAt(0, ec);
    if (ec)
        return String();
    if (!wholeRange->startContainer() || !wholeRange->startContainer())
        return String();
    // Since formatted markup contains invisible nodes it
    // is created from the concatenation of the visible fragments.
    Node* firstNode = wholeRange->firstNode();
    Node* pastLastNode = wholeRange->pastLastNode();
    Node* currentNode = firstNode;
    RefPtr<Range> currentRange;

    while (currentNode != pastLastNode) {
        Node* nextNode = currentNode->traverseNextNode();
        if (!isVisible(currentNode)) {
            if (currentRange) {
                markup = markup + currentRange->toHTML().utf8().data();
                currentRange = 0;
            }
        } else {
            if (!currentRange) {
                currentRange = selection->frame()->document()->createRange();
                if (ec)
                    break;
                if (currentNode == firstNode) {
                    currentRange->setStart(wholeRange->startContainer(),
                        wholeRange->startOffset(), ec);
                    if (ec)
                        break;
                } else {
                    currentRange->setStart(currentNode->parentNode(),
                        currentNode->nodeIndex(), ec);
                    if (ec)
                       break;
                }
            }
            if (nextNode == pastLastNode) {
                currentRange->setEnd(wholeRange->endContainer(),
                    wholeRange->endOffset(), ec);
                if (ec)
                    break;
                markup = markup + currentRange->toHTML().utf8().data();
            } else {
                if (currentNode->offsetInCharacters())
                    currentRange->setEnd(currentNode,
                        currentNode->maxCharacterOffset(), ec);
                else
                    currentRange->setEnd(currentNode->parentNode(),
                            currentNode->nodeIndex() + 1, ec);
                if (ec)
                    break;
            }
        }
        currentNode = nextNode;
    }
    return markup.stripWhiteSpace();
}

void WebViewCore::selectAt(int x, int y)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_selectAt, x, y);
    checkException(env);
}

void WebViewCore::deleteSelection(int start, int end, int textGeneration)
{
    setSelection(start, end);
    if (start == end)
        return;
    WebCore::Node* focus = currentFocus();
    if (!focus)
        return;
    // Prevent our editor client from passing a message to change the
    // selection.
    EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
            m_mainFrame->editor()->client());
    client->setUiGeneratedSelectionChange(true);
    PlatformKeyboardEvent down(AKEYCODE_DEL, 0, 0, true, false, false, false);
    PlatformKeyboardEvent up(AKEYCODE_DEL, 0, 0, false, false, false, false);
    key(down);
    key(up);
    client->setUiGeneratedSelectionChange(false);
    m_textGeneration = textGeneration;
}

void WebViewCore::replaceTextfieldText(int oldStart,
        int oldEnd, const WTF::String& replace, int start, int end,
        int textGeneration)
{
    WebCore::Node* focus = currentFocus();
    if (!focus)
        return;
    setSelection(oldStart, oldEnd);
    // Prevent our editor client from passing a message to change the
    // selection.
    EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
            m_mainFrame->editor()->client());
    client->setUiGeneratedSelectionChange(true);
    if (replace.length())
        WebCore::TypingCommand::insertText(focus->document(), replace,
                false);
    else
        WebCore::TypingCommand::deleteSelection(focus->document());
    client->setUiGeneratedSelectionChange(false);
    // setSelection calls revealSelection, so there is no need to do it here.
    setSelection(start, end);
    m_textGeneration = textGeneration;
}

void WebViewCore::passToJs(int generation, const WTF::String& current,
    const PlatformKeyboardEvent& event)
{
    WebCore::Node* focus = currentFocus();
    if (!focus) {
        clearTextEntry();
        return;
    }
    // Block text field updates during a key press.
    m_blockTextfieldUpdates = true;
    // Also prevent our editor client from passing a message to change the
    // selection.
    EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
            m_mainFrame->editor()->client());
    client->setUiGeneratedSelectionChange(true);
    key(event);
    client->setUiGeneratedSelectionChange(false);
    m_blockTextfieldUpdates = false;
    m_textGeneration = generation;
    WTF::String test = getInputText(focus);
    if (test != current) {
        // If the text changed during the key event, update the UI text field.
        updateTextfield(focus, test);
    }
    // Now that the selection has settled down, send it.
    updateTextSelection();
}

void WebViewCore::scrollFocusedTextInput(float xPercent, int y)
{
    WebCore::Node* focus = currentFocus();
    if (!focus) {
        clearTextEntry();
        return;
    }
    WebCore::RenderTextControl* renderText = toRenderTextControl(focus);
    if (!renderText) {
        clearTextEntry();
        return;
    }

    int x = (int)round(xPercent * (renderText->scrollWidth() -
        renderText->contentWidth()));
    renderText->setScrollLeft(x);
    renderText->setScrollTop(y);
    focus->document()->frame()->selection()->recomputeCaretRect();
    updateTextSelection();
}

void WebViewCore::setFocusControllerActive(bool active)
{
    m_mainFrame->page()->focusController()->setActive(active);
}

void WebViewCore::saveDocumentState(WebCore::Frame* frame)
{
    if (!validNode(m_mainFrame, frame, 0))
        frame = m_mainFrame;
    WebCore::HistoryItem *item = frame->loader()->history()->currentItem();

    // item can be null when there is no offical URL for the current page. This happens
    // when the content is loaded using with WebCoreFrameBridge::LoadData() and there
    // is no failing URL (common case is when content is loaded using data: scheme)
    if (item) {
        item->setDocumentState(frame->document()->formElementsState());
    }
}

// Create an array of java Strings.
static jobjectArray makeLabelArray(JNIEnv* env, const uint16_t** labels, size_t count)
{
    jclass stringClass = env->FindClass("java/lang/String");
    ALOG_ASSERT(stringClass, "Could not find java/lang/String");
    jobjectArray array = env->NewObjectArray(count, stringClass, 0);
    ALOG_ASSERT(array, "Could not create new string array");

    for (size_t i = 0; i < count; i++) {
        jobject newString = env->NewString(&labels[i][1], labels[i][0]);
        env->SetObjectArrayElement(array, i, newString);
        env->DeleteLocalRef(newString);
        checkException(env);
    }
    env->DeleteLocalRef(stringClass);
    return array;
}

void WebViewCore::openFileChooser(PassRefPtr<WebCore::FileChooser> chooser)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;

    if (!chooser)
        return;

    WTF::String acceptType = chooser->acceptTypes();
    WTF::String capture;

#if ENABLE(MEDIA_CAPTURE)
    capture = chooser->capture();
#endif

    jstring jAcceptType = wtfStringToJstring(env, acceptType, true);
    jstring jCapture = wtfStringToJstring(env, capture, true);
    jstring jName = (jstring) env->CallObjectMethod(
            javaObject.get(), m_javaGlue->m_openFileChooser, jAcceptType, jCapture);
    checkException(env);
    env->DeleteLocalRef(jAcceptType);
    env->DeleteLocalRef(jCapture);

    WTF::String wtfString = jstringToWtfString(env, jName);
    env->DeleteLocalRef(jName);

    if (!wtfString.isEmpty())
        chooser->chooseFile(wtfString);
}

void WebViewCore::listBoxRequest(WebCoreReply* reply, const uint16_t** labels, size_t count, const int enabled[], size_t enabledCount,
        bool multiple, const int selected[], size_t selectedCountOrSelection)
{
    ALOG_ASSERT(m_javaGlue->m_obj, "No java widget associated with this view!");

    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;

    // If m_popupReply is not null, then we already have a list showing.
    if (m_popupReply != 0)
        return;

    // Create an array of java Strings for the drop down.
    jobjectArray labelArray = makeLabelArray(env, labels, count);

    // Create an array determining whether each item is enabled.
    jintArray enabledArray = env->NewIntArray(enabledCount);
    checkException(env);
    jint* ptrArray = env->GetIntArrayElements(enabledArray, 0);
    checkException(env);
    for (size_t i = 0; i < enabledCount; i++) {
        ptrArray[i] = enabled[i];
    }
    env->ReleaseIntArrayElements(enabledArray, ptrArray, 0);
    checkException(env);

    if (multiple) {
        // Pass up an array representing which items are selected.
        jintArray selectedArray = env->NewIntArray(selectedCountOrSelection);
        checkException(env);
        jint* selArray = env->GetIntArrayElements(selectedArray, 0);
        checkException(env);
        for (size_t i = 0; i < selectedCountOrSelection; i++) {
            selArray[i] = selected[i];
        }
        env->ReleaseIntArrayElements(selectedArray, selArray, 0);

        env->CallVoidMethod(javaObject.get(),
                m_javaGlue->m_requestListBox, labelArray, enabledArray,
                selectedArray);
        env->DeleteLocalRef(selectedArray);
    } else {
        // Pass up the single selection.
        env->CallVoidMethod(javaObject.get(),
                m_javaGlue->m_requestSingleListBox, labelArray, enabledArray,
                selectedCountOrSelection);
    }

    env->DeleteLocalRef(labelArray);
    env->DeleteLocalRef(enabledArray);
    checkException(env);

    Retain(reply);
    m_popupReply = reply;
}

bool WebViewCore::key(const PlatformKeyboardEvent& event)
{
    WebCore::EventHandler* eventHandler;
    WebCore::Node* focusNode = currentFocus();
    if (focusNode) {
        WebCore::Frame* frame = focusNode->document()->frame();
        eventHandler = frame->eventHandler();
        VisibleSelection old = frame->selection()->selection();
        EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
                m_mainFrame->editor()->client());
        client->setUiGeneratedSelectionChange(true);
        bool handled = eventHandler->keyEvent(event);
        client->setUiGeneratedSelectionChange(false);
        if (isContentEditable(focusNode)) {
            // keyEvent will return true even if the contentEditable did not
            // change its selection.  In the case that it does not, we want to
            // return false so that the key will be sent back to our navigation
            // system.
            handled |= frame->selection()->selection() != old;
        }
        return handled;
    } else {
        eventHandler = focusedFrame()->eventHandler();
    }
    return eventHandler->keyEvent(event);
}

bool WebViewCore::chromeCanTakeFocus(FocusDirection direction)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return false;
    return env->CallBooleanMethod(javaObject.get(), m_javaGlue->m_chromeCanTakeFocus, direction);
}

void WebViewCore::chromeTakeFocus(FocusDirection direction)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_chromeTakeFocus, direction);
}

void WebViewCore::setInitialFocus(const WebCore::PlatformKeyboardEvent& platformEvent)
{
    Frame* frame = focusedFrame();
    Document* document = frame->document();
    if (document)
        document->setFocusedNode(0);
    FocusDirection direction;
    switch (platformEvent.nativeVirtualKeyCode()) {
    case AKEYCODE_DPAD_LEFT:
        direction = FocusDirectionLeft;
        break;
    case AKEYCODE_DPAD_RIGHT:
        direction = FocusDirectionRight;
        break;
    case AKEYCODE_DPAD_UP:
        direction = FocusDirectionUp;
        break;
    default:
        direction = FocusDirectionDown;
        break;
    }
    RefPtr<KeyboardEvent> webkitEvent = KeyboardEvent::create(platformEvent, 0);
    m_mainFrame->page()->focusController()->setInitialFocus(direction,
            webkitEvent.get());
}

#if USE(ACCELERATED_COMPOSITING)
GraphicsLayerAndroid* WebViewCore::graphicsRootLayer() const
{
    RenderView* contentRenderer = m_mainFrame->contentRenderer();
    if (!contentRenderer)
        return 0;
    return static_cast<GraphicsLayerAndroid*>(
          contentRenderer->compositor()->rootPlatformLayer());
}
#endif

int WebViewCore::handleTouchEvent(int action, Vector<int>& ids, Vector<IntPoint>& points, int actionIndex, int metaState)
{
    int flags = 0;

#if USE(ACCELERATED_COMPOSITING)
    GraphicsLayerAndroid* rootLayer = graphicsRootLayer();
    if (rootLayer)
      rootLayer->pauseDisplay(true);
#endif

#if ENABLE(TOUCH_EVENTS) // Android
    #define MOTION_EVENT_ACTION_POINTER_DOWN 5
    #define MOTION_EVENT_ACTION_POINTER_UP 6

    WebCore::TouchEventType type = WebCore::TouchStart;
    WebCore::PlatformTouchPoint::State defaultTouchState;
    Vector<WebCore::PlatformTouchPoint::State> touchStates(points.size());

    switch (action) {
    case 0: // MotionEvent.ACTION_DOWN
        type = WebCore::TouchStart;
        defaultTouchState = WebCore::PlatformTouchPoint::TouchPressed;
        break;
    case 1: // MotionEvent.ACTION_UP
        type = WebCore::TouchEnd;
        defaultTouchState = WebCore::PlatformTouchPoint::TouchReleased;
        break;
    case 2: // MotionEvent.ACTION_MOVE
        type = WebCore::TouchMove;
        defaultTouchState = WebCore::PlatformTouchPoint::TouchMoved;
        break;
    case 3: // MotionEvent.ACTION_CANCEL
        type = WebCore::TouchCancel;
        defaultTouchState = WebCore::PlatformTouchPoint::TouchCancelled;
        break;
    case 5: // MotionEvent.ACTION_POINTER_DOWN
        type = WebCore::TouchStart;
        defaultTouchState = WebCore::PlatformTouchPoint::TouchStationary;
        break;
    case 6: // MotionEvent.ACTION_POINTER_UP
        type = WebCore::TouchEnd;
        defaultTouchState = WebCore::PlatformTouchPoint::TouchStationary;
        break;
    default:
        // We do not support other kinds of touch event inside WebCore
        // at the moment.
        ALOGW("Java passed a touch event type that we do not support in WebCore: %d", action);
        return 0;
    }

    for (int c = 0; c < static_cast<int>(points.size()); c++) {
        points[c].setX(points[c].x() - m_scrollOffsetX);
        points[c].setY(points[c].y() - m_scrollOffsetY);

        // Setting the touch state for each point.
        // Note: actionIndex will be 0 for all actions that are not ACTION_POINTER_DOWN/UP.
        if (action == MOTION_EVENT_ACTION_POINTER_DOWN && c == actionIndex) {
            touchStates[c] = WebCore::PlatformTouchPoint::TouchPressed;
        } else if (action == MOTION_EVENT_ACTION_POINTER_UP && c == actionIndex) {
            touchStates[c] = WebCore::PlatformTouchPoint::TouchReleased;
        } else {
            touchStates[c] = defaultTouchState;
        };
    }

    WebCore::PlatformTouchEvent te(ids, points, type, touchStates, metaState);
    if (m_mainFrame->eventHandler()->handleTouchEvent(te))
        flags |= TOUCH_FLAG_PREVENT_DEFAULT;
    if (te.hitTouchHandler())
        flags |= TOUCH_FLAG_HIT_HANDLER;
#endif

#if USE(ACCELERATED_COMPOSITING)
    if (rootLayer)
      rootLayer->pauseDisplay(false);
#endif
    return flags;
}

bool WebViewCore::performMouseClick()
{
    WebCore::PlatformMouseEvent mouseDown(m_mouseClickPos, m_mouseClickPos, WebCore::LeftButton,
            WebCore::MouseEventPressed, 1, false, false, false, false,
            WTF::currentTime());
    // ignore the return from as it will return true if the hit point can trigger selection change
    m_mainFrame->eventHandler()->handleMousePressEvent(mouseDown);
    WebCore::PlatformMouseEvent mouseUp(m_mouseClickPos, m_mouseClickPos, WebCore::LeftButton,
            WebCore::MouseEventReleased, 1, false, false, false, false,
            WTF::currentTime());
    bool handled = m_mainFrame->eventHandler()->handleMouseReleaseEvent(mouseUp);

    WebCore::Node* focusNode = currentFocus();
    initializeTextInput(focusNode, false);
    return handled;
}

// Check for the "x-webkit-soft-keyboard" attribute.  If it is there and
// set to hidden, do not show the soft keyboard.  Node passed as a parameter
// must not be null.
static bool shouldSuppressKeyboard(const WebCore::Node* node) {
    ALOG_ASSERT(node, "node passed to shouldSuppressKeyboard cannot be null");
    const NamedNodeMap* attributes = node->attributes();
    if (!attributes) return false;
    size_t length = attributes->length();
    for (size_t i = 0; i < length; i++) {
        const Attribute* a = attributes->attributeItem(i);
        if (a->localName() == "x-webkit-soft-keyboard" && a->value() == "hidden")
            return true;
    }
    return false;
}

WebViewCore::InputType WebViewCore::getInputType(Node* node)
{
    WebCore::RenderObject* renderer = node->renderer();
    if (!renderer)
        return WebViewCore::NONE;
    if (renderer->isTextArea())
        return WebViewCore::TEXT_AREA;

    if (node->hasTagName(WebCore::HTMLNames::inputTag)) {
        HTMLInputElement* htmlInput = static_cast<HTMLInputElement*>(node);
        if (htmlInput->isPasswordField())
            return WebViewCore::PASSWORD;
        if (htmlInput->isSearchField())
            return WebViewCore::SEARCH;
        if (htmlInput->isEmailField())
            return WebViewCore::EMAIL;
        if (htmlInput->isNumberField())
            return WebViewCore::NUMBER;
        if (htmlInput->isTelephoneField())
            return WebViewCore::TELEPHONE;
        if (htmlInput->isTextField())
            return WebViewCore::NORMAL_TEXT_FIELD;
    }

    if (node->isContentEditable())
        return WebViewCore::TEXT_AREA;

    return WebViewCore::NONE;
}

int WebViewCore::getMaxLength(Node* node)
{
    int maxLength = -1;
    if (node->hasTagName(WebCore::HTMLNames::inputTag)) {
        HTMLInputElement* htmlInput = static_cast<HTMLInputElement*>(node);
        maxLength = htmlInput->maxLength();
    }
    return maxLength;
}

String WebViewCore::getFieldName(Node* node)
{
    String name;
    if (node->hasTagName(WebCore::HTMLNames::inputTag)) {
        HTMLInputElement* htmlInput = static_cast<HTMLInputElement*>(node);
        name = htmlInput->name();
    }
    return name;
}

bool WebViewCore::isSpellCheckEnabled(Node* node)
{
    bool isEnabled = true;
    if (node->isElementNode()) {
        WebCore::Element* element = static_cast<WebCore::Element*>(node);
        isEnabled = element->isSpellCheckingEnabled();
    }
    return isEnabled;
}

bool WebViewCore::isAutoCompleteEnabled(Node* node)
{
    bool isEnabled = false;
    if (node->hasTagName(WebCore::HTMLNames::inputTag)) {
        HTMLInputElement* htmlInput = static_cast<HTMLInputElement*>(node);
        isEnabled = htmlInput->autoComplete();
    }
    return isEnabled;
}

WebCore::IntRect WebViewCore::absoluteClientRect(WebCore::Node* node,
        LayerAndroid* layer)
{
    IntRect clientRect;
    if (node) {
        RenderObject* render = node->renderer();
        if (render && render->isBox() && !render->isBody()) {
            IntPoint offset = convertGlobalContentToFrameContent(IntPoint(),
                    node->document()->frame());
            WebViewCore::layerToAbsoluteOffset(layer, offset);

            RenderBox* renderBox = toRenderBox(render);
            clientRect = renderBox->clientBoxRect();
            IntRect contentBox = renderBox->contentBoxRect();
            clientRect.setX(contentBox.x());
            clientRect.setWidth(contentBox.width());
            FloatPoint absPos = renderBox->localToAbsolute(FloatPoint());
            clientRect.move(absPos.x() - offset.x(), absPos.y() - offset.y());
        }
    }
    return clientRect;
}

jobject WebViewCore::createTextFieldInitData(Node* node)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    TextFieldInitDataGlue* classDef = m_textFieldInitDataGlue;
    ScopedLocalRef<jclass> clazz(env,
            env->FindClass("android/webkit/WebViewCore$TextFieldInitData"));
    jobject initData = env->NewObject(clazz.get(), classDef->m_constructor);
    env->SetIntField(initData, classDef->m_fieldPointer,
            reinterpret_cast<int>(node));
    ScopedLocalRef<jstring> inputText(env,
            wtfStringToJstring(env, getInputText(node), true));
    env->SetObjectField(initData, classDef->m_text, inputText.get());
    env->SetIntField(initData, classDef->m_type, getInputType(node));
    env->SetBooleanField(initData, classDef->m_isSpellCheckEnabled,
            isSpellCheckEnabled(node));
    Document* document = node->document();
    PlatformKeyboardEvent tab(AKEYCODE_TAB, 0, 0, false, false, false, false);
    PassRefPtr<KeyboardEvent> tabEvent =
            KeyboardEvent::create(tab, document->defaultView());
    env->SetBooleanField(initData, classDef->m_isTextFieldNext,
            isTextInput(document->nextFocusableNode(node, tabEvent.get())));
    env->SetBooleanField(initData, classDef->m_isTextFieldPrev,
            isTextInput(document->previousFocusableNode(node, tabEvent.get())));
    env->SetBooleanField(initData, classDef->m_isAutoCompleteEnabled,
            isAutoCompleteEnabled(node));
    ScopedLocalRef<jstring> fieldName(env,
            wtfStringToJstring(env, getFieldName(node), false));
    env->SetObjectField(initData, classDef->m_name, fieldName.get());
    ScopedLocalRef<jstring> label(env,
            wtfStringToJstring(env, requestLabel(document->frame(), node), false));
    env->SetObjectField(initData, classDef->m_label, label.get());
    env->SetIntField(initData, classDef->m_maxLength, getMaxLength(node));
    LayerAndroid* layer = 0;
    int layerId = platformLayerIdFromNode(node, &layer);
    IntRect bounds = absoluteClientRect(node, layer);
    ScopedLocalRef<jobject> jbounds(env, intRectToRect(env, bounds));
    env->SetObjectField(initData, classDef->m_contentBounds, jbounds.get());
    env->SetIntField(initData, classDef->m_nodeLayerId, layerId);
    IntRect contentRect;
    RenderTextControl* rtc = toRenderTextControl(node);
    if (rtc) {
        contentRect.setWidth(rtc->scrollWidth());
        contentRect.setHeight(rtc->scrollHeight());
        contentRect.move(-rtc->scrollLeft(), -rtc->scrollTop());
    }
    ScopedLocalRef<jobject> jcontentRect(env, intRectToRect(env, contentRect));
    env->SetObjectField(initData, classDef->m_clientRect, jcontentRect.get());
    return initData;
}

void WebViewCore::initEditField(Node* node)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    m_textGeneration = 0;
    int start = 0;
    int end = 0;
    getSelectionOffsets(node, start, end);
    SelectText* selectText = createSelectText(focusedFrame()->selection()->selection());
    ScopedLocalRef<jobject> initData(env, createTextFieldInitData(node));
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_initEditField,
            start, end, reinterpret_cast<int>(selectText), initData.get());
    checkException(env);
}

void WebViewCore::popupReply(int index)
{
    if (m_popupReply) {
        m_popupReply->replyInt(index);
        ::Release(m_popupReply);
        m_popupReply = 0;
    }
}

void WebViewCore::popupReply(const int* array, int count)
{
    if (m_popupReply) {
        m_popupReply->replyIntArray(array, count);
        ::Release(m_popupReply);
        m_popupReply = 0;
    }
}

// This is a slightly modified Node::nextNodeConsideringAtomicNodes() with the
// extra constraint of limiting the search to inside a containing parent
WebCore::Node* nextNodeWithinParent(WebCore::Node* parent, WebCore::Node* start)
{
    if (!isAtomicNode(start) && start->firstChild())
        return start->firstChild();
    if (start->nextSibling())
        return start->nextSibling();
    const Node *n = start;
    while (n && !n->nextSibling()) {
        n = n->parentNode();
        if (n == parent)
            return 0;
    }
    if (n)
        return n->nextSibling();
    return 0;
}

void WebViewCore::initializeTextInput(WebCore::Node* node, bool fake)
{
    if (node) {
        if (isTextInput(node)) {
            bool showKeyboard = true;
            initEditField(node);
            WebCore::RenderTextControl* rtc = toRenderTextControl(node);
            if (rtc && node->hasTagName(HTMLNames::inputTag)) {
                HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(node);
                bool ime = !shouldSuppressKeyboard(node) && !inputElement->readOnly();
                if (ime) {
#if ENABLE(WEB_AUTOFILL)
                    if (rtc->isTextField()) {
                        Page* page = node->document()->page();
                        EditorClient* editorClient = page->editorClient();
                        EditorClientAndroid* androidEditor =
                                static_cast<EditorClientAndroid*>(editorClient);
                        WebAutofill* autoFill = androidEditor->getAutofill();
                        autoFill->formFieldFocused(inputElement);
                    }
#endif
                } else
                    showKeyboard = false;
            }
            if (!fake)
                requestKeyboard(showKeyboard);
        } else if (!fake && !nodeIsPlugin(node)) {
            // not a text entry field, put away the keyboard.
            clearTextEntry();
        }
    } else if (!fake) {
        // There is no focusNode, so the keyboard is not needed.
        clearTextEntry();
    }
}

void WebViewCore::focusNodeChanged(WebCore::Node* newFocus)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    if (isTextInput(newFocus))
        initializeTextInput(newFocus, true);
    HitTestResult focusHitResult;
    focusHitResult.setInnerNode(newFocus);
    focusHitResult.setInnerNonSharedNode(newFocus);
    if (newFocus && newFocus->isLink() && newFocus->isElementNode()) {
        focusHitResult.setURLElement(static_cast<Element*>(newFocus));
        if (newFocus->hasChildNodes() && !newFocus->hasTagName(HTMLNames::imgTag)) {
            // Check to see if any of the children are images, and if so
            // set them as the innerNode and innerNonSharedNode
            // This will stop when it hits the first image. I'm not sure what
            // should be done in the case of multiple images inside one anchor...
            Node* nextNode = newFocus->firstChild();
            bool found = false;
            while (nextNode) {
                if (nextNode->hasTagName(HTMLNames::imgTag)) {
                    found = true;
                    break;
                }
                nextNode = nextNodeWithinParent(newFocus, nextNode);
            }
            if (found) {
                focusHitResult.setInnerNode(nextNode);
                focusHitResult.setInnerNonSharedNode(nextNode);
            }
        }
    }
    AndroidHitTestResult androidHitTest(this, focusHitResult);
    jobject jHitTestObj = androidHitTest.createJavaObject(env);
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_focusNodeChanged,
            reinterpret_cast<int>(newFocus), jHitTestObj);
    env->DeleteLocalRef(jHitTestObj);
}

void WebViewCore::addMessageToConsole(const WTF::String& message, unsigned int lineNumber, const WTF::String& sourceID, int msgLevel) {
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    jstring jMessageStr = wtfStringToJstring(env, message);
    jstring jSourceIDStr = wtfStringToJstring(env, sourceID);
    env->CallVoidMethod(javaObject.get(),
            m_javaGlue->m_addMessageToConsole, jMessageStr, lineNumber,
            jSourceIDStr, msgLevel);
    env->DeleteLocalRef(jMessageStr);
    env->DeleteLocalRef(jSourceIDStr);
    checkException(env);
}

void WebViewCore::jsAlert(const WTF::String& url, const WTF::String& text)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    jstring jInputStr = wtfStringToJstring(env, text);
    jstring jUrlStr = wtfStringToJstring(env, url);
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_jsAlert, jUrlStr, jInputStr);
    env->DeleteLocalRef(jInputStr);
    env->DeleteLocalRef(jUrlStr);
    checkException(env);
}

bool WebViewCore::exceededDatabaseQuota(const WTF::String& url, const WTF::String& databaseIdentifier, const unsigned long long currentQuota, unsigned long long estimatedSize)
{
#if ENABLE(DATABASE)
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return false;
    jstring jDatabaseIdentifierStr = wtfStringToJstring(env, databaseIdentifier);
    jstring jUrlStr = wtfStringToJstring(env, url);
    env->CallVoidMethod(javaObject.get(),
            m_javaGlue->m_exceededDatabaseQuota, jUrlStr,
            jDatabaseIdentifierStr, currentQuota, estimatedSize);
    env->DeleteLocalRef(jDatabaseIdentifierStr);
    env->DeleteLocalRef(jUrlStr);
    checkException(env);
    return true;
#endif
}

/*
 * TODO Note that this logic still needs to be cleaned up. Normally the
 * information provided in this callback is used to resize the appcache.
 * so we need to provide the current database size. However, webkit provides no
 * way to reach this information. It can be calculated by fetching all the
 * origins and their usage, however this is too expensize (requires one inner
 * join operation for each origin). Rather, we simply return the maximum cache size,
 * which should be equivalent to the current cache size. This is generally safe.
 * However, setting the maximum database size to less than the current database size
 * may cause a problem. In this case, ApplicationCacheStorage ("the owner of database")
 * uses the updated value, while database internally ignores it and uses the current size
 * as quota. This means the value we returned here won't reflect the actual database size.
 */
bool WebViewCore::reachedMaxAppCacheSize(const unsigned long long spaceNeeded)
{
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return false;
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_reachedMaxAppCacheSize, spaceNeeded, WebCore::cacheStorage().maximumSize());
    checkException(env);
    return true;
#endif
}

void WebViewCore::populateVisitedLinks(WebCore::PageGroup* group)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    m_groupForVisitedLinks = group;
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_populateVisitedLinks);
    checkException(env);
}

void WebViewCore::geolocationPermissionsShowPrompt(const WTF::String& origin)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    jstring originString = wtfStringToJstring(env, origin);
    env->CallVoidMethod(javaObject.get(),
                        m_javaGlue->m_geolocationPermissionsShowPrompt,
                        originString);
    env->DeleteLocalRef(originString);
    checkException(env);
}

void WebViewCore::geolocationPermissionsHidePrompt()
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_geolocationPermissionsHidePrompt);
    checkException(env);
}

jobject WebViewCore::getDeviceMotionService()
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return 0;
    jobject object = env->CallObjectMethod(javaObject.get(), m_javaGlue->m_getDeviceMotionService);
    checkException(env);
    return object;
}

jobject WebViewCore::getDeviceOrientationService()
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return 0;
    jobject object = env->CallObjectMethod(javaObject.get(), m_javaGlue->m_getDeviceOrientationService);
    checkException(env);
    return object;
}

bool WebViewCore::jsConfirm(const WTF::String& url, const WTF::String& text)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return false;
    jstring jInputStr = wtfStringToJstring(env, text);
    jstring jUrlStr = wtfStringToJstring(env, url);
    jboolean result = env->CallBooleanMethod(javaObject.get(), m_javaGlue->m_jsConfirm, jUrlStr, jInputStr);
    env->DeleteLocalRef(jInputStr);
    env->DeleteLocalRef(jUrlStr);
    checkException(env);
    return result;
}

bool WebViewCore::jsPrompt(const WTF::String& url, const WTF::String& text, const WTF::String& defaultValue, WTF::String& result)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return false;
    jstring jUrlStr = wtfStringToJstring(env, url);
    jstring jInputStr = wtfStringToJstring(env, text);
    jstring jDefaultStr = wtfStringToJstring(env, defaultValue);
    jstring returnVal = static_cast<jstring>(env->CallObjectMethod(javaObject.get(), m_javaGlue->m_jsPrompt, jUrlStr, jInputStr, jDefaultStr));
    env->DeleteLocalRef(jUrlStr);
    env->DeleteLocalRef(jInputStr);
    env->DeleteLocalRef(jDefaultStr);
    checkException(env);

    // If returnVal is null, it means that the user cancelled the dialog.
    if (!returnVal)
        return false;

    result = jstringToWtfString(env, returnVal);
    env->DeleteLocalRef(returnVal);
    return true;
}

bool WebViewCore::jsUnload(const WTF::String& url, const WTF::String& message)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return false;
    jstring jInputStr = wtfStringToJstring(env, message);
    jstring jUrlStr = wtfStringToJstring(env, url);
    jboolean result = env->CallBooleanMethod(javaObject.get(), m_javaGlue->m_jsUnload, jUrlStr, jInputStr);
    env->DeleteLocalRef(jInputStr);
    env->DeleteLocalRef(jUrlStr);
    checkException(env);
    return result;
}

bool WebViewCore::jsInterrupt()
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return false;
    jboolean result = env->CallBooleanMethod(javaObject.get(), m_javaGlue->m_jsInterrupt);
    checkException(env);
    return result;
}

AutoJObject
WebViewCore::getJavaObject()
{
    return m_javaGlue->object(JSC::Bindings::getJNIEnv());
}

jobject
WebViewCore::getWebViewJavaObject()
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return 0;
    return env->CallObjectMethod(javaObject.get(), m_javaGlue->m_getWebView);
}

RenderTextControl* WebViewCore::toRenderTextControl(Node* node)
{
    RenderTextControl* rtc = 0;
    RenderObject* renderer = node->renderer();
    if (renderer && renderer->isTextControl()) {
        rtc = WebCore::toRenderTextControl(renderer);
    }
    return rtc;
}

void WebViewCore::getSelectionOffsets(Node* node, int& start, int& end)
{
    RenderTextControl* rtc = toRenderTextControl(node);
    if (rtc) {
        start = rtc->selectionStart();
        end = rtc->selectionEnd();
    } else {
        // It must be content editable field.
        Document* document = node->document();
        Frame* frame = document->frame();
        SelectionController* selector = frame->selection();
        Position selectionStart = selector->start();
        Position selectionEnd = selector->end();
        Position startOfNode = firstPositionInNode(node);
        RefPtr<Range> startRange = Range::create(document, startOfNode,
                selectionStart);
        start = TextIterator::rangeLength(startRange.get(), true);
        RefPtr<Range> endRange = Range::create(document, startOfNode,
                selectionEnd);
        end = TextIterator::rangeLength(endRange.get(), true);
    }
}

String WebViewCore::getInputText(Node* node)
{
    String text;
    WebCore::RenderTextControl* renderText = toRenderTextControl(node);
    if (renderText)
        text = renderText->text();
    else {
        // It must be content editable field.
        Position start = firstPositionInNode(node);
        Position end = lastPositionInNode(node);
        VisibleSelection allEditableText(start, end);
        if (allEditableText.isRange())
            text = allEditableText.firstRange()->text();
    }
    return text;
}

void WebViewCore::updateTextSelection()
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    VisibleSelection selection = focusedFrame()->selection()->selection();
    int start = 0;
    int end = 0;
    if (selection.isCaretOrRange())
        getSelectionOffsets(selection.start().anchorNode(), start, end);
    SelectText* selectText = createSelectText(selection);
    env->CallVoidMethod(javaObject.get(),
            m_javaGlue->m_updateTextSelection, reinterpret_cast<int>(currentFocus()),
            start, end, m_textGeneration, reinterpret_cast<int>(selectText));
    checkException(env);
}

void WebViewCore::updateTextSizeAndScroll(WebCore::Node* node)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    RenderTextControl* rtc = toRenderTextControl(node);
    if (!rtc)
        return;
    int width = rtc->scrollWidth();
    int height = rtc->contentHeight();
    int scrollX = rtc->scrollLeft();
    int scrollY = rtc->scrollTop();
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_updateTextSizeAndScroll,
            reinterpret_cast<int>(node), width, height, scrollX, scrollY);
    checkException(env);
}

void WebViewCore::updateTextfield(WebCore::Node* ptr, const WTF::String& text)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    if (m_blockTextfieldUpdates)
        return;
    jstring string = wtfStringToJstring(env, text);
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_updateTextfield,
            (int) ptr, string, m_textGeneration);
    env->DeleteLocalRef(string);
    checkException(env);
}

void WebViewCore::clearTextEntry()
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_clearTextEntry);
}

void WebViewCore::setBackgroundColor(SkColor c)
{
    WebCore::FrameView* view = m_mainFrame->view();
    if (!view)
        return;

    // need (int) cast to find the right constructor
    WebCore::Color bcolor((int)SkColorGetR(c), (int)SkColorGetG(c),
                          (int)SkColorGetB(c), (int)SkColorGetA(c));

    if (view->baseBackgroundColor() == bcolor)
        return;

    view->setBaseBackgroundColor(bcolor);

    // Background color of 0 indicates we want a transparent background
    if (c == 0)
        view->setTransparent(true);

    //invalidate so the new color is shown
    contentInvalidateAll();
}

jclass WebViewCore::getPluginClass(const WTF::String& libName, const char* className)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return 0;

    jstring libString = wtfStringToJstring(env, libName);
    jstring classString = env->NewStringUTF(className);
    jobject pluginClass = env->CallObjectMethod(javaObject.get(),
                                           m_javaGlue->m_getPluginClass,
                                           libString, classString);
    checkException(env);

    // cleanup unneeded local JNI references
    env->DeleteLocalRef(libString);
    env->DeleteLocalRef(classString);

    if (pluginClass != 0) {
        return static_cast<jclass>(pluginClass);
    } else {
        return 0;
    }
}

void WebViewCore::showFullScreenPlugin(jobject childView, int32_t orientation, NPP npp)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;

    env->CallVoidMethod(javaObject.get(),
                        m_javaGlue->m_showFullScreenPlugin,
                        childView, orientation, reinterpret_cast<int>(npp));
    checkException(env);
}

void WebViewCore::hideFullScreenPlugin()
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_hideFullScreenPlugin);
    checkException(env);
}

jobject WebViewCore::createSurface(jobject view)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return 0;
    jobject result = env->CallObjectMethod(javaObject.get(), m_javaGlue->m_createSurface, view);
    checkException(env);
    return result;
}

jobject WebViewCore::addSurface(jobject view, int x, int y, int width, int height)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return 0;
    jobject result = env->CallObjectMethod(javaObject.get(),
                                           m_javaGlue->m_addSurface,
                                           view, x, y, width, height);
    checkException(env);
    return result;
}

void WebViewCore::updateSurface(jobject childView, int x, int y, int width, int height)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    env->CallVoidMethod(javaObject.get(),
                        m_javaGlue->m_updateSurface, childView,
                        x, y, width, height);
    checkException(env);
}

void WebViewCore::destroySurface(jobject childView)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_destroySurface, childView);
    checkException(env);
}

jobject WebViewCore::getContext()
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return 0;

    jobject result = env->CallObjectMethod(javaObject.get(), m_javaGlue->m_getContext);
    checkException(env);
    return result;
}

void WebViewCore::keepScreenOn(bool screenOn) {
    if ((screenOn && m_screenOnCounter == 0) || (!screenOn && m_screenOnCounter == 1)) {
        JNIEnv* env = JSC::Bindings::getJNIEnv();
        AutoJObject javaObject = m_javaGlue->object(env);
        if (!javaObject.get())
            return;
        env->CallVoidMethod(javaObject.get(), m_javaGlue->m_keepScreenOn, screenOn);
        checkException(env);
    }

    // update the counter
    if (screenOn)
        m_screenOnCounter++;
    else if (m_screenOnCounter > 0)
        m_screenOnCounter--;
}

void WebViewCore::showRect(int left, int top, int width, int height,
        int contentWidth, int contentHeight, float xPercentInDoc,
        float xPercentInView, float yPercentInDoc, float yPercentInView)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_showRect,
            left, top, width, height, contentWidth, contentHeight,
            xPercentInDoc, xPercentInView, yPercentInDoc, yPercentInView);
    checkException(env);
}

void WebViewCore::centerFitRect(int x, int y, int width, int height)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_centerFitRect, x, y, width, height);
    checkException(env);
}

void WebViewCore::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode)
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_setScrollbarModes, horizontalMode, verticalMode);
    checkException(env);
}

#if ENABLE(VIDEO)
void WebViewCore::enterFullscreenForVideoLayer()
{
    // Just need to update the video mode, to avoid multiple exit full screen.
    m_fullscreenVideoMode = true;
}

void WebViewCore::exitFullscreenVideo()
{
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    if (m_fullscreenVideoMode) {
        env->CallVoidMethod(javaObject.get(), m_javaGlue->m_exitFullscreenVideo);
        m_fullscreenVideoMode = false;
    }
    checkException(env);
}
#endif

void WebViewCore::setWebTextViewAutoFillable(int queryId, const string16& previewSummary)
{
#if ENABLE(WEB_AUTOFILL)
    JNIEnv* env = JSC::Bindings::getJNIEnv();
    AutoJObject javaObject = m_javaGlue->object(env);
    if (!javaObject.get())
        return;
    jstring preview = env->NewString(previewSummary.data(), previewSummary.length());
    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_setWebTextViewAutoFillable, queryId, preview);
    env->DeleteLocalRef(preview);
#endif
}

bool WebViewCore::drawIsPaused() const
{
    // returning true says scrollview should be offscreen, which pauses
    // gifs. because this is not again queried when we stop scrolling, we don't
    // use the stopping currently.
    return false;
}

void WebViewCore::setWebRequestContextUserAgent()
{
    // We cannot create a WebRequestContext, because we might not know it this is a private tab or not yet
    if (m_webRequestContext)
        m_webRequestContext->setUserAgent(WebFrame::getWebFrame(m_mainFrame)->userAgentForURL(0)); // URL not used
}

void WebViewCore::setWebRequestContextCacheMode(int cacheMode)
{
    m_cacheMode = cacheMode;
    // We cannot create a WebRequestContext, because we might not know it this is a private tab or not yet
    if (!m_webRequestContext)
        return;

    m_webRequestContext->setCacheMode(cacheMode);
}

WebRequestContext* WebViewCore::webRequestContext()
{
    if (!m_webRequestContext) {
        Settings* settings = mainFrame()->settings();
        m_webRequestContext = new WebRequestContext(settings && settings->privateBrowsingEnabled());
        setWebRequestContextUserAgent();
        setWebRequestContextCacheMode(m_cacheMode);
    }
    return m_webRequestContext.get();
}

void WebViewCore::scrollRenderLayer(int layer, const SkRect& rect)
{
#if USE(ACCELERATED_COMPOSITING)
    GraphicsLayerAndroid* root = graphicsRootLayer();
    if (!root)
        return;

    LayerAndroid* layerAndroid = root->platformLayer();
    if (!layerAndroid)
        return;

    LayerAndroid* target = layerAndroid->findById(layer);
    if (!target)
        return;

    RenderLayer* owner = target->owningLayer();
    if (!owner)
        return;

    if (owner->isRootLayer()) {
        FrameView* view = owner->renderer()->frame()->view();
        IntPoint pt(rect.fLeft, rect.fTop);
        view->setScrollPosition(pt);
    } else
        owner->scrollToOffset(rect.fLeft, rect.fTop);
#endif
}

Vector<VisibleSelection> WebViewCore::getTextRanges(
        int startX, int startY, int endX, int endY)
{
    // These are the positions of the selection handles,
    // which reside below the line that they are selecting.
    // Use the vertical position higher, which will include
    // the selected text.
    startY--;
    endY--;
    VisiblePosition startSelect = visiblePositionForContentPoint(startX, startY);
    VisiblePosition endSelect =  visiblePositionForContentPoint(endX, endY);
    Position start = startSelect.deepEquivalent();
    Position end = endSelect.deepEquivalent();
    Vector<VisibleSelection> ranges;
    if (!start.isNull() && !end.isNull()) {
        if (comparePositions(start, end) > 0) {
            swap(start, end); // RTL start/end positions may be swapped
        }
        Position nextRangeStart = start;
        Position previousRangeEnd;
        do {
            VisibleSelection selection(nextRangeStart, end);
            ranges.append(selection);
            previousRangeEnd = selection.end();
            nextRangeStart = nextCandidate(previousRangeEnd);
        } while (comparePositions(previousRangeEnd, end) < 0);
    }
    return ranges;
}

void WebViewCore::deleteText(int startX, int startY, int endX, int endY)
{
    Vector<VisibleSelection> ranges =
            getTextRanges(startX, startY, endX, endY);

    EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
            m_mainFrame->editor()->client());
    client->setUiGeneratedSelectionChange(true);

    SelectionController* selector = m_mainFrame->selection();
    for (size_t i = 0; i < ranges.size(); i++) {
        const VisibleSelection& selection = ranges[i];
        if (selection.isContentEditable()) {
            selector->setSelection(selection, CharacterGranularity);
            Document* document = selection.start().anchorNode()->document();
            WebCore::TypingCommand::deleteSelection(document, 0);
        }
    }
    client->setUiGeneratedSelectionChange(false);
}

void WebViewCore::insertText(const WTF::String &text)
{
    WebCore::Node* focus = currentFocus();
    if (!focus || !isTextInput(focus))
        return;

    Document* document = focus->document();

    EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
            m_mainFrame->editor()->client());
    if (!client)
        return;
    client->setUiGeneratedSelectionChange(true);
    WebCore::TypingCommand::insertText(document, text,
            TypingCommand::PreventSpellChecking);
    client->setUiGeneratedSelectionChange(false);
}

void WebViewCore::resetFindOnPage()
{
    m_searchText.truncate(0);
    m_matchCount = 0;
    m_activeMatchIndex = 0;
    m_activeMatch = 0;
}

int WebViewCore::findTextOnPage(const WTF::String &text)
{
    resetFindOnPage(); // reset even if parameters are bad

    WebCore::Frame* frame = m_mainFrame;
    if (!frame)
        return 0;

    m_searchText = text;
    FindOptions findOptions = WebCore::CaseInsensitive;

    do {
        frame->document()->markers()->removeMarkers(DocumentMarker::TextMatch);
        m_matchCount += frame->editor()->countMatchesForText(text, findOptions,
            0, true);
        frame->editor()->setMarkedTextMatchesAreHighlighted(true);
        frame = frame->tree()->traverseNextWithWrap(false);
    } while (frame);
    m_activeMatchIndex = m_matchCount - 1; // prime first findNext
    return m_matchCount;
}

int WebViewCore::findNextOnPage(bool forward)
{
    if (!m_mainFrame)
        return -1;
    if (!m_matchCount)
        return -1;

    EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
        m_mainFrame->editor()->client());
    client->setUiGeneratedSelectionChange(true);

    // Clear previous active match.
    if (m_activeMatch) {
        m_mainFrame->document()->markers()->setMarkersActive(
            m_activeMatch.get(), false);
    }

    FindOptions findOptions = WebCore::CaseInsensitive
        | WebCore::StartInSelection | WebCore::WrapAround;
    if (!forward)
        findOptions |= WebCore::Backwards;

    // Start from the previous active match.
    if (m_activeMatch) {
        m_mainFrame->selection()->setSelection(m_activeMatch.get());
    }

    bool found = m_mainFrame->editor()->findString(m_searchText, findOptions);
    if (found) {
        VisibleSelection selection(m_mainFrame->selection()->selection());
        if (selection.isNone() || selection.start() == selection.end()) {
            // Temporary workaround for findString() refusing to select text
            // marked "-webkit-user-select: none".
            m_activeMatchIndex = 0;
            m_activeMatch = 0;
        } else {
            // Mark current match "active".
            if (forward) {
                ++m_activeMatchIndex;
                if (m_activeMatchIndex == m_matchCount)
                    m_activeMatchIndex = 0;
            } else {
                if (m_activeMatchIndex == 0)
                    m_activeMatchIndex = m_matchCount;
                --m_activeMatchIndex;
            }
            m_activeMatch = selection.firstRange();
            m_mainFrame->document()->markers()->setMarkersActive(
                m_activeMatch.get(), true);
            m_mainFrame->selection()->revealSelection(
                ScrollAlignment::alignCenterIfNeeded, true);
        }
    }

    // Clear selection so it doesn't display.
    m_mainFrame->selection()->clear();
    client->setUiGeneratedSelectionChange(false);
    return m_activeMatchIndex;
}

String WebViewCore::getText(int startX, int startY, int endX, int endY)
{
    String text;

    Vector<VisibleSelection> ranges =
            getTextRanges(startX, startY, endX, endY);

    for (size_t i = 0; i < ranges.size(); i++) {
        const VisibleSelection& selection = ranges[i];
        if (selection.isRange()) {
            PassRefPtr<Range> range = selection.firstRange();
            String textInRange = range->text();
            if (textInRange.length() > 0) {
                if (text.length() > 0)
                    text.append('\n');
                text.append(textInRange);
            }
        }
    }

    return text;
}

/**
 * Read the persistent locale.
 */
void WebViewCore::getLocale(String& language, String& region)
{
    char propLang[PROPERTY_VALUE_MAX], propRegn[PROPERTY_VALUE_MAX];

    property_get("persist.sys.language", propLang, "");
    property_get("persist.sys.country", propRegn, "");
    if (*propLang == 0 && *propRegn == 0) {
        /* Set to ro properties, default is en_US */
        property_get("ro.product.locale.language", propLang, "en");
        property_get("ro.product.locale.region", propRegn, "US");
    }
    language = String(propLang, 2);
    region = String(propRegn, 2);
}

// generate bcp47 identifier for the supplied language/region
static void toLanguageTag(char* output, size_t outSize, const String& language,
    const String& region) {
    if (output == NULL || outSize <= 0)
        return;
    String locale = language;
    locale.append('_');
    locale.append(region);
    char canonicalChars[ULOC_FULLNAME_CAPACITY];
    UErrorCode uErr = U_ZERO_ERROR;
    uloc_canonicalize(locale.ascii().data(), canonicalChars,
        ULOC_FULLNAME_CAPACITY, &uErr);
    if (U_SUCCESS(uErr)) {
        char likelyChars[ULOC_FULLNAME_CAPACITY];
        uErr = U_ZERO_ERROR;
        uloc_addLikelySubtags(canonicalChars, likelyChars,
            ULOC_FULLNAME_CAPACITY, &uErr);
        if (U_SUCCESS(uErr)) {
            uErr = U_ZERO_ERROR;
            uloc_toLanguageTag(likelyChars, output, outSize, FALSE, &uErr);
            if (U_SUCCESS(uErr)) {
                return;
            } else {
                ALOGD("uloc_toLanguageTag(\"%s\") failed: %s", likelyChars,
                    u_errorName(uErr));
            }
        } else {
            ALOGD("uloc_addLikelySubtags(\"%s\") failed: %s", canonicalChars,
                u_errorName(uErr));
        }
    } else {
        ALOGD("uloc_canonicalize(\"%s\") failed: %s", locale.ascii().data(),
            u_errorName(uErr));
    }
    // unable to build a proper language identifier
    output[0] = '\0';
}

void WebViewCore::updateLocale()
{
    static String prevLang;
    static String prevRegn;
    String language;
    String region;

    getLocale(language, region);

    if ((language != prevLang) || (region != prevRegn)) {
        prevLang = language;
        prevRegn = region;
        GlyphPageTreeNode::resetRoots();
        fontCache()->invalidate();
        char langTag[ULOC_FULLNAME_CAPACITY];
        toLanguageTag(langTag, ULOC_FULLNAME_CAPACITY, language, region);
        FontPlatformData::setDefaultLanguage(langTag);
    }
}

//----------------------------------------------------------------------
// Native JNI methods
//----------------------------------------------------------------------
static void RevealSelection(JNIEnv* env, jobject obj, jint nativeClass)
{
    reinterpret_cast<WebViewCore*>(nativeClass)->revealSelection();
}

static jstring RequestLabel(JNIEnv* env, jobject obj, jint nativeClass,
        int framePointer, int nodePointer)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    return wtfStringToJstring(env, viewImpl->requestLabel(
            (WebCore::Frame*) framePointer, (WebCore::Node*) nodePointer));
}

static void ClearContent(JNIEnv* env, jobject obj, jint nativeClass)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    viewImpl->clearContent();
}

static void SetSize(JNIEnv* env, jobject obj, jint nativeClass, jint width,
        jint height, jint textWrapWidth, jfloat scale, jint screenWidth,
        jint screenHeight, jint anchorX, jint anchorY, jboolean ignoreHeight)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    ALOGV("webviewcore::nativeSetSize(%u %u)\n viewImpl: %p", (unsigned)width, (unsigned)height, viewImpl);
    ALOG_ASSERT(viewImpl, "viewImpl not set in nativeSetSize");
    viewImpl->setSizeScreenWidthAndScale(width, height, textWrapWidth, scale,
            screenWidth, screenHeight, anchorX, anchorY, ignoreHeight);
}

static void SetScrollOffset(JNIEnv* env, jobject obj, jint nativeClass,
        jboolean sendScrollEvent, jint x, jint y)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    ALOG_ASSERT(viewImpl, "need viewImpl");

    viewImpl->setScrollOffset(sendScrollEvent, x, y);
}

static void SetGlobalBounds(JNIEnv* env, jobject obj, jint nativeClass,
        jint x, jint y, jint h, jint v)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    ALOG_ASSERT(viewImpl, "need viewImpl");

    viewImpl->setGlobalBounds(x, y, h, v);
}

static jboolean Key(JNIEnv* env, jobject obj, jint nativeClass, jint keyCode,
        jint unichar, jint repeatCount, jboolean isShift, jboolean isAlt,
        jboolean isSym, jboolean isDown)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    return viewImpl->key(PlatformKeyboardEvent(keyCode,
        unichar, repeatCount, isDown, isShift, isAlt, isSym));
}

static void SetInitialFocus(JNIEnv* env, jobject obj, jint nativeClass,
                            jint keyDirection)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    viewImpl->setInitialFocus(PlatformKeyboardEvent(keyDirection,
            0, 0, false, false, false, false));
}

static void ContentInvalidateAll(JNIEnv* env, jobject obj, jint nativeClass)
{
    reinterpret_cast<WebViewCore*>(nativeClass)->contentInvalidateAll();
}

static void DeleteSelection(JNIEnv* env, jobject obj, jint nativeClass,
        jint start, jint end, jint textGeneration)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    viewImpl->deleteSelection(start, end, textGeneration);
}

static void SetSelection(JNIEnv* env, jobject obj, jint nativeClass,
        jint start, jint end)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    viewImpl->setSelection(start, end);
}

static jstring ModifySelection(JNIEnv* env, jobject obj, jint nativeClass,
        jint direction, jint granularity)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    String selectionString = viewImpl->modifySelection(direction, granularity);
    return wtfStringToJstring(env, selectionString);
}

static void ReplaceTextfieldText(JNIEnv* env, jobject obj, jint nativeClass,
    jint oldStart, jint oldEnd, jstring replace, jint start, jint end,
    jint textGeneration)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    WTF::String webcoreString = jstringToWtfString(env, replace);
    viewImpl->replaceTextfieldText(oldStart,
            oldEnd, webcoreString, start, end, textGeneration);
}

static void PassToJs(JNIEnv* env, jobject obj, jint nativeClass,
    jint generation, jstring currentText, jint keyCode,
    jint keyValue, jboolean down, jboolean cap, jboolean fn, jboolean sym)
{
    WTF::String current = jstringToWtfString(env, currentText);
    reinterpret_cast<WebViewCore*>(nativeClass)->passToJs(generation, current,
        PlatformKeyboardEvent(keyCode, keyValue, 0, down, cap, fn, sym));
}

static void ScrollFocusedTextInput(JNIEnv* env, jobject obj, jint nativeClass,
        jfloat xPercent, jint y)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    viewImpl->scrollFocusedTextInput(xPercent, y);
}

static void SetFocusControllerActive(JNIEnv* env, jobject obj, jint nativeClass,
        jboolean active)
{
    ALOGV("webviewcore::nativeSetFocusControllerActive()\n");
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    ALOG_ASSERT(viewImpl, "viewImpl not set in nativeSetFocusControllerActive");
    viewImpl->setFocusControllerActive(active);
}

static void SaveDocumentState(JNIEnv* env, jobject obj, jint nativeClass)
{
    ALOGV("webviewcore::nativeSaveDocumentState()\n");
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    ALOG_ASSERT(viewImpl, "viewImpl not set in nativeSaveDocumentState");
    viewImpl->saveDocumentState(viewImpl->focusedFrame());
}

void WebViewCore::addVisitedLink(const UChar* string, int length)
{
    if (m_groupForVisitedLinks)
        m_groupForVisitedLinks->addVisitedLink(string, length);
}

static void NotifyAnimationStarted(JNIEnv* env, jobject obj, jint nativeClass)
{
    WebViewCore* viewImpl = (WebViewCore*) nativeClass;
    viewImpl->notifyAnimationStarted();
}

static jint RecordContent(JNIEnv* env, jobject obj, jint nativeClass, jobject pt)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    SkIPoint nativePt;
    BaseLayerAndroid* result = viewImpl->recordContent(&nativePt);
    GraphicsJNI::ipoint_to_jpoint(nativePt, env, pt);
    return reinterpret_cast<jint>(result);
}

static void SendListBoxChoice(JNIEnv* env, jobject obj, jint nativeClass,
        jint choice)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    ALOG_ASSERT(viewImpl, "viewImpl not set in nativeSendListBoxChoice");
    viewImpl->popupReply(choice);
}

// Set aside a predetermined amount of space in which to place the listbox
// choices, to avoid unnecessary allocations.
// The size here is arbitrary.  We want the size to be at least as great as the
// number of items in the average multiple-select listbox.
#define PREPARED_LISTBOX_STORAGE 10

static void SendListBoxChoices(JNIEnv* env, jobject obj, jint nativeClass,
        jbooleanArray jArray, jint size)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    ALOG_ASSERT(viewImpl, "viewImpl not set in nativeSendListBoxChoices");
    jboolean* ptrArray = env->GetBooleanArrayElements(jArray, 0);
    SkAutoSTMalloc<PREPARED_LISTBOX_STORAGE, int> storage(size);
    int* array = storage.get();
    int count = 0;
    for (int i = 0; i < size; i++) {
        if (ptrArray[i]) {
            array[count++] = i;
        }
    }
    env->ReleaseBooleanArrayElements(jArray, ptrArray, JNI_ABORT);
    viewImpl->popupReply(array, count);
}

// TODO: Move this to WebView.cpp since it is only needed there
static jstring FindAddress(JNIEnv* env, jobject obj, jstring addr,
        jboolean caseInsensitive)
{
    if (!addr)
        return 0;
    int length = env->GetStringLength(addr);
    if (!length)
        return 0;
    const jchar* addrChars = env->GetStringChars(addr, 0);
    size_t start, end;
    AddressDetector detector;
    bool success = detector.FindContent(addrChars, addrChars + length, &start, &end);
    jstring ret = 0;
    if (success)
        ret = env->NewString(addrChars + start, end - start);
    env->ReleaseStringChars(addr, addrChars);
    return ret;
}

static jint HandleTouchEvent(JNIEnv* env, jobject obj, jint nativeClass,
        jint action, jintArray idArray, jintArray xArray, jintArray yArray,
        jint count, jint actionIndex, jint metaState)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
    jint* ptrIdArray = env->GetIntArrayElements(idArray, 0);
    jint* ptrXArray = env->GetIntArrayElements(xArray, 0);
    jint* ptrYArray = env->GetIntArrayElements(yArray, 0);
    Vector<int> ids(count);
    Vector<IntPoint> points(count);
    for (int c = 0; c < count; c++) {
        ids[c] = ptrIdArray[c];
        points[c].setX(ptrXArray[c]);
        points[c].setY(ptrYArray[c]);
    }
    env->ReleaseIntArrayElements(idArray, ptrIdArray, JNI_ABORT);
    env->ReleaseIntArrayElements(xArray, ptrXArray, JNI_ABORT);
    env->ReleaseIntArrayElements(yArray, ptrYArray, JNI_ABORT);

    return viewImpl->handleTouchEvent(action, ids, points, actionIndex, metaState);
}

static bool MouseClick(JNIEnv* env, jobject obj, jint nativeClass)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    return viewImpl->performMouseClick();
}

static jstring RetrieveHref(JNIEnv* env, jobject obj, jint nativeClass,
        jint x, jint y)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
    WTF::String result = viewImpl->retrieveHref(x, y);
    if (!result.isEmpty())
        return wtfStringToJstring(env, result);
    return 0;
}

static jstring RetrieveAnchorText(JNIEnv* env, jobject obj, jint nativeClass,
        jint x, jint y)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
    WTF::String result = viewImpl->retrieveAnchorText(x, y);
    if (!result.isEmpty())
        return wtfStringToJstring(env, result);
    return 0;
}

static jstring RetrieveImageSource(JNIEnv* env, jobject obj, jint nativeClass,
        jint x, jint y)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    WTF::String result = viewImpl->retrieveImageSource(x, y);
    return !result.isEmpty() ? wtfStringToJstring(env, result) : 0;
}

static void MoveMouse(JNIEnv* env, jobject obj, jint nativeClass, jint x, jint y)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
    viewImpl->moveMouse(x, y);
}

static jint GetContentMinPrefWidth(JNIEnv* env, jobject obj, jint nativeClass)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);

    WebCore::Frame* frame = viewImpl->mainFrame();
    if (frame) {
        WebCore::Document* document = frame->document();
        if (document) {
            WebCore::RenderObject* renderer = document->renderer();
            if (renderer && renderer->isRenderView()) {
                return renderer->minPreferredLogicalWidth();
            }
        }
    }
    return 0;
}

static void SetViewportSettingsFromNative(JNIEnv* env, jobject obj,
        jint nativeClass)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);

    WebCore::Settings* s = viewImpl->mainFrame()->page()->settings();
    if (!s)
        return;

#ifdef ANDROID_META_SUPPORT
    env->SetIntField(obj, gWebViewCoreFields.m_viewportWidth, s->viewportWidth());
    env->SetIntField(obj, gWebViewCoreFields.m_viewportHeight, s->viewportHeight());
    env->SetIntField(obj, gWebViewCoreFields.m_viewportInitialScale, s->viewportInitialScale());
    env->SetIntField(obj, gWebViewCoreFields.m_viewportMinimumScale, s->viewportMinimumScale());
    env->SetIntField(obj, gWebViewCoreFields.m_viewportMaximumScale, s->viewportMaximumScale());
    env->SetBooleanField(obj, gWebViewCoreFields.m_viewportUserScalable, s->viewportUserScalable());
    env->SetIntField(obj, gWebViewCoreFields.m_viewportDensityDpi, s->viewportTargetDensityDpi());
#endif
}

static void SetBackgroundColor(JNIEnv* env, jobject obj, jint nativeClass,
        jint color)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);

    viewImpl->setBackgroundColor((SkColor) color);
}

static void DumpDomTree(JNIEnv* env, jobject obj, jint nativeClass,
        jboolean useFile)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);

    viewImpl->dumpDomTree(useFile);
}

static void DumpRenderTree(JNIEnv* env, jobject obj, jint nativeClass,
        jboolean useFile)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);

    viewImpl->dumpRenderTree(useFile);
}

static void SetJsFlags(JNIEnv* env, jobject obj, jint nativeClass, jstring flags)
{
    WTF::String flagsString = jstringToWtfString(env, flags);
    WTF::CString utf8String = flagsString.utf8();
    WebCore::ScriptController::setFlags(utf8String.data(), utf8String.length());
}


// Called from the Java side to set a new quota for the origin or new appcache
// max size in response to a notification that the original quota was exceeded or
// that the appcache has reached its maximum size.
static void SetNewStorageLimit(JNIEnv* env, jobject obj, jint nativeClass,
        jlong quota)
{
#if ENABLE(DATABASE) || ENABLE(OFFLINE_WEB_APPLICATIONS)
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    Frame* frame = viewImpl->mainFrame();

    // The main thread is blocked awaiting this response, so now we can wake it
    // up.
    ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(frame->page()->chrome()->client());
    chromeC->wakeUpMainThreadWithNewQuota(quota);
#endif
}

// Called from Java to provide a Geolocation permission state for the specified origin.
static void GeolocationPermissionsProvide(JNIEnv* env, jobject obj,
        jint nativeClass, jstring origin, jboolean allow, jboolean remember)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    viewImpl->geolocationManager()->provideRealClientPermissionState(jstringToWtfString(env, origin), allow, remember);
}

static void RegisterURLSchemeAsLocal(JNIEnv* env, jobject obj, jint nativeClass,
        jstring scheme)
{
    WebCore::SchemeRegistry::registerURLSchemeAsLocal(jstringToWtfString(env, scheme));
}

static void Pause(JNIEnv* env, jobject obj, jint nativeClass)
{
    // This is called for the foreground tab when the browser is put to the
    // background (and also for any tab when it is put to the background of the
    // browser). The browser can only be killed by the system when it is in the
    // background, so saving the Geolocation permission state now ensures that
    // is maintained when the browser is killed.
    GeolocationPermissions::maybeStorePermanentPermissions();

    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    Frame* mainFrame = viewImpl->mainFrame();
    if (mainFrame)
        mainFrame->settings()->setMinDOMTimerInterval(BACKGROUND_TIMER_INTERVAL);

    viewImpl->deviceMotionAndOrientationManager()->maybeSuspendClients();
    viewImpl->geolocationManager()->suspendRealClient();

    ANPEvent event;
    SkANP::InitEvent(&event, kLifecycle_ANPEventType);
    event.data.lifecycle.action = kPause_ANPLifecycleAction;
    viewImpl->sendPluginEvent(event);
}

static void Resume(JNIEnv* env, jobject obj, jint nativeClass)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    Frame* mainFrame = viewImpl->mainFrame();
    if (mainFrame)
        mainFrame->settings()->setMinDOMTimerInterval(FOREGROUND_TIMER_INTERVAL);

    viewImpl->deviceMotionAndOrientationManager()->maybeResumeClients();
    viewImpl->geolocationManager()->resumeRealClient();

    ANPEvent event;
    SkANP::InitEvent(&event, kLifecycle_ANPEventType);
    event.data.lifecycle.action = kResume_ANPLifecycleAction;
    viewImpl->sendPluginEvent(event);
}

static void FreeMemory(JNIEnv* env, jobject obj, jint nativeClass)
{
    ANPEvent event;
    SkANP::InitEvent(&event, kLifecycle_ANPEventType);
    event.data.lifecycle.action = kFreeMemory_ANPLifecycleAction;
    reinterpret_cast<WebViewCore*>(nativeClass)->sendPluginEvent(event);
}

static void ProvideVisitedHistory(JNIEnv* env, jobject obj, jint nativeClass,
        jobject hist)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);

    jobjectArray array = static_cast<jobjectArray>(hist);

    jsize len = env->GetArrayLength(array);
    for (jsize i = 0; i < len; i++) {
        jstring item = static_cast<jstring>(env->GetObjectArrayElement(array, i));
        const UChar* str = static_cast<const UChar*>(env->GetStringChars(item, 0));
        jsize len = env->GetStringLength(item);
        viewImpl->addVisitedLink(str, len);
        env->ReleaseStringChars(item, str);
        env->DeleteLocalRef(item);
    }
}

static void PluginSurfaceReady(JNIEnv* env, jobject obj, jint nativeClass)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    if (viewImpl)
        viewImpl->sendPluginSurfaceReady();
}

// Notification from the UI thread that the plugin's full-screen surface has been discarded
static void FullScreenPluginHidden(JNIEnv* env, jobject obj, jint nativeClass,
        jint npp)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    PluginWidgetAndroid* plugin = viewImpl->getPluginWidget((NPP)npp);
    if (plugin)
        plugin->exitFullScreen(false);
}

static jobject HitTest(JNIEnv* env, jobject obj, jint nativeClass, jint x,
                       jint y, jint slop, jboolean doMoveMouse)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    if (!viewImpl)
        return 0;
    AndroidHitTestResult result = viewImpl->hitTestAtPoint(x, y, slop, doMoveMouse);
    return result.createJavaObject(env);
}

static void AutoFillForm(JNIEnv* env, jobject obj, jint nativeClass,
        jint queryId)
{
#if ENABLE(WEB_AUTOFILL)
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    if (!viewImpl)
        return;

    WebCore::Frame* frame = viewImpl->mainFrame();
    if (frame) {
        EditorClientAndroid* editorC = static_cast<EditorClientAndroid*>(frame->page()->editorClient());
        WebAutofill* autoFill = editorC->getAutofill();
        autoFill->fillFormFields(queryId);
    }
#endif
}

static void CloseIdleConnections(JNIEnv* env, jobject obj, jint nativeClass)
{
    WebCache::get(true)->closeIdleConnections();
    WebCache::get(false)->closeIdleConnections();
}

static void nativeCertTrustChanged(JNIEnv *env, jobject obj)
{
    WebCache::get(true)->certTrustChanged();
    WebCache::get(false)->certTrustChanged();
}

static void ScrollRenderLayer(JNIEnv* env, jobject obj, jint nativeClass,
        jint layer, jobject jRect)
{
    SkRect rect;
    GraphicsJNI::jrect_to_rect(env, jRect, &rect);
    reinterpret_cast<WebViewCore*>(nativeClass)->scrollRenderLayer(layer, rect);
}

static void DeleteText(JNIEnv* env, jobject obj, jint nativeClass,
        jint startX, jint startY, jint endX, jint endY)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    viewImpl->deleteText(startX, startY, endX, endY);
}

static void InsertText(JNIEnv* env, jobject obj, jint nativeClass,
        jstring text)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    WTF::String wtfText = jstringToWtfString(env, text);
    viewImpl->insertText(wtfText);
}

static jobject GetText(JNIEnv* env, jobject obj, jint nativeClass,
        jint startX, jint startY, jint endX, jint endY)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    WTF::String text = viewImpl->getText(startX, startY, endX, endY);
    return text.isEmpty() ? 0 : wtfStringToJstring(env, text);
}

static void SelectText(JNIEnv* env, jobject obj, jint nativeClass,
        jint handleId, jint x, jint y)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    viewImpl->selectText(static_cast<SelectText::HandleId>(handleId), x, y);
}

static void ClearSelection(JNIEnv* env, jobject obj, jint nativeClass)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    viewImpl->focusedFrame()->selection()->clear();
}

static bool SelectWordAt(JNIEnv* env, jobject obj, jint nativeClass, jint x, jint y)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    return viewImpl->selectWordAt(x, y);
}

static void SelectAll(JNIEnv* env, jobject obj, jint nativeClass)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    viewImpl->focusedFrame()->selection()->selectAll();
}

static int FindAll(JNIEnv* env, jobject obj, jint nativeClass,
        jstring text)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    WTF::String wtfText = jstringToWtfString(env, text);
    return viewImpl->findTextOnPage(wtfText);
}

static int FindNext(JNIEnv* env, jobject obj, jint nativeClass,
        jboolean forward)
{
    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
    return viewImpl->findNextOnPage(forward);
}

// ----------------------------------------------------------------------------

/*
 * JNI registration.
 */
static JNINativeMethod gJavaWebViewCoreMethods[] = {
    { "nativeClearContent", "(I)V",
            (void*) ClearContent },
    { "nativeKey", "(IIIIZZZZ)Z",
        (void*) Key },
    { "nativeContentInvalidateAll", "(I)V",
        (void*) ContentInvalidateAll },
    { "nativeSendListBoxChoices", "(I[ZI)V",
        (void*) SendListBoxChoices },
    { "nativeSendListBoxChoice", "(II)V",
        (void*) SendListBoxChoice },
    { "nativeSetSize", "(IIIIFIIIIZ)V",
        (void*) SetSize },
    { "nativeSetScrollOffset", "(IZII)V",
        (void*) SetScrollOffset },
    { "nativeSetGlobalBounds", "(IIIII)V",
        (void*) SetGlobalBounds },
    { "nativeSetSelection", "(III)V",
        (void*) SetSelection } ,
    { "nativeModifySelection", "(III)Ljava/lang/String;",
        (void*) ModifySelection },
    { "nativeDeleteSelection", "(IIII)V",
        (void*) DeleteSelection } ,
    { "nativeReplaceTextfieldText", "(IIILjava/lang/String;III)V",
        (void*) ReplaceTextfieldText } ,
    { "nativeMoveMouse", "(III)V",
        (void*) MoveMouse },
    { "passToJs", "(IILjava/lang/String;IIZZZZ)V",
        (void*) PassToJs },
    { "nativeScrollFocusedTextInput", "(IFI)V",
        (void*) ScrollFocusedTextInput },
    { "nativeSetFocusControllerActive", "(IZ)V",
        (void*) SetFocusControllerActive },
    { "nativeSaveDocumentState", "(I)V",
        (void*) SaveDocumentState },
    { "nativeFindAddress", "(Ljava/lang/String;Z)Ljava/lang/String;",
        (void*) FindAddress },
    { "nativeHandleTouchEvent", "(II[I[I[IIII)I",
        (void*) HandleTouchEvent },
    { "nativeMouseClick", "(I)Z",
        (void*) MouseClick },
    { "nativeRetrieveHref", "(III)Ljava/lang/String;",
        (void*) RetrieveHref },
    { "nativeRetrieveAnchorText", "(III)Ljava/lang/String;",
        (void*) RetrieveAnchorText },
    { "nativeRetrieveImageSource", "(III)Ljava/lang/String;",
        (void*) RetrieveImageSource },
    { "nativeGetContentMinPrefWidth", "(I)I",
        (void*) GetContentMinPrefWidth },
    { "nativeNotifyAnimationStarted", "(I)V",
        (void*) NotifyAnimationStarted },
    { "nativeRecordContent", "(ILandroid/graphics/Point;)I",
        (void*) RecordContent },
    { "setViewportSettingsFromNative", "(I)V",
        (void*) SetViewportSettingsFromNative },
    { "nativeSetBackgroundColor", "(II)V",
        (void*) SetBackgroundColor },
    { "nativeRegisterURLSchemeAsLocal", "(ILjava/lang/String;)V",
        (void*) RegisterURLSchemeAsLocal },
    { "nativeDumpDomTree", "(IZ)V",
        (void*) DumpDomTree },
    { "nativeDumpRenderTree", "(IZ)V",
        (void*) DumpRenderTree },
    { "nativeSetNewStorageLimit", "(IJ)V",
        (void*) SetNewStorageLimit },
    { "nativeGeolocationPermissionsProvide", "(ILjava/lang/String;ZZ)V",
        (void*) GeolocationPermissionsProvide },
    { "nativePause", "(I)V", (void*) Pause },
    { "nativeResume", "(I)V", (void*) Resume },
    { "nativeFreeMemory", "(I)V", (void*) FreeMemory },
    { "nativeSetJsFlags", "(ILjava/lang/String;)V", (void*) SetJsFlags },
    { "nativeRequestLabel", "(III)Ljava/lang/String;",
        (void*) RequestLabel },
    { "nativeRevealSelection", "(I)V", (void*) RevealSelection },
    { "nativeProvideVisitedHistory", "(I[Ljava/lang/String;)V",
        (void*) ProvideVisitedHistory },
    { "nativeFullScreenPluginHidden", "(II)V",
        (void*) FullScreenPluginHidden },
    { "nativePluginSurfaceReady", "(I)V",
        (void*) PluginSurfaceReady },
    { "nativeHitTest", "(IIIIZ)Landroid/webkit/WebViewCore$WebKitHitTest;",
        (void*) HitTest },
    { "nativeAutoFillForm", "(II)V",
        (void*) AutoFillForm },
    { "nativeScrollLayer", "(IILandroid/graphics/Rect;)V",
        (void*) ScrollRenderLayer },
    { "nativeCloseIdleConnections", "(I)V",
        (void*) CloseIdleConnections },
    { "nativeDeleteText", "(IIIII)V",
        (void*) DeleteText },
    { "nativeInsertText", "(ILjava/lang/String;)V",
        (void*) InsertText },
    { "nativeGetText", "(IIIII)Ljava/lang/String;",
        (void*) GetText },
    { "nativeSelectText", "(IIII)V",
        (void*) SelectText },
    { "nativeClearTextSelection", "(I)V",
        (void*) ClearSelection },
    { "nativeSelectWordAt", "(III)Z",
        (void*) SelectWordAt },
    { "nativeSelectAll", "(I)V",
        (void*) SelectAll },
    { "nativeCertTrustChanged","()V",
        (void*) nativeCertTrustChanged },
    { "nativeFindAll", "(ILjava/lang/String;)I",
        (void*) FindAll },
    { "nativeFindNext", "(IZ)I",
        (void*) FindNext },
    { "nativeSetInitialFocus", "(II)V", (void*) SetInitialFocus },
};

int registerWebViewCore(JNIEnv* env)
{
    jclass widget = env->FindClass("android/webkit/WebViewCore");
    ALOG_ASSERT(widget,
            "Unable to find class android/webkit/WebViewCore");
    gWebViewCoreFields.m_nativeClass = env->GetFieldID(widget, "mNativeClass",
            "I");
    ALOG_ASSERT(gWebViewCoreFields.m_nativeClass,
            "Unable to find android/webkit/WebViewCore.mNativeClass");
    gWebViewCoreFields.m_viewportWidth = env->GetFieldID(widget,
            "mViewportWidth", "I");
    ALOG_ASSERT(gWebViewCoreFields.m_viewportWidth,
            "Unable to find android/webkit/WebViewCore.mViewportWidth");
    gWebViewCoreFields.m_viewportHeight = env->GetFieldID(widget,
            "mViewportHeight", "I");
    ALOG_ASSERT(gWebViewCoreFields.m_viewportHeight,
            "Unable to find android/webkit/WebViewCore.mViewportHeight");
    gWebViewCoreFields.m_viewportInitialScale = env->GetFieldID(widget,
            "mViewportInitialScale", "I");
    ALOG_ASSERT(gWebViewCoreFields.m_viewportInitialScale,
            "Unable to find android/webkit/WebViewCore.mViewportInitialScale");
    gWebViewCoreFields.m_viewportMinimumScale = env->GetFieldID(widget,
            "mViewportMinimumScale", "I");
    ALOG_ASSERT(gWebViewCoreFields.m_viewportMinimumScale,
            "Unable to find android/webkit/WebViewCore.mViewportMinimumScale");
    gWebViewCoreFields.m_viewportMaximumScale = env->GetFieldID(widget,
            "mViewportMaximumScale", "I");
    ALOG_ASSERT(gWebViewCoreFields.m_viewportMaximumScale,
            "Unable to find android/webkit/WebViewCore.mViewportMaximumScale");
    gWebViewCoreFields.m_viewportUserScalable = env->GetFieldID(widget,
            "mViewportUserScalable", "Z");
    ALOG_ASSERT(gWebViewCoreFields.m_viewportUserScalable,
            "Unable to find android/webkit/WebViewCore.mViewportUserScalable");
    gWebViewCoreFields.m_viewportDensityDpi = env->GetFieldID(widget,
            "mViewportDensityDpi", "I");
    ALOG_ASSERT(gWebViewCoreFields.m_viewportDensityDpi,
            "Unable to find android/webkit/WebViewCore.mViewportDensityDpi");
    gWebViewCoreFields.m_drawIsPaused = env->GetFieldID(widget,
            "mDrawIsPaused", "Z");
    ALOG_ASSERT(gWebViewCoreFields.m_drawIsPaused,
            "Unable to find android/webkit/WebViewCore.mDrawIsPaused");
    gWebViewCoreFields.m_lowMemoryUsageMb = env->GetFieldID(widget, "mLowMemoryUsageThresholdMb", "I");
    gWebViewCoreFields.m_highMemoryUsageMb = env->GetFieldID(widget, "mHighMemoryUsageThresholdMb", "I");
    gWebViewCoreFields.m_highUsageDeltaMb = env->GetFieldID(widget, "mHighUsageDeltaMb", "I");

    gWebViewCoreStaticMethods.m_isSupportedMediaMimeType =
        env->GetStaticMethodID(widget, "isSupportedMediaMimeType", "(Ljava/lang/String;)Z");
    LOG_FATAL_IF(!gWebViewCoreStaticMethods.m_isSupportedMediaMimeType,
        "Could not find static method isSupportedMediaMimeType from WebViewCore");

    env->DeleteLocalRef(widget);

    return jniRegisterNativeMethods(env, "android/webkit/WebViewCore",
            gJavaWebViewCoreMethods, NELEM(gJavaWebViewCoreMethods));
}

} /* namespace android */
