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