check to see if nav cache is up to date on tap

- WebKit/android/jni/WebViewCore.cpp
- WebKit/android/jni/WebViewCore.h
Add validNodeAndBounds() to determine if the clicked cached
node is good. First check to see if the pointer
to the frame and node still exist in the DOM. If
they do, see if the hit test bounds they point
to is the same as when the cache was recorded.

-  WebKit/android/nav/CacheBuilder.cpp
-  WebKit/android/nav/CachedNode.h
Record the original absolute bounds for later
comparison.

-  WebKit/android/nav/CacheBuilder.h
Make getAreaRect() public so it can be called by
validation.

- WebKit/android/nav/WebView.cpp
Enhance motionUp() with additional validation:
use pointInNavCache() to see if there's a cached node;
wait for message from webkit to see if bounds is unchanged;
then use motionUp() to pass the original or altered click.

This is a two-part change with frameworks/base.

Fixes http://b/2249425
diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp
index 4bff8a7..e62b362 100644
--- a/WebKit/android/jni/WebViewCore.cpp
+++ b/WebKit/android/jni/WebViewCore.cpp
@@ -2632,6 +2632,21 @@
     checkException(env);
 }
 
+bool WebViewCore::validNodeAndBounds(Frame* frame, Node* node,
+    const IntRect& originalAbsoluteBounds)
+{
+    bool valid = CacheBuilder::validNode(m_mainFrame, frame, node);
+    if (!valid)
+        return false;
+    RenderObject* renderer = node->renderer();
+    if (!renderer)
+        return false;
+    IntRect absBounds = node->hasTagName(HTMLNames::areaTag)
+        ? CacheBuilder::getAreaRect(static_cast<HTMLAreaElement*>(node))
+        : renderer->absoluteBoundingBoxRect();
+    return absBounds == originalAbsoluteBounds;
+}
+
 //----------------------------------------------------------------------
 // Native JNI methods
 //----------------------------------------------------------------------
@@ -3219,6 +3234,22 @@
     plugin->exitFullScreen(false);
 }
 
