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