WebView.cpp revision 296d05c7bd54360261dedc8d387a7bf9f52ca41b
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 "BaseLayerAndroid.h" 33#include "DrawExtra.h" 34#include "Frame.h" 35#include "GraphicsJNI.h" 36#include "HTMLInputElement.h" 37#include "IntPoint.h" 38#include "IntRect.h" 39#include "LayerAndroid.h" 40#include "Node.h" 41#include "utils/Functor.h" 42#include "private/hwui/DrawGlInfo.h" 43#include "PlatformGraphicsContext.h" 44#include "PlatformString.h" 45#include "ScrollableLayerAndroid.h" 46#include "SelectText.h" 47#include "SkCanvas.h" 48#include "SkDumpCanvas.h" 49#include "SkPicture.h" 50#include "SkRect.h" 51#include "SkTime.h" 52#include "TilesManager.h" 53#include "WebCoreJni.h" 54#include "WebRequestContext.h" 55#include "WebViewCore.h" 56#include "android_graphics.h" 57 58#ifdef GET_NATIVE_VIEW 59#undef GET_NATIVE_VIEW 60#endif 61 62#define GET_NATIVE_VIEW(env, obj) ((WebView*)env->GetIntField(obj, gWebViewField)) 63 64#include <JNIUtility.h> 65#include <JNIHelp.h> 66#include <jni.h> 67#include <androidfw/KeycodeLabels.h> 68#include <wtf/text/AtomicString.h> 69#include <wtf/text/CString.h> 70 71// Free as much as we possible can 72#define TRIM_MEMORY_COMPLETE 80 73// Free a lot (all textures gone) 74#define TRIM_MEMORY_MODERATE 60 75// More moderate free (keep bare minimum to restore quickly-ish - possibly clear all textures) 76#define TRIM_MEMORY_BACKGROUND 40 77// Moderate free (clear cached tiles, keep visible ones) 78#define TRIM_MEMORY_UI_HIDDEN 20 79// Duration to show the pressed cursor ring 80#define PRESSED_STATE_DURATION 400 81 82namespace android { 83 84static jfieldID gWebViewField; 85 86//------------------------------------- 87 88static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[], const char signature[]) 89{ 90 jmethodID m = env->GetMethodID(clazz, name, signature); 91 ALOG_ASSERT(m, "Could not find method %s", name); 92 return m; 93} 94 95//------------------------------------- 96// This class provides JNI for making calls into native code from the UI side 97// of the multi-threaded WebView. 98class WebView 99{ 100public: 101enum FrameCachePermission { 102 DontAllowNewer, 103 AllowNewer 104}; 105 106#define DRAW_EXTRAS_SIZE 2 107enum DrawExtras { // keep this in sync with WebView.java 108 DrawExtrasNone = 0, 109 DrawExtrasSelection = 1, 110 DrawExtrasCursorRing = 2 111}; 112 113struct JavaGlue { 114 jweak m_obj; 115 jmethodID m_scrollBy; 116 jmethodID m_getScaledMaxXScroll; 117 jmethodID m_getScaledMaxYScroll; 118 jmethodID m_getVisibleRect; 119 jmethodID m_viewInvalidate; 120 jmethodID m_viewInvalidateRect; 121 jmethodID m_postInvalidateDelayed; 122 jmethodID m_pageSwapCallback; 123 jfieldID m_rectLeft; 124 jfieldID m_rectTop; 125 jmethodID m_rectWidth; 126 jmethodID m_rectHeight; 127 AutoJObject object(JNIEnv* env) { 128 return getRealObject(env, m_obj); 129 } 130} m_javaGlue; 131 132WebView(JNIEnv* env, jobject javaWebView, int viewImpl, WTF::String drawableDir, 133 bool isHighEndGfx) 134 : m_isHighEndGfx(isHighEndGfx) 135{ 136 memset(m_extras, 0, DRAW_EXTRAS_SIZE * sizeof(DrawExtra*)); 137 jclass clazz = env->FindClass("android/webkit/WebViewClassic"); 138 m_javaGlue.m_obj = env->NewWeakGlobalRef(javaWebView); 139 m_javaGlue.m_scrollBy = GetJMethod(env, clazz, "setContentScrollBy", "(IIZ)Z"); 140 m_javaGlue.m_getScaledMaxXScroll = GetJMethod(env, clazz, "getScaledMaxXScroll", "()I"); 141 m_javaGlue.m_getScaledMaxYScroll = GetJMethod(env, clazz, "getScaledMaxYScroll", "()I"); 142 m_javaGlue.m_getVisibleRect = GetJMethod(env, clazz, "sendOurVisibleRect", "()Landroid/graphics/Rect;"); 143 m_javaGlue.m_viewInvalidate = GetJMethod(env, clazz, "viewInvalidate", "()V"); 144 m_javaGlue.m_viewInvalidateRect = GetJMethod(env, clazz, "viewInvalidate", "(IIII)V"); 145 m_javaGlue.m_postInvalidateDelayed = GetJMethod(env, clazz, 146 "viewInvalidateDelayed", "(JIIII)V"); 147 m_javaGlue.m_pageSwapCallback = GetJMethod(env, clazz, "pageSwapCallback", "(Z)V"); 148 env->DeleteLocalRef(clazz); 149 150 jclass rectClass = env->FindClass("android/graphics/Rect"); 151 ALOG_ASSERT(rectClass, "Could not find Rect class"); 152 m_javaGlue.m_rectLeft = env->GetFieldID(rectClass, "left", "I"); 153 m_javaGlue.m_rectTop = env->GetFieldID(rectClass, "top", "I"); 154 m_javaGlue.m_rectWidth = GetJMethod(env, rectClass, "width", "()I"); 155 m_javaGlue.m_rectHeight = GetJMethod(env, rectClass, "height", "()I"); 156 env->DeleteLocalRef(rectClass); 157 158 env->SetIntField(javaWebView, gWebViewField, (jint)this); 159 m_viewImpl = (WebViewCore*) viewImpl; 160 m_generation = 0; 161 m_heightCanMeasure = false; 162 m_lastDx = 0; 163 m_lastDxTime = 0; 164 m_baseLayer = 0; 165 m_glDrawFunctor = 0; 166 m_isDrawingPaused = false; 167#if USE(ACCELERATED_COMPOSITING) 168 m_glWebViewState = 0; 169#endif 170} 171 172~WebView() 173{ 174 if (m_javaGlue.m_obj) 175 { 176 JNIEnv* env = JSC::Bindings::getJNIEnv(); 177 env->DeleteWeakGlobalRef(m_javaGlue.m_obj); 178 m_javaGlue.m_obj = 0; 179 } 180#if USE(ACCELERATED_COMPOSITING) 181 // We must remove the m_glWebViewState prior to deleting m_baseLayer. If we 182 // do not remove it here, we risk having BaseTiles trying to paint using a 183 // deallocated base layer. 184 stopGL(); 185#endif 186 SkSafeUnref(m_baseLayer); 187 delete m_glDrawFunctor; 188 for (int i = 0; i < DRAW_EXTRAS_SIZE; i++) 189 delete m_extras[i]; 190} 191 192DrawExtra* getDrawExtra(DrawExtras extras) 193{ 194 if (extras == DrawExtrasNone) 195 return 0; 196 return m_extras[extras - 1]; 197} 198 199void stopGL() 200{ 201#if USE(ACCELERATED_COMPOSITING) 202 delete m_glWebViewState; 203 m_glWebViewState = 0; 204#endif 205} 206 207WebViewCore* getWebViewCore() const { 208 return m_viewImpl; 209} 210 211void scrollRectOnScreen(const IntRect& rect) 212{ 213 if (rect.isEmpty()) 214 return; 215 int dx = 0; 216 int left = rect.x(); 217 int right = rect.maxX(); 218 if (left < m_visibleRect.fLeft) 219 dx = left - m_visibleRect.fLeft; 220 // Only scroll right if the entire width can fit on screen. 221 else if (right > m_visibleRect.fRight 222 && right - left < m_visibleRect.width()) 223 dx = right - m_visibleRect.fRight; 224 int dy = 0; 225 int top = rect.y(); 226 int bottom = rect.maxY(); 227 if (top < m_visibleRect.fTop) 228 dy = top - m_visibleRect.fTop; 229 // Only scroll down if the entire height can fit on screen 230 else if (bottom > m_visibleRect.fBottom 231 && bottom - top < m_visibleRect.height()) 232 dy = bottom - m_visibleRect.fBottom; 233 if ((dx|dy) == 0 || !scrollBy(dx, dy)) 234 return; 235 viewInvalidate(); 236} 237 238bool drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect, 239 WebCore::IntRect& webViewRect, int titleBarHeight, 240 WebCore::IntRect& clip, float scale, int extras) 241{ 242#if USE(ACCELERATED_COMPOSITING) 243 if (!m_baseLayer) 244 return false; 245 246 if (!m_glWebViewState) { 247 TilesManager::instance()->setHighEndGfx(m_isHighEndGfx); 248 m_glWebViewState = new GLWebViewState(); 249 if (m_baseLayer->content()) { 250 SkRegion region; 251 SkIRect rect; 252 rect.set(0, 0, m_baseLayer->content()->width(), m_baseLayer->content()->height()); 253 region.setRect(rect); 254 m_baseLayer->markAsDirty(region); 255 m_glWebViewState->setBaseLayer(m_baseLayer, false, true); 256 } 257 } 258 259 DrawExtra* extra = getDrawExtra((DrawExtras) extras); 260 261 m_glWebViewState->glExtras()->setDrawExtra(extra); 262 263 // Make sure we have valid coordinates. We might not have valid coords 264 // if the zoom manager is still initializing. We will be redrawn 265 // once the correct scale is set 266 if (!m_visibleRect.isFinite()) 267 return false; 268 bool treesSwapped = false; 269 bool newTreeHasAnim = false; 270 bool ret = m_glWebViewState->drawGL(viewRect, m_visibleRect, invalRect, 271 webViewRect, titleBarHeight, clip, scale, 272 &treesSwapped, &newTreeHasAnim); 273 if (treesSwapped) { 274 ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); 275 JNIEnv* env = JSC::Bindings::getJNIEnv(); 276 AutoJObject javaObject = m_javaGlue.object(env); 277 if (javaObject.get()) { 278 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_pageSwapCallback, newTreeHasAnim); 279 checkException(env); 280 } 281 } 282 if (ret) 283 return !m_isDrawingPaused; 284#endif 285 return false; 286} 287 288PictureSet* draw(SkCanvas* canvas, SkColor bgColor, DrawExtras extras, bool split) 289{ 290 PictureSet* ret = 0; 291 if (!m_baseLayer) { 292 canvas->drawColor(bgColor); 293 return ret; 294 } 295 296 // draw the content of the base layer first 297 PictureSet* content = m_baseLayer->content(); 298 int sc = canvas->save(SkCanvas::kClip_SaveFlag); 299 canvas->clipRect(SkRect::MakeLTRB(0, 0, content->width(), 300 content->height()), SkRegion::kDifference_Op); 301 canvas->drawColor(bgColor); 302 canvas->restoreToCount(sc); 303 if (content->draw(canvas)) 304 ret = split ? new PictureSet(*content) : 0; 305 306 DrawExtra* extra = getDrawExtra(extras); 307 if (extra) 308 extra->draw(canvas, 0); 309 310#if USE(ACCELERATED_COMPOSITING) 311 LayerAndroid* compositeLayer = compositeRoot(); 312 if (compositeLayer) { 313 // call this to be sure we've adjusted for any scrolling or animations 314 // before we actually draw 315 compositeLayer->updateLayerPositions(m_visibleRect); 316 compositeLayer->updatePositions(); 317 // We have to set the canvas' matrix on the base layer 318 // (to have fixed layers work as intended) 319 SkAutoCanvasRestore restore(canvas, true); 320 m_baseLayer->setMatrix(canvas->getTotalMatrix()); 321 canvas->resetMatrix(); 322 m_baseLayer->draw(canvas, extra); 323 } 324 if (extra) { 325 IntRect dummy; // inval area, unused for now 326 extra->drawLegacy(canvas, compositeLayer, &dummy); 327 } 328#endif 329 return ret; 330} 331 332int getScaledMaxXScroll() 333{ 334 ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); 335 JNIEnv* env = JSC::Bindings::getJNIEnv(); 336 AutoJObject javaObject = m_javaGlue.object(env); 337 if (!javaObject.get()) 338 return 0; 339 int result = env->CallIntMethod(javaObject.get(), m_javaGlue.m_getScaledMaxXScroll); 340 checkException(env); 341 return result; 342} 343 344int getScaledMaxYScroll() 345{ 346 ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); 347 JNIEnv* env = JSC::Bindings::getJNIEnv(); 348 AutoJObject javaObject = m_javaGlue.object(env); 349 if (!javaObject.get()) 350 return 0; 351 int result = env->CallIntMethod(javaObject.get(), m_javaGlue.m_getScaledMaxYScroll); 352 checkException(env); 353 return result; 354} 355 356IntRect getVisibleRect() 357{ 358 IntRect rect; 359 ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); 360 JNIEnv* env = JSC::Bindings::getJNIEnv(); 361 AutoJObject javaObject = m_javaGlue.object(env); 362 if (!javaObject.get()) 363 return rect; 364 jobject jRect = env->CallObjectMethod(javaObject.get(), m_javaGlue.m_getVisibleRect); 365 checkException(env); 366 rect.setX(env->GetIntField(jRect, m_javaGlue.m_rectLeft)); 367 checkException(env); 368 rect.setY(env->GetIntField(jRect, m_javaGlue.m_rectTop)); 369 checkException(env); 370 rect.setWidth(env->CallIntMethod(jRect, m_javaGlue.m_rectWidth)); 371 checkException(env); 372 rect.setHeight(env->CallIntMethod(jRect, m_javaGlue.m_rectHeight)); 373 checkException(env); 374 env->DeleteLocalRef(jRect); 375 checkException(env); 376 return rect; 377} 378 379#if USE(ACCELERATED_COMPOSITING) 380static const ScrollableLayerAndroid* findScrollableLayer( 381 const LayerAndroid* parent, int x, int y, SkIRect* foundBounds) { 382 SkRect bounds; 383 parent->bounds(&bounds); 384 // Check the parent bounds first; this will clip to within a masking layer's 385 // bounds. 386 if (parent->masksToBounds() && !bounds.contains(x, y)) 387 return 0; 388 // Move the hit test local to parent. 389 x -= bounds.fLeft; 390 y -= bounds.fTop; 391 int count = parent->countChildren(); 392 while (count--) { 393 const LayerAndroid* child = parent->getChild(count); 394 const ScrollableLayerAndroid* result = findScrollableLayer(child, x, y, 395 foundBounds); 396 if (result) { 397 foundBounds->offset(bounds.fLeft, bounds.fTop); 398 if (parent->masksToBounds()) { 399 if (bounds.width() < foundBounds->width()) 400 foundBounds->fRight = foundBounds->fLeft + bounds.width(); 401 if (bounds.height() < foundBounds->height()) 402 foundBounds->fBottom = foundBounds->fTop + bounds.height(); 403 } 404 return result; 405 } 406 } 407 if (parent->contentIsScrollable()) { 408 foundBounds->set(0, 0, bounds.width(), bounds.height()); 409 return static_cast<const ScrollableLayerAndroid*>(parent); 410 } 411 return 0; 412} 413#endif 414 415int scrollableLayer(int x, int y, SkIRect* layerRect, SkIRect* bounds) 416{ 417#if USE(ACCELERATED_COMPOSITING) 418 const LayerAndroid* layerRoot = compositeRoot(); 419 if (!layerRoot) 420 return 0; 421 const ScrollableLayerAndroid* result = findScrollableLayer(layerRoot, x, y, 422 bounds); 423 if (result) { 424 result->getScrollRect(layerRect); 425 return result->uniqueId(); 426 } 427#endif 428 return 0; 429} 430 431void scrollLayer(int layerId, int x, int y) 432{ 433 if (m_glWebViewState) 434 m_glWebViewState->scrollLayer(layerId, x, y); 435} 436 437void setHeightCanMeasure(bool measure) 438{ 439 m_heightCanMeasure = measure; 440} 441 442String getSelection() 443{ 444 SelectText* select = static_cast<SelectText*>( 445 getDrawExtra(WebView::DrawExtrasSelection)); 446 if (select) 447 return select->getText(); 448 return String(); 449} 450 451bool scrollBy(int dx, int dy) 452{ 453 ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); 454 455 JNIEnv* env = JSC::Bindings::getJNIEnv(); 456 AutoJObject javaObject = m_javaGlue.object(env); 457 if (!javaObject.get()) 458 return false; 459 bool result = env->CallBooleanMethod(javaObject.get(), m_javaGlue.m_scrollBy, dx, dy, true); 460 checkException(env); 461 return result; 462} 463 464void setIsScrolling(bool isScrolling) 465{ 466#if USE(ACCELERATED_COMPOSITING) 467 if (m_glWebViewState) 468 m_glWebViewState->setIsScrolling(isScrolling); 469#endif 470} 471 472void viewInvalidate() 473{ 474 JNIEnv* env = JSC::Bindings::getJNIEnv(); 475 AutoJObject javaObject = m_javaGlue.object(env); 476 if (!javaObject.get()) 477 return; 478 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_viewInvalidate); 479 checkException(env); 480} 481 482void viewInvalidateRect(int l, int t, int r, int b) 483{ 484 JNIEnv* env = JSC::Bindings::getJNIEnv(); 485 AutoJObject javaObject = m_javaGlue.object(env); 486 if (!javaObject.get()) 487 return; 488 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_viewInvalidateRect, l, r, t, b); 489 checkException(env); 490} 491 492void postInvalidateDelayed(int64_t delay, const WebCore::IntRect& bounds) 493{ 494 JNIEnv* env = JSC::Bindings::getJNIEnv(); 495 AutoJObject javaObject = m_javaGlue.object(env); 496 if (!javaObject.get()) 497 return; 498 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_postInvalidateDelayed, 499 delay, bounds.x(), bounds.y(), bounds.maxX(), bounds.maxY()); 500 checkException(env); 501} 502 503LayerAndroid* compositeRoot() const 504{ 505 ALOG_ASSERT(!m_baseLayer || m_baseLayer->countChildren() == 1, 506 "base layer can't have more than one child %s", __FUNCTION__); 507 if (m_baseLayer && m_baseLayer->countChildren() == 1) 508 return static_cast<LayerAndroid*>(m_baseLayer->getChild(0)); 509 else 510 return 0; 511} 512 513#if ENABLE(ANDROID_OVERFLOW_SCROLL) 514static void copyScrollPositionRecursive(const LayerAndroid* from, 515 LayerAndroid* root) 516{ 517 if (!from || !root) 518 return; 519 for (int i = 0; i < from->countChildren(); i++) { 520 const LayerAndroid* l = from->getChild(i); 521 if (l->contentIsScrollable()) { 522 const SkPoint& pos = l->getPosition(); 523 LayerAndroid* match = root->findById(l->uniqueId()); 524 if (match && match->contentIsScrollable()) 525 match->setPosition(pos.fX, pos.fY); 526 } 527 copyScrollPositionRecursive(l, root); 528 } 529} 530#endif 531 532bool setBaseLayer(BaseLayerAndroid* layer, SkRegion& inval, bool showVisualIndicator, 533 bool isPictureAfterFirstLayout) 534{ 535 bool queueFull = false; 536#if USE(ACCELERATED_COMPOSITING) 537 if (m_glWebViewState) { 538 if (layer) 539 layer->markAsDirty(inval); 540 queueFull = m_glWebViewState->setBaseLayer(layer, showVisualIndicator, 541 isPictureAfterFirstLayout); 542 } 543#endif 544 545#if ENABLE(ANDROID_OVERFLOW_SCROLL) 546 if (layer) { 547 // TODO: the below tree copies are only necessary in software rendering 548 LayerAndroid* newCompositeRoot = static_cast<LayerAndroid*>(layer->getChild(0)); 549 copyScrollPositionRecursive(compositeRoot(), newCompositeRoot); 550 } 551#endif 552 SkSafeUnref(m_baseLayer); 553 m_baseLayer = layer; 554 555 return queueFull; 556} 557 558void replaceBaseContent(PictureSet* set) 559{ 560 if (!m_baseLayer) 561 return; 562 m_baseLayer->setContent(*set); 563 delete set; 564} 565 566void copyBaseContentToPicture(SkPicture* picture) 567{ 568 if (!m_baseLayer) 569 return; 570 PictureSet* content = m_baseLayer->content(); 571 m_baseLayer->drawCanvas(picture->beginRecording(content->width(), content->height(), 572 SkPicture::kUsePathBoundsForClip_RecordingFlag)); 573 picture->endRecording(); 574} 575 576bool hasContent() { 577 if (!m_baseLayer) 578 return false; 579 return !m_baseLayer->content()->isEmpty(); 580} 581 582void setFunctor(Functor* functor) { 583 delete m_glDrawFunctor; 584 m_glDrawFunctor = functor; 585} 586 587Functor* getFunctor() { 588 return m_glDrawFunctor; 589} 590 591BaseLayerAndroid* getBaseLayer() { 592 return m_baseLayer; 593} 594 595void setVisibleRect(SkRect& visibleRect) { 596 m_visibleRect = visibleRect; 597} 598 599void setDrawExtra(DrawExtra *extra, DrawExtras type) 600{ 601 if (type == DrawExtrasNone) 602 return; 603 DrawExtra* old = m_extras[type - 1]; 604 m_extras[type - 1] = extra; 605 if (old != extra) { 606 delete old; 607 } 608} 609 610void setTextSelection(SelectText *selection) { 611 setDrawExtra(selection, DrawExtrasSelection); 612} 613 614int getHandleLayerId(SelectText::HandleId handleId, SkIRect& cursorRect) { 615 SelectText* selectText = static_cast<SelectText*>(getDrawExtra(DrawExtrasSelection)); 616 if (!selectText || !m_baseLayer) 617 return -1; 618 int layerId = selectText->caretLayerId(handleId); 619 IntRect rect = selectText->caretRect(handleId); 620 if (layerId != -1) { 621 // We need to make sure the drawTransform is up to date as this is 622 // called before a draw() or drawGL() 623 m_baseLayer->updateLayerPositions(m_visibleRect); 624 LayerAndroid* root = compositeRoot(); 625 LayerAndroid* layer = root ? root->findById(layerId) : 0; 626 if (layer && layer->drawTransform()) 627 rect = layer->drawTransform()->mapRect(rect); 628 } 629 cursorRect.set(rect.x(), rect.y(), rect.maxX(), rect.maxY()); 630 return layerId; 631} 632 633 bool m_isDrawingPaused; 634private: // local state for WebView 635 // private to getFrameCache(); other functions operate in a different thread 636 WebViewCore* m_viewImpl; 637 int m_generation; // associate unique ID with sent kit focus to match with ui 638 // Corresponds to the same-named boolean on the java side. 639 bool m_heightCanMeasure; 640 int m_lastDx; 641 SkMSec m_lastDxTime; 642 DrawExtra* m_extras[DRAW_EXTRAS_SIZE]; 643 BaseLayerAndroid* m_baseLayer; 644 Functor* m_glDrawFunctor; 645#if USE(ACCELERATED_COMPOSITING) 646 GLWebViewState* m_glWebViewState; 647#endif 648 SkRect m_visibleRect; 649 bool m_isHighEndGfx; 650}; // end of WebView class 651 652 653/** 654 * This class holds a function pointer and parameters for calling drawGL into a specific 655 * viewport. The pointer to the Functor will be put on a framework display list to be called 656 * when the display list is replayed. 657 */ 658class GLDrawFunctor : Functor { 659 public: 660 GLDrawFunctor(WebView* _wvInstance, 661 bool(WebView::*_funcPtr)(WebCore::IntRect&, WebCore::IntRect*, 662 WebCore::IntRect&, int, WebCore::IntRect&, jfloat, jint), 663 WebCore::IntRect _viewRect, float _scale, int _extras) { 664 wvInstance = _wvInstance; 665 funcPtr = _funcPtr; 666 viewRect = _viewRect; 667 scale = _scale; 668 extras = _extras; 669 }; 670 status_t operator()(int messageId, void* data) { 671 if (viewRect.isEmpty()) { 672 // NOOP operation if viewport is empty 673 return 0; 674 } 675 676 WebCore::IntRect inval; 677 int titlebarHeight = webViewRect.height() - viewRect.height(); 678 679 uirenderer::DrawGlInfo* info = reinterpret_cast<uirenderer::DrawGlInfo*>(data); 680 WebCore::IntRect localViewRect = viewRect; 681 if (info->isLayer) 682 localViewRect.move(-1 * localViewRect.x(), -1 * localViewRect.y()); 683 684 WebCore::IntRect clip(info->clipLeft, info->clipTop, 685 info->clipRight - info->clipLeft, 686 info->clipBottom - info->clipTop); 687 TilesManager::instance()->shader()->setWebViewMatrix(info->transform, info->isLayer); 688 689 bool retVal = (*wvInstance.*funcPtr)(localViewRect, &inval, webViewRect, 690 titlebarHeight, clip, scale, extras); 691 if (retVal) { 692 IntRect finalInval; 693 if (inval.isEmpty()) { 694 finalInval = webViewRect; 695 retVal = true; 696 } else { 697 finalInval.setX(webViewRect.x() + inval.x()); 698 finalInval.setY(webViewRect.y() + titlebarHeight + inval.y()); 699 finalInval.setWidth(inval.width()); 700 finalInval.setHeight(inval.height()); 701 } 702 info->dirtyLeft = finalInval.x(); 703 info->dirtyTop = finalInval.y(); 704 info->dirtyRight = finalInval.maxX(); 705 info->dirtyBottom = finalInval.maxY(); 706 } 707 // return 1 if invalidation needed, 0 otherwise 708 return retVal ? 1 : 0; 709 } 710 void updateRect(WebCore::IntRect& _viewRect) { 711 viewRect = _viewRect; 712 } 713 void updateViewRect(WebCore::IntRect& _viewRect) { 714 webViewRect = _viewRect; 715 } 716 void updateScale(float _scale) { 717 scale = _scale; 718 } 719 private: 720 WebView* wvInstance; 721 bool (WebView::*funcPtr)(WebCore::IntRect&, WebCore::IntRect*, 722 WebCore::IntRect&, int, WebCore::IntRect&, float, int); 723 WebCore::IntRect viewRect; 724 WebCore::IntRect webViewRect; 725 jfloat scale; 726 jint extras; 727}; 728 729/* 730 * Native JNI methods 731 */ 732 733static void nativeCreate(JNIEnv *env, jobject obj, int viewImpl, 734 jstring drawableDir, jboolean isHighEndGfx) 735{ 736 WTF::String dir = jstringToWtfString(env, drawableDir); 737 new WebView(env, obj, viewImpl, dir, isHighEndGfx); 738 // NEED THIS OR SOMETHING LIKE IT! 739 //Release(obj); 740} 741 742static WebCore::IntRect jrect_to_webrect(JNIEnv* env, jobject obj) 743{ 744 if (obj) { 745 int L, T, R, B; 746 GraphicsJNI::get_jrect(env, obj, &L, &T, &R, &B); 747 return WebCore::IntRect(L, T, R - L, B - T); 748 } else 749 return WebCore::IntRect(); 750} 751 752static SkRect jrectf_to_rect(JNIEnv* env, jobject obj) 753{ 754 SkRect rect = SkRect::MakeEmpty(); 755 if (obj) 756 GraphicsJNI::jrectf_to_rect(env, obj, &rect); 757 return rect; 758} 759 760static jint nativeDraw(JNIEnv *env, jobject obj, jobject canv, 761 jobject visible, jint color, 762 jint extras, jboolean split) { 763 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv); 764 WebView* webView = GET_NATIVE_VIEW(env, obj); 765 SkRect visibleRect = jrectf_to_rect(env, visible); 766 webView->setVisibleRect(visibleRect); 767 PictureSet* pictureSet = webView->draw(canvas, color, 768 static_cast<WebView::DrawExtras>(extras), split); 769 return reinterpret_cast<jint>(pictureSet); 770} 771 772static jint nativeGetDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView, 773 jobject jrect, jobject jviewrect, 774 jobject jvisiblerect, 775 jfloat scale, jint extras) { 776 WebCore::IntRect viewRect = jrect_to_webrect(env, jrect); 777 WebView *wvInstance = (WebView*) nativeView; 778 SkRect visibleRect = jrectf_to_rect(env, jvisiblerect); 779 wvInstance->setVisibleRect(visibleRect); 780 781 GLDrawFunctor* functor = new GLDrawFunctor(wvInstance, 782 &android::WebView::drawGL, viewRect, scale, extras); 783 wvInstance->setFunctor((Functor*) functor); 784 785 WebCore::IntRect webViewRect = jrect_to_webrect(env, jviewrect); 786 functor->updateViewRect(webViewRect); 787 788 return (jint)functor; 789} 790 791static void nativeUpdateDrawGLFunction(JNIEnv *env, jobject obj, jobject jrect, 792 jobject jviewrect, jobject jvisiblerect, jfloat scale) { 793 WebView *wvInstance = GET_NATIVE_VIEW(env, obj); 794 if (wvInstance) { 795 GLDrawFunctor* functor = (GLDrawFunctor*) wvInstance->getFunctor(); 796 if (functor) { 797 WebCore::IntRect viewRect = jrect_to_webrect(env, jrect); 798 functor->updateRect(viewRect); 799 800 SkRect visibleRect = jrectf_to_rect(env, jvisiblerect); 801 wvInstance->setVisibleRect(visibleRect); 802 803 WebCore::IntRect webViewRect = jrect_to_webrect(env, jviewrect); 804 functor->updateViewRect(webViewRect); 805 806 functor->updateScale(scale); 807 } 808 } 809} 810 811static bool nativeEvaluateLayersAnimations(JNIEnv *env, jobject obj, jint nativeView) 812{ 813 // only call in software rendering, initialize and evaluate animations 814#if USE(ACCELERATED_COMPOSITING) 815 LayerAndroid* root = ((WebView*)nativeView)->compositeRoot(); 816 if (root) { 817 root->initAnimations(); 818 return root->evaluateAnimations(); 819 } 820#endif 821 return false; 822} 823 824static bool nativeSetBaseLayer(JNIEnv *env, jobject obj, jint nativeView, jint layer, jobject inval, 825 jboolean showVisualIndicator, 826 jboolean isPictureAfterFirstLayout) 827{ 828 BaseLayerAndroid* layerImpl = reinterpret_cast<BaseLayerAndroid*>(layer); 829 SkRegion invalRegion; 830 if (inval) 831 invalRegion = *GraphicsJNI::getNativeRegion(env, inval); 832 return ((WebView*)nativeView)->setBaseLayer(layerImpl, invalRegion, showVisualIndicator, 833 isPictureAfterFirstLayout); 834} 835 836static BaseLayerAndroid* nativeGetBaseLayer(JNIEnv *env, jobject obj) 837{ 838 return GET_NATIVE_VIEW(env, obj)->getBaseLayer(); 839} 840 841static void nativeReplaceBaseContent(JNIEnv *env, jobject obj, jint content) 842{ 843 PictureSet* set = reinterpret_cast<PictureSet*>(content); 844 GET_NATIVE_VIEW(env, obj)->replaceBaseContent(set); 845} 846 847static void nativeCopyBaseContentToPicture(JNIEnv *env, jobject obj, jobject pict) 848{ 849 SkPicture* picture = GraphicsJNI::getNativePicture(env, pict); 850 GET_NATIVE_VIEW(env, obj)->copyBaseContentToPicture(picture); 851} 852 853static bool nativeHasContent(JNIEnv *env, jobject obj) 854{ 855 return GET_NATIVE_VIEW(env, obj)->hasContent(); 856} 857 858static jobject nativeLayerBounds(JNIEnv* env, jobject obj, jint jlayer) 859{ 860 SkRect r; 861#if USE(ACCELERATED_COMPOSITING) 862 LayerAndroid* layer = (LayerAndroid*) jlayer; 863 r = layer->bounds(); 864#else 865 r.setEmpty(); 866#endif 867 SkIRect irect; 868 r.round(&irect); 869 jclass rectClass = env->FindClass("android/graphics/Rect"); 870 jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V"); 871 jobject rect = env->NewObject(rectClass, init, irect.fLeft, irect.fTop, 872 irect.fRight, irect.fBottom); 873 env->DeleteLocalRef(rectClass); 874 return rect; 875} 876 877static void nativeSetHeightCanMeasure(JNIEnv *env, jobject obj, bool measure) 878{ 879 WebView* view = GET_NATIVE_VIEW(env, obj); 880 ALOG_ASSERT(view, "view not set in nativeSetHeightCanMeasure"); 881 view->setHeightCanMeasure(measure); 882} 883 884static void nativeDestroy(JNIEnv *env, jobject obj) 885{ 886 WebView* view = GET_NATIVE_VIEW(env, obj); 887 ALOGD("nativeDestroy view: %p", view); 888 ALOG_ASSERT(view, "view not set in nativeDestroy"); 889 delete view; 890} 891 892static void nativeStopGL(JNIEnv *env, jobject obj) 893{ 894 GET_NATIVE_VIEW(env, obj)->stopGL(); 895} 896 897static jobject nativeGetSelection(JNIEnv *env, jobject obj) 898{ 899 WebView* view = GET_NATIVE_VIEW(env, obj); 900 ALOG_ASSERT(view, "view not set in %s", __FUNCTION__); 901 String selection = view->getSelection(); 902 return wtfStringToJstring(env, selection); 903} 904 905static void nativeDiscardAllTextures(JNIEnv *env, jobject obj) 906{ 907 //discard all textures for debugging/test purposes, but not gl backing memory 908 bool allTextures = true, deleteGLTextures = false; 909 TilesManager::instance()->discardTextures(allTextures, deleteGLTextures); 910} 911 912static void nativeTileProfilingStart(JNIEnv *env, jobject obj) 913{ 914 TilesManager::instance()->getProfiler()->start(); 915} 916 917static float nativeTileProfilingStop(JNIEnv *env, jobject obj) 918{ 919 return TilesManager::instance()->getProfiler()->stop(); 920} 921 922static void nativeTileProfilingClear(JNIEnv *env, jobject obj) 923{ 924 TilesManager::instance()->getProfiler()->clear(); 925} 926 927static int nativeTileProfilingNumFrames(JNIEnv *env, jobject obj) 928{ 929 return TilesManager::instance()->getProfiler()->numFrames(); 930} 931 932static int nativeTileProfilingNumTilesInFrame(JNIEnv *env, jobject obj, int frame) 933{ 934 return TilesManager::instance()->getProfiler()->numTilesInFrame(frame); 935} 936 937static int nativeTileProfilingGetInt(JNIEnv *env, jobject obj, int frame, int tile, jstring jkey) 938{ 939 WTF::String key = jstringToWtfString(env, jkey); 940 TileProfileRecord* record = TilesManager::instance()->getProfiler()->getTile(frame, tile); 941 942 if (key == "left") 943 return record->left; 944 if (key == "top") 945 return record->top; 946 if (key == "right") 947 return record->right; 948 if (key == "bottom") 949 return record->bottom; 950 if (key == "level") 951 return record->level; 952 if (key == "isReady") 953 return record->isReady ? 1 : 0; 954 return -1; 955} 956 957static float nativeTileProfilingGetFloat(JNIEnv *env, jobject obj, int frame, int tile, jstring jkey) 958{ 959 TileProfileRecord* record = TilesManager::instance()->getProfiler()->getTile(frame, tile); 960 return record->scale; 961} 962 963#ifdef ANDROID_DUMP_DISPLAY_TREE 964static void dumpToFile(const char text[], void* file) { 965 fwrite(text, 1, strlen(text), reinterpret_cast<FILE*>(file)); 966 fwrite("\n", 1, 1, reinterpret_cast<FILE*>(file)); 967} 968#endif 969 970static bool nativeSetProperty(JNIEnv *env, jobject obj, jstring jkey, jstring jvalue) 971{ 972 WTF::String key = jstringToWtfString(env, jkey); 973 WTF::String value = jstringToWtfString(env, jvalue); 974 if (key == "inverted") { 975 bool shouldInvert = (value == "true"); 976 TilesManager::instance()->setInvertedScreen(shouldInvert); 977 return true; 978 } 979 else if (key == "inverted_contrast") { 980 float contrast = value.toFloat(); 981 TilesManager::instance()->setInvertedScreenContrast(contrast); 982 return true; 983 } 984 else if (key == "enable_cpu_upload_path") { 985 TilesManager::instance()->transferQueue()->setTextureUploadType( 986 value == "true" ? CpuUpload : GpuUpload); 987 return true; 988 } 989 else if (key == "use_minimal_memory") { 990 TilesManager::instance()->setUseMinimalMemory(value == "true"); 991 return true; 992 } 993 else if (key == "use_double_buffering") { 994 TilesManager::instance()->setUseDoubleBuffering(value == "true"); 995 return true; 996 } 997 else if (key == "tree_updates") { 998 TilesManager::instance()->clearContentUpdates(); 999 return true; 1000 } 1001 return false; 1002} 1003 1004static jstring nativeGetProperty(JNIEnv *env, jobject obj, jstring jkey) 1005{ 1006 WTF::String key = jstringToWtfString(env, jkey); 1007 if (key == "tree_updates") { 1008 int updates = TilesManager::instance()->getContentUpdates(); 1009 WTF::String wtfUpdates = WTF::String::number(updates); 1010 return wtfStringToJstring(env, wtfUpdates); 1011 } 1012 return 0; 1013} 1014 1015static void nativeOnTrimMemory(JNIEnv *env, jobject obj, jint level) 1016{ 1017 if (TilesManager::hardwareAccelerationEnabled()) { 1018 // When we got TRIM_MEMORY_MODERATE or TRIM_MEMORY_COMPLETE, we should 1019 // make sure the transfer queue is empty and then abandon the Surface 1020 // Texture to avoid ANR b/c framework may destroy the EGL context. 1021 // Refer to WindowManagerImpl.java for conditions we followed. 1022 TilesManager* tilesManager = TilesManager::instance(); 1023 if (level >= TRIM_MEMORY_MODERATE 1024 && !tilesManager->highEndGfx()) { 1025 ALOGD("OnTrimMemory with EGL Context %p", eglGetCurrentContext()); 1026 tilesManager->transferQueue()->emptyQueue(); 1027 tilesManager->shader()->cleanupGLResources(); 1028 tilesManager->videoLayerManager()->cleanupGLResources(); 1029 } 1030 1031 bool freeAllTextures = (level > TRIM_MEMORY_UI_HIDDEN), glTextures = true; 1032 tilesManager->discardTextures(freeAllTextures, glTextures); 1033 } 1034} 1035 1036static void nativeDumpDisplayTree(JNIEnv* env, jobject jwebview, jstring jurl) 1037{ 1038#ifdef ANDROID_DUMP_DISPLAY_TREE 1039 WebView* view = GET_NATIVE_VIEW(env, jwebview); 1040 ALOG_ASSERT(view, "view not set in %s", __FUNCTION__); 1041 1042 if (view && view->getWebViewCore()) { 1043 FILE* file = fopen(DISPLAY_TREE_LOG_FILE, "w"); 1044 if (file) { 1045 SkFormatDumper dumper(dumpToFile, file); 1046 // dump the URL 1047 if (jurl) { 1048 const char* str = env->GetStringUTFChars(jurl, 0); 1049 SkDebugf("Dumping %s to %s\n", str, DISPLAY_TREE_LOG_FILE); 1050 dumpToFile(str, file); 1051 env->ReleaseStringUTFChars(jurl, str); 1052 } 1053 // now dump the display tree 1054 SkDumpCanvas canvas(&dumper); 1055 // this will playback the picture into the canvas, which will 1056 // spew its contents to the dumper 1057 view->draw(&canvas, 0, WebView::DrawExtrasNone, false); 1058 // we're done with the file now 1059 fwrite("\n", 1, 1, file); 1060 fclose(file); 1061 } 1062#if USE(ACCELERATED_COMPOSITING) 1063 const LayerAndroid* rootLayer = view->compositeRoot(); 1064 if (rootLayer) { 1065 FILE* file = fopen(LAYERS_TREE_LOG_FILE,"w"); 1066 if (file) { 1067 rootLayer->dumpLayers(file, 0); 1068 fclose(file); 1069 } 1070 } 1071#endif 1072 } 1073#endif 1074} 1075 1076static int nativeScrollableLayer(JNIEnv* env, jobject jwebview, jint x, jint y, 1077 jobject rect, jobject bounds) 1078{ 1079 WebView* view = GET_NATIVE_VIEW(env, jwebview); 1080 ALOG_ASSERT(view, "view not set in %s", __FUNCTION__); 1081 SkIRect nativeRect, nativeBounds; 1082 int id = view->scrollableLayer(x, y, &nativeRect, &nativeBounds); 1083 if (rect) 1084 GraphicsJNI::irect_to_jrect(nativeRect, env, rect); 1085 if (bounds) 1086 GraphicsJNI::irect_to_jrect(nativeBounds, env, bounds); 1087 return id; 1088} 1089 1090static bool nativeScrollLayer(JNIEnv* env, jobject obj, jint layerId, jint x, 1091 jint y) 1092{ 1093#if ENABLE(ANDROID_OVERFLOW_SCROLL) 1094 WebView* view = GET_NATIVE_VIEW(env, obj); 1095 view->scrollLayer(layerId, x, y); 1096 1097 //TODO: the below only needed for the SW rendering path 1098 LayerAndroid* root = view->compositeRoot(); 1099 if (!root) 1100 return false; 1101 LayerAndroid* layer = root->findById(layerId); 1102 if (!layer || !layer->contentIsScrollable()) 1103 return false; 1104 return static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y); 1105#endif 1106 return false; 1107} 1108 1109static void nativeSetIsScrolling(JNIEnv* env, jobject jwebview, jboolean isScrolling) 1110{ 1111 WebView* view = GET_NATIVE_VIEW(env, jwebview); 1112 ALOG_ASSERT(view, "view not set in %s", __FUNCTION__); 1113 view->setIsScrolling(isScrolling); 1114} 1115 1116static void nativeUseHardwareAccelSkia(JNIEnv*, jobject, jboolean enabled) 1117{ 1118 BaseRenderer::setCurrentRendererType(enabled ? BaseRenderer::Ganesh : BaseRenderer::Raster); 1119} 1120 1121static int nativeGetBackgroundColor(JNIEnv* env, jobject obj) 1122{ 1123 WebView* view = GET_NATIVE_VIEW(env, obj); 1124 BaseLayerAndroid* baseLayer = view->getBaseLayer(); 1125 if (baseLayer) { 1126 WebCore::Color color = baseLayer->getBackgroundColor(); 1127 if (color.isValid()) 1128 return SkColorSetARGB(color.alpha(), color.red(), 1129 color.green(), color.blue()); 1130 } 1131 return SK_ColorWHITE; 1132} 1133 1134static void nativeSetPauseDrawing(JNIEnv *env, jobject obj, jint nativeView, 1135 jboolean pause) 1136{ 1137 ((WebView*)nativeView)->m_isDrawingPaused = pause; 1138} 1139 1140static void nativeSetTextSelection(JNIEnv *env, jobject obj, jint nativeView, 1141 jint selectionPtr) 1142{ 1143 SelectText* selection = reinterpret_cast<SelectText*>(selectionPtr); 1144 reinterpret_cast<WebView*>(nativeView)->setTextSelection(selection); 1145} 1146 1147static jint nativeGetHandleLayerId(JNIEnv *env, jobject obj, jint nativeView, 1148 jint handleIndex, jobject cursorRect) 1149{ 1150 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1151 SkIRect nativeRect; 1152 int layerId = webview->getHandleLayerId((SelectText::HandleId) handleIndex, nativeRect); 1153 if (cursorRect) 1154 GraphicsJNI::irect_to_jrect(nativeRect, env, cursorRect); 1155 return layerId; 1156} 1157 1158static jboolean nativeIsBaseFirst(JNIEnv *env, jobject obj, jint nativeView) 1159{ 1160 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1161 SelectText* select = static_cast<SelectText*>( 1162 webview->getDrawExtra(WebView::DrawExtrasSelection)); 1163 return select ? select->isBaseFirst() : false; 1164} 1165 1166/* 1167 * JNI registration 1168 */ 1169static JNINativeMethod gJavaWebViewMethods[] = { 1170 { "nativeCreate", "(ILjava/lang/String;Z)V", 1171 (void*) nativeCreate }, 1172 { "nativeDestroy", "()V", 1173 (void*) nativeDestroy }, 1174 { "nativeDraw", "(Landroid/graphics/Canvas;Landroid/graphics/RectF;IIZ)I", 1175 (void*) nativeDraw }, 1176 { "nativeGetDrawGLFunction", "(ILandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;FI)I", 1177 (void*) nativeGetDrawGLFunction }, 1178 { "nativeUpdateDrawGLFunction", "(Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;F)V", 1179 (void*) nativeUpdateDrawGLFunction }, 1180 { "nativeDumpDisplayTree", "(Ljava/lang/String;)V", 1181 (void*) nativeDumpDisplayTree }, 1182 { "nativeEvaluateLayersAnimations", "(I)Z", 1183 (void*) nativeEvaluateLayersAnimations }, 1184 { "nativeGetSelection", "()Ljava/lang/String;", 1185 (void*) nativeGetSelection }, 1186 { "nativeLayerBounds", "(I)Landroid/graphics/Rect;", 1187 (void*) nativeLayerBounds }, 1188 { "nativeSetHeightCanMeasure", "(Z)V", 1189 (void*) nativeSetHeightCanMeasure }, 1190 { "nativeSetBaseLayer", "(IILandroid/graphics/Region;ZZ)Z", 1191 (void*) nativeSetBaseLayer }, 1192 { "nativeGetBaseLayer", "()I", 1193 (void*) nativeGetBaseLayer }, 1194 { "nativeReplaceBaseContent", "(I)V", 1195 (void*) nativeReplaceBaseContent }, 1196 { "nativeCopyBaseContentToPicture", "(Landroid/graphics/Picture;)V", 1197 (void*) nativeCopyBaseContentToPicture }, 1198 { "nativeHasContent", "()Z", 1199 (void*) nativeHasContent }, 1200 { "nativeDiscardAllTextures", "()V", 1201 (void*) nativeDiscardAllTextures }, 1202 { "nativeTileProfilingStart", "()V", 1203 (void*) nativeTileProfilingStart }, 1204 { "nativeTileProfilingStop", "()F", 1205 (void*) nativeTileProfilingStop }, 1206 { "nativeTileProfilingClear", "()V", 1207 (void*) nativeTileProfilingClear }, 1208 { "nativeTileProfilingNumFrames", "()I", 1209 (void*) nativeTileProfilingNumFrames }, 1210 { "nativeTileProfilingNumTilesInFrame", "(I)I", 1211 (void*) nativeTileProfilingNumTilesInFrame }, 1212 { "nativeTileProfilingGetInt", "(IILjava/lang/String;)I", 1213 (void*) nativeTileProfilingGetInt }, 1214 { "nativeTileProfilingGetFloat", "(IILjava/lang/String;)F", 1215 (void*) nativeTileProfilingGetFloat }, 1216 { "nativeStopGL", "()V", 1217 (void*) nativeStopGL }, 1218 { "nativeScrollableLayer", "(IILandroid/graphics/Rect;Landroid/graphics/Rect;)I", 1219 (void*) nativeScrollableLayer }, 1220 { "nativeScrollLayer", "(III)Z", 1221 (void*) nativeScrollLayer }, 1222 { "nativeSetIsScrolling", "(Z)V", 1223 (void*) nativeSetIsScrolling }, 1224 { "nativeUseHardwareAccelSkia", "(Z)V", 1225 (void*) nativeUseHardwareAccelSkia }, 1226 { "nativeGetBackgroundColor", "()I", 1227 (void*) nativeGetBackgroundColor }, 1228 { "nativeSetProperty", "(Ljava/lang/String;Ljava/lang/String;)Z", 1229 (void*) nativeSetProperty }, 1230 { "nativeGetProperty", "(Ljava/lang/String;)Ljava/lang/String;", 1231 (void*) nativeGetProperty }, 1232 { "nativeOnTrimMemory", "(I)V", 1233 (void*) nativeOnTrimMemory }, 1234 { "nativeSetPauseDrawing", "(IZ)V", 1235 (void*) nativeSetPauseDrawing }, 1236 { "nativeSetTextSelection", "(II)V", 1237 (void*) nativeSetTextSelection }, 1238 { "nativeGetHandleLayerId", "(IILandroid/graphics/Rect;)I", 1239 (void*) nativeGetHandleLayerId }, 1240 { "nativeIsBaseFirst", "(I)Z", 1241 (void*) nativeIsBaseFirst }, 1242}; 1243 1244int registerWebView(JNIEnv* env) 1245{ 1246 jclass clazz = env->FindClass("android/webkit/WebViewClassic"); 1247 ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebViewClassic"); 1248 gWebViewField = env->GetFieldID(clazz, "mNativeClass", "I"); 1249 ALOG_ASSERT(gWebViewField, "Unable to find android/webkit/WebViewClassic.mNativeClass"); 1250 env->DeleteLocalRef(clazz); 1251 1252 return jniRegisterNativeMethods(env, "android/webkit/WebViewClassic", gJavaWebViewMethods, NELEM(gJavaWebViewMethods)); 1253} 1254 1255} // namespace android 1256