Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright 2006, The Android Open Source Project
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *  * Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  *  * Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #define LOG_TAG "webcoreglue"
     27 
     28 #include "config.h"
     29 #include "WebViewCore.h"
     30 
     31 #include "AtomicString.h"
     32 #include "CachedNode.h"
     33 #include "CachedRoot.h"
     34 #include "Chrome.h"
     35 #include "ChromeClientAndroid.h"
     36 #include "Color.h"
     37 #include "DatabaseTracker.h"
     38 #include "Document.h"
     39 #include "DOMWindow.h"
     40 #include "Element.h"
     41 #include "Editor.h"
     42 #include "EditorClientAndroid.h"
     43 #include "EventHandler.h"
     44 #include "EventNames.h"
     45 #include "FocusController.h"
     46 #include "Font.h"
     47 #include "Frame.h"
     48 #include "FrameLoader.h"
     49 #include "FrameLoaderClientAndroid.h"
     50 #include "FrameTree.h"
     51 #include "FrameView.h"
     52 #include "Geolocation.h"
     53 #include "GraphicsContext.h"
     54 #include "GraphicsJNI.h"
     55 #include "HTMLAnchorElement.h"
     56 #include "HTMLAreaElement.h"
     57 #include "HTMLElement.h"
     58 #include "HTMLImageElement.h"
     59 #include "HTMLInputElement.h"
     60 #include "HTMLLabelElement.h"
     61 #include "HTMLMapElement.h"
     62 #include "HTMLNames.h"
     63 #include "HTMLOptGroupElement.h"
     64 #include "HTMLOptionElement.h"
     65 #include "HTMLSelectElement.h"
     66 #include "HTMLTextAreaElement.h"
     67 #include "HistoryItem.h"
     68 #include "HitTestResult.h"
     69 #include "InlineTextBox.h"
     70 #include "KeyboardCodes.h"
     71 #include "Navigator.h"
     72 #include "Node.h"
     73 #include "NodeList.h"
     74 #include "Page.h"
     75 #include "PageGroup.h"
     76 #include "PlatformKeyboardEvent.h"
     77 #include "PlatformString.h"
     78 #include "PluginWidgetAndroid.h"
     79 #include "PluginView.h"
     80 #include "Position.h"
     81 #include "ProgressTracker.h"
     82 #include "RenderBox.h"
     83 #include "RenderLayer.h"
     84 #include "RenderPart.h"
     85 #include "RenderText.h"
     86 #include "RenderTextControl.h"
     87 #include "RenderThemeAndroid.h"
     88 #include "RenderView.h"
     89 #include "ResourceRequest.h"
     90 #include "SelectionController.h"
     91 #include "Settings.h"
     92 #include "SkANP.h"
     93 #include "SkTemplates.h"
     94 #include "SkTDArray.h"
     95 #include "SkTypes.h"
     96 #include "SkCanvas.h"
     97 #include "SkPicture.h"
     98 #include "SkUtils.h"
     99 #include "StringImpl.h"
    100 #include "Text.h"
    101 #include "TypingCommand.h"
    102 #include "WebCoreFrameBridge.h"
    103 #include "WebFrameView.h"
    104 #include "android_graphics.h"
    105 
    106 #include <JNIHelp.h>
    107 #include <JNIUtility.h>
    108 #include <ui/KeycodeLabels.h>
    109 #include <wtf/CurrentTime.h>
    110 
    111 #if USE(V8)
    112 #include "CString.h"
    113 #include "ScriptController.h"
    114 #include "V8Counters.h"
    115 #endif
    116 
    117 #if DEBUG_NAV_UI
    118 #include "SkTime.h"
    119 #endif
    120 
    121 #if ENABLE(TOUCH_EVENTS) // Android
    122 #include "PlatformTouchEvent.h"
    123 #endif
    124 
    125 #ifdef ANDROID_DOM_LOGGING
    126 #include "AndroidLog.h"
    127 #include "RenderTreeAsText.h"
    128 #include "CString.h"
    129 
    130 FILE* gDomTreeFile = 0;
    131 FILE* gRenderTreeFile = 0;
    132 #endif
    133 
    134 #ifdef ANDROID_INSTRUMENT
    135 #include "TimeCounter.h"
    136 #endif
    137 
    138 #if USE(ACCELERATED_COMPOSITING)
    139 #include "GraphicsLayerAndroid.h"
    140 #include "RenderLayerCompositor.h"
    141 #endif
    142 
    143 /*  We pass this flag when recording the actual content, so that we don't spend
    144     time actually regionizing complex path clips, when all we really want to do
    145     is record them.
    146  */
    147 #define PICT_RECORD_FLAGS   SkPicture::kUsePathBoundsForClip_RecordingFlag
    148 
    149 ////////////////////////////////////////////////////////////////////////////////////////////////
    150 
    151 namespace android {
    152 
    153 static SkTDArray<WebViewCore*> gInstanceList;
    154 
    155 void WebViewCore::addInstance(WebViewCore* inst) {
    156     *gInstanceList.append() = inst;
    157 }
    158 
    159 void WebViewCore::removeInstance(WebViewCore* inst) {
    160     int index = gInstanceList.find(inst);
    161     LOG_ASSERT(index >= 0, "RemoveInstance inst not found");
    162     if (index >= 0) {
    163         gInstanceList.removeShuffle(index);
    164     }
    165 }
    166 
    167 bool WebViewCore::isInstance(WebViewCore* inst) {
    168     return gInstanceList.find(inst) >= 0;
    169 }
    170 
    171 jobject WebViewCore::getApplicationContext() {
    172 
    173     // check to see if there is a valid webviewcore object
    174     if (gInstanceList.isEmpty())
    175         return 0;
    176 
    177     // get the context from the webview
    178     jobject context = gInstanceList[0]->getContext();
    179 
    180     if (!context)
    181         return 0;
    182 
    183     // get the application context using JNI
    184     JNIEnv* env = JSC::Bindings::getJNIEnv();
    185     jclass contextClass = env->GetObjectClass(context);
    186     jmethodID appContextMethod = env->GetMethodID(contextClass, "getApplicationContext", "()Landroid/content/Context;");
    187     jobject result = env->CallObjectMethod(context, appContextMethod);
    188     checkException(env);
    189     return result;
    190 }
    191 
    192 // ----------------------------------------------------------------------------
    193 
    194 #define GET_NATIVE_VIEW(env, obj) ((WebViewCore*)env->GetIntField(obj, gWebViewCoreFields.m_nativeClass))
    195 
    196 // Field ids for WebViewCore
    197 struct WebViewCoreFields {
    198     jfieldID    m_nativeClass;
    199     jfieldID    m_viewportWidth;
    200     jfieldID    m_viewportHeight;
    201     jfieldID    m_viewportInitialScale;
    202     jfieldID    m_viewportMinimumScale;
    203     jfieldID    m_viewportMaximumScale;
    204     jfieldID    m_viewportUserScalable;
    205     jfieldID    m_viewportDensityDpi;
    206     jfieldID    m_webView;
    207 } gWebViewCoreFields;
    208 
    209 // ----------------------------------------------------------------------------
    210 
    211 struct WebViewCore::JavaGlue {
    212     jweak       m_obj;
    213     jmethodID   m_spawnScrollTo;
    214     jmethodID   m_scrollTo;
    215     jmethodID   m_scrollBy;
    216     jmethodID   m_contentDraw;
    217     jmethodID   m_requestListBox;
    218     jmethodID   m_openFileChooser;
    219     jmethodID   m_requestSingleListBox;
    220     jmethodID   m_jsAlert;
    221     jmethodID   m_jsConfirm;
    222     jmethodID   m_jsPrompt;
    223     jmethodID   m_jsUnload;
    224     jmethodID   m_jsInterrupt;
    225     jmethodID   m_didFirstLayout;
    226     jmethodID   m_updateViewport;
    227     jmethodID   m_sendNotifyProgressFinished;
    228     jmethodID   m_sendViewInvalidate;
    229     jmethodID   m_sendImmediateRepaint;
    230     jmethodID   m_setRootLayer;
    231     jmethodID   m_updateTextfield;
    232     jmethodID   m_updateTextSelection;
    233     jmethodID   m_clearTextEntry;
    234     jmethodID   m_restoreScale;
    235     jmethodID   m_restoreScreenWidthScale;
    236     jmethodID   m_needTouchEvents;
    237     jmethodID   m_requestKeyboard;
    238     jmethodID   m_requestKeyboardWithSelection;
    239     jmethodID   m_exceededDatabaseQuota;
    240     jmethodID   m_reachedMaxAppCacheSize;
    241     jmethodID   m_populateVisitedLinks;
    242     jmethodID   m_geolocationPermissionsShowPrompt;
    243     jmethodID   m_geolocationPermissionsHidePrompt;
    244     jmethodID   m_addMessageToConsole;
    245     jmethodID   m_getPluginClass;
    246     jmethodID   m_showFullScreenPlugin;
    247     jmethodID   m_hideFullScreenPlugin;
    248     jmethodID   m_addSurface;
    249     jmethodID   m_updateSurface;
    250     jmethodID   m_destroySurface;
    251     jmethodID   m_getContext;
    252     jmethodID   m_sendFindAgain;
    253     jmethodID   m_showRect;
    254     jmethodID   m_centerFitRect;
    255     jmethodID   m_setScrollbarModes;
    256     AutoJObject object(JNIEnv* env) {
    257         return getRealObject(env, m_obj);
    258     }
    259 };
    260 
    261 /*
    262  * WebViewCore Implementation
    263  */
    264 
    265 static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[], const char signature[])
    266 {
    267     jmethodID m = env->GetMethodID(clazz, name, signature);
    268     LOG_ASSERT(m, "Could not find method %s", name);
    269     return m;
    270 }
    271 
    272 Mutex WebViewCore::gFrameCacheMutex;
    273 Mutex WebViewCore::gButtonMutex;
    274 Mutex WebViewCore::gCursorBoundsMutex;
    275 Mutex WebViewCore::m_contentMutex;
    276 
    277 WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* mainframe)
    278         : m_pluginInvalTimer(this, &WebViewCore::pluginInvalTimerFired)
    279 {
    280     m_mainFrame = mainframe;
    281 
    282     m_popupReply = 0;
    283     m_moveGeneration = 0;
    284     m_lastGeneration = 0;
    285     m_touchGeneration = 0;
    286     m_blockTextfieldUpdates = false;
    287     // just initial values. These should be set by client
    288     m_maxXScroll = 320/4;
    289     m_maxYScroll = 240/4;
    290     m_textGeneration = 0;
    291     m_screenWidth = 320;
    292     m_scale = 1;
    293     m_screenWidthScale = 1;
    294 #if ENABLE(TOUCH_EVENTS)
    295     m_forwardingTouchEvents = false;
    296 #endif
    297     m_isPaused = false;
    298 
    299     LOG_ASSERT(m_mainFrame, "Uh oh, somehow a frameview was made without an initial frame!");
    300 
    301     jclass clazz = env->GetObjectClass(javaWebViewCore);
    302     m_javaGlue = new JavaGlue;
    303     m_javaGlue->m_obj = env->NewWeakGlobalRef(javaWebViewCore);
    304     m_javaGlue->m_spawnScrollTo = GetJMethod(env, clazz, "contentSpawnScrollTo", "(II)V");
    305     m_javaGlue->m_scrollTo = GetJMethod(env, clazz, "contentScrollTo", "(II)V");
    306     m_javaGlue->m_scrollBy = GetJMethod(env, clazz, "contentScrollBy", "(IIZ)V");
    307     m_javaGlue->m_contentDraw = GetJMethod(env, clazz, "contentDraw", "()V");
    308     m_javaGlue->m_requestListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[I[I)V");
    309     m_javaGlue->m_openFileChooser = GetJMethod(env, clazz, "openFileChooser", "()Ljava/lang/String;");
    310     m_javaGlue->m_requestSingleListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[II)V");
    311     m_javaGlue->m_jsAlert = GetJMethod(env, clazz, "jsAlert", "(Ljava/lang/String;Ljava/lang/String;)V");
    312     m_javaGlue->m_jsConfirm = GetJMethod(env, clazz, "jsConfirm", "(Ljava/lang/String;Ljava/lang/String;)Z");
    313     m_javaGlue->m_jsPrompt = GetJMethod(env, clazz, "jsPrompt", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
    314     m_javaGlue->m_jsUnload = GetJMethod(env, clazz, "jsUnload", "(Ljava/lang/String;Ljava/lang/String;)Z");
    315     m_javaGlue->m_jsInterrupt = GetJMethod(env, clazz, "jsInterrupt", "()Z");
    316     m_javaGlue->m_didFirstLayout = GetJMethod(env, clazz, "didFirstLayout", "(Z)V");
    317     m_javaGlue->m_updateViewport = GetJMethod(env, clazz, "updateViewport", "()V");
    318     m_javaGlue->m_sendNotifyProgressFinished = GetJMethod(env, clazz, "sendNotifyProgressFinished", "()V");
    319     m_javaGlue->m_sendViewInvalidate = GetJMethod(env, clazz, "sendViewInvalidate", "(IIII)V");
    320     m_javaGlue->m_sendImmediateRepaint = GetJMethod(env, clazz, "sendImmediateRepaint", "()V");
    321     m_javaGlue->m_setRootLayer = GetJMethod(env, clazz, "setRootLayer", "(I)V");
    322     m_javaGlue->m_updateTextfield = GetJMethod(env, clazz, "updateTextfield", "(IZLjava/lang/String;I)V");
    323     m_javaGlue->m_updateTextSelection = GetJMethod(env, clazz, "updateTextSelection", "(IIII)V");
    324     m_javaGlue->m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "()V");
    325     m_javaGlue->m_restoreScale = GetJMethod(env, clazz, "restoreScale", "(I)V");
    326     m_javaGlue->m_restoreScreenWidthScale = GetJMethod(env, clazz, "restoreScreenWidthScale", "(I)V");
    327     m_javaGlue->m_needTouchEvents = GetJMethod(env, clazz, "needTouchEvents", "(Z)V");
    328     m_javaGlue->m_requestKeyboard = GetJMethod(env, clazz, "requestKeyboard", "(Z)V");
    329     m_javaGlue->m_requestKeyboardWithSelection = GetJMethod(env, clazz, "requestKeyboardWithSelection", "(IIII)V");
    330     m_javaGlue->m_exceededDatabaseQuota = GetJMethod(env, clazz, "exceededDatabaseQuota", "(Ljava/lang/String;Ljava/lang/String;JJ)V");
    331     m_javaGlue->m_reachedMaxAppCacheSize = GetJMethod(env, clazz, "reachedMaxAppCacheSize", "(J)V");
    332     m_javaGlue->m_populateVisitedLinks = GetJMethod(env, clazz, "populateVisitedLinks", "()V");
    333     m_javaGlue->m_geolocationPermissionsShowPrompt = GetJMethod(env, clazz, "geolocationPermissionsShowPrompt", "(Ljava/lang/String;)V");
    334     m_javaGlue->m_geolocationPermissionsHidePrompt = GetJMethod(env, clazz, "geolocationPermissionsHidePrompt", "()V");
    335     m_javaGlue->m_addMessageToConsole = GetJMethod(env, clazz, "addMessageToConsole", "(Ljava/lang/String;ILjava/lang/String;I)V");
    336     m_javaGlue->m_getPluginClass = GetJMethod(env, clazz, "getPluginClass", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Class;");
    337     m_javaGlue->m_showFullScreenPlugin = GetJMethod(env, clazz, "showFullScreenPlugin", "(Landroid/webkit/ViewManager$ChildView;I)V");
    338     m_javaGlue->m_hideFullScreenPlugin = GetJMethod(env, clazz, "hideFullScreenPlugin", "()V");
    339     m_javaGlue->m_addSurface = GetJMethod(env, clazz, "addSurface", "(Landroid/view/View;IIII)Landroid/webkit/ViewManager$ChildView;");
    340     m_javaGlue->m_updateSurface = GetJMethod(env, clazz, "updateSurface", "(Landroid/webkit/ViewManager$ChildView;IIII)V");
    341     m_javaGlue->m_destroySurface = GetJMethod(env, clazz, "destroySurface", "(Landroid/webkit/ViewManager$ChildView;)V");
    342     m_javaGlue->m_getContext = GetJMethod(env, clazz, "getContext", "()Landroid/content/Context;");
    343     m_javaGlue->m_sendFindAgain = GetJMethod(env, clazz, "sendFindAgain", "()V");
    344     m_javaGlue->m_showRect = GetJMethod(env, clazz, "showRect", "(IIIIIIFFFF)V");
    345     m_javaGlue->m_centerFitRect = GetJMethod(env, clazz, "centerFitRect", "(IIII)V");
    346     m_javaGlue->m_setScrollbarModes = GetJMethod(env, clazz, "setScrollbarModes", "(II)V");
    347 
    348     env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this);
    349 
    350     m_scrollOffsetX = m_scrollOffsetY = 0;
    351 
    352     PageGroup::setShouldTrackVisitedLinks(true);
    353 
    354     reset(true);
    355 
    356     WebViewCore::addInstance(this);
    357 }
    358 
    359 WebViewCore::~WebViewCore()
    360 {
    361     WebViewCore::removeInstance(this);
    362 
    363     // Release the focused view
    364     Release(m_popupReply);
    365 
    366     if (m_javaGlue->m_obj) {
    367         JNIEnv* env = JSC::Bindings::getJNIEnv();
    368         env->DeleteWeakGlobalRef(m_javaGlue->m_obj);
    369         m_javaGlue->m_obj = 0;
    370     }
    371     delete m_javaGlue;
    372     delete m_frameCacheKit;
    373     delete m_navPictureKit;
    374 }
    375 
    376 WebViewCore* WebViewCore::getWebViewCore(const WebCore::FrameView* view)
    377 {
    378     return getWebViewCore(static_cast<const WebCore::ScrollView*>(view));
    379 }
    380 
    381 WebViewCore* WebViewCore::getWebViewCore(const WebCore::ScrollView* view)
    382 {
    383     if (!view)
    384         return 0;
    385 
    386     WebFrameView* webFrameView = static_cast<WebFrameView*>(view->platformWidget());
    387     if (!webFrameView)
    388         return 0;
    389     return webFrameView->webViewCore();
    390 }
    391 
    392 void WebViewCore::reset(bool fromConstructor)
    393 {
    394     DBG_SET_LOG("");
    395     if (fromConstructor) {
    396         m_frameCacheKit = 0;
    397         m_navPictureKit = 0;
    398     } else {
    399         gFrameCacheMutex.lock();
    400         delete m_frameCacheKit;
    401         delete m_navPictureKit;
    402         m_frameCacheKit = 0;
    403         m_navPictureKit = 0;
    404         gFrameCacheMutex.unlock();
    405     }
    406 
    407     m_lastFocused = 0;
    408     m_lastFocusedBounds = WebCore::IntRect(0,0,0,0);
    409     m_focusBoundsChanged = false;
    410     m_lastFocusedSelStart = 0;
    411     m_lastFocusedSelEnd = 0;
    412     clearContent();
    413     m_updatedFrameCache = true;
    414     m_frameCacheOutOfDate = true;
    415     m_skipContentDraw = false;
    416     m_findIsUp = false;
    417     m_domtree_version = 0;
    418     m_check_domtree_version = true;
    419     m_progressDone = false;
    420     m_hasCursorBounds = false;
    421 
    422     m_scrollOffsetX = 0;
    423     m_scrollOffsetY = 0;
    424     m_screenWidth = 0;
    425     m_screenHeight = 0;
    426     m_groupForVisitedLinks = NULL;
    427 }
    428 
    429 static bool layoutIfNeededRecursive(WebCore::Frame* f)
    430 {
    431     if (!f)
    432         return true;
    433 
    434     WebCore::FrameView* v = f->view();
    435     if (!v)
    436         return true;
    437 
    438     if (v->needsLayout())
    439         v->layout(f->tree()->parent());
    440 
    441     WebCore::Frame* child = f->tree()->firstChild();
    442     bool success = true;
    443     while (child) {
    444         success &= layoutIfNeededRecursive(child);
    445         child = child->tree()->nextSibling();
    446     }
    447 
    448     return success && !v->needsLayout();
    449 }
    450 
    451 CacheBuilder& WebViewCore::cacheBuilder()
    452 {
    453     return FrameLoaderClientAndroid::get(m_mainFrame)->getCacheBuilder();
    454 }
    455 
    456 WebCore::Node* WebViewCore::currentFocus()
    457 {
    458     return cacheBuilder().currentFocus();
    459 }
    460 
    461 void WebViewCore::recordPicture(SkPicture* picture)
    462 {
    463     // if there is no document yet, just return
    464     if (!m_mainFrame->document()) {
    465         DBG_NAV_LOG("no document");
    466         return;
    467     }
    468     // Call layout to ensure that the contentWidth and contentHeight are correct
    469     if (!layoutIfNeededRecursive(m_mainFrame)) {
    470         DBG_NAV_LOG("layout failed");
    471         return;
    472     }
    473     // draw into the picture's recording canvas
    474     WebCore::FrameView* view = m_mainFrame->view();
    475     DBG_NAV_LOGD("view=(w=%d,h=%d)", view->contentsWidth(),
    476         view->contentsHeight());
    477     SkAutoPictureRecord arp(picture, view->contentsWidth(),
    478                             view->contentsHeight(), PICT_RECORD_FLAGS);
    479     SkAutoMemoryUsageProbe mup(__FUNCTION__);
    480 
    481     // Copy m_buttons so we can pass it to our graphics context.
    482     gButtonMutex.lock();
    483     WTF::Vector<Container> buttons(m_buttons);
    484     gButtonMutex.unlock();
    485 
    486     WebCore::PlatformGraphicsContext pgc(arp.getRecordingCanvas(), &buttons);
    487     WebCore::GraphicsContext gc(&pgc);
    488     view->platformWidget()->draw(&gc, WebCore::IntRect(0, 0, INT_MAX, INT_MAX));
    489 
    490     gButtonMutex.lock();
    491     updateButtonList(&buttons);
    492     gButtonMutex.unlock();
    493 }
    494 
    495 void WebViewCore::recordPictureSet(PictureSet* content)
    496 {
    497     // if there is no document yet, just return
    498     if (!m_mainFrame->document()) {
    499         DBG_SET_LOG("!m_mainFrame->document()");
    500         return;
    501     }
    502     if (m_addInval.isEmpty()) {
    503         DBG_SET_LOG("m_addInval.isEmpty()");
    504         return;
    505     }
    506     // Call layout to ensure that the contentWidth and contentHeight are correct
    507     // it's fine for layout to gather invalidates, but defeat sending a message
    508     // back to java to call webkitDraw, since we're already in the middle of
    509     // doing that
    510     m_skipContentDraw = true;
    511     bool success = layoutIfNeededRecursive(m_mainFrame);
    512     m_skipContentDraw = false;
    513 
    514     // We may be mid-layout and thus cannot draw.
    515     if (!success)
    516         return;
    517 
    518     {   // collect WebViewCoreRecordTimeCounter after layoutIfNeededRecursive
    519 #ifdef ANDROID_INSTRUMENT
    520     TimeCounterAuto counter(TimeCounter::WebViewCoreRecordTimeCounter);
    521 #endif
    522 
    523     // if the webkit page dimensions changed, discard the pictureset and redraw.
    524     WebCore::FrameView* view = m_mainFrame->view();
    525     int width = view->contentsWidth();
    526     int height = view->contentsHeight();
    527 
    528     // Use the contents width and height as a starting point.
    529     SkIRect contentRect;
    530     contentRect.set(0, 0, width, height);
    531     SkIRect total(contentRect);
    532 
    533     // Traverse all the frames and add their sizes if they are in the visible
    534     // rectangle.
    535     for (WebCore::Frame* frame = m_mainFrame->tree()->traverseNext(); frame;
    536             frame = frame->tree()->traverseNext()) {
    537         // If the frame doesn't have an owner then it is the top frame and the
    538         // view size is the frame size.
    539         WebCore::RenderPart* owner = frame->ownerRenderer();
    540         if (owner && owner->style()->visibility() == VISIBLE) {
    541             int x = owner->x();
    542             int y = owner->y();
    543 
    544             // Traverse the tree up to the parent to find the absolute position
    545             // of this frame.
    546             WebCore::Frame* parent = frame->tree()->parent();
    547             while (parent) {
    548                 WebCore::RenderPart* parentOwner = parent->ownerRenderer();
    549                 if (parentOwner) {
    550                     x += parentOwner->x();
    551                     y += parentOwner->y();
    552                 }
    553                 parent = parent->tree()->parent();
    554             }
    555             // Use the owner dimensions so that padding and border are
    556             // included.
    557             int right = x + owner->width();
    558             int bottom = y + owner->height();
    559             SkIRect frameRect = {x, y, right, bottom};
    560             // Ignore a width or height that is smaller than 1. Some iframes
    561             // have small dimensions in order to be hidden. The iframe
    562             // expansion code does not expand in that case so we should ignore
    563             // them here.
    564             if (frameRect.width() > 1 && frameRect.height() > 1
    565                     && SkIRect::Intersects(total, frameRect))
    566                 total.join(x, y, right, bottom);
    567         }
    568     }
    569 
    570     // If the new total is larger than the content, resize the view to include
    571     // all the content.
    572     if (!contentRect.contains(total)) {
    573         // Resize the view to change the overflow clip.
    574         view->resize(total.fRight, total.fBottom);
    575 
    576         // We have to force a layout in order for the clip to change.
    577         m_mainFrame->contentRenderer()->setNeedsLayoutAndPrefWidthsRecalc();
    578         view->forceLayout();
    579 
    580         // Relayout similar to above
    581         m_skipContentDraw = true;
    582         bool success = layoutIfNeededRecursive(m_mainFrame);
    583         m_skipContentDraw = false;
    584         if (!success)
    585             return;
    586 
    587         // Set the computed content width
    588         width = view->contentsWidth();
    589         height = view->contentsHeight();
    590     }
    591 
    592     content->checkDimensions(width, height, &m_addInval);
    593 
    594     // The inval region may replace existing pictures. The existing pictures
    595     // may have already been split into pieces. If reuseSubdivided() returns
    596     // true, the split pieces are the last entries in the picture already. They
    597     // are marked as invalid, and are rebuilt by rebuildPictureSet().
    598 
    599     // If the new region doesn't match a set of split pieces, add it to the end.
    600     if (!content->reuseSubdivided(m_addInval)) {
    601         const SkIRect& inval = m_addInval.getBounds();
    602         SkPicture* picture = rebuildPicture(inval);
    603         DBG_SET_LOGD("{%d,%d,w=%d,h=%d}", inval.fLeft,
    604             inval.fTop, inval.width(), inval.height());
    605         content->add(m_addInval, picture, 0, false);
    606         picture->safeUnref();
    607     }
    608     // Remove any pictures already in the set that are obscured by the new one,
    609     // and check to see if any already split pieces need to be redrawn.
    610     if (content->build())
    611         rebuildPictureSet(content);
    612     } // WebViewCoreRecordTimeCounter
    613     WebCore::Node* oldFocusNode = currentFocus();
    614     m_frameCacheOutOfDate = true;
    615     WebCore::IntRect oldBounds;
    616     int oldSelStart = 0;
    617     int oldSelEnd = 0;
    618     if (oldFocusNode) {
    619         oldBounds = oldFocusNode->getRect();
    620         RenderObject* renderer = oldFocusNode->renderer();
    621         if (renderer && (renderer->isTextArea() || renderer->isTextField())) {
    622             WebCore::RenderTextControl* rtc =
    623                 static_cast<WebCore::RenderTextControl*>(renderer);
    624             oldSelStart = rtc->selectionStart();
    625             oldSelEnd = rtc->selectionEnd();
    626         }
    627     } else
    628         oldBounds = WebCore::IntRect(0,0,0,0);
    629     unsigned latestVersion = 0;
    630     if (m_check_domtree_version) {
    631         // as domTreeVersion only increment, we can just check the sum to see
    632         // whether we need to update the frame cache
    633         for (Frame* frame = m_mainFrame; frame; frame = frame->tree()->traverseNext()) {
    634             latestVersion += frame->document()->domTreeVersion();
    635         }
    636     }
    637     DBG_NAV_LOGD("m_lastFocused=%p oldFocusNode=%p"
    638         " m_lastFocusedBounds={%d,%d,%d,%d} oldBounds={%d,%d,%d,%d}"
    639         " m_lastFocusedSelection={%d,%d} oldSelection={%d,%d}"
    640         " m_check_domtree_version=%s latestVersion=%d m_domtree_version=%d",
    641         m_lastFocused, oldFocusNode,
    642         m_lastFocusedBounds.x(), m_lastFocusedBounds.y(),
    643         m_lastFocusedBounds.width(), m_lastFocusedBounds.height(),
    644         oldBounds.x(), oldBounds.y(), oldBounds.width(), oldBounds.height(),
    645         m_lastFocusedSelStart, m_lastFocusedSelEnd, oldSelStart, oldSelEnd,
    646         m_check_domtree_version ? "true" : "false",
    647         latestVersion, m_domtree_version);
    648     if (m_lastFocused == oldFocusNode && m_lastFocusedBounds == oldBounds
    649             && m_lastFocusedSelStart == oldSelStart
    650             && m_lastFocusedSelEnd == oldSelEnd
    651             && !m_findIsUp
    652             && (!m_check_domtree_version || latestVersion == m_domtree_version))
    653     {
    654         return;
    655     }
    656     m_focusBoundsChanged |= m_lastFocused == oldFocusNode
    657         && m_lastFocusedBounds != oldBounds;
    658     m_lastFocused = oldFocusNode;
    659     m_lastFocusedBounds = oldBounds;
    660     m_lastFocusedSelStart = oldSelStart;
    661     m_lastFocusedSelEnd = oldSelEnd;
    662     m_domtree_version = latestVersion;
    663     DBG_NAV_LOG("call updateFrameCache");
    664     updateFrameCache();
    665     if (m_findIsUp) {
    666         LOG_ASSERT(m_javaGlue->m_obj,
    667                 "A Java widget was not associated with this view bridge!");
    668         JNIEnv* env = JSC::Bindings::getJNIEnv();
    669         env->CallVoidMethod(m_javaGlue->object(env).get(),
    670                 m_javaGlue->m_sendFindAgain);
    671         checkException(env);
    672     }
    673 }
    674 
    675 void WebViewCore::updateButtonList(WTF::Vector<Container>* buttons)
    676 {
    677     // All the entries in buttons are either updates of previous entries in
    678     // m_buttons or they need to be added to it.
    679     Container* end = buttons->end();
    680     for (Container* updatedContainer = buttons->begin();
    681             updatedContainer != end; updatedContainer++) {
    682         bool updated = false;
    683         // Search for a previous entry that references the same node as our new
    684         // data
    685         Container* lastPossibleMatch = m_buttons.end();
    686         for (Container* possibleMatch = m_buttons.begin();
    687                 possibleMatch != lastPossibleMatch; possibleMatch++) {
    688             if (updatedContainer->matches(possibleMatch->node())) {
    689                 // Update our record, and skip to the next one.
    690                 possibleMatch->setRect(updatedContainer->rect());
    691                 updated = true;
    692                 break;
    693             }
    694         }
    695         if (!updated) {
    696             // This is a brand new button, so append it to m_buttons
    697             m_buttons.append(*updatedContainer);
    698         }
    699     }
    700     size_t i = 0;
    701     // count will decrease each time one is removed, so check count each time.
    702     while (i < m_buttons.size()) {
    703         if (m_buttons[i].canBeRemoved()) {
    704             m_buttons[i] = m_buttons.last();
    705             m_buttons.removeLast();
    706         } else {
    707             i++;
    708         }
    709     }
    710 }
    711 
    712 // note: updateCursorBounds is called directly by the WebView thread
    713 // This needs to be called each time we call CachedRoot::setCursor() with
    714 // non-null CachedNode/CachedFrame, since otherwise the WebViewCore's data
    715 // about the cursor is incorrect.  When we call setCursor(0,0), we need
    716 // to set hasCursorBounds to false.
    717 void WebViewCore::updateCursorBounds(const CachedRoot* root,
    718         const CachedFrame* cachedFrame, const CachedNode* cachedNode)
    719 {
    720     LOG_ASSERT(root, "updateCursorBounds: root cannot be null");
    721     LOG_ASSERT(cachedNode, "updateCursorBounds: cachedNode cannot be null");
    722     LOG_ASSERT(cachedFrame, "updateCursorBounds: cachedFrame cannot be null");
    723     gCursorBoundsMutex.lock();
    724     m_hasCursorBounds = !cachedNode->isHidden();
    725     // If m_hasCursorBounds is false, we never look at the other
    726     // values, so do not bother setting them.
    727     if (m_hasCursorBounds) {
    728         WebCore::IntRect bounds = cachedNode->bounds(cachedFrame);
    729         if (m_cursorBounds != bounds)
    730             DBG_NAV_LOGD("new cursor bounds=(%d,%d,w=%d,h=%d)",
    731                 bounds.x(), bounds.y(), bounds.width(), bounds.height());
    732         m_cursorBounds = bounds;
    733         m_cursorHitBounds = cachedNode->hitBounds(cachedFrame);
    734         m_cursorFrame = cachedFrame->framePointer();
    735         root->getSimulatedMousePosition(&m_cursorLocation);
    736         m_cursorNode = cachedNode->nodePointer();
    737     }
    738     gCursorBoundsMutex.unlock();
    739 }
    740 
    741 void WebViewCore::clearContent()
    742 {
    743     DBG_SET_LOG("");
    744     m_contentMutex.lock();
    745     m_content.clear();
    746     m_contentMutex.unlock();
    747     m_addInval.setEmpty();
    748     m_rebuildInval.setEmpty();
    749 }
    750 
    751 void WebViewCore::copyContentToPicture(SkPicture* picture)
    752 {
    753     DBG_SET_LOG("start");
    754     m_contentMutex.lock();
    755     PictureSet copyContent = PictureSet(m_content);
    756     m_contentMutex.unlock();
    757 
    758     int w = copyContent.width();
    759     int h = copyContent.height();
    760     copyContent.draw(picture->beginRecording(w, h, PICT_RECORD_FLAGS));
    761     picture->endRecording();
    762     DBG_SET_LOG("end");
    763 }
    764 
    765 bool WebViewCore::drawContent(SkCanvas* canvas, SkColor color)
    766 {
    767 #ifdef ANDROID_INSTRUMENT
    768     TimeCounterAuto counter(TimeCounter::WebViewUIDrawTimeCounter);
    769 #endif
    770     DBG_SET_LOG("start");
    771     m_contentMutex.lock();
    772     PictureSet copyContent = PictureSet(m_content);
    773     m_contentMutex.unlock();
    774     int sc = canvas->save(SkCanvas::kClip_SaveFlag);
    775     SkRect clip;
    776     clip.set(0, 0, copyContent.width(), copyContent.height());
    777     canvas->clipRect(clip, SkRegion::kDifference_Op);
    778     canvas->drawColor(color);
    779     canvas->restoreToCount(sc);
    780     bool tookTooLong = copyContent.draw(canvas);
    781     m_contentMutex.lock();
    782     m_content.setDrawTimes(copyContent);
    783     m_contentMutex.unlock();
    784     DBG_SET_LOG("end");
    785     return tookTooLong;
    786 }
    787 
    788 bool WebViewCore::focusBoundsChanged()
    789 {
    790     bool result = m_focusBoundsChanged;
    791     m_focusBoundsChanged = false;
    792     return result;
    793 }
    794 
    795 bool WebViewCore::pictureReady()
    796 {
    797     bool done;
    798     m_contentMutex.lock();
    799     PictureSet copyContent = PictureSet(m_content);
    800     done = m_progressDone;
    801     m_contentMutex.unlock();
    802     DBG_NAV_LOGD("done=%s empty=%s", done ? "true" : "false",
    803         copyContent.isEmpty() ? "true" : "false");
    804     return done || !copyContent.isEmpty();
    805 }
    806 
    807 SkPicture* WebViewCore::rebuildPicture(const SkIRect& inval)
    808 {
    809     WebCore::FrameView* view = m_mainFrame->view();
    810     int width = view->contentsWidth();
    811     int height = view->contentsHeight();
    812     SkPicture* picture = new SkPicture();
    813     SkAutoPictureRecord arp(picture, width, height, PICT_RECORD_FLAGS);
    814     SkAutoMemoryUsageProbe mup(__FUNCTION__);
    815     SkCanvas* recordingCanvas = arp.getRecordingCanvas();
    816 
    817     gButtonMutex.lock();
    818     WTF::Vector<Container> buttons(m_buttons);
    819     gButtonMutex.unlock();
    820 
    821     WebCore::PlatformGraphicsContext pgc(recordingCanvas, &buttons);
    822     WebCore::GraphicsContext gc(&pgc);
    823     recordingCanvas->translate(-inval.fLeft, -inval.fTop);
    824     recordingCanvas->save();
    825     view->platformWidget()->draw(&gc, WebCore::IntRect(inval.fLeft,
    826         inval.fTop, inval.width(), inval.height()));
    827     m_rebuildInval.op(inval, SkRegion::kUnion_Op);
    828     DBG_SET_LOGD("m_rebuildInval={%d,%d,r=%d,b=%d}",
    829         m_rebuildInval.getBounds().fLeft, m_rebuildInval.getBounds().fTop,
    830         m_rebuildInval.getBounds().fRight, m_rebuildInval.getBounds().fBottom);
    831 
    832     gButtonMutex.lock();
    833     updateButtonList(&buttons);
    834     gButtonMutex.unlock();
    835 
    836     return picture;
    837 }
    838 
    839 void WebViewCore::rebuildPictureSet(PictureSet* pictureSet)
    840 {
    841     WebCore::FrameView* view = m_mainFrame->view();
    842     size_t size = pictureSet->size();
    843     for (size_t index = 0; index < size; index++) {
    844         if (pictureSet->upToDate(index))
    845             continue;
    846         const SkIRect& inval = pictureSet->bounds(index);
    847         DBG_SET_LOGD("pictSet=%p [%d] {%d,%d,w=%d,h=%d}", pictureSet, index,
    848             inval.fLeft, inval.fTop, inval.width(), inval.height());
    849         pictureSet->setPicture(index, rebuildPicture(inval));
    850     }
    851     pictureSet->validate(__FUNCTION__);
    852 }
    853 
    854 bool WebViewCore::recordContent(SkRegion* region, SkIPoint* point)
    855 {
    856     DBG_SET_LOG("start");
    857     float progress = (float) m_mainFrame->page()->progress()->estimatedProgress();
    858     m_contentMutex.lock();
    859     PictureSet contentCopy(m_content);
    860     m_progressDone = progress <= 0.0f || progress >= 1.0f;
    861     m_contentMutex.unlock();
    862     recordPictureSet(&contentCopy);
    863     if (!m_progressDone && contentCopy.isEmpty()) {
    864         DBG_SET_LOGD("empty (progress=%g)", progress);
    865         return false;
    866     }
    867     region->set(m_addInval);
    868     m_addInval.setEmpty();
    869     region->op(m_rebuildInval, SkRegion::kUnion_Op);
    870     m_rebuildInval.setEmpty();
    871     m_contentMutex.lock();
    872     contentCopy.setDrawTimes(m_content);
    873     m_content.set(contentCopy);
    874     point->fX = m_content.width();
    875     point->fY = m_content.height();
    876     m_contentMutex.unlock();
    877     DBG_SET_LOGD("region={%d,%d,r=%d,b=%d}", region->getBounds().fLeft,
    878         region->getBounds().fTop, region->getBounds().fRight,
    879         region->getBounds().fBottom);
    880     DBG_SET_LOG("end");
    881     return true;
    882 }
    883 
    884 void WebViewCore::splitContent()
    885 {
    886     bool layoutSuceeded = layoutIfNeededRecursive(m_mainFrame);
    887     LOG_ASSERT(layoutSuceeded, "Can never be called recursively");
    888     PictureSet tempPictureSet;
    889     m_contentMutex.lock();
    890     m_content.split(&tempPictureSet);
    891     m_contentMutex.unlock();
    892     rebuildPictureSet(&tempPictureSet);
    893     m_contentMutex.lock();
    894     m_content.set(tempPictureSet);
    895     m_contentMutex.unlock();
    896 }
    897 
    898 void WebViewCore::scrollTo(int x, int y, bool animate)
    899 {
    900     LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
    901 
    902 //    LOGD("WebViewCore::scrollTo(%d %d)\n", x, y);
    903 
    904     JNIEnv* env = JSC::Bindings::getJNIEnv();
    905     env->CallVoidMethod(m_javaGlue->object(env).get(),
    906             animate ? m_javaGlue->m_spawnScrollTo : m_javaGlue->m_scrollTo,
    907             x, y);
    908     checkException(env);
    909 }
    910 
    911 void WebViewCore::sendNotifyProgressFinished()
    912 {
    913     LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
    914     JNIEnv* env = JSC::Bindings::getJNIEnv();
    915     env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_sendNotifyProgressFinished);
    916     checkException(env);
    917 }
    918 
    919 void WebViewCore::viewInvalidate(const WebCore::IntRect& rect)
    920 {
    921     LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
    922     JNIEnv* env = JSC::Bindings::getJNIEnv();
    923     env->CallVoidMethod(m_javaGlue->object(env).get(),
    924                         m_javaGlue->m_sendViewInvalidate,
    925                         rect.x(), rect.y(), rect.right(), rect.bottom());
    926     checkException(env);
    927 }
    928 
    929 void WebViewCore::scrollBy(int dx, int dy, bool animate)
    930 {
    931     if (!(dx | dy))
    932         return;
    933     JNIEnv* env = JSC::Bindings::getJNIEnv();
    934     env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_scrollBy,
    935         dx, dy, animate);
    936     checkException(env);
    937 }
    938 
    939 #if USE(ACCELERATED_COMPOSITING)
    940 
    941 void WebViewCore::immediateRepaint()
    942 {
    943     LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
    944     JNIEnv* env = JSC::Bindings::getJNIEnv();
    945     env->CallVoidMethod(m_javaGlue->object(env).get(),
    946                         m_javaGlue->m_sendImmediateRepaint);
    947     checkException(env);
    948 }
    949 
    950 void WebViewCore::setUIRootLayer(const LayerAndroid* layer)
    951 {
    952     JNIEnv* env = JSC::Bindings::getJNIEnv();
    953     env->CallVoidMethod(m_javaGlue->object(env).get(),
    954                         m_javaGlue->m_setRootLayer,
    955                         reinterpret_cast<jint>(layer));
    956     checkException(env);
    957 }
    958 
    959 #endif // USE(ACCELERATED_COMPOSITING)
    960 
    961 void WebViewCore::contentDraw()
    962 {
    963     JNIEnv* env = JSC::Bindings::getJNIEnv();
    964     env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_contentDraw);
    965     checkException(env);
    966 }
    967 
    968 void WebViewCore::contentInvalidate(const WebCore::IntRect &r)
    969 {
    970     DBG_SET_LOGD("rect={%d,%d,w=%d,h=%d}", r.x(), r.y(), r.width(), r.height());
    971     SkIRect rect(r);
    972     if (!rect.intersect(0, 0, INT_MAX, INT_MAX))
    973         return;
    974     m_addInval.op(rect, SkRegion::kUnion_Op);
    975     DBG_SET_LOGD("m_addInval={%d,%d,r=%d,b=%d}",
    976         m_addInval.getBounds().fLeft, m_addInval.getBounds().fTop,
    977         m_addInval.getBounds().fRight, m_addInval.getBounds().fBottom);
    978     if (!m_skipContentDraw)
    979         contentDraw();
    980 }
    981 
    982 void WebViewCore::offInvalidate(const WebCore::IntRect &r)
    983 {
    984     // FIXME: these invalidates are offscreen, and can be throttled or
    985     // deferred until the area is visible. For now, treat them as
    986     // regular invals so that drawing happens (inefficiently) for now.
    987     contentInvalidate(r);
    988 }
    989 
    990 static int pin_pos(int x, int width, int targetWidth)
    991 {
    992     if (x + width > targetWidth)
    993         x = targetWidth - width;
    994     if (x < 0)
    995         x = 0;
    996     return x;
    997 }
    998 
    999 void WebViewCore::didFirstLayout()
   1000 {
   1001     DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
   1002     LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
   1003 
   1004     WebCore::FrameLoader* loader = m_mainFrame->loader();
   1005     const WebCore::KURL& url = loader->url();
   1006     if (url.isEmpty())
   1007         return;
   1008     LOGV("::WebCore:: didFirstLayout %s", url.string().ascii().data());
   1009 
   1010     WebCore::FrameLoadType loadType = loader->loadType();
   1011 
   1012     JNIEnv* env = JSC::Bindings::getJNIEnv();
   1013     env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_didFirstLayout,
   1014             loadType == WebCore::FrameLoadTypeStandard
   1015             // When redirect with locked history, we would like to reset the
   1016             // scale factor. This is important for www.yahoo.com as it is
   1017             // redirected to www.yahoo.com/?rs=1 on load.
   1018             || loadType == WebCore::FrameLoadTypeRedirectWithLockedBackForwardList);
   1019     checkException(env);
   1020 
   1021     DBG_NAV_LOG("call updateFrameCache");
   1022     m_check_domtree_version = false;
   1023     updateFrameCache();
   1024     m_history.setDidFirstLayout(true);
   1025 }
   1026 
   1027 void WebViewCore::updateViewport()
   1028 {
   1029     DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
   1030     LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
   1031 
   1032     JNIEnv* env = JSC::Bindings::getJNIEnv();
   1033     env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_updateViewport);
   1034     checkException(env);
   1035 }
   1036 
   1037 void WebViewCore::restoreScale(int scale)
   1038 {
   1039     DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
   1040     LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
   1041 
   1042     JNIEnv* env = JSC::Bindings::getJNIEnv();
   1043     env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_restoreScale, scale);
   1044     checkException(env);
   1045 }
   1046 
   1047 void WebViewCore::restoreScreenWidthScale(int scale)
   1048 {
   1049     DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
   1050     LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
   1051 
   1052     JNIEnv* env = JSC::Bindings::getJNIEnv();
   1053     env->CallVoidMethod(m_javaGlue->object(env).get(),
   1054             m_javaGlue->m_restoreScreenWidthScale, scale);
   1055     checkException(env);
   1056 }
   1057 
   1058 void WebViewCore::needTouchEvents(bool need)
   1059 {
   1060     DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
   1061     LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
   1062 
   1063 #if ENABLE(TOUCH_EVENTS)
   1064     if (m_forwardingTouchEvents == need)
   1065         return;
   1066 
   1067     JNIEnv* env = JSC::Bindings::getJNIEnv();
   1068     env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_needTouchEvents, need);
   1069     checkException(env);
   1070 
   1071     m_forwardingTouchEvents = need;
   1072 #endif
   1073 }
   1074 
   1075 void WebViewCore::requestKeyboardWithSelection(const WebCore::Node* node,
   1076         int selStart, int selEnd)
   1077 {
   1078     DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
   1079     LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
   1080 
   1081     JNIEnv* env = JSC::Bindings::getJNIEnv();
   1082     env->CallVoidMethod(m_javaGlue->object(env).get(),
   1083             m_javaGlue->m_requestKeyboardWithSelection,
   1084             reinterpret_cast<int>(node), selStart, selEnd, m_textGeneration);
   1085     checkException(env);
   1086 }
   1087 
   1088 void WebViewCore::requestKeyboard(bool showKeyboard)
   1089 {
   1090     DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
   1091     LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
   1092 
   1093     JNIEnv* env = JSC::Bindings::getJNIEnv();
   1094     env->CallVoidMethod(m_javaGlue->object(env).get(),
   1095             m_javaGlue->m_requestKeyboard, showKeyboard);
   1096     checkException(env);
   1097 }
   1098 
   1099 void WebViewCore::notifyProgressFinished()
   1100 {
   1101     DBG_NAV_LOG("call updateFrameCache");
   1102     m_check_domtree_version = true;
   1103     updateFrameCache();
   1104     sendNotifyProgressFinished();
   1105 }
   1106 
   1107 void WebViewCore::doMaxScroll(CacheBuilder::Direction dir)
   1108 {
   1109     int dx = 0, dy = 0;
   1110 
   1111     switch (dir) {
   1112     case CacheBuilder::LEFT:
   1113         dx = -m_maxXScroll;
   1114         break;
   1115     case CacheBuilder::UP:
   1116         dy = -m_maxYScroll;
   1117         break;
   1118     case CacheBuilder::RIGHT:
   1119         dx = m_maxXScroll;
   1120         break;
   1121     case CacheBuilder::DOWN:
   1122         dy = m_maxYScroll;
   1123         break;
   1124     case CacheBuilder::UNINITIALIZED:
   1125     default:
   1126         LOG_ASSERT(0, "unexpected focus selector");
   1127     }
   1128     this->scrollBy(dx, dy, true);
   1129 }
   1130 
   1131 void WebViewCore::setScrollOffset(int moveGeneration, int dx, int dy)
   1132 {
   1133     DBG_NAV_LOGD("{%d,%d} m_scrollOffset=(%d,%d)", dx, dy,
   1134         m_scrollOffsetX, m_scrollOffsetY);
   1135     if (m_scrollOffsetX != dx || m_scrollOffsetY != dy) {
   1136         m_scrollOffsetX = dx;
   1137         m_scrollOffsetY = dy;
   1138         // The visible rect is located within our coordinate space so it
   1139         // contains the actual scroll position. Setting the location makes hit
   1140         // testing work correctly.
   1141         m_mainFrame->view()->platformWidget()->setLocation(m_scrollOffsetX,
   1142                 m_scrollOffsetY);
   1143         m_mainFrame->eventHandler()->sendScrollEvent();
   1144 
   1145         // update the currently visible screen
   1146         sendPluginVisibleScreen();
   1147     }
   1148     gCursorBoundsMutex.lock();
   1149     bool hasCursorBounds = m_hasCursorBounds;
   1150     Frame* frame = (Frame*) m_cursorFrame;
   1151     IntPoint location = m_cursorLocation;
   1152     gCursorBoundsMutex.unlock();
   1153     if (!hasCursorBounds)
   1154         return;
   1155     moveMouseIfLatest(moveGeneration, frame, location.x(), location.y());
   1156 }
   1157 
   1158 void WebViewCore::setGlobalBounds(int x, int y, int h, int v)
   1159 {
   1160     DBG_NAV_LOGD("{%d,%d}", x, y);
   1161     m_mainFrame->view()->platformWidget()->setWindowBounds(x, y, h, v);
   1162 }
   1163 
   1164 void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
   1165     int screenWidth, float scale, int realScreenWidth, int screenHeight,
   1166     int anchorX, int anchorY, bool ignoreHeight)
   1167 {
   1168     WebCoreViewBridge* window = m_mainFrame->view()->platformWidget();
   1169     int ow = window->width();
   1170     int oh = window->height();
   1171     window->setSize(width, height);
   1172     int osw = m_screenWidth;
   1173     int orsw = m_screenWidth * m_screenWidthScale / m_scale;
   1174     int osh = m_screenHeight;
   1175     DBG_NAV_LOGD("old:(w=%d,h=%d,sw=%d,scale=%g) new:(w=%d,h=%d,sw=%d,scale=%g)",
   1176         ow, oh, osw, m_scale, width, height, screenWidth, scale);
   1177     m_screenWidth = screenWidth;
   1178     m_screenHeight = screenHeight;
   1179     if (scale >= 0) { // negative means ignore
   1180         m_scale = scale;
   1181         if (screenWidth != realScreenWidth)
   1182             m_screenWidthScale = realScreenWidth * scale / screenWidth;
   1183         else
   1184             m_screenWidthScale = m_scale;
   1185     }
   1186     m_maxXScroll = screenWidth >> 2;
   1187     m_maxYScroll = (screenWidth * height / width) >> 2;
   1188     if (ow != width || (!ignoreHeight && oh != height) || osw != screenWidth) {
   1189         WebCore::RenderObject *r = m_mainFrame->contentRenderer();
   1190         DBG_NAV_LOGD("renderer=%p view=(w=%d,h=%d)", r,
   1191             realScreenWidth, screenHeight);
   1192         if (r) {
   1193             WebCore::IntPoint anchorPoint = WebCore::IntPoint(anchorX, anchorY);
   1194             DBG_NAV_LOGD("anchorX=%d anchorY=%d", anchorX, anchorY);
   1195             WebCore::Node* node = 0;
   1196             WebCore::IntRect bounds;
   1197             WebCore::IntPoint offset;
   1198             // If the screen width changed, it is probably zoom change or
   1199             // orientation change. Try to keep the anchor at the same place.
   1200             if (osw && screenWidth && osw != screenWidth) {
   1201                 WebCore::HitTestResult hitTestResult =
   1202                         m_mainFrame->eventHandler()-> hitTestResultAtPoint(
   1203                                 anchorPoint, false);
   1204                 node = hitTestResult.innerNode();
   1205             }
   1206             if (node) {
   1207                 bounds = node->getRect();
   1208                 DBG_NAV_LOGD("ob:(x=%d,y=%d,w=%d,h=%d)",
   1209                     bounds.x(), bounds.y(), bounds.width(), bounds.height());
   1210                 // sites like nytimes.com insert a non-standard tag <nyt_text>
   1211                 // in the html. If it is the HitTestResult, it may have zero
   1212                 // width and height. In this case, use its parent node.
   1213                 if (bounds.width() == 0) {
   1214                     node = node->parent();
   1215                     if (node) {
   1216                         bounds = node->getRect();
   1217                         DBG_NAV_LOGD("found a zero width node and use its parent, whose ob:(x=%d,y=%d,w=%d,h=%d)",
   1218                                 bounds.x(), bounds.y(), bounds.width(), bounds.height());
   1219                     }
   1220                 }
   1221             }
   1222             r->setNeedsLayoutAndPrefWidthsRecalc();
   1223             m_mainFrame->view()->forceLayout();
   1224             // scroll to restore current screen center
   1225             if (node) {
   1226                 const WebCore::IntRect& newBounds = node->getRect();
   1227                 DBG_NAV_LOGD("nb:(x=%d,y=%d,w=%d,"
   1228                     "h=%d)", newBounds.x(), newBounds.y(),
   1229                     newBounds.width(), newBounds.height());
   1230                 if ((orsw && osh && bounds.width() && bounds.height())
   1231                     && (bounds != newBounds)) {
   1232                     WebCore::FrameView* view = m_mainFrame->view();
   1233                     // force left align if width is not changed while height changed.
   1234                     // the anchorPoint is probably at some white space in the node
   1235                     // which is affected by text wrap around the screen width.
   1236                     const bool leftAlign = (osw != m_screenWidth)
   1237                         && (bounds.width() == newBounds.width())
   1238                         && (bounds.height() != newBounds.height());
   1239                     const float xPercentInDoc =
   1240                         leftAlign ? 0.0 : (float) (anchorX - bounds.x()) / bounds.width();
   1241                     const float xPercentInView =
   1242                         leftAlign ? 0.0 : (float) (anchorX - m_scrollOffsetX) / orsw;
   1243                     const float yPercentInDoc = (float) (anchorY - bounds.y()) / bounds.height();
   1244                     const float yPercentInView = (float) (anchorY - m_scrollOffsetY) / osh;
   1245                     showRect(newBounds.x(), newBounds.y(), newBounds.width(),
   1246                              newBounds.height(), view->contentsWidth(),
   1247                              view->contentsHeight(),
   1248                              xPercentInDoc, xPercentInView,
   1249                              yPercentInDoc, yPercentInView);
   1250                 }
   1251             }
   1252         }
   1253     }
   1254 
   1255     // update the currently visible screen as perceived by the plugin
   1256     sendPluginVisibleScreen();
   1257 }
   1258 
   1259 void WebViewCore::dumpDomTree(bool useFile)
   1260 {
   1261 #ifdef ANDROID_DOM_LOGGING
   1262     if (useFile)
   1263         gDomTreeFile = fopen(DOM_TREE_LOG_FILE, "w");
   1264     m_mainFrame->document()->showTreeForThis();
   1265     if (gDomTreeFile) {
   1266         fclose(gDomTreeFile);
   1267         gDomTreeFile = 0;
   1268     }
   1269 #endif
   1270 }
   1271 
   1272 void WebViewCore::dumpRenderTree(bool useFile)
   1273 {
   1274 #ifdef ANDROID_DOM_LOGGING
   1275     WebCore::CString renderDump = WebCore::externalRepresentation(m_mainFrame).utf8();
   1276     const char* data = renderDump.data();
   1277     if (useFile) {
   1278         gRenderTreeFile = fopen(RENDER_TREE_LOG_FILE, "w");
   1279         DUMP_RENDER_LOGD("%s", data);
   1280         fclose(gRenderTreeFile);
   1281         gRenderTreeFile = 0;
   1282     } else {
   1283         // adb log can only output 1024 characters, so write out line by line.
   1284         // exclude '\n' as adb log adds it for each output.
   1285         int length = renderDump.length();
   1286         for (int i = 0, last = 0; i < length; i++) {
   1287             if (data[i] == '\n') {
   1288                 if (i != last)
   1289                     DUMP_RENDER_LOGD("%.*s", (i - last), &(data[last]));
   1290                 last = i + 1;
   1291             }
   1292         }
   1293     }
   1294 #endif
   1295 }
   1296 
   1297 void WebViewCore::dumpNavTree()
   1298 {
   1299 #if DUMP_NAV_CACHE
   1300     cacheBuilder().mDebug.print();
   1301 #endif
   1302 }
   1303 
   1304 WebCore::HTMLAnchorElement* WebViewCore::retrieveAnchorElement(WebCore::Frame* frame, WebCore::Node* node)
   1305 {
   1306     if (!CacheBuilder::validNode(m_mainFrame, frame, node))
   1307         return 0;
   1308     if (!node->hasTagName(WebCore::HTMLNames::aTag))
   1309         return 0;
   1310     return static_cast<WebCore::HTMLAnchorElement*>(node);
   1311 }
   1312 
   1313 WebCore::String WebViewCore::retrieveHref(WebCore::Frame* frame, WebCore::Node* node)
   1314 {
   1315     WebCore::HTMLAnchorElement* anchor = retrieveAnchorElement(frame, node);
   1316     return anchor ? anchor->href() : WebCore::String();
   1317 }
   1318 
   1319 WebCore::String WebViewCore::retrieveAnchorText(WebCore::Frame* frame, WebCore::Node* node)
   1320 {
   1321     WebCore::HTMLAnchorElement* anchor = retrieveAnchorElement(frame, node);
   1322     return anchor ? anchor->text() : WebCore::String();
   1323 }
   1324 
   1325 WebCore::String WebViewCore::requestLabel(WebCore::Frame* frame,
   1326         WebCore::Node* node)
   1327 {
   1328     if (node && CacheBuilder::validNode(m_mainFrame, frame, node)) {
   1329         RefPtr<WebCore::NodeList> list = node->document()->getElementsByTagName("label");
   1330         unsigned length = list->length();
   1331         for (unsigned i = 0; i < length; i++) {
   1332             WebCore::HTMLLabelElement* label = static_cast<WebCore::HTMLLabelElement*>(
   1333                     list->item(i));
   1334             if (label->correspondingControl() == node) {
   1335                 Node* node = label;
   1336                 String result;
   1337                 while ((node = node->traverseNextNode(label))) {
   1338                     if (node->isTextNode()) {
   1339                         Text* textNode = static_cast<Text*>(node);
   1340                         result += textNode->dataImpl();
   1341                     }
   1342                 }
   1343                 return result;
   1344             }
   1345         }
   1346     }
   1347     return WebCore::String();
   1348 }
   1349 
   1350 void WebViewCore::updateCacheOnNodeChange()
   1351 {
   1352     gCursorBoundsMutex.lock();
   1353     bool hasCursorBounds = m_hasCursorBounds;
   1354     Frame* frame = (Frame*) m_cursorFrame;
   1355     Node* node = (Node*) m_cursorNode;
   1356     IntRect bounds = m_cursorHitBounds;
   1357     gCursorBoundsMutex.unlock();
   1358     if (!hasCursorBounds || !node)
   1359         return;
   1360     if (CacheBuilder::validNode(m_mainFrame, frame, node)) {
   1361         RenderObject* renderer = node->renderer();
   1362         if (renderer && renderer->style()->visibility() != HIDDEN) {
   1363             IntRect absBox = renderer->absoluteBoundingBoxRect();
   1364             int globalX, globalY;
   1365             CacheBuilder::GetGlobalOffset(frame, &globalX, &globalY);
   1366             absBox.move(globalX, globalY);
   1367             if (absBox == bounds)
   1368                 return;
   1369             DBG_NAV_LOGD("absBox=(%d,%d,%d,%d) bounds=(%d,%d,%d,%d)",
   1370                 absBox.x(), absBox.y(), absBox.width(), absBox.height(),
   1371                 bounds.x(), bounds.y(), bounds.width(), bounds.height());
   1372         }
   1373     }
   1374     DBG_NAV_LOGD("updateFrameCache node=%p", node);
   1375     updateFrameCache();
   1376 }
   1377 
   1378 void WebViewCore::updateFrameCache()
   1379 {
   1380     if (!m_frameCacheOutOfDate) {
   1381         DBG_NAV_LOG("!m_frameCacheOutOfDate");
   1382         return;
   1383     }
   1384 #ifdef ANDROID_INSTRUMENT
   1385     TimeCounterAuto counter(TimeCounter::WebViewCoreBuildNavTimeCounter);
   1386 #endif
   1387     m_frameCacheOutOfDate = false;
   1388 #if DEBUG_NAV_UI
   1389     m_now = SkTime::GetMSecs();
   1390 #endif
   1391     m_temp = new CachedRoot();
   1392     m_temp->init(m_mainFrame, &m_history);
   1393 #if USE(ACCELERATED_COMPOSITING)
   1394     GraphicsLayerAndroid* graphicsLayer = graphicsRootLayer();
   1395     if (graphicsLayer)
   1396         m_temp->setRootLayer(graphicsLayer->contentLayer());
   1397 #endif
   1398     CacheBuilder& builder = cacheBuilder();
   1399     WebCore::Settings* settings = m_mainFrame->page()->settings();
   1400     builder.allowAllTextDetection();
   1401 #ifdef ANDROID_META_SUPPORT
   1402     if (settings) {
   1403         if (!settings->formatDetectionAddress())
   1404             builder.disallowAddressDetection();
   1405         if (!settings->formatDetectionEmail())
   1406             builder.disallowEmailDetection();
   1407         if (!settings->formatDetectionTelephone())
   1408             builder.disallowPhoneDetection();
   1409     }
   1410 #endif
   1411     builder.buildCache(m_temp);
   1412     m_tempPict = new SkPicture();
   1413     recordPicture(m_tempPict);
   1414     m_temp->setPicture(m_tempPict);
   1415     m_temp->setTextGeneration(m_textGeneration);
   1416     WebCoreViewBridge* window = m_mainFrame->view()->platformWidget();
   1417     m_temp->setVisibleRect(WebCore::IntRect(m_scrollOffsetX,
   1418         m_scrollOffsetY, window->width(), window->height()));
   1419     gFrameCacheMutex.lock();
   1420     delete m_frameCacheKit;
   1421     delete m_navPictureKit;
   1422     m_frameCacheKit = m_temp;
   1423     m_navPictureKit = m_tempPict;
   1424     m_updatedFrameCache = true;
   1425 #if DEBUG_NAV_UI
   1426     const CachedNode* cachedFocusNode = m_frameCacheKit->currentFocus();
   1427     DBG_NAV_LOGD("cachedFocusNode=%d (nodePointer=%p)",
   1428         cachedFocusNode ? cachedFocusNode->index() : 0,
   1429         cachedFocusNode ? cachedFocusNode->nodePointer() : 0);
   1430 #endif
   1431     gFrameCacheMutex.unlock();
   1432 }
   1433 
   1434 void WebViewCore::updateFrameCacheIfLoading()
   1435 {
   1436     if (!m_check_domtree_version)
   1437         updateFrameCache();
   1438 }
   1439 
   1440 ///////////////////////////////////////////////////////////////////////////////
   1441 
   1442 void WebViewCore::addPlugin(PluginWidgetAndroid* w)
   1443 {
   1444 //    SkDebugf("----------- addPlugin %p", w);
   1445     /* The plugin must be appended to the end of the array. This ensures that if
   1446        the plugin is added while iterating through the array (e.g. sendEvent(...))
   1447        that the iteration process is not corrupted.
   1448      */
   1449     *m_plugins.append() = w;
   1450 }
   1451 
   1452 void WebViewCore::removePlugin(PluginWidgetAndroid* w)
   1453 {
   1454 //    SkDebugf("----------- removePlugin %p", w);
   1455     int index = m_plugins.find(w);
   1456     if (index < 0) {
   1457         SkDebugf("--------------- pluginwindow not found! %p\n", w);
   1458     } else {
   1459         m_plugins.removeShuffle(index);
   1460     }
   1461 }
   1462 
   1463 bool WebViewCore::isPlugin(PluginWidgetAndroid* w) const
   1464 {
   1465     return m_plugins.find(w) >= 0;
   1466 }
   1467 
   1468 void WebViewCore::invalPlugin(PluginWidgetAndroid* w)
   1469 {
   1470     const double PLUGIN_INVAL_DELAY = 1.0 / 60;
   1471 
   1472     if (!m_pluginInvalTimer.isActive()) {
   1473         m_pluginInvalTimer.startOneShot(PLUGIN_INVAL_DELAY);
   1474     }
   1475 }
   1476 
   1477 void WebViewCore::drawPlugins()
   1478 {
   1479     SkRegion inval; // accumualte what needs to be redrawn
   1480     PluginWidgetAndroid** iter = m_plugins.begin();
   1481     PluginWidgetAndroid** stop = m_plugins.end();
   1482 
   1483     for (; iter < stop; ++iter) {
   1484         PluginWidgetAndroid* w = *iter;
   1485         SkIRect dirty;
   1486         if (w->isDirty(&dirty)) {
   1487             w->draw();
   1488             inval.op(dirty, SkRegion::kUnion_Op);
   1489         }
   1490     }
   1491 
   1492     if (!inval.isEmpty()) {
   1493         // inval.getBounds() is our rectangle
   1494         const SkIRect& bounds = inval.getBounds();
   1495         WebCore::IntRect r(bounds.fLeft, bounds.fTop,
   1496                            bounds.width(), bounds.height());
   1497         this->viewInvalidate(r);
   1498     }
   1499 }
   1500 
   1501 void WebViewCore::notifyPluginsOnFrameLoad(const Frame* frame) {
   1502     // if frame is the parent then notify all plugins
   1503     if (!frame->tree()->parent()) {
   1504         // trigger an event notifying the plugins that the page has loaded
   1505         ANPEvent event;
   1506         SkANP::InitEvent(&event, kLifecycle_ANPEventType);
   1507         event.data.lifecycle.action = kOnLoad_ANPLifecycleAction;
   1508         sendPluginEvent(event);
   1509     }
   1510     // else if frame's parent has completed
   1511     else if (!frame->tree()->parent()->loader()->isLoading()) {
   1512         // send to all plugins who have this frame in their heirarchy
   1513         PluginWidgetAndroid** iter = m_plugins.begin();
   1514         PluginWidgetAndroid** stop = m_plugins.end();
   1515         for (; iter < stop; ++iter) {
   1516             Frame* currentFrame = (*iter)->pluginView()->parentFrame();
   1517             while (currentFrame) {
   1518                 if (frame == currentFrame) {
   1519                     ANPEvent event;
   1520                     SkANP::InitEvent(&event, kLifecycle_ANPEventType);
   1521                     event.data.lifecycle.action = kOnLoad_ANPLifecycleAction;
   1522                     (*iter)->sendEvent(event);
   1523                     break;
   1524                 }
   1525                 currentFrame = currentFrame->tree()->parent();
   1526             }
   1527         }
   1528     }
   1529 }
   1530 
   1531 void WebViewCore::sendPluginVisibleScreen()
   1532 {
   1533     /* We may want to cache the previous values and only send the notification
   1534        to the plugin in the event that one of the values has changed.
   1535      */
   1536 
   1537     ANPRectI visibleRect;
   1538     visibleRect.left = m_scrollOffsetX;
   1539     visibleRect.top = m_scrollOffsetY;
   1540     visibleRect.right = m_scrollOffsetX + m_screenWidth;
   1541     visibleRect.bottom = m_scrollOffsetY + m_screenHeight;
   1542 
   1543     PluginWidgetAndroid** iter = m_plugins.begin();
   1544     PluginWidgetAndroid** stop = m_plugins.end();
   1545     for (; iter < stop; ++iter) {
   1546         (*iter)->setVisibleScreen(visibleRect, m_scale);
   1547     }
   1548 }
   1549 
   1550 void WebViewCore::sendPluginEvent(const ANPEvent& evt)
   1551 {
   1552     /* The list of plugins may be manipulated as we iterate through the list.
   1553        This implementation allows for the addition of new plugins during an
   1554        iteration, but may fail if a plugin is removed. Currently, there are not
   1555        any use cases where a plugin is deleted while processing this loop, but
   1556        if it does occur we will have to use an alternate data structure and/or
   1557        iteration mechanism.
   1558      */
   1559     for (int x = 0; x < m_plugins.count(); x++) {
   1560         m_plugins[x]->sendEvent(evt);
   1561     }
   1562 }
   1563 
   1564 PluginWidgetAndroid* WebViewCore::getPluginWidget(NPP npp)
   1565 {
   1566     PluginWidgetAndroid** iter = m_plugins.begin();
   1567     PluginWidgetAndroid** stop = m_plugins.end();
   1568     for (; iter < stop; ++iter) {
   1569         if ((*iter)->pluginView()->instance() == npp) {
   1570             return (*iter);
   1571         }
   1572     }
   1573     return NULL;
   1574 }
   1575 
   1576 static PluginView* nodeIsPlugin(Node* node) {
   1577     RenderObject* renderer = node->renderer();
   1578     if (renderer && renderer->isWidget()) {
   1579         Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
   1580         if (widget && widget->isPluginView())
   1581             return static_cast<PluginView*>(widget);
   1582     }
   1583     return 0;
   1584 }
   1585 
   1586 Node* WebViewCore::cursorNodeIsPlugin() {
   1587     gCursorBoundsMutex.lock();
   1588     bool hasCursorBounds = m_hasCursorBounds;
   1589     Frame* frame = (Frame*) m_cursorFrame;
   1590     Node* node = (Node*) m_cursorNode;
   1591     gCursorBoundsMutex.unlock();
   1592     if (hasCursorBounds && CacheBuilder::validNode(m_mainFrame, frame, node)
   1593             && nodeIsPlugin(node)) {
   1594         return node;
   1595     }
   1596     return 0;
   1597 }
   1598 
   1599 ///////////////////////////////////////////////////////////////////////////////
   1600 void WebViewCore::moveMouseIfLatest(int moveGeneration,
   1601     WebCore::Frame* frame, int x, int y)
   1602 {
   1603     DBG_NAV_LOGD("m_moveGeneration=%d moveGeneration=%d"
   1604         " frame=%p x=%d y=%d",
   1605         m_moveGeneration, moveGeneration, frame, x, y);
   1606     if (m_moveGeneration > moveGeneration) {
   1607         DBG_NAV_LOGD("m_moveGeneration=%d > moveGeneration=%d",
   1608             m_moveGeneration, moveGeneration);
   1609         return; // short-circuit if a newer move has already been generated
   1610     }
   1611     m_lastGeneration = moveGeneration;
   1612     moveMouse(frame, x, y);
   1613 }
   1614 
   1615 void WebViewCore::moveFocus(WebCore::Frame* frame, WebCore::Node* node)
   1616 {
   1617     DBG_NAV_LOGD("frame=%p node=%p", frame, node);
   1618     if (!node || !CacheBuilder::validNode(m_mainFrame, frame, node)
   1619             || !node->isElementNode())
   1620         return;
   1621     // Code borrowed from FocusController::advanceFocus
   1622     WebCore::FocusController* focusController
   1623             = m_mainFrame->page()->focusController();
   1624     WebCore::Document* oldDoc
   1625             = focusController->focusedOrMainFrame()->document();
   1626     if (oldDoc->focusedNode() == node)
   1627         return;
   1628     if (node->document() != oldDoc)
   1629         oldDoc->setFocusedNode(0);
   1630     focusController->setFocusedFrame(frame);
   1631     static_cast<WebCore::Element*>(node)->focus(false);
   1632 }
   1633 
   1634 // Update mouse position
   1635 void WebViewCore::moveMouse(WebCore::Frame* frame, int x, int y)
   1636 {
   1637     DBG_NAV_LOGD("frame=%p x=%d y=%d scrollOffset=(%d,%d)", frame,
   1638         x, y, m_scrollOffsetX, m_scrollOffsetY);
   1639     if (!frame || CacheBuilder::validNode(m_mainFrame, frame, NULL) == false)
   1640         frame = m_mainFrame;
   1641     // mouse event expects the position in the window coordinate
   1642     m_mousePos = WebCore::IntPoint(x - m_scrollOffsetX, y - m_scrollOffsetY);
   1643     // validNode will still return true if the node is null, as long as we have
   1644     // a valid frame.  Do not want to make a call on frame unless it is valid.
   1645     WebCore::PlatformMouseEvent mouseEvent(m_mousePos, m_mousePos,
   1646         WebCore::NoButton, WebCore::MouseEventMoved, 1, false, false, false,
   1647         false, WTF::currentTime());
   1648     frame->eventHandler()->handleMouseMoveEvent(mouseEvent);
   1649     updateCacheOnNodeChange();
   1650 }
   1651 
   1652 void WebViewCore::setSelection(int start, int end)
   1653 {
   1654     WebCore::Node* focus = currentFocus();
   1655     if (!focus)
   1656         return;
   1657     WebCore::RenderObject* renderer = focus->renderer();
   1658     if (!renderer || (!renderer->isTextField() && !renderer->isTextArea()))
   1659         return;
   1660     WebCore::RenderTextControl* rtc = static_cast<WebCore::RenderTextControl*>(renderer);
   1661     if (start > end) {
   1662         int temp = start;
   1663         start = end;
   1664         end = temp;
   1665     }
   1666     // Tell our EditorClient that this change was generated from the UI, so it
   1667     // does not need to echo it to the UI.
   1668     EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
   1669             m_mainFrame->editor()->client());
   1670     client->setUiGeneratedSelectionChange(true);
   1671     rtc->setSelectionRange(start, end);
   1672     client->setUiGeneratedSelectionChange(false);
   1673     WebCore::Frame* focusedFrame = focus->document()->frame();
   1674     focusedFrame->revealSelection();
   1675     setFocusControllerActive(focusedFrame, true);
   1676 }
   1677 
   1678 void WebViewCore::deleteSelection(int start, int end, int textGeneration)
   1679 {
   1680     setSelection(start, end);
   1681     if (start == end)
   1682         return;
   1683     WebCore::Node* focus = currentFocus();
   1684     if (!focus)
   1685         return;
   1686     // Prevent our editor client from passing a message to change the
   1687     // selection.
   1688     EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
   1689             m_mainFrame->editor()->client());
   1690     client->setUiGeneratedSelectionChange(true);
   1691     PlatformKeyboardEvent down(kKeyCodeDel, 0, 0, true, false, false, false);
   1692     PlatformKeyboardEvent up(kKeyCodeDel, 0, 0, false, false, false, false);
   1693     key(down);
   1694     key(up);
   1695     client->setUiGeneratedSelectionChange(false);
   1696     m_textGeneration = textGeneration;
   1697 }
   1698 
   1699 void WebViewCore::replaceTextfieldText(int oldStart,
   1700         int oldEnd, const WebCore::String& replace, int start, int end,
   1701         int textGeneration)
   1702 {
   1703     WebCore::Node* focus = currentFocus();
   1704     if (!focus)
   1705         return;
   1706     setSelection(oldStart, oldEnd);
   1707     // Prevent our editor client from passing a message to change the
   1708     // selection.
   1709     EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
   1710             m_mainFrame->editor()->client());
   1711     client->setUiGeneratedSelectionChange(true);
   1712     WebCore::TypingCommand::insertText(focus->document(), replace,
   1713         false);
   1714     client->setUiGeneratedSelectionChange(false);
   1715     setSelection(start, end);
   1716     m_textGeneration = textGeneration;
   1717 }
   1718 
   1719 void WebViewCore::passToJs(int generation, const WebCore::String& current,
   1720     const PlatformKeyboardEvent& event)
   1721 {
   1722     WebCore::Node* focus = currentFocus();
   1723     if (!focus) {
   1724         DBG_NAV_LOG("!focus");
   1725         clearTextEntry();
   1726         return;
   1727     }
   1728     WebCore::RenderObject* renderer = focus->renderer();
   1729     if (!renderer || (!renderer->isTextField() && !renderer->isTextArea())) {
   1730         DBG_NAV_LOGD("renderer==%p || not text", renderer);
   1731         clearTextEntry();
   1732         return;
   1733     }
   1734     // Block text field updates during a key press.
   1735     m_blockTextfieldUpdates = true;
   1736     // Also prevent our editor client from passing a message to change the
   1737     // selection.
   1738     EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
   1739             m_mainFrame->editor()->client());
   1740     client->setUiGeneratedSelectionChange(true);
   1741     key(event);
   1742     client->setUiGeneratedSelectionChange(false);
   1743     m_blockTextfieldUpdates = false;
   1744     m_textGeneration = generation;
   1745     setFocusControllerActive(focus->document()->frame(), true);
   1746     WebCore::RenderTextControl* renderText =
   1747         static_cast<WebCore::RenderTextControl*>(renderer);
   1748     WebCore::String test = renderText->text();
   1749     if (test == current) {
   1750         DBG_NAV_LOG("test == current");
   1751         return;
   1752     }
   1753     // If the text changed during the key event, update the UI text field.
   1754     updateTextfield(focus, false, test);
   1755 }
   1756 
   1757 void WebViewCore::scrollFocusedTextInput(float xPercent, int y)
   1758 {
   1759     WebCore::Node* focus = currentFocus();
   1760     if (!focus) {
   1761         DBG_NAV_LOG("!focus");
   1762         clearTextEntry();
   1763         return;
   1764     }
   1765     WebCore::RenderObject* renderer = focus->renderer();
   1766     if (!renderer || (!renderer->isTextField() && !renderer->isTextArea())) {
   1767         DBG_NAV_LOGD("renderer==%p || not text", renderer);
   1768         clearTextEntry();
   1769         return;
   1770     }
   1771     WebCore::RenderTextControl* renderText =
   1772         static_cast<WebCore::RenderTextControl*>(renderer);
   1773     int x = (int) (xPercent * (renderText->scrollWidth() -
   1774         renderText->clientWidth()));
   1775     DBG_NAV_LOGD("x=%d y=%d xPercent=%g scrollW=%d clientW=%d", x, y,
   1776         xPercent, renderText->scrollWidth(), renderText->clientWidth());
   1777     renderText->setScrollLeft(x);
   1778     renderText->setScrollTop(y);
   1779 }
   1780 
   1781 void WebViewCore::setFocusControllerActive(WebCore::Frame* frame, bool active)
   1782 {
   1783     if (!frame) {
   1784         WebCore::Node* focus = currentFocus();
   1785         if (focus)
   1786             frame = focus->document()->frame();
   1787         else
   1788             frame = m_mainFrame;
   1789     }
   1790     WebCore::FocusController* controller = frame->page()->focusController();
   1791     controller->setActive(active);
   1792     controller->setFocused(active);
   1793 }
   1794 
   1795 void WebViewCore::saveDocumentState(WebCore::Frame* frame)
   1796 {
   1797     if (!CacheBuilder::validNode(m_mainFrame, frame, 0))
   1798         frame = m_mainFrame;
   1799     WebCore::HistoryItem *item = frame->loader()->history()->currentItem();
   1800 
   1801     // item can be null when there is no offical URL for the current page. This happens
   1802     // when the content is loaded using with WebCoreFrameBridge::LoadData() and there
   1803     // is no failing URL (common case is when content is loaded using data: scheme)
   1804     if (item) {
   1805         item->setDocumentState(frame->document()->formElementsState());
   1806     }
   1807 }
   1808 
   1809 // Convert a WebCore::String into an array of characters where the first
   1810 // character represents the length, for easy conversion to java.
   1811 static uint16_t* stringConverter(const WebCore::String& text)
   1812 {
   1813     size_t length = text.length();
   1814     uint16_t* itemName = new uint16_t[length+1];
   1815     itemName[0] = (uint16_t)length;
   1816     uint16_t* firstChar = &(itemName[1]);
   1817     memcpy((void*)firstChar, text.characters(), sizeof(UChar)*length);
   1818     return itemName;
   1819 }
   1820 
   1821 // Response to dropdown created for a listbox.
   1822 class ListBoxReply : public WebCoreReply {
   1823 public:
   1824     ListBoxReply(WebCore::HTMLSelectElement* select, WebCore::Frame* frame, WebViewCore* view)
   1825         : m_select(select)
   1826         , m_frame(frame)
   1827         , m_viewImpl(view)
   1828     {}
   1829 
   1830     // Response used if the listbox only allows single selection.
   1831     // index is listIndex of the selected item, or -1 if nothing is selected.
   1832     virtual void replyInt(int index)
   1833     {
   1834         if (-2 == index) {
   1835             // Special value for cancel. Do nothing.
   1836             return;
   1837         }
   1838         // If the select element no longer exists, due to a page change, etc,
   1839         // silently return.
   1840         if (!m_select || !CacheBuilder::validNode(m_viewImpl->m_mainFrame,
   1841                 m_frame, m_select))
   1842             return;
   1843         // Use a pointer to HTMLSelectElement's superclass, where
   1844         // listToOptionIndex is public.
   1845         SelectElement* selectElement = m_select;
   1846         int optionIndex = selectElement->listToOptionIndex(index);
   1847         m_select->setSelectedIndex(optionIndex, true);
   1848         m_select->dispatchFormControlChangeEvent();
   1849         m_viewImpl->contentInvalidate(m_select->getRect());
   1850     }
   1851 
   1852     // Response if the listbox allows multiple selection.  array stores the listIndices
   1853     // of selected positions.
   1854     virtual void replyIntArray(const int* array, int count)
   1855     {
   1856         // If the select element no longer exists, due to a page change, etc,
   1857         // silently return.
   1858         if (!m_select || !CacheBuilder::validNode(m_viewImpl->m_mainFrame,
   1859                 m_frame, m_select))
   1860             return;
   1861 
   1862         // If count is 1 or 0, use replyInt.
   1863         SkASSERT(count > 1);
   1864 
   1865         const WTF::Vector<Element*>& items = m_select->listItems();
   1866         int totalItems = static_cast<int>(items.size());
   1867         // Keep track of the position of the value we are comparing against.
   1868         int arrayIndex = 0;
   1869         // The value we are comparing against.
   1870         int selection = array[arrayIndex];
   1871         WebCore::HTMLOptionElement* option;
   1872         for (int listIndex = 0; listIndex < totalItems; listIndex++) {
   1873             if (items[listIndex]->hasLocalName(WebCore::HTMLNames::optionTag)) {
   1874                 option = static_cast<WebCore::HTMLOptionElement*>(
   1875                         items[listIndex]);
   1876                 if (listIndex == selection) {
   1877                     option->setSelectedState(true);
   1878                     arrayIndex++;
   1879                     if (arrayIndex == count)
   1880                         selection = -1;
   1881                     else
   1882                         selection = array[arrayIndex];
   1883                 } else
   1884                     option->setSelectedState(false);
   1885             }
   1886         }
   1887         m_select->dispatchFormControlChangeEvent();
   1888         m_viewImpl->contentInvalidate(m_select->getRect());
   1889     }
   1890 private:
   1891     // The select element associated with this listbox.
   1892     WebCore::HTMLSelectElement* m_select;
   1893     // The frame of this select element, to verify that it is valid.
   1894     WebCore::Frame* m_frame;
   1895     // For calling invalidate and checking the select element's validity
   1896     WebViewCore* m_viewImpl;
   1897 };
   1898 
   1899 // Create an array of java Strings.
   1900 static jobjectArray makeLabelArray(JNIEnv* env, const uint16_t** labels, size_t count)
   1901 {
   1902     jclass stringClass = env->FindClass("java/lang/String");
   1903     LOG_ASSERT(stringClass, "Could not find java/lang/String");
   1904     jobjectArray array = env->NewObjectArray(count, stringClass, 0);
   1905     LOG_ASSERT(array, "Could not create new string array");
   1906 
   1907     for (size_t i = 0; i < count; i++) {
   1908         jobject newString = env->NewString(&labels[i][1], labels[i][0]);
   1909         env->SetObjectArrayElement(array, i, newString);
   1910         env->DeleteLocalRef(newString);
   1911         checkException(env);
   1912     }
   1913     env->DeleteLocalRef(stringClass);
   1914     return array;
   1915 }
   1916 
   1917 void WebViewCore::openFileChooser(PassRefPtr<WebCore::FileChooser> chooser) {
   1918     if (!chooser)
   1919         return;
   1920     JNIEnv* env = JSC::Bindings::getJNIEnv();
   1921     jstring jName = (jstring) env->CallObjectMethod(
   1922             m_javaGlue->object(env).get(), m_javaGlue->m_openFileChooser);
   1923     checkException(env);
   1924     const UChar* string = (const UChar*) env->GetStringChars(jName, NULL);
   1925     if (!string)
   1926         return;
   1927     WebCore::String webcoreString = to_string(env, jName);
   1928     env->ReleaseStringChars(jName, string);
   1929     chooser->chooseFile(webcoreString);
   1930 }
   1931 
   1932 void WebViewCore::listBoxRequest(WebCoreReply* reply, const uint16_t** labels, size_t count, const int enabled[], size_t enabledCount,
   1933         bool multiple, const int selected[], size_t selectedCountOrSelection)
   1934 {
   1935     // If m_popupReply is not null, then we already have a list showing.
   1936     if (m_popupReply != 0)
   1937         return;
   1938 
   1939     LOG_ASSERT(m_javaGlue->m_obj, "No java widget associated with this view!");
   1940 
   1941     // Create an array of java Strings for the drop down.
   1942     JNIEnv* env = JSC::Bindings::getJNIEnv();
   1943     jobjectArray labelArray = makeLabelArray(env, labels, count);
   1944 
   1945     // Create an array determining whether each item is enabled.
   1946     jintArray enabledArray = env->NewIntArray(enabledCount);
   1947     checkException(env);
   1948     jint* ptrArray = env->GetIntArrayElements(enabledArray, 0);
   1949     checkException(env);
   1950     for (size_t i = 0; i < enabledCount; i++) {
   1951         ptrArray[i] = enabled[i];
   1952     }
   1953     env->ReleaseIntArrayElements(enabledArray, ptrArray, 0);
   1954     checkException(env);
   1955 
   1956     if (multiple) {
   1957         // Pass up an array representing which items are selected.
   1958         jintArray selectedArray = env->NewIntArray(selectedCountOrSelection);
   1959         checkException(env);
   1960         jint* selArray = env->GetIntArrayElements(selectedArray, 0);
   1961         checkException(env);
   1962         for (size_t i = 0; i < selectedCountOrSelection; i++) {
   1963             selArray[i] = selected[i];
   1964         }
   1965         env->ReleaseIntArrayElements(selectedArray, selArray, 0);
   1966 
   1967         env->CallVoidMethod(m_javaGlue->object(env).get(),
   1968                 m_javaGlue->m_requestListBox, labelArray, enabledArray,
   1969                 selectedArray);
   1970         env->DeleteLocalRef(selectedArray);
   1971     } else {
   1972         // Pass up the single selection.
   1973         env->CallVoidMethod(m_javaGlue->object(env).get(),
   1974                 m_javaGlue->m_requestSingleListBox, labelArray, enabledArray,
   1975                 selectedCountOrSelection);
   1976     }
   1977 
   1978     env->DeleteLocalRef(labelArray);
   1979     env->DeleteLocalRef(enabledArray);
   1980     checkException(env);
   1981 
   1982     Retain(reply);
   1983     m_popupReply = reply;
   1984 }
   1985 
   1986 bool WebViewCore::key(const PlatformKeyboardEvent& event)
   1987 {
   1988     WebCore::EventHandler* eventHandler = m_mainFrame->eventHandler();
   1989     WebCore::Node* focusNode = currentFocus();
   1990     if (focusNode)
   1991         eventHandler = focusNode->document()->frame()->eventHandler();
   1992     DBG_NAV_LOGD("keyCode=%s unichar=%d focusNode=%p",
   1993         event.keyIdentifier().utf8().data(), event.unichar(), focusNode);
   1994     return eventHandler->keyEvent(event);
   1995 }
   1996 
   1997 // For when the user clicks the trackball
   1998 void WebViewCore::click(WebCore::Frame* frame, WebCore::Node* node) {
   1999     if (!node) {
   2000         WebCore::IntPoint pt = m_mousePos;
   2001         pt.move(m_scrollOffsetX, m_scrollOffsetY);
   2002         WebCore::HitTestResult hitTestResult = m_mainFrame->eventHandler()->
   2003                 hitTestResultAtPoint(pt, false);
   2004         node = hitTestResult.innerNode();
   2005         frame = node->document()->frame();
   2006         DBG_NAV_LOGD("m_mousePos=(%d,%d) m_scrollOffset=(%d,%d) pt=(%d,%d)"
   2007             " node=%p", m_mousePos.x(), m_mousePos.y(),
   2008             m_scrollOffsetX, m_scrollOffsetY, pt.x(), pt.y(), node);
   2009     }
   2010     if (node) {
   2011         EditorClientAndroid* client
   2012                 = static_cast<EditorClientAndroid*>(
   2013                 m_mainFrame->editor()->client());
   2014         client->setShouldChangeSelectedRange(false);
   2015         handleMouseClick(frame, node);
   2016         client->setShouldChangeSelectedRange(true);
   2017     }
   2018 }
   2019 
   2020 #if USE(ACCELERATED_COMPOSITING)
   2021 GraphicsLayerAndroid* WebViewCore::graphicsRootLayer() const
   2022 {
   2023     RenderView* contentRenderer = m_mainFrame->contentRenderer();
   2024     if (!contentRenderer)
   2025         return 0;
   2026     return static_cast<GraphicsLayerAndroid*>(
   2027           contentRenderer->compositor()->rootPlatformLayer());
   2028 }
   2029 #endif
   2030 
   2031 bool WebViewCore::handleTouchEvent(int action, int x, int y, int metaState)
   2032 {
   2033     bool preventDefault = false;
   2034 
   2035 #if USE(ACCELERATED_COMPOSITING)
   2036     GraphicsLayerAndroid* rootLayer = graphicsRootLayer();
   2037     if (rootLayer)
   2038       rootLayer->pauseDisplay(true);
   2039 #endif
   2040 
   2041 #if ENABLE(TOUCH_EVENTS) // Android
   2042     WebCore::TouchEventType type = WebCore::TouchStart;
   2043     WebCore::PlatformTouchPoint::State touchState = WebCore::PlatformTouchPoint::TouchPressed;
   2044     switch (action) {
   2045     case 0: // MotionEvent.ACTION_DOWN
   2046         type = WebCore::TouchStart;
   2047         break;
   2048     case 1: // MotionEvent.ACTION_UP
   2049         type = WebCore::TouchEnd;
   2050         touchState = WebCore::PlatformTouchPoint::TouchReleased;
   2051         break;
   2052     case 2: // MotionEvent.ACTION_MOVE
   2053         type = WebCore::TouchMove;
   2054         touchState = WebCore::PlatformTouchPoint::TouchMoved;
   2055         break;
   2056     case 3: // MotionEvent.ACTION_CANCEL
   2057         type = WebCore::TouchCancel;
   2058         touchState = WebCore::PlatformTouchPoint::TouchCancelled;
   2059         break;
   2060     case 0x100: // WebViewCore.ACTION_LONGPRESS
   2061         type = WebCore::TouchLongPress;
   2062         touchState = WebCore::PlatformTouchPoint::TouchPressed;
   2063         break;
   2064     case 0x200: // WebViewCore.ACTION_DOUBLETAP
   2065         type = WebCore::TouchDoubleTap;
   2066         touchState = WebCore::PlatformTouchPoint::TouchPressed;
   2067         break;
   2068     default:
   2069         // We do not support other kinds of touch event inside WebCore
   2070         // at the moment.
   2071         LOGW("Java passed a touch event type that we do not support in WebCore: %d", action);
   2072         return 0;
   2073     }
   2074 
   2075     // Track previous touch and if stationary set the state.
   2076     WebCore::IntPoint pt(x - m_scrollOffsetX, y - m_scrollOffsetY);
   2077 
   2078 //  handleTouchEvent() in EventHandler.cpp doesn't handle TouchStationary, which
   2079 //  causes preventDefault be false when it returns. As our Java side may continue
   2080 //  process the events if WebKit doesn't, it can cause unexpected result.
   2081 //    if (type == WebCore::TouchMove && pt == m_lastTouchPoint)
   2082 //        touchState = WebCore::PlatformTouchPoint::TouchStationary;
   2083 
   2084     m_lastTouchPoint = pt;
   2085 
   2086     WebCore::PlatformTouchEvent te(pt, type, touchState, metaState);
   2087     preventDefault = m_mainFrame->eventHandler()->handleTouchEvent(te);
   2088 #endif
   2089 
   2090 #if USE(ACCELERATED_COMPOSITING)
   2091     if (rootLayer)
   2092       rootLayer->pauseDisplay(false);
   2093 #endif
   2094     return preventDefault;
   2095 }
   2096 
   2097 void WebViewCore::touchUp(int touchGeneration,
   2098     WebCore::Frame* frame, WebCore::Node* node, int x, int y)
   2099 {
   2100     if (m_touchGeneration > touchGeneration) {
   2101         DBG_NAV_LOGD("m_touchGeneration=%d > touchGeneration=%d"
   2102             " x=%d y=%d", m_touchGeneration, touchGeneration, x, y);
   2103         return; // short circuit if a newer touch has been generated
   2104     }
   2105     // This moves m_mousePos to the correct place, and handleMouseClick uses
   2106     // m_mousePos to determine where the click happens.
   2107     moveMouse(frame, x, y);
   2108     m_lastGeneration = touchGeneration;
   2109     if (frame && CacheBuilder::validNode(m_mainFrame, frame, 0)) {
   2110         frame->loader()->resetMultipleFormSubmissionProtection();
   2111     }
   2112     DBG_NAV_LOGD("touchGeneration=%d handleMouseClick frame=%p node=%p"
   2113         " x=%d y=%d", touchGeneration, frame, node, x, y);
   2114     handleMouseClick(frame, node);
   2115 }
   2116 
   2117 // Common code for both clicking with the trackball and touchUp
   2118 bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* nodePtr)
   2119 {
   2120     bool valid = framePtr == NULL
   2121             || CacheBuilder::validNode(m_mainFrame, framePtr, nodePtr);
   2122     WebFrame* webFrame = WebFrame::getWebFrame(m_mainFrame);
   2123     if (valid && nodePtr) {
   2124     // Need to special case area tags because an image map could have an area element in the middle
   2125     // so when attempting to get the default, the point chosen would be follow the wrong link.
   2126         if (nodePtr->hasTagName(WebCore::HTMLNames::areaTag)) {
   2127             webFrame->setUserInitiatedClick(true);
   2128             nodePtr->dispatchSimulatedClick(0, true, true);
   2129             webFrame->setUserInitiatedClick(false);
   2130             DBG_NAV_LOG("area");
   2131             return true;
   2132         }
   2133         WebCore::RenderObject* renderer = nodePtr->renderer();
   2134         if (renderer && (renderer->isMenuList() || renderer->isListBox())) {
   2135             WebCore::HTMLSelectElement* select = static_cast<WebCore::HTMLSelectElement*>(nodePtr);
   2136             const WTF::Vector<WebCore::Element*>& listItems = select->listItems();
   2137             SkTDArray<const uint16_t*> names;
   2138             // Possible values for enabledArray.  Keep in Sync with values in
   2139             // InvokeListBox.Container in WebView.java
   2140             enum OptionStatus {
   2141                 OPTGROUP = -1,
   2142                 OPTION_DISABLED = 0,
   2143                 OPTION_ENABLED = 1,
   2144             };
   2145             SkTDArray<int> enabledArray;
   2146             SkTDArray<int> selectedArray;
   2147             int size = listItems.size();
   2148             bool multiple = select->multiple();
   2149             for (int i = 0; i < size; i++) {
   2150                 if (listItems[i]->hasTagName(WebCore::HTMLNames::optionTag)) {
   2151                     WebCore::HTMLOptionElement* option = static_cast<WebCore::HTMLOptionElement*>(listItems[i]);
   2152                     *names.append() = stringConverter(option->textIndentedToRespectGroupLabel());
   2153                     *enabledArray.append() = option->disabled() ? OPTION_DISABLED : OPTION_ENABLED;
   2154                     if (multiple && option->selected())
   2155                         *selectedArray.append() = i;
   2156                 } else if (listItems[i]->hasTagName(WebCore::HTMLNames::optgroupTag)) {
   2157                     WebCore::HTMLOptGroupElement* optGroup = static_cast<WebCore::HTMLOptGroupElement*>(listItems[i]);
   2158                     *names.append() = stringConverter(optGroup->groupLabelText());
   2159                     *enabledArray.append() = OPTGROUP;
   2160                 }
   2161             }
   2162             WebCoreReply* reply = new ListBoxReply(select, select->document()->frame(), this);
   2163             // Use a pointer to HTMLSelectElement's superclass, where
   2164             // optionToListIndex is public.
   2165             SelectElement* selectElement = select;
   2166             listBoxRequest(reply, names.begin(), size, enabledArray.begin(), enabledArray.count(),
   2167                     multiple, selectedArray.begin(), multiple ? selectedArray.count() :
   2168                     selectElement->optionToListIndex(select->selectedIndex()));
   2169             DBG_NAV_LOG("menu list");
   2170             return true;
   2171         }
   2172     }
   2173     if (!valid || !framePtr)
   2174         framePtr = m_mainFrame;
   2175     webFrame->setUserInitiatedClick(true);
   2176     WebCore::PlatformMouseEvent mouseDown(m_mousePos, m_mousePos, WebCore::LeftButton,
   2177             WebCore::MouseEventPressed, 1, false, false, false, false,
   2178             WTF::currentTime());
   2179     // ignore the return from as it will return true if the hit point can trigger selection change
   2180     framePtr->eventHandler()->handleMousePressEvent(mouseDown);
   2181     WebCore::PlatformMouseEvent mouseUp(m_mousePos, m_mousePos, WebCore::LeftButton,
   2182             WebCore::MouseEventReleased, 1, false, false, false, false,
   2183             WTF::currentTime());
   2184     bool handled = framePtr->eventHandler()->handleMouseReleaseEvent(mouseUp);
   2185     webFrame->setUserInitiatedClick(false);
   2186 
   2187     // If the user clicked on a textfield, make the focusController active
   2188     // so we show the blinking cursor.
   2189     WebCore::Node* focusNode = currentFocus();
   2190     DBG_NAV_LOGD("m_mousePos={%d,%d} focusNode=%p handled=%s", m_mousePos.x(),
   2191         m_mousePos.y(), focusNode, handled ? "true" : "false");
   2192     if (focusNode) {
   2193         WebCore::RenderObject* renderer = focusNode->renderer();
   2194         if (renderer && (renderer->isTextField() || renderer->isTextArea())) {
   2195             bool ime = !(static_cast<WebCore::HTMLInputElement*>(focusNode))
   2196                     ->readOnly();
   2197             setFocusControllerActive(framePtr, ime);
   2198             if (ime) {
   2199                 RenderTextControl* rtc
   2200                         = static_cast<RenderTextControl*> (renderer);
   2201                 requestKeyboardWithSelection(focusNode, rtc->selectionStart(),
   2202                         rtc->selectionEnd());
   2203             } else {
   2204                 requestKeyboard(false);
   2205             }
   2206         }
   2207     }
   2208     return handled;
   2209 }
   2210 
   2211 void WebViewCore::popupReply(int index)
   2212 {
   2213     if (m_popupReply) {
   2214         m_popupReply->replyInt(index);
   2215         Release(m_popupReply);
   2216         m_popupReply = 0;
   2217     }
   2218 }
   2219 
   2220 void WebViewCore::popupReply(const int* array, int count)
   2221 {
   2222     if (m_popupReply) {
   2223         m_popupReply->replyIntArray(array, count);
   2224         Release(m_popupReply);
   2225         m_popupReply = NULL;
   2226     }
   2227 }
   2228 
   2229 void WebViewCore::addMessageToConsole(const WebCore::String& message, unsigned int lineNumber, const WebCore::String& sourceID, int msgLevel) {
   2230     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2231     jstring jMessageStr = env->NewString((unsigned short *)message.characters(), message.length());
   2232     jstring jSourceIDStr = env->NewString((unsigned short *)sourceID.characters(), sourceID.length());
   2233     env->CallVoidMethod(m_javaGlue->object(env).get(),
   2234             m_javaGlue->m_addMessageToConsole, jMessageStr, lineNumber,
   2235             jSourceIDStr, msgLevel);
   2236     env->DeleteLocalRef(jMessageStr);
   2237     env->DeleteLocalRef(jSourceIDStr);
   2238     checkException(env);
   2239 }
   2240 
   2241 void WebViewCore::jsAlert(const WebCore::String& url, const WebCore::String& text)
   2242 {
   2243     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2244     jstring jInputStr = env->NewString((unsigned short *)text.characters(), text.length());
   2245     jstring jUrlStr = env->NewString((unsigned short *)url.characters(), url.length());
   2246     env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_jsAlert, jUrlStr, jInputStr);
   2247     env->DeleteLocalRef(jInputStr);
   2248     env->DeleteLocalRef(jUrlStr);
   2249     checkException(env);
   2250 }
   2251 
   2252 void WebViewCore::exceededDatabaseQuota(const WebCore::String& url, const WebCore::String& databaseIdentifier, const unsigned long long currentQuota, unsigned long long estimatedSize)
   2253 {
   2254 #if ENABLE(DATABASE)
   2255     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2256     jstring jDatabaseIdentifierStr = env->NewString((unsigned short *)databaseIdentifier.characters(), databaseIdentifier.length());
   2257     jstring jUrlStr = env->NewString((unsigned short *)url.characters(), url.length());
   2258     env->CallVoidMethod(m_javaGlue->object(env).get(),
   2259             m_javaGlue->m_exceededDatabaseQuota, jUrlStr,
   2260             jDatabaseIdentifierStr, currentQuota, estimatedSize);
   2261     env->DeleteLocalRef(jDatabaseIdentifierStr);
   2262     env->DeleteLocalRef(jUrlStr);
   2263     checkException(env);
   2264 #endif
   2265 }
   2266 
   2267 void WebViewCore::reachedMaxAppCacheSize(const unsigned long long spaceNeeded)
   2268 {
   2269 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
   2270     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2271     env->CallVoidMethod(m_javaGlue->object(env).get(),
   2272             m_javaGlue->m_reachedMaxAppCacheSize, spaceNeeded);
   2273     checkException(env);
   2274 #endif
   2275 }
   2276 
   2277 void WebViewCore::populateVisitedLinks(WebCore::PageGroup* group)
   2278 {
   2279     m_groupForVisitedLinks = group;
   2280     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2281     env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_populateVisitedLinks);
   2282     checkException(env);
   2283 }
   2284 
   2285 void WebViewCore::geolocationPermissionsShowPrompt(const WebCore::String& origin)
   2286 {
   2287     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2288     jstring originString = env->NewString((unsigned short *)origin.characters(), origin.length());
   2289     env->CallVoidMethod(m_javaGlue->object(env).get(),
   2290                         m_javaGlue->m_geolocationPermissionsShowPrompt,
   2291                         originString);
   2292     env->DeleteLocalRef(originString);
   2293     checkException(env);
   2294 }
   2295 
   2296 void WebViewCore::geolocationPermissionsHidePrompt()
   2297 {
   2298     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2299     env->CallVoidMethod(m_javaGlue->object(env).get(),
   2300                         m_javaGlue->m_geolocationPermissionsHidePrompt);
   2301     checkException(env);
   2302 }
   2303 
   2304 bool WebViewCore::jsConfirm(const WebCore::String& url, const WebCore::String& text)
   2305 {
   2306     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2307     jstring jInputStr = env->NewString((unsigned short *)text.characters(), text.length());
   2308     jstring jUrlStr = env->NewString((unsigned short *)url.characters(), url.length());
   2309     jboolean result = env->CallBooleanMethod(m_javaGlue->object(env).get(), m_javaGlue->m_jsConfirm, jUrlStr, jInputStr);
   2310     env->DeleteLocalRef(jInputStr);
   2311     env->DeleteLocalRef(jUrlStr);
   2312     checkException(env);
   2313     return result;
   2314 }
   2315 
   2316 bool WebViewCore::jsPrompt(const WebCore::String& url, const WebCore::String& text, const WebCore::String& defaultValue, WebCore::String& result)
   2317 {
   2318     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2319     jstring jInputStr = env->NewString((unsigned short *)text.characters(), text.length());
   2320     jstring jDefaultStr = env->NewString((unsigned short *)defaultValue.characters(), defaultValue.length());
   2321     jstring jUrlStr = env->NewString((unsigned short *)url.characters(), url.length());
   2322     jstring returnVal = (jstring) env->CallObjectMethod(m_javaGlue->object(env).get(), m_javaGlue->m_jsPrompt, jUrlStr, jInputStr, jDefaultStr);
   2323     // If returnVal is null, it means that the user cancelled the dialog.
   2324     if (!returnVal)
   2325         return false;
   2326 
   2327     result = to_string(env, returnVal);
   2328     env->DeleteLocalRef(jInputStr);
   2329     env->DeleteLocalRef(jDefaultStr);
   2330     env->DeleteLocalRef(jUrlStr);
   2331     checkException(env);
   2332     return true;
   2333 }
   2334 
   2335 bool WebViewCore::jsUnload(const WebCore::String& url, const WebCore::String& message)
   2336 {
   2337     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2338     jstring jInputStr = env->NewString((unsigned short *)message.characters(), message.length());
   2339     jstring jUrlStr = env->NewString((unsigned short *)url.characters(), url.length());
   2340     jboolean result = env->CallBooleanMethod(m_javaGlue->object(env).get(), m_javaGlue->m_jsUnload, jUrlStr, jInputStr);
   2341     env->DeleteLocalRef(jInputStr);
   2342     env->DeleteLocalRef(jUrlStr);
   2343     checkException(env);
   2344     return result;
   2345 }
   2346 
   2347 bool WebViewCore::jsInterrupt()
   2348 {
   2349     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2350     jboolean result = env->CallBooleanMethod(m_javaGlue->object(env).get(), m_javaGlue->m_jsInterrupt);
   2351     checkException(env);
   2352     return result;
   2353 }
   2354 
   2355 AutoJObject
   2356 WebViewCore::getJavaObject()
   2357 {
   2358     return getRealObject(JSC::Bindings::getJNIEnv(), m_javaGlue->m_obj);
   2359 }
   2360 
   2361 jobject
   2362 WebViewCore::getWebViewJavaObject()
   2363 {
   2364     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2365     return env->GetObjectField(m_javaGlue->object(env).get(), gWebViewCoreFields.m_webView);
   2366 }
   2367 
   2368 void WebViewCore::updateTextSelection() {
   2369     WebCore::Node* focusNode = currentFocus();
   2370     if (!focusNode)
   2371         return;
   2372     RenderObject* renderer = focusNode->renderer();
   2373     if (!renderer || (!renderer->isTextArea() && !renderer->isTextField()))
   2374         return;
   2375     RenderTextControl* rtc = static_cast<RenderTextControl*>(renderer);
   2376     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2377     env->CallVoidMethod(m_javaGlue->object(env).get(),
   2378             m_javaGlue->m_updateTextSelection, reinterpret_cast<int>(focusNode),
   2379             rtc->selectionStart(), rtc->selectionEnd(), m_textGeneration);
   2380     checkException(env);
   2381 }
   2382 
   2383 void WebViewCore::updateTextfield(WebCore::Node* ptr, bool changeToPassword,
   2384         const WebCore::String& text)
   2385 {
   2386     if (m_blockTextfieldUpdates)
   2387         return;
   2388     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2389     if (changeToPassword) {
   2390         env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_updateTextfield,
   2391                 (int) ptr, true, 0, m_textGeneration);
   2392         checkException(env);
   2393         return;
   2394     }
   2395     int length = text.length();
   2396     jstring string = env->NewString((unsigned short *) text.characters(), length);
   2397     env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_updateTextfield,
   2398             (int) ptr, false, string, m_textGeneration);
   2399     env->DeleteLocalRef(string);
   2400     checkException(env);
   2401 }
   2402 
   2403 void WebViewCore::clearTextEntry()
   2404 {
   2405     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2406     env->CallVoidMethod(m_javaGlue->object(env).get(),
   2407         m_javaGlue->m_clearTextEntry);
   2408 }
   2409 
   2410 void WebViewCore::setBackgroundColor(SkColor c)
   2411 {
   2412     WebCore::FrameView* view = m_mainFrame->view();
   2413     if (!view)
   2414         return;
   2415 
   2416     // need (int) cast to find the right constructor
   2417     WebCore::Color bcolor((int)SkColorGetR(c), (int)SkColorGetG(c),
   2418                           (int)SkColorGetB(c), (int)SkColorGetA(c));
   2419     view->setBaseBackgroundColor(bcolor);
   2420 
   2421     // Background color of 0 indicates we want a transparent background
   2422     if (c == 0)
   2423         view->setTransparent(true);
   2424 }
   2425 
   2426 jclass WebViewCore::getPluginClass(const WebCore::String& libName, const char* className)
   2427 {
   2428     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2429 
   2430     jstring libString = env->NewString(libName.characters(), libName.length());
   2431     jstring classString = env->NewStringUTF(className);
   2432     jobject pluginClass = env->CallObjectMethod(m_javaGlue->object(env).get(),
   2433                                            m_javaGlue->m_getPluginClass,
   2434                                            libString, classString);
   2435     checkException(env);
   2436 
   2437     // cleanup unneeded local JNI references
   2438     env->DeleteLocalRef(libString);
   2439     env->DeleteLocalRef(classString);
   2440 
   2441     if (pluginClass != NULL) {
   2442         return static_cast<jclass>(pluginClass);
   2443     } else {
   2444         return NULL;
   2445     }
   2446 }
   2447 
   2448 void WebViewCore::showFullScreenPlugin(jobject childView, NPP npp)
   2449 {
   2450     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2451     AutoJObject obj = m_javaGlue->object(env);
   2452 
   2453     env->CallVoidMethod(obj.get(),
   2454                         m_javaGlue->m_showFullScreenPlugin, childView, (int)npp);
   2455     checkException(env);
   2456 }
   2457 
   2458 void WebViewCore::hideFullScreenPlugin()
   2459 {
   2460     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2461     env->CallVoidMethod(m_javaGlue->object(env).get(),
   2462                         m_javaGlue->m_hideFullScreenPlugin);
   2463     checkException(env);
   2464 }
   2465 
   2466 jobject WebViewCore::addSurface(jobject view, int x, int y, int width, int height)
   2467 {
   2468     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2469     jobject result = env->CallObjectMethod(m_javaGlue->object(env).get(),
   2470                                            m_javaGlue->m_addSurface,
   2471                                            view, x, y, width, height);
   2472     checkException(env);
   2473     return result;
   2474 }
   2475 
   2476 void WebViewCore::updateSurface(jobject childView, int x, int y, int width, int height)
   2477 {
   2478     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2479     env->CallVoidMethod(m_javaGlue->object(env).get(),
   2480                         m_javaGlue->m_updateSurface, childView,
   2481                         x, y, width, height);
   2482     checkException(env);
   2483 }
   2484 
   2485 void WebViewCore::destroySurface(jobject childView)
   2486 {
   2487     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2488     env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_destroySurface, childView);
   2489     checkException(env);
   2490 }
   2491 
   2492 jobject WebViewCore::getContext()
   2493 {
   2494     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2495     AutoJObject obj = m_javaGlue->object(env);
   2496 
   2497     jobject result = env->CallObjectMethod(obj.get(), m_javaGlue->m_getContext);
   2498     checkException(env);
   2499     return result;
   2500 }
   2501 
   2502 bool WebViewCore::validNodeAndBounds(Frame* frame, Node* node,
   2503     const IntRect& originalAbsoluteBounds)
   2504 {
   2505     bool valid = CacheBuilder::validNode(m_mainFrame, frame, node);
   2506     if (!valid)
   2507         return false;
   2508     RenderObject* renderer = node->renderer();
   2509     if (!renderer)
   2510         return false;
   2511     IntRect absBounds = node->hasTagName(HTMLNames::areaTag)
   2512         ? CacheBuilder::getAreaRect(static_cast<HTMLAreaElement*>(node))
   2513         : renderer->absoluteBoundingBoxRect();
   2514     return absBounds == originalAbsoluteBounds;
   2515 }
   2516 
   2517 void WebViewCore::showRect(int left, int top, int width, int height,
   2518         int contentWidth, int contentHeight, float xPercentInDoc,
   2519         float xPercentInView, float yPercentInDoc, float yPercentInView)
   2520 {
   2521     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2522     env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_showRect,
   2523             left, top, width, height, contentWidth, contentHeight,
   2524             xPercentInDoc, xPercentInView, yPercentInDoc, yPercentInView);
   2525     checkException(env);
   2526 }
   2527 
   2528 void WebViewCore::centerFitRect(int x, int y, int width, int height)
   2529 {
   2530     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2531     env->CallVoidMethod(m_javaGlue->object(env).get(),
   2532             m_javaGlue->m_centerFitRect, x, y, width, height);
   2533     checkException(env);
   2534 }
   2535 
   2536 
   2537 void WebViewCore::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode)
   2538 {
   2539     JNIEnv* env = JSC::Bindings::getJNIEnv();
   2540     env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_setScrollbarModes,
   2541             horizontalMode, verticalMode);
   2542     checkException(env);
   2543 }
   2544 
   2545 //----------------------------------------------------------------------
   2546 // Native JNI methods
   2547 //----------------------------------------------------------------------
   2548 static jstring WebCoreStringToJString(JNIEnv *env, WebCore::String string)
   2549 {
   2550     int length = string.length();
   2551     if (!length)
   2552         return 0;
   2553     jstring ret = env->NewString((jchar *)string.characters(), length);
   2554     env->DeleteLocalRef(ret);
   2555     return ret;
   2556 }
   2557 
   2558 static jstring RequestLabel(JNIEnv *env, jobject obj, int framePointer,
   2559         int nodePointer)
   2560 {
   2561     return WebCoreStringToJString(env, GET_NATIVE_VIEW(env, obj)->requestLabel(
   2562             (WebCore::Frame*) framePointer, (WebCore::Node*) nodePointer));
   2563 }
   2564 
   2565 static void UpdateFrameCacheIfLoading(JNIEnv *env, jobject obj)
   2566 {
   2567     GET_NATIVE_VIEW(env, obj)->updateFrameCacheIfLoading();
   2568 }
   2569 
   2570 static void SetSize(JNIEnv *env, jobject obj, jint width, jint height,
   2571         jint screenWidth, jfloat scale, jint realScreenWidth, jint screenHeight,
   2572         jint anchorX, jint anchorY, jboolean ignoreHeight)
   2573 {
   2574 #ifdef ANDROID_INSTRUMENT
   2575     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2576 #endif
   2577     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2578     LOGV("webviewcore::nativeSetSize(%u %u)\n viewImpl: %p", (unsigned)width, (unsigned)height, viewImpl);
   2579     LOG_ASSERT(viewImpl, "viewImpl not set in nativeSetSize");
   2580     viewImpl->setSizeScreenWidthAndScale(width, height, screenWidth, scale,
   2581         realScreenWidth, screenHeight, anchorX, anchorY, ignoreHeight);
   2582 }
   2583 
   2584 static void SetScrollOffset(JNIEnv *env, jobject obj, jint gen, jint x, jint y)
   2585 {
   2586 #ifdef ANDROID_INSTRUMENT
   2587     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2588 #endif
   2589     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2590     LOG_ASSERT(viewImpl, "need viewImpl");
   2591 
   2592     viewImpl->setScrollOffset(gen, x, y);
   2593 }
   2594 
   2595 static void SetGlobalBounds(JNIEnv *env, jobject obj, jint x, jint y, jint h,
   2596                             jint v)
   2597 {
   2598 #ifdef ANDROID_INSTRUMENT
   2599     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2600 #endif
   2601     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2602     LOG_ASSERT(viewImpl, "need viewImpl");
   2603 
   2604     viewImpl->setGlobalBounds(x, y, h, v);
   2605 }
   2606 
   2607 static jboolean Key(JNIEnv *env, jobject obj, jint keyCode, jint unichar,
   2608         jint repeatCount, jboolean isShift, jboolean isAlt, jboolean isSym,
   2609         jboolean isDown)
   2610 {
   2611 #ifdef ANDROID_INSTRUMENT
   2612     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2613 #endif
   2614     return GET_NATIVE_VIEW(env, obj)->key(PlatformKeyboardEvent(keyCode,
   2615         unichar, repeatCount, isDown, isShift, isAlt, isSym));
   2616 }
   2617 
   2618 static void Click(JNIEnv *env, jobject obj, int framePtr, int nodePtr)
   2619 {
   2620 #ifdef ANDROID_INSTRUMENT
   2621     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2622 #endif
   2623     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2624     LOG_ASSERT(viewImpl, "viewImpl not set in Click");
   2625 
   2626     viewImpl->click(reinterpret_cast<WebCore::Frame*>(framePtr),
   2627         reinterpret_cast<WebCore::Node*>(nodePtr));
   2628 }
   2629 
   2630 static void DeleteSelection(JNIEnv *env, jobject obj, jint start, jint end,
   2631         jint textGeneration)
   2632 {
   2633 #ifdef ANDROID_INSTRUMENT
   2634     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2635 #endif
   2636     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2637     viewImpl->deleteSelection(start, end, textGeneration);
   2638 }
   2639 
   2640 static void SetSelection(JNIEnv *env, jobject obj, jint start, jint end)
   2641 {
   2642 #ifdef ANDROID_INSTRUMENT
   2643     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2644 #endif
   2645     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2646     viewImpl->setSelection(start, end);
   2647 }
   2648 
   2649 
   2650 static void ReplaceTextfieldText(JNIEnv *env, jobject obj,
   2651     jint oldStart, jint oldEnd, jstring replace, jint start, jint end,
   2652     jint textGeneration)
   2653 {
   2654 #ifdef ANDROID_INSTRUMENT
   2655     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2656 #endif
   2657     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2658     WebCore::String webcoreString = to_string(env, replace);
   2659     viewImpl->replaceTextfieldText(oldStart,
   2660             oldEnd, webcoreString, start, end, textGeneration);
   2661 }
   2662 
   2663 static void PassToJs(JNIEnv *env, jobject obj,
   2664     jint generation, jstring currentText, jint keyCode,
   2665     jint keyValue, jboolean down, jboolean cap, jboolean fn, jboolean sym)
   2666 {
   2667 #ifdef ANDROID_INSTRUMENT
   2668     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2669 #endif
   2670     WebCore::String current = to_string(env, currentText);
   2671     GET_NATIVE_VIEW(env, obj)->passToJs(generation, current,
   2672         PlatformKeyboardEvent(keyCode, keyValue, 0, down, cap, fn, sym));
   2673 }
   2674 
   2675 static void ScrollFocusedTextInput(JNIEnv *env, jobject obj, jfloat xPercent,
   2676     jint y)
   2677 {
   2678 #ifdef ANDROID_INSTRUMENT
   2679     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2680 #endif
   2681     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2682     viewImpl->scrollFocusedTextInput(xPercent, y);
   2683 }
   2684 
   2685 static void SetFocusControllerActive(JNIEnv *env, jobject obj, jboolean active)
   2686 {
   2687 #ifdef ANDROID_INSTRUMENT
   2688     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2689 #endif
   2690     LOGV("webviewcore::nativeSetFocusControllerActive()\n");
   2691     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2692     LOG_ASSERT(viewImpl, "viewImpl not set in nativeSetFocusControllerActive");
   2693     viewImpl->setFocusControllerActive(0, active);
   2694 }
   2695 
   2696 static void SaveDocumentState(JNIEnv *env, jobject obj, jint frame)
   2697 {
   2698 #ifdef ANDROID_INSTRUMENT
   2699     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2700 #endif
   2701     LOGV("webviewcore::nativeSaveDocumentState()\n");
   2702     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2703     LOG_ASSERT(viewImpl, "viewImpl not set in nativeSaveDocumentState");
   2704     viewImpl->saveDocumentState((WebCore::Frame*) frame);
   2705 }
   2706 
   2707 void WebViewCore::addVisitedLink(const UChar* string, int length)
   2708 {
   2709     if (m_groupForVisitedLinks)
   2710         m_groupForVisitedLinks->addVisitedLink(string, length);
   2711 }
   2712 
   2713 static bool RecordContent(JNIEnv *env, jobject obj, jobject region, jobject pt)
   2714 {
   2715 #ifdef ANDROID_INSTRUMENT
   2716     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2717 #endif
   2718     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2719     SkRegion* nativeRegion = GraphicsJNI::getNativeRegion(env, region);
   2720     SkIPoint nativePt;
   2721     bool result = viewImpl->recordContent(nativeRegion, &nativePt);
   2722     GraphicsJNI::ipoint_to_jpoint(nativePt, env, pt);
   2723     return result;
   2724 }
   2725 
   2726 static void SplitContent(JNIEnv *env, jobject obj)
   2727 {
   2728 #ifdef ANDROID_INSTRUMENT
   2729     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2730 #endif
   2731     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2732     viewImpl->splitContent();
   2733 }
   2734 
   2735 static void SendListBoxChoice(JNIEnv* env, jobject obj, jint choice)
   2736 {
   2737 #ifdef ANDROID_INSTRUMENT
   2738     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2739 #endif
   2740     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2741     LOG_ASSERT(viewImpl, "viewImpl not set in nativeSendListBoxChoice");
   2742     viewImpl->popupReply(choice);
   2743 }
   2744 
   2745 // Set aside a predetermined amount of space in which to place the listbox
   2746 // choices, to avoid unnecessary allocations.
   2747 // The size here is arbitrary.  We want the size to be at least as great as the
   2748 // number of items in the average multiple-select listbox.
   2749 #define PREPARED_LISTBOX_STORAGE 10
   2750 
   2751 static void SendListBoxChoices(JNIEnv* env, jobject obj, jbooleanArray jArray,
   2752         jint size)
   2753 {
   2754 #ifdef ANDROID_INSTRUMENT
   2755     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2756 #endif
   2757     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2758     LOG_ASSERT(viewImpl, "viewImpl not set in nativeSendListBoxChoices");
   2759     jboolean* ptrArray = env->GetBooleanArrayElements(jArray, 0);
   2760     SkAutoSTMalloc<PREPARED_LISTBOX_STORAGE, int> storage(size);
   2761     int* array = storage.get();
   2762     int count = 0;
   2763     for (int i = 0; i < size; i++) {
   2764         if (ptrArray[i]) {
   2765             array[count++] = i;
   2766         }
   2767     }
   2768     env->ReleaseBooleanArrayElements(jArray, ptrArray, JNI_ABORT);
   2769     viewImpl->popupReply(array, count);
   2770 }
   2771 
   2772 static jstring FindAddress(JNIEnv *env, jobject obj, jstring addr,
   2773     jboolean caseInsensitive)
   2774 {
   2775 #ifdef ANDROID_INSTRUMENT
   2776     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2777 #endif
   2778     if (!addr)
   2779         return 0;
   2780     int length = env->GetStringLength(addr);
   2781     if (!length)
   2782         return 0;
   2783     const jchar* addrChars = env->GetStringChars(addr, 0);
   2784     int start, end;
   2785     bool success = CacheBuilder::FindAddress(addrChars, length,
   2786         &start, &end, caseInsensitive) == CacheBuilder::FOUND_COMPLETE;
   2787     jstring ret = 0;
   2788     if (success) {
   2789         ret = env->NewString((jchar*) addrChars + start, end - start);
   2790         env->DeleteLocalRef(ret);
   2791     }
   2792     env->ReleaseStringChars(addr, addrChars);
   2793     return ret;
   2794 }
   2795 
   2796 static jboolean HandleTouchEvent(JNIEnv *env, jobject obj, jint action, jint x, jint y, jint metaState)
   2797 {
   2798 #ifdef ANDROID_INSTRUMENT
   2799     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2800 #endif
   2801     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2802     LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
   2803     return viewImpl->handleTouchEvent(action, x, y, metaState);
   2804 }
   2805 
   2806 static void TouchUp(JNIEnv *env, jobject obj, jint touchGeneration,
   2807         jint frame, jint node, jint x, jint y)
   2808 {
   2809 #ifdef ANDROID_INSTRUMENT
   2810     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2811 #endif
   2812     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2813     LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
   2814     viewImpl->touchUp(touchGeneration,
   2815         (WebCore::Frame*) frame, (WebCore::Node*) node, x, y);
   2816 }
   2817 
   2818 static jstring RetrieveHref(JNIEnv *env, jobject obj, jint frame,
   2819         jint node)
   2820 {
   2821 #ifdef ANDROID_INSTRUMENT
   2822     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2823 #endif
   2824     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2825     LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
   2826     WebCore::String result = viewImpl->retrieveHref((WebCore::Frame*) frame,
   2827             (WebCore::Node*) node);
   2828     if (!result.isEmpty())
   2829         return WebCoreStringToJString(env, result);
   2830     return 0;
   2831 }
   2832 
   2833 static jstring RetrieveAnchorText(JNIEnv *env, jobject obj, jint frame,
   2834         jint node)
   2835 {
   2836 #ifdef ANDROID_INSTRUMENT
   2837     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2838 #endif
   2839     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2840     LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
   2841     WebCore::String result = viewImpl->retrieveAnchorText((WebCore::Frame*) frame,
   2842             (WebCore::Node*) node);
   2843     if (!result.isEmpty())
   2844         return WebCoreStringToJString(env, result);
   2845     return 0;
   2846 }
   2847 
   2848 
   2849 static void MoveFocus(JNIEnv *env, jobject obj, jint framePtr, jint nodePtr)
   2850 {
   2851 #ifdef ANDROID_INSTRUMENT
   2852     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2853 #endif
   2854     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2855     LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
   2856     viewImpl->moveFocus((WebCore::Frame*) framePtr, (WebCore::Node*) nodePtr);
   2857 }
   2858 
   2859 static void MoveMouse(JNIEnv *env, jobject obj, jint frame,
   2860         jint x, jint y)
   2861 {
   2862 #ifdef ANDROID_INSTRUMENT
   2863     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2864 #endif
   2865     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2866     LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
   2867     viewImpl->moveMouse((WebCore::Frame*) frame, x, y);
   2868 }
   2869 
   2870 static void MoveMouseIfLatest(JNIEnv *env, jobject obj, jint moveGeneration,
   2871         jint frame, jint x, jint y)
   2872 {
   2873 #ifdef ANDROID_INSTRUMENT
   2874     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2875 #endif
   2876     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2877     LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
   2878     viewImpl->moveMouseIfLatest(moveGeneration,
   2879         (WebCore::Frame*) frame, x, y);
   2880 }
   2881 
   2882 static void UpdateFrameCache(JNIEnv *env, jobject obj)
   2883 {
   2884 #ifdef ANDROID_INSTRUMENT
   2885     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2886 #endif
   2887     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2888     LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
   2889     viewImpl->updateFrameCache();
   2890 }
   2891 
   2892 static jint GetContentMinPrefWidth(JNIEnv *env, jobject obj)
   2893 {
   2894 #ifdef ANDROID_INSTRUMENT
   2895     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2896 #endif
   2897     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2898     LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
   2899 
   2900     WebCore::Frame* frame = viewImpl->mainFrame();
   2901     if (frame) {
   2902         WebCore::Document* document = frame->document();
   2903         if (document) {
   2904             WebCore::RenderObject* renderer = document->renderer();
   2905             if (renderer && renderer->isRenderView()) {
   2906                 return renderer->minPrefWidth();
   2907             }
   2908         }
   2909     }
   2910     return 0;
   2911 }
   2912 
   2913 static void SetViewportSettingsFromNative(JNIEnv *env, jobject obj)
   2914 {
   2915 #ifdef ANDROID_INSTRUMENT
   2916     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2917 #endif
   2918     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2919     LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
   2920 
   2921     WebCore::Settings* s = viewImpl->mainFrame()->page()->settings();
   2922     if (!s)
   2923         return;
   2924 
   2925 #ifdef ANDROID_META_SUPPORT
   2926     env->SetIntField(obj, gWebViewCoreFields.m_viewportWidth, s->viewportWidth());
   2927     env->SetIntField(obj, gWebViewCoreFields.m_viewportHeight, s->viewportHeight());
   2928     env->SetIntField(obj, gWebViewCoreFields.m_viewportInitialScale, s->viewportInitialScale());
   2929     env->SetIntField(obj, gWebViewCoreFields.m_viewportMinimumScale, s->viewportMinimumScale());
   2930     env->SetIntField(obj, gWebViewCoreFields.m_viewportMaximumScale, s->viewportMaximumScale());
   2931     env->SetBooleanField(obj, gWebViewCoreFields.m_viewportUserScalable, s->viewportUserScalable());
   2932     env->SetIntField(obj, gWebViewCoreFields.m_viewportDensityDpi, s->viewportTargetDensityDpi());
   2933 #endif
   2934 }
   2935 
   2936 static void SetBackgroundColor(JNIEnv *env, jobject obj, jint color)
   2937 {
   2938 #ifdef ANDROID_INSTRUMENT
   2939     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   2940 #endif
   2941     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2942     LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
   2943 
   2944     viewImpl->setBackgroundColor((SkColor) color);
   2945 }
   2946 
   2947 static void DumpDomTree(JNIEnv *env, jobject obj, jboolean useFile)
   2948 {
   2949     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2950     LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
   2951 
   2952     viewImpl->dumpDomTree(useFile);
   2953 }
   2954 
   2955 static void DumpRenderTree(JNIEnv *env, jobject obj, jboolean useFile)
   2956 {
   2957     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2958     LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
   2959 
   2960     viewImpl->dumpRenderTree(useFile);
   2961 }
   2962 
   2963 static void DumpNavTree(JNIEnv *env, jobject obj)
   2964 {
   2965     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2966     LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
   2967 
   2968     viewImpl->dumpNavTree();
   2969 }
   2970 
   2971 static void DumpV8Counters(JNIEnv*, jobject)
   2972 {
   2973 #if USE(V8)
   2974 #ifdef ANDROID_INSTRUMENT
   2975     V8Counters::dumpCounters();
   2976 #endif
   2977 #endif
   2978 }
   2979 
   2980 static void SetJsFlags(JNIEnv *env, jobject obj, jstring flags)
   2981 {
   2982 #if USE(V8)
   2983     WebCore::String flagsString = to_string(env, flags);
   2984     WebCore::CString utf8String = flagsString.utf8();
   2985     WebCore::ScriptController::setFlags(utf8String.data(), utf8String.length());
   2986 #endif
   2987 }
   2988 
   2989 
   2990 // Called from the Java side to set a new quota for the origin or new appcache
   2991 // max size in response to a notification that the original quota was exceeded or
   2992 // that the appcache has reached its maximum size.
   2993 static void SetNewStorageLimit(JNIEnv* env, jobject obj, jlong quota) {
   2994 #if ENABLE(DATABASE) || ENABLE(OFFLINE_WEB_APPLICATIONS)
   2995     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   2996     Frame* frame = viewImpl->mainFrame();
   2997 
   2998     // The main thread is blocked awaiting this response, so now we can wake it
   2999     // up.
   3000     ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(frame->page()->chrome()->client());
   3001     chromeC->wakeUpMainThreadWithNewQuota(quota);
   3002 #endif
   3003 }
   3004 
   3005 // Called from Java to provide a Geolocation permission state for the specified origin.
   3006 static void GeolocationPermissionsProvide(JNIEnv* env, jobject obj, jstring origin, jboolean allow, jboolean remember) {
   3007     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   3008     Frame* frame = viewImpl->mainFrame();
   3009 
   3010     ChromeClientAndroid* chromeClient = static_cast<ChromeClientAndroid*>(frame->page()->chrome()->client());
   3011     chromeClient->provideGeolocationPermissions(to_string(env, origin), allow, remember);
   3012 }
   3013 
   3014 static void RegisterURLSchemeAsLocal(JNIEnv* env, jobject obj, jstring scheme) {
   3015 #ifdef ANDROID_INSTRUMENT
   3016     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   3017 #endif
   3018     WebCore::SecurityOrigin::registerURLSchemeAsLocal(to_string(env, scheme));
   3019 }
   3020 
   3021 static void ClearContent(JNIEnv *env, jobject obj)
   3022 {
   3023 #ifdef ANDROID_INSTRUMENT
   3024     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   3025 #endif
   3026     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   3027     viewImpl->clearContent();
   3028 }
   3029 
   3030 static void CopyContentToPicture(JNIEnv *env, jobject obj, jobject pict)
   3031 {
   3032 #ifdef ANDROID_INSTRUMENT
   3033     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
   3034 #endif
   3035     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   3036     if (!viewImpl)
   3037         return;
   3038     SkPicture* picture = GraphicsJNI::getNativePicture(env, pict);
   3039     viewImpl->copyContentToPicture(picture);
   3040 }
   3041 
   3042 static bool DrawContent(JNIEnv *env, jobject obj, jobject canv, jint color)
   3043 {
   3044     // Note: this is called from UI thread, don't count it for WebViewCoreTimeCounter
   3045     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   3046     SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv);
   3047     return viewImpl->drawContent(canvas, color);
   3048 }
   3049 
   3050 static bool FocusBoundsChanged(JNIEnv* env, jobject obj)
   3051 {
   3052     return GET_NATIVE_VIEW(env, obj)->focusBoundsChanged();
   3053 }
   3054 
   3055 static bool PictureReady(JNIEnv* env, jobject obj)
   3056 {
   3057     return GET_NATIVE_VIEW(env, obj)->pictureReady();
   3058 }
   3059 
   3060 static void Pause(JNIEnv* env, jobject obj)
   3061 {
   3062     // This is called for the foreground tab when the browser is put to the
   3063     // background (and also for any tab when it is put to the background of the
   3064     // browser). The browser can only be killed by the system when it is in the
   3065     // background, so saving the Geolocation permission state now ensures that
   3066     // is maintained when the browser is killed.
   3067     ChromeClient* chromeClient = GET_NATIVE_VIEW(env, obj)->mainFrame()->page()->chrome()->client();
   3068     ChromeClientAndroid* chromeClientAndroid = static_cast<ChromeClientAndroid*>(chromeClient);
   3069     chromeClientAndroid->storeGeolocationPermissions();
   3070 
   3071     Frame* mainFrame = GET_NATIVE_VIEW(env, obj)->mainFrame();
   3072     for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext()) {
   3073         Geolocation* geolocation = frame->domWindow()->navigator()->optionalGeolocation();
   3074         if (geolocation)
   3075             geolocation->suspend();
   3076     }
   3077 
   3078     ANPEvent event;
   3079     SkANP::InitEvent(&event, kLifecycle_ANPEventType);
   3080     event.data.lifecycle.action = kPause_ANPLifecycleAction;
   3081     GET_NATIVE_VIEW(env, obj)->sendPluginEvent(event);
   3082 
   3083     GET_NATIVE_VIEW(env, obj)->setIsPaused(true);
   3084 }
   3085 
   3086 static void Resume(JNIEnv* env, jobject obj)
   3087 {
   3088     Frame* mainFrame = GET_NATIVE_VIEW(env, obj)->mainFrame();
   3089     for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext()) {
   3090         Geolocation* geolocation = frame->domWindow()->navigator()->optionalGeolocation();
   3091         if (geolocation)
   3092             geolocation->resume();
   3093     }
   3094 
   3095     ANPEvent event;
   3096     SkANP::InitEvent(&event, kLifecycle_ANPEventType);
   3097     event.data.lifecycle.action = kResume_ANPLifecycleAction;
   3098     GET_NATIVE_VIEW(env, obj)->sendPluginEvent(event);
   3099 
   3100     GET_NATIVE_VIEW(env, obj)->setIsPaused(false);
   3101 }
   3102 
   3103 static void FreeMemory(JNIEnv* env, jobject obj)
   3104 {
   3105     ANPEvent event;
   3106     SkANP::InitEvent(&event, kLifecycle_ANPEventType);
   3107     event.data.lifecycle.action = kFreeMemory_ANPLifecycleAction;
   3108     GET_NATIVE_VIEW(env, obj)->sendPluginEvent(event);
   3109 }
   3110 
   3111 static void ProvideVisitedHistory(JNIEnv *env, jobject obj, jobject hist)
   3112 {
   3113     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   3114     LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
   3115 
   3116     jobjectArray array = static_cast<jobjectArray>(hist);
   3117 
   3118     jsize len = env->GetArrayLength(array);
   3119     for (jsize i = 0; i < len; i++) {
   3120         jstring item = static_cast<jstring>(env->GetObjectArrayElement(array, i));
   3121         const UChar* str = static_cast<const UChar*>(env->GetStringChars(item, NULL));
   3122         jsize len = env->GetStringLength(item);
   3123         viewImpl->addVisitedLink(str, len);
   3124         env->ReleaseStringChars(item, str);
   3125         env->DeleteLocalRef(item);
   3126     }
   3127 }
   3128 
   3129 // Notification from the UI thread that the plugin's full-screen surface has been discarded
   3130 static void FullScreenPluginHidden(JNIEnv* env, jobject obj, jint npp)
   3131 {
   3132     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
   3133     PluginWidgetAndroid* plugin = viewImpl->getPluginWidget((NPP)npp);
   3134     if (plugin)
   3135         plugin->exitFullScreen(false);
   3136 }
   3137 
   3138 static WebCore::IntRect jrect_to_webrect(JNIEnv* env, jobject obj)
   3139 {
   3140     int L, T, R, B;
   3141     GraphicsJNI::get_jrect(env, obj, &L, &T, &R, &B);
   3142     return WebCore::IntRect(L, T, R - L, B - T);
   3143 }
   3144 
   3145 static bool ValidNodeAndBounds(JNIEnv *env, jobject obj, int frame, int node,
   3146     jobject rect)
   3147 {
   3148     IntRect nativeRect = jrect_to_webrect(env, rect);
   3149     return GET_NATIVE_VIEW(env, obj)->validNodeAndBounds(
   3150             reinterpret_cast<Frame*>(frame),
   3151             reinterpret_cast<Node*>(node), nativeRect);
   3152 }
   3153 
   3154 // ----------------------------------------------------------------------------
   3155 
   3156 /*
   3157  * JNI registration.
   3158  */
   3159 static JNINativeMethod gJavaWebViewCoreMethods[] = {
   3160     { "nativeClearContent", "()V",
   3161         (void*) ClearContent },
   3162     { "nativeCopyContentToPicture", "(Landroid/graphics/Picture;)V",
   3163         (void*) CopyContentToPicture },
   3164     { "nativeDrawContent", "(Landroid/graphics/Canvas;I)Z",
   3165         (void*) DrawContent } ,
   3166     { "nativeFocusBoundsChanged", "()Z",
   3167         (void*) FocusBoundsChanged } ,
   3168     { "nativeKey", "(IIIZZZZ)Z",
   3169         (void*) Key },
   3170     { "nativeClick", "(II)V",
   3171         (void*) Click },
   3172     { "nativePictureReady", "()Z",
   3173         (void*) PictureReady } ,
   3174     { "nativeSendListBoxChoices", "([ZI)V",
   3175         (void*) SendListBoxChoices },
   3176     { "nativeSendListBoxChoice", "(I)V",
   3177         (void*) SendListBoxChoice },
   3178     { "nativeSetSize", "(IIIFIIIIZ)V",
   3179         (void*) SetSize },
   3180     { "nativeSetScrollOffset", "(III)V",
   3181         (void*) SetScrollOffset },
   3182     { "nativeSetGlobalBounds", "(IIII)V",
   3183         (void*) SetGlobalBounds },
   3184     { "nativeSetSelection", "(II)V",
   3185         (void*) SetSelection } ,
   3186     { "nativeDeleteSelection", "(III)V",
   3187         (void*) DeleteSelection } ,
   3188     { "nativeReplaceTextfieldText", "(IILjava/lang/String;III)V",
   3189         (void*) ReplaceTextfieldText } ,
   3190     { "nativeMoveFocus", "(II)V",
   3191         (void*) MoveFocus },
   3192     { "nativeMoveMouse", "(III)V",
   3193         (void*) MoveMouse },
   3194     { "nativeMoveMouseIfLatest", "(IIII)V",
   3195         (void*) MoveMouseIfLatest },
   3196     { "passToJs", "(ILjava/lang/String;IIZZZZ)V",
   3197         (void*) PassToJs },
   3198     { "nativeScrollFocusedTextInput", "(FI)V",
   3199         (void*) ScrollFocusedTextInput },
   3200     { "nativeSetFocusControllerActive", "(Z)V",
   3201         (void*) SetFocusControllerActive },
   3202     { "nativeSaveDocumentState", "(I)V",
   3203         (void*) SaveDocumentState },
   3204     { "nativeFindAddress", "(Ljava/lang/String;Z)Ljava/lang/String;",
   3205         (void*) FindAddress },
   3206     { "nativeHandleTouchEvent", "(IIII)Z",
   3207             (void*) HandleTouchEvent },
   3208     { "nativeTouchUp", "(IIIII)V",
   3209         (void*) TouchUp },
   3210     { "nativeRetrieveHref", "(II)Ljava/lang/String;",
   3211         (void*) RetrieveHref },
   3212     { "nativeRetrieveAnchorText", "(II)Ljava/lang/String;",
   3213         (void*) RetrieveAnchorText },
   3214     { "nativeUpdateFrameCache", "()V",
   3215         (void*) UpdateFrameCache },
   3216     { "nativeGetContentMinPrefWidth", "()I",
   3217         (void*) GetContentMinPrefWidth },
   3218     { "nativeRecordContent", "(Landroid/graphics/Region;Landroid/graphics/Point;)Z",
   3219         (void*) RecordContent },
   3220     { "setViewportSettingsFromNative", "()V",
   3221         (void*) SetViewportSettingsFromNative },
   3222     { "nativeSplitContent", "()V",
   3223         (void*) SplitContent },
   3224     { "nativeSetBackgroundColor", "(I)V",
   3225         (void*) SetBackgroundColor },
   3226     { "nativeRegisterURLSchemeAsLocal", "(Ljava/lang/String;)V",
   3227         (void*) RegisterURLSchemeAsLocal },
   3228     { "nativeDumpDomTree", "(Z)V",
   3229         (void*) DumpDomTree },
   3230     { "nativeDumpRenderTree", "(Z)V",
   3231         (void*) DumpRenderTree },
   3232     { "nativeDumpNavTree", "()V",
   3233         (void*) DumpNavTree },
   3234     { "nativeDumpV8Counters", "()V",
   3235         (void*) DumpV8Counters },
   3236     { "nativeSetNewStorageLimit", "(J)V",
   3237         (void*) SetNewStorageLimit },
   3238     { "nativeGeolocationPermissionsProvide", "(Ljava/lang/String;ZZ)V",
   3239         (void*) GeolocationPermissionsProvide },
   3240     { "nativePause", "()V", (void*) Pause },
   3241     { "nativeResume", "()V", (void*) Resume },
   3242     { "nativeFreeMemory", "()V", (void*) FreeMemory },
   3243     { "nativeSetJsFlags", "(Ljava/lang/String;)V", (void*) SetJsFlags },
   3244     { "nativeRequestLabel", "(II)Ljava/lang/String;",
   3245         (void*) RequestLabel },
   3246     { "nativeUpdateFrameCacheIfLoading", "()V",
   3247         (void*) UpdateFrameCacheIfLoading },
   3248     { "nativeProvideVisitedHistory", "([Ljava/lang/String;)V",
   3249         (void*) ProvideVisitedHistory },
   3250     { "nativeFullScreenPluginHidden", "(I)V",
   3251         (void*) FullScreenPluginHidden },
   3252     { "nativeValidNodeAndBounds", "(IILandroid/graphics/Rect;)Z",
   3253         (void*) ValidNodeAndBounds },
   3254 };
   3255 
   3256 int register_webviewcore(JNIEnv* env)
   3257 {
   3258     jclass widget = env->FindClass("android/webkit/WebViewCore");
   3259     LOG_ASSERT(widget,
   3260             "Unable to find class android/webkit/WebViewCore");
   3261     gWebViewCoreFields.m_nativeClass = env->GetFieldID(widget, "mNativeClass",
   3262             "I");
   3263     LOG_ASSERT(gWebViewCoreFields.m_nativeClass,
   3264             "Unable to find android/webkit/WebViewCore.mNativeClass");
   3265     gWebViewCoreFields.m_viewportWidth = env->GetFieldID(widget,
   3266             "mViewportWidth", "I");
   3267     LOG_ASSERT(gWebViewCoreFields.m_viewportWidth,
   3268             "Unable to find android/webkit/WebViewCore.mViewportWidth");
   3269     gWebViewCoreFields.m_viewportHeight = env->GetFieldID(widget,
   3270             "mViewportHeight", "I");
   3271     LOG_ASSERT(gWebViewCoreFields.m_viewportHeight,
   3272             "Unable to find android/webkit/WebViewCore.mViewportHeight");
   3273     gWebViewCoreFields.m_viewportInitialScale = env->GetFieldID(widget,
   3274             "mViewportInitialScale", "I");
   3275     LOG_ASSERT(gWebViewCoreFields.m_viewportInitialScale,
   3276             "Unable to find android/webkit/WebViewCore.mViewportInitialScale");
   3277     gWebViewCoreFields.m_viewportMinimumScale = env->GetFieldID(widget,
   3278             "mViewportMinimumScale", "I");
   3279     LOG_ASSERT(gWebViewCoreFields.m_viewportMinimumScale,
   3280             "Unable to find android/webkit/WebViewCore.mViewportMinimumScale");
   3281     gWebViewCoreFields.m_viewportMaximumScale = env->GetFieldID(widget,
   3282             "mViewportMaximumScale", "I");
   3283     LOG_ASSERT(gWebViewCoreFields.m_viewportMaximumScale,
   3284             "Unable to find android/webkit/WebViewCore.mViewportMaximumScale");
   3285     gWebViewCoreFields.m_viewportUserScalable = env->GetFieldID(widget,
   3286             "mViewportUserScalable", "Z");
   3287     LOG_ASSERT(gWebViewCoreFields.m_viewportUserScalable,
   3288             "Unable to find android/webkit/WebViewCore.mViewportUserScalable");
   3289     gWebViewCoreFields.m_viewportDensityDpi = env->GetFieldID(widget,
   3290             "mViewportDensityDpi", "I");
   3291     LOG_ASSERT(gWebViewCoreFields.m_viewportDensityDpi,
   3292             "Unable to find android/webkit/WebViewCore.mViewportDensityDpi");
   3293     gWebViewCoreFields.m_webView = env->GetFieldID(widget,
   3294             "mWebView", "Landroid/webkit/WebView;");
   3295     LOG_ASSERT(gWebViewCoreFields.m_webView,
   3296             "Unable to find android/webkit/WebViewCore.mWebView");
   3297 
   3298     return jniRegisterNativeMethods(env, "android/webkit/WebViewCore",
   3299             gJavaWebViewCoreMethods, NELEM(gJavaWebViewCoreMethods));
   3300 }
   3301 
   3302 } /* namespace android */
   3303