AndroidHitTestResult.cpp revision dea0c131566f424923425970fe5621305d136e5a
1/* 2 * Copyright 2012, 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 "AndroidHitTestResult" 27 28#include "config.h" 29#include "AndroidHitTestResult.h" 30 31#include "Element.h" 32#include "HitTestResult.h" 33#include "KURL.h" 34#include "LayerAndroid.h" 35#include "PlatformString.h" 36#include "Range.h" 37#include "RenderLayer.h" 38#include "RenderLayerBacking.h" 39#include "RenderObject.h" 40#include "WebCoreJni.h" 41#include "WebViewCore.h" 42 43#include <cutils/log.h> 44#include <JNIHelp.h> 45#include <JNIUtility.h> 46 47namespace android { 48 49using namespace WebCore; 50 51static bool gJniInitialized = false; 52static struct JavaGlue { 53 jmethodID m_hitTestInit; 54 jfieldID m_hitTestLinkUrl; 55 jfieldID m_hitTestAnchorText; 56 jfieldID m_hitTestImageUrl; 57 jfieldID m_hitTestAltDisplayString; 58 jfieldID m_hitTestTitle; 59 jfieldID m_hitTestEditable; 60 jfieldID m_hitTestTouchRects; 61 jfieldID m_hitTestTapHighlightColor; 62} gJavaGlue; 63 64struct field { 65 jclass m_class; 66 const char *m_fieldName; 67 const char *m_fieldType; 68 jfieldID *m_jfield; 69}; 70 71static void InitJni(JNIEnv* env) 72{ 73 if (gJniInitialized) 74 return; 75 76 jclass rectClass = env->FindClass("android/graphics/Rect"); 77 ALOG_ASSERT(rectClass, "Could not find android/graphics/Rect"); 78 jclass hitTestClass = env->FindClass("android/webkit/WebViewCore$WebKitHitTest"); 79 ALOG_ASSERT(hitTestClass, "Could not find android/webkit/WebViewCore$WebKitHitTest"); 80 81 gJavaGlue.m_hitTestInit = env->GetMethodID(hitTestClass, "<init>", "()V"); 82 ALOG_ASSERT(gJavaGlue.m_hitTestInit, "Could not find init method on android/webkit/WebViewCore$WebKitHitTest"); 83 84 field fields[] = { 85 { hitTestClass, "mTouchRects", "[Landroid/graphics/Rect;", &gJavaGlue.m_hitTestTouchRects }, 86 { hitTestClass, "mEditable", "Z", &gJavaGlue.m_hitTestEditable }, 87 { hitTestClass, "mLinkUrl", "Ljava/lang/String;", &gJavaGlue.m_hitTestLinkUrl }, 88 { hitTestClass, "mAnchorText", "Ljava/lang/String;", &gJavaGlue.m_hitTestAnchorText }, 89 { hitTestClass, "mImageUrl", "Ljava/lang/String;", &gJavaGlue.m_hitTestImageUrl }, 90 { hitTestClass, "mAltDisplayString", "Ljava/lang/String;", &gJavaGlue.m_hitTestAltDisplayString }, 91 { hitTestClass, "mTitle", "Ljava/lang/String;", &gJavaGlue.m_hitTestTitle }, 92 { hitTestClass, "mTapHighlightColor", "I", &gJavaGlue.m_hitTestTapHighlightColor }, 93 {0, 0, 0, 0}, 94 }; 95 96 for (int i = 0; fields[i].m_jfield; i++) { 97 field *f = &fields[i]; 98 jfieldID field = env->GetFieldID(f->m_class, f->m_fieldName, f->m_fieldType); 99 ALOG_ASSERT(field, "Can't find %s", f->m_fieldName); 100 *(f->m_jfield) = field; 101 } 102 103 gJniInitialized = true; 104} 105 106AndroidHitTestResult::AndroidHitTestResult(WebCore::HitTestResult& hitTestResult) 107 : m_hitTestResult(hitTestResult) 108{ 109} 110 111void setStringField(JNIEnv* env, jobject obj, jfieldID field, const String& str) 112{ 113 jstring jstr = wtfStringToJstring(env, str, false); 114 env->SetObjectField(obj, field, jstr); 115 env->DeleteLocalRef(jstr); 116} 117 118void setRectArray(JNIEnv* env, jobject obj, jfieldID field, Vector<IntRect> &rects) 119{ 120 jobjectArray array = intRectVectorToRectArray(env, rects); 121 env->SetObjectField(obj, field, array); 122 env->DeleteLocalRef(array); 123} 124 125// Some helper macros specific to setting hitTest fields 126#define _SET(jtype, jfield, value) env->Set ## jtype ## Field(hitTest, gJavaGlue.m_hitTest ## jfield, value) 127#define SET_BOOL(jfield, value) _SET(Boolean, jfield, value) 128#define SET_STRING(jfield, value) setStringField(env, hitTest, gJavaGlue.m_hitTest ## jfield, value) 129#define SET_INT(jfield, value) _SET(Int, jfield, value) 130 131jobject AndroidHitTestResult::createJavaObject(JNIEnv* env) 132{ 133 InitJni(env); 134 jclass hitTestClass = env->FindClass("android/webkit/WebViewCore$WebKitHitTest"); 135 ALOG_ASSERT(hitTestClass, "Could not find android/webkit/WebViewCore$WebKitHitTest"); 136 137 jobject hitTest = env->NewObject(hitTestClass, gJavaGlue.m_hitTestInit); 138 setRectArray(env, hitTest, gJavaGlue.m_hitTestTouchRects, m_highlightRects); 139 140 SET_BOOL(Editable, m_hitTestResult.isContentEditable()); 141 SET_STRING(LinkUrl, m_hitTestResult.absoluteLinkURL().string()); 142 SET_STRING(ImageUrl, m_hitTestResult.absoluteImageURL().string()); 143 SET_STRING(AltDisplayString, m_hitTestResult.altDisplayString()); 144 TextDirection titleTextDirection; 145 SET_STRING(Title, m_hitTestResult.title(titleTextDirection)); 146 if (m_hitTestResult.URLElement()) { 147 Element* urlElement = m_hitTestResult.URLElement(); 148 SET_STRING(AnchorText, urlElement->innerText()); 149 if (urlElement->renderer()) { 150 SET_INT(TapHighlightColor, 151 urlElement->renderer()->style()->tapHighlightColor().rgb()); 152 } 153 } 154 155 env->DeleteLocalRef(hitTestClass); 156 157 return hitTest; 158} 159 160} /* namespace android */ 161