• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2007, 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 "webviewglue"
27 
28 #include "config.h"
29 
30 #include "AndroidAnimation.h"
31 #include "AndroidLog.h"
32 #include "AtomicString.h"
33 #include "CachedFrame.h"
34 #include "CachedNode.h"
35 #include "CachedRoot.h"
36 #include "CString.h"
37 #include "DrawExtra.h"
38 #include "FindCanvas.h"
39 #include "Frame.h"
40 #include "GraphicsJNI.h"
41 #include "HTMLInputElement.h"
42 #include "IntPoint.h"
43 #include "IntRect.h"
44 #include "LayerAndroid.h"
45 #include "Node.h"
46 #include "PlatformGraphicsContext.h"
47 #include "PlatformString.h"
48 #include "SelectText.h"
49 #include "SkCanvas.h"
50 #include "SkDumpCanvas.h"
51 #include "SkPicture.h"
52 #include "SkRect.h"
53 #include "SkTime.h"
54 #ifdef ANDROID_INSTRUMENT
55 #include "TimeCounter.h"
56 #endif
57 #include "WebCoreJni.h"
58 #include "WebViewCore.h"
59 #include "android_graphics.h"
60 
61 #ifdef GET_NATIVE_VIEW
62 #undef GET_NATIVE_VIEW
63 #endif
64 
65 #define GET_NATIVE_VIEW(env, obj) ((WebView*)env->GetIntField(obj, gWebViewField))
66 
67 #include <JNIUtility.h>
68 #include <JNIHelp.h>
69 #include <jni.h>
70 #include <ui/KeycodeLabels.h>
71 
72 namespace android {
73 
74 static jfieldID gWebViewField;
75 
76 //-------------------------------------
77 
GetJMethod(JNIEnv * env,jclass clazz,const char name[],const char signature[])78 static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[], const char signature[])
79 {
80     jmethodID m = env->GetMethodID(clazz, name, signature);
81     LOG_ASSERT(m, "Could not find method %s", name);
82     return m;
83 }
84 
85 //-------------------------------------
86 // This class provides JNI for making calls into native code from the UI side
87 // of the multi-threaded WebView.
88 class WebView
89 {
90 public:
91 enum FrameCachePermission {
92     DontAllowNewer,
93     AllowNewer,
94     AllowNewest
95 };
96 
97 enum DrawExtras { // keep this in sync with WebView.java
98     DrawExtrasNone = 0,
99     DrawExtrasFind = 1,
100     DrawExtrasSelection = 2,
101     DrawExtrasCursorRing = 3
102 };
103 
104 struct JavaGlue {
105     jweak       m_obj;
106     jmethodID   m_calcOurContentVisibleRectF;
107     jmethodID   m_clearTextEntry;
108     jmethodID   m_overrideLoading;
109     jmethodID   m_scrollBy;
110     jmethodID   m_sendMoveFocus;
111     jmethodID   m_sendMoveMouse;
112     jmethodID   m_sendMoveMouseIfLatest;
113     jmethodID   m_sendMotionUp;
114     jmethodID   m_domChangedFocus;
115     jmethodID   m_getScaledMaxXScroll;
116     jmethodID   m_getScaledMaxYScroll;
117     jmethodID   m_getVisibleRect;
118     jmethodID   m_rebuildWebTextView;
119     jmethodID   m_viewInvalidate;
120     jmethodID   m_viewInvalidateRect;
121     jmethodID   m_postInvalidateDelayed;
122     jfieldID    m_rectLeft;
123     jfieldID    m_rectTop;
124     jmethodID   m_rectWidth;
125     jmethodID   m_rectHeight;
126     jfieldID    m_rectFLeft;
127     jfieldID    m_rectFTop;
128     jmethodID   m_rectFWidth;
129     jmethodID   m_rectFHeight;
objectandroid::WebView::JavaGlue130     AutoJObject object(JNIEnv* env) {
131         return getRealObject(env, m_obj);
132     }
133 } m_javaGlue;
134 
WebView(JNIEnv * env,jobject javaWebView,int viewImpl)135 WebView(JNIEnv* env, jobject javaWebView, int viewImpl) :
136     m_ring((WebViewCore*) viewImpl)
137 {
138     jclass clazz = env->FindClass("android/webkit/WebView");
139  //   m_javaGlue = new JavaGlue;
140     m_javaGlue.m_obj = env->NewWeakGlobalRef(javaWebView);
141     m_javaGlue.m_scrollBy = GetJMethod(env, clazz, "setContentScrollBy", "(IIZ)Z");
142     m_javaGlue.m_calcOurContentVisibleRectF = GetJMethod(env, clazz, "calcOurContentVisibleRectF", "(Landroid/graphics/RectF;)V");
143     m_javaGlue.m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "(Z)V");
144     m_javaGlue.m_overrideLoading = GetJMethod(env, clazz, "overrideLoading", "(Ljava/lang/String;)V");
145     m_javaGlue.m_sendMoveFocus = GetJMethod(env, clazz, "sendMoveFocus", "(II)V");
146     m_javaGlue.m_sendMoveMouse = GetJMethod(env, clazz, "sendMoveMouse", "(IIII)V");
147     m_javaGlue.m_sendMoveMouseIfLatest = GetJMethod(env, clazz, "sendMoveMouseIfLatest", "(Z)V");
148     m_javaGlue.m_sendMotionUp = GetJMethod(env, clazz, "sendMotionUp", "(IIIII)V");
149     m_javaGlue.m_domChangedFocus = GetJMethod(env, clazz, "domChangedFocus", "()V");
150     m_javaGlue.m_getScaledMaxXScroll = GetJMethod(env, clazz, "getScaledMaxXScroll", "()I");
151     m_javaGlue.m_getScaledMaxYScroll = GetJMethod(env, clazz, "getScaledMaxYScroll", "()I");
152     m_javaGlue.m_getVisibleRect = GetJMethod(env, clazz, "sendOurVisibleRect", "()Landroid/graphics/Rect;");
153     m_javaGlue.m_rebuildWebTextView = GetJMethod(env, clazz, "rebuildWebTextView", "()V");
154     m_javaGlue.m_viewInvalidate = GetJMethod(env, clazz, "viewInvalidate", "()V");
155     m_javaGlue.m_viewInvalidateRect = GetJMethod(env, clazz, "viewInvalidate", "(IIII)V");
156     m_javaGlue.m_postInvalidateDelayed = GetJMethod(env, clazz,
157         "viewInvalidateDelayed", "(JIIII)V");
158     jclass rectClass = env->FindClass("android/graphics/Rect");
159     LOG_ASSERT(rectClass, "Could not find Rect class");
160     m_javaGlue.m_rectLeft = env->GetFieldID(rectClass, "left", "I");
161     m_javaGlue.m_rectTop = env->GetFieldID(rectClass, "top", "I");
162     m_javaGlue.m_rectWidth = GetJMethod(env, rectClass, "width", "()I");
163     m_javaGlue.m_rectHeight = GetJMethod(env, rectClass, "height", "()I");
164     jclass rectClassF = env->FindClass("android/graphics/RectF");
165     LOG_ASSERT(rectClassF, "Could not find RectF class");
166     m_javaGlue.m_rectFLeft = env->GetFieldID(rectClassF, "left", "F");
167     m_javaGlue.m_rectFTop = env->GetFieldID(rectClassF, "top", "F");
168     m_javaGlue.m_rectFWidth = GetJMethod(env, rectClassF, "width", "()F");
169     m_javaGlue.m_rectFHeight = GetJMethod(env, rectClassF, "height", "()F");
170     env->SetIntField(javaWebView, gWebViewField, (jint)this);
171     m_viewImpl = (WebViewCore*) viewImpl;
172     m_frameCacheUI = 0;
173     m_navPictureUI = 0;
174     m_generation = 0;
175     m_heightCanMeasure = false;
176     m_ring.m_followedLink = false;
177     m_lastDx = 0;
178     m_lastDxTime = 0;
179     m_ringAnimationEnd = 0;
180     m_rootLayer = 0;
181 }
182 
~WebView()183 ~WebView()
184 {
185     if (m_javaGlue.m_obj)
186     {
187         JNIEnv* env = JSC::Bindings::getJNIEnv();
188         env->DeleteWeakGlobalRef(m_javaGlue.m_obj);
189         m_javaGlue.m_obj = 0;
190     }
191     delete m_frameCacheUI;
192     delete m_navPictureUI;
193     delete m_rootLayer;
194 }
195 
getWebViewCore() const196 WebViewCore* getWebViewCore() const {
197     return m_viewImpl;
198 }
199 
200 // removes the cursor altogether (e.g., when going to a new page)
clearCursor()201 void clearCursor()
202 {
203     CachedRoot* root = getFrameCache(AllowNewer);
204     if (!root)
205         return;
206     DBG_NAV_LOG("");
207     m_viewImpl->m_hasCursorBounds = false;
208     root->clearCursor();
209     viewInvalidate();
210 }
211 
212 // leaves the cursor where it is, but suppresses drawing it
hideCursor()213 void hideCursor()
214 {
215     CachedRoot* root = getFrameCache(AllowNewer);
216     if (!root)
217         return;
218     DBG_NAV_LOG("");
219     m_viewImpl->m_hasCursorBounds = false;
220     root->hideCursor();
221     viewInvalidate();
222 }
223 
clearTextEntry()224 void clearTextEntry()
225 {
226     DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
227     JNIEnv* env = JSC::Bindings::getJNIEnv();
228     env->CallVoidMethod(m_javaGlue.object(env).get(),
229         m_javaGlue.m_clearTextEntry, true);
230     checkException(env);
231 }
232 
233 #if DUMP_NAV_CACHE
debugDump()234 void debugDump()
235 {
236     CachedRoot* root = getFrameCache(DontAllowNewer);
237     if (root)
238         root->mDebug.print();
239 }
240 #endif
241 
242 // Traverse our stored array of buttons that are in our picture, and update
243 // their subpictures according to their current state.
244 // Called from the UI thread.  This is the one place in the UI thread where we
245 // access the buttons stored in the WebCore thread.
246 // hasFocus keeps track of whether the WebView has focus && windowFocus.
247 // If not, we do not want to draw the button in a selected or pressed state
nativeRecordButtons(bool hasFocus,bool pressed,bool invalidate)248 void nativeRecordButtons(bool hasFocus, bool pressed, bool invalidate)
249 {
250     bool cursorIsOnButton = false;
251     const CachedFrame* cachedFrame;
252     const CachedNode* cachedCursor = 0;
253     // Lock the mutex, since we now share with the WebCore thread.
254     m_viewImpl->gButtonMutex.lock();
255     if (m_viewImpl->m_buttons.size()) {
256         // FIXME: In a future change, we should keep track of whether the selection
257         // has changed to short circuit (note that we would still need to update
258         // if we received new buttons from the WebCore thread).
259         WebCore::Node* cursor = 0;
260         CachedRoot* root = getFrameCache(DontAllowNewer);
261         if (root) {
262             cachedCursor = root->currentCursor(&cachedFrame);
263             if (cachedCursor)
264                 cursor = (WebCore::Node*) cachedCursor->nodePointer();
265         }
266 
267         // Traverse the array, and update each button, depending on whether it
268         // is selected.
269         Container* end = m_viewImpl->m_buttons.end();
270         for (Container* ptr = m_viewImpl->m_buttons.begin(); ptr != end; ptr++) {
271             WebCore::RenderSkinAndroid::State state;
272             if (ptr->matches(cursor)) {
273                 cursorIsOnButton = true;
274                 // If the WebView is out of focus/window focus, set the state to
275                 // normal, but still keep track of the fact that the selected is a
276                 // button
277                 if (!hasFocus) {
278                     state = WebCore::RenderSkinAndroid::kNormal;
279                 } else if (m_ring.m_followedLink || pressed) {
280                     state = WebCore::RenderSkinAndroid::kPressed;
281                 } else {
282                     state = WebCore::RenderSkinAndroid::kFocused;
283                 }
284             } else {
285                 state = WebCore::RenderSkinAndroid::kNormal;
286             }
287             ptr->updateFocusState(state);
288         }
289     }
290     m_viewImpl->gButtonMutex.unlock();
291     if (invalidate && cachedCursor && cursorIsOnButton) {
292         const WebCore::IntRect& b = cachedCursor->bounds(cachedFrame);
293         viewInvalidateRect(b.x(), b.y(), b.right(), b.bottom());
294     }
295 }
296 
297 // The caller has already determined that the desired document rect corresponds
298 // to the main picture, and not a layer
scrollRectOnScreen(const IntRect & rect)299 void scrollRectOnScreen(const IntRect& rect)
300 {
301     if (rect.isEmpty())
302         return;
303     SkRect visible;
304     calcOurContentVisibleRect(&visible);
305 #if USE(ACCELERATED_COMPOSITING)
306     if (m_rootLayer) {
307         m_rootLayer->updateFixedLayersPositions(visible);
308         m_rootLayer->updatePositions();
309         visible = m_rootLayer->subtractLayers(visible);
310     }
311 #endif
312     int dx = 0;
313     int left = rect.x();
314     int right = rect.right();
315     if (left < visible.fLeft) {
316         dx = left - visible.fLeft;
317     // Only scroll right if the entire width can fit on screen.
318     } else if (right > visible.fRight && right - left < visible.width()) {
319         dx = right - visible.fRight;
320     }
321     int dy = 0;
322     int top = rect.y();
323     int bottom = rect.bottom();
324     if (top < visible.fTop) {
325         dy = top - visible.fTop;
326     // Only scroll down if the entire height can fit on screen
327     } else if (bottom > visible.fBottom && bottom - top < visible.height()) {
328         dy = bottom - visible.fBottom;
329     }
330     if ((dx|dy) == 0 || !scrollBy(dx, dy))
331         return;
332     viewInvalidate();
333 }
334 
calcOurContentVisibleRect(SkRect * r)335 void calcOurContentVisibleRect(SkRect* r)
336 {
337     JNIEnv* env = JSC::Bindings::getJNIEnv();
338     jclass rectClass = env->FindClass("android/graphics/RectF");
339     jmethodID init = env->GetMethodID(rectClass, "<init>", "(FFFF)V");
340     jobject jRect = env->NewObject(rectClass, init, 0, 0, 0, 0);
341     env->CallVoidMethod(m_javaGlue.object(env).get(),
342         m_javaGlue.m_calcOurContentVisibleRectF, jRect);
343     r->fLeft = env->GetFloatField(jRect, m_javaGlue.m_rectFLeft);
344     r->fTop = env->GetFloatField(jRect, m_javaGlue.m_rectFTop);
345     r->fRight = r->fLeft + env->CallFloatMethod(jRect, m_javaGlue.m_rectFWidth);
346     r->fBottom = r->fTop + env->CallFloatMethod(jRect, m_javaGlue.m_rectFHeight);
347     env->DeleteLocalRef(jRect);
348     checkException(env);
349 }
350 
resetCursorRing()351 void resetCursorRing()
352 {
353     m_ring.m_followedLink = false;
354     m_viewImpl->m_hasCursorBounds = false;
355 }
356 
drawCursorPreamble(CachedRoot * root)357 bool drawCursorPreamble(CachedRoot* root)
358 {
359     const CachedFrame* frame;
360     const CachedNode* node = root->currentCursor(&frame);
361     if (!node) {
362         DBG_NAV_LOGV("%s", "!node");
363         resetCursorRing();
364         return false;
365     }
366     if (node->isHidden()) {
367         DBG_NAV_LOG("node->isHidden()");
368         m_viewImpl->m_hasCursorBounds = false;
369         return false;
370     }
371     setVisibleRect(root);
372     m_ring.m_root = root;
373     m_ring.m_frame = frame;
374     m_ring.m_node = node;
375     return true;
376 }
377 
drawCursorPostamble()378 void drawCursorPostamble()
379 {
380     if (!m_ring.m_isButton && m_ring.m_flavor < CursorRing::NORMAL_ANIMATING)
381         return;
382     SkMSec time = SkTime::GetMSecs();
383     if (time < m_ringAnimationEnd) {
384         // views assume that inval bounds coordinates are non-negative
385         WebCore::IntRect invalBounds(0, 0, INT_MAX, INT_MAX);
386         invalBounds.intersect(m_ring.m_bounds);
387         postInvalidateDelayed(m_ringAnimationEnd - time, invalBounds);
388     } else {
389         if (m_ring.m_followedLink)
390             hideCursor();
391         m_ring.m_followedLink = false;
392         m_ring.m_flavor = static_cast<CursorRing::Flavor>
393                 (m_ring.m_flavor - CursorRing::NORMAL_ANIMATING);
394     }
395 }
396 
drawExtras(SkCanvas * canvas,int extras)397 void drawExtras(SkCanvas* canvas, int extras)
398 {
399     CachedRoot* root = getFrameCache(AllowNewer);
400     if (!root) {
401         DBG_NAV_LOG("!root");
402         if (extras == DrawExtrasCursorRing)
403             resetCursorRing();
404         return;
405     }
406     LayerAndroid mainPicture(m_navPictureUI);
407     DrawExtra* extra = 0;
408     switch (extras) {
409         case DrawExtrasFind:
410             extra = &m_findOnPage;
411             break;
412         case DrawExtrasSelection:
413             extra = &m_selectText;
414             break;
415         case DrawExtrasCursorRing:
416             if (drawCursorPreamble(root) && m_ring.setup()) {
417                 if (!m_ring.m_isButton)
418                     extra = &m_ring;
419                 drawCursorPostamble();
420             }
421             break;
422         default:
423             ;
424     }
425     if (extra)
426         extra->draw(canvas, &mainPicture);
427 #if USE(ACCELERATED_COMPOSITING)
428     if (!m_rootLayer)
429         return;
430     m_rootLayer->setExtra(extra);
431     SkRect visible;
432     calcOurContentVisibleRect(&visible);
433     // call this to be sure we've adjusted for any scrolling or animations
434     // before we actually draw
435     m_rootLayer->updateFixedLayersPositions(visible);
436     m_rootLayer->updatePositions();
437     // We have to set the canvas' matrix on the root layer
438     // (to have fixed layers work as intended)
439     SkAutoCanvasRestore restore(canvas, true);
440     m_rootLayer->setMatrix(canvas->getTotalMatrix());
441     canvas->resetMatrix();
442     m_rootLayer->draw(canvas);
443 #endif
444 }
445 
446 
cursorIsTextInput(FrameCachePermission allowNewer)447 bool cursorIsTextInput(FrameCachePermission allowNewer)
448 {
449     CachedRoot* root = getFrameCache(allowNewer);
450     if (!root) {
451         DBG_NAV_LOG("!root");
452         return false;
453     }
454     const CachedNode* cursor = root->currentCursor();
455     if (!cursor) {
456         DBG_NAV_LOG("!cursor");
457         return false;
458     }
459     DBG_NAV_LOGD("%s", cursor->isTextInput() ? "true" : "false");
460     return cursor->isTextInput();
461 }
462 
cursorRingBounds(WebCore::IntRect * bounds)463 void cursorRingBounds(WebCore::IntRect* bounds)
464 {
465     DBG_NAV_LOGD("%s", "");
466     CachedRoot* root = getFrameCache(DontAllowNewer);
467     if (root) {
468         const CachedFrame* cachedFrame;
469         const CachedNode* cachedNode = root->currentCursor(&cachedFrame);
470         if (cachedNode) {
471             *bounds = cachedNode->cursorRingBounds(cachedFrame);
472             DBG_NAV_LOGD("bounds={%d,%d,%d,%d}", bounds->x(), bounds->y(),
473                 bounds->width(), bounds->height());
474             return;
475         }
476     }
477     *bounds = WebCore::IntRect(0, 0, 0, 0);
478 }
479 
fixCursor()480 void fixCursor()
481 {
482     m_viewImpl->gCursorBoundsMutex.lock();
483     bool hasCursorBounds = m_viewImpl->m_hasCursorBounds;
484     IntRect bounds = m_viewImpl->m_cursorBounds;
485     m_viewImpl->gCursorBoundsMutex.unlock();
486     if (!hasCursorBounds)
487         return;
488     int x, y;
489     const CachedFrame* frame;
490     const CachedNode* node = m_frameCacheUI->findAt(bounds, &frame, &x, &y, false);
491     if (!node)
492         return;
493     // require that node have approximately the same bounds (+/- 4) and the same
494     // center (+/- 2)
495     IntPoint oldCenter = IntPoint(bounds.x() + (bounds.width() >> 1),
496         bounds.y() + (bounds.height() >> 1));
497     IntRect newBounds = node->bounds(frame);
498     IntPoint newCenter = IntPoint(newBounds.x() + (newBounds.width() >> 1),
499         newBounds.y() + (newBounds.height() >> 1));
500     DBG_NAV_LOGD("oldCenter=(%d,%d) newCenter=(%d,%d)"
501         " bounds=(%d,%d,w=%d,h=%d) newBounds=(%d,%d,w=%d,h=%d)",
502         oldCenter.x(), oldCenter.y(), newCenter.x(), newCenter.y(),
503         bounds.x(), bounds.y(), bounds.width(), bounds.height(),
504         newBounds.x(), newBounds.y(), newBounds.width(), newBounds.height());
505     if (abs(oldCenter.x() - newCenter.x()) > 2)
506         return;
507     if (abs(oldCenter.y() - newCenter.y()) > 2)
508         return;
509     if (abs(bounds.x() - newBounds.x()) > 4)
510         return;
511     if (abs(bounds.y() - newBounds.y()) > 4)
512         return;
513     if (abs(bounds.right() - newBounds.right()) > 4)
514         return;
515     if (abs(bounds.bottom() - newBounds.bottom()) > 4)
516         return;
517     DBG_NAV_LOGD("node=%p frame=%p x=%d y=%d bounds=(%d,%d,w=%d,h=%d)",
518         node, frame, x, y, bounds.x(), bounds.y(), bounds.width(),
519         bounds.height());
520     m_frameCacheUI->setCursor(const_cast<CachedFrame*>(frame),
521         const_cast<CachedNode*>(node));
522 }
523 
getFrameCache(FrameCachePermission allowNewer)524 CachedRoot* getFrameCache(FrameCachePermission allowNewer)
525 {
526     if (!m_viewImpl->m_updatedFrameCache) {
527         DBG_NAV_LOGV("%s", "!m_viewImpl->m_updatedFrameCache");
528         return m_frameCacheUI;
529     }
530     if (allowNewer == DontAllowNewer && m_viewImpl->m_lastGeneration < m_generation) {
531         DBG_NAV_LOGD("allowNewer==DontAllowNewer m_viewImpl->m_lastGeneration=%d"
532             " < m_generation=%d", m_viewImpl->m_lastGeneration, m_generation);
533         return m_frameCacheUI;
534     }
535     DBG_NAV_LOGD("%s", "m_viewImpl->m_updatedFrameCache == true");
536     const CachedFrame* oldCursorFrame;
537     const CachedNode* oldCursorNode = m_frameCacheUI ?
538         m_frameCacheUI->currentCursor(&oldCursorFrame) : 0;
539 #if USE(ACCELERATED_COMPOSITING)
540     int layerId = -1;
541     if (oldCursorNode && oldCursorNode->isInLayer()) {
542         const LayerAndroid* cursorLayer = oldCursorFrame->layer(oldCursorNode)
543             ->layer(m_frameCacheUI->rootLayer());
544         if (cursorLayer)
545             layerId = cursorLayer->uniqueId();
546     }
547 #endif
548     // get id from old layer and use to find new layer
549     bool oldFocusIsTextInput = false;
550     void* oldFocusNodePointer = 0;
551     if (m_frameCacheUI) {
552         const CachedNode* oldFocus = m_frameCacheUI->currentFocus();
553         if (oldFocus) {
554             oldFocusIsTextInput = oldFocus->isTextInput();
555             oldFocusNodePointer = oldFocus->nodePointer();
556         }
557     }
558     m_viewImpl->gFrameCacheMutex.lock();
559     delete m_frameCacheUI;
560     delete m_navPictureUI;
561     m_viewImpl->m_updatedFrameCache = false;
562     m_frameCacheUI = m_viewImpl->m_frameCacheKit;
563     m_navPictureUI = m_viewImpl->m_navPictureKit;
564     m_viewImpl->m_frameCacheKit = 0;
565     m_viewImpl->m_navPictureKit = 0;
566     m_viewImpl->gFrameCacheMutex.unlock();
567     if (m_frameCacheUI)
568         m_frameCacheUI->setRootLayer(m_rootLayer);
569 #if USE(ACCELERATED_COMPOSITING)
570     if (layerId >= 0) {
571         SkRect visible;
572         calcOurContentVisibleRect(&visible);
573         LayerAndroid* layer = const_cast<LayerAndroid*>(
574                                                 m_frameCacheUI->rootLayer());
575         if (layer) {
576             layer->updateFixedLayersPositions(visible);
577             layer->updatePositions();
578         }
579     }
580 #endif
581     fixCursor();
582     if (oldFocusIsTextInput) {
583         const CachedNode* newFocus = m_frameCacheUI->currentFocus();
584         if (newFocus && oldFocusNodePointer != newFocus->nodePointer()
585                 && newFocus->isTextInput()
586                 && newFocus != m_frameCacheUI->currentCursor()) {
587             // The focus has changed.  We may need to update things.
588             LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
589             JNIEnv* env = JSC::Bindings::getJNIEnv();
590             env->CallVoidMethod(m_javaGlue.object(env).get(),
591                     m_javaGlue.m_domChangedFocus);
592             checkException(env);
593         }
594     }
595     if (oldCursorNode && (!m_frameCacheUI || !m_frameCacheUI->currentCursor()))
596         viewInvalidate(); // redraw in case cursor ring is still visible
597     return m_frameCacheUI;
598 }
599 
getScaledMaxXScroll()600 int getScaledMaxXScroll()
601 {
602     LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
603     JNIEnv* env = JSC::Bindings::getJNIEnv();
604     int result = env->CallIntMethod(m_javaGlue.object(env).get(), m_javaGlue.m_getScaledMaxXScroll);
605     checkException(env);
606     return result;
607 }
608 
getScaledMaxYScroll()609 int getScaledMaxYScroll()
610 {
611     LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
612     JNIEnv* env = JSC::Bindings::getJNIEnv();
613     int result = env->CallIntMethod(m_javaGlue.object(env).get(), m_javaGlue.m_getScaledMaxYScroll);
614     checkException(env);
615     return result;
616 }
617 
getVisibleRect(WebCore::IntRect * rect)618 void getVisibleRect(WebCore::IntRect* rect)
619 {
620     LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
621     JNIEnv* env = JSC::Bindings::getJNIEnv();
622     jobject jRect = env->CallObjectMethod(m_javaGlue.object(env).get(), m_javaGlue.m_getVisibleRect);
623     checkException(env);
624     int left = (int) env->GetIntField(jRect, m_javaGlue.m_rectLeft);
625     checkException(env);
626     rect->setX(left);
627     int top = (int) env->GetIntField(jRect, m_javaGlue.m_rectTop);
628     checkException(env);
629     rect->setY(top);
630     int width = (int) env->CallIntMethod(jRect, m_javaGlue.m_rectWidth);
631     checkException(env);
632     rect->setWidth(width);
633     int height = (int) env->CallIntMethod(jRect, m_javaGlue.m_rectHeight);
634     checkException(env);
635     rect->setHeight(height);
636     env->DeleteLocalRef(jRect);
637     checkException(env);
638 }
639 
KeyToDirection(int32_t keyCode)640 static CachedFrame::Direction KeyToDirection(int32_t keyCode)
641 {
642     switch (keyCode) {
643         case AKEYCODE_DPAD_RIGHT:
644             DBG_NAV_LOGD("keyCode=%s", "right");
645             return CachedFrame::RIGHT;
646         case AKEYCODE_DPAD_LEFT:
647             DBG_NAV_LOGD("keyCode=%s", "left");
648             return CachedFrame::LEFT;
649         case AKEYCODE_DPAD_DOWN:
650             DBG_NAV_LOGD("keyCode=%s", "down");
651             return CachedFrame::DOWN;
652         case AKEYCODE_DPAD_UP:
653             DBG_NAV_LOGD("keyCode=%s", "up");
654             return CachedFrame::UP;
655         default:
656             DBG_NAV_LOGD("bad key %d sent", keyCode);
657             return CachedFrame::UNINITIALIZED;
658     }
659 }
660 
imageURI(int x,int y)661 WebCore::String imageURI(int x, int y)
662 {
663     const CachedRoot* root = getFrameCache(DontAllowNewer);
664     return root ? root->imageURI(x, y) : WebCore::String();
665 }
666 
cursorWantsKeyEvents()667 bool cursorWantsKeyEvents()
668 {
669     const CachedRoot* root = getFrameCache(DontAllowNewer);
670     if (root) {
671         const CachedNode* focus = root->currentCursor();
672         if (focus)
673             return focus->wantsKeyEvents();
674     }
675     return false;
676 }
677 
678 
679 /* returns true if the key had no effect (neither scrolled nor changed cursor) */
moveCursor(int keyCode,int count,bool ignoreScroll)680 bool moveCursor(int keyCode, int count, bool ignoreScroll)
681 {
682     CachedRoot* root = getFrameCache(AllowNewer);
683     if (!root) {
684         DBG_NAV_LOG("!root");
685         return true;
686     }
687 
688     m_viewImpl->m_moveGeneration++;
689     CachedFrame::Direction direction = KeyToDirection(keyCode);
690     const CachedFrame* cachedFrame, * oldFrame = 0;
691     const CachedNode* cursor = root->currentCursor(&oldFrame);
692     WebCore::IntPoint cursorLocation = root->cursorLocation();
693     DBG_NAV_LOGD("old cursor %d (nativeNode=%p) cursorLocation={%d, %d}",
694         cursor ? cursor->index() : 0,
695         cursor ? cursor->nodePointer() : 0, cursorLocation.x(), cursorLocation.y());
696     WebCore::IntRect visibleRect = setVisibleRect(root);
697     int xMax = getScaledMaxXScroll();
698     int yMax = getScaledMaxYScroll();
699     root->setMaxScroll(xMax, yMax);
700     const CachedNode* cachedNode = 0;
701     int dx = 0;
702     int dy = 0;
703     int counter = count;
704     if (!cursor || !m_ring.m_followedLink)
705         root->setScrollOnly(m_ring.m_followedLink);
706     while (--counter >= 0) {
707         WebCore::IntPoint scroll = WebCore::IntPoint(0, 0);
708         cachedNode = root->moveCursor(direction, &cachedFrame, &scroll);
709         dx += scroll.x();
710         dy += scroll.y();
711     }
712     DBG_NAV_LOGD("new cursor %d (nativeNode=%p) cursorLocation={%d, %d}"
713         "bounds={%d,%d,w=%d,h=%d}", cachedNode ? cachedNode->index() : 0,
714         cachedNode ? cachedNode->nodePointer() : 0,
715             root->cursorLocation().x(), root->cursorLocation().y(),
716             cachedNode ? cachedNode->bounds(cachedFrame).x() : 0,
717             cachedNode ? cachedNode->bounds(cachedFrame).y() : 0,
718             cachedNode ? cachedNode->bounds(cachedFrame).width() : 0,
719             cachedNode ? cachedNode->bounds(cachedFrame).height() : 0);
720     // If !m_heightCanMeasure (such as in the browser), we want to scroll no
721     // matter what
722     if (!ignoreScroll && (!m_heightCanMeasure ||
723             !cachedNode ||
724             (cursor && cursor->nodePointer() == cachedNode->nodePointer())))
725     {
726         if (count == 1 && dx != 0 && dy == 0 && -m_lastDx == dx &&
727                 SkTime::GetMSecs() - m_lastDxTime < 1000)
728             root->checkForJiggle(&dx);
729         DBG_NAV_LOGD("scrollBy %d,%d", dx, dy);
730         if ((dx | dy))
731             this->scrollBy(dx, dy);
732         m_lastDx = dx;
733         m_lastDxTime = SkTime::GetMSecs();
734     }
735     bool result = false;
736     if (cachedNode) {
737         m_viewImpl->updateCursorBounds(root, cachedFrame, cachedNode);
738         root->setCursor(const_cast<CachedFrame*>(cachedFrame),
739                 const_cast<CachedNode*>(cachedNode));
740         bool disableFocusController = cachedNode != root->currentFocus()
741                 && cachedNode->wantsKeyEvents();
742         sendMoveMouseIfLatest(disableFocusController);
743         viewInvalidate();
744     } else {
745         int docHeight = root->documentHeight();
746         int docWidth = root->documentWidth();
747         if (visibleRect.bottom() + dy > docHeight)
748             dy = docHeight - visibleRect.bottom();
749         else if (visibleRect.y() + dy < 0)
750             dy = -visibleRect.y();
751         if (visibleRect.right() + dx > docWidth)
752             dx = docWidth - visibleRect.right();
753         else if (visibleRect.x() < 0)
754             dx = -visibleRect.x();
755         result = direction == CachedFrame::LEFT ? dx >= 0 :
756             direction == CachedFrame::RIGHT ? dx <= 0 :
757             direction == CachedFrame::UP ? dy >= 0 : dy <= 0;
758     }
759     return result;
760 }
761 
notifyProgressFinished()762 void notifyProgressFinished()
763 {
764     DBG_NAV_LOGD("cursorIsTextInput=%d", cursorIsTextInput(DontAllowNewer));
765     rebuildWebTextView();
766 #if DEBUG_NAV_UI
767     if (m_frameCacheUI) {
768         const CachedNode* focus = m_frameCacheUI->currentFocus();
769         DBG_NAV_LOGD("focus %d (nativeNode=%p)",
770             focus ? focus->index() : 0,
771             focus ? focus->nodePointer() : 0);
772     }
773 #endif
774 }
775 
findAt(CachedRoot * root,const WebCore::IntRect & rect,const CachedFrame ** framePtr,int * rxPtr,int * ryPtr)776 const CachedNode* findAt(CachedRoot* root, const WebCore::IntRect& rect,
777     const CachedFrame** framePtr, int* rxPtr, int* ryPtr)
778 {
779     *rxPtr = 0;
780     *ryPtr = 0;
781     *framePtr = 0;
782     if (!root)
783         return 0;
784     setVisibleRect(root);
785     return root->findAt(rect, framePtr, rxPtr, ryPtr, true);
786 }
787 
setVisibleRect(CachedRoot * root)788 IntRect setVisibleRect(CachedRoot* root)
789 {
790     IntRect visibleRect;
791     getVisibleRect(&visibleRect);
792     DBG_NAV_LOGD("getVisibleRect %d,%d,%d,%d",
793         visibleRect.x(), visibleRect.y(), visibleRect.width(), visibleRect.height());
794     root->setVisibleRect(visibleRect);
795     return visibleRect;
796 }
797 
selectBestAt(const WebCore::IntRect & rect)798 void selectBestAt(const WebCore::IntRect& rect)
799 {
800     const CachedFrame* frame;
801     int rx, ry;
802     CachedRoot* root = getFrameCache(DontAllowNewer);
803     const CachedNode* node = findAt(root, rect, &frame, &rx, &ry);
804 
805     if (!node) {
806         DBG_NAV_LOGD("no nodes found root=%p", root);
807         m_viewImpl->m_hasCursorBounds = false;
808         if (root)
809             root->setCursor(0, 0);
810     } else {
811         DBG_NAV_LOGD("CachedNode:%p (%d)", node, node->index());
812         root->rootHistory()->setMouseBounds(node->bounds(frame));
813         m_viewImpl->updateCursorBounds(root, frame, node);
814         root->setCursor(const_cast<CachedFrame*>(frame),
815                 const_cast<CachedNode*>(node));
816     }
817     sendMoveMouseIfLatest(false);
818     viewInvalidate();
819 }
820 
getNavBounds()821 WebCore::IntRect getNavBounds()
822 {
823     CachedRoot* root = getFrameCache(DontAllowNewer);
824     return root ? root->rootHistory()->navBounds() :
825         WebCore::IntRect(0, 0, 0, 0);
826 }
827 
setNavBounds(const WebCore::IntRect & rect)828 void setNavBounds(const WebCore::IntRect& rect)
829 {
830     CachedRoot* root = getFrameCache(DontAllowNewer);
831     if (!root)
832         return;
833     root->rootHistory()->setNavBounds(rect);
834 }
835 
836 
837 
838 const CachedNode* m_cacheHitNode;
839 const CachedFrame* m_cacheHitFrame;
840 
pointInNavCache(int x,int y,int slop)841 bool pointInNavCache(int x, int y, int slop)
842 {
843     CachedRoot* root = getFrameCache(AllowNewer);
844     if (!root)
845         return false;
846     IntRect rect = IntRect(x - slop, y - slop, slop * 2, slop * 2);
847     int rx, ry;
848     return (m_cacheHitNode = findAt(root, rect, &m_cacheHitFrame, &rx, &ry));
849 }
850 
motionUp(int x,int y,int slop)851 bool motionUp(int x, int y, int slop)
852 {
853     bool pageScrolled = false;
854     m_ring.m_followedLink = false;
855     IntRect rect = IntRect(x - slop, y - slop, slop * 2, slop * 2);
856     int rx, ry;
857     CachedRoot* root = getFrameCache(AllowNewer);
858     if (!root)
859         return 0;
860     const CachedFrame* frame = 0;
861     const CachedNode* result = findAt(root, rect, &frame, &rx, &ry);
862     if (!result) {
863         DBG_NAV_LOGD("no nodes found root=%p", root);
864         setNavBounds(rect);
865         m_viewImpl->m_hasCursorBounds = false;
866         root->hideCursor();
867         int dx = root->checkForCenter(x, y);
868         if (dx) {
869             scrollBy(dx, 0);
870             pageScrolled = true;
871         }
872         sendMotionUp(frame ? (WebCore::Frame*) frame->framePointer() : 0,
873             0, x, y);
874         viewInvalidate();
875         clearTextEntry();
876         return pageScrolled;
877     }
878     DBG_NAV_LOGD("CachedNode:%p (%d) x=%d y=%d rx=%d ry=%d", result,
879         result->index(), x, y, rx, ry);
880     WebCore::IntRect navBounds = WebCore::IntRect(rx, ry, 1, 1);
881     setNavBounds(navBounds);
882     root->rootHistory()->setMouseBounds(navBounds);
883     m_viewImpl->updateCursorBounds(root, frame, result);
884     root->setCursor(const_cast<CachedFrame*>(frame),
885         const_cast<CachedNode*>(result));
886     bool syntheticLink = result->isSyntheticLink();
887     if (!syntheticLink) {
888         sendMotionUp(
889             (WebCore::Frame*) frame->framePointer(),
890             (WebCore::Node*) result->nodePointer(), rx, ry);
891     }
892     viewInvalidate();
893     if (!result->isTextInput()) {
894         clearTextEntry();
895         setFollowedLink(true);
896         if (syntheticLink)
897             overrideUrlLoading(result->getExport());
898     }
899     return pageScrolled;
900 }
901 
getBlockLeftEdge(int x,int y,float scale)902 int getBlockLeftEdge(int x, int y, float scale)
903 {
904     CachedRoot* root = getFrameCache(AllowNewer);
905     if (root)
906         return root->getBlockLeftEdge(x, y, scale);
907     return -1;
908 }
909 
overrideUrlLoading(const WebCore::String & url)910 void overrideUrlLoading(const WebCore::String& url)
911 {
912     JNIEnv* env = JSC::Bindings::getJNIEnv();
913     jstring jName = env->NewString((jchar*) url.characters(), url.length());
914     env->CallVoidMethod(m_javaGlue.object(env).get(),
915             m_javaGlue.m_overrideLoading, jName);
916     env->DeleteLocalRef(jName);
917 }
918 
setFindIsUp(bool up)919 void setFindIsUp(bool up)
920 {
921     DBG_NAV_LOGD("up=%d", up);
922     m_viewImpl->m_findIsUp = up;
923 }
924 
setFindIsEmpty()925 void setFindIsEmpty()
926 {
927     DBG_NAV_LOG("");
928     m_findOnPage.clearCurrentLocation();
929 }
930 
setFollowedLink(bool followed)931 void setFollowedLink(bool followed)
932 {
933     if ((m_ring.m_followedLink = followed) != false) {
934         m_ringAnimationEnd = SkTime::GetMSecs() + 500;
935         viewInvalidate();
936     }
937 }
938 
setHeightCanMeasure(bool measure)939 void setHeightCanMeasure(bool measure)
940 {
941     m_heightCanMeasure = measure;
942 }
943 
getSelection()944 String getSelection()
945 {
946     return m_selectText.getSelection();
947 }
948 
moveSelection(int x,int y)949 void moveSelection(int x, int y)
950 {
951     const CachedRoot* root = getFrameCache(DontAllowNewer);
952     if (!root)
953         return;
954     SkPicture* picture = root->pictureAt(x, y);
955     // FIXME: use the visibleRect only for the main picture
956     // for layer pictures, use the equivalent of the canvas clipping rect
957     IntRect visibleRect;
958     getVisibleRect(&visibleRect);
959     m_selectText.setVisibleRect(visibleRect);
960     m_selectText.moveSelection(picture, x, y);
961 }
962 
selectAll()963 void selectAll()
964 {
965     const CachedRoot* root = getFrameCache(DontAllowNewer);
966     if (!root)
967         return;
968     SkPicture* picture = root->pictureAt(0, 0);
969     m_selectText.selectAll(picture);
970 }
971 
selectionX()972 int selectionX()
973 {
974     return m_selectText.selectionX();
975 }
976 
selectionY()977 int selectionY()
978 {
979     return m_selectText.selectionY();
980 }
981 
resetSelection()982 void resetSelection()
983 {
984     m_selectText.reset();
985 }
986 
startSelection(int x,int y)987 bool startSelection(int x, int y)
988 {
989     return m_selectText.startSelection(x, y);
990 }
991 
wordSelection(int x,int y)992 bool wordSelection(int x, int y)
993 {
994     startSelection(x, y);
995     if (!extendSelection(x, y))
996         return false;
997     m_selectText.setDrawPointer(false);
998     SkPicture* picture = getFrameCache(DontAllowNewer)->pictureAt(x, y);
999     return m_selectText.wordSelection(picture);
1000 }
1001 
extendSelection(int x,int y)1002 bool extendSelection(int x, int y)
1003 {
1004     const CachedRoot* root = getFrameCache(DontAllowNewer);
1005     if (!root)
1006         return false;
1007     SkPicture* picture = root->pictureAt(x, y);
1008     IntRect visibleRect;
1009     getVisibleRect(&visibleRect);
1010     m_selectText.setVisibleRect(visibleRect);
1011     m_selectText.extendSelection(picture, x, y);
1012     return true;
1013 }
1014 
hitSelection(int x,int y)1015 bool hitSelection(int x, int y)
1016 {
1017     return m_selectText.hitSelection(x, y);
1018 }
1019 
setExtendSelection()1020 void setExtendSelection()
1021 {
1022     m_selectText.setExtendSelection(true);
1023 }
1024 
setSelectionPointer(bool set,float scale,int x,int y)1025 void setSelectionPointer(bool set, float scale, int x, int y)
1026 {
1027     m_selectText.setDrawPointer(set);
1028     if (!set)
1029         return;
1030     m_selectText.m_inverseScale = scale;
1031     m_selectText.m_selectX = x;
1032     m_selectText.m_selectY = y;
1033 }
1034 
sendMoveFocus(WebCore::Frame * framePtr,WebCore::Node * nodePtr)1035 void sendMoveFocus(WebCore::Frame* framePtr, WebCore::Node* nodePtr)
1036 {
1037     DBG_NAV_LOGD("framePtr=%p nodePtr=%p", framePtr, nodePtr);
1038     JNIEnv* env = JSC::Bindings::getJNIEnv();
1039     env->CallVoidMethod(m_javaGlue.object(env).get(),
1040         m_javaGlue.m_sendMoveFocus, (jint) framePtr, (jint) nodePtr);
1041     checkException(env);
1042 }
1043 
sendMoveMouse(WebCore::Frame * framePtr,WebCore::Node * nodePtr,int x,int y)1044 void sendMoveMouse(WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y)
1045 {
1046     DBG_NAV_LOGD("framePtr=%p nodePtr=%p x=%d y=%d", framePtr, nodePtr, x, y);
1047     JNIEnv* env = JSC::Bindings::getJNIEnv();
1048     env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_sendMoveMouse,
1049         (jint) framePtr, (jint) nodePtr, x, y);
1050     checkException(env);
1051 }
1052 
sendMoveMouseIfLatest(bool disableFocusController)1053 void sendMoveMouseIfLatest(bool disableFocusController)
1054 {
1055     LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
1056     JNIEnv* env = JSC::Bindings::getJNIEnv();
1057     env->CallVoidMethod(m_javaGlue.object(env).get(),
1058             m_javaGlue.m_sendMoveMouseIfLatest, disableFocusController);
1059     checkException(env);
1060 }
1061 
sendMotionUp(WebCore::Frame * framePtr,WebCore::Node * nodePtr,int x,int y)1062 void sendMotionUp(
1063     WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y)
1064 {
1065     m_viewImpl->m_touchGeneration = ++m_generation;
1066     DBG_NAV_LOGD("m_generation=%d framePtr=%p nodePtr=%p x=%d y=%d",
1067         m_generation, framePtr, nodePtr, x, y);
1068     LOG_ASSERT(m_javaGlue.m_obj, "A WebView was not associated with this WebViewNative!");
1069     JNIEnv* env = JSC::Bindings::getJNIEnv();
1070     env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_sendMotionUp,
1071         m_generation, (jint) framePtr, (jint) nodePtr, x, y);
1072     checkException(env);
1073 }
1074 
findNext(bool forward)1075 void findNext(bool forward)
1076 {
1077     m_findOnPage.findNext(forward);
1078     if (!m_findOnPage.currentMatchIsInLayer())
1079         scrollRectOnScreen(m_findOnPage.currentMatchBounds());
1080     viewInvalidate();
1081 }
1082 
1083 // With this call, WebView takes ownership of matches, and is responsible for
1084 // deleting it.
setMatches(WTF::Vector<MatchInfo> * matches)1085 void setMatches(WTF::Vector<MatchInfo>* matches)
1086 {
1087     m_findOnPage.setMatches(matches);
1088     if (!m_findOnPage.currentMatchIsInLayer())
1089         scrollRectOnScreen(m_findOnPage.currentMatchBounds());
1090     viewInvalidate();
1091 }
1092 
currentMatchIndex()1093 int currentMatchIndex()
1094 {
1095     return m_findOnPage.currentMatchIndex();
1096 }
1097 
scrollBy(int dx,int dy)1098 bool scrollBy(int dx, int dy)
1099 {
1100     LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
1101 
1102     JNIEnv* env = JSC::Bindings::getJNIEnv();
1103     bool result = env->CallBooleanMethod(m_javaGlue.object(env).get(),
1104         m_javaGlue.m_scrollBy, dx, dy, true);
1105     checkException(env);
1106     return result;
1107 }
1108 
hasCursorNode()1109 bool hasCursorNode()
1110 {
1111     CachedRoot* root = getFrameCache(DontAllowNewer);
1112     if (!root) {
1113         DBG_NAV_LOG("!root");
1114         return false;
1115     }
1116     const CachedNode* cursorNode = root->currentCursor();
1117     DBG_NAV_LOGD("cursorNode=%d (nodePointer=%p)",
1118         cursorNode ? cursorNode->index() : -1,
1119         cursorNode ? cursorNode->nodePointer() : 0);
1120     return cursorNode;
1121 }
1122 
hasFocusNode()1123 bool hasFocusNode()
1124 {
1125     CachedRoot* root = getFrameCache(DontAllowNewer);
1126     if (!root) {
1127         DBG_NAV_LOG("!root");
1128         return false;
1129     }
1130     const CachedNode* focusNode = root->currentFocus();
1131     DBG_NAV_LOGD("focusNode=%d (nodePointer=%p)",
1132         focusNode ? focusNode->index() : -1,
1133         focusNode ? focusNode->nodePointer() : 0);
1134     return focusNode;
1135 }
1136 
rebuildWebTextView()1137 void rebuildWebTextView()
1138 {
1139     JNIEnv* env = JSC::Bindings::getJNIEnv();
1140     env->CallVoidMethod(m_javaGlue.object(env).get(),
1141             m_javaGlue.m_rebuildWebTextView);
1142     checkException(env);
1143 }
1144 
viewInvalidate()1145 void viewInvalidate()
1146 {
1147     JNIEnv* env = JSC::Bindings::getJNIEnv();
1148     env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_viewInvalidate);
1149     checkException(env);
1150 }
1151 
viewInvalidateRect(int l,int t,int r,int b)1152 void viewInvalidateRect(int l, int t, int r, int b)
1153 {
1154     JNIEnv* env = JSC::Bindings::getJNIEnv();
1155     env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_viewInvalidateRect, l, r, t, b);
1156     checkException(env);
1157 }
1158 
postInvalidateDelayed(int64_t delay,const WebCore::IntRect & bounds)1159 void postInvalidateDelayed(int64_t delay, const WebCore::IntRect& bounds)
1160 {
1161     JNIEnv* env = JSC::Bindings::getJNIEnv();
1162     env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_postInvalidateDelayed,
1163         delay, bounds.x(), bounds.y(), bounds.right(), bounds.bottom());
1164     checkException(env);
1165 }
1166 
moveGeneration()1167 int moveGeneration()
1168 {
1169     return m_viewImpl->m_moveGeneration;
1170 }
1171 
rootLayer() const1172 LayerAndroid* rootLayer() const
1173 {
1174     return m_rootLayer;
1175 }
1176 
setRootLayer(LayerAndroid * layer)1177 void setRootLayer(LayerAndroid* layer)
1178 {
1179     delete m_rootLayer;
1180     m_rootLayer = layer;
1181     CachedRoot* root = getFrameCache(DontAllowNewer);
1182     if (!root)
1183         return;
1184     root->resetLayers();
1185     root->setRootLayer(m_rootLayer);
1186 }
1187 
1188 private: // local state for WebView
1189     // private to getFrameCache(); other functions operate in a different thread
1190     CachedRoot* m_frameCacheUI; // navigation data ready for use
1191     WebViewCore* m_viewImpl;
1192     int m_generation; // associate unique ID with sent kit focus to match with ui
1193     SkPicture* m_navPictureUI;
1194     SkMSec m_ringAnimationEnd;
1195     // Corresponds to the same-named boolean on the java side.
1196     bool m_heightCanMeasure;
1197     int m_lastDx;
1198     SkMSec m_lastDxTime;
1199     SelectText m_selectText;
1200     FindOnPage m_findOnPage;
1201     CursorRing m_ring;
1202     LayerAndroid* m_rootLayer;
1203 }; // end of WebView class
1204 
1205 /*
1206  * Native JNI methods
1207  */
WebCoreStringToJString(JNIEnv * env,WebCore::String string)1208 static jstring WebCoreStringToJString(JNIEnv *env, WebCore::String string)
1209 {
1210     int length = string.length();
1211     if (!length)
1212         return 0;
1213     jstring ret = env->NewString((jchar *)string.characters(), length);
1214     env->DeleteLocalRef(ret);
1215     return ret;
1216 }
1217 
nativeCacheHitFramePointer(JNIEnv * env,jobject obj)1218 static int nativeCacheHitFramePointer(JNIEnv *env, jobject obj)
1219 {
1220     return reinterpret_cast<int>(GET_NATIVE_VIEW(env, obj)
1221             ->m_cacheHitFrame->framePointer());
1222 }
1223 
nativeCacheHitNodeBounds(JNIEnv * env,jobject obj)1224 static jobject nativeCacheHitNodeBounds(JNIEnv *env, jobject obj)
1225 {
1226     WebCore::IntRect bounds = GET_NATIVE_VIEW(env, obj)
1227         ->m_cacheHitNode->originalAbsoluteBounds();
1228     jclass rectClass = env->FindClass("android/graphics/Rect");
1229     jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
1230     jobject rect = env->NewObject(rectClass, init, bounds.x(),
1231         bounds.y(), bounds.right(), bounds.bottom());
1232     return rect;
1233 }
1234 
nativeCacheHitNodePointer(JNIEnv * env,jobject obj)1235 static int nativeCacheHitNodePointer(JNIEnv *env, jobject obj)
1236 {
1237     return reinterpret_cast<int>(GET_NATIVE_VIEW(env, obj)
1238         ->m_cacheHitNode->nodePointer());
1239 }
1240 
nativeClearCursor(JNIEnv * env,jobject obj)1241 static void nativeClearCursor(JNIEnv *env, jobject obj)
1242 {
1243     WebView* view = GET_NATIVE_VIEW(env, obj);
1244     LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1245     view->clearCursor();
1246 }
1247 
nativeCreate(JNIEnv * env,jobject obj,int viewImpl)1248 static void nativeCreate(JNIEnv *env, jobject obj, int viewImpl)
1249 {
1250     WebView* webview = new WebView(env, obj, viewImpl);
1251     // NEED THIS OR SOMETHING LIKE IT!
1252     //Release(obj);
1253 }
1254 
nativeCursorFramePointer(JNIEnv * env,jobject obj)1255 static jint nativeCursorFramePointer(JNIEnv *env, jobject obj)
1256 {
1257     WebView* view = GET_NATIVE_VIEW(env, obj);
1258     CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1259     if (!root)
1260         return 0;
1261     const CachedFrame* frame = 0;
1262     (void) root->currentCursor(&frame);
1263     return reinterpret_cast<int>(frame ? frame->framePointer() : 0);
1264 }
1265 
getCursorNode(JNIEnv * env,jobject obj)1266 static const CachedNode* getCursorNode(JNIEnv *env, jobject obj)
1267 {
1268     WebView* view = GET_NATIVE_VIEW(env, obj);
1269     CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1270     return root ? root->currentCursor() : 0;
1271 }
1272 
getCursorNode(JNIEnv * env,jobject obj,const CachedFrame ** frame)1273 static const CachedNode* getCursorNode(JNIEnv *env, jobject obj,
1274     const CachedFrame** frame)
1275 {
1276     WebView* view = GET_NATIVE_VIEW(env, obj);
1277     CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1278     return root ? root->currentCursor(frame) : 0;
1279 }
1280 
getFocusCandidate(JNIEnv * env,jobject obj,const CachedFrame ** frame)1281 static const CachedNode* getFocusCandidate(JNIEnv *env, jobject obj,
1282     const CachedFrame** frame)
1283 {
1284     WebView* view = GET_NATIVE_VIEW(env, obj);
1285     CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1286     if (!root)
1287         return 0;
1288     const CachedNode* cursor = root->currentCursor(frame);
1289     if (cursor && cursor->wantsKeyEvents())
1290         return cursor;
1291     return root->currentFocus();
1292 }
1293 
focusCandidateHasNextTextfield(JNIEnv * env,jobject obj)1294 static bool focusCandidateHasNextTextfield(JNIEnv *env, jobject obj)
1295 {
1296     WebView* view = GET_NATIVE_VIEW(env, obj);
1297     CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1298     if (!root)
1299         return false;
1300     const CachedNode* cursor = root->currentCursor();
1301     if (!cursor || !cursor->isTextInput())
1302         cursor = root->currentFocus();
1303     if (!cursor || !cursor->isTextInput()) return false;
1304     return root->nextTextField(cursor, 0);
1305 }
1306 
getFocusNode(JNIEnv * env,jobject obj)1307 static const CachedNode* getFocusNode(JNIEnv *env, jobject obj)
1308 {
1309     WebView* view = GET_NATIVE_VIEW(env, obj);
1310     CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1311     return root ? root->currentFocus() : 0;
1312 }
1313 
getFocusNode(JNIEnv * env,jobject obj,const CachedFrame ** frame)1314 static const CachedNode* getFocusNode(JNIEnv *env, jobject obj,
1315     const CachedFrame** frame)
1316 {
1317     WebView* view = GET_NATIVE_VIEW(env, obj);
1318     CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1319     return root ? root->currentFocus(frame) : 0;
1320 }
1321 
getInputCandidate(JNIEnv * env,jobject obj)1322 static const CachedInput* getInputCandidate(JNIEnv *env, jobject obj)
1323 {
1324     WebView* view = GET_NATIVE_VIEW(env, obj);
1325     CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1326     if (!root)
1327         return 0;
1328     const CachedFrame* frame;
1329     const CachedNode* cursor = root->currentCursor(&frame);
1330     if (!cursor || !cursor->wantsKeyEvents())
1331         cursor = root->currentFocus(&frame);
1332     return cursor ? frame->textInput(cursor) : 0;
1333 }
1334 
nativeCursorMatchesFocus(JNIEnv * env,jobject obj)1335 static jboolean nativeCursorMatchesFocus(JNIEnv *env, jobject obj)
1336 {
1337     const CachedNode* cursor = getCursorNode(env, obj);
1338     const CachedNode* focus = getFocusNode(env, obj);
1339     return cursor && focus && cursor->nodePointer() == focus->nodePointer();
1340 }
1341 
nativeCursorNodeBounds(JNIEnv * env,jobject obj)1342 static jobject nativeCursorNodeBounds(JNIEnv *env, jobject obj)
1343 {
1344     const CachedFrame* frame;
1345     const CachedNode* node = getCursorNode(env, obj, &frame);
1346     WebCore::IntRect bounds = node ? node->bounds(frame)
1347         : WebCore::IntRect(0, 0, 0, 0);
1348     jclass rectClass = env->FindClass("android/graphics/Rect");
1349     jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
1350     jobject rect = env->NewObject(rectClass, init, bounds.x(),
1351         bounds.y(), bounds.right(), bounds.bottom());
1352     return rect;
1353 }
1354 
nativeCursorNodePointer(JNIEnv * env,jobject obj)1355 static jint nativeCursorNodePointer(JNIEnv *env, jobject obj)
1356 {
1357     const CachedNode* node = getCursorNode(env, obj);
1358     return reinterpret_cast<int>(node ? node->nodePointer() : 0);
1359 }
1360 
nativeCursorPosition(JNIEnv * env,jobject obj)1361 static jobject nativeCursorPosition(JNIEnv *env, jobject obj)
1362 {
1363     WebView* view = GET_NATIVE_VIEW(env, obj);
1364     const CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1365     WebCore::IntPoint pos = WebCore::IntPoint(0, 0);
1366     if (root)
1367         root->getSimulatedMousePosition(&pos);
1368     jclass pointClass = env->FindClass("android/graphics/Point");
1369     jmethodID init = env->GetMethodID(pointClass, "<init>", "(II)V");
1370     jobject point = env->NewObject(pointClass, init, pos.x(), pos.y());
1371     return point;
1372 }
1373 
jrect_to_webrect(JNIEnv * env,jobject obj)1374 static WebCore::IntRect jrect_to_webrect(JNIEnv* env, jobject obj)
1375 {
1376     int L, T, R, B;
1377     GraphicsJNI::get_jrect(env, obj, &L, &T, &R, &B);
1378     return WebCore::IntRect(L, T, R - L, B - T);
1379 }
1380 
nativeCursorIntersects(JNIEnv * env,jobject obj,jobject visRect)1381 static bool nativeCursorIntersects(JNIEnv *env, jobject obj, jobject visRect)
1382 {
1383     const CachedFrame* frame;
1384     const CachedNode* node = getCursorNode(env, obj, &frame);
1385     return node ? node->bounds(frame).intersects(
1386         jrect_to_webrect(env, visRect)) : false;
1387 }
1388 
nativeCursorIsAnchor(JNIEnv * env,jobject obj)1389 static bool nativeCursorIsAnchor(JNIEnv *env, jobject obj)
1390 {
1391     const CachedNode* node = getCursorNode(env, obj);
1392     return node ? node->isAnchor() : false;
1393 }
1394 
nativeCursorIsTextInput(JNIEnv * env,jobject obj)1395 static bool nativeCursorIsTextInput(JNIEnv *env, jobject obj)
1396 {
1397     const CachedNode* node = getCursorNode(env, obj);
1398     return node ? node->isTextInput() : false;
1399 }
1400 
nativeCursorText(JNIEnv * env,jobject obj)1401 static jobject nativeCursorText(JNIEnv *env, jobject obj)
1402 {
1403     const CachedNode* node = getCursorNode(env, obj);
1404     if (!node)
1405         return 0;
1406     WebCore::String value = node->getExport();
1407     return !value.isEmpty() ? env->NewString((jchar *)value.characters(),
1408         value.length()) : 0;
1409 }
1410 
nativeDebugDump(JNIEnv * env,jobject obj)1411 static void nativeDebugDump(JNIEnv *env, jobject obj)
1412 {
1413 #if DUMP_NAV_CACHE
1414     WebView* view = GET_NATIVE_VIEW(env, obj);
1415     LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1416     view->debugDump();
1417 #endif
1418 }
1419 
nativeDrawExtras(JNIEnv * env,jobject obj,jobject canv,jint extras)1420 static void nativeDrawExtras(JNIEnv *env, jobject obj, jobject canv, jint extras)
1421 {
1422     SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv);
1423     GET_NATIVE_VIEW(env, obj)->drawExtras(canvas, extras);
1424 }
1425 
nativeEvaluateLayersAnimations(JNIEnv * env,jobject obj)1426 static bool nativeEvaluateLayersAnimations(JNIEnv *env, jobject obj)
1427 {
1428 #if USE(ACCELERATED_COMPOSITING)
1429     const LayerAndroid* root = GET_NATIVE_VIEW(env, obj)->rootLayer();
1430     if (root)
1431         return root->evaluateAnimations();
1432 #endif
1433     return false;
1434 }
1435 
nativeSetRootLayer(JNIEnv * env,jobject obj,jint layer)1436 static void nativeSetRootLayer(JNIEnv *env, jobject obj, jint layer)
1437 {
1438 #if USE(ACCELERATED_COMPOSITING)
1439     LayerAndroid* layerImpl = reinterpret_cast<LayerAndroid*>(layer);
1440     GET_NATIVE_VIEW(env, obj)->setRootLayer(layerImpl);
1441 #endif
1442 }
1443 
nativeImageURI(JNIEnv * env,jobject obj,jint x,jint y)1444 static jobject nativeImageURI(JNIEnv *env, jobject obj, jint x, jint y)
1445 {
1446     WebView* view = GET_NATIVE_VIEW(env, obj);
1447     LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1448     WebCore::String uri = view->imageURI(x, y);
1449     jstring ret = 0;
1450     unsigned len = uri.length();
1451     if (len) {
1452         ret = env->NewString((jchar*) uri.characters(), len);
1453         env->DeleteLocalRef(ret);
1454     }
1455     return ret;
1456 }
1457 
nativeFocusCandidateFramePointer(JNIEnv * env,jobject obj)1458 static jint nativeFocusCandidateFramePointer(JNIEnv *env, jobject obj)
1459 {
1460     WebView* view = GET_NATIVE_VIEW(env, obj);
1461     CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1462     if (!root)
1463         return 0;
1464     const CachedFrame* frame = 0;
1465     const CachedNode* cursor = root->currentCursor(&frame);
1466     if (!cursor || !cursor->wantsKeyEvents())
1467         (void) root->currentFocus(&frame);
1468     return reinterpret_cast<int>(frame ? frame->framePointer() : 0);
1469 }
1470 
nativeFocusCandidateIsPassword(JNIEnv * env,jobject obj)1471 static bool nativeFocusCandidateIsPassword(JNIEnv *env, jobject obj)
1472 {
1473     const CachedInput* input = getInputCandidate(env, obj);
1474     return input && input->inputType() == WebCore::HTMLInputElement::PASSWORD;
1475 }
1476 
nativeFocusCandidateIsRtlText(JNIEnv * env,jobject obj)1477 static bool nativeFocusCandidateIsRtlText(JNIEnv *env, jobject obj)
1478 {
1479     const CachedInput* input = getInputCandidate(env, obj);
1480     return input ? input->isRtlText() : false;
1481 }
1482 
nativeFocusCandidateIsTextInput(JNIEnv * env,jobject obj)1483 static bool nativeFocusCandidateIsTextInput(JNIEnv *env, jobject obj)
1484 {
1485     const CachedNode* node = getFocusCandidate(env, obj, 0);
1486     return node ? node->isTextInput() : false;
1487 }
1488 
nativeFocusCandidateMaxLength(JNIEnv * env,jobject obj)1489 static jint nativeFocusCandidateMaxLength(JNIEnv *env, jobject obj)
1490 {
1491     const CachedInput* input = getInputCandidate(env, obj);
1492     return input ? input->maxLength() : false;
1493 }
1494 
nativeFocusCandidateName(JNIEnv * env,jobject obj)1495 static jobject nativeFocusCandidateName(JNIEnv *env, jobject obj)
1496 {
1497     const CachedInput* input = getInputCandidate(env, obj);
1498     if (!input)
1499         return 0;
1500     const WebCore::String& name = input->name();
1501     return env->NewString((jchar*)name.characters(), name.length());
1502 }
1503 
createJavaRect(JNIEnv * env,int x,int y,int right,int bottom)1504 static jobject createJavaRect(JNIEnv* env, int x, int y, int right, int bottom)
1505 {
1506     jclass rectClass = env->FindClass("android/graphics/Rect");
1507     jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
1508     jobject rect = env->NewObject(rectClass, init, x, y, right, bottom);
1509     return rect;
1510 }
1511 
nativeFocusCandidateNodeBounds(JNIEnv * env,jobject obj)1512 static jobject nativeFocusCandidateNodeBounds(JNIEnv *env, jobject obj)
1513 {
1514     const CachedFrame* frame;
1515     const CachedNode* node = getFocusCandidate(env, obj, &frame);
1516     WebCore::IntRect bounds = node ? node->bounds(frame)
1517         : WebCore::IntRect(0, 0, 0, 0);
1518     return createJavaRect(env, bounds.x(), bounds.y(), bounds.right(), bounds.bottom());
1519 }
1520 
nativeFocusCandidatePaddingRect(JNIEnv * env,jobject obj)1521 static jobject nativeFocusCandidatePaddingRect(JNIEnv *env, jobject obj)
1522 {
1523     const CachedInput* input = getInputCandidate(env, obj);
1524     if (!input)
1525         return 0;
1526     // Note that the Java Rect is being used to pass four integers, rather than
1527     // being used as an actual rectangle.
1528     return createJavaRect(env, input->paddingLeft(), input->paddingTop(),
1529             input->paddingRight(), input->paddingBottom());
1530 }
1531 
nativeFocusCandidatePointer(JNIEnv * env,jobject obj)1532 static jint nativeFocusCandidatePointer(JNIEnv *env, jobject obj)
1533 {
1534     const CachedNode* node = getFocusCandidate(env, obj, 0);
1535     return reinterpret_cast<int>(node ? node->nodePointer() : 0);
1536 }
1537 
nativeFocusCandidateText(JNIEnv * env,jobject obj)1538 static jobject nativeFocusCandidateText(JNIEnv *env, jobject obj)
1539 {
1540     const CachedNode* node = getFocusCandidate(env, obj, 0);
1541     if (!node)
1542         return 0;
1543     WebCore::String value = node->getExport();
1544     return !value.isEmpty() ? env->NewString((jchar *)value.characters(),
1545         value.length()) : 0;
1546 }
1547 
nativeFocusCandidateTextSize(JNIEnv * env,jobject obj)1548 static jint nativeFocusCandidateTextSize(JNIEnv *env, jobject obj)
1549 {
1550     const CachedInput* input = getInputCandidate(env, obj);
1551     return input ? input->textSize() : 0;
1552 }
1553 
1554 enum type {
1555     NONE = -1,
1556     NORMAL_TEXT_FIELD = 0,
1557     TEXT_AREA = 1,
1558     PASSWORD = 2,
1559     SEARCH = 3,
1560     EMAIL = 4,
1561     NUMBER = 5,
1562     TELEPHONE = 6,
1563     URL = 7
1564 };
1565 
nativeFocusCandidateType(JNIEnv * env,jobject obj)1566 static int nativeFocusCandidateType(JNIEnv *env, jobject obj)
1567 {
1568     const CachedInput* input = getInputCandidate(env, obj);
1569     if (!input) return NONE;
1570     if (!input->isTextField()) return TEXT_AREA;
1571     switch (input->inputType()) {
1572     case HTMLInputElement::PASSWORD:
1573         return PASSWORD;
1574     case HTMLInputElement::SEARCH:
1575         return SEARCH;
1576     case HTMLInputElement::EMAIL:
1577         return EMAIL;
1578     case HTMLInputElement::NUMBER:
1579         return NUMBER;
1580     case HTMLInputElement::TELEPHONE:
1581         return TELEPHONE;
1582     case HTMLInputElement::URL:
1583         return URL;
1584     default:
1585         return NORMAL_TEXT_FIELD;
1586     }
1587 }
1588 
nativeFocusIsPlugin(JNIEnv * env,jobject obj)1589 static bool nativeFocusIsPlugin(JNIEnv *env, jobject obj)
1590 {
1591     const CachedNode* node = getFocusNode(env, obj);
1592     return node ? node->isPlugin() : false;
1593 }
1594 
nativeFocusNodeBounds(JNIEnv * env,jobject obj)1595 static jobject nativeFocusNodeBounds(JNIEnv *env, jobject obj)
1596 {
1597     const CachedFrame* frame;
1598     const CachedNode* node = getFocusNode(env, obj, &frame);
1599     WebCore::IntRect bounds = node ? node->bounds(frame)
1600         : WebCore::IntRect(0, 0, 0, 0);
1601     jclass rectClass = env->FindClass("android/graphics/Rect");
1602     jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
1603     jobject rect = env->NewObject(rectClass, init, bounds.x(),
1604         bounds.y(), bounds.right(), bounds.bottom());
1605     return rect;
1606 }
1607 
nativeFocusNodePointer(JNIEnv * env,jobject obj)1608 static jint nativeFocusNodePointer(JNIEnv *env, jobject obj)
1609 {
1610     const CachedNode* node = getFocusNode(env, obj);
1611     return node ? reinterpret_cast<int>(node->nodePointer()) : 0;
1612 }
1613 
nativeCursorWantsKeyEvents(JNIEnv * env,jobject jwebview)1614 static bool nativeCursorWantsKeyEvents(JNIEnv* env, jobject jwebview) {
1615     WebView* view = GET_NATIVE_VIEW(env, jwebview);
1616     LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1617     return view->cursorWantsKeyEvents();
1618 }
1619 
nativeHideCursor(JNIEnv * env,jobject obj)1620 static void nativeHideCursor(JNIEnv *env, jobject obj)
1621 {
1622     WebView* view = GET_NATIVE_VIEW(env, obj);
1623     LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1624     view->hideCursor();
1625 }
1626 
nativeInstrumentReport(JNIEnv * env,jobject obj)1627 static void nativeInstrumentReport(JNIEnv *env, jobject obj)
1628 {
1629 #ifdef ANDROID_INSTRUMENT
1630     TimeCounter::reportNow();
1631 #endif
1632 }
1633 
nativeSelectBestAt(JNIEnv * env,jobject obj,jobject jrect)1634 static void nativeSelectBestAt(JNIEnv *env, jobject obj, jobject jrect)
1635 {
1636     WebView* view = GET_NATIVE_VIEW(env, obj);
1637     LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1638     WebCore::IntRect rect = jrect_to_webrect(env, jrect);
1639     view->selectBestAt(rect);
1640 }
1641 
nativeSubtractLayers(JNIEnv * env,jobject obj,jobject jrect)1642 static jobject nativeSubtractLayers(JNIEnv* env, jobject obj, jobject jrect)
1643 {
1644     SkIRect irect = jrect_to_webrect(env, jrect);
1645 #if USE(ACCELERATED_COMPOSITING)
1646     LayerAndroid* root = GET_NATIVE_VIEW(env, obj)->rootLayer();
1647     if (root) {
1648         SkRect rect;
1649         rect.set(irect);
1650         rect = root->subtractLayers(rect);
1651         rect.round(&irect);
1652     }
1653 #endif
1654     jclass rectClass = env->FindClass("android/graphics/Rect");
1655     jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
1656     return env->NewObject(rectClass, init, irect.fLeft, irect.fTop,
1657         irect.fRight, irect.fBottom);
1658 }
1659 
nativeTextGeneration(JNIEnv * env,jobject obj)1660 static jint nativeTextGeneration(JNIEnv *env, jobject obj)
1661 {
1662     WebView* view = GET_NATIVE_VIEW(env, obj);
1663     CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1664     return root ? root->textGeneration() : 0;
1665 }
1666 
nativePointInNavCache(JNIEnv * env,jobject obj,int x,int y,int slop)1667 static bool nativePointInNavCache(JNIEnv *env, jobject obj,
1668     int x, int y, int slop)
1669 {
1670     return GET_NATIVE_VIEW(env, obj)->pointInNavCache(x, y, slop);
1671 }
1672 
nativeMotionUp(JNIEnv * env,jobject obj,int x,int y,int slop)1673 static bool nativeMotionUp(JNIEnv *env, jobject obj,
1674     int x, int y, int slop)
1675 {
1676     WebView* view = GET_NATIVE_VIEW(env, obj);
1677     LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1678     return view->motionUp(x, y, slop);
1679 }
1680 
nativeHasCursorNode(JNIEnv * env,jobject obj)1681 static bool nativeHasCursorNode(JNIEnv *env, jobject obj)
1682 {
1683     return GET_NATIVE_VIEW(env, obj)->hasCursorNode();
1684 }
1685 
nativeHasFocusNode(JNIEnv * env,jobject obj)1686 static bool nativeHasFocusNode(JNIEnv *env, jobject obj)
1687 {
1688     return GET_NATIVE_VIEW(env, obj)->hasFocusNode();
1689 }
1690 
nativeMoveCursor(JNIEnv * env,jobject obj,int key,int count,bool ignoreScroll)1691 static bool nativeMoveCursor(JNIEnv *env, jobject obj,
1692     int key, int count, bool ignoreScroll)
1693 {
1694     WebView* view = GET_NATIVE_VIEW(env, obj);
1695     DBG_NAV_LOGD("env=%p obj=%p view=%p", env, obj, view);
1696     LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1697     return view->moveCursor(key, count, ignoreScroll);
1698 }
1699 
nativeRecordButtons(JNIEnv * env,jobject obj,bool hasFocus,bool pressed,bool invalidate)1700 static void nativeRecordButtons(JNIEnv* env, jobject obj, bool hasFocus,
1701         bool pressed, bool invalidate)
1702 {
1703     WebView* view = GET_NATIVE_VIEW(env, obj);
1704     LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1705     view->nativeRecordButtons(hasFocus, pressed, invalidate);
1706 }
1707 
nativeSetFindIsUp(JNIEnv * env,jobject obj,jboolean isUp)1708 static void nativeSetFindIsUp(JNIEnv *env, jobject obj, jboolean isUp)
1709 {
1710     WebView* view = GET_NATIVE_VIEW(env, obj);
1711     LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1712     view->setFindIsUp(isUp);
1713 }
1714 
nativeSetFindIsEmpty(JNIEnv * env,jobject obj)1715 static void nativeSetFindIsEmpty(JNIEnv *env, jobject obj)
1716 {
1717     GET_NATIVE_VIEW(env, obj)->setFindIsEmpty();
1718 }
1719 
nativeSetFollowedLink(JNIEnv * env,jobject obj,bool followed)1720 static void nativeSetFollowedLink(JNIEnv *env, jobject obj, bool followed)
1721 {
1722     WebView* view = GET_NATIVE_VIEW(env, obj);
1723     LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1724     view->setFollowedLink(followed);
1725 }
1726 
nativeSetHeightCanMeasure(JNIEnv * env,jobject obj,bool measure)1727 static void nativeSetHeightCanMeasure(JNIEnv *env, jobject obj, bool measure)
1728 {
1729     WebView* view = GET_NATIVE_VIEW(env, obj);
1730     LOG_ASSERT(view, "view not set in nativeSetHeightCanMeasure");
1731     view->setHeightCanMeasure(measure);
1732 }
1733 
nativeGetCursorRingBounds(JNIEnv * env,jobject obj)1734 static jobject nativeGetCursorRingBounds(JNIEnv *env, jobject obj)
1735 {
1736     WebView* view = GET_NATIVE_VIEW(env, obj);
1737     LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1738     jclass rectClass = env->FindClass("android/graphics/Rect");
1739     LOG_ASSERT(rectClass, "Could not find Rect class!");
1740     jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
1741     LOG_ASSERT(init, "Could not find constructor for Rect");
1742     WebCore::IntRect webRect;
1743     view->cursorRingBounds(&webRect);
1744     jobject rect = env->NewObject(rectClass, init, webRect.x(),
1745         webRect.y(), webRect.right(), webRect.bottom());
1746     return rect;
1747 }
1748 
nativeFindAll(JNIEnv * env,jobject obj,jstring findLower,jstring findUpper)1749 static int nativeFindAll(JNIEnv *env, jobject obj, jstring findLower,
1750         jstring findUpper)
1751 {
1752     // If one or the other is null, do not search.
1753     if (!(findLower && findUpper))
1754         return 0;
1755     // Obtain the characters for both the lower case string and the upper case
1756     // string representing the same word.
1757     const jchar* findLowerChars = env->GetStringChars(findLower, 0);
1758     const jchar* findUpperChars = env->GetStringChars(findUpper, 0);
1759     // If one or the other is null, do not search.
1760     if (!(findLowerChars && findUpperChars)) {
1761         if (findLowerChars)
1762             env->ReleaseStringChars(findLower, findLowerChars);
1763         if (findUpperChars)
1764             env->ReleaseStringChars(findUpper, findUpperChars);
1765         checkException(env);
1766         return 0;
1767     }
1768     WebView* view = GET_NATIVE_VIEW(env, obj);
1769     LOG_ASSERT(view, "view not set in nativeFindAll");
1770     CachedRoot* root = view->getFrameCache(WebView::AllowNewer);
1771     if (!root) {
1772         env->ReleaseStringChars(findLower, findLowerChars);
1773         env->ReleaseStringChars(findUpper, findUpperChars);
1774         checkException(env);
1775         return 0;
1776     }
1777     int length = env->GetStringLength(findLower);
1778     // If the lengths of the strings do not match, then they are not the same
1779     // word, so do not search.
1780     if (!length || env->GetStringLength(findUpper) != length) {
1781         env->ReleaseStringChars(findLower, findLowerChars);
1782         env->ReleaseStringChars(findUpper, findUpperChars);
1783         checkException(env);
1784         return 0;
1785     }
1786     int width = root->documentWidth();
1787     int height = root->documentHeight();
1788     // Create a FindCanvas, which allows us to fake draw into it so we can
1789     // figure out where our search string is rendered (and how many times).
1790     FindCanvas canvas(width, height, (const UChar*) findLowerChars,
1791             (const UChar*) findUpperChars, length << 1);
1792     SkBitmap bitmap;
1793     bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
1794     canvas.setBitmapDevice(bitmap);
1795     root->draw(canvas);
1796     WTF::Vector<MatchInfo>* matches = canvas.detachMatches();
1797     // With setMatches, the WebView takes ownership of matches
1798     view->setMatches(matches);
1799 
1800     env->ReleaseStringChars(findLower, findLowerChars);
1801     env->ReleaseStringChars(findUpper, findUpperChars);
1802     checkException(env);
1803     return canvas.found();
1804 }
1805 
nativeFindNext(JNIEnv * env,jobject obj,bool forward)1806 static void nativeFindNext(JNIEnv *env, jobject obj, bool forward)
1807 {
1808     WebView* view = GET_NATIVE_VIEW(env, obj);
1809     LOG_ASSERT(view, "view not set in nativeFindNext");
1810     view->findNext(forward);
1811 }
1812 
nativeFindIndex(JNIEnv * env,jobject obj)1813 static int nativeFindIndex(JNIEnv *env, jobject obj)
1814 {
1815     WebView* view = GET_NATIVE_VIEW(env, obj);
1816     LOG_ASSERT(view, "view not set in nativeFindIndex");
1817     return view->currentMatchIndex();
1818 }
1819 
nativeUpdateCachedTextfield(JNIEnv * env,jobject obj,jstring updatedText,jint generation)1820 static void nativeUpdateCachedTextfield(JNIEnv *env, jobject obj, jstring updatedText, jint generation)
1821 {
1822     WebView* view = GET_NATIVE_VIEW(env, obj);
1823     LOG_ASSERT(view, "view not set in nativeUpdateCachedTextfield");
1824     CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1825     if (!root)
1826         return;
1827     const CachedNode* cachedFocusNode = root->currentFocus();
1828     if (!cachedFocusNode || !cachedFocusNode->isTextInput())
1829         return;
1830     WebCore::String webcoreString = to_string(env, updatedText);
1831     (const_cast<CachedNode*>(cachedFocusNode))->setExport(webcoreString);
1832     root->setTextGeneration(generation);
1833     checkException(env);
1834 }
1835 
nativeGetBlockLeftEdge(JNIEnv * env,jobject obj,jint x,jint y,jfloat scale)1836 static jint nativeGetBlockLeftEdge(JNIEnv *env, jobject obj, jint x, jint y,
1837         jfloat scale)
1838 {
1839     WebView* view = GET_NATIVE_VIEW(env, obj);
1840     LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1841     if (!view)
1842         return -1;
1843     return view->getBlockLeftEdge(x, y, scale);
1844 }
1845 
nativeDestroy(JNIEnv * env,jobject obj)1846 static void nativeDestroy(JNIEnv *env, jobject obj)
1847 {
1848     WebView* view = GET_NATIVE_VIEW(env, obj);
1849     LOGD("nativeDestroy view: %p", view);
1850     LOG_ASSERT(view, "view not set in nativeDestroy");
1851     delete view;
1852 }
1853 
nativeMoveCursorToNextTextInput(JNIEnv * env,jobject obj)1854 static bool nativeMoveCursorToNextTextInput(JNIEnv *env, jobject obj)
1855 {
1856     WebView* view = GET_NATIVE_VIEW(env, obj);
1857     CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1858     if (!root)
1859         return false;
1860     const CachedNode* current = root->currentCursor();
1861     if (!current || !current->isTextInput())
1862         current = root->currentFocus();
1863     if (!current || !current->isTextInput())
1864         return false;
1865     const CachedFrame* frame;
1866     const CachedNode* next = root->nextTextField(current, &frame);
1867     if (!next)
1868         return false;
1869     const WebCore::IntRect& bounds = next->bounds(frame);
1870     root->rootHistory()->setMouseBounds(bounds);
1871     view->getWebViewCore()->updateCursorBounds(root, frame, next);
1872     root->setCursor(const_cast<CachedFrame*>(frame),
1873             const_cast<CachedNode*>(next));
1874     view->sendMoveFocus(static_cast<WebCore::Frame*>(frame->framePointer()),
1875             static_cast<WebCore::Node*>(next->nodePointer()));
1876     if (!next->isInLayer())
1877         view->scrollRectOnScreen(bounds);
1878     view->getWebViewCore()->m_moveGeneration++;
1879     return true;
1880 }
1881 
nativeMoveGeneration(JNIEnv * env,jobject obj)1882 static int nativeMoveGeneration(JNIEnv *env, jobject obj)
1883 {
1884     WebView* view = GET_NATIVE_VIEW(env, obj);
1885     if (!view)
1886         return 0;
1887     return view->moveGeneration();
1888 }
1889 
nativeMoveSelection(JNIEnv * env,jobject obj,int x,int y)1890 static void nativeMoveSelection(JNIEnv *env, jobject obj, int x, int y)
1891 {
1892     GET_NATIVE_VIEW(env, obj)->moveSelection(x, y);
1893 }
1894 
nativeResetSelection(JNIEnv * env,jobject obj)1895 static void nativeResetSelection(JNIEnv *env, jobject obj)
1896 {
1897     return GET_NATIVE_VIEW(env, obj)->resetSelection();
1898 }
1899 
nativeSelectAll(JNIEnv * env,jobject obj)1900 static void nativeSelectAll(JNIEnv* env, jobject obj)
1901 {
1902     GET_NATIVE_VIEW(env, obj)->selectAll();
1903 }
1904 
nativeSetExtendSelection(JNIEnv * env,jobject obj)1905 static void nativeSetExtendSelection(JNIEnv *env, jobject obj)
1906 {
1907     GET_NATIVE_VIEW(env, obj)->setExtendSelection();
1908 }
1909 
nativeStartSelection(JNIEnv * env,jobject obj,int x,int y)1910 static jboolean nativeStartSelection(JNIEnv *env, jobject obj, int x, int y)
1911 {
1912     return GET_NATIVE_VIEW(env, obj)->startSelection(x, y);
1913 }
1914 
nativeWordSelection(JNIEnv * env,jobject obj,int x,int y)1915 static jboolean nativeWordSelection(JNIEnv *env, jobject obj, int x, int y)
1916 {
1917     return GET_NATIVE_VIEW(env, obj)->wordSelection(x, y);
1918 }
1919 
nativeExtendSelection(JNIEnv * env,jobject obj,int x,int y)1920 static void nativeExtendSelection(JNIEnv *env, jobject obj, int x, int y)
1921 {
1922     GET_NATIVE_VIEW(env, obj)->extendSelection(x, y);
1923 }
1924 
nativeGetSelection(JNIEnv * env,jobject obj)1925 static jobject nativeGetSelection(JNIEnv *env, jobject obj)
1926 {
1927     WebView* view = GET_NATIVE_VIEW(env, obj);
1928     LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1929     String selection = view->getSelection();
1930     return env->NewString((jchar*)selection.characters(), selection.length());
1931 }
1932 
nativeHitSelection(JNIEnv * env,jobject obj,int x,int y)1933 static jboolean nativeHitSelection(JNIEnv *env, jobject obj, int x, int y)
1934 {
1935     return GET_NATIVE_VIEW(env, obj)->hitSelection(x, y);
1936 }
1937 
nativeSelectionX(JNIEnv * env,jobject obj)1938 static jint nativeSelectionX(JNIEnv *env, jobject obj)
1939 {
1940     return GET_NATIVE_VIEW(env, obj)->selectionX();
1941 }
1942 
nativeSelectionY(JNIEnv * env,jobject obj)1943 static jint nativeSelectionY(JNIEnv *env, jobject obj)
1944 {
1945     return GET_NATIVE_VIEW(env, obj)->selectionY();
1946 }
1947 
nativeSetSelectionPointer(JNIEnv * env,jobject obj,jboolean set,jfloat scale,jint x,jint y)1948 static void nativeSetSelectionPointer(JNIEnv *env, jobject obj, jboolean set,
1949     jfloat scale, jint x, jint y)
1950 {
1951     GET_NATIVE_VIEW(env, obj)->setSelectionPointer(set, scale, x, y);
1952 }
1953 
1954 #ifdef ANDROID_DUMP_DISPLAY_TREE
dumpToFile(const char text[],void * file)1955 static void dumpToFile(const char text[], void* file) {
1956     fwrite(text, 1, strlen(text), reinterpret_cast<FILE*>(file));
1957     fwrite("\n", 1, 1, reinterpret_cast<FILE*>(file));
1958 }
1959 #endif
1960 
nativeDumpDisplayTree(JNIEnv * env,jobject jwebview,jstring jurl)1961 static void nativeDumpDisplayTree(JNIEnv* env, jobject jwebview, jstring jurl)
1962 {
1963 #ifdef ANDROID_DUMP_DISPLAY_TREE
1964     WebView* view = GET_NATIVE_VIEW(env, jwebview);
1965     LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1966 
1967     if (view && view->getWebViewCore()) {
1968         FILE* file = fopen(DISPLAY_TREE_LOG_FILE, "w");
1969         if (file) {
1970             SkFormatDumper dumper(dumpToFile, file);
1971             // dump the URL
1972             if (jurl) {
1973                 const char* str = env->GetStringUTFChars(jurl, 0);
1974                 SkDebugf("Dumping %s to %s\n", str, DISPLAY_TREE_LOG_FILE);
1975                 dumpToFile(str, file);
1976                 env->ReleaseStringUTFChars(jurl, str);
1977             }
1978             // now dump the display tree
1979             SkDumpCanvas canvas(&dumper);
1980             // this will playback the picture into the canvas, which will
1981             // spew its contents to the dumper
1982             view->getWebViewCore()->drawContent(&canvas, 0);
1983 #if USE(ACCELERATED_COMPOSITING)
1984             if (true) {
1985                 LayerAndroid* rootLayer = view->rootLayer();
1986                 if (rootLayer) {
1987                     // We have to set the canvas' matrix on the root layer
1988                     // (to have fixed layers work as intended)
1989                     SkAutoCanvasRestore restore(&canvas, true);
1990                     rootLayer->setMatrix(canvas.getTotalMatrix());
1991                     canvas.resetMatrix();
1992                     rootLayer->draw(&canvas);
1993                 }
1994             }
1995 #endif
1996             // we're done with the file now
1997             fwrite("\n", 1, 1, file);
1998             fclose(file);
1999         }
2000 #if USE(ACCELERATED_COMPOSITING)
2001         const LayerAndroid* rootLayer = view->rootLayer();
2002         if (rootLayer) {
2003           FILE* file = fopen(LAYERS_TREE_LOG_FILE,"w");
2004           if (file) {
2005               rootLayer->dumpLayers(file, 0);
2006               fclose(file);
2007           }
2008         }
2009 #endif
2010     }
2011 #endif
2012 }
2013 
2014 /*
2015  * JNI registration
2016  */
2017 static JNINativeMethod gJavaWebViewMethods[] = {
2018     { "nativeCacheHitFramePointer", "()I",
2019         (void*) nativeCacheHitFramePointer },
2020     { "nativeCacheHitNodeBounds", "()Landroid/graphics/Rect;",
2021         (void*) nativeCacheHitNodeBounds },
2022     { "nativeCacheHitNodePointer", "()I",
2023         (void*) nativeCacheHitNodePointer },
2024     { "nativeClearCursor", "()V",
2025         (void*) nativeClearCursor },
2026     { "nativeCreate", "(I)V",
2027         (void*) nativeCreate },
2028     { "nativeCursorFramePointer", "()I",
2029         (void*) nativeCursorFramePointer },
2030     { "nativeCursorMatchesFocus", "()Z",
2031         (void*) nativeCursorMatchesFocus },
2032     { "nativeCursorNodeBounds", "()Landroid/graphics/Rect;",
2033         (void*) nativeCursorNodeBounds },
2034     { "nativeCursorNodePointer", "()I",
2035         (void*) nativeCursorNodePointer },
2036     { "nativeCursorIntersects", "(Landroid/graphics/Rect;)Z",
2037         (void*) nativeCursorIntersects },
2038     { "nativeCursorIsAnchor", "()Z",
2039         (void*) nativeCursorIsAnchor },
2040     { "nativeCursorIsTextInput", "()Z",
2041         (void*) nativeCursorIsTextInput },
2042     { "nativeCursorPosition", "()Landroid/graphics/Point;",
2043         (void*) nativeCursorPosition },
2044     { "nativeCursorText", "()Ljava/lang/String;",
2045         (void*) nativeCursorText },
2046     { "nativeCursorWantsKeyEvents", "()Z",
2047         (void*)nativeCursorWantsKeyEvents },
2048     { "nativeDebugDump", "()V",
2049         (void*) nativeDebugDump },
2050     { "nativeDestroy", "()V",
2051         (void*) nativeDestroy },
2052     { "nativeDrawExtras", "(Landroid/graphics/Canvas;I)V",
2053         (void*) nativeDrawExtras },
2054     { "nativeDumpDisplayTree", "(Ljava/lang/String;)V",
2055         (void*) nativeDumpDisplayTree },
2056     { "nativeEvaluateLayersAnimations", "()Z",
2057         (void*) nativeEvaluateLayersAnimations },
2058     { "nativeExtendSelection", "(II)V",
2059         (void*) nativeExtendSelection },
2060     { "nativeFindAll", "(Ljava/lang/String;Ljava/lang/String;)I",
2061         (void*) nativeFindAll },
2062     { "nativeFindNext", "(Z)V",
2063         (void*) nativeFindNext },
2064     { "nativeFindIndex", "()I",
2065         (void*) nativeFindIndex},
2066     { "nativeFocusCandidateFramePointer", "()I",
2067         (void*) nativeFocusCandidateFramePointer },
2068     { "nativeFocusCandidateHasNextTextfield", "()Z",
2069         (void*) focusCandidateHasNextTextfield },
2070     { "nativeFocusCandidateIsPassword", "()Z",
2071         (void*) nativeFocusCandidateIsPassword },
2072     { "nativeFocusCandidateIsRtlText", "()Z",
2073         (void*) nativeFocusCandidateIsRtlText },
2074     { "nativeFocusCandidateIsTextInput", "()Z",
2075         (void*) nativeFocusCandidateIsTextInput },
2076     { "nativeFocusCandidateMaxLength", "()I",
2077         (void*) nativeFocusCandidateMaxLength },
2078     { "nativeFocusCandidateName", "()Ljava/lang/String;",
2079         (void*) nativeFocusCandidateName },
2080     { "nativeFocusCandidateNodeBounds", "()Landroid/graphics/Rect;",
2081         (void*) nativeFocusCandidateNodeBounds },
2082     { "nativeFocusCandidatePaddingRect", "()Landroid/graphics/Rect;",
2083         (void*) nativeFocusCandidatePaddingRect },
2084     { "nativeFocusCandidatePointer", "()I",
2085         (void*) nativeFocusCandidatePointer },
2086     { "nativeFocusCandidateText", "()Ljava/lang/String;",
2087         (void*) nativeFocusCandidateText },
2088     { "nativeFocusCandidateTextSize", "()I",
2089         (void*) nativeFocusCandidateTextSize },
2090     { "nativeFocusCandidateType", "()I",
2091         (void*) nativeFocusCandidateType },
2092     { "nativeFocusIsPlugin", "()Z",
2093         (void*) nativeFocusIsPlugin },
2094     { "nativeFocusNodeBounds", "()Landroid/graphics/Rect;",
2095         (void*) nativeFocusNodeBounds },
2096     { "nativeFocusNodePointer", "()I",
2097         (void*) nativeFocusNodePointer },
2098     { "nativeGetCursorRingBounds", "()Landroid/graphics/Rect;",
2099         (void*) nativeGetCursorRingBounds },
2100     { "nativeGetSelection", "()Ljava/lang/String;",
2101         (void*) nativeGetSelection },
2102     { "nativeHasCursorNode", "()Z",
2103         (void*) nativeHasCursorNode },
2104     { "nativeHasFocusNode", "()Z",
2105         (void*) nativeHasFocusNode },
2106     { "nativeHideCursor", "()V",
2107         (void*) nativeHideCursor },
2108     { "nativeHitSelection", "(II)Z",
2109         (void*) nativeHitSelection },
2110     { "nativeImageURI", "(II)Ljava/lang/String;",
2111         (void*) nativeImageURI },
2112     { "nativeInstrumentReport", "()V",
2113         (void*) nativeInstrumentReport },
2114     { "nativeMotionUp", "(III)Z",
2115         (void*) nativeMotionUp },
2116     { "nativeMoveCursor", "(IIZ)Z",
2117         (void*) nativeMoveCursor },
2118     { "nativeMoveCursorToNextTextInput", "()Z",
2119         (void*) nativeMoveCursorToNextTextInput },
2120     { "nativeMoveGeneration", "()I",
2121         (void*) nativeMoveGeneration },
2122     { "nativeMoveSelection", "(II)V",
2123         (void*) nativeMoveSelection },
2124     { "nativePointInNavCache", "(III)Z",
2125         (void*) nativePointInNavCache },
2126     { "nativeRecordButtons", "(ZZZ)V",
2127         (void*) nativeRecordButtons },
2128     { "nativeResetSelection", "()V",
2129         (void*) nativeResetSelection },
2130     { "nativeSelectAll", "()V",
2131         (void*) nativeSelectAll },
2132     { "nativeSelectBestAt", "(Landroid/graphics/Rect;)V",
2133         (void*) nativeSelectBestAt },
2134     { "nativeSelectionX", "()I",
2135         (void*) nativeSelectionX },
2136     { "nativeSelectionY", "()I",
2137         (void*) nativeSelectionY },
2138     { "nativeSetExtendSelection", "()V",
2139         (void*) nativeSetExtendSelection },
2140     { "nativeSetFindIsEmpty", "()V",
2141         (void*) nativeSetFindIsEmpty },
2142     { "nativeSetFindIsUp", "(Z)V",
2143         (void*) nativeSetFindIsUp },
2144     { "nativeSetFollowedLink", "(Z)V",
2145         (void*) nativeSetFollowedLink },
2146     { "nativeSetHeightCanMeasure", "(Z)V",
2147         (void*) nativeSetHeightCanMeasure },
2148     { "nativeSetRootLayer", "(I)V",
2149         (void*) nativeSetRootLayer },
2150     { "nativeSetSelectionPointer", "(ZFII)V",
2151         (void*) nativeSetSelectionPointer },
2152     { "nativeStartSelection", "(II)Z",
2153         (void*) nativeStartSelection },
2154     { "nativeSubtractLayers", "(Landroid/graphics/Rect;)Landroid/graphics/Rect;",
2155         (void*) nativeSubtractLayers },
2156     { "nativeTextGeneration", "()I",
2157         (void*) nativeTextGeneration },
2158     { "nativeUpdateCachedTextfield", "(Ljava/lang/String;I)V",
2159         (void*) nativeUpdateCachedTextfield },
2160     {  "nativeWordSelection", "(II)Z",
2161         (void*) nativeWordSelection },
2162     { "nativeGetBlockLeftEdge", "(IIF)I",
2163         (void*) nativeGetBlockLeftEdge },
2164 };
2165 
register_webview(JNIEnv * env)2166 int register_webview(JNIEnv* env)
2167 {
2168     jclass clazz = env->FindClass("android/webkit/WebView");
2169     LOG_ASSERT(clazz, "Unable to find class android/webkit/WebView");
2170     gWebViewField = env->GetFieldID(clazz, "mNativeClass", "I");
2171     LOG_ASSERT(gWebViewField, "Unable to find android/webkit/WebView.mNativeClass");
2172 
2173     return jniRegisterNativeMethods(env, "android/webkit/WebView", gJavaWebViewMethods, NELEM(gJavaWebViewMethods));
2174 }
2175 
2176 } // namespace android
2177