Do not merge: fix array overwrite crasher

If two nodes have the same coordinates, one is deleted.
If either has focus, the focus needs to be transfered
to the other, and the focus index recomputed, so the
index won't point to the wrong node.

If the two nodes are at the end of the list, the
index may point off the end of the array, subsequently
crashing on access.

This is a possible security issue.

Change-Id: I1ca934074637fbf68e40318fbc354e28c6b474ba
http://b/3043268
diff --git a/WebKit/android/nav/CacheBuilder.cpp b/WebKit/android/nav/CacheBuilder.cpp
index 7ee2a16..214058c 100644
--- a/WebKit/android/nav/CacheBuilder.cpp
+++ b/WebKit/android/nav/CacheBuilder.cpp
@@ -960,7 +960,7 @@
         FocusTracker* last = &tracker.last();
         int lastChildIndex = cachedFrame->size() - 1;
         while (node == last->mLastChild) {
-            if (CleanUpContainedNodes(cachedFrame, last, lastChildIndex))
+            if (CleanUpContainedNodes(cachedRoot, cachedFrame, last, lastChildIndex))
                 cacheIndex--;
             tracker.removeLast();
             lastChildIndex = last->mCachedNodeIndex;
@@ -1344,14 +1344,14 @@
     while (tracker.size() > 1) {
         FocusTracker* last = &tracker.last();
         int lastChildIndex = cachedFrame->size() - 1;
-        if (CleanUpContainedNodes(cachedFrame, last, lastChildIndex))
+        if (CleanUpContainedNodes(cachedRoot, cachedFrame, last, lastChildIndex))
             cacheIndex--;
         tracker.removeLast();
     }
 }
 
-bool CacheBuilder::CleanUpContainedNodes(CachedFrame* cachedFrame, 
-    const FocusTracker* last, int lastChildIndex)
+bool CacheBuilder::CleanUpContainedNodes(CachedRoot* cachedRoot,
+    CachedFrame* cachedFrame, const FocusTracker* last, int lastChildIndex)
 {
     // if outer is body, disable outer
     // or if there's more than one inner, disable outer
@@ -1380,9 +1380,12 @@
         HasTriggerEvent(lastNode) == false;
     if (onlyChildCached->parent() == lastCached)
         onlyChildCached->setParentIndex(lastCached->parentIndex());
+    bool hasFocus = lastCached->isFocus() || onlyChildCached->isFocus();
     if (outerIsMouseMoveOnly || onlyChild->isKeyboardFocusable(NULL))
         *lastCached = *onlyChildCached;
     cachedFrame->removeLast();
+    if (hasFocus)
+        cachedRoot->setCachedFocus(cachedFrame, cachedFrame->lastNode());
     return true;
 }
 
diff --git a/WebKit/android/nav/CacheBuilder.h b/WebKit/android/nav/CacheBuilder.h
index 4ded58d..407d590 100644
--- a/WebKit/android/nav/CacheBuilder.h
+++ b/WebKit/android/nav/CacheBuilder.h
@@ -215,7 +215,7 @@
     static bool NodeHasEventListeners(Node* node, AtomicString* eventTypes, int length);
     void BuildFrame(Frame* root, Frame* frame,
         CachedRoot* cachedRoot, CachedFrame* cachedFrame);
-    bool CleanUpContainedNodes(CachedFrame* cachedFrame, 
+    bool CleanUpContainedNodes(CachedRoot* cachedRoot, CachedFrame* cachedFrame, 
         const FocusTracker* last, int lastChildIndex);
     static bool ConstructTextRect(Text* textNode,
         InlineTextBox* textBox, int start, int relEnd, int x, int y,