+static WebCore::IntRect jrect_to_webrect(JNIEnv* env, jobject obj)
+{
+    int L, T, R, B;
+    GraphicsJNI::get_jrect(env, obj, &L, &T, &R, &B);
+    return WebCore::IntRect(L, T, R - L, B - T);
+}
+
+static bool ValidNodeAndBounds(JNIEnv *env, jobject obj, int frame, int node,
+    jobject rect)
+{
+    IntRect nativeRect = jrect_to_webrect(env, rect);
+    return GET_NATIVE_VIEW(env, obj)->validNodeAndBounds(
+            reinterpret_cast<Frame*>(frame),
+            reinterpret_cast<Node*>(node), nativeRect);
+}
+
 // ----------------------------------------------------------------------------
 
 /*
@@ -3315,6 +3346,8 @@
         (void*) ProvideVisitedHistory },
     { "nativeFullScreenPluginHidden", "(I)V",
         (void*) FullScreenPluginHidden },
+    { "nativeValidNodeAndBounds", "(IILandroid/graphics/Rect;)Z",
+        (void*) ValidNodeAndBounds },
 };
 
 int register_webviewcore(JNIEnv* env)
diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h
index 3f00f3c..21dd51b 100644
--- a/WebKit/android/jni/WebViewCore.h
+++ b/WebKit/android/jni/WebViewCore.h
@@ -397,6 +397,7 @@
         // Destroys a SurfaceView for a plugin
         void destroySurface(jobject childView);
 
+        bool validNodeAndBounds(Frame* , Node* , const IntRect& );
         // other public functions
     public:
         // Open a file chooser for selecting a file to upload
diff --git a/WebKit/android/nav/CacheBuilder.cpp b/WebKit/android/nav/CacheBuilder.cpp
index f854e71..ce78c29 100644
--- a/WebKit/android/nav/CacheBuilder.cpp
+++ b/WebKit/android/nav/CacheBuilder.cpp
@@ -1005,11 +1005,13 @@
         CachedInput cachedInput;
         IntRect bounds;
         IntRect absBounds;
+        IntRect originalAbsBounds;
         WTF::Vector<IntRect>* columns = NULL;
         if (node->hasTagName(HTMLNames::areaTag)) {
             type = AREA_CACHEDNODETYPE;
             HTMLAreaElement* area = static_cast<HTMLAreaElement*>(node);
             bounds = getAreaRect(area);
+            originalAbsBounds = bounds;
             bounds.move(globalOffsetX, globalOffsetY);
             absBounds = bounds;
             isUnclipped = true;  // FIXME: areamaps require more effort to detect
@@ -1022,6 +1024,7 @@
 
         // some common setup
         absBounds = nodeRenderer->absoluteBoundingBoxRect();
+        originalAbsBounds = absBounds;
         absBounds.move(globalOffsetX, globalOffsetY);
         hasClip = nodeRenderer->hasOverflowClip();
 
@@ -1212,6 +1215,7 @@
         cachedNode.setIsFocus(isFocus);
         cachedNode.setIsTransparent(isTransparent);
         cachedNode.setIsUnclipped(isUnclipped);
+        cachedNode.setOriginalAbsoluteBounds(originalAbsBounds);
         cachedNode.setParentIndex(last->mCachedNodeIndex);
         cachedNode.setParentGroup(ParentWithChildren(node));
         cachedNode.setTabIndex(tabIndex);
diff --git a/WebKit/android/nav/CacheBuilder.h b/WebKit/android/nav/CacheBuilder.h
index 6cf1817..ff395d3 100644
--- a/WebKit/android/nav/CacheBuilder.h
+++ b/WebKit/android/nav/CacheBuilder.h
@@ -90,6 +90,7 @@
         mAllowableTypes & ~PHONE_CACHEDNODE_BIT); }
     static FoundState FindAddress(const UChar* , unsigned length, int* start,
         int* end, bool caseInsensitive);
+    static IntRect getAreaRect(const HTMLAreaElement* area);
     static void GetGlobalOffset(Frame* , int* x, int * y);
     static void GetGlobalOffset(Node* , int* x, int * y);
     static bool validNode(Frame* startFrame, void* framePtr, void* nodePtr);
@@ -227,7 +228,6 @@
     static Frame* FrameAnd(CacheBuilder* focusNav);
     static Frame* FrameAnd(const CacheBuilder* focusNav);
     static CacheBuilder* Builder(Frame* );
-    static IntRect getAreaRect(const HTMLAreaElement* area);
     static Frame* HasFrame(Node* );
     static bool HasOverOrOut(Node* );
     static bool HasTriggerEvent(Node* );
diff --git a/WebKit/android/nav/CachedNode.h b/WebKit/android/nav/CachedNode.h
index a2e1f39..a433a47 100644
--- a/WebKit/android/nav/CachedNode.h
+++ b/WebKit/android/nav/CachedNode.h
@@ -129,6 +129,8 @@
     int navableRects() const { return mNavableRects; }
     void* nodePointer() const { return mNode; }
     bool noSecondChance() const { return mCondition > SECOND_CHANCE_END; }
+    const WebCore::IntRect& originalAbsoluteBounds() const {
+        return mOriginalAbsoluteBounds; }
     const CachedNode* parent() const { return document() + mParentIndex; }
     void* parentGroup() const { return mParentGroup; }
     int parentIndex() const { return mParentIndex; }
@@ -143,6 +145,8 @@
     void setHasCursorRing(bool hasRing) { mHasCursorRing = hasRing; }
     void setHasMouseOver(bool hasMouseOver) { mHasMouseOver = hasMouseOver; }
     void setHitBounds(const WebCore::IntRect& bounds) { mHitBounds = bounds; }
+    void setOriginalAbsoluteBounds(const WebCore::IntRect& bounds) {
+        mOriginalAbsoluteBounds = bounds; }
     void setIndex(int index) { mIndex = index; }
     void setIsCursor(bool isCursor) { mIsCursor = isCursor; }
     void setIsFocus(bool isFocus) { mIsFocus = isFocus; }
@@ -166,6 +170,7 @@
     WebCore::String mExport;
     WebCore::IntRect mBounds;
     WebCore::IntRect mHitBounds;
+    WebCore::IntRect mOriginalAbsoluteBounds;
     WTF::Vector<WebCore::IntRect> mCursorRing;
     void* mNode; // WebCore::Node*, only used to match pointers
     void* mParentGroup; // WebCore::Node*, only used to match pointers
diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp
index 3232a74..c29cb22 100644
--- a/WebKit/android/nav/WebView.cpp
+++ b/WebKit/android/nav/WebView.cpp
@@ -907,17 +907,32 @@
     root->rootHistory()->setNavBounds(rect);
 }
 
+
+
+const CachedNode* m_cacheHitNode;
+const CachedFrame* m_cacheHitFrame;
+
+bool pointInNavCache(int x, int y, int slop)
+{
+    CachedRoot* root = getFrameCache(AllowNewer);
+    if (!root)
+        return false;
+    IntRect rect = IntRect(x - slop, y - slop, slop * 2, slop * 2);
+    int rx, ry;
+    return (m_cacheHitNode = findAt(root, rect, &m_cacheHitFrame, &rx, &ry));
+}
+
 bool motionUp(int x, int y, int slop)
 {
     bool pageScrolled = false;
     m_followedLink = false;
-    const CachedFrame* frame;
-    WebCore::IntRect rect = WebCore::IntRect(x - slop, y - slop, slop * 2, slop * 2);
+    IntRect rect = IntRect(x - slop, y - slop, slop * 2, slop * 2);
     int rx, ry;
     CachedRoot* root = getFrameCache(AllowNewer);
     if (!root)
-        return false;
-    const CachedNode* result = findAt(root, rect, &frame, &rx, &ry);
+        return 0;
+    const CachedFrame* frame = 0;
+    const CachedNode* result = slop ? findAt(root, rect, &frame, &rx, &ry) : 0;
     if (!result) {
         DBG_NAV_LOGD("no nodes found root=%p", root);
         setNavBounds(rect);
@@ -1372,6 +1387,29 @@
     return ret;
 }
 
+static int nativeCacheHitFramePointer(JNIEnv *env, jobject obj)
+{
+    return reinterpret_cast<int>(GET_NATIVE_VIEW(env, obj)
+            ->m_cacheHitFrame->framePointer());
+}
+
+static jobject nativeCacheHitNodeBounds(JNIEnv *env, jobject obj)
+{
+    WebCore::IntRect bounds = GET_NATIVE_VIEW(env, obj)
+        ->m_cacheHitNode->originalAbsoluteBounds();
+    jclass rectClass = env->FindClass("android/graphics/Rect");
+    jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
+    jobject rect = env->NewObject(rectClass, init, bounds.x(),
+        bounds.y(), bounds.right(), bounds.bottom());
+    return rect;
+}
+
+static int nativeCacheHitNodePointer(JNIEnv *env, jobject obj)
+{
+    return reinterpret_cast<int>(GET_NATIVE_VIEW(env, obj)
+        ->m_cacheHitNode->nodePointer());
+}
+
 static void nativeClearCursor(JNIEnv *env, jobject obj)
 {
     WebView* view = GET_NATIVE_VIEW(env, obj);
@@ -1782,6 +1820,12 @@
     return root ? root->textGeneration() : 0;
 }
 
+static bool nativePointInNavCache(JNIEnv *env, jobject obj,
+    int x, int y, int slop)
+{
+    return GET_NATIVE_VIEW(env, obj)->pointInNavCache(x, y, slop);
+}
+
 static bool nativeMotionUp(JNIEnv *env, jobject obj,
     int x, int y, int slop)
 {
@@ -2049,6 +2093,12 @@
  * JNI registration
  */
 static JNINativeMethod gJavaWebViewMethods[] = {
+    { "nativeCacheHitFramePointer", "()I",
+        (void*) nativeCacheHitFramePointer },
+    { "nativeCacheHitNodeBounds", "()Landroid/graphics/Rect;",
+        (void*) nativeCacheHitNodeBounds },
+    { "nativeCacheHitNodePointer", "()I",
+        (void*) nativeCacheHitNodePointer },
     { "nativeClearCursor", "()V",
         (void*) nativeClearCursor },
     { "nativeCreate", "(I)V",
@@ -2145,6 +2195,8 @@
         (void*) nativeMoveGeneration },
     { "nativeMoveSelection", "(IIZ)V",
         (void*) nativeMoveSelection },
+    { "nativePointInNavCache", "(III)Z",
+        (void*) nativePointInNavCache },
     { "nativeRecordButtons", "(ZZZ)V",
         (void*) nativeRecordButtons },
     { "nativeSelectBestAt", "(Landroid/graphics/Rect;)V",