Reconcile AOSP master and JellyBean

Change-Id: I7c9f8c596ec815bc110922acccbb346aa7cbb2bf
diff --git a/Android.mk b/Android.mk
index 61bd467..da77333 100644
--- a/Android.mk
+++ b/Android.mk
@@ -35,12 +35,81 @@
     SUPPORT_COMPLEX_SCRIPTS = true
 endif
 
+# Two ways to control which JS engine is used:
+# 1. use JS_ENGINE environment variable, value can be either 'jsc' or 'v8'
+#    This is the preferred way.
+# 2. if JS_ENGINE is not set, or is not 'jsc' or 'v8', this makefile picks
+#    up a default engine to build.
+#    To help setup buildbot, a new environment variable, USE_ALT_JS_ENGINE,
+#    can be set to true, so that two builds can be different but without
+#    specifying which JS engine to use.
+# To enable JIT in Android's JSC, please set ENABLE_JSC_JIT environment
+# variable to true.
+
+# To enable JIT in Android's JSC, please set ENABLE_JSC_JIT environment
+# variable to true.
+
+# Read JS_ENGINE environment variable
+JAVASCRIPT_ENGINE = $(JS_ENGINE)
+
+# We default to the V8 JS engine.
+DEFAULT_ENGINE = v8
+ALT_ENGINE = jsc
+
+ifneq ($(JAVASCRIPT_ENGINE),jsc)
+  ifneq ($(JAVASCRIPT_ENGINE),v8)
+    # No JS engine is specified, pickup the one we want as default.
+    ifeq ($(USE_ALT_JS_ENGINE),true)
+      JAVASCRIPT_ENGINE = $(ALT_ENGINE)
+    else
+      JAVASCRIPT_ENGINE = $(DEFAULT_ENGINE)
+    endif
+  endif
+endif
+
+# On ARM, V8 also requires an ARMv7 CPU, and since we must use jsc, we cannot
+# use the Chrome http stack either.
+ifeq ($(TARGET_ARCH),arm)
+  ifneq ($(strip $(ARCH_ARM_HAVE_ARMV7A)),true)
+    JAVASCRIPT_ENGINE := jsc
+    USE_ALT_HTTP := true
+  endif
+endif
+
+# See if the user has specified a stack they want to use
+HTTP_STACK = $(HTTP)
+# We default to the Chrome HTTP stack.
+DEFAULT_HTTP = chrome
+ALT_HTTP = android
+
+ifneq ($(HTTP_STACK),chrome)
+  ifneq ($(HTTP_STACK),android)
+    # No HTTP stack is specified, pickup the one we want as default.
+    ifeq ($(USE_ALT_HTTP),true)
+      HTTP_STACK = $(ALT_HTTP)
+    else
+      HTTP_STACK = $(DEFAULT_HTTP)
+    endif
+  endif
+endif
+
+# The Chrome stack can not be used with JSC and hence can not be used be used
+# with the simulator.
+ifeq ($(JAVASCRIPT_ENGINE),jsc)
+  ifeq ($(HTTP_STACK),chrome)
+    $(error Can not build with JSC and the Chrome HTTP stack)
+  endif
+endif
+
 # Read the environment variable to determine if Autofill is compiled.
-# The default is on.
+# The default is on. Chrome HTTP stack must be used when Autofill
 # is turned on.
 ifneq ($(ENABLE_AUTOFILL),false)
   ENABLE_AUTOFILL = true
 endif
+ifneq ($(HTTP_STACK),chrome)
+  ENABLE_AUTOFILL = false
+endif
 
 BASE_PATH := $(call my-dir)
 include $(CLEAR_VARS)
@@ -127,11 +196,6 @@
 	$(WEBCORE_PATH)/platform/animation \
 	$(WEBCORE_PATH)/platform/graphics \
 	$(WEBCORE_PATH)/platform/graphics/android \
-	$(WEBCORE_PATH)/platform/graphics/android/context \
-	$(WEBCORE_PATH)/platform/graphics/android/fonts \
-	$(WEBCORE_PATH)/platform/graphics/android/layers \
-	$(WEBCORE_PATH)/platform/graphics/android/rendering \
-	$(WEBCORE_PATH)/platform/graphics/android/utils \
 	$(WEBCORE_PATH)/platform/graphics/filters \
 	$(WEBCORE_PATH)/platform/graphics/gpu \
 	$(WEBCORE_PATH)/platform/graphics/network \
@@ -198,28 +262,38 @@
 	external/chromium/chrome \
 	external/skia
 
-LOCAL_CFLAGS += -DWEBKIT_IMPLEMENTATION=1
-
+ifeq ($(JAVASCRIPT_ENGINE),v8)
 # Include WTF source file.
 d := Source/JavaScriptCore
 LOCAL_PATH := $(BASE_PATH)/$d
 intermediates := $(base_intermediates)/$d
 include $(LOCAL_PATH)/Android.v8.wtf.mk
 WEBKIT_SRC_FILES += $(addprefix $d/,$(LOCAL_SRC_FILES))
+endif  # JAVASCRIPT_ENGINE == v8
 
 # Include source files for WebCore
 d := Source/WebCore
 LOCAL_PATH := $(BASE_PATH)/$d
 intermediates := $(base_intermediates)/$d
 include $(LOCAL_PATH)/Android.mk
+ifeq ($(JAVASCRIPT_ENGINE),jsc)
+include $(LOCAL_PATH)/Android.jscbindings.mk
+endif
+ifeq ($(JAVASCRIPT_ENGINE),v8)
 include $(LOCAL_PATH)/Android.v8bindings.mk
+endif
 WEBKIT_SRC_FILES += $(addprefix $d/,$(LOCAL_SRC_FILES))
 LOCAL_C_INCLUDES += $(BINDING_C_INCLUDES)
 
 # Include the derived source files for WebCore. Uses the same path as
 # WebCore
 include $(LOCAL_PATH)/Android.derived.mk
+ifeq ($(JAVASCRIPT_ENGINE),jsc)
+include $(LOCAL_PATH)/Android.derived.jscbindings.mk
+endif
+ifeq ($(JAVASCRIPT_ENGINE),v8)
 include $(LOCAL_PATH)/Android.derived.v8bindings.mk
+endif
 
 # Include source files for android WebKit port
 d := Source/WebKit
@@ -239,13 +313,23 @@
 LOCAL_CFLAGS += -DALWAYS_INLINE=inline
 # Make sure assert.h is included before assert is defined
 LOCAL_CFLAGS += -include "assert.h"
+ifeq ($(HTTP_STACK),chrome)
 LOCAL_CFLAGS += -DGOOGLEURL
+LOCAL_CFLAGS += -DWTF_USE_CHROME_NETWORK_STACK
+endif # HTTP_STACK == chrome
 LOCAL_CPPFLAGS := -Wno-sign-promo
-LOCAL_CPPFLAGS := -Wno-c++0x-compat
 
 # Adds GL and EGL extensions for the GL backend
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
+# Enable JSC JIT if JSC is used and ENABLE_JSC_JIT environment
+# variable is set to true
+ifeq ($(JAVASCRIPT_ENGINE),jsc)
+ifeq ($(ENABLE_JSC_JIT),true)
+LOCAL_CFLAGS += -DENABLE_ANDROID_JSC_JIT=1
+endif
+endif
+
 ifeq ($(TARGET_ARCH),arm)
 LOCAL_CFLAGS += -Darm
 # remove this warning: "note: the mangling of 'va_list' has changed in GCC 4.4"
@@ -270,36 +354,41 @@
 LOCAL_CFLAGS += -DWTF_USE_ACCELERATED_COMPOSITING=1
 endif
 
+ifeq ($(WEBCORE_INSTRUMENTATION),true)
+LOCAL_CFLAGS += -DANDROID_INSTRUMENT
+endif
+
 # LOCAL_LDLIBS is used in simulator builds only and simulator builds are only
 # valid on Linux
 LOCAL_LDLIBS += -lpthread -ldl
 
 # Build the list of shared libraries
-# We have to use the android version of libdl
 LOCAL_SHARED_LIBRARIES := \
-	libEGL \
-	libGLESv2 \
 	libandroid \
-	libandroidfw \
 	libandroid_runtime \
-	libchromium_net \
-	libcrypto \
+	libnativehelper \
+	libsqlite \
+	libskia \
+	libutils \
+	libui \
 	libcutils \
-	libdl \
-	libgui \
 	libicuuc \
 	libicui18n \
 	libmedia \
-	libmedia_native \
-	libnativehelper \
-	libskia \
-	libsqlite \
-	libssl \
-	libstlport \
-	libutils \
-	libui \
-	libz
+	libEGL \
+	libGLESv2 \
+	libgui
 
+ifeq ($(PLATFORM_VERSION),3.1.4.1.5.9.2.6.5)
+LOCAL_SHARED_LIBRARIES += libsurfaceflinger_client
+endif
+
+ifeq ($(WEBCORE_INSTRUMENTATION),true)
+LOCAL_SHARED_LIBRARIES += libhardware_legacy
+endif
+
+# We have to use the android version of libdl
+LOCAL_SHARED_LIBRARIES += libdl libstlport
 # We have to fake out some headers when using stlport.
 LOCAL_C_INCLUDES += \
 	external/chromium/android
@@ -315,7 +404,14 @@
 endif
 
 # Build the list of static libraries
-LOCAL_STATIC_LIBRARIES := libxml2 libxslt libhyphenation libskiagpu libv8
+LOCAL_STATIC_LIBRARIES := libxml2 libxslt libhyphenation libskiagpu
+ifeq ($(JAVASCRIPT_ENGINE),v8)
+LOCAL_STATIC_LIBRARIES += libv8
+endif
+
+ifeq ($(HTTP_STACK),chrome)
+LOCAL_SHARED_LIBRARIES += libcrypto libssl libz libchromium_net
+endif # HTTP_STACK == chrome
 
 ifeq ($(ENABLE_AUTOFILL),true)
 LOCAL_SHARED_LIBRARIES += libexpat
@@ -336,6 +432,34 @@
 # Build the library all at once
 include $(BUILD_STATIC_LIBRARY)
 
+ifeq ($(JAVASCRIPT_ENGINE),jsc)
+# Now build libjs as a static library.
+include $(CLEAR_VARS)
+LOCAL_MODULE := libjs
+LOCAL_LDLIBS := $(WEBKIT_LDLIBS)
+LOCAL_SHARED_LIBRARIES := $(WEBKIT_SHARED_LIBRARIES)
+LOCAL_STATIC_LIBRARIES := $(WEBKIT_STATIC_LIBRARIES)
+LOCAL_CFLAGS := $(WEBKIT_CFLAGS)
+# Include source files for JavaScriptCore
+d := Source/JavaScriptCore
+LOCAL_PATH := $(BASE_PATH)/$d
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+# Cannot use base_intermediates as this is a new module
+intermediates := $(call local-intermediates-dir)
+include $(LOCAL_PATH)/Android.mk
+# Redefine LOCAL_SRC_FILES with the correct prefix
+LOCAL_SRC_FILES := $(addprefix $d/,$(LOCAL_SRC_FILES))
+# Use the base path to resolve file names
+LOCAL_PATH := $(BASE_PATH)
+# Append jsc intermediate include paths to the WebKit include list.
+LOCAL_C_INCLUDES := $(WEBKIT_C_INCLUDES) \
+	$(intermediates) \
+	$(intermediates)/parser \
+	$(intermediates)/runtime \
+# Build libjs
+include $(BUILD_STATIC_LIBRARY)
+endif  # JAVASCRIPT_ENGINE == jsc
+
 # Now build the shared library using only the exported jni entry point. This
 # will strip out any unused code from the entry point.
 include $(CLEAR_VARS)
@@ -347,26 +471,27 @@
 LOCAL_LDLIBS := $(WEBKIT_LDLIBS)
 LOCAL_SHARED_LIBRARIES := $(WEBKIT_SHARED_LIBRARIES)
 LOCAL_STATIC_LIBRARIES := libwebcore $(WEBKIT_STATIC_LIBRARIES)
+ifeq ($(JAVASCRIPT_ENGINE),jsc)
+LOCAL_STATIC_LIBRARIES += libjs
+endif
 LOCAL_LDFLAGS := -fvisibility=hidden
 LOCAL_CFLAGS := $(WEBKIT_CFLAGS)
 LOCAL_CPPFLAGS := $(WEBKIT_CPPFLAGS)
 LOCAL_C_INCLUDES := $(WEBKIT_C_INCLUDES)
 LOCAL_PATH := $(BASE_PATH)
 LOCAL_SRC_FILES := \
-	Source/WebKit/android/jni/WebCoreJniOnLoad.cpp \
-	Source/WebKit/chromium/src/android/WebDOMTextContentWalker.cpp \
-	Source/WebKit/chromium/src/android/WebHitTestInfo.cpp \
-	Source/WebKit/chromium/src/WebRange.cpp \
-	Source/WebKit/chromium/src/WebString.cpp
+	Source/WebKit/android/jni/WebCoreJniOnLoad.cpp
 
 ifeq ($(ENABLE_AUTOFILL),true)
 # AutoFill requires some cpp files from Chromium to link with
 # libchromium_net. We cannot compile them into libchromium_net
 # because they have cpp file extensions, not .cc.
+LOCAL_CFLAGS += -DWEBKIT_IMPLEMENTATION=1
 LOCAL_SRC_FILES += \
 	Source/WebKit/android/WebCoreSupport/autofill/MainThreadProxy.cpp \
 	Source/WebKit/chromium/src/WebCString.cpp \
-	Source/WebKit/chromium/src/WebRegularExpression.cpp
+	Source/WebKit/chromium/src/WebRegularExpression.cpp \
+	Source/WebKit/chromium/src/WebString.cpp
 endif
 
 # Do this dependency by hand. The reason we have to do this is because the
@@ -379,5 +504,8 @@
 # Build the wds client
 include $(WEBKIT_PATH)/android/wds/client/Android.mk
 
+# Build the performance command line tool.
+include $(WEBKIT_PATH)/android/benchmark/Android.mk
+
 # Build the webkit merge tool.
 include $(BASE_PATH)/Tools/android/webkitmerge/Android.mk
diff --git a/CleanSpec.mk b/CleanSpec.mk
index d2841a3..5b3f9a2 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -77,11 +77,6 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libwebcore_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libwebcore_intermediates)
 
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/LayoutTests/fast/events/touch/document-create-touch-list-crash-expected.txt b/LayoutTests/fast/events/touch/document-create-touch-list-crash-expected.txt
deleted file mode 100644
index 848712a..0000000
--- a/LayoutTests/fast/events/touch/document-create-touch-list-crash-expected.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-This test ensures that WebKit doesn't crash when the document.createTouchList API is called with non-Touch parameters
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS document.createTouchList(document).item(0) is null
-PASS document.createTouchList({"a":1}).item(0) is null
-PASS document.createTouchList(new Array(5)).item(0) is null
-PASS document.createTouchList("string").item(0) is null
-PASS document.createTouchList(null).item(0) is null
-PASS document.createTouchList(undefined).item(0) is null
-PASS tl.length is 3
-PASS tl.item(0) is non-null.
-PASS tl.item(1) is null
-PASS tl.item(2) is non-null.
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/LayoutTests/fast/events/touch/document-create-touch-list-crash.html b/LayoutTests/fast/events/touch/document-create-touch-list-crash.html
deleted file mode 100644
index 9204abb..0000000
--- a/LayoutTests/fast/events/touch/document-create-touch-list-crash.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html>
-<head>
-<link rel="stylesheet" href="../../js/resources/js-test-style.css">
-<script src="../../js/resources/js-test-pre.js"></script>
-<script src="../../js/resources/js-test-post-function.js"></script>
-<!--
-  Touch tests that involve the ontouchstart, ontouchmove, ontouchend or ontouchcancel callbacks
-  should be written in an asynchronous fashion so they can be run on mobile platforms like Android.
-  You will need to invoke isSuccessfullyParsed() in your test script when the test completes.
--->
-</head>
-<body>
-<p id="description"></p>
-<div id="console"></div>
-<script src="script-tests/document-create-touch-list-crash.js"></script>
-</body>
-</html>
diff --git a/LayoutTests/fast/events/touch/script-tests/document-create-touch-list-crash.js b/LayoutTests/fast/events/touch/script-tests/document-create-touch-list-crash.js
deleted file mode 100644
index 19cf913..0000000
--- a/LayoutTests/fast/events/touch/script-tests/document-create-touch-list-crash.js
+++ /dev/null
@@ -1,20 +0,0 @@
-description("This test ensures that WebKit doesn't crash when the document.createTouchList API is called with non-Touch parameters");
-
-shouldBeNull('document.createTouchList(document).item(0)');
-shouldBeNull('document.createTouchList({"a":1}).item(0)');
-shouldBeNull('document.createTouchList(new Array(5)).item(0)');
-shouldBeNull('document.createTouchList("string").item(0)');
-shouldBeNull('document.createTouchList(null).item(0)');
-shouldBeNull('document.createTouchList(undefined).item(0)');
-
-var t = document.createTouch(window, document.body, 12341, 60, 65, 100, 105);
-var t2 = document.createTouch(window, document.body, 12342, 50, 55, 115, 120);
-var tl = document.createTouchList(t, document, t2);
-
-shouldBe('tl.length', '3');
-shouldBeNonNull('tl.item(0)');
-shouldBeNull('tl.item(1)');
-shouldBeNonNull('tl.item(2)');
-
-successfullyParsed = true;
-isSuccessfullyParsed();
diff --git a/LayoutTests/fast/url/file-http-base-expected.txt b/LayoutTests/fast/url/file-http-base-expected.txt
index f9169cd..afd3131 100644
--- a/LayoutTests/fast/url/file-http-base-expected.txt
+++ b/LayoutTests/fast/url/file-http-base-expected.txt
@@ -20,8 +20,7 @@
 FAIL canonicalize('FILE:/\\/\\7:\\\\//foo\\bar.html') should be file://7:////foo/bar.html. Was file:////7:////foo/bar.html.
 PASS canonicalize('file:filer/home\\me') is 'file://filer/home/me'
 FAIL canonicalize('file:///C:/foo/../../../bar.html') should be file:///C:/bar.html. Was file:///bar.html.
-FAIL canonicalize('file:///C:/asdf#\xc2') should be file:///C:/asdf#Â. Was file:///C:/asdf#%C2.
-FAIL canonicalize('file:///C:/asdf#Â') should be file:///C:/asdf#Â. Was file:///C:/asdf#%C2.
+FAIL canonicalize('file:///C:/asdf#\xc2') should be file:///C:/asdf#�. Was file:///C:/asdf#%C2.
 PASS canonicalize('file:///home/me') is 'file:///home/me'
 FAIL canonicalize('file:c:\\foo\\bar.html') should be file:///c:/foo/bar.html. Was file://c:/foo/bar.html.
 FAIL canonicalize('file:c|//foo\\bar.html') should be file:///c%7C//foo/bar.html. Was file://c|//foo/bar.html.
diff --git a/LayoutTests/fast/url/mailto-expected.txt b/LayoutTests/fast/url/mailto-expected.txt
index dc49e91..cd318f9 100644
--- a/LayoutTests/fast/url/mailto-expected.txt
+++ b/LayoutTests/fast/url/mailto-expected.txt
@@ -8,7 +8,7 @@
 PASS canonicalize('mailto:addr1 	 ') is 'mailto:addr1'
 PASS canonicalize('mailto:addr1?to=jon') is 'mailto:addr1?to=jon'
 PASS canonicalize('mailto:addr1,addr2') is 'mailto:addr1,addr2'
-PASS canonicalize('mailto:addr1, addr2') is 'mailto:addr1, addr2'
+FAIL canonicalize('mailto:addr1, addr2') should be mailto:addr1, addr2. Was mailto:addr1,%20addr2.
 PASS canonicalize('mailto:addr1%2caddr2') is 'mailto:addr1%2caddr2'
 PASS canonicalize('mailto:𐌀') is 'mailto:%F0%90%8C%80'
 PASS canonicalize('mailto:addr1?') is 'mailto:addr1?'
diff --git a/LayoutTests/fast/url/relative-expected.txt b/LayoutTests/fast/url/relative-expected.txt
index 7f93285..8ee781c 100644
--- a/LayoutTests/fast/url/relative-expected.txt
+++ b/LayoutTests/fast/url/relative-expected.txt
@@ -13,9 +13,9 @@
 PASS canonicalize(' 	 ') is 'http://foo/bar'
 PASS canonicalize('http:path') is 'http://host/path'
 PASS canonicalize('http:path') is 'http://host/a/path'
-FAIL canonicalize('http:/path') should be http://host/path. Was http://path/.
+FAIL canonicalize('http:/path') should be http://host/path. Was http:/path.
 FAIL canonicalize('HTTP:/path') should be http://host/path. Was http:/path.
-PASS canonicalize('https:host2') is 'https://host2/'
+FAIL canonicalize('https:host2') should be https://host2/. Was https:host2.
 PASS canonicalize('htto:/host2') is 'htto:/host2'
 PASS canonicalize('/b/c/d') is 'http://host/b/c/d'
 PASS canonicalize('\\b\\c\\d') is 'http://host/b/c/d'
@@ -42,7 +42,7 @@
 PASS canonicalize('data:baz') is 'data:baz'
 PASS canonicalize('data:/base') is 'data:/base'
 PASS canonicalize('http://host/') is 'http://host/'
-PASS canonicalize('http:host') is 'http://host/'
+FAIL canonicalize('http:host') should be http://host/. Was http:host.
 PASS canonicalize('./asd:fgh') is 'http://foo/asd:fgh'
 PASS canonicalize(':foo') is 'http://foo/:foo'
 PASS canonicalize(' hello world') is 'http://foo/hello%20world'
diff --git a/LayoutTests/fast/url/script-tests/file-http-base.js b/LayoutTests/fast/url/script-tests/file-http-base.js
index 00965b8..ca9e734 100644
--- a/LayoutTests/fast/url/script-tests/file-http-base.js
+++ b/LayoutTests/fast/url/script-tests/file-http-base.js
@@ -36,8 +36,7 @@
     // Make sure relative paths can't go above the "C:"
     ["file:///C:/foo/../../../bar.html", "file:///C:/bar.html"],
     // Busted refs shouldn't make the whole thing fail.
-    ["file:///C:/asdf#\\xc2", "file:///C:/asdf#\\xc2"],
-    ["file:///C:/asdf#\xc2", "file:///C:/asdf#\xc2"],
+    ["file:///C:/asdf#\\xc2", "file:///C:/asdf#\\xef\\xbf\\xbd"],
 
     // Unix-style paths
     ["file:///home/me", "file:///home/me"],
diff --git a/LayoutTests/fast/url/script-tests/segments-from-data-url.js b/LayoutTests/fast/url/script-tests/segments-from-data-url.js
index 9be7142..5c4ae02 100644
--- a/LayoutTests/fast/url/script-tests/segments-from-data-url.js
+++ b/LayoutTests/fast/url/script-tests/segments-from-data-url.js
@@ -3,71 +3,71 @@
 cases = [ 
   // [URL, [SCHEME, HOST, PORT, PATH, QUERY, REF]]
   ["http://user:pass@foo:21/bar;par?b#c",    ["http:","foo","21","/bar;par","?b","#c"]],
-  ["http:foo.com",                           ["http:","foo.com","","/","",""]],
-  ["\\t   :foo.com   \\n",                   [":","","","","",""]],
-  [" foo.com  ",                             [":","","","","",""]],
-  ["a:\\t foo.com",                          ["a:","",""," foo.com","",""]],
+  ["http:foo.com",                           ["http:","foo.com","0","/","",""]],
+  ["\\t   :foo.com   \\n",                   [":","","0","","",""]],
+  [" foo.com  ",                             [":","","0","","",""]],
+  ["a:\\t foo.com",                          ["a:","","0"," foo.com","",""]],
   ["http://f:21/ b ? d # e ",                ["http:","f","21","/%20b%20","?%20d%20","# e"]],
-  ["http://f:/c",                            ["http:","f","","/c","",""]],
+  ["http://f:/c",                            ["http:","f","0","/c","",""]],
   ["http://f:0/c",                           ["http:","f","0","/c","",""]],
   ["http://f:00000000000000/c",              ["http:","f","0","/c","",""]],
   ["http://f:00000000000000000000080/c",     ["http:","f","0","/c","",""]],
-  ["http://f:b/c",                           [":","","","","",""]],
-  ["http://f: /c",                           [":","","","","",""]],
-  ["http://f:\\n/c",                         [":","","","","",""]],
-  ["http://f:fifty-two/c",                   [":","","","","",""]],
+  ["http://f:b/c",                           [":","","0","","",""]],
+  ["http://f: /c",                           [":","","0","","",""]],
+  ["http://f:\\n/c",                         [":","","0","","",""]],
+  ["http://f:fifty-two/c",                   [":","","0","","",""]],
   ["http://f:999999/c",                      [":","","0","","",""]],
-  ["http://f: 21 / b ? d # e ",              [":","","","","",""]],
-  ["",                                       ["data:","","","text/plain,baseURL","",""]],
-  ["  \\t",                                  ["data:","","","text/plain,baseURL","",""]],
-  [":foo.com/",                              [":","","","","",""]],
-  [":foo.com\\\\",                           [":","","","","",""]],
-  [":",                                      [":","","","","",""]],
-  [":a",                                     [":","","","","",""]],
-  [":/",                                     [":","","","","",""]],
-  [":\\\\",                                  [":","","","","",""]],
-  [":#",                                     [":","","","","",""]],
-  ["#",                                      [":","","","","",""]],
-  ["#/",                                     [":","","","","",""]],
-  ["#\\\\",                                  [":","","","","",""]],
-  ["#;?",                                    [":","","","","",""]],
-  ["?",                                      [":","","","","",""]],
-  ["/",                                      [":","","","","",""]],
-  [":23",                                    [":","","","","",""]],
-  ["/:23",                                   ["data:","","","/:23","",""]],
-  ["//",                                     [":","","","","",""]],
-  ["::",                                     [":","","","","",""]],
-  ["::23",                                   [":","","","","",""]],
-  ["foo://",                                 ["foo:","","","//","",""]],
+  ["http://f: 21 / b ? d # e ",              [":","","0","","",""]],
+  ["",                                       ["data:","","0","text/plain,baseURL","",""]],
+  ["  \\t",                                  ["data:","","0","text/plain,baseURL","",""]],
+  [":foo.com/",                              [":","","0","","",""]],
+  [":foo.com\\\\",                           [":","","0","","",""]],
+  [":",                                      [":","","0","","",""]],
+  [":a",                                     [":","","0","","",""]],
+  [":/",                                     [":","","0","","",""]],
+  [":\\\\",                                  [":","","0","","",""]],
+  [":#",                                     [":","","0","","",""]],
+  ["#",                                      [":","","0","","",""]],
+  ["#/",                                     [":","","0","","",""]],
+  ["#\\\\",                                  [":","","0","","",""]],
+  ["#;?",                                    [":","","0","","",""]],
+  ["?",                                      [":","","0","","",""]],
+  ["/",                                      [":","","0","","",""]],
+  [":23",                                    [":","","0","","",""]],
+  ["/:23",                                   ["data:","","0","/:23","",""]],
+  ["//",                                     [":","","0","","",""]],
+  ["::",                                     [":","","0","","",""]],
+  ["::23",                                   [":","","0","","",""]],
+  ["foo://",                                 ["foo:","","0","//","",""]],
   ["http://a:b@c:29/d",                      ["http:","c","29","/d","",""]],
   ["http::@c:29",                            ["http:","c","29","/","",""]],
   ["http://&a:foo(b]c@d:2/",                 ["http:","d","2","/","",""]],
   ["http://::@c@d:2",                        ["http:","d","2","/","",""]],
-  ["http://foo.com:b@d/",                    ["http:","d","","/","",""]],
-  ["http://foo.com/\\\\@",                   ["http:","foo.com","","//@","",""]],
-  ["http:\\\\\\\\foo.com\\\\",               ["http:","foo.com","","/","",""]],
-  ["http:\\\\\\\\a\\\\b:c\\\\d@foo.com\\\\", ["http:","a","","/b:c/d@foo.com/","",""]],
-  ["foo:/",                                  ["foo:","","","/","",""]],
-  ["foo:/bar.com/",                          ["foo:","","","/bar.com/","",""]],
-  ["foo://///////",                          ["foo:","","","/////////","",""]],
-  ["foo://///////bar.com/",                  ["foo:","","","/////////bar.com/","",""]],
-  ["foo:////://///",                         ["foo:","","","////://///","",""]],
-  ["c:/foo",                                 ["c:","","","/foo","",""]],
-  ["//foo/bar",                              [":","","","","",""]],
-  ["http://foo/path;a??e#f#g",               ["http:","foo","","/path;a","??e","#f#g"]],
-  ["http://foo/abcd?efgh?ijkl",              ["http:","foo","","/abcd","?efgh?ijkl",""]],
-  ["http://foo/abcd#foo?bar",                ["http:","foo","","/abcd","","#foo?bar"]],
-  ["[61:24:74]:98",                          ["data:","","","text/[61:24:74]:98","",""]],
+  ["http://foo.com:b@d/",                    ["http:","d","0","/","",""]],
+  ["http://foo.com/\\\\@",                   ["http:","foo.com","0","//@","",""]],
+  ["http:\\\\\\\\foo.com\\\\",               ["http:","foo.com","0","/","",""]],
+  ["http:\\\\\\\\a\\\\b:c\\\\d@foo.com\\\\", ["http:","a","0","/b:c/d@foo.com/","",""]],
+  ["foo:/",                                  ["foo:","","0","/","",""]],
+  ["foo:/bar.com/",                          ["foo:","","0","/bar.com/","",""]],
+  ["foo://///////",                          ["foo:","","0","/////////","",""]],
+  ["foo://///////bar.com/",                  ["foo:","","0","/////////bar.com/","",""]],
+  ["foo:////://///",                         ["foo:","","0","////://///","",""]],
+  ["c:/foo",                                 ["c:","","0","/foo","",""]],
+  ["//foo/bar",                              [":","","0","","",""]],
+  ["http://foo/path;a??e#f#g",               ["http:","foo","0","/path;a","??e","#f#g"]],
+  ["http://foo/abcd?efgh?ijkl",              ["http:","foo","0","/abcd","?efgh?ijkl",""]],
+  ["http://foo/abcd#foo?bar",                ["http:","foo","0","/abcd","","#foo?bar"]],
+  ["[61:24:74]:98",                          ["data:","","0","text/[61:24:74]:98","",""]],
   ["http://[61:27]:98",                      [":","","0","","",""]],
-  ["http:[61:27]/:foo",                      [":","","","","",""]],
-  ["http://[1::2]:3:4",                      [":","","","","",""]],
-  ["http://2001::1",                         [":","","","","",""]],
-  ["http://[2001::1",                        [":","","","","",""]],
-  ["http://2001::1]",                        [":","","","","",""]],
-  ["http://2001::1]:80",                     [":","","","","",""]],
-  ["http://[2001::1]",                       ["http:","[2001::1]","","/","",""]],
-  ["http://[2001::1]:80",                    ["http:","[2001::1]","","/","",""]],
-  ["http://[[::]]",                          [":","","","","",""]],
+  ["http:[61:27]/:foo",                      [":","","0","","",""]],
+  ["http://[1::2]:3:4",                      [":","","0","","",""]],
+  ["http://2001::1",                         [":","","0","","",""]],
+  ["http://[2001::1",                        [":","","0","","",""]],
+  ["http://2001::1]",                        [":","","0","","",""]],
+  ["http://2001::1]:80",                     [":","","0","","",""]],
+  ["http://[2001::1]",                       ["http:","[2001::1]","0","/","",""]],
+  ["http://[2001::1]:80",                    ["http:","[2001::1]","0","/","",""]],
+  ["http://[[::]]",                          [":","","0","","",""]],
 ];
 
 var originalBaseURL = canonicalize(".");
diff --git a/LayoutTests/fast/url/script-tests/segments.js b/LayoutTests/fast/url/script-tests/segments.js
index a83cb61..c621da1 100644
--- a/LayoutTests/fast/url/script-tests/segments.js
+++ b/LayoutTests/fast/url/script-tests/segments.js
@@ -1,104 +1,73 @@
 description("Test URL segmentation");
 
-cases = [
+cases = [ 
   // [URL, [SCHEME, HOST, PORT, PATH, QUERY, REF]]
   ["http://user:pass@foo:21/bar;par?b#c",    ["http:","foo","21","/bar;par","?b","#c"]],
-  ["http:foo.com",                           ["http:","example.org","","/foo/foo.com","",""]],
-  ["\\t   :foo.com   \\n",                   ["http:","example.org","","/foo/:foo.com","",""]],
-  [" foo.com  ",                             ["http:","example.org","","/foo/foo.com","",""]],
-  ["a:\\t foo.com",                          ["a:","",""," foo.com","",""]],
+  ["http:foo.com",                           ["http:","example.org","0","/foo/foo.com","",""]],
+  ["\\t   :foo.com   \\n",                   ["http:","example.org","0","/foo/:foo.com","",""]],
+  [" foo.com  ",                             ["http:","example.org","0","/foo/foo.com","",""]],
+  ["a:\\t foo.com",                          ["a:","","0"," foo.com","",""]],
   ["http://f:21/ b ? d # e ",                ["http:","f","21","/%20b%20","?%20d%20","# e"]],
-  ["http://f:/c",                            ["http:","f","","/c","",""]],
+  ["http://f:/c",                            ["http:","f","0","/c","",""]],
   ["http://f:0/c",                           ["http:","f","0","/c","",""]],
   ["http://f:00000000000000/c",              ["http:","f","0","/c","",""]],
   ["http://f:00000000000000000000080/c",     ["http:","f","0","/c","",""]],
-  ["http://f:b/c",                           [":","","","","",""]],
-  ["http://f: /c",                           [":","","","","",""]],
-  ["http://f:\\n/c",                         [":","","","","",""]],
-  ["http://f:fifty-two/c",                   [":","","","","",""]],
+  ["http://f:b/c",                           [":","","0","","",""]],
+  ["http://f: /c",                           [":","","0","","",""]],
+  ["http://f:\\n/c",                         [":","","0","","",""]],
+  ["http://f:fifty-two/c",                   [":","","0","","",""]],
   ["http://f:999999/c",                      [":","","0","","",""]],
-  ["http://f: 21 / b ? d # e ",              [":","","","","",""]],
-  ["",                                       ["http:","example.org","","/foo/bar","",""]],
-  ["  \\t",                                  ["http:","example.org","","/foo/bar","",""]],
-  [":foo.com/",                              ["http:","example.org","","/foo/:foo.com/","",""]],
-  [":foo.com\\\\",                           ["http:","example.org","","/foo/:foo.com/","",""]],
-  [":",                                      ["http:","example.org","","/foo/:","",""]],
-  [":a",                                     ["http:","example.org","","/foo/:a","",""]],
-  [":/",                                     ["http:","example.org","","/foo/:/","",""]],
-  [":\\\\",                                  ["http:","example.org","","/foo/:/","",""]],
-  [":#",                                     ["http:","example.org","","/foo/:","",""]],
-  ["#",                                      ["http:","example.org","","/foo/bar","",""]],
-  ["#/",                                     ["http:","example.org","","/foo/bar","","#/"]],
-  ["#\\\\",                                  ["http:","example.org","","/foo/bar","","#\\\\"]],
-  ["#;?",                                    ["http:","example.org","","/foo/bar","","#;?"]],
-  ["?",                                      ["http:","example.org","","/foo/bar","",""]],
-  ["/",                                      ["http:","example.org","","/","",""]],
-  [":23",                                    ["http:","example.org","","/foo/:23","",""]],
-  ["/:23",                                   ["http:","example.org","","/:23","",""]],
-  ["//",                                     [":","","","","",""]],
-  ["::",                                     ["http:","example.org","","/foo/::","",""]],
-  ["::23",                                   ["http:","example.org","","/foo/::23","",""]],
-  ["foo://",                                 ["foo:","","","//","",""]],
+  ["http://f: 21 / b ? d # e ",              [":","","0","","",""]],
+  ["",                                       ["http:","example.org","0","/foo/bar","",""]],
+  ["  \\t",                                  ["http:","example.org","0","/foo/bar","",""]],
+  [":foo.com/",                              ["http:","example.org","0","/foo/:foo.com/","",""]],
+  [":foo.com\\\\",                           ["http:","example.org","0","/foo/:foo.com/","",""]],
+  [":",                                      ["http:","example.org","0","/foo/:","",""]],
+  [":a",                                     ["http:","example.org","0","/foo/:a","",""]],
+  [":/",                                     ["http:","example.org","0","/foo/:/","",""]],
+  [":\\\\",                                  ["http:","example.org","0","/foo/:/","",""]],
+  [":#",                                     ["http:","example.org","0","/foo/:","",""]],
+  ["#",                                      ["http:","example.org","0","/foo/bar","",""]],
+  ["#/",                                     ["http:","example.org","0","/foo/bar","","#/"]],
+  ["#\\\\",                                  ["http:","example.org","0","/foo/bar","","#\\\\"]],
+  ["#;?",                                    ["http:","example.org","0","/foo/bar","","#;?"]],
+  ["?",                                      ["http:","example.org","0","/foo/bar","",""]],
+  ["/",                                      ["http:","example.org","0","/","",""]],
+  [":23",                                    ["http:","example.org","0","/foo/:23","",""]],
+  ["/:23",                                   ["http:","example.org","0","/:23","",""]],
+  ["//",                                     [":","","0","","",""]],
+  ["::",                                     ["http:","example.org","0","/foo/::","",""]],
+  ["::23",                                   ["http:","example.org","0","/foo/::23","",""]],
+  ["foo://",                                 ["foo:","","0","//","",""]],
   ["http://a:b@c:29/d",                      ["http:","c","29","/d","",""]],
-  ["http::@c:29",                            ["http:","example.org","","/foo/:@c:29","",""]],
+  ["http::@c:29",                            ["http:","example.org","0","/foo/:@c:29","",""]],
   ["http://&a:foo(b]c@d:2/",                 ["http:","d","2","/","",""]],
   ["http://::@c@d:2",                        ["http:","d","2","/","",""]],
-  ["http://foo.com:b@d/",                    ["http:","d","","/","",""]],
-  ["http://foo.com/\\\\@",                   ["http:","foo.com","","//@","",""]],
-  ["http:\\\\\\\\foo.com\\\\",               ["http:","foo.com","","/","",""]],
-  ["http:\\\\\\\\a\\\\b:c\\\\d@foo.com\\\\", ["http:","a","","/b:c/d@foo.com/","",""]],
-  ["foo:/",                                  ["foo:","","","/","",""]],
-  ["foo:/bar.com/",                          ["foo:","","","/bar.com/","",""]],
-  ["foo://///////",                          ["foo:","","","/////////","",""]],
-  ["foo://///////bar.com/",                  ["foo:","","","/////////bar.com/","",""]],
-  ["foo:////://///",                         ["foo:","","","////://///","",""]],
-  ["c:/foo",                                 ["c:","","","/foo","",""]],
-  ["//foo/bar",                              ["http:","foo","","/bar","",""]],
-  ["http://foo/path;a??e#f#g",               ["http:","foo","","/path;a","??e","#f#g"]],
-  ["http://foo/abcd?efgh?ijkl",              ["http:","foo","","/abcd","?efgh?ijkl",""]],
-  ["http://foo/abcd#foo?bar",                ["http:","foo","","/abcd","","#foo?bar"]],
-  ["[61:24:74]:98",                          ["http:","example.org","","/foo/[61:24:74]:98","",""]],
+  ["http://foo.com:b@d/",                    ["http:","d","0","/","",""]],
+  ["http://foo.com/\\\\@",                   ["http:","foo.com","0","//@","",""]],
+  ["http:\\\\\\\\foo.com\\\\",               ["http:","foo.com","0","/","",""]],
+  ["http:\\\\\\\\a\\\\b:c\\\\d@foo.com\\\\", ["http:","a","0","/b:c/d@foo.com/","",""]],
+  ["foo:/",                                  ["foo:","","0","/","",""]],
+  ["foo:/bar.com/",                          ["foo:","","0","/bar.com/","",""]],
+  ["foo://///////",                          ["foo:","","0","/////////","",""]],
+  ["foo://///////bar.com/",                  ["foo:","","0","/////////bar.com/","",""]],
+  ["foo:////://///",                         ["foo:","","0","////://///","",""]],
+  ["c:/foo",                                 ["c:","","0","/foo","",""]],
+  ["//foo/bar",                              ["http:","foo","0","/bar","",""]],
+  ["http://foo/path;a??e#f#g",               ["http:","foo","0","/path;a","??e","#f#g"]],
+  ["http://foo/abcd?efgh?ijkl",              ["http:","foo","0","/abcd","?efgh?ijkl",""]],
+  ["http://foo/abcd#foo?bar",                ["http:","foo","0","/abcd","","#foo?bar"]],
+  ["[61:24:74]:98",                          ["http:","example.org","0","/foo/[61:24:74]:98","",""]],
   ["http://[61:27]:98",                      [":","","0","","",""]],
-  ["http:[61:27]/:foo",                      ["http:","example.org","","/foo/[61:27]/:foo","",""]],
-  ["http://[1::2]:3:4",                      [":","","","","",""]],
-  ["http://2001::1",                         [":","","","","",""]],
-  ["http://[2001::1",                        [":","","","","",""]],
-  ["http://2001::1]",                        [":","","","","",""]],
-  ["http://2001::1]:80",                     [":","","","","",""]],
-  ["http://[2001::1]",                       ["http:","[2001::1]","","/","",""]],
-  ["http://[2001::1]:80",                    ["http:","[2001::1]","","/","",""]],
-  ["http://[[::]]",                          [":","","","","",""]],
-  ["http:/example.com/",                     ["http:","example.org","","/example.com/","",""]],
-  ["ftp:/example.com/",                      ["ftp:","example.com","","/","",""]],
-  ["https:/example.com/",                    ["https:","example.com","","/","",""]],
-  ["madeupscheme:/example.com/",             ["madeupscheme:","","","/example.com/","",""]],
-  ["file:/example.com/",                     ["file:","","","/example.com/","",""]],
-  ["ftps:/example.com/",                     ["ftps:","","","/example.com/","",""]],
-  ["gopher:/example.com/",                   ["gopher:","example.com","","/","",""]],
-  ["ws:/example.com/",                       ["ws:","example.com","","/","",""]],
-  ["wss:/example.com/",                      ["wss:","example.com","","/","",""]],
-  ["data:/example.com/",                     ["data:","","","/example.com/","",""]],
-  ["javascript:/example.com/",               ["javascript:","","","/example.com/","",""]],
-  ["mailto:/example.com/",                   ["mailto:","","","/example.com/","",""]],
-  ["http:example.com/",                      ["http:","example.org","","/foo/example.com/","",""]],
-  ["ftp:example.com/",                       ["ftp:","example.com","","/","",""]],
-  ["https:example.com/",                     ["https:","example.com","","/","",""]],
-  ["madeupscheme:example.com/",              ["madeupscheme:","","","example.com/","",""]],
-  ["file:example.com/",                      ["file:","","","/example.com/","",""]],
-  ["ftps:example.com/",                      ["ftps:","","","example.com/","",""]],
-  ["gopher:example.com/",                    ["gopher:","example.com","","/","",""]],
-  ["ws:example.com/",                        ["ws:","example.com","","/","",""]],
-  ["wss:example.com/",                       ["wss:","example.com","","/","",""]],
-  ["data:example.com/",                      ["data:","","","example.com/","",""]],
-  ["javascript:example.com/",                ["javascript:","","","example.com/","",""]],
-  ["mailto:example.com/",                    ["mailto:","","","example.com/","",""]],
-
-  ["/a/b/c",                                  ["http:","example.org","","/a/b/c","",""]],
-  ["/a/ /c",                                  ["http:","example.org","","/a/%20/c","",""]],
-  ["/a%2fc",                                  ["http:","example.org","","/a%2fc","",""]],
-  ["/a/%2f/c",                                ["http:","example.org","","/a/%2f/c","",""]],
-
-  ["#\u03B2",                                 ["http:","example.org","","/foo/bar","","#\u03B2"]],
+  ["http:[61:27]/:foo",                      ["http:","example.org","0","/foo/[61:27]/:foo","",""]],
+  ["http://[1::2]:3:4",                      [":","","0","","",""]],
+  ["http://2001::1",                         [":","","0","","",""]],
+  ["http://[2001::1",                        [":","","0","","",""]],
+  ["http://2001::1]",                        [":","","0","","",""]],
+  ["http://2001::1]:80",                     [":","","0","","",""]],
+  ["http://[2001::1]",                       ["http:","[2001::1]","0","/","",""]],
+  ["http://[2001::1]:80",                    ["http:","[2001::1]","0","/","",""]],
+  ["http://[[::]]",                          [":","","0","","",""]],
 ];
 
 var originalBaseURL = canonicalize(".");
diff --git a/LayoutTests/fast/url/script-tests/standard-url.js b/LayoutTests/fast/url/script-tests/standard-url.js
index 5611faa..03808a8 100644
--- a/LayoutTests/fast/url/script-tests/standard-url.js
+++ b/LayoutTests/fast/url/script-tests/standard-url.js
@@ -1,10 +1,8 @@
 description("Canonicalization of standard URLs");
 
-cases = [
+cases = [ 
   ["http://www.google.com/foo?bar=baz#", "http://www.google.com/foo?bar=baz#"],
-  ["http://www.google.com/foo?bar=baz# \u00bb", "http://www.google.com/foo?bar=baz# \u00bb"],
   ["http://[www.google.com]/", "http://[www.google.com]/"],
-  ["http://www.google.com", "http://www.google.com/"],
   // Disabled because whitespace gets treated different in this API.
   // ["ht\ttp:@www.google.com:80/;p?#", "ht%09tp://www.google.com:80/;p?#"],
   ["http:////////user:@google.com:99?foo", "http://user@google.com:99/?foo"],
@@ -37,32 +35,6 @@
   ["wss://foo:81/", "wss://foo:81/"],
   ["wss://foo:443/", "wss://foo/"],
   ["wss://foo:815/", "wss://foo:815/"],
-  ["http:/example.com/", "http://example.com/"],
-  ["ftp:/example.com/", "ftp://example.com/"],
-  ["https:/example.com/", "https://example.com/"],
-  ["madeupscheme:/example.com/", "madeupscheme:/example.com/"],
-  ["file:/example.com/", "file://localhost/example.com/"],
-  ["ftps:/example.com/", "ftps:/example.com/"],
-  ["gopher:/example.com/", "gopher://example.com/"],
-  ["ws:/example.com/", "ws://example.com/"],
-  ["wss:/example.com/", "wss://example.com/"],
-  ["data:/example.com/", "data:/example.com/"],
-  ["javascript:/example.com/", "javascript:/example.com/"],
-  ["mailto:/example.com/", "mailto:/example.com/"],
-  ["http:example.com/", "http://example.com/"],
-  ["ftp:example.com/", "ftp://example.com/"],
-  ["https:example.com/", "https://example.com/"],
-  ["madeupscheme:example.com/", "madeupscheme:example.com/"],
-  ["ftps:example.com/", "ftps:example.com/"],
-  ["gopher:example.com/", "gopher://example.com/"],
-  ["ws:example.com/", "ws://example.com/"],
-  ["wss:example.com/", "wss://example.com/"],
-  ["data:example.com/", "data:example.com/"],
-  ["javascript:example.com/", "javascript:example.com/"],
-  ["mailto:example.com/", "mailto:example.com/"],
-  // Escaping of non hierarchical URLs
-  ["javascript:alert(\\t 1 \\n\\r)", "javascript:alert( 1 )"],
-  ['javascript:alert(" \1 \u03B2 ")', 'javascript:alert(" %01 %CE%B2 ")'],
 ];
 
 for (var i = 0; i < cases.length; ++i) {
diff --git a/LayoutTests/fast/url/script-tests/trivial-segments.js b/LayoutTests/fast/url/script-tests/trivial-segments.js
index c19551b..81edfd1 100644
--- a/LayoutTests/fast/url/script-tests/trivial-segments.js
+++ b/LayoutTests/fast/url/script-tests/trivial-segments.js
@@ -2,7 +2,7 @@
 
 cases = [ 
   // [URL, [SCHEME, HOST, PORT, PATH, QUERY, REF]]
-  ["http://example.com/", ["http:", "example.com", "", "/", "", ""]],
+  ["http://example.com/", ["http:", "example.com", "0", "/", "", ""]],
 ];
 
 var originalBaseURL = canonicalize(".");
diff --git a/LayoutTests/fast/url/segments-expected.txt b/LayoutTests/fast/url/segments-expected.txt
index 76e49aa..659be5f 100644
--- a/LayoutTests/fast/url/segments-expected.txt
+++ b/LayoutTests/fast/url/segments-expected.txt
@@ -4,100 +4,71 @@
 
 
 PASS segments('http://user:pass@foo:21/bar;par?b#c') is '["http:","foo","21","/bar;par","?b","#c"]'
-PASS segments('http:foo.com') is '["http:","example.org","","/foo/foo.com","",""]'
-PASS segments('\t   :foo.com   \n') is '["http:","example.org","","/foo/:foo.com","",""]'
-PASS segments(' foo.com  ') is '["http:","example.org","","/foo/foo.com","",""]'
-PASS segments('a:\t foo.com') is '["a:","",""," foo.com","",""]'
-PASS segments('http://f:21/ b ? d # e ') is '["http:","f","21","/%20b%20","?%20d%20","# e"]'
-PASS segments('http://f:/c') is '["http:","f","","/c","",""]'
+PASS segments('http:foo.com') is '["http:","example.org","0","/foo/foo.com","",""]'
+PASS segments('\t   :foo.com   \n') is '["http:","example.org","0","/foo/:foo.com","",""]'
+PASS segments(' foo.com  ') is '["http:","example.org","0","/foo/foo.com","",""]'
+PASS segments('a:\t foo.com') is '["a:","","0"," foo.com","",""]'
+FAIL segments('http://f:21/ b ? d # e ') should be ["http:","f","21","/%20b%20","?%20d%20","# e"]. Was ["http:","f","21","/ b ","?%20d%20","# e"].
+PASS segments('http://f:/c') is '["http:","f","0","/c","",""]'
 PASS segments('http://f:0/c') is '["http:","f","0","/c","",""]'
 PASS segments('http://f:00000000000000/c') is '["http:","f","0","/c","",""]'
 FAIL segments('http://f:00000000000000000000080/c') should be ["http:","f","0","/c","",""]. Was ["http:","f","80","/c","",""].
-PASS segments('http://f:b/c') is '[":","","","","",""]'
-PASS segments('http://f: /c') is '[":","","","","",""]'
-PASS segments('http://f:\n/c') is '[":","","","","",""]'
-PASS segments('http://f:fifty-two/c') is '[":","","","","",""]'
+PASS segments('http://f:b/c') is '[":","","0","","",""]'
+PASS segments('http://f: /c') is '[":","","0","","",""]'
+PASS segments('http://f:\n/c') is '[":","","0","","",""]'
+PASS segments('http://f:fifty-two/c') is '[":","","0","","",""]'
 FAIL segments('http://f:999999/c') should be [":","","0","","",""]. Was ["http:","f","65535","/c","",""].
-PASS segments('http://f: 21 / b ? d # e ') is '[":","","","","",""]'
-PASS segments('') is '["http:","example.org","","/foo/bar","",""]'
-PASS segments('  \t') is '["http:","example.org","","/foo/bar","",""]'
-PASS segments(':foo.com/') is '["http:","example.org","","/foo/:foo.com/","",""]'
-PASS segments(':foo.com\\') is '["http:","example.org","","/foo/:foo.com/","",""]'
-PASS segments(':') is '["http:","example.org","","/foo/:","",""]'
-PASS segments(':a') is '["http:","example.org","","/foo/:a","",""]'
-PASS segments(':/') is '["http:","example.org","","/foo/:/","",""]'
-PASS segments(':\\') is '["http:","example.org","","/foo/:/","",""]'
-PASS segments(':#') is '["http:","example.org","","/foo/:","",""]'
-PASS segments('#') is '["http:","example.org","","/foo/bar","",""]'
-PASS segments('#/') is '["http:","example.org","","/foo/bar","","#/"]'
-PASS segments('#\\') is '["http:","example.org","","/foo/bar","","#\\\\"]'
-PASS segments('#;?') is '["http:","example.org","","/foo/bar","","#;?"]'
-PASS segments('?') is '["http:","example.org","","/foo/bar","",""]'
-PASS segments('/') is '["http:","example.org","","/","",""]'
-PASS segments(':23') is '["http:","example.org","","/foo/:23","",""]'
-PASS segments('/:23') is '["http:","example.org","","/:23","",""]'
-FAIL segments('//') should be [":","","","","",""]. Was ["http:","","","/","",""].
-PASS segments('::') is '["http:","example.org","","/foo/::","",""]'
-PASS segments('::23') is '["http:","example.org","","/foo/::23","",""]'
-PASS segments('foo://') is '["foo:","","","//","",""]'
+PASS segments('http://f: 21 / b ? d # e ') is '[":","","0","","",""]'
+PASS segments('') is '["http:","example.org","0","/foo/bar","",""]'
+PASS segments('  \t') is '["http:","example.org","0","/foo/bar","",""]'
+PASS segments(':foo.com/') is '["http:","example.org","0","/foo/:foo.com/","",""]'
+PASS segments(':foo.com\\') is '["http:","example.org","0","/foo/:foo.com/","",""]'
+PASS segments(':') is '["http:","example.org","0","/foo/:","",""]'
+PASS segments(':a') is '["http:","example.org","0","/foo/:a","",""]'
+PASS segments(':/') is '["http:","example.org","0","/foo/:/","",""]'
+PASS segments(':\\') is '["http:","example.org","0","/foo/:/","",""]'
+PASS segments(':#') is '["http:","example.org","0","/foo/:","",""]'
+PASS segments('#') is '["http:","example.org","0","/foo/bar","",""]'
+PASS segments('#/') is '["http:","example.org","0","/foo/bar","","#/"]'
+PASS segments('#\\') is '["http:","example.org","0","/foo/bar","","#\\\\"]'
+PASS segments('#;?') is '["http:","example.org","0","/foo/bar","","#;?"]'
+PASS segments('?') is '["http:","example.org","0","/foo/bar","",""]'
+PASS segments('/') is '["http:","example.org","0","/","",""]'
+PASS segments(':23') is '["http:","example.org","0","/foo/:23","",""]'
+PASS segments('/:23') is '["http:","example.org","0","/:23","",""]'
+FAIL segments('//') should be [":","","0","","",""]. Was ["http:","","0","/","",""].
+PASS segments('::') is '["http:","example.org","0","/foo/::","",""]'
+PASS segments('::23') is '["http:","example.org","0","/foo/::23","",""]'
+PASS segments('foo://') is '["foo:","","0","//","",""]'
 PASS segments('http://a:b@c:29/d') is '["http:","c","29","/d","",""]'
-PASS segments('http::@c:29') is '["http:","example.org","","/foo/:@c:29","",""]'
-FAIL segments('http://&a:foo(b]c@d:2/') should be ["http:","d","2","/","",""]. Was [":","","","","",""].
-FAIL segments('http://::@c@d:2') should be ["http:","d","2","/","",""]. Was [":","","","","",""].
-PASS segments('http://foo.com:b@d/') is '["http:","d","","/","",""]'
-PASS segments('http://foo.com/\\@') is '["http:","foo.com","","//@","",""]'
-PASS segments('http:\\\\foo.com\\') is '["http:","foo.com","","/","",""]'
-PASS segments('http:\\\\a\\b:c\\d@foo.com\\') is '["http:","a","","/b:c/d@foo.com/","",""]'
-PASS segments('foo:/') is '["foo:","","","/","",""]'
-PASS segments('foo:/bar.com/') is '["foo:","","","/bar.com/","",""]'
-PASS segments('foo://///////') is '["foo:","","","/////////","",""]'
-PASS segments('foo://///////bar.com/') is '["foo:","","","/////////bar.com/","",""]'
-PASS segments('foo:////://///') is '["foo:","","","////://///","",""]'
-PASS segments('c:/foo') is '["c:","","","/foo","",""]'
-PASS segments('//foo/bar') is '["http:","foo","","/bar","",""]'
-PASS segments('http://foo/path;a??e#f#g') is '["http:","foo","","/path;a","??e","#f#g"]'
-PASS segments('http://foo/abcd?efgh?ijkl') is '["http:","foo","","/abcd","?efgh?ijkl",""]'
-PASS segments('http://foo/abcd#foo?bar') is '["http:","foo","","/abcd","","#foo?bar"]'
-PASS segments('[61:24:74]:98') is '["http:","example.org","","/foo/[61:24:74]:98","",""]'
+PASS segments('http::@c:29') is '["http:","example.org","0","/foo/:@c:29","",""]'
+FAIL segments('http://&a:foo(b]c@d:2/') should be ["http:","d","2","/","",""]. Was [":","","0","","",""].
+FAIL segments('http://::@c@d:2') should be ["http:","d","2","/","",""]. Was [":","","0","","",""].
+PASS segments('http://foo.com:b@d/') is '["http:","d","0","/","",""]'
+PASS segments('http://foo.com/\\@') is '["http:","foo.com","0","//@","",""]'
+PASS segments('http:\\\\foo.com\\') is '["http:","foo.com","0","/","",""]'
+PASS segments('http:\\\\a\\b:c\\d@foo.com\\') is '["http:","a","0","/b:c/d@foo.com/","",""]'
+PASS segments('foo:/') is '["foo:","","0","/","",""]'
+PASS segments('foo:/bar.com/') is '["foo:","","0","/bar.com/","",""]'
+PASS segments('foo://///////') is '["foo:","","0","/////////","",""]'
+PASS segments('foo://///////bar.com/') is '["foo:","","0","/////////bar.com/","",""]'
+PASS segments('foo:////://///') is '["foo:","","0","////://///","",""]'
+PASS segments('c:/foo') is '["c:","","0","/foo","",""]'
+PASS segments('//foo/bar') is '["http:","foo","0","/bar","",""]'
+PASS segments('http://foo/path;a??e#f#g') is '["http:","foo","0","/path;a","??e","#f#g"]'
+PASS segments('http://foo/abcd?efgh?ijkl') is '["http:","foo","0","/abcd","?efgh?ijkl",""]'
+PASS segments('http://foo/abcd#foo?bar') is '["http:","foo","0","/abcd","","#foo?bar"]'
+PASS segments('[61:24:74]:98') is '["http:","example.org","0","/foo/[61:24:74]:98","",""]'
 FAIL segments('http://[61:27]:98') should be [":","","0","","",""]. Was ["http:","[61:27]","98","/","",""].
-PASS segments('http:[61:27]/:foo') is '["http:","example.org","","/foo/[61:27]/:foo","",""]'
-PASS segments('http://[1::2]:3:4') is '[":","","","","",""]'
-PASS segments('http://2001::1') is '[":","","","","",""]'
-PASS segments('http://[2001::1') is '[":","","","","",""]'
-PASS segments('http://2001::1]') is '[":","","","","",""]'
-PASS segments('http://2001::1]:80') is '[":","","","","",""]'
-PASS segments('http://[2001::1]') is '["http:","[2001::1]","","/","",""]'
-PASS segments('http://[2001::1]:80') is '["http:","[2001::1]","","/","",""]'
-PASS segments('http://[[::]]') is '[":","","","","",""]'
-FAIL segments('http:/example.com/') should be ["http:","example.org","","/example.com/","",""]. Was ["http:","example.com","","/","",""].
-PASS segments('ftp:/example.com/') is '["ftp:","example.com","","/","",""]'
-PASS segments('https:/example.com/') is '["https:","example.com","","/","",""]'
-PASS segments('madeupscheme:/example.com/') is '["madeupscheme:","","","/example.com/","",""]'
-PASS segments('file:/example.com/') is '["file:","","","/example.com/","",""]'
-PASS segments('ftps:/example.com/') is '["ftps:","","","/example.com/","",""]'
-PASS segments('gopher:/example.com/') is '["gopher:","example.com","","/","",""]'
-PASS segments('ws:/example.com/') is '["ws:","example.com","","/","",""]'
-PASS segments('wss:/example.com/') is '["wss:","example.com","","/","",""]'
-PASS segments('data:/example.com/') is '["data:","","","/example.com/","",""]'
-PASS segments('javascript:/example.com/') is '["javascript:","","","/example.com/","",""]'
-PASS segments('mailto:/example.com/') is '["mailto:","","","/example.com/","",""]'
-PASS segments('http:example.com/') is '["http:","example.org","","/foo/example.com/","",""]'
-PASS segments('ftp:example.com/') is '["ftp:","example.com","","/","",""]'
-PASS segments('https:example.com/') is '["https:","example.com","","/","",""]'
-PASS segments('madeupscheme:example.com/') is '["madeupscheme:","","","example.com/","",""]'
-FAIL segments('file:example.com/') should be ["file:","","","/example.com/","",""]. Was ["file:","","","example.com/","",""].
-PASS segments('ftps:example.com/') is '["ftps:","","","example.com/","",""]'
-PASS segments('gopher:example.com/') is '["gopher:","example.com","","/","",""]'
-PASS segments('ws:example.com/') is '["ws:","example.com","","/","",""]'
-PASS segments('wss:example.com/') is '["wss:","example.com","","/","",""]'
-PASS segments('data:example.com/') is '["data:","","","example.com/","",""]'
-PASS segments('javascript:example.com/') is '["javascript:","","","example.com/","",""]'
-PASS segments('mailto:example.com/') is '["mailto:","","","example.com/","",""]'
-PASS segments('/a/b/c') is '["http:","example.org","","/a/b/c","",""]'
-PASS segments('/a/ /c') is '["http:","example.org","","/a/%20/c","",""]'
-PASS segments('/a%2fc') is '["http:","example.org","","/a%2fc","",""]'
-PASS segments('/a/%2f/c') is '["http:","example.org","","/a/%2f/c","",""]'
-FAIL segments('#β') should be ["http:","example.org","","/foo/bar","","#β"]. Was ["http:","example.org","","/foo/bar","","#%CE%B2"].
+PASS segments('http:[61:27]/:foo') is '["http:","example.org","0","/foo/[61:27]/:foo","",""]'
+PASS segments('http://[1::2]:3:4') is '[":","","0","","",""]'
+PASS segments('http://2001::1') is '[":","","0","","",""]'
+PASS segments('http://[2001::1') is '[":","","0","","",""]'
+PASS segments('http://2001::1]') is '[":","","0","","",""]'
+PASS segments('http://2001::1]:80') is '[":","","0","","",""]'
+PASS segments('http://[2001::1]') is '["http:","[2001::1]","0","/","",""]'
+PASS segments('http://[2001::1]:80') is '["http:","[2001::1]","0","/","",""]'
+PASS segments('http://[[::]]') is '[":","","0","","",""]'
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/LayoutTests/fast/url/segments-from-data-url-expected.txt b/LayoutTests/fast/url/segments-from-data-url-expected.txt
index c64aefc..b97e489 100644
--- a/LayoutTests/fast/url/segments-from-data-url-expected.txt
+++ b/LayoutTests/fast/url/segments-from-data-url-expected.txt
@@ -4,71 +4,71 @@
 
 
 PASS segments('http://user:pass@foo:21/bar;par?b#c') is '["http:","foo","21","/bar;par","?b","#c"]'
-PASS segments('http:foo.com') is '["http:","foo.com","","/","",""]'
-PASS segments('\t   :foo.com   \n') is '[":","","","","",""]'
-PASS segments(' foo.com  ') is '[":","","","","",""]'
-PASS segments('a:\t foo.com') is '["a:","",""," foo.com","",""]'
-PASS segments('http://f:21/ b ? d # e ') is '["http:","f","21","/%20b%20","?%20d%20","# e"]'
-PASS segments('http://f:/c') is '["http:","f","","/c","",""]'
+FAIL segments('http:foo.com') should be ["http:","foo.com","0","/","",""]. Was ["http:","","0","foo.com","",""].
+PASS segments('\t   :foo.com   \n') is '[":","","0","","",""]'
+PASS segments(' foo.com  ') is '[":","","0","","",""]'
+PASS segments('a:\t foo.com') is '["a:","","0"," foo.com","",""]'
+FAIL segments('http://f:21/ b ? d # e ') should be ["http:","f","21","/%20b%20","?%20d%20","# e"]. Was ["http:","f","21","/ b ","?%20d%20","# e"].
+PASS segments('http://f:/c') is '["http:","f","0","/c","",""]'
 PASS segments('http://f:0/c') is '["http:","f","0","/c","",""]'
 PASS segments('http://f:00000000000000/c') is '["http:","f","0","/c","",""]'
 FAIL segments('http://f:00000000000000000000080/c') should be ["http:","f","0","/c","",""]. Was ["http:","f","80","/c","",""].
-PASS segments('http://f:b/c') is '[":","","","","",""]'
-PASS segments('http://f: /c') is '[":","","","","",""]'
-PASS segments('http://f:\n/c') is '[":","","","","",""]'
-PASS segments('http://f:fifty-two/c') is '[":","","","","",""]'
+PASS segments('http://f:b/c') is '[":","","0","","",""]'
+PASS segments('http://f: /c') is '[":","","0","","",""]'
+PASS segments('http://f:\n/c') is '[":","","0","","",""]'
+PASS segments('http://f:fifty-two/c') is '[":","","0","","",""]'
 FAIL segments('http://f:999999/c') should be [":","","0","","",""]. Was ["http:","f","65535","/c","",""].
-PASS segments('http://f: 21 / b ? d # e ') is '[":","","","","",""]'
-FAIL segments('') should be ["data:","","","text/plain,baseURL","",""]. Was [":","","","","",""].
-FAIL segments('  \t') should be ["data:","","","text/plain,baseURL","",""]. Was [":","","","","",""].
-PASS segments(':foo.com/') is '[":","","","","",""]'
-PASS segments(':foo.com\\') is '[":","","","","",""]'
-PASS segments(':') is '[":","","","","",""]'
-PASS segments(':a') is '[":","","","","",""]'
-PASS segments(':/') is '[":","","","","",""]'
-PASS segments(':\\') is '[":","","","","",""]'
-PASS segments(':#') is '[":","","","","",""]'
-FAIL segments('#') should be [":","","","","",""]. Was ["data:","","","text/plain,baseURL","",""].
-FAIL segments('#/') should be [":","","","","",""]. Was ["data:","","","text/plain,baseURL","","#/"].
-FAIL segments('#\\') should be [":","","","","",""]. Was ["data:","","","text/plain,baseURL","","#\\"].
-FAIL segments('#;?') should be [":","","","","",""]. Was ["data:","","","text/plain,baseURL","","#;?"].
-PASS segments('?') is '[":","","","","",""]'
-PASS segments('/') is '[":","","","","",""]'
-PASS segments(':23') is '[":","","","","",""]'
-FAIL segments('/:23') should be ["data:","","","/:23","",""]. Was [":","","","","",""].
-PASS segments('//') is '[":","","","","",""]'
-PASS segments('::') is '[":","","","","",""]'
-PASS segments('::23') is '[":","","","","",""]'
-PASS segments('foo://') is '["foo:","","","//","",""]'
+PASS segments('http://f: 21 / b ? d # e ') is '[":","","0","","",""]'
+FAIL segments('') should be ["data:","","0","text/plain,baseURL","",""]. Was [":","","0","","",""].
+FAIL segments('  \t') should be ["data:","","0","text/plain,baseURL","",""]. Was [":","","0","","",""].
+PASS segments(':foo.com/') is '[":","","0","","",""]'
+PASS segments(':foo.com\\') is '[":","","0","","",""]'
+PASS segments(':') is '[":","","0","","",""]'
+PASS segments(':a') is '[":","","0","","",""]'
+PASS segments(':/') is '[":","","0","","",""]'
+PASS segments(':\\') is '[":","","0","","",""]'
+PASS segments(':#') is '[":","","0","","",""]'
+FAIL segments('#') should be [":","","0","","",""]. Was ["data:","","0","text/plain,baseURL","",""].
+FAIL segments('#/') should be [":","","0","","",""]. Was ["data:","","0","text/plain,baseURL","","#/"].
+FAIL segments('#\\') should be [":","","0","","",""]. Was ["data:","","0","text/plain,baseURL","","#\\"].
+FAIL segments('#;?') should be [":","","0","","",""]. Was ["data:","","0","text/plain,baseURL","","#;?"].
+PASS segments('?') is '[":","","0","","",""]'
+PASS segments('/') is '[":","","0","","",""]'
+PASS segments(':23') is '[":","","0","","",""]'
+FAIL segments('/:23') should be ["data:","","0","/:23","",""]. Was [":","","0","","",""].
+PASS segments('//') is '[":","","0","","",""]'
+PASS segments('::') is '[":","","0","","",""]'
+PASS segments('::23') is '[":","","0","","",""]'
+PASS segments('foo://') is '["foo:","","0","//","",""]'
 PASS segments('http://a:b@c:29/d') is '["http:","c","29","/d","",""]'
-PASS segments('http::@c:29') is '["http:","c","29","/","",""]'
-FAIL segments('http://&a:foo(b]c@d:2/') should be ["http:","d","2","/","",""]. Was [":","","","","",""].
-FAIL segments('http://::@c@d:2') should be ["http:","d","2","/","",""]. Was [":","","","","",""].
-PASS segments('http://foo.com:b@d/') is '["http:","d","","/","",""]'
-PASS segments('http://foo.com/\\@') is '["http:","foo.com","","//@","",""]'
-PASS segments('http:\\\\foo.com\\') is '["http:","foo.com","","/","",""]'
-PASS segments('http:\\\\a\\b:c\\d@foo.com\\') is '["http:","a","","/b:c/d@foo.com/","",""]'
-PASS segments('foo:/') is '["foo:","","","/","",""]'
-PASS segments('foo:/bar.com/') is '["foo:","","","/bar.com/","",""]'
-PASS segments('foo://///////') is '["foo:","","","/////////","",""]'
-PASS segments('foo://///////bar.com/') is '["foo:","","","/////////bar.com/","",""]'
-PASS segments('foo:////://///') is '["foo:","","","////://///","",""]'
-PASS segments('c:/foo') is '["c:","","","/foo","",""]'
-PASS segments('//foo/bar') is '[":","","","","",""]'
-PASS segments('http://foo/path;a??e#f#g') is '["http:","foo","","/path;a","??e","#f#g"]'
-PASS segments('http://foo/abcd?efgh?ijkl') is '["http:","foo","","/abcd","?efgh?ijkl",""]'
-PASS segments('http://foo/abcd#foo?bar') is '["http:","foo","","/abcd","","#foo?bar"]'
-FAIL segments('[61:24:74]:98') should be ["data:","","","text/[61:24:74]:98","",""]. Was [":","","","","",""].
+FAIL segments('http::@c:29') should be ["http:","c","29","/","",""]. Was ["http:","","0",":@c:29","",""].
+FAIL segments('http://&a:foo(b]c@d:2/') should be ["http:","d","2","/","",""]. Was [":","","0","","",""].
+FAIL segments('http://::@c@d:2') should be ["http:","d","2","/","",""]. Was [":","","0","","",""].
+PASS segments('http://foo.com:b@d/') is '["http:","d","0","/","",""]'
+PASS segments('http://foo.com/\\@') is '["http:","foo.com","0","//@","",""]'
+PASS segments('http:\\\\foo.com\\') is '["http:","foo.com","0","/","",""]'
+PASS segments('http:\\\\a\\b:c\\d@foo.com\\') is '["http:","a","0","/b:c/d@foo.com/","",""]'
+PASS segments('foo:/') is '["foo:","","0","/","",""]'
+PASS segments('foo:/bar.com/') is '["foo:","","0","/bar.com/","",""]'
+PASS segments('foo://///////') is '["foo:","","0","/////////","",""]'
+PASS segments('foo://///////bar.com/') is '["foo:","","0","/////////bar.com/","",""]'
+PASS segments('foo:////://///') is '["foo:","","0","////://///","",""]'
+PASS segments('c:/foo') is '["c:","","0","/foo","",""]'
+PASS segments('//foo/bar') is '[":","","0","","",""]'
+PASS segments('http://foo/path;a??e#f#g') is '["http:","foo","0","/path;a","??e","#f#g"]'
+PASS segments('http://foo/abcd?efgh?ijkl') is '["http:","foo","0","/abcd","?efgh?ijkl",""]'
+PASS segments('http://foo/abcd#foo?bar') is '["http:","foo","0","/abcd","","#foo?bar"]'
+FAIL segments('[61:24:74]:98') should be ["data:","","0","text/[61:24:74]:98","",""]. Was [":","","0","","",""].
 FAIL segments('http://[61:27]:98') should be [":","","0","","",""]. Was ["http:","[61:27]","98","/","",""].
-FAIL segments('http:[61:27]/:foo') should be [":","","","","",""]. Was ["http:","[61:27]","","/:foo","",""].
-PASS segments('http://[1::2]:3:4') is '[":","","","","",""]'
-PASS segments('http://2001::1') is '[":","","","","",""]'
-PASS segments('http://[2001::1') is '[":","","","","",""]'
-PASS segments('http://2001::1]') is '[":","","","","",""]'
-PASS segments('http://2001::1]:80') is '[":","","","","",""]'
-PASS segments('http://[2001::1]') is '["http:","[2001::1]","","/","",""]'
-PASS segments('http://[2001::1]:80') is '["http:","[2001::1]","","/","",""]'
-PASS segments('http://[[::]]') is '[":","","","","",""]'
+FAIL segments('http:[61:27]/:foo') should be [":","","0","","",""]. Was ["http:","","0","[61:27]/:foo","",""].
+PASS segments('http://[1::2]:3:4') is '[":","","0","","",""]'
+PASS segments('http://2001::1') is '[":","","0","","",""]'
+PASS segments('http://[2001::1') is '[":","","0","","",""]'
+PASS segments('http://2001::1]') is '[":","","0","","",""]'
+PASS segments('http://2001::1]:80') is '[":","","0","","",""]'
+PASS segments('http://[2001::1]') is '["http:","[2001::1]","0","/","",""]'
+PASS segments('http://[2001::1]:80') is '["http:","[2001::1]","0","/","",""]'
+PASS segments('http://[[::]]') is '[":","","0","","",""]'
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/LayoutTests/fast/url/segments.html b/LayoutTests/fast/url/segments.html
index 96aa871..5cc2f82 100644
--- a/LayoutTests/fast/url/segments.html
+++ b/LayoutTests/fast/url/segments.html
@@ -1,7 +1,6 @@
-<!DOCTYPE html>
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
 <html>
 <head>
-<meta charset="utf-8">
 <link rel="stylesheet" href="../js/resources/js-test-style.css">
 <script src="../js/resources/js-test-pre.js"></script>
 <script src="resources/utilities.js"></script>
diff --git a/LayoutTests/fast/url/standard-url-expected.txt b/LayoutTests/fast/url/standard-url-expected.txt
index d274059..5312e07 100644
--- a/LayoutTests/fast/url/standard-url-expected.txt
+++ b/LayoutTests/fast/url/standard-url-expected.txt
@@ -4,9 +4,7 @@
 
 
 PASS canonicalize('http://www.google.com/foo?bar=baz#') is 'http://www.google.com/foo?bar=baz#'
-FAIL canonicalize('http://www.google.com/foo?bar=baz# »') should be http://www.google.com/foo?bar=baz# ». Was http://www.google.com/foo?bar=baz# %BB.
 PASS canonicalize('http://[www.google.com]/') is 'http://[www.google.com]/'
-PASS canonicalize('http://www.google.com') is 'http://www.google.com/'
 FAIL canonicalize('http:////////user:@google.com:99?foo') should be http://user@google.com:99/?foo. Was http://////user:@google.com:99?foo.
 FAIL canonicalize('http://192.0x00A80001') should be http://192.168.0.1/. Was http://192.0x00A80001/.
 FAIL canonicalize('http://www/foo%2Ehtml') should be http://www/foo.html. Was http://www/foo%2Ehtml.
@@ -32,31 +30,6 @@
 PASS canonicalize('wss://foo:81/') is 'wss://foo:81/'
 PASS canonicalize('wss://foo:443/') is 'wss://foo/'
 PASS canonicalize('wss://foo:815/') is 'wss://foo:815/'
-PASS canonicalize('http:/example.com/') is 'http://example.com/'
-PASS canonicalize('ftp:/example.com/') is 'ftp://example.com/'
-PASS canonicalize('https:/example.com/') is 'https://example.com/'
-PASS canonicalize('madeupscheme:/example.com/') is 'madeupscheme:/example.com/'
-FAIL canonicalize('file:/example.com/') should be file://localhost/example.com/. Was file:///example.com/.
-PASS canonicalize('ftps:/example.com/') is 'ftps:/example.com/'
-PASS canonicalize('gopher:/example.com/') is 'gopher://example.com/'
-PASS canonicalize('ws:/example.com/') is 'ws://example.com/'
-PASS canonicalize('wss:/example.com/') is 'wss://example.com/'
-PASS canonicalize('data:/example.com/') is 'data:/example.com/'
-PASS canonicalize('javascript:/example.com/') is 'javascript:/example.com/'
-PASS canonicalize('mailto:/example.com/') is 'mailto:/example.com/'
-PASS canonicalize('http:example.com/') is 'http://example.com/'
-PASS canonicalize('ftp:example.com/') is 'ftp://example.com/'
-PASS canonicalize('https:example.com/') is 'https://example.com/'
-PASS canonicalize('madeupscheme:example.com/') is 'madeupscheme:example.com/'
-PASS canonicalize('ftps:example.com/') is 'ftps:example.com/'
-PASS canonicalize('gopher:example.com/') is 'gopher://example.com/'
-PASS canonicalize('ws:example.com/') is 'ws://example.com/'
-PASS canonicalize('wss:example.com/') is 'wss://example.com/'
-PASS canonicalize('data:example.com/') is 'data:example.com/'
-PASS canonicalize('javascript:example.com/') is 'javascript:example.com/'
-PASS canonicalize('mailto:example.com/') is 'mailto:example.com/'
-PASS canonicalize('javascript:alert(\t 1 \n\r)') is 'javascript:alert( 1 )'
-PASS canonicalize('javascript:alert("  β ")') is 'javascript:alert(" %01 %CE%B2 ")'
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/LayoutTests/fast/url/trivial-segments-expected.txt b/LayoutTests/fast/url/trivial-segments-expected.txt
index 4f384fc..882ff73 100644
--- a/LayoutTests/fast/url/trivial-segments-expected.txt
+++ b/LayoutTests/fast/url/trivial-segments-expected.txt
@@ -3,7 +3,7 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS segments('http://example.com/') is '["http:","example.com","","/","",""]'
+PASS segments('http://example.com/') is '["http:","example.com","0","/","",""]'
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/NOTICE b/NOTICE
index fc77db5..92c7323 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,79 +1,57 @@
-(WebKit doesn't distribute an explicit license.  This LICENSE is derived from
-license text in the source.)
-
-Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-2006, 2007 Alexander Kellett, Alexey Proskuryakov, Alex Mathews, Allan
-Sandfeld Jensen, Alp Toker, Anders Carlsson, Andrew Wellington, Antti
-Koivisto, Apple Inc., Arthur Langereis, Baron Schwartz, Bjoern Graf,
-Brent Fulgham, Cameron Zwarich, Charles Samuels, Christian Dywan,
-Collabora Ltd., Cyrus Patel, Daniel Molkentin, Dave Maclachlan, David
-Smith, Dawit Alemayehu, Dirk Mueller, Dirk Schulze, Don Gibson, Enrico
-Ros, Eric Seidel, Frederik Holljen, Frerich Raabe, Friedmann Kleint,
-George Staikos, Google Inc., Graham Dennis, Harri Porten, Henry Mason,
-Hiroyuki Ikezoe, Holger Hans Peter Freyther, IBM, James G. Speth, Jan
-Alonzo, Jean-Loup Gailly, John Reis, Jonas Witt, Jon Shier, Jonas
-Witt, Julien Chaffraix, Justin Haygood, Kevin Ollivier, Kevin Watters,
-Kimmo Kinnunen, Kouhei Sutou, Krzysztof Kowalczyk, Lars Knoll, Luca
-Bruno, Maks Orlovich, Malte Starostik, Mark Adler, Martin Jones,
-Marvin Decker, Matt Lilek, Michael Emmel, Mitz Pettel, mozilla.org,
-Netscape Communications Corporation, Nicholas Shanks, Nikolas
-Zimmermann, Nokia, Oliver Hunt, Opened Hand, Paul Johnston, Peter
-Kelly, Pioneer Research Center USA, Rich Moore, Rob Buis, Robin Dunn,
-Ronald Tschalär, Samuel Weinig, Simon Hausmann, Staikos Computing
-Services Inc., Stefan Schimanski, Symantec Corporation, The Dojo
-Foundation, The Karbon Developers, Thomas Boyer, Tim Copperfield,
-Tobias Anton, Torben Weis, Trolltech, University of Cambridge, Vaclav
-Slavik, Waldo Bastian, Xan Lopez, Zack Rusin
-
-The terms and conditions vary from file to file, but are one of:
+Copyright (C) 2005 Apple Computer, Inc.  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
+modification, are permitted provided that the following conditions
+are met:
 
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
+1.  Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer. 
+2.  Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution. 
+3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+    its contributors may be used to endorse or promote products derived
+    from this software without specific prior written permission. 
 
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the
-   distribution.
+THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-*OR*
+Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
+modification, are permitted provided that the following conditions
+are met:
 1. Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
 2. Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the
-   distribution.
-3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
-   its contributors may be used to endorse or promote products derived
-   from this software without specific prior written permission.
+   documentation and/or other materials provided with the distribution.
 
 THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-
 OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 
                   GNU LIBRARY GENERAL PUBLIC LICENSE
                        Version 2, June 1991
 
  Copyright (C) 1991 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
@@ -506,12 +484,55 @@
 DAMAGES.
 
                      END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
 
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
                   GNU LESSER GENERAL PUBLIC LICENSE
                        Version 2.1, February 1999
 
  Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
@@ -655,7 +676,7 @@
 on the Library (independent of the use of the Library in a tool for
 writing it).  Whether that is true depends on what the Library does
 and what the program that uses the Library does.
-
+  
   1. You may copy and distribute verbatim copies of the Library's
 complete source code as you receive it, in any medium, provided that
 you conspicuously and appropriately publish on each copy an
@@ -965,3 +986,47 @@
 DAMAGES.
 
                      END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/Source/Android.mk b/Source/Android.mk
new file mode 100644
index 0000000..fd1f622
--- /dev/null
+++ b/Source/Android.mk
@@ -0,0 +1,320 @@
+##
+## Copyright 2009, The Android Open Source Project
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions
+## are met:
+##  * Redistributions of source code must retain the above copyright
+##    notice, this list of conditions and the following disclaimer.
+##  * Redistributions in binary form must reproduce the above copyright
+##    notice, this list of conditions and the following disclaimer in the
+##    documentation and/or other materials provided with the distribution.
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+## PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+##
+
+LOCAL_PATH := $(call my-dir)
+
+# Two ways to control which JS engine is used:
+# 1. use JS_ENGINE environment variable, value can be either 'jsc' or 'v8'
+#    This is the preferred way.
+# 2. if JS_ENGINE is not set, or is not 'jsc' or 'v8', this makefile picks
+#    up a default engine to build.
+#    To help setup buildbot, a new environment variable, USE_ALT_JS_ENGINE,
+#    can be set to true, so that two builds can be different but without
+#    specifying which JS engine to use.
+# To enable JIT in Android's JSC, please set ENABLE_JSC_JIT environment
+# variable to true.
+
+# Read JS_ENGINE environment variable
+JAVASCRIPT_ENGINE = $(JS_ENGINE)
+
+ifneq ($(JAVASCRIPT_ENGINE),jsc)
+  ifneq ($(JAVASCRIPT_ENGINE),v8)
+    # No JS engine is specified, pickup the one we want as default.
+    ifeq ($(USE_ALT_JS_ENGINE),true)
+      JAVASCRIPT_ENGINE = v8
+    else
+      JAVASCRIPT_ENGINE = jsc
+    endif
+  endif
+endif
+
+BASE_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# Define our module and find the intermediates directory
+LOCAL_MODULE := libwebcore
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+base_intermediates := $(call local-intermediates-dir)
+
+# Using := here prevents recursive expansion
+WEBKIT_SRC_FILES :=
+
+# We have to use bison 2.3
+include $(BASE_PATH)/bison_check.mk
+
+# Build our list of include paths. We include WebKit/android/icu first so that
+# any files that include <unicode/ucnv.h> will include our ucnv.h first. We
+# also add external/ as an include directory so that we can specify the real
+# icu header directory as a more exact reference to avoid including our ucnv.h.
+#
+# Note that JavasCriptCore/ must be included after WebCore/, so that we pick up
+# the right config.h.
+LOCAL_C_INCLUDES := \
+	$(JNI_H_INCLUDE) \
+	$(LOCAL_PATH)/WebKit/android/icu \
+	external/ \
+	external/icu4c/common \
+	external/icu4c/i18n \
+	external/libxml2/include \
+	external/skia/emoji \
+	external/skia/include/core \
+	external/skia/include/effects \
+	external/skia/include/images \
+	external/skia/include/ports \
+	external/skia/include/utils \
+	external/skia/src/ports \
+	external/sqlite/dist \
+	frameworks/base/core/jni/android/graphics
+
+LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \
+	$(LOCAL_PATH)/WebCore \
+	$(LOCAL_PATH)/WebCore/accessibility \
+	$(LOCAL_PATH)/WebCore/bindings/generic \
+	$(LOCAL_PATH)/WebCore/css \
+	$(LOCAL_PATH)/WebCore/dom \
+	$(LOCAL_PATH)/WebCore/editing \
+	$(LOCAL_PATH)/WebCore/history \
+	$(LOCAL_PATH)/WebCore/history/android \
+	$(LOCAL_PATH)/WebCore/html \
+	$(LOCAL_PATH)/WebCore/html/canvas \
+	$(LOCAL_PATH)/WebCore/inspector \
+	$(LOCAL_PATH)/WebCore/loader \
+	$(LOCAL_PATH)/WebCore/loader/appcache \
+	$(LOCAL_PATH)/WebCore/loader/icon \
+	$(LOCAL_PATH)/WebCore/notifications \
+	$(LOCAL_PATH)/WebCore/page \
+	$(LOCAL_PATH)/WebCore/page/android \
+	$(LOCAL_PATH)/WebCore/page/animation \
+	$(LOCAL_PATH)/WebCore/platform \
+	$(LOCAL_PATH)/WebCore/platform/android \
+	$(LOCAL_PATH)/WebCore/platform/animation \
+	$(LOCAL_PATH)/WebCore/platform/graphics \
+	$(LOCAL_PATH)/WebCore/platform/graphics/android \
+	$(LOCAL_PATH)/WebCore/platform/graphics/network \
+	$(LOCAL_PATH)/WebCore/platform/graphics/skia \
+	$(LOCAL_PATH)/WebCore/platform/graphics/transforms \
+	$(LOCAL_PATH)/WebCore/platform/image-decoders \
+	$(LOCAL_PATH)/WebCore/platform/leveldb \
+	$(LOCAL_PATH)/WebCore/platform/mock \
+	$(LOCAL_PATH)/WebCore/platform/network \
+	$(LOCAL_PATH)/WebCore/platform/network/android \
+	$(LOCAL_PATH)/WebCore/platform/sql \
+	$(LOCAL_PATH)/WebCore/platform/text \
+	$(LOCAL_PATH)/WebCore/plugins \
+	$(LOCAL_PATH)/WebCore/plugins/android \
+	$(LOCAL_PATH)/WebCore/rendering \
+	$(LOCAL_PATH)/WebCore/rendering/style \
+	$(LOCAL_PATH)/WebCore/storage \
+	$(LOCAL_PATH)/WebCore/workers \
+	$(LOCAL_PATH)/WebCore/xml
+
+LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \
+	$(LOCAL_PATH)/WebKit/android \
+	$(LOCAL_PATH)/WebKit/android/WebCoreSupport \
+	$(LOCAL_PATH)/WebKit/android/jni \
+	$(LOCAL_PATH)/WebKit/android/nav \
+	$(LOCAL_PATH)/WebKit/android/plugins \
+	$(LOCAL_PATH)/WebKit/android/stl
+
+LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \
+	$(LOCAL_PATH)/JavaScriptCore \
+	$(LOCAL_PATH)/JavaScriptCore/wtf \
+	$(LOCAL_PATH)/JavaScriptCore/wtf/unicode \
+	$(LOCAL_PATH)/JavaScriptCore/wtf/unicode/icu
+
+LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \
+	$(base_intermediates)/WebCore/ \
+	$(base_intermediates)/WebCore/css \
+	$(base_intermediates)/WebCore/html \
+	$(base_intermediates)/WebCore/platform
+
+ifeq ($(ENABLE_SVG), true)
+LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \
+	$(LOCAL_PATH)/WebCore/platform/graphics/filters \
+	$(LOCAL_PATH)/WebCore/svg \
+	$(LOCAL_PATH)/WebCore/svg/animation \
+	$(LOCAL_PATH)/WebCore/svg/graphics \
+	$(LOCAL_PATH)/WebCore/svg/graphics/filters \
+	$(base_intermediates)/WebCore/svg
+endif
+
+ifeq ($(JAVASCRIPT_ENGINE),v8)
+# Include WTF source file.
+d := JavaScriptCore
+LOCAL_PATH := $(BASE_PATH)/$d
+intermediates := $(base_intermediates)/$d
+include $(LOCAL_PATH)/Android.v8.wtf.mk
+WEBKIT_SRC_FILES += $(addprefix $d/,$(LOCAL_SRC_FILES))
+endif  # JAVASCRIPT_ENGINE == v8
+
+# Include source files for WebCore
+d := WebCore
+LOCAL_PATH := $(BASE_PATH)/$d
+JAVASCRIPTCORE_PATH := $(BASE_PATH)/JavaScriptCore
+intermediates := $(base_intermediates)/$d
+include $(LOCAL_PATH)/Android.mk
+ifeq ($(JAVASCRIPT_ENGINE),jsc)
+include $(LOCAL_PATH)/Android.jscbindings.mk
+endif
+ifeq ($(JAVASCRIPT_ENGINE),v8)
+include $(LOCAL_PATH)/Android.v8bindings.mk
+endif
+WEBKIT_SRC_FILES += $(addprefix $d/,$(LOCAL_SRC_FILES))
+LOCAL_C_INCLUDES += $(BINDING_C_INCLUDES)
+
+# Include the derived source files for WebCore. Uses the same path as
+# WebCore
+include $(LOCAL_PATH)/Android.derived.mk
+ifeq ($(JAVASCRIPT_ENGINE),jsc)
+include $(LOCAL_PATH)/Android.derived.jscbindings.mk
+endif
+ifeq ($(JAVASCRIPT_ENGINE),v8)
+include $(LOCAL_PATH)/Android.derived.v8bindings.mk
+endif
+
+# Redefine LOCAL_PATH here so the build system is not confused
+LOCAL_PATH := $(BASE_PATH)
+
+# Define our compiler flags
+LOCAL_CFLAGS += -Wno-endif-labels -Wno-import -Wno-format
+LOCAL_CFLAGS += -fno-strict-aliasing
+LOCAL_CFLAGS += -include "WebCorePrefix.h"
+LOCAL_CFLAGS += -fvisibility=hidden
+
+# Enable JSC JIT if JSC is used and ENABLE_JSC_JIT environment
+# variable is set to true
+ifeq ($(JAVASCRIPT_ENGINE),jsc)
+ifeq ($(ENABLE_JSC_JIT),true)
+LOCAL_CFLAGS += -DENABLE_ANDROID_JSC_JIT=1
+endif
+endif
+
+ifeq ($(TARGET_ARCH),arm)
+LOCAL_CFLAGS += -Darm
+endif
+
+ifeq ($(ENABLE_SVG),true)
+LOCAL_CFLAGS += -DENABLE_SVG=1
+endif
+
+# Temporary disable SVG_ANIMATION.
+ifeq ($(ENABLE_SVG_ANIMATION),true)
+LOCAL_CFLAGS += -DENABLE_SVG_ANIMATION=1
+endif
+
+ifeq ($(WEBCORE_INSTRUMENTATION),true)
+LOCAL_CFLAGS += -DANDROID_INSTRUMENT
+endif
+
+# LOCAL_LDLIBS is used in simulator builds only and simulator builds are only
+# valid on Linux
+LOCAL_LDLIBS += -lpthread -ldl
+
+# Build the list of shared libraries
+LOCAL_SHARED_LIBRARIES := \
+	libandroid_runtime \
+	libnativehelper \
+	libsqlite \
+	libskia \
+	libutils \
+	libui \
+	libcutils \
+	libicuuc \
+	libicudata \
+	libicui18n \
+	libmedia
+
+ifeq ($(WEBCORE_INSTRUMENTATION),true)
+LOCAL_SHARED_LIBRARIES += libhardware_legacy
+endif
+
+# We have to use the android version of libdl.
+LOCAL_SHARED_LIBRARIES += libdl
+
+# Build the list of static libraries
+LOCAL_STATIC_LIBRARIES := libxml2
+ifeq ($(JAVASCRIPT_ENGINE),v8)
+LOCAL_STATIC_LIBRARIES += libv8
+endif
+
+# Redefine LOCAL_SRC_FILES to be all the WebKit source files
+LOCAL_SRC_FILES := $(WEBKIT_SRC_FILES)
+
+# Define this for use in other makefiles.
+WEBKIT_C_INCLUDES := $(LOCAL_C_INCLUDES)
+WEBKIT_CFLAGS := $(LOCAL_CFLAGS)
+WEBKIT_GENERATED_SOURCES := $(LOCAL_GENERATED_SOURCES)
+WEBKIT_LDLIBS := $(LOCAL_LDLIBS)
+WEBKIT_SHARED_LIBRARIES := $(LOCAL_SHARED_LIBRARIES)
+WEBKIT_STATIC_LIBRARIES := $(LOCAL_STATIC_LIBRARIES)
+
+# Build the library all at once
+include $(BUILD_STATIC_LIBRARY)
+
+ifeq ($(JAVASCRIPT_ENGINE),jsc)
+# Now build libjs as a static library.
+include $(CLEAR_VARS)
+LOCAL_MODULE := libjs
+LOCAL_LDLIBS := $(WEBKIT_LDLIBS)
+LOCAL_SHARED_LIBRARIES := $(WEBKIT_SHARED_LIBRARIES)
+LOCAL_STATIC_LIBRARIES := $(WEBKIT_STATIC_LIBRARIES)
+LOCAL_CFLAGS := $(WEBKIT_CFLAGS)
+# Include source files for JavaScriptCore
+d := JavaScriptCore
+LOCAL_PATH := $(BASE_PATH)/$d
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+# Cannot use base_intermediates as this is a new module
+intermediates := $(call local-intermediates-dir)
+include $(LOCAL_PATH)/Android.mk
+# Redefine LOCAL_SRC_FILES with the correct prefix
+LOCAL_SRC_FILES := $(addprefix $d/,$(LOCAL_SRC_FILES))
+# Use the base path to resolve file names
+LOCAL_PATH := $(BASE_PATH)
+# Append jsc intermediate include paths to the WebKit include list.
+LOCAL_C_INCLUDES := $(WEBKIT_C_INCLUDES) \
+	$(intermediates) \
+	$(intermediates)/parser \
+	$(intermediates)/runtime \
+# Build libjs
+include $(BUILD_STATIC_LIBRARY)
+endif  # JAVASCRIPT_ENGINE == jsc
+
+# Now build the shared library using only the exported jni entry point. This
+# will strip out any unused code from the entry point.
+include $(CLEAR_VARS)
+# if you need to make webcore huge (for debugging), enable this line
+#LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE := libwebcore
+LOCAL_LDLIBS := $(WEBKIT_LDLIBS)
+LOCAL_SHARED_LIBRARIES := $(WEBKIT_SHARED_LIBRARIES)
+LOCAL_STATIC_LIBRARIES := libwebcore $(WEBKIT_STATIC_LIBRARIES)
+ifeq ($(JAVASCRIPT_ENGINE),jsc)
+LOCAL_STATIC_LIBRARIES += libjs
+endif
+LOCAL_LDFLAGS := -fvisibility=hidden
+LOCAL_CFLAGS := $(WEBKIT_CFLAGS)
+LOCAL_C_INCLUDES := $(WEBKIT_C_INCLUDES)
+LOCAL_PATH := $(BASE_PATH)
+include $(BUILD_SHARED_LIBRARY)
diff --git a/Source/JavaScriptCore/Android.mk b/Source/JavaScriptCore/Android.mk
new file mode 100644
index 0000000..48f326a
--- /dev/null
+++ b/Source/JavaScriptCore/Android.mk
@@ -0,0 +1,251 @@
+##
+## Copyright 2009, The Android Open Source Project
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions
+## are met:
+##  * Redistributions of source code must retain the above copyright
+##    notice, this list of conditions and the following disclaimer.
+##  * Redistributions in binary form must reproduce the above copyright
+##    notice, this list of conditions and the following disclaimer in the
+##    documentation and/or other materials provided with the distribution.
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+## PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+##
+
+LOCAL_SRC_FILES := \
+	API/JSValueRef.cpp \
+	API/JSCallbackConstructor.cpp \
+	API/JSCallbackFunction.cpp \
+	API/JSCallbackObject.cpp \
+	API/JSClassRef.cpp \
+	API/JSObjectRef.cpp \
+	API/JSStringRef.cpp \
+	API/OpaqueJSString.cpp \
+	\
+	assembler/ARMv7Assembler.cpp \
+	\
+	bytecode/CodeBlock.cpp \
+	bytecode/JumpTable.cpp \
+	bytecode/Opcode.cpp \
+	bytecode/SamplingTool.cpp \
+	bytecode/StructureStubInfo.cpp \
+	\
+	bytecompiler/BytecodeGenerator.cpp \
+	bytecompiler/NodesCodegen.cpp \
+	\
+	debugger/Debugger.cpp \
+	debugger/DebuggerActivation.cpp \
+	debugger/DebuggerCallFrame.cpp \
+	\
+	heap/ConservativeRoots.cpp \
+	heap/HandleHeap.cpp \
+	heap/HandleStack.cpp \
+	heap/Heap.cpp \
+	heap/MachineStackMarker.cpp \
+	heap/MarkStack.cpp \
+	heap/MarkStackPosix.cpp \
+	heap/MarkedBlock.cpp \
+	heap/MarkedSpace.cpp \
+	\
+	interpreter/CallFrame.cpp \
+	interpreter/Interpreter.cpp \
+	interpreter/RegisterFile.cpp \
+	\
+	jit/ExecutableAllocator.cpp\
+	jit/ExecutableAllocatorFixedVMPool.cpp \
+	jit/JIT.cpp \
+	jit/JITArithmetic.cpp \
+	jit/JITArithmetic32_64.cpp \
+	jit/JITCall.cpp \
+	jit/JITCall32_64.cpp \
+	jit/JITOpcodes.cpp \
+	jit/JITPropertyAccess.cpp \
+	jit/JITStubs.cpp \
+	jit/ThunkGenerators.cpp \
+	\
+	parser/JSParser.cpp \
+	parser/Lexer.cpp \
+	parser/Nodes.cpp \
+	parser/Parser.cpp \
+	parser/ParserArena.cpp \
+	parser/SourceProviderCache.cpp \
+	\
+	profiler/Profile.cpp \
+	profiler/ProfileGenerator.cpp \
+	profiler/ProfileNode.cpp \
+	profiler/Profiler.cpp \
+	\
+	runtime/ArgList.cpp \
+	runtime/Arguments.cpp \
+	runtime/ArrayConstructor.cpp \
+	runtime/ArrayPrototype.cpp \
+	runtime/BooleanConstructor.cpp \
+	runtime/BooleanObject.cpp \
+	runtime/BooleanPrototype.cpp \
+	runtime/CallData.cpp \
+	runtime/CommonIdentifiers.cpp \
+	runtime/Completion.cpp \
+	runtime/ConstructData.cpp \
+	runtime/DateConstructor.cpp \
+	runtime/DateConversion.cpp \
+	runtime/DateInstance.cpp \
+	runtime/DatePrototype.cpp \
+	runtime/Error.cpp \
+	runtime/ErrorConstructor.cpp \
+	runtime/ErrorInstance.cpp \
+	runtime/ErrorPrototype.cpp \
+	runtime/ExceptionHelpers.cpp \
+	runtime/Executable.cpp \
+	runtime/FunctionConstructor.cpp \
+	runtime/FunctionPrototype.cpp \
+	runtime/GCActivityCallback.cpp \
+	runtime/GetterSetter.cpp \
+	runtime/Identifier.cpp \
+	runtime/InitializeThreading.cpp \
+	runtime/InternalFunction.cpp \
+	runtime/JSAPIValueWrapper.cpp \
+	runtime/JSActivation.cpp \
+	runtime/JSArray.cpp \
+	runtime/JSByteArray.cpp \
+	runtime/JSCell.cpp \
+	runtime/JSChunk.cpp \
+	runtime/JSFunction.cpp \
+	runtime/JSGlobalData.cpp \
+	runtime/JSGlobalObject.cpp \
+	runtime/JSGlobalObjectFunctions.cpp \
+	runtime/JSLock.cpp \
+	runtime/JSNotAnObject.cpp \
+	runtime/JSONObject.cpp \
+	runtime/JSObject.cpp \
+	runtime/JSObjectWithGlobalObject.cpp \
+	runtime/JSPropertyNameIterator.cpp \
+	runtime/JSStaticScopeObject.cpp \
+	runtime/JSString.cpp \
+	runtime/JSValue.cpp \
+	runtime/JSVariableObject.cpp \
+	runtime/JSWrapperObject.cpp \
+	runtime/LiteralParser.cpp \
+	runtime/Lookup.cpp \
+	runtime/MathObject.cpp \
+	runtime/NativeErrorConstructor.cpp \
+	runtime/NativeErrorPrototype.cpp \
+	runtime/NumberConstructor.cpp \
+	runtime/NumberObject.cpp \
+	runtime/NumberPrototype.cpp \
+	runtime/ObjectConstructor.cpp \
+	runtime/ObjectPrototype.cpp \
+	runtime/Operations.cpp \
+	runtime/PropertyDescriptor.cpp \
+	runtime/PropertyNameArray.cpp \
+	runtime/PropertySlot.cpp \
+	runtime/RegExp.cpp \
+	runtime/RegExpCache.cpp \
+	runtime/RegExpConstructor.cpp \
+	runtime/RegExpObject.cpp \
+	runtime/RegExpPrototype.cpp \
+	runtime/RopeImpl.cpp \
+	runtime/ScopeChain.cpp \
+	runtime/SmallStrings.cpp \
+	runtime/StrictEvalActivation.cpp \
+	runtime/StringConstructor.cpp \
+	runtime/StringObject.cpp \
+	runtime/StringPrototype.cpp \
+	runtime/StringRecursionChecker.cpp \
+	runtime/Structure.cpp \
+	runtime/StructureChain.cpp \
+	runtime/TimeoutChecker.cpp \
+	runtime/UString.cpp \
+	\
+	wtf/Assertions.cpp \
+	wtf/ByteArray.cpp \
+	wtf/CryptographicallyRandomNumber.cpp \
+	wtf/CurrentTime.cpp \
+	wtf/DateMath.cpp \
+	wtf/DecimalNumber.cpp \
+	wtf/FastMalloc.cpp \
+	wtf/HashTable.cpp \
+	wtf/MD5.cpp \
+	wtf/MainThread.cpp \
+	wtf/OSAllocatorPosix.cpp \
+	wtf/OSRandomSource.cpp \
+	wtf/PageAllocationAligned.cpp\
+	wtf/PageBlock.cpp\
+	wtf/RandomNumber.cpp \
+	wtf/RefCountedLeakCounter.cpp \
+	wtf/SHA1.cpp \
+	wtf/StackBounds.cpp \
+	wtf/TCSystemAlloc.cpp \
+	wtf/ThreadIdentifierDataPthreads.cpp \
+	wtf/Threading.cpp \
+	wtf/ThreadingPthreads.cpp \
+	wtf/TypeTraits.cpp \
+	wtf/WTFThreadData.cpp \
+	wtf/dtoa.cpp \
+	\
+	wtf/android/MainThreadAndroid.cpp \
+	\
+	wtf/text/AtomicString.cpp \
+	wtf/text/CString.cpp \
+	wtf/text/StringBuilder.cpp \
+	wtf/text/StringImpl.cpp \
+	wtf/text/StringStatics.cpp \
+	wtf/text/WTFString.cpp \
+	\
+	wtf/unicode/CollatorDefault.cpp \
+	wtf/unicode/UTF8.cpp \
+	\
+	wtf/unicode/icu/CollatorICU.cpp \
+	\
+	wtf/url/src/URLCharacterTypes.cpp \
+	wtf/url/src/URLEscape.cpp \
+	wtf/url/src/URLSegments.cpp \
+	\
+	yarr/YarrPattern.cpp \
+	yarr/YarrInterpreter.cpp \
+	yarr/YarrJIT.cpp \
+	yarr/YarrSyntaxChecker.cpp
+
+# generated headers
+JSC_OBJECTS := $(addprefix $(intermediates)/runtime/, \
+				ArrayPrototype.lut.h \
+				DatePrototype.lut.h \
+				JSONObject.lut.h \
+				MathObject.lut.h \
+				NumberConstructor.lut.h \
+				ObjectConstructor.lut.h \
+				RegExpConstructor.lut.h \
+				RegExpObject.lut.h \
+				StringPrototype.lut.h \
+			)
+$(JSC_OBJECTS): PRIVATE_PATH := $(LOCAL_PATH)
+$(JSC_OBJECTS): PRIVATE_CUSTOM_TOOL = perl $(PRIVATE_PATH)/create_hash_table $< -i > $@
+$(JSC_OBJECTS): $(LOCAL_PATH)/create_hash_table
+$(JSC_OBJECTS): $(intermediates)/%.lut.h : $(LOCAL_PATH)/%.cpp
+	$(transform-generated-source)
+
+
+LEXER_HEADER := $(intermediates)/Lexer.lut.h
+$(LEXER_HEADER): PRIVATE_PATH := $(LOCAL_PATH)
+$(LEXER_HEADER): PRIVATE_CUSTOM_TOOL = perl $(PRIVATE_PATH)/create_hash_table $< -i > $@
+$(LEXER_HEADER): $(LOCAL_PATH)/create_hash_table
+$(LEXER_HEADER): $(intermediates)/%.lut.h : $(LOCAL_PATH)/parser/Keywords.table
+	$(transform-generated-source)
+
+REGEXP_JIT_TABLES := $(intermediates)/RegExpJitTables.h
+$(REGEXP_JIT_TABLES): PRIVATE_PATH := $(LOCAL_PATH)
+$(REGEXP_JIT_TABLES): PRIVATE_CUSTOM_TOOL = python $(PRIVATE_PATH)/create_regex_tables > $@
+$(REGEXP_JIT_TABLES): $(LOCAL_PATH)/create_regex_tables
+	$(transform-generated-source)
+
+LOCAL_GENERATED_SOURCES += $(JSC_OBJECTS) $(LEXER_HEADER) $(REGEXP_JIT_TABLES)
diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp
index fc1e986..dc15e4f 100644
--- a/Source/JavaScriptCore/parser/Parser.cpp
+++ b/Source/JavaScriptCore/parser/Parser.cpp
@@ -27,10 +27,17 @@
 #include "JSParser.h"
 #include "Lexer.h"
 
+#ifdef ANDROID_INSTRUMENT
+#include "TimeCounter.h"
+#endif
+
 namespace JSC {
 
 void Parser::parse(JSGlobalData* globalData, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode mode, int* errLine, UString* errMsg)
 {
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::start(android::TimeCounter::JavaScriptParseTimeCounter);
+#endif
     ASSERT(globalData);
     m_sourceElements = 0;
 
@@ -58,6 +65,9 @@
         *errMsg = parseError ? parseError : "Parse error";
         m_sourceElements = 0;
     }
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::record(android::TimeCounter::JavaScriptParseTimeCounter, __FUNCTION__);
+#endif
 }
 
 void Parser::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack, 
diff --git a/Source/JavaScriptCore/runtime/TimeoutChecker.h b/Source/JavaScriptCore/runtime/TimeoutChecker.h
index 5925641..71ce169 100644
--- a/Source/JavaScriptCore/runtime/TimeoutChecker.h
+++ b/Source/JavaScriptCore/runtime/TimeoutChecker.h
@@ -31,6 +31,10 @@
 
 #include <wtf/Assertions.h>
 
+#ifdef ANDROID_INSTRUMENT
+#include "TimeCounter.h"
+#endif
+
 namespace JSC {
 
     class ExecState;
@@ -48,6 +52,10 @@
         {
             if (!m_startCount)
                 reset();
+#ifdef ANDROID_INSTRUMENT
+            if (!m_startCount)
+                android::TimeCounter::start(android::TimeCounter::JavaScriptTimeCounter);
+#endif
             ++m_startCount;
         }
 
@@ -55,6 +63,10 @@
         {
             ASSERT(m_startCount);
             --m_startCount;
+#ifdef ANDROID_INSTRUMENT
+            if (!m_startCount)
+                android::TimeCounter::record(android::TimeCounter::JavaScriptTimeCounter, __FUNCTION__);
+#endif
         }
 
         void reset();
diff --git a/Source/JavaScriptCore/wtf/Assertions.cpp b/Source/JavaScriptCore/wtf/Assertions.cpp
index 0642414..930368c 100644
--- a/Source/JavaScriptCore/wtf/Assertions.cpp
+++ b/Source/JavaScriptCore/wtf/Assertions.cpp
@@ -66,10 +66,6 @@
 #include <execinfo.h>
 #endif
 
-#if OS(ANDROID)
-#include <utils/Log.h>
-#endif
-
 extern "C" {
 
 #if PLATFORM(BREWMP)
@@ -128,9 +124,7 @@
         vsnprintf(buffer.data(), size, format, args);
         printLog(buffer);
     }
-#elif OS(ANDROID)
-    LOG_PRI_VA(ANDROID_LOG_DEBUG, "WebKit", format, args);
-    return;
+
 #elif HAVE(ISDEBUGGERPRESENT)
     if (IsDebuggerPresent()) {
         size_t size = 1024;
diff --git a/Source/JavaScriptCore/wtf/HashTraits.h b/Source/JavaScriptCore/wtf/HashTraits.h
index 7deeb3a..fba5afe 100644
--- a/Source/JavaScriptCore/wtf/HashTraits.h
+++ b/Source/JavaScriptCore/wtf/HashTraits.h
@@ -28,8 +28,6 @@
 
 namespace WTF {
 
-    class String;
-
     using std::pair;
     using std::make_pair;
 
@@ -90,7 +88,6 @@
     };
 
     template<typename P> struct HashTraits<RefPtr<P> > : SimpleClassHashTraits<RefPtr<P> > { };
-    template<> struct HashTraits<String> : SimpleClassHashTraits<String> { };
 
     // special traits for pairs, helpful for their use in HashMap implementation
 
diff --git a/Source/JavaScriptCore/wtf/Platform.h b/Source/JavaScriptCore/wtf/Platform.h
index a1db9d6..e92af89 100644
--- a/Source/JavaScriptCore/wtf/Platform.h
+++ b/Source/JavaScriptCore/wtf/Platform.h
@@ -676,10 +676,7 @@
 #if PLATFORM(ANDROID)
 #define WEBCORE_NAVIGATOR_VENDOR "Google Inc."
 
-// Force LOG_ERROR() to be enabled in all builds. All other logging and
-// assertions are enabled in debug builds only.
-#define ERROR_DISABLED 0
-
+#define LOG_DISABLED 1
 // This must be defined before we include FastMalloc.h in config.h.
 #define USE_SYSTEM_MALLOC 1
 
@@ -735,7 +732,6 @@
 #define ENABLE_NO_LISTBOX_RENDERING 1
 #define ENABLE_LINK_PREFETCH 1
 #define ENABLE_WEB_TIMING 1
-#define ENABLE_MEDIA_CAPTURE 1
 
 // Android ENABLE guards not present upstream
 #define ENABLE_COMPOSITED_FIXED_ELEMENTS 1 // FIXME: Rename to ENABLE_ANDROID_COMPOSITED_FIXED_ELEMENTS
@@ -754,8 +750,11 @@
 // Passes the webkit-originated changes of a focused textfield to our UI
 // thread
 #define ANDROID_ACCEPT_CHANGES_TO_FOCUSED_TEXTFIELDS
+// Allow us to turn off the blinking caret as desired.
+#define ANDROID_ALLOW_TURNING_OFF_CARET
 #define ANDROID_META_SUPPORT
 #define ANDROID_MULTIPLE_WINDOWS
+#define ANDROID_CSS_RING
 #define ANDROID_CSS_TAP_HIGHLIGHT_COLOR
 #define ANDROID_BLOCK_NETWORK_IMAGE
 // Changes needed to support native plugins (npapi.h). If the change is generic,
@@ -782,6 +781,10 @@
 // track changes to the style that may change what is drawn
 #define ANDROID_STYLE_VERSION
 
+#if !defined(WTF_USE_CHROME_NETWORK_STACK)
+#define WTF_USE_CHROME_NETWORK_STACK 0
+#endif /* !defined(WTF_USE_CHROME_NETWORK_STACK) */
+
 // This is present in JavaScriptCore/config.h, which Android does not use.
 #define WTF_CHANGES 1
 #endif /* PLATFORM(ANDROID) */
diff --git a/Source/JavaScriptCore/wtf/text/StringHash.h b/Source/JavaScriptCore/wtf/text/StringHash.h
index 497184d..c47c1d8 100644
--- a/Source/JavaScriptCore/wtf/text/StringHash.h
+++ b/Source/JavaScriptCore/wtf/text/StringHash.h
@@ -179,6 +179,8 @@
         }
     };
 
+    template<> struct HashTraits<String> : SimpleClassHashTraits<String> { };
+
 }
 
 using WTF::StringHash;
diff --git a/Source/WebCore/Android.derived.jscbindings.mk b/Source/WebCore/Android.derived.jscbindings.mk
new file mode 100644
index 0000000..d859b15
--- /dev/null
+++ b/Source/WebCore/Android.derived.jscbindings.mk
@@ -0,0 +1,752 @@
+
+##
+## Copyright 2009, The Android Open Source Project
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions
+## are met:
+##  * Redistributions of source code must retain the above copyright
+##    notice, this list of conditions and the following disclaimer.
+##  * Redistributions in binary form must reproduce the above copyright
+##    notice, this list of conditions and the following disclaimer in the
+##    documentation and/or other materials provided with the distribution.
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+## PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+##
+
+# lookup tables for old-style JavaScript bindings
+create_hash_table := $(LOCAL_PATH)/../JavaScriptCore/create_hash_table
+
+GEN := $(addprefix $(intermediates)/, \
+			bindings/js/JSDOMWindowBase.lut.h \
+		)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl $(create_hash_table) $< > $@
+$(GEN): $(intermediates)/bindings/js/%.lut.h: $(LOCAL_PATH)/bindings/js/%.cpp $(create_hash_table)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+
+GEN := $(intermediates)/bindings/js/JSHTMLInputElementBaseTable.cpp
+$(GEN): PRIVATE_CUSTOM_TOOL = perl $(create_hash_table) $< > $@
+$(GEN): $(intermediates)/bindings/js/%Table.cpp: $(LOCAL_PATH)/bindings/js/%.cpp $(create_hash_table)
+	$(transform-generated-source)
+$(intermediates)/bindings/js/JSHTMLInputElementBase.o : $(GEN)
+
+# lookup tables for old-style JavaScript bindings
+js_binding_scripts := $(addprefix $(LOCAL_PATH)/,\
+			bindings/scripts/CodeGenerator.pm \
+			bindings/scripts/IDLParser.pm \
+			bindings/scripts/IDLStructure.pm \
+			bindings/scripts/generate-bindings.pl \
+		)
+
+FEATURE_DEFINES := ENABLE_ORIENTATION_EVENTS=1 ENABLE_TOUCH_EVENTS=1 ENABLE_DATABASE=1 ENABLE_OFFLINE_WEB_APPLICATIONS=1 ENABLE_DOM_STORAGE=1 ENABLE_VIDEO=1 ENABLE_GEOLOCATION=1 ENABLE_CONNECTION=1 ENABLE_APPLICATION_INSTALLED=1 ENABLE_XPATH=1 ENABLE_XSLT=1 ENABLE_DEVICE_ORIENTATION=1 ENABLE_FILE_READER=1 ENABLE_BLOB=1 ENABLE_WEB_TIMING=1
+
+ifeq ($(ENABLE_SVG), true)
+    FEATURE_DEFINES += ENABLE_SVG=1
+endif
+
+# CSS
+GEN := \
+    $(intermediates)/css/JSCSSCharsetRule.h \
+    $(intermediates)/css/JSCSSFontFaceRule.h \
+    $(intermediates)/css/JSCSSImportRule.h \
+    $(intermediates)/css/JSCSSMediaRule.h \
+    $(intermediates)/css/JSCSSPageRule.h \
+    $(intermediates)/css/JSCSSPrimitiveValue.h \
+    $(intermediates)/css/JSCSSRule.h \
+    $(intermediates)/css/JSCSSRuleList.h \
+    $(intermediates)/css/JSCSSStyleDeclaration.h \
+    $(intermediates)/css/JSCSSStyleRule.h \
+    $(intermediates)/css/JSCSSStyleSheet.h \
+    $(intermediates)/css/JSCSSValue.h \
+    $(intermediates)/css/JSCSSValueList.h \
+    $(intermediates)/css/JSCounter.h \
+    $(intermediates)/css/JSMediaList.h \
+    $(intermediates)/css/JSMediaQueryList.h \
+    $(intermediates)/css/JSRGBColor.h \
+    $(intermediates)/css/JSRect.h \
+    $(intermediates)/css/JSStyleMedia.h \
+    $(intermediates)/css/JSStyleSheet.h \
+    $(intermediates)/css/JSStyleSheetList.h \
+    $(intermediates)/css/JSWebKitCSSKeyframeRule.h \
+    $(intermediates)/css/JSWebKitCSSKeyframesRule.h \
+    $(intermediates)/css/JSWebKitCSSMatrix.h \
+    $(intermediates)/css/JSWebKitCSSTransformValue.h
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $<
+$(GEN): $(intermediates)/css/JS%.h : $(LOCAL_PATH)/css/%.idl $(js_binding_scripts)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp)
+
+
+# We also need the .cpp files, which are generated as side effects of the
+# above rules.  Specifying this explicitly makes -j2 work.
+$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/css/%.cpp : $(intermediates)/css/%.h
+
+# DOM
+GEN := \
+    $(intermediates)/dom/JSAttr.h \
+    $(intermediates)/dom/JSBeforeLoadEvent.h \
+    $(intermediates)/dom/JSCDATASection.h \
+    $(intermediates)/dom/JSCharacterData.h \
+    $(intermediates)/dom/JSClientRect.h \
+    $(intermediates)/dom/JSClientRectList.h \
+    $(intermediates)/dom/JSClipboard.h \
+    $(intermediates)/dom/JSComment.h \
+    $(intermediates)/dom/JSCustomEvent.h \
+    $(intermediates)/dom/JSCompositionEvent.h \
+    $(intermediates)/dom/JSDOMCoreException.h \
+    $(intermediates)/dom/JSDOMImplementation.h \
+    $(intermediates)/dom/JSDOMStringList.h \
+    $(intermediates)/dom/JSDOMStringMap.h \
+    $(intermediates)/dom/JSDataTransferItems.h \
+    $(intermediates)/dom/JSDeviceMotionEvent.h \
+    $(intermediates)/dom/JSDeviceOrientationEvent.h \
+    $(intermediates)/dom/JSDocument.h \
+    $(intermediates)/dom/JSDocumentFragment.h \
+    $(intermediates)/dom/JSDocumentType.h \
+    $(intermediates)/dom/JSElement.h \
+    $(intermediates)/dom/JSEntity.h \
+    $(intermediates)/dom/JSEntityReference.h \
+    $(intermediates)/dom/JSErrorEvent.h \
+    $(intermediates)/dom/JSEvent.h \
+    $(intermediates)/dom/JSEventException.h \
+    $(intermediates)/dom/JSHashChangeEvent.h \
+    $(intermediates)/dom/JSKeyboardEvent.h \
+    $(intermediates)/dom/JSMessageChannel.h \
+    $(intermediates)/dom/JSMessageEvent.h \
+    $(intermediates)/dom/JSMessagePort.h \
+    $(intermediates)/dom/JSMouseEvent.h \
+    $(intermediates)/dom/JSMutationEvent.h \
+    $(intermediates)/dom/JSNamedNodeMap.h \
+    $(intermediates)/dom/JSNode.h \
+    $(intermediates)/dom/JSNodeFilter.h \
+    $(intermediates)/dom/JSNodeIterator.h \
+    $(intermediates)/dom/JSNodeList.h \
+    $(intermediates)/dom/JSNotation.h \
+    $(intermediates)/dom/JSOverflowEvent.h \
+    $(intermediates)/dom/JSPageTransitionEvent.h \
+    $(intermediates)/dom/JSPopStateEvent.h \
+    $(intermediates)/dom/JSProcessingInstruction.h \
+    $(intermediates)/dom/JSProgressEvent.h \
+    $(intermediates)/dom/JSRange.h \
+    $(intermediates)/dom/JSRangeException.h \
+    $(intermediates)/dom/JSText.h \
+    $(intermediates)/dom/JSTextEvent.h \
+    $(intermediates)/dom/JSTouch.h \
+    $(intermediates)/dom/JSTouchEvent.h \
+    $(intermediates)/dom/JSTouchList.h \
+    $(intermediates)/dom/JSTreeWalker.h \
+    $(intermediates)/dom/JSUIEvent.h \
+    $(intermediates)/dom/JSWebKitAnimationEvent.h \
+    $(intermediates)/dom/JSWebKitTransitionEvent.h \
+    $(intermediates)/dom/JSWheelEvent.h
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $<
+$(GEN): $(intermediates)/dom/JS%.h : $(LOCAL_PATH)/dom/%.idl $(js_binding_scripts)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp)
+
+# We also need the .cpp files, which are generated as side effects of the
+# above rules.  Specifying this explicitly makes -j2 work.
+$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/dom/%.cpp : $(intermediates)/dom/%.h
+
+# Fileapi
+GEN := \
+    $(intermediates)/fileapi/JSBlob.h \
+    $(intermediates)/fileapi/JSDOMFileSystem.h \
+    $(intermediates)/fileapi/JSDOMFileSystemSync.h \
+    $(intermediates)/fileapi/JSDirectoryEntry.h \
+    $(intermediates)/fileapi/JSDirectoryEntrySync.h \
+    $(intermediates)/fileapi/JSDirectoryReader.h \
+    $(intermediates)/fileapi/JSDirectoryReaderSync.h \
+    $(intermediates)/fileapi/JSEntriesCallback.h \
+    $(intermediates)/fileapi/JSEntry.h \
+    $(intermediates)/fileapi/JSEntryArray.h \
+    $(intermediates)/fileapi/JSEntryArraySync.h \
+    $(intermediates)/fileapi/JSEntryCallback.h \
+    $(intermediates)/fileapi/JSEntrySync.h \
+    $(intermediates)/fileapi/JSErrorCallback.h \
+    $(intermediates)/fileapi/JSFile.h \
+    $(intermediates)/fileapi/JSFileCallback.h \
+    $(intermediates)/fileapi/JSFileEntry.h \
+    $(intermediates)/fileapi/JSFileEntrySync.h \
+    $(intermediates)/fileapi/JSFileError.h \
+    $(intermediates)/fileapi/JSFileException.h \
+    $(intermediates)/fileapi/JSFileList.h \
+    $(intermediates)/fileapi/JSFileReader.h \
+    $(intermediates)/fileapi/JSFileReaderSync.h \
+    $(intermediates)/fileapi/JSFileSystemCallback.h \
+    $(intermediates)/fileapi/JSFileWriter.h \
+    $(intermediates)/fileapi/JSFileWriterCallback.h \
+    $(intermediates)/fileapi/JSMetadata.h \
+    $(intermediates)/fileapi/JSMetadataCallback.h \
+    $(intermediates)/fileapi/JSWebKitBlobBuilder.h \
+    $(intermediates)/fileapi/JSWebKitFlags.h
+
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --include fileapi --outputdir $(dir $@) $<
+$(GEN): $(intermediates)/fileapi/JS%.h : $(LOCAL_PATH)/fileapi/%.idl $(js_binding_scripts)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp)
+
+# We also need the .cpp files, which are generated as side effects of the
+# above rules.  Specifying this explicitly makes -j2 work.
+$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/fileapi/%.cpp : $(intermediates)/fileapi/%.h
+
+# HTML
+GEN := \
+    $(intermediates)/html/JSDOMFormData.h \
+    $(intermediates)/html/JSDOMSettableTokenList.h \
+    $(intermediates)/html/JSDOMTokenList.h \
+    $(intermediates)/html/JSDOMURL.h \
+    $(intermediates)/html/JSDataGridColumn.h \
+    $(intermediates)/html/JSDataGridColumnList.h \
+    $(intermediates)/html/JSHTMLAllCollection.h \
+    $(intermediates)/html/JSHTMLAnchorElement.h \
+    $(intermediates)/html/JSHTMLAppletElement.h \
+    $(intermediates)/html/JSHTMLAreaElement.h \
+    $(intermediates)/html/JSHTMLAudioElement.h \
+    $(intermediates)/html/JSHTMLBRElement.h \
+    $(intermediates)/html/JSHTMLBaseElement.h \
+    $(intermediates)/html/JSHTMLBaseFontElement.h \
+    $(intermediates)/html/JSHTMLBlockquoteElement.h \
+    $(intermediates)/html/JSHTMLBodyElement.h \
+    $(intermediates)/html/JSHTMLButtonElement.h \
+    $(intermediates)/html/JSHTMLCanvasElement.h \
+    $(intermediates)/html/JSHTMLCollection.h \
+    $(intermediates)/html/JSHTMLDataGridElement.h \
+    $(intermediates)/html/JSHTMLDataGridCellElement.h \
+    $(intermediates)/html/JSHTMLDataGridColElement.h \
+    $(intermediates)/html/JSHTMLDataGridRowElement.h \
+    $(intermediates)/html/JSHTMLDataListElement.h \
+    $(intermediates)/html/JSHTMLDetailsElement.h \
+    $(intermediates)/html/JSHTMLDListElement.h \
+    $(intermediates)/html/JSHTMLDirectoryElement.h \
+    $(intermediates)/html/JSHTMLDivElement.h \
+    $(intermediates)/html/JSHTMLDocument.h \
+    $(intermediates)/html/JSHTMLElement.h \
+    $(intermediates)/html/JSHTMLEmbedElement.h \
+    $(intermediates)/html/JSHTMLFieldSetElement.h \
+    $(intermediates)/html/JSHTMLFontElement.h \
+    $(intermediates)/html/JSHTMLFormElement.h \
+    $(intermediates)/html/JSHTMLFrameElement.h \
+    $(intermediates)/html/JSHTMLFrameSetElement.h \
+    $(intermediates)/html/JSHTMLHRElement.h \
+    $(intermediates)/html/JSHTMLHeadElement.h \
+    $(intermediates)/html/JSHTMLHeadingElement.h \
+    $(intermediates)/html/JSHTMLHtmlElement.h \
+    $(intermediates)/html/JSHTMLIFrameElement.h \
+    $(intermediates)/html/JSHTMLImageElement.h \
+    $(intermediates)/html/JSHTMLInputElement.h \
+    $(intermediates)/html/JSHTMLIsIndexElement.h \
+    $(intermediates)/html/JSHTMLKeygenElement.h \
+    $(intermediates)/html/JSHTMLLIElement.h \
+    $(intermediates)/html/JSHTMLLabelElement.h \
+    $(intermediates)/html/JSHTMLLegendElement.h \
+    $(intermediates)/html/JSHTMLLinkElement.h \
+    $(intermediates)/html/JSHTMLMapElement.h \
+    $(intermediates)/html/JSHTMLMarqueeElement.h \
+    $(intermediates)/html/JSHTMLMediaElement.h \
+    $(intermediates)/html/JSHTMLMenuElement.h \
+    $(intermediates)/html/JSHTMLMetaElement.h \
+    $(intermediates)/html/JSHTMLMeterElement.h \
+    $(intermediates)/html/JSHTMLModElement.h \
+    $(intermediates)/html/JSHTMLOListElement.h \
+    $(intermediates)/html/JSHTMLObjectElement.h \
+    $(intermediates)/html/JSHTMLOptGroupElement.h \
+    $(intermediates)/html/JSHTMLOptionElement.h \
+    $(intermediates)/html/JSHTMLOptionsCollection.h \
+    $(intermediates)/html/JSHTMLOutputElement.h \
+    $(intermediates)/html/JSHTMLParagraphElement.h \
+    $(intermediates)/html/JSHTMLParamElement.h \
+    $(intermediates)/html/JSHTMLPreElement.h \
+    $(intermediates)/html/JSHTMLProgressElement.h \
+    $(intermediates)/html/JSHTMLQuoteElement.h \
+    $(intermediates)/html/JSHTMLScriptElement.h \
+    $(intermediates)/html/JSHTMLSelectElement.h \
+    $(intermediates)/html/JSHTMLSourceElement.h \
+    $(intermediates)/html/JSHTMLStyleElement.h \
+    $(intermediates)/html/JSHTMLTableCaptionElement.h \
+    $(intermediates)/html/JSHTMLTableCellElement.h \
+    $(intermediates)/html/JSHTMLTableColElement.h \
+    $(intermediates)/html/JSHTMLTableElement.h \
+    $(intermediates)/html/JSHTMLTableRowElement.h \
+    $(intermediates)/html/JSHTMLTableSectionElement.h \
+    $(intermediates)/html/JSHTMLTextAreaElement.h \
+    $(intermediates)/html/JSHTMLTitleElement.h \
+    $(intermediates)/html/JSHTMLUListElement.h \
+    $(intermediates)/html/JSHTMLVideoElement.h \
+    $(intermediates)/html/JSImageData.h \
+    $(intermediates)/html/JSMediaError.h \
+    $(intermediates)/html/JSTextMetrics.h \
+    $(intermediates)/html/JSTimeRanges.h \
+    $(intermediates)/html/JSValidityState.h \
+    $(intermediates)/html/JSVoidCallback.h
+
+
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $<
+$(GEN): $(intermediates)/html/JS%.h : $(LOCAL_PATH)/html/%.idl $(js_binding_scripts)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp)
+
+# We also need the .cpp files, which are generated as side effects of the
+# above rules.  Specifying this explicitly makes -j2 work.
+$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/html/%.cpp : $(intermediates)/html/%.h
+
+# Canvas
+GEN := \
+    $(intermediates)/html/canvas/JSArrayBuffer.h \
+    $(intermediates)/html/canvas/JSArrayBufferView.h \
+    $(intermediates)/html/canvas/JSCanvasGradient.h \
+    $(intermediates)/html/canvas/JSCanvasPattern.h \
+    $(intermediates)/html/canvas/JSCanvasRenderingContext.h \
+    $(intermediates)/html/canvas/JSCanvasRenderingContext2D.h \
+    $(intermediates)/html/canvas/JSDataView.h \
+    $(intermediates)/html/canvas/JSFloat32Array.h \
+    $(intermediates)/html/canvas/JSInt8Array.h \
+    $(intermediates)/html/canvas/JSInt16Array.h \
+    $(intermediates)/html/canvas/JSInt32Array.h \
+    $(intermediates)/html/canvas/JSOESTextureFloat.h \
+    $(intermediates)/html/canvas/JSOESVertexArrayObject.h \
+    $(intermediates)/html/canvas/JSUint8Array.h \
+    $(intermediates)/html/canvas/JSUint16Array.h \
+    $(intermediates)/html/canvas/JSUint32Array.h \
+    $(intermediates)/html/canvas/JSWebGLActiveInfo.h \
+    $(intermediates)/html/canvas/JSWebGLBuffer.h \
+    $(intermediates)/html/canvas/JSWebGLFramebuffer.h \
+    $(intermediates)/html/canvas/JSWebGLProgram.h \
+    $(intermediates)/html/canvas/JSWebGLRenderbuffer.h \
+    $(intermediates)/html/canvas/JSWebGLRenderingContext.h \
+    $(intermediates)/html/canvas/JSWebGLShader.h \
+    $(intermediates)/html/canvas/JSWebGLTexture.h \
+    $(intermediates)/html/canvas/JSWebGLUniformLocation.h \
+    $(intermediates)/html/canvas/JSWebGLVertexArrayObjectOES.h
+
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $<
+$(GEN): $(intermediates)/html/canvas/JS%.h : $(LOCAL_PATH)/html/canvas/%.idl $(js_binding_scripts)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp)
+
+# We also need the .cpp files, which are generated as side effects of the
+# above rules.  Specifying this explicitly makes -j2 work.
+$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/html/canvas/%.cpp : $(intermediates)/html/canvas/%.h
+
+# Appcache
+GEN := \
+    $(intermediates)/loader/appcache/JSDOMApplicationCache.h
+
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $<
+$(GEN): $(intermediates)/loader/appcache/JS%.h : $(LOCAL_PATH)/loader/appcache/%.idl $(js_binding_scripts)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp)
+
+# We also need the .cpp files, which are generated as side effects of the
+# above rules.  Specifying this explicitly makes -j2 work.
+$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/loader/appcache/%.cpp : $(intermediates)/loader/appcache/%.h
+
+# page
+GEN := \
+    $(intermediates)/page/JSBarInfo.h \
+    $(intermediates)/page/JSConnection.h \
+    $(intermediates)/page/JSConsole.h \
+    $(intermediates)/page/JSCoordinates.h \
+    $(intermediates)/page/JSCrypto.h \
+    $(intermediates)/page/JSDOMSelection.h \
+    $(intermediates)/page/JSDOMWindow.h \
+    $(intermediates)/page/JSEventSource.h \
+    $(intermediates)/page/JSGeolocation.h \
+    $(intermediates)/page/JSGeoposition.h \
+    $(intermediates)/page/JSHistory.h \
+    $(intermediates)/page/JSLocation.h \
+    $(intermediates)/page/JSMemoryInfo.h \
+    $(intermediates)/page/JSNavigator.h \
+    $(intermediates)/page/JSNavigatorUserMediaError.h \
+    $(intermediates)/page/JSNavigatorUserMediaErrorCallback.h \
+    $(intermediates)/page/JSNavigatorUserMediaSuccessCallback.h \
+    $(intermediates)/page/JSPerformance.h \
+    $(intermediates)/page/JSPerformanceNavigation.h \
+    $(intermediates)/page/JSPerformanceTiming.h \
+    $(intermediates)/page/JSPositionError.h \
+    $(intermediates)/page/JSScreen.h \
+    $(intermediates)/page/JSSpeechInputEvent.h \
+    $(intermediates)/page/JSWebKitAnimation.h \
+    $(intermediates)/page/JSWebKitAnimationList.h \
+    $(intermediates)/page/JSWebKitPoint.h \
+    $(intermediates)/page/JSWorkerNavigator.h
+
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $<
+$(GEN): $(intermediates)/page/JS%.h : $(LOCAL_PATH)/page/%.idl $(js_binding_scripts)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp)
+
+# We also need the .cpp files, which are generated as side effects of the
+# above rules.  Specifying this explicitly makes -j2 work.
+$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/page/%.cpp : $(intermediates)/page/%.h
+
+GEN := \
+    $(intermediates)/plugins/JSDOMMimeType.h \
+    $(intermediates)/plugins/JSDOMMimeTypeArray.h \
+    $(intermediates)/plugins/JSDOMPlugin.h \
+    $(intermediates)/plugins/JSDOMPluginArray.h
+
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $<
+$(GEN): $(intermediates)/plugins/JS%.h : $(LOCAL_PATH)/plugins/%.idl $(js_binding_scripts)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp)
+
+# We also need the .cpp files, which are generated as side effects of the
+# above rules.  Specifying this explicitly makes -j2 work.
+$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/plugins/%.cpp : $(intermediates)/plugins/%.h
+
+# Database
+GEN := \
+    $(intermediates)/storage/JSDatabase.h \
+    $(intermediates)/storage/JSDatabaseCallback.h \
+    $(intermediates)/storage/JSDatabaseSync.h \
+    $(intermediates)/storage/JSSQLError.h \
+    $(intermediates)/storage/JSSQLException.h \
+    $(intermediates)/storage/JSSQLResultSet.h \
+    $(intermediates)/storage/JSSQLResultSetRowList.h \
+    $(intermediates)/storage/JSSQLStatementCallback.h \
+    $(intermediates)/storage/JSSQLStatementErrorCallback.h \
+    $(intermediates)/storage/JSSQLTransaction.h \
+    $(intermediates)/storage/JSSQLTransactionCallback.h \
+    $(intermediates)/storage/JSSQLTransactionSync.h \
+    $(intermediates)/storage/JSSQLTransactionSyncCallback.h \
+    $(intermediates)/storage/JSSQLTransactionErrorCallback.h
+
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --include storage --outputdir $(dir $@) $<
+$(GEN): $(intermediates)/storage/JS%.h : $(LOCAL_PATH)/storage/%.idl $(js_binding_scripts)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp)
+
+# We also need the .cpp files, which are generated as side effects of the
+# above rules.  Specifying this explicitly makes -j2 work.
+$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/storage/%.cpp : $(intermediates)/storage/%.h
+
+# DOM Storage
+GEN := \
+    $(intermediates)/storage/JSStorage.h \
+    $(intermediates)/storage/JSStorageEvent.h
+
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $<
+$(GEN): $(intermediates)/storage/JS%.h : $(LOCAL_PATH)/storage/%.idl $(js_binding_scripts)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp)
+
+# We also need the .cpp files, which are generated as side effects of the
+# above rules.  Specifying this explicitly makes -j2 work.
+$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/storage/%.cpp : $(intermediates)/storage/%.h
+
+# Indexed Database
+GEN := \
+    $(intermediates)/storage/JSIDBAny.h \
+    $(intermediates)/storage/JSIDBCursor.h \
+    $(intermediates)/storage/JSIDBCursorWithValue.h \
+    $(intermediates)/storage/JSIDBDatabaseError.h \
+    $(intermediates)/storage/JSIDBDatabaseException.h \
+    $(intermediates)/storage/JSIDBDatabase.h \
+    $(intermediates)/storage/JSIDBFactory.h \
+    $(intermediates)/storage/JSIDBIndex.h \
+    $(intermediates)/storage/JSIDBKey.h \
+    $(intermediates)/storage/JSIDBKeyRange.h \
+    $(intermediates)/storage/JSIDBObjectStore.h \
+    $(intermediates)/storage/JSIDBRequest.h \
+    $(intermediates)/storage/JSIDBTransaction.h \
+    $(intermediates)/storage/JSIDBVersionChangeEvent.h \
+    $(intermediates)/storage/JSIDBVersionChangeRequest.h
+
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --include storage --outputdir $(dir $@) $<
+$(GEN): $(intermediates)/storage/JS%.h : $(LOCAL_PATH)/storage/%.idl $(js_binding_scripts)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp)
+
+# We also need the .cpp files, which are generated as side effects of the
+# above rules.  Specifying this explicitly makes -j2 work.
+$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/storage/%.cpp : $(intermediates)/storage/%.h
+
+# SVG
+ifeq ($(ENABLE_SVG), true)
+GEN := \
+    $(intermediates)/svg/JSSVGAElement.h \
+    $(intermediates)/svg/JSSVGAltGlyphElement.h \
+    $(intermediates)/svg/JSSVGAngle.h \
+    $(intermediates)/svg/JSSVGAnimateColorElement.h \
+    $(intermediates)/svg/JSSVGAnimateElement.h \
+    $(intermediates)/svg/JSSVGAnimateTransformElement.h \
+    $(intermediates)/svg/JSSVGAnimatedAngle.h \
+    $(intermediates)/svg/JSSVGAnimatedBoolean.h \
+    $(intermediates)/svg/JSSVGAnimatedEnumeration.h \
+    $(intermediates)/svg/JSSVGAnimatedInteger.h \
+    $(intermediates)/svg/JSSVGAnimatedLength.h \
+    $(intermediates)/svg/JSSVGAnimatedLengthList.h \
+    $(intermediates)/svg/JSSVGAnimatedNumber.h \
+    $(intermediates)/svg/JSSVGAnimatedNumberList.h \
+    $(intermediates)/svg/JSSVGAnimatedPreserveAspectRatio.h \
+    $(intermediates)/svg/JSSVGAnimatedRect.h \
+    $(intermediates)/svg/JSSVGAnimatedString.h \
+    $(intermediates)/svg/JSSVGAnimatedTransformList.h \
+    $(intermediates)/svg/JSSVGAnimationElement.h \
+    $(intermediates)/svg/JSSVGCircleElement.h \
+    $(intermediates)/svg/JSSVGClipPathElement.h \
+    $(intermediates)/svg/JSSVGColor.h \
+    $(intermediates)/svg/JSSVGComponentTransferFunctionElement.h \
+    $(intermediates)/svg/JSSVGCursorElement.h \
+    $(intermediates)/svg/JSSVGDefsElement.h \
+    $(intermediates)/svg/JSSVGDescElement.h \
+    $(intermediates)/svg/JSSVGDocument.h \
+    $(intermediates)/svg/JSSVGElement.h \
+    $(intermediates)/svg/JSSVGElementInstance.h \
+    $(intermediates)/svg/JSSVGElementInstanceList.h \
+    $(intermediates)/svg/JSSVGEllipseElement.h \
+    $(intermediates)/svg/JSSVGException.h \
+    $(intermediates)/svg/JSSVGFEBlendElement.h \
+    $(intermediates)/svg/JSSVGFEColorMatrixElement.h \
+    $(intermediates)/svg/JSSVGFEComponentTransferElement.h \
+    $(intermediates)/svg/JSSVGFECompositeElement.h \
+    $(intermediates)/svg/JSSVGFEConvolveMatrixElement.h \
+    $(intermediates)/svg/JSSVGFEDiffuseLightingElement.h \
+    $(intermediates)/svg/JSSVGFEDisplacementMapElement.h \
+    $(intermediates)/svg/JSSVGFEDistantLightElement.h \
+    $(intermediates)/svg/JSSVGFEFloodElement.h \
+    $(intermediates)/svg/JSSVGFEFuncAElement.h \
+    $(intermediates)/svg/JSSVGFEFuncBElement.h \
+    $(intermediates)/svg/JSSVGFEFuncGElement.h \
+    $(intermediates)/svg/JSSVGFEFuncRElement.h \
+    $(intermediates)/svg/JSSVGFEGaussianBlurElement.h \
+    $(intermediates)/svg/JSSVGFEImageElement.h \
+    $(intermediates)/svg/JSSVGFEMergeElement.h \
+    $(intermediates)/svg/JSSVGFEMergeNodeElement.h \
+    $(intermediates)/svg/JSSVGFEOffsetElement.h \
+    $(intermediates)/svg/JSSVGFEPointLightElement.h \
+    $(intermediates)/svg/JSSVGFESpecularLightingElement.h \
+    $(intermediates)/svg/JSSVGFESpotLightElement.h \
+    $(intermediates)/svg/JSSVGFETileElement.h \
+    $(intermediates)/svg/JSSVGFETurbulenceElement.h \
+    $(intermediates)/svg/JSSVGFilterElement.h \
+    $(intermediates)/svg/JSSVGFontElement.h \
+    $(intermediates)/svg/JSSVGFontFaceElement.h \
+    $(intermediates)/svg/JSSVGFontFaceFormatElement.h \
+    $(intermediates)/svg/JSSVGFontFaceNameElement.h \
+    $(intermediates)/svg/JSSVGFontFaceSrcElement.h \
+    $(intermediates)/svg/JSSVGFontFaceUriElement.h \
+    $(intermediates)/svg/JSSVGForeignObjectElement.h \
+    $(intermediates)/svg/JSSVGGElement.h \
+    $(intermediates)/svg/JSSVGGlyphElement.h \
+    $(intermediates)/svg/JSSVGGradientElement.h \
+    $(intermediates)/svg/JSSVGHKernElement.h \
+    $(intermediates)/svg/JSSVGImageElement.h \
+    $(intermediates)/svg/JSSVGLength.h \
+    $(intermediates)/svg/JSSVGLengthList.h \
+    $(intermediates)/svg/JSSVGLineElement.h \
+    $(intermediates)/svg/JSSVGLinearGradientElement.h \
+    $(intermediates)/svg/JSSVGMarkerElement.h \
+    $(intermediates)/svg/JSSVGMaskElement.h \
+    $(intermediates)/svg/JSSVGMatrix.h \
+    $(intermediates)/svg/JSSVGMetadataElement.h \
+    $(intermediates)/svg/JSSVGMissingGlyphElement.h \
+    $(intermediates)/svg/JSSVGNumber.h \
+    $(intermediates)/svg/JSSVGNumberList.h \
+    $(intermediates)/svg/JSSVGPaint.h \
+    $(intermediates)/svg/JSSVGPathElement.h \
+    $(intermediates)/svg/JSSVGPathSeg.h \
+    $(intermediates)/svg/JSSVGPathSegArcAbs.h \
+    $(intermediates)/svg/JSSVGPathSegArcRel.h \
+    $(intermediates)/svg/JSSVGPathSegClosePath.h \
+    $(intermediates)/svg/JSSVGPathSegCurvetoCubicAbs.h \
+    $(intermediates)/svg/JSSVGPathSegCurvetoCubicRel.h \
+    $(intermediates)/svg/JSSVGPathSegCurvetoCubicSmoothAbs.h \
+    $(intermediates)/svg/JSSVGPathSegCurvetoCubicSmoothRel.h \
+    $(intermediates)/svg/JSSVGPathSegCurvetoQuadraticAbs.h \
+    $(intermediates)/svg/JSSVGPathSegCurvetoQuadraticRel.h \
+    $(intermediates)/svg/JSSVGPathSegCurvetoQuadraticSmoothAbs.h \
+    $(intermediates)/svg/JSSVGPathSegCurvetoQuadraticSmoothRel.h \
+    $(intermediates)/svg/JSSVGPathSegLinetoAbs.h \
+    $(intermediates)/svg/JSSVGPathSegLinetoHorizontalAbs.h \
+    $(intermediates)/svg/JSSVGPathSegLinetoHorizontalRel.h \
+    $(intermediates)/svg/JSSVGPathSegLinetoRel.h \
+    $(intermediates)/svg/JSSVGPathSegLinetoVerticalAbs.h \
+    $(intermediates)/svg/JSSVGPathSegLinetoVerticalRel.h \
+    $(intermediates)/svg/JSSVGPathSegList.h \
+    $(intermediates)/svg/JSSVGPathSegMovetoAbs.h \
+    $(intermediates)/svg/JSSVGPathSegMovetoRel.h \
+    $(intermediates)/svg/JSSVGPatternElement.h \
+    $(intermediates)/svg/JSSVGPoint.h \
+    $(intermediates)/svg/JSSVGPointList.h \
+    $(intermediates)/svg/JSSVGPolygonElement.h \
+    $(intermediates)/svg/JSSVGPolylineElement.h \
+    $(intermediates)/svg/JSSVGPreserveAspectRatio.h \
+    $(intermediates)/svg/JSSVGRadialGradientElement.h \
+    $(intermediates)/svg/JSSVGRect.h \
+    $(intermediates)/svg/JSSVGRectElement.h \
+    $(intermediates)/svg/JSSVGRenderingIntent.h \
+    $(intermediates)/svg/JSSVGSVGElement.h \
+    $(intermediates)/svg/JSSVGScriptElement.h \
+    $(intermediates)/svg/JSSVGSetElement.h \
+    $(intermediates)/svg/JSSVGStopElement.h \
+    $(intermediates)/svg/JSSVGStringList.h \
+    $(intermediates)/svg/JSSVGStyleElement.h \
+    $(intermediates)/svg/JSSVGSwitchElement.h \
+    $(intermediates)/svg/JSSVGSymbolElement.h \
+    $(intermediates)/svg/JSSVGTRefElement.h \
+    $(intermediates)/svg/JSSVGTSpanElement.h \
+    $(intermediates)/svg/JSSVGTextContentElement.h \
+    $(intermediates)/svg/JSSVGTextElement.h \
+    $(intermediates)/svg/JSSVGTextPathElement.h \
+    $(intermediates)/svg/JSSVGTextPositioningElement.h \
+    $(intermediates)/svg/JSSVGTitleElement.h \
+    $(intermediates)/svg/JSSVGTransform.h \
+    $(intermediates)/svg/JSSVGTransformList.h \
+    $(intermediates)/svg/JSSVGUnitTypes.h \
+    $(intermediates)/svg/JSSVGUseElement.h \
+    $(intermediates)/svg/JSSVGViewElement.h \
+    $(intermediates)/svg/JSSVGVKernElement.h \
+    $(intermediates)/svg/JSSVGZoomEvent.h
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include external/webkit/Source/WebCore/dom --include external/webkit/Source/WebCore/html --include external/webkit/Source/WebCore/svg --outputdir $(dir $@) $<
+$(GEN): $(intermediates)/svg/JS%.h : $(LOCAL_PATH)/svg/%.idl $(js_binding_scripts)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp)
+
+# We also need the .cpp files, which are generated as side effects of the
+# above rules.  Specifying this explicitly makes -j2 work.
+$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/svg/%.cpp : $(intermediates)/svg/%.h
+endif
+
+# Workers
+GEN := \
+    $(intermediates)/workers/JSAbstractWorker.h \
+    $(intermediates)/workers/JSDedicatedWorkerContext.h \
+    $(intermediates)/workers/JSSharedWorker.h \
+    $(intermediates)/workers/JSSharedWorkerContext.h \
+    $(intermediates)/workers/JSWorker.h \
+    $(intermediates)/workers/JSWorkerContext.h \
+    $(intermediates)/workers/JSWorkerLocation.h
+
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $<
+$(GEN): $(intermediates)/workers/JS%.h : $(LOCAL_PATH)/workers/%.idl $(js_binding_scripts)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp)
+
+# We also need the .cpp files, which are generated as side effects of the
+# above rules.  Specifying this explicitly makes -j2 work.
+$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/workers/%.cpp : $(intermediates)/workers/%.h
+
+# XML
+GEN := \
+    $(intermediates)/xml/JSDOMParser.h \
+    $(intermediates)/xml/JSXMLHttpRequest.h \
+    $(intermediates)/xml/JSXMLHttpRequestException.h \
+    $(intermediates)/xml/JSXMLHttpRequestProgressEvent.h \
+    $(intermediates)/xml/JSXMLHttpRequestUpload.h \
+    $(intermediates)/xml/JSXMLSerializer.h \
+    $(intermediates)/xml/JSXPathException.h \
+    $(intermediates)/xml/JSXPathExpression.h \
+    $(intermediates)/xml/JSXPathEvaluator.h \
+    $(intermediates)/xml/JSXPathNSResolver.h \
+    $(intermediates)/xml/JSXPathResult.h \
+    $(intermediates)/xml/JSXSLTProcessor.h
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $<
+$(GEN): $(intermediates)/xml/JS%.h : $(LOCAL_PATH)/xml/%.idl $(js_binding_scripts)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp)
+
+# We also need the .cpp files, which are generated as side effects of the
+# above rules.  Specifying this explicitly makes -j2 work.
+$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/xml/%.cpp : $(intermediates)/xml/%.h
+#end
+
+# Inspector
+# These headers are required even when Inspector is disabled.
+# Note that Inspector.idl should not be processed using the JS generator.
+GEN := \
+    $(intermediates)/inspector/JSScriptProfile.h
+
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $<
+$(GEN): $(intermediates)/inspector/JS%.h : $(LOCAL_PATH)/inspector/%.idl $(js_binding_scripts)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp)
+
+# We also need the .cpp files, which are generated as side effects of the
+# above rules.  Specifying this explicitly makes -j2 work.
+$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/inspector/%.cpp : $(intermediates)/inspector/%.h
+
+# WebAudio
+# These headers are required even when WebAudio is disabled
+GEN := \
+    $(intermediates)/webaudio/JSAudioContext.h \
+    $(intermediates)/webaudio/JSAudioPannerNode.h
+
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I$(PRIVATE_PATH)/bindings/scripts $(PRIVATE_PATH)/bindings/scripts/generate-bindings.pl --defines "$(FEATURE_DEFINES) LANGUAGE_JAVASCRIPT" --generator JS --include dom --include html --outputdir $(dir $@) $<
+$(GEN): $(intermediates)/webaudio/JS%.h : $(LOCAL_PATH)/webaudio/%.idl $(js_binding_scripts)
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN) $(GEN:%.h=%.cpp)
+
+# We also need the .cpp files, which are generated as side effects of the
+# above rules.  Specifying this explicitly makes -j2 work.
+$(patsubst %.h,%.cpp,$(GEN)): $(intermediates)/webaudio/%.cpp : $(intermediates)/webaudio/%.h
+
+# HTML tag and attribute names
+
+GEN:= $(intermediates)/HTMLNames.cpp $(intermediates)/HTMLNames.h $(intermediates)/HTMLElementFactory.cpp $(intermediates)/HTMLElementFactory.h $(intermediates)/JSHTMLElementWrapperFactory.cpp $(intermediates)/JSHTMLElementWrapperFactory.h
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I $(PRIVATE_PATH)/bindings/scripts $< --tags $(PRIVATE_PATH)/html/HTMLTagNames.in --attrs $(PRIVATE_PATH)/html/HTMLAttributeNames.in --extraDefines "$(FEATURE_DEFINES)" --factory --wrapperFactory --output $(dir $@)
+$(GEN): $(LOCAL_PATH)/dom/make_names.pl $(LOCAL_PATH)/html/HTMLTagNames.in $(LOCAL_PATH)/html/HTMLAttributeNames.in
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+# SVG tag and attribute names
+
+# Note that if SVG is not used, we still need the headers and SVGNames.cpp as
+# the HTML5 parser still requires these. The factory .cpp files are also
+# generated in this case, but since these are not needed, they are excluded
+# from GEN so that they don't get compiled.
+ifeq ($(ENABLE_SVG), true)
+GEN:= $(intermediates)/SVGNames.cpp $(intermediates)/SVGNames.h $(intermediates)/SVGElementFactory.cpp $(intermediates)/SVGElementFactory.h $(intermediates)/JSSVGElementWrapperFactory.cpp $(intermediates)/JSSVGElementWrapperFactory.h
+else
+GEN:= $(intermediates)/SVGNames.h $(intermediates)/SVGNames.cpp $(intermediates)/SVGElementFactory.h $(intermediates)/JSSVGElementWrapperFactory.h
+endif
+SVG_FLAGS:=ENABLE_SVG_ANIMATION=1 ENABLE_SVG_AS_IMAGE=1 ENABLE_SVG_FILTERS=1 ENABLE_SVG_FONTS=1 ENABLE_SVG_FOREIGN_OBJECT=1 ENABLE_SVG_USE=1
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I $(PRIVATE_PATH)/bindings/scripts $< --tags $(PRIVATE_PATH)/svg/svgtags.in --attrs $(PRIVATE_PATH)/svg/svgattrs.in --extraDefines "$(SVG_FLAGS)" --factory --wrapperFactory --output $(dir $@)
+$(GEN): $(LOCAL_PATH)/dom/make_names.pl $(LOCAL_PATH)/svg/svgtags.in $(LOCAL_PATH)/svg/svgattrs.in
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+# MathML tag and attribute names
+
+# Note that MathML is never used but we still need the headers and
+# MathMLames.cpp as the HTML5 parser still requires these. The factory
+# .cpp files are also generated in this case, but since these are not
+# needed, they are excluded from GEN so that they don't get compiled.
+GEN:= $(intermediates)/MathMLNames.h $(intermediates)/MathMLNames.cpp $(intermediates)/MathMLElementFactory.h $(intermediates)/JSMathMLElementWrapperFactory.h
+$(GEN): PRIVATE_PATH := $(LOCAL_PATH)
+$(GEN): PRIVATE_CUSTOM_TOOL = perl -I $(PRIVATE_PATH)/bindings/scripts $< --tags $(PRIVATE_PATH)/mathml/mathtags.in --attrs $(PRIVATE_PATH)/mathml/mathattrs.in --factory --wrapperFactory --output $(dir $@)
+$(GEN): $(LOCAL_PATH)/dom/make_names.pl $(LOCAL_PATH)/mathml/mathtags.in $(LOCAL_PATH)/mathml/mathattrs.in
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
diff --git a/Source/WebCore/Android.derived.v8bindings.mk b/Source/WebCore/Android.derived.v8bindings.mk
index 509d21e..992cc40 100644
--- a/Source/WebCore/Android.derived.v8bindings.mk
+++ b/Source/WebCore/Android.derived.v8bindings.mk
@@ -31,7 +31,7 @@
 	$(LOCAL_PATH)/bindings/scripts/generate-bindings.pl
 
 # Add ACCELERATED_COMPOSITING=1 and ENABLE_3D_RENDERING=1 for layers support
-FEATURE_DEFINES := ENABLE_ORIENTATION_EVENTS=1 ENABLE_TOUCH_EVENTS=1 ENABLE_DATABASE=1 ENABLE_OFFLINE_WEB_APPLICATIONS=1 ENABLE_DOM_STORAGE=1 ENABLE_VIDEO=1 ENABLE_GEOLOCATION=1 ENABLE_CONNECTION=1 ENABLE_APPLICATION_INSTALLED=1 ENABLE_XPATH=1 ENABLE_XSLT=1 ENABLE_DEVICE_ORIENTATION=1 ENABLE_FILE_READER=1 ENABLE_BLOB=1 ENABLE_WEB_TIMING=1 ENABLE_MEDIA_CAPTURE=1
+FEATURE_DEFINES := ENABLE_ORIENTATION_EVENTS=1 ENABLE_TOUCH_EVENTS=1 ENABLE_DATABASE=1 ENABLE_OFFLINE_WEB_APPLICATIONS=1 ENABLE_DOM_STORAGE=1 ENABLE_VIDEO=1 ENABLE_GEOLOCATION=1 ENABLE_CONNECTION=1 ENABLE_APPLICATION_INSTALLED=1 ENABLE_XPATH=1 ENABLE_XSLT=1 ENABLE_DEVICE_ORIENTATION=1 ENABLE_FILE_READER=1 ENABLE_BLOB=1 ENABLE_WEB_TIMING=1
 # The defines above should be identical to those for JSC.
 FEATURE_DEFINES += V8_BINDING
 
@@ -301,7 +301,6 @@
     $(intermediates)/bindings/V8CanvasRenderingContext2D.h \
     $(intermediates)/bindings/V8DataView.h \
     $(intermediates)/bindings/V8Float32Array.h \
-    $(intermediates)/bindings/V8Float64Array.h \
     $(intermediates)/bindings/V8Int8Array.h \
     $(intermediates)/bindings/V8Int16Array.h \
     $(intermediates)/bindings/V8Int32Array.h \
diff --git a/Source/WebCore/Android.jscbindings.mk b/Source/WebCore/Android.jscbindings.mk
new file mode 100644
index 0000000..bdd6d92
--- /dev/null
+++ b/Source/WebCore/Android.jscbindings.mk
@@ -0,0 +1,240 @@
+##
+## Copyright 2009, The Android Open Source Project
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions
+## are met:
+##  * Redistributions of source code must retain the above copyright
+##    notice, this list of conditions and the following disclaimer.
+##  * Redistributions in binary form must reproduce the above copyright
+##    notice, this list of conditions and the following disclaimer in the
+##    documentation and/or other materials provided with the distribution.
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+## PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+##
+
+BINDING_C_INCLUDES := \
+	$(LOCAL_PATH)/bindings/js \
+	$(LOCAL_PATH)/bindings/js/specialization \
+	$(LOCAL_PATH)/bridge \
+	$(LOCAL_PATH)/bridge/c \
+	$(LOCAL_PATH)/bridge/jni \
+	$(LOCAL_PATH)/bridge/jni/jsc \
+	$(LOCAL_PATH)/bridge/jsc \
+	\
+	$(JAVASCRIPTCORE_PATH)/API \
+	$(JAVASCRIPTCORE_PATH)/assembler \
+	$(JAVASCRIPTCORE_PATH)/bytecode \
+	$(JAVASCRIPTCORE_PATH)/bytecompiler \
+	$(JAVASCRIPTCORE_PATH)/debugger \
+	$(JAVASCRIPTCORE_PATH)/parser \
+	$(JAVASCRIPTCORE_PATH)/jit \
+	$(JAVASCRIPTCORE_PATH)/interpreter \
+	$(JAVASCRIPTCORE_PATH)/profiler \
+	$(JAVASCRIPTCORE_PATH)/runtime \
+	$(JAVASCRIPTCORE_PATH)/yarr \
+	$(JAVASCRIPTCORE_PATH)/ForwardingHeaders \
+	\
+	$(WEBCORE_INTERMEDIATES_PATH)/bindings/js \
+	$(WEBCORE_INTERMEDIATES_PATH)/dom \
+	$(WEBCORE_INTERMEDIATES_PATH)/fileapi \
+	$(WEBCORE_INTERMEDIATES_PATH)/html/canvas \
+	$(WEBCORE_INTERMEDIATES_PATH)/inspector \
+	$(WEBCORE_INTERMEDIATES_PATH)/loader/appcache \
+	$(WEBCORE_INTERMEDIATES_PATH)/page \
+	$(WEBCORE_INTERMEDIATES_PATH)/plugins \
+	$(WEBCORE_INTERMEDIATES_PATH)/storage \
+	$(WEBCORE_INTERMEDIATES_PATH)/svg \
+	$(WEBCORE_INTERMEDIATES_PATH)/webaudio \
+	$(WEBCORE_INTERMEDIATES_PATH)/workers \
+	$(WEBCORE_INTERMEDIATES_PATH)/xml
+
+LOCAL_SRC_FILES += \
+	bindings/js/CallbackFunction.cpp \
+	bindings/js/DOMObjectHashTableMap.cpp \
+	bindings/js/DOMWrapperWorld.cpp \
+	bindings/js/GCController.cpp \
+	bindings/js/IDBBindingUtilities.cpp \
+	bindings/js/JSArrayBufferCustom.cpp \
+	bindings/js/JSAttrCustom.cpp \
+	bindings/js/JSAudioBufferSourceNodeCustom.cpp \
+	bindings/js/JSAudioConstructor.cpp \
+	bindings/js/JSCDATASectionCustom.cpp \
+	bindings/js/JSCSSFontFaceRuleCustom.cpp \
+	bindings/js/JSCSSImportRuleCustom.cpp \
+	bindings/js/JSCSSMediaRuleCustom.cpp \
+	bindings/js/JSCSSPageRuleCustom.cpp \
+	bindings/js/JSCSSRuleCustom.cpp \
+	bindings/js/JSCSSRuleListCustom.cpp \
+	bindings/js/JSCSSStyleDeclarationCustom.cpp \
+	bindings/js/JSCSSStyleRuleCustom.cpp \
+	bindings/js/JSCSSValueCustom.cpp \
+	bindings/js/JSCallbackData.cpp \
+	bindings/js/JSCanvasRenderingContext2DCustom.cpp \
+	bindings/js/JSCanvasRenderingContextCustom.cpp \
+	bindings/js/JSClipboardCustom.cpp \
+	bindings/js/JSConsoleCustom.cpp \
+	bindings/js/JSConvolverNodeCustom.cpp \
+	bindings/js/JSCoordinatesCustom.cpp \
+	bindings/js/JSCustomApplicationInstalledCallback.cpp \
+	bindings/js/JSCustomPositionCallback.cpp \
+	bindings/js/JSCustomPositionErrorCallback.cpp \
+	bindings/js/JSCustomSQLStatementErrorCallback.cpp \
+	bindings/js/JSCustomVoidCallback.cpp \
+	bindings/js/JSDOMApplicationCacheCustom.cpp \
+	bindings/js/JSDOMBinding.cpp \
+	bindings/js/JSDOMFormDataCustom.cpp \
+	bindings/js/JSDOMGlobalObject.cpp \
+	bindings/js/JSDOMImplementationCustom.cpp \
+	bindings/js/JSDOMMimeTypeArrayCustom.cpp \
+	bindings/js/JSDOMPluginArrayCustom.cpp \
+	bindings/js/JSDOMPluginCustom.cpp \
+	bindings/js/JSDOMStringMapCustom.cpp \
+	bindings/js/JSDOMWindowBase.cpp \
+	bindings/js/JSDOMWindowCustom.cpp \
+	bindings/js/JSDOMWindowShell.cpp \
+	bindings/js/JSDOMWrapper.cpp \
+	bindings/js/JSDataGridColumnListCustom.cpp \
+	bindings/js/JSDataGridDataSource.cpp \
+	bindings/js/JSDataViewCustom.cpp \
+	bindings/js/JSDedicatedWorkerContextCustom.cpp \
+	bindings/js/JSDesktopNotificationsCustom.cpp \
+	bindings/js/JSDeviceMotionEventCustom.cpp \
+	bindings/js/JSDeviceOrientationEventCustom.cpp \
+	bindings/js/JSDirectoryEntrySyncCustom.cpp \
+	bindings/js/JSDocumentCustom.cpp \
+	bindings/js/JSElementCustom.cpp \
+	bindings/js/JSEntrySyncCustom.cpp \
+	bindings/js/JSErrorHandler.cpp \
+	bindings/js/JSEventCustom.cpp \
+	bindings/js/JSEventListener.cpp \
+	bindings/js/JSEventTarget.cpp \
+	bindings/js/JSExceptionBase.cpp \
+	bindings/js/JSFloat32ArrayCustom.cpp \
+	bindings/js/JSFileReaderCustom.cpp \
+	bindings/js/JSGeolocationCustom.cpp \
+	bindings/js/JSHTMLAllCollectionCustom.cpp \
+	bindings/js/JSHTMLAppletElementCustom.cpp \
+	bindings/js/JSHTMLCanvasElementCustom.cpp \
+	bindings/js/JSHTMLCollectionCustom.cpp \
+	bindings/js/JSHTMLDataGridElementCustom.cpp \
+	bindings/js/JSHTMLDocumentCustom.cpp \
+	bindings/js/JSHTMLElementCustom.cpp \
+	bindings/js/JSHTMLEmbedElementCustom.cpp \
+	bindings/js/JSHTMLFormElementCustom.cpp \
+	bindings/js/JSHTMLFrameElementCustom.cpp \
+	bindings/js/JSHTMLFrameSetElementCustom.cpp \
+	bindings/js/JSHTMLInputElementCustom.cpp \
+	bindings/js/JSHTMLLinkElementCustom.cpp \
+	bindings/js/JSHTMLObjectElementCustom.cpp \
+	bindings/js/JSHTMLOptionsCollectionCustom.cpp \
+	bindings/js/JSHTMLOutputElementCustom.cpp \
+	bindings/js/JSHTMLSelectElementCustom.cpp \
+	bindings/js/JSHTMLStyleElementCustom.cpp \
+	bindings/js/JSHistoryCustom.cpp \
+	bindings/js/JSIDBAnyCustom.cpp \
+	bindings/js/JSIDBKeyCustom.cpp \
+	bindings/js/JSImageConstructor.cpp \
+	bindings/js/JSImageDataCustom.cpp \
+	bindings/js/JSInt16ArrayCustom.cpp \
+	bindings/js/JSInt32ArrayCustom.cpp \
+	bindings/js/JSInt8ArrayCustom.cpp \
+	bindings/js/JSJavaScriptAudioNodeCustom.cpp \
+	bindings/js/JSLazyEventListener.cpp \
+	bindings/js/JSLocationCustom.cpp \
+	bindings/js/JSMainThreadExecState.cpp \
+	bindings/js/JSMemoryInfoCustom.cpp \
+	bindings/js/JSMessageChannelCustom.cpp \
+	bindings/js/JSMessageEventCustom.cpp \
+	bindings/js/JSMessagePortCustom.cpp \
+	bindings/js/JSNamedNodeMapCustom.cpp \
+	bindings/js/JSNavigatorCustom.cpp \
+	bindings/js/JSNodeCustom.cpp \
+	bindings/js/JSNodeFilterCondition.cpp \
+	bindings/js/JSNodeFilterCustom.cpp \
+	bindings/js/JSNodeIteratorCustom.cpp \
+	bindings/js/JSNodeListCustom.cpp \
+	bindings/js/JSOptionConstructor.cpp \
+	bindings/js/JSPluginElementFunctions.cpp \
+	bindings/js/JSProcessingInstructionCustom.cpp \
+	bindings/js/JSSQLResultSetRowListCustom.cpp \
+	bindings/js/JSSQLTransactionCustom.cpp \
+	bindings/js/JSSQLTransactionSyncCustom.cpp \
+	bindings/js/JSSVGElementInstanceCustom.cpp \
+	bindings/js/JSSVGLengthCustom.cpp \
+	bindings/js/JSSVGPathSegCustom.cpp \
+	bindings/js/JSSharedWorkerCustom.cpp \
+	bindings/js/JSStorageCustom.cpp \
+	bindings/js/JSStyleSheetCustom.cpp \
+	bindings/js/JSStyleSheetListCustom.cpp \
+	bindings/js/JSTextCustom.cpp \
+	bindings/js/JSTouchCustom.cpp \
+	bindings/js/JSTouchListCustom.cpp \
+	bindings/js/JSTreeWalkerCustom.cpp \
+	bindings/js/JSUint16ArrayCustom.cpp \
+	bindings/js/JSUint32ArrayCustom.cpp \
+	bindings/js/JSUint8ArrayCustom.cpp \
+	bindings/js/JSWebKitAnimationCustom.cpp \
+	bindings/js/JSWebKitAnimationListCustom.cpp \
+	bindings/js/JSWebKitCSSKeyframeRuleCustom.cpp \
+	bindings/js/JSWebKitCSSKeyframesRuleCustom.cpp \
+	bindings/js/JSWebKitCSSMatrixCustom.cpp \
+	bindings/js/JSWebKitPointCustom.cpp \
+	bindings/js/JSWorkerContextBase.cpp \
+	bindings/js/JSWorkerContextCustom.cpp \
+	bindings/js/JSWorkerCustom.cpp \
+	bindings/js/JSXMLHttpRequestCustom.cpp \
+	bindings/js/JSXMLHttpRequestUploadCustom.cpp \
+	bindings/js/JSXSLTProcessorCustom.cpp \
+	bindings/js/ScheduledAction.cpp \
+	bindings/js/ScriptCachedFrameData.cpp \
+	bindings/js/ScriptCallStackFactory.cpp \
+	bindings/js/ScriptController.cpp \
+	bindings/js/ScriptControllerAndroid.cpp \
+	bindings/js/ScriptEventListener.cpp \
+	bindings/js/ScriptFunctionCall.cpp \
+	bindings/js/ScriptObject.cpp \
+	bindings/js/ScriptProfile.cpp \
+	bindings/js/ScriptState.cpp \
+	bindings/js/ScriptValue.cpp \
+	bindings/js/SerializedScriptValue.cpp \
+	bindings/js/WorkerScriptController.cpp \
+	\
+	bindings/ScriptControllerBase.cpp \
+	\
+	bridge/IdentifierRep.cpp \
+	bridge/NP_jsobject.cpp \
+	bridge/c/CRuntimeObject.cpp \
+	bridge/c/c_class.cpp \
+	bridge/c/c_instance.cpp \
+	bridge/c/c_runtime.cpp \
+	bridge/c/c_utility.cpp \
+	bridge/jni/JNIUtility.cpp \
+	bridge/jni/JavaMethodJobject.cpp \
+	bridge/jni/JobjectWrapper.cpp \
+	bridge/jni/jsc/JNIUtilityPrivate.cpp \
+	bridge/jni/jsc/JavaArrayJSC.cpp \
+	bridge/jni/jsc/JavaClassJSC.cpp \
+	bridge/jni/jsc/JavaFieldJSC.cpp \
+	bridge/jni/jsc/JavaInstanceJSC.cpp \
+	bridge/jni/jsc/JavaRuntimeObject.cpp \
+	bridge/jsc/BridgeJSC.cpp \
+	bridge/npruntime.cpp \
+	bridge/runtime_array.cpp \
+	bridge/runtime_method.cpp \
+	bridge/runtime_object.cpp \
+	bridge/runtime_root.cpp
+
+# For XPath.
+LOCAL_SRC_FILES += \
+	bindings/js/JSCustomXPathNSResolver.cpp
diff --git a/Source/WebCore/Android.mk b/Source/WebCore/Android.mk
index 742fade..6542931 100644
--- a/Source/WebCore/Android.mk
+++ b/Source/WebCore/Android.mk
@@ -124,7 +124,6 @@
 	dom/DOMImplementation.cpp \
 	dom/DOMStringList.cpp \
 	dom/DOMStringMap.cpp \
-	dom/DOMTextContentWalker.cpp \
 	dom/DatasetDOMStringMap.cpp \
 	dom/DecodedDataDocumentParser.cpp \
 	dom/DeviceMotionController.cpp \
@@ -379,7 +378,6 @@
 	html/canvas/CanvasStyle.cpp \
 	html/canvas/DataView.cpp \
 	html/canvas/Float32Array.cpp \
-	html/canvas/Float64Array.cpp \
 	html/canvas/Int16Array.cpp \
 	html/canvas/Int32Array.cpp \
 	html/canvas/Int8Array.cpp \
@@ -633,73 +631,61 @@
 	platform/graphics/StringTruncator.cpp \
 	platform/graphics/WidthIterator.cpp \
 	\
+	platform/graphics/android/AndroidAnimation.cpp \
+	platform/graphics/android/BaseLayerAndroid.cpp \
+	platform/graphics/android/BaseRenderer.cpp \
+	platform/graphics/android/BaseTile.cpp \
+	platform/graphics/android/BaseTileTexture.cpp \
 	platform/graphics/android/BitmapAllocatorAndroid.cpp \
-	platform/graphics/android/GraphicsLayerAndroid.cpp \
+	platform/graphics/android/ClassTracker.cpp \
+	platform/graphics/android/DoubleBufferedTexture.cpp \
+	platform/graphics/android/FontAndroid.cpp \
+	platform/graphics/android/FontCacheAndroid.cpp \
+	platform/graphics/android/FontCustomPlatformData.cpp \
+	platform/graphics/android/FontDataAndroid.cpp \
+	platform/graphics/android/FontPlatformDataAndroid.cpp \
+	platform/graphics/android/GaneshContext.cpp \
+	platform/graphics/android/GaneshRenderer.cpp \
+	platform/graphics/android/GLExtras.cpp \
+	platform/graphics/android/GLUtils.cpp \
 	platform/graphics/android/GLWebViewState.cpp \
+	platform/graphics/android/GlyphMapAndroid.cpp \
+	platform/graphics/android/GradientAndroid.cpp \
+	platform/graphics/android/GraphicsContextAndroid.cpp \
+	platform/graphics/android/GraphicsLayerAndroid.cpp \
 	platform/graphics/android/ImageAndroid.cpp \
 	platform/graphics/android/ImageBufferAndroid.cpp \
 	platform/graphics/android/ImageSourceAndroid.cpp \
+	platform/graphics/android/ImagesManager.cpp \
+	platform/graphics/android/ImageTexture.cpp \
+	platform/graphics/android/Layer.cpp \
+	platform/graphics/android/LayerAndroid.cpp \
+	platform/graphics/android/MediaLayer.cpp \
+	platform/graphics/android/MediaTexture.cpp \
+	platform/graphics/android/PaintTileOperation.cpp \
+	platform/graphics/android/PaintedSurface.cpp \
 	platform/graphics/android/PathAndroid.cpp \
 	platform/graphics/android/PatternAndroid.cpp \
+	platform/graphics/android/PlatformGraphicsContext.cpp \
+	platform/graphics/android/PerformanceMonitor.cpp \
+	platform/graphics/android/RasterRenderer.cpp \
+	platform/graphics/android/ScrollableLayerAndroid.cpp \
 	platform/graphics/android/SharedBufferStream.cpp \
-	\
-	platform/graphics/android/context/GraphicsContextAndroid.cpp \
-	platform/graphics/android/context/GraphicsOperationCollection.cpp \
-	platform/graphics/android/context/PlatformGraphicsContext.cpp \
-	platform/graphics/android/context/PlatformGraphicsContextRecording.cpp \
-	platform/graphics/android/context/PlatformGraphicsContextSkia.cpp \
-	\
-	platform/graphics/android/fonts/FontAndroid.cpp \
-	platform/graphics/android/fonts/FontCacheAndroid.cpp \
-	platform/graphics/android/fonts/FontCustomPlatformData.cpp \
-	platform/graphics/android/fonts/FontDataAndroid.cpp \
-	platform/graphics/android/fonts/FontPlatformDataAndroid.cpp \
-	platform/graphics/android/fonts/GlyphMapAndroid.cpp \
-	platform/graphics/android/fonts/VerticalTextMap.cpp \
-	\
-	platform/graphics/android/layers/AndroidAnimation.cpp \
-	platform/graphics/android/layers/BaseLayerAndroid.cpp \
-	platform/graphics/android/layers/CanvasLayer.cpp \
-	platform/graphics/android/layers/CanvasTexture.cpp \
-	platform/graphics/android/layers/DumpLayer.cpp \
-	platform/graphics/android/layers/FixedPositioning.cpp \
-	platform/graphics/android/layers/IFrameContentLayerAndroid.cpp \
-	platform/graphics/android/layers/IFrameLayerAndroid.cpp \
-	platform/graphics/android/layers/Layer.cpp \
-	platform/graphics/android/layers/LayerAndroid.cpp \
-	platform/graphics/android/layers/MediaLayer.cpp \
-	platform/graphics/android/layers/MediaTexture.cpp \
-	platform/graphics/android/layers/PictureLayerContent.cpp \
-	platform/graphics/android/layers/PicturePileLayerContent.cpp \
-	platform/graphics/android/layers/ScrollableLayerAndroid.cpp \
-	platform/graphics/android/layers/VideoLayerAndroid.cpp \
-	platform/graphics/android/layers/VideoLayerManager.cpp \
-	\
-	platform/graphics/android/rendering/BaseRenderer.cpp \
-	platform/graphics/android/rendering/GaneshContext.cpp \
-	platform/graphics/android/rendering/GaneshRenderer.cpp \
-	platform/graphics/android/rendering/GLExtras.cpp \
-	platform/graphics/android/rendering/GLUtils.cpp \
-	platform/graphics/android/rendering/ImagesManager.cpp \
-	platform/graphics/android/rendering/ImageTexture.cpp \
-	platform/graphics/android/rendering/InspectorCanvas.cpp \
-	platform/graphics/android/rendering/PaintTileOperation.cpp \
-	platform/graphics/android/rendering/RasterRenderer.cpp \
-	platform/graphics/android/rendering/ShaderProgram.cpp \
-	platform/graphics/android/rendering/Surface.cpp \
-	platform/graphics/android/rendering/SurfaceBacking.cpp \
-	platform/graphics/android/rendering/SurfaceCollection.cpp \
-	platform/graphics/android/rendering/SurfaceCollectionManager.cpp \
-	platform/graphics/android/rendering/TextureInfo.cpp \
-	platform/graphics/android/rendering/TexturesGenerator.cpp \
-	platform/graphics/android/rendering/Tile.cpp \
-	platform/graphics/android/rendering/TileGrid.cpp \
-	platform/graphics/android/rendering/TileTexture.cpp \
-	platform/graphics/android/rendering/TilesManager.cpp \
-	platform/graphics/android/rendering/TilesProfiler.cpp \
-	platform/graphics/android/rendering/TransferQueue.cpp \
-	\
-	platform/graphics/android/utils/ClassTracker.cpp
+	platform/graphics/android/ShaderProgram.cpp \
+	platform/graphics/android/SharedTexture.cpp \
+	platform/graphics/android/TextureInfo.cpp \
+	platform/graphics/android/TexturesGenerator.cpp \
+	platform/graphics/android/TilesManager.cpp \
+	platform/graphics/android/TilesProfiler.cpp \
+	platform/graphics/android/TiledPage.cpp \
+	platform/graphics/android/TiledTexture.cpp \
+	platform/graphics/android/TransferQueue.cpp \
+	platform/graphics/android/TreeManager.cpp \
+	platform/graphics/android/VerticalTextMap.cpp \
+	platform/graphics/android/VideoLayerAndroid.cpp \
+	platform/graphics/android/VideoLayerManager.cpp \
+	platform/graphics/android/ZoomManager.cpp \
+	platform/graphics/android/android_graphics.cpp \
 
 ifeq ($(ENABLE_SVG), true)
 LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
@@ -727,7 +713,6 @@
 	platform/graphics/skia/FloatPointSkia.cpp \
 	platform/graphics/skia/FloatRectSkia.cpp \
 	platform/graphics/skia/GlyphPageTreeNodeSkia.cpp \
-	platform/graphics/skia/GradientSkia.cpp \
 	platform/graphics/skia/IntPointSkia.cpp \
 	platform/graphics/skia/IntRectSkia.cpp \
 	platform/graphics/skia/NativeImageSkia.cpp \
@@ -826,7 +811,6 @@
 	plugins/DOMPluginArray.cpp \
 	plugins/PluginData.cpp \
 	plugins/PluginDatabase.cpp \
-	plugins/PluginDebug.cpp \
 	plugins/PluginMainThreadScheduler.cpp \
 	plugins/PluginPackage.cpp \
 	plugins/PluginStream.cpp \
@@ -1272,5 +1256,5 @@
 # For complex scripts(Arabic, Thai, Hindi...).
 ifeq ($(SUPPORT_COMPLEX_SCRIPTS),true)
 LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
-	platform/graphics/android/fonts/HarfbuzzSkia.cpp
+	platform/graphics/android/HarfbuzzSkia.cpp
 endif
diff --git a/Source/WebCore/Android.v8bindings.mk b/Source/WebCore/Android.v8bindings.mk
index 7858ef3..283a212 100644
--- a/Source/WebCore/Android.v8bindings.mk
+++ b/Source/WebCore/Android.v8bindings.mk
@@ -130,7 +130,6 @@
 	bindings/v8/custom/V8EventSourceConstructor.cpp \
 	bindings/v8/custom/V8FileReaderCustom.cpp \
 	bindings/v8/custom/V8Float32ArrayCustom.cpp \
-	bindings/v8/custom/V8Float64ArrayCustom.cpp \
 	bindings/v8/custom/V8GeolocationCustom.cpp \
 	bindings/v8/custom/V8HistoryCustom.cpp \
 	bindings/v8/custom/V8HTMLAllCollectionCustom.cpp \
diff --git a/Source/WebCore/DerivedSources.cpp b/Source/WebCore/DerivedSources.cpp
index 45a425c..3bba78c 100644
--- a/Source/WebCore/DerivedSources.cpp
+++ b/Source/WebCore/DerivedSources.cpp
@@ -130,7 +130,6 @@
 #include "JSFileWriterSync.cpp"
 #include "JSWebKitFlags.cpp"
 #include "JSFloat32Array.cpp"
-#include "JSFloat64Array.cpp"
 #include "JSGeolocation.cpp"
 #include "JSGeoposition.cpp"
 #include "JSHashChangeEvent.cpp"
diff --git a/Source/WebCore/WebCore.exp.in b/Source/WebCore/WebCore.exp.in
index c6c76bf..f110846 100644
--- a/Source/WebCore/WebCore.exp.in
+++ b/Source/WebCore/WebCore.exp.in
@@ -1595,6 +1595,7 @@
 __ZNK7WebCore14SecurityOrigin9canAccessEPKS0_
 __ZNK7WebCore4KURL10protocolIsEPKc
 __ZNK7WebCore4KURL7hasPathEv
+__ZNK7WebCore4KURL9prettyURLEv
 #endif
 
 #if ENABLE(ORIENTATION_EVENTS)
diff --git a/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp b/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp
index 82367b2..a457ce8 100644
--- a/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp
+++ b/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp
@@ -81,7 +81,6 @@
 #include "JSEventTarget.cpp"
 #include "JSExceptionBase.cpp"
 #include "JSFloat32ArrayCustom.cpp"
-#include "JSFloat64ArrayCustom.cpp"
 #include "JSGeolocationCustom.cpp"
 #include "JSHTMLAllCollectionCustom.cpp"
 #include "JSHTMLAppletElementCustom.cpp"
diff --git a/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp b/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
index 938be96..4bde9e5 100644
--- a/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
+++ b/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
@@ -31,7 +31,6 @@
 #include "JSEventListener.h"
 #include "JSEventSource.h"
 #include "JSFloat32Array.h"
-#include "JSFloat64Array.h"
 #include "JSHTMLCollection.h"
 #include "JSHistory.h"
 #include "JSImageConstructor.h"
@@ -570,11 +569,6 @@
     return getDOMConstructor<JSFloat32ArrayConstructor>(exec, this);
 }
 
-JSValue JSDOMWindow::float64Array(ExecState* exec) const 
-{ 
-    return getDOMConstructor<JSFloat64ArrayConstructor>(exec, this); 
-} 
-
 JSValue JSDOMWindow::dataView(ExecState* exec) const
 {
     return getDOMConstructor<JSDataViewConstructor>(exec, this);
diff --git a/Source/WebCore/bindings/js/JSFloat64ArrayCustom.cpp b/Source/WebCore/bindings/js/JSFloat64ArrayCustom.cpp
deleted file mode 100644
index 446b0ec..0000000
--- a/Source/WebCore/bindings/js/JSFloat64ArrayCustom.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
- */
-
-#include "config.h"
-#include "JSFloat64Array.h"
-
-#include "Float64Array.h"
-#include "JSArrayBufferViewHelper.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-void JSFloat64Array::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value)
-{
-    impl()->set(index, value.toNumber(exec));
-}
-
-JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, Float64Array* object)
-{
-    return toJSArrayBufferView<JSFloat64Array>(exec, globalObject, object);
-}
-
-JSC::JSValue JSFloat64Array::set(JSC::ExecState* exec)
-{
-    return setWebGLArrayHelper(exec, impl(), toFloat64Array);
-}
-
-EncodedJSValue JSC_HOST_CALL JSFloat64ArrayConstructor::constructJSFloat64Array(ExecState* exec)
-{
-    JSFloat64ArrayConstructor* jsConstructor = static_cast<JSFloat64ArrayConstructor*>(exec->callee());
-    RefPtr<Float64Array> array = constructArrayBufferView<Float64Array, double>(exec);
-    if (!array.get())
-        // Exception has already been thrown.
-        return JSValue::encode(JSValue());
-    return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), array.get())));
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp b/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp
index c3a0cbb..e025008 100644
--- a/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp
+++ b/Source/WebCore/bindings/v8/V8DOMWindowShell.cpp
@@ -76,6 +76,10 @@
 #include <wtf/UnusedParam.h>
 #include <wtf/text/CString.h>
 
+#ifdef ANDROID_INSTRUMENT
+#include "TimeCounter.h"
+#endif
+
 namespace WebCore {
 
 static void handleFatalErrorInV8()
@@ -279,6 +283,10 @@
     if (!m_context.IsEmpty())
         return false;
 
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::start(android::TimeCounter::JavaScriptInitTimeCounter);
+#endif
+
     // Create a handle scope for all local handles.
     v8::HandleScope handleScope;
 
@@ -344,6 +352,10 @@
     // we do isolated worlds the WebCore way.
     m_frame->loader()->dispatchDidClearWindowObjectInWorld(0);
 
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::record(android::TimeCounter::JavaScriptInitTimeCounter, __FUNCTION__);
+#endif
+
     return true;
 }
 
diff --git a/Source/WebCore/bindings/v8/V8Proxy.cpp b/Source/WebCore/bindings/v8/V8Proxy.cpp
index d90cf1c..ca57fa8 100644
--- a/Source/WebCore/bindings/v8/V8Proxy.cpp
+++ b/Source/WebCore/bindings/v8/V8Proxy.cpp
@@ -83,6 +83,14 @@
 #include <wtf/UnusedParam.h>
 #include <wtf/text/StringConcatenate.h>
 
+#ifdef ANDROID_INSTRUMENT
+#include "TimeCounter.h"
+#endif
+
+#if PLATFORM(ANDROID)
+#include <wtf/text/CString.h>
+#endif
+
 namespace WebCore {
 
 // Static list of registered extensions
@@ -201,6 +209,16 @@
 }
 
 v8::Handle<v8::Script> V8Proxy::compileScript(v8::Handle<v8::String> code, const String& fileName, const TextPosition0& scriptStartPosition, v8::ScriptData* scriptData)
+#ifdef ANDROID_INSTRUMENT
+{
+    android::TimeCounter::start(android::TimeCounter::JavaScriptParseTimeCounter);
+    v8::Handle<v8::Script> script = compileScriptInternal(code, fileName, scriptStartPosition, scriptData);
+    android::TimeCounter::record(android::TimeCounter::JavaScriptParseTimeCounter, __FUNCTION__);
+    return script;
+}
+
+v8::Handle<v8::Script> V8Proxy::compileScriptInternal(v8::Handle<v8::String> code, const String& fileName, const TextPosition0& scriptStartPosition, v8::ScriptData* scriptData)
+#endif
 {
     const uint16_t* fileNameString = fromWebCoreString(fileName);
     v8::Handle<v8::String> name = v8::String::New(fileNameString, fileName.length());
@@ -380,6 +398,16 @@
 }
 
 v8::Local<v8::Value> V8Proxy::runScript(v8::Handle<v8::Script> script, bool isInlineCode)
+#ifdef ANDROID_INSTRUMENT
+{
+    android::TimeCounter::start(android::TimeCounter::JavaScriptExecuteTimeCounter);
+    v8::Local<v8::Value> result = runScriptInternal(script, isInlineCode);
+    android::TimeCounter::record(android::TimeCounter::JavaScriptExecuteTimeCounter, __FUNCTION__);
+    return result;
+}
+
+v8::Local<v8::Value> V8Proxy::runScriptInternal(v8::Handle<v8::Script> script, bool isInlineCode)
+#endif
 {
     if (script.IsEmpty())
         return notHandledByInterceptor();
@@ -444,6 +472,9 @@
 
 v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[])
 {
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::start(android::TimeCounter::JavaScriptExecuteTimeCounter);
+#endif
     V8GCController::checkMemoryUsage();
     v8::Local<v8::Value> result;
     {
@@ -490,6 +521,9 @@
     if (v8::V8::IsDead())
         handleFatalErrorInV8();
 
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::record(android::TimeCounter::JavaScriptExecuteTimeCounter, __FUNCTION__);
+#endif
     return result;
 }
 
diff --git a/Source/WebCore/bindings/v8/V8Proxy.h b/Source/WebCore/bindings/v8/V8Proxy.h
index 777815b..fc52b19 100644
--- a/Source/WebCore/bindings/v8/V8Proxy.h
+++ b/Source/WebCore/bindings/v8/V8Proxy.h
@@ -171,6 +171,10 @@
         // Run an already compiled script.
         v8::Local<v8::Value> runScript(v8::Handle<v8::Script>, bool isInlineCode);
 
+#ifdef ANDROID_INSTRUMENT
+        v8::Local<v8::Value> runScriptInternal(v8::Handle<v8::Script> script, bool inline_code);
+#endif
+
         // Call the function with the given receiver and arguments.
         v8::Local<v8::Value> callFunction(v8::Handle<v8::Function>, v8::Handle<v8::Object>, int argc, v8::Handle<v8::Value> argv[]);
 
@@ -240,6 +244,10 @@
 
         static v8::Handle<v8::Script> compileScript(v8::Handle<v8::String> code, const String& fileName, const TextPosition0& scriptStartPosition, v8::ScriptData* = 0);
 
+#ifdef ANDROID_INSTRUMENT
+        static v8::Handle<v8::Script> compileScriptInternal(v8::Handle<v8::String> code, const String& fileName, int baseLine, v8::ScriptData* scriptData);
+#endif
+
         // If the exception code is different from zero, a DOM exception is
         // schedule to be thrown.
         static void setDOMException(int exceptionCode);
diff --git a/Source/WebCore/bindings/v8/custom/V8DocumentCustom.cpp b/Source/WebCore/bindings/v8/custom/V8DocumentCustom.cpp
index d142a9f..7cad58e 100644
--- a/Source/WebCore/bindings/v8/custom/V8DocumentCustom.cpp
+++ b/Source/WebCore/bindings/v8/custom/V8DocumentCustom.cpp
@@ -43,7 +43,6 @@
 #include "V8CanvasRenderingContext2D.h"
 #include "V8CustomXPathNSResolver.h"
 #include "V8DOMImplementation.h"
-#include "V8DOMWrapper.h"
 #include "V8HTMLDocument.h"
 #include "V8IsolatedContext.h"
 #include "V8Node.h"
@@ -145,8 +144,9 @@
     RefPtr<TouchList> touchList = TouchList::create();
 
     for (int i = 0; i < args.Length(); i++) {
-        Touch* touch = V8DOMWrapper::isWrapperOfType(args[i], &V8Touch::info) ? V8Touch::toNative(args[i]->ToObject()) : 0;
-        touchList->append(touch);
+        if (!args[i]->IsObject())
+            return v8::Undefined();
+        touchList->append(V8Touch::toNative(args[i]->ToObject()));
     }
 
     return toV8(touchList.release());
diff --git a/Source/WebCore/bindings/v8/custom/V8Float64ArrayCustom.cpp b/Source/WebCore/bindings/v8/custom/V8Float64ArrayCustom.cpp
deleted file mode 100644
index 429e962..0000000
--- a/Source/WebCore/bindings/v8/custom/V8Float64ArrayCustom.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "Float64Array.h"
-
-#include "ArrayBuffer.h"
-#include "V8ArrayBuffer.h"
-#include "V8ArrayBufferViewCustom.h"
-#include "V8Binding.h"
-#include "V8Float64Array.h"
-#include "V8Proxy.h"
-
-namespace WebCore {
-
-v8::Handle<v8::Value> V8Float64Array::constructorCallback(const v8::Arguments& args)
-{
-    INC_STATS("DOM.Float64Array.Contructor");
-
-    return constructWebGLArray<Float64Array, double>(args, &info, v8::kExternalDoubleArray);
-}
-
-v8::Handle<v8::Value> V8Float64Array::setCallback(const v8::Arguments& args)
-{
-    INC_STATS("DOM.Float64Array.set()");
-    return setWebGLArrayHelper<Float64Array, V8Float64Array>(args);
-}
-
-v8::Handle<v8::Value> toV8(Float64Array* impl)
-{
-    if (!impl)
-        return v8::Null();
-    v8::Handle<v8::Object> wrapper = V8Float64Array::wrap(impl);
-    if (!wrapper.IsEmpty())
-        wrapper->SetIndexedPropertiesToExternalArrayData(impl->baseAddress(), v8::kExternalDoubleArray, impl->length());
-    return wrapper;
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bridge/jni/JavaMethodJobject.cpp b/Source/WebCore/bridge/jni/JavaMethodJobject.cpp
index f93e197..01a0b5b 100644
--- a/Source/WebCore/bridge/jni/JavaMethodJobject.cpp
+++ b/Source/WebCore/bridge/jni/JavaMethodJobject.cpp
@@ -131,9 +131,9 @@
             else {
                 signatureBuilder.append(signatureFromJavaType(type));
                 if (type == JavaTypeObject
-// ANDROID
+#if USE(V8)
                     || type == JavaTypeString
-// ANDROID
+#endif
                     ) {
                     appendClassName(signatureBuilder, javaClassName.data());
                     signatureBuilder.append(';');
@@ -148,9 +148,9 @@
         else {
             signatureBuilder.append(signatureFromJavaType(m_returnType));
             if (m_returnType == JavaTypeObject
-// ANDROID
+#if USE(V8)
                 || m_returnType == JavaTypeString
-// ANDROID
+#endif
                 ) {
                 appendClassName(signatureBuilder, returnType);
                 signatureBuilder.append(';');
diff --git a/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp b/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp
index 15b4bda..42efaac 100644
--- a/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp
+++ b/Source/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp
@@ -72,16 +72,11 @@
                 break;
             }
 
-            // Convert to null if the length property is not a number.
-            if (!NPVARIANT_IS_INT32(npvLength) && !NPVARIANT_IS_DOUBLE(npvLength))
-                break;
-
-            // Convert to null if the length property is out of bounds.
-            double doubleLength = NPVARIANT_IS_INT32(npvLength) ? NPVARIANT_TO_INT32(npvLength) : NPVARIANT_TO_DOUBLE(npvLength);
-            if (doubleLength < 0.0 || doubleLength > INT32_MAX)
-                break;
-
-            jsize length = static_cast<jsize>(doubleLength);
+            jsize length = 0;
+            if (NPVARIANT_IS_INT32(npvLength))
+                length = static_cast<jsize>(NPVARIANT_TO_INT32(npvLength));
+            else if (NPVARIANT_IS_DOUBLE(npvLength))
+                length = static_cast<jsize>(NPVARIANT_TO_DOUBLE(npvLength));
 
             if (!strcmp(javaClassName.data(), "[Ljava.lang.String;")) {
                 // Match JSC behavior by only allowing Object arrays if they are Strings.
@@ -90,7 +85,7 @@
                 for (jsize i = 0; i < length; i++) {
                     NPVariant npvValue;
                     _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
-                    if (NPVARIANT_IS_STRING(npvValue)) {
+                    if(NPVARIANT_IS_STRING(npvValue)) {
                         NPString str = NPVARIANT_TO_STRING(npvValue);
                         env->SetObjectArrayElement(static_cast<jobjectArray>(javaArray), i, env->NewStringUTF(str.UTF8Characters));
                     }
@@ -105,10 +100,11 @@
                     NPVariant npvValue;
                     _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
                     jbyte bVal = 0;
-                    if (NPVARIANT_IS_INT32(npvValue))
+                    if (NPVARIANT_IS_INT32(npvValue)) {
                         bVal = static_cast<jbyte>(NPVARIANT_TO_INT32(npvValue));
-                    else if (NPVARIANT_IS_DOUBLE(npvValue))
+                    } else if (NPVARIANT_IS_DOUBLE(npvValue)) {
                         bVal = static_cast<jbyte>(NPVARIANT_TO_DOUBLE(npvValue));
+                    }
                     env->SetByteArrayRegion(static_cast<jbyteArray>(javaArray), i, 1, &bVal);
                 }
             } else if (!strcmp(javaClassName.data(), "[C")) {
@@ -119,8 +115,12 @@
                     NPVariant npvValue;
                     _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
                     jchar cVal = 0;
-                    if (NPVARIANT_IS_INT32(npvValue))
+                    if (NPVARIANT_IS_INT32(npvValue)) {
                         cVal = static_cast<jchar>(NPVARIANT_TO_INT32(npvValue));
+                    } else if (NPVARIANT_IS_STRING(npvValue)) {
+                        NPString str = NPVARIANT_TO_STRING(npvValue);
+                        cVal = str.UTF8Characters[0];
+                    }
                     env->SetCharArrayRegion(static_cast<jcharArray>(javaArray), i, 1, &cVal);
                 }
             } else if (!strcmp(javaClassName.data(), "[D")) {
@@ -155,10 +155,11 @@
                     NPVariant npvValue;
                     _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
                     jint iVal = 0;
-                    if (NPVARIANT_IS_INT32(npvValue))
+                    if (NPVARIANT_IS_INT32(npvValue)) {
                         iVal = NPVARIANT_TO_INT32(npvValue);
-                    else if (NPVARIANT_IS_DOUBLE(npvValue))
+                    } else if (NPVARIANT_IS_DOUBLE(npvValue)) {
                         iVal = static_cast<jint>(NPVARIANT_TO_DOUBLE(npvValue));
+                    }
                     env->SetIntArrayRegion(static_cast<jintArray>(javaArray), i, 1, &iVal);
                 }
             } else if (!strcmp(javaClassName.data(), "[J")) {
@@ -169,10 +170,11 @@
                     NPVariant npvValue;
                     _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
                     jlong jVal = 0;
-                    if (NPVARIANT_IS_INT32(npvValue))
+                    if (NPVARIANT_IS_INT32(npvValue)) {
                         jVal = static_cast<jlong>(NPVARIANT_TO_INT32(npvValue));
-                    else if (NPVARIANT_IS_DOUBLE(npvValue))
+                    } else if (NPVARIANT_IS_DOUBLE(npvValue)) {
                         jVal = static_cast<jlong>(NPVARIANT_TO_DOUBLE(npvValue));
+                    }
                     env->SetLongArrayRegion(static_cast<jlongArray>(javaArray), i, 1, &jVal);
                 }
             } else if (!strcmp(javaClassName.data(), "[S")) {
@@ -183,10 +185,11 @@
                     NPVariant npvValue;
                     _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
                     jshort sVal = 0;
-                    if (NPVARIANT_IS_INT32(npvValue))
+                    if (NPVARIANT_IS_INT32(npvValue)) {
                         sVal = static_cast<jshort>(NPVARIANT_TO_INT32(npvValue));
-                    else if (NPVARIANT_IS_DOUBLE(npvValue))
+                    } else if (NPVARIANT_IS_DOUBLE(npvValue)) {
                         sVal = static_cast<jshort>(NPVARIANT_TO_DOUBLE(npvValue));
+                    }
                     env->SetShortArrayRegion(static_cast<jshortArray>(javaArray), i, 1, &sVal);
                 }
             } else if (!strcmp(javaClassName.data(), "[Z")) {
diff --git a/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.cpp b/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.cpp
index e7b854d..f2dd1d2 100644
--- a/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.cpp
+++ b/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.cpp
@@ -65,29 +65,15 @@
     return m_class.get();
 }
 
-// ANDROID
-JavaValue JavaInstanceJobject::invokeMethod(const JavaMethod* method, JavaValue* args, bool& didRaiseUncaughtException)
+JavaValue JavaInstanceJobject::invokeMethod(const JavaMethod* method, JavaValue* args)
 {
-    didRaiseUncaughtException = false;
-// END ANDROID
-
     ASSERT(getClass()->methodsNamed(method->name().utf8().data()).find(method) != notFound);
     unsigned int numParams = method->numParameters();
     OwnArrayPtr<jvalue> jvalueArgs = adoptArrayPtr(new jvalue[numParams]);
     for (unsigned int i = 0; i < numParams; ++i)
         jvalueArgs[i] = javaValueToJvalue(args[i]);
     jvalue result = callJNIMethod(javaInstance(), method->returnType(), method->name().utf8().data(), method->signature(), jvalueArgs.get());
-
-// ANDROID
-    JNIEnv* env = getJNIEnv();
-    if (env->ExceptionCheck() != JNI_FALSE) {
-        env->ExceptionClear();
-        didRaiseUncaughtException = true;
-        return JavaValue();
-    }
-
     return jvalueToJavaValue(result, method->returnType());
-// END ANDROID
 }
 
 static void appendClassName(StringBuilder& builder, const char* className)
diff --git a/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.h b/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.h
index 255c190..bb38e77 100644
--- a/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.h
+++ b/Source/WebCore/bridge/jni/v8/JavaInstanceJobjectV8.h
@@ -52,9 +52,7 @@
 
     // JavaInstance implementation
     virtual JavaClass* getClass() const;
-// ANDROID
-    virtual JavaValue invokeMethod(const JavaMethod*, JavaValue* args, bool& didRaiseUncaughtException);
-// END ANDROID
+    virtual JavaValue invokeMethod(const JavaMethod*, JavaValue* args);
     virtual JavaValue getField(const JavaField*);
     virtual void begin();
     virtual void end();
diff --git a/Source/WebCore/bridge/jni/v8/JavaInstanceV8.h b/Source/WebCore/bridge/jni/v8/JavaInstanceV8.h
index 5a1960a..7436de7 100644
--- a/Source/WebCore/bridge/jni/v8/JavaInstanceV8.h
+++ b/Source/WebCore/bridge/jni/v8/JavaInstanceV8.h
@@ -49,9 +49,7 @@
     virtual JavaClass* getClass() const = 0;
     // args must be an array of length greater than or equal to the number of
     // arguments expected by the method.
-// ANDROID
-    virtual JavaValue invokeMethod(const JavaMethod*, JavaValue* args, bool& didRaiseUncaughtException) = 0;
-// END ANDROID
+    virtual JavaValue invokeMethod(const JavaMethod*, JavaValue* args) = 0;
     virtual JavaValue getField(const JavaField*) = 0;
 
     // These functions are called before and after the main entry points into
diff --git a/Source/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp b/Source/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp
index 784ea01..b22d57f 100644
--- a/Source/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp
+++ b/Source/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp
@@ -146,16 +146,10 @@
     for (unsigned int i = 0; i < argCount; i++)
         jArgs[i] = convertNPVariantToJavaValue(args[i], jMethod->parameterAt(i));
 
-// ANDROID
-    bool exceptionOccurred;
-    JavaValue jResult = instance->invokeMethod(jMethod, jArgs, exceptionOccurred);
+    JavaValue jResult = instance->invokeMethod(jMethod, jArgs);
     instance->end();
     delete[] jArgs;
 
-    if (exceptionOccurred)
-        return false;
-// END ANDROID
-
     VOID_TO_NPVARIANT(*result);
     convertJavaValueToNPVariant(jResult, result);
     return true;
diff --git a/Source/WebCore/bridge/jni/v8/JavaValueV8.h b/Source/WebCore/bridge/jni/v8/JavaValueV8.h
index c6ff315..3e1c623 100644
--- a/Source/WebCore/bridge/jni/v8/JavaValueV8.h
+++ b/Source/WebCore/bridge/jni/v8/JavaValueV8.h
@@ -49,18 +49,7 @@
 // currently used only with V8.
 // See https://bugs.webkit.org/show_bug.cgi?id=57023.
 struct JavaValue {
-// ANDROID
-    JavaValue()
-        : m_type(JavaTypeInvalid)
-        , m_booleanValue(false)
-        , m_byteValue(0)
-        , m_charValue(0)
-        , m_shortValue(0)
-        , m_intValue(0)
-        , m_longValue(0)
-        , m_floatValue(0.0)
-        , m_doubleValue(0.0) {}
-// ANDROID
+    JavaValue() : m_type(JavaTypeInvalid) {}
 
     JavaType m_type;
     // We don't use a union because we want to be able to ref-count some of the
diff --git a/Source/WebCore/css/AndroidCSSPropertyNames.in b/Source/WebCore/css/AndroidCSSPropertyNames.in
index be751da..ef67d6b 100644
--- a/Source/WebCore/css/AndroidCSSPropertyNames.in
+++ b/Source/WebCore/css/AndroidCSSPropertyNames.in
@@ -21,5 +21,14 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #
-
+-webkit-ring
+-webkit-ring-fill-color
+-webkit-ring-inner-width
+-webkit-ring-outer-width
+-webkit-ring-outset
+-webkit-ring-pressed-inner-color
+-webkit-ring-pressed-outer-color
+-webkit-ring-radius
+-webkit-ring-selected-inner-color
+-webkit-ring-selected-outer-color
 -webkit-tap-highlight-color
diff --git a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
index 4922109..4c0571d 100644
--- a/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
+++ b/Source/WebCore/css/CSSComputedStyleDeclaration.cpp
@@ -291,6 +291,18 @@
     CSSPropertyWebkitSvgShadow,
     CSSPropertyVectorEffect
 #endif
+#ifdef ANDROID_CSS_RING
+    ,
+    CSSPropertyWebkitRingFillColor,
+    CSSPropertyWebkitRingInnerWidth,
+    CSSPropertyWebkitRingOuterWidth,
+    CSSPropertyWebkitRingOutset,
+    CSSPropertyWebkitRingPressedInnerColor,
+    CSSPropertyWebkitRingPressedOuterColor,
+    CSSPropertyWebkitRingRadius,
+    CSSPropertyWebkitRingSelectedInnerColor,
+    CSSPropertyWebkitRingSelectedOuterColor
+#endif
 #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
     ,
     CSSPropertyWebkitTapHighlightColor
@@ -1806,6 +1818,29 @@
         case CSSPropertyWebkitTransformOriginZ:
         case CSSPropertyWebkitTransition:
             break;
+#ifdef ANDROID_CSS_RING
+        case CSSPropertyWebkitRing:
+            // shorthand property currently not supported see bug 13658
+            break;
+        case CSSPropertyWebkitRingFillColor:
+            return primitiveValueCache->createColorValue(style->ringFillColor().rgb());
+        case CSSPropertyWebkitRingInnerWidth:
+            return primitiveValueCache->createValue(style->ringInnerWidth());
+        case CSSPropertyWebkitRingOuterWidth:
+            return primitiveValueCache->createValue(style->ringOuterWidth());
+        case CSSPropertyWebkitRingOutset:
+            return primitiveValueCache->createValue(style->ringOutset());
+        case CSSPropertyWebkitRingPressedInnerColor:
+            return primitiveValueCache->createColorValue(style->ringPressedInnerColor().rgb());
+        case CSSPropertyWebkitRingPressedOuterColor:
+            return primitiveValueCache->createColorValue(style->ringPressedOuterColor().rgb());
+        case CSSPropertyWebkitRingRadius:
+            return primitiveValueCache->createValue(style->ringRadius());
+        case CSSPropertyWebkitRingSelectedInnerColor:
+            return primitiveValueCache->createColorValue(style->ringSelectedInnerColor().rgb());
+        case CSSPropertyWebkitRingSelectedOuterColor:
+            return primitiveValueCache->createColorValue(style->ringSelectedOuterColor().rgb());
+#endif
 #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
         case CSSPropertyWebkitTapHighlightColor:
             return primitiveValueCache->createColorValue(style->tapHighlightColor().rgb());
diff --git a/Source/WebCore/css/CSSFontFace.cpp b/Source/WebCore/css/CSSFontFace.cpp
index 3b6dea4..2c50a04 100644
--- a/Source/WebCore/css/CSSFontFace.cpp
+++ b/Source/WebCore/css/CSSFontFace.cpp
@@ -118,19 +118,6 @@
     return 0;
 }
 
-void CSSFontFace::retireCustomFont(SimpleFontData* fontData)
-{
-    if (m_segmentedFontFaces.isEmpty()) {
-        GlyphPageTreeNode::pruneTreeCustomFontData(fontData);
-        delete fontData;
-        return;
-    }
-
-    // Use one of the CSSSegmentedFontFaces' font selector. They all have
-    // the same font selector.
-    (*m_segmentedFontFaces.begin())->fontSelector()->retireCustomFont(fontData);
-}
-
 #if ENABLE(SVG_FONTS)
 bool CSSFontFace::hasSVGFontFaceSource() const
 {
diff --git a/Source/WebCore/css/CSSFontFace.h b/Source/WebCore/css/CSSFontFace.h
index 45f8f13..55e048c 100644
--- a/Source/WebCore/css/CSSFontFace.h
+++ b/Source/WebCore/css/CSSFontFace.h
@@ -63,7 +63,6 @@
     void addSource(CSSFontFaceSource*);
 
     void fontLoaded(CSSFontFaceSource*);
-    void retireCustomFont(SimpleFontData*);
 
     SimpleFontData* getFontData(const FontDescription&, bool syntheticBold, bool syntheticItalic);
 
diff --git a/Source/WebCore/css/CSSFontFaceSource.cpp b/Source/WebCore/css/CSSFontFaceSource.cpp
index 49175e6..eeb90a4 100644
--- a/Source/WebCore/css/CSSFontFaceSource.cpp
+++ b/Source/WebCore/css/CSSFontFaceSource.cpp
@@ -69,11 +69,10 @@
 {
     if (m_fontDataTable.isEmpty())
         return;
-
     HashMap<unsigned, SimpleFontData*>::iterator end = m_fontDataTable.end();
     for (HashMap<unsigned, SimpleFontData*>::iterator it = m_fontDataTable.begin(); it != end; ++it)
-        m_face->retireCustomFont(it->second);
-
+        GlyphPageTreeNode::pruneTreeCustomFontData(it->second);
+    deleteAllValues(m_fontDataTable);
     m_fontDataTable.clear();
 }
 
diff --git a/Source/WebCore/css/CSSFontSelector.cpp b/Source/WebCore/css/CSSFontSelector.cpp
index 0f70664..8024afa 100644
--- a/Source/WebCore/css/CSSFontSelector.cpp
+++ b/Source/WebCore/css/CSSFontSelector.cpp
@@ -378,16 +378,6 @@
     dispatchInvalidationCallbacks();
 }
 
-void CSSFontSelector::retireCustomFont(FontData* fontData)
-{
-    if (m_document)
-        m_document->retireCustomFont(fontData);
-    else {
-        GlyphPageTreeNode::pruneTreeCustomFontData(fontData);
-        delete fontData;
-    }
-}
-
 static FontData* fontDataForGenericFamily(Document* document, const FontDescription& fontDescription, const AtomicString& familyName)
 {
     if (!document || !document->frame())
diff --git a/Source/WebCore/css/CSSFontSelector.h b/Source/WebCore/css/CSSFontSelector.h
index 2b0df28..f50ea42 100644
--- a/Source/WebCore/css/CSSFontSelector.h
+++ b/Source/WebCore/css/CSSFontSelector.h
@@ -59,8 +59,6 @@
     void fontLoaded();
     virtual void fontCacheInvalidated();
 
-    void retireCustomFont(FontData*);
-
     bool isEmpty() const;
 
     CachedResourceLoader* cachedResourceLoader() const;
diff --git a/Source/WebCore/css/CSSImportRule.cpp b/Source/WebCore/css/CSSImportRule.cpp
index 81ade39..09e313e 100644
--- a/Source/WebCore/css/CSSImportRule.cpp
+++ b/Source/WebCore/css/CSSImportRule.cpp
@@ -170,4 +170,26 @@
         addSubresourceURL(urls, m_styleSheet->baseURL());
 }
 
+#ifdef ANDROID_INSTRUMENT
+void* CSSImportRule::operator new(size_t size)
+{
+    return StyleBase::operator new(size);
+}
+
+void* CSSImportRule::operator new[](size_t size)
+{
+    return StyleBase::operator new[](size);
+}
+
+void CSSImportRule::operator delete(void* p, size_t size)
+{
+    StyleBase::operator delete(p, size);
+}
+
+void CSSImportRule::operator delete[](void* p, size_t size)
+{
+    StyleBase::operator delete[](p, size);
+}
+#endif
+
 } // namespace WebCore
diff --git a/Source/WebCore/css/CSSImportRule.h b/Source/WebCore/css/CSSImportRule.h
index ad4e97d..3f44f5b 100644
--- a/Source/WebCore/css/CSSImportRule.h
+++ b/Source/WebCore/css/CSSImportRule.h
@@ -66,6 +66,14 @@
     // from CachedResourceClient
     virtual void setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CachedCSSStyleSheet*);
 
+#ifdef ANDROID_INSTRUMENT
+    // Overridden to resolve the ambiguous
+    void* operator new(size_t size);
+    void* operator new[](size_t size);
+    void operator delete(void* p, size_t size);
+    void operator delete[](void* p, size_t size);
+#endif
+
     String m_strHref;
     RefPtr<MediaList> m_lstMedia;
     RefPtr<CSSStyleSheet> m_styleSheet;
diff --git a/Source/WebCore/css/CSSMutableStyleDeclaration.cpp b/Source/WebCore/css/CSSMutableStyleDeclaration.cpp
index ece418a..ba3332d 100644
--- a/Source/WebCore/css/CSSMutableStyleDeclaration.cpp
+++ b/Source/WebCore/css/CSSMutableStyleDeclaration.cpp
@@ -261,6 +261,20 @@
                 return value->cssText();
         }
 #endif
+#ifdef ANDROID_CSS_RING
+        case CSSPropertyWebkitRing: {
+            const int properties[9] = { CSSPropertyWebkitRingFillColor,
+                                        CSSPropertyWebkitRingInnerWidth,
+                                        CSSPropertyWebkitRingOuterWidth,
+                                        CSSPropertyWebkitRingOutset,
+                                        CSSPropertyWebkitRingPressedInnerColor,
+                                        CSSPropertyWebkitRingPressedOuterColor,
+                                        CSSPropertyWebkitRingRadius,
+                                        CSSPropertyWebkitRingSelectedInnerColor,
+                                        CSSPropertyWebkitRingSelectedOuterColor };
+            return getLayeredShorthandValue(properties, 9);
+        }
+#endif
     }
     return String();
 }
diff --git a/Source/WebCore/css/CSSParser.cpp b/Source/WebCore/css/CSSParser.cpp
index 06e895d..831e438 100644
--- a/Source/WebCore/css/CSSParser.cpp
+++ b/Source/WebCore/css/CSSParser.cpp
@@ -92,6 +92,10 @@
 using namespace std;
 using namespace WTF;
 
+#ifdef ANDROID_INSTRUMENT
+#include "TimeCounter.h"
+#endif
+
 namespace WebCore {
 
 static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
@@ -226,6 +230,9 @@
 
 void CSSParser::parseSheet(CSSStyleSheet* sheet, const String& string, int startLineNumber, StyleRuleRangeMap* ruleRangeMap)
 {
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter);
+#endif
     setStyleSheet(sheet);
     m_defaultNamespace = starAtom; // Reset the default namespace.
     m_ruleRangeMap = ruleRangeMap;
@@ -240,22 +247,37 @@
     m_ruleRangeMap = 0;
     m_currentRuleData = 0;
     m_rule = 0;
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::record(android::TimeCounter::CSSParseTimeCounter, __FUNCTION__);
+#endif
 }
 
 PassRefPtr<CSSRule> CSSParser::parseRule(CSSStyleSheet* sheet, const String& string)
 {
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter);
+#endif
     setStyleSheet(sheet);
     m_allowNamespaceDeclarations = false;
     setupParser("@-webkit-rule{", string, "} ");
     cssyyparse(this);
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::record(android::TimeCounter::CSSParseTimeCounter, __FUNCTION__);
+#endif
     return m_rule.release();
 }
 
 PassRefPtr<CSSRule> CSSParser::parseKeyframeRule(CSSStyleSheet *sheet, const String &string)
 {
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter);
+#endif
     setStyleSheet(sheet);
     setupParser("@-webkit-keyframe-rule{ ", string, "} ");
     cssyyparse(this);
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::record(android::TimeCounter::CSSParseTimeCounter, __FUNCTION__);
+#endif
     return m_keyframe.release();
 }
 
@@ -418,6 +440,9 @@
 
 bool CSSParser::parseValue(CSSMutableStyleDeclaration* declaration, int propertyId, const String& string, bool important)
 {
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter);
+#endif
     ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet());
     setStyleSheet(static_cast<CSSStyleSheet*>(declaration->stylesheet()));
 
@@ -439,6 +464,9 @@
         clearProperties();
     }
 
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::record(android::TimeCounter::CSSParseTimeCounter, __FUNCTION__);
+#endif
     return ok;
 }
 
@@ -471,6 +499,9 @@
 
 bool CSSParser::parseColor(CSSMutableStyleDeclaration* declaration, const String& string)
 {
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter);
+#endif
     ASSERT(!declaration->stylesheet() || declaration->stylesheet()->isCSSStyleSheet());
     setStyleSheet(static_cast<CSSStyleSheet*>(declaration->stylesheet()));
 
@@ -478,6 +509,9 @@
     cssyyparse(this);
     m_rule = 0;
 
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::record(android::TimeCounter::CSSParseTimeCounter, __FUNCTION__);
+#endif
     return (m_numParsedProperties && m_parsedProperties[0]->m_id == CSSPropertyColor);
 }
 
@@ -499,6 +533,9 @@
 
 void CSSParser::parseSelector(const String& string, Document* doc, CSSSelectorList& selectorList)
 {
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter);
+#endif
     RefPtr<CSSStyleSheet> dummyStyleSheet = CSSStyleSheet::create(doc);
 
     setStyleSheet(dummyStyleSheet.get());
@@ -512,10 +549,18 @@
 
     // The style sheet will be deleted right away, so it won't outlive the document.
     ASSERT(dummyStyleSheet->hasOneRef());
+
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::record(android::TimeCounter::CSSParseTimeCounter, __FUNCTION__);
+#endif
 }
 
 bool CSSParser::parseDeclaration(CSSMutableStyleDeclaration* declaration, const String& string, RefPtr<CSSStyleSourceData>* styleSourceData)
 {
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter);
+#endif
+
     // Length of the "@-webkit-decls{" prefix.
     static const unsigned prefixLength = 15;
 
@@ -554,6 +599,9 @@
         m_currentRuleData = 0;
         m_inStyleRuleOrDeclaration = false;
     }
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::record(android::TimeCounter::CSSParseTimeCounter, __FUNCTION__);
+#endif
     return ok;
 }
 
@@ -562,6 +610,9 @@
     if (string.isEmpty())
         return true;
 
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::start(android::TimeCounter::CSSParseTimeCounter);
+#endif
     ASSERT(!m_mediaQuery);
 
     // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
@@ -575,6 +626,9 @@
         queries->appendMediaQuery(m_mediaQuery.release());
     }
 
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::record(android::TimeCounter::CSSParseTimeCounter, __FUNCTION__);
+#endif
     return ok;
 }
 
@@ -1962,6 +2016,7 @@
     case CSSPropertyTextOverline:
     case CSSPropertyTextUnderline:
         return false;
+
 #if ENABLE(WCSS)
     case CSSPropertyWapInputFormat:
         validPrimitive = true;
@@ -2008,6 +2063,36 @@
             return parseLineBoxContain(important);
         break;
 
+#ifdef ANDROID_CSS_RING
+    case CSSPropertyWebkitRing:
+    {
+        const int properties[9] = { CSSPropertyWebkitRingFillColor,
+                                    CSSPropertyWebkitRingInnerWidth,
+                                    CSSPropertyWebkitRingOuterWidth,
+                                    CSSPropertyWebkitRingOutset,
+                                    CSSPropertyWebkitRingPressedInnerColor,
+                                    CSSPropertyWebkitRingPressedOuterColor,
+                                    CSSPropertyWebkitRingRadius,
+                                    CSSPropertyWebkitRingSelectedInnerColor,
+                                    CSSPropertyWebkitRingSelectedOuterColor };
+        return parseShorthand(propId, properties, 9, important);
+    }
+    case CSSPropertyWebkitRingFillColor:
+    case CSSPropertyWebkitRingPressedInnerColor:
+    case CSSPropertyWebkitRingPressedOuterColor:
+    case CSSPropertyWebkitRingSelectedInnerColor:
+    case CSSPropertyWebkitRingSelectedOuterColor:
+        parsedValue = parseColor();
+        if (parsedValue)
+            m_valueList->next();
+        break;
+    case CSSPropertyWebkitRingInnerWidth:
+    case CSSPropertyWebkitRingOuterWidth:
+    case CSSPropertyWebkitRingOutset:
+    case CSSPropertyWebkitRingRadius:
+        validPrimitive = validUnit(value, FLength | FNonNeg, m_strict);
+        break;
+#endif
 #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
     case CSSPropertyWebkitTapHighlightColor:
         parsedValue = parseColor();
@@ -5383,8 +5468,6 @@
     // parseFillPosition advances the args next pointer.
     parseFillPosition(args, centerX, centerY);
     a = args->current();
-    if (!a)
-        return false;
     
     if (centerX || centerY) {
         // Comma
diff --git a/Source/WebCore/css/CSSPrimitiveValue.cpp b/Source/WebCore/css/CSSPrimitiveValue.cpp
index 237844e..04f1089 100644
--- a/Source/WebCore/css/CSSPrimitiveValue.cpp
+++ b/Source/WebCore/css/CSSPrimitiveValue.cpp
@@ -316,8 +316,7 @@
             break;
         case CSS_REMS:
             applyZoomMultiplier = false;
-            if (rootStyle)
-                factor = computingFontSize ? rootStyle->fontDescription().specifiedSize() : rootStyle->fontDescription().computedSize();
+            factor = computingFontSize ? rootStyle->fontDescription().specifiedSize() : rootStyle->fontDescription().computedSize();
             break;
         case CSS_PX:
             break;
diff --git a/Source/WebCore/css/CSSPropertyNames.in b/Source/WebCore/css/CSSPropertyNames.in
index 395b7cf..a62d2f3 100644
--- a/Source/WebCore/css/CSSPropertyNames.in
+++ b/Source/WebCore/css/CSSPropertyNames.in
@@ -306,4 +306,3 @@
 -webkit-user-drag
 -webkit-user-modify
 -webkit-user-select
--webkit-overflow-scrolling
diff --git a/Source/WebCore/css/CSSSegmentedFontFace.cpp b/Source/WebCore/css/CSSSegmentedFontFace.cpp
index 6303ff8..1f6e20d 100644
--- a/Source/WebCore/css/CSSSegmentedFontFace.cpp
+++ b/Source/WebCore/css/CSSSegmentedFontFace.cpp
@@ -52,11 +52,10 @@
     // Make sure the glyph page tree prunes out all uses of this custom font.
     if (m_fontDataTable.isEmpty())
         return;
-
     HashMap<unsigned, SegmentedFontData*>::iterator end = m_fontDataTable.end();
     for (HashMap<unsigned, SegmentedFontData*>::iterator it = m_fontDataTable.begin(); it != end; ++it)
-        m_fontSelector->retireCustomFont(it->second);
-
+        GlyphPageTreeNode::pruneTreeCustomFontData(it->second);
+    deleteAllValues(m_fontDataTable);
     m_fontDataTable.clear();
 }
 
diff --git a/Source/WebCore/css/CSSStyleDeclaration.cpp b/Source/WebCore/css/CSSStyleDeclaration.cpp
index d4acc2a..1c465e5 100644
--- a/Source/WebCore/css/CSSStyleDeclaration.cpp
+++ b/Source/WebCore/css/CSSStyleDeclaration.cpp
@@ -27,7 +27,6 @@
 #include "CSSPropertyNames.h"
 #include "CSSRule.h"
 #include <wtf/ASCIICType.h>
-#include <wtf/text/CString.h>
 
 using namespace WTF;
 
diff --git a/Source/WebCore/css/CSSStyleSelector.cpp b/Source/WebCore/css/CSSStyleSelector.cpp
index d81cc9d..b79f2dc 100644
--- a/Source/WebCore/css/CSSStyleSelector.cpp
+++ b/Source/WebCore/css/CSSStyleSelector.cpp
@@ -1194,8 +1194,7 @@
     documentStyle->setVisuallyOrdered(document->visuallyOrdered());
     documentStyle->setZoom(frame ? frame->pageZoomFactor() : 1);
     documentStyle->setPageScaleTransform(frame ? frame->pageScaleFactor() : 1);
-    documentStyle->setUserModify(document->inDesignMode() ? READ_WRITE : READ_ONLY);
-
+    
     Element* docElement = document->documentElement();
     RenderObject* docElementRenderer = docElement ? docElement->renderer() : 0;
     if (docElementRenderer) {
@@ -1285,11 +1284,8 @@
 
     if (m_parentStyle)
         m_style->inheritFrom(m_parentStyle);
-    else {
+    else
         m_parentStyle = style();
-        // Make sure our fonts are initialized if we don't inherit them from our parent style.
-        m_style->font().update(0);
-    }
 
     if (e->isLink()) {
         m_style->setIsLink(true);
@@ -4970,11 +4966,6 @@
             applyProperty(CSSPropertyFontStyle, font->style.get());
             applyProperty(CSSPropertyFontVariant, font->variant.get());
             applyProperty(CSSPropertyFontWeight, font->weight.get());
-            // The previous properties can dirty our font but they don't try to read the font's
-            // properties back, which is safe. However if font-size is using the 'ex' unit, it will
-            // need query the dirtied font's x-height to get the computed size. To be safe in this
-            // case, let's just update the font now.
-            updateFont();
             applyProperty(CSSPropertyFontSize, font->size.get());
 
             m_lineHeightValue = font->lineHeight.get();
@@ -6063,6 +6054,138 @@
         ASSERT_NOT_REACHED();
         return;
 
+#ifdef ANDROID_CSS_RING
+    case CSSPropertyWebkitRing:
+        if (valueType != CSSValue::CSS_INHERIT || !m_parentNode) return;
+        m_style->setRingFillColor(m_parentStyle->ringFillColor());
+        m_style->setRingInnerWidth(m_parentStyle->ringInnerWidth());
+        m_style->setRingOuterWidth(m_parentStyle->ringOuterWidth());
+        m_style->setRingOutset(m_parentStyle->ringOutset());
+        m_style->setRingPressedInnerColor(m_parentStyle->ringPressedInnerColor());
+        m_style->setRingPressedOuterColor(m_parentStyle->ringPressedOuterColor());
+        m_style->setRingRadius(m_parentStyle->ringRadius());
+        m_style->setRingSelectedInnerColor(m_parentStyle->ringSelectedInnerColor());
+        m_style->setRingSelectedOuterColor(m_parentStyle->ringSelectedOuterColor());
+        return;
+    case CSSPropertyWebkitRingFillColor: {
+        HANDLE_INHERIT_AND_INITIAL(ringFillColor, RingFillColor);
+        if (!primitiveValue)
+            break;
+        Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite();
+        m_style->setRingFillColor(col);
+        return;
+    }
+    case CSSPropertyWebkitRingInnerWidth: {
+        HANDLE_INHERIT_AND_INITIAL(ringInnerWidth, RingInnerWidth)
+        if (!primitiveValue)
+            break;
+        Length l;
+        int type = primitiveValue->primitiveType();
+        if (CSSPrimitiveValue::isUnitTypeLength(type)) {
+            // width can be specified with fractional px
+            // scale by 16 here (and unscale in android_graphics) to keep
+            // 4 bits of fraction
+            RefPtr<CSSPrimitiveValue> scaledValue = CSSPrimitiveValue::create(
+                primitiveValue->getFloatValue() * 16,
+                (CSSPrimitiveValue::UnitTypes) type);
+            l = Length(scaledValue->computeLengthIntForLength(style(),
+                m_rootElementStyle, zoomFactor), Fixed);
+            scaledValue.release();
+        } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
+            l = Length(primitiveValue->getDoubleValue(), Percent);
+        else
+            return;
+        m_style->setRingInnerWidth(l);
+        return;
+    }
+    case CSSPropertyWebkitRingOuterWidth: {
+        HANDLE_INHERIT_AND_INITIAL(ringOuterWidth, RingOuterWidth)
+        if (!primitiveValue)
+            break;
+        Length l;
+        int type = primitiveValue->primitiveType();
+        if (CSSPrimitiveValue::isUnitTypeLength(type)) {
+            // width can be specified with fractional px
+            // scale by 16 here (and unscale in android_graphics) to keep
+            // 4 bits of fraction
+            RefPtr<CSSPrimitiveValue> scaledValue = CSSPrimitiveValue::create(
+                primitiveValue->getFloatValue() * 16,
+                (CSSPrimitiveValue::UnitTypes) type);
+            l = Length(scaledValue->computeLengthIntForLength(style(),
+                m_rootElementStyle, zoomFactor), Fixed);
+            scaledValue.release();
+        } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
+            l = Length(primitiveValue->getDoubleValue(), Percent);
+        else
+            return;
+        m_style->setRingOuterWidth(l);
+        return;
+    }
+    case CSSPropertyWebkitRingOutset: {
+        HANDLE_INHERIT_AND_INITIAL(ringOutset, RingOutset)
+        if (!primitiveValue)
+            break;
+        Length l;
+        int type = primitiveValue->primitiveType();
+        if (CSSPrimitiveValue::isUnitTypeLength(type))
+            l = Length(primitiveValue->computeLengthIntForLength(style(),
+                m_rootElementStyle, zoomFactor), Fixed);
+        else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
+            l = Length(primitiveValue->getDoubleValue(), Percent);
+        else
+            return;
+        m_style->setRingOutset(l);
+        return;
+    }
+    case CSSPropertyWebkitRingPressedInnerColor: {
+        HANDLE_INHERIT_AND_INITIAL(ringPressedInnerColor, RingPressedInnerColor);
+        if (!primitiveValue)
+            break;
+        Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite();
+        m_style->setRingPressedInnerColor(col);
+        return;
+    }
+    case CSSPropertyWebkitRingPressedOuterColor: {
+        HANDLE_INHERIT_AND_INITIAL(ringPressedOuterColor, RingPressedOuterColor);
+        if (!primitiveValue)
+            break;
+        Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite();
+        m_style->setRingPressedOuterColor(col);
+        return;
+    }
+    case CSSPropertyWebkitRingRadius: {
+        HANDLE_INHERIT_AND_INITIAL(ringRadius, RingRadius)
+        if (!primitiveValue)
+            break;
+        Length l;
+        int type = primitiveValue->primitiveType();
+        if (CSSPrimitiveValue::isUnitTypeLength(type))
+            l = Length(primitiveValue->computeLengthIntForLength(style(),
+                m_rootElementStyle, zoomFactor), Fixed);
+        else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
+            l = Length(primitiveValue->getDoubleValue(), Percent);
+        else
+            return;
+        m_style->setRingRadius(l);
+        return;
+    }
+    case CSSPropertyWebkitRingSelectedInnerColor: {
+        HANDLE_INHERIT_AND_INITIAL(ringSelectedInnerColor, RingSelectedInnerColor);
+        if (!primitiveValue)
+            break;
+        Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite();
+        m_style->setRingSelectedInnerColor(col);
+        return;
+    }
+    case CSSPropertyWebkitRingSelectedOuterColor: {
+        HANDLE_INHERIT_AND_INITIAL(ringSelectedOuterColor, RingSelectedOuterColor);
+        if (!primitiveValue)
+            break;
+        Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite();
+        m_style->setRingSelectedOuterColor(col);
+        return;
+    }
+#endif
 #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
     case CSSPropertyWebkitTapHighlightColor: {
         HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor);
diff --git a/Source/WebCore/css/CSSValueKeywords.in b/Source/WebCore/css/CSSValueKeywords.in
index 5b6e5b0..6dac06f 100644
--- a/Source/WebCore/css/CSSValueKeywords.in
+++ b/Source/WebCore/css/CSSValueKeywords.in
@@ -756,10 +756,6 @@
 manual
 # auto
 
-# -webkit-overflow-scrolling
-# auto
-touch
-
 # -webkit-writing-mode
 # SVG compatibility
 lr
diff --git a/Source/WebCore/css/StyleBase.cpp b/Source/WebCore/css/StyleBase.cpp
index 93dbda0..5d9d79d 100644
--- a/Source/WebCore/css/StyleBase.cpp
+++ b/Source/WebCore/css/StyleBase.cpp
@@ -65,4 +65,37 @@
     return sheet->ownerNode()->document()->baseURL();
 }
 
+#ifdef ANDROID_INSTRUMENT
+static size_t styleSize = 0;
+
+void* StyleBase::operator new(size_t size)
+{
+    styleSize += size;
+    return ::operator new(size);
+}
+
+void* StyleBase::operator new[](size_t size)
+{
+    styleSize += size;
+    return ::operator new[](size);
+}
+
+void StyleBase::operator delete(void* p, size_t size)
+{
+    styleSize -= size;
+    ::operator delete(p);
+}
+
+void StyleBase::operator delete[](void* p, size_t size)
+{
+    styleSize -= size;
+    ::operator delete[](p);
+}
+
+size_t StyleBase::reportStyleSize()
+{
+    return styleSize;
+}
+#endif
+
 }
diff --git a/Source/WebCore/css/StyleBase.h b/Source/WebCore/css/StyleBase.h
index 63c671e..94efa01 100644
--- a/Source/WebCore/css/StyleBase.h
+++ b/Source/WebCore/css/StyleBase.h
@@ -72,6 +72,18 @@
 
         StyleSheet* stylesheet();
 
+#ifdef ANDROID_INSTRUMENT
+        // Overridden to prevent the normal new from being called.
+        void* operator new(size_t size);
+        void* operator new[](size_t size);
+
+        // Overridden to prevent the normal delete from being called.
+        void operator delete(void* p, size_t size);
+        void operator delete[](void* p, size_t size);
+
+        static size_t reportStyleSize();
+#endif
+
     protected:
         StyleBase(StyleBase* parent)
             : m_parent(parent)
diff --git a/Source/WebCore/css/WebKitCSSKeyframesRule.cpp b/Source/WebCore/css/WebKitCSSKeyframesRule.cpp
index 497bd19..3b41f43 100644
--- a/Source/WebCore/css/WebKitCSSKeyframesRule.cpp
+++ b/Source/WebCore/css/WebKitCSSKeyframesRule.cpp
@@ -66,8 +66,7 @@
     
     // Since the name is used in the keyframe map list in CSSStyleSelector, we need
     // to recompute the style sheet to get the updated name.
-    if (stylesheet())
-        stylesheet()->styleSheetChanged();
+    stylesheet()->styleSheetChanged();
 }
 
 unsigned WebKitCSSKeyframesRule::length() const
diff --git a/Source/WebCore/css/mediaControlsAndroid.css b/Source/WebCore/css/mediaControlsAndroid.css
index 614c92f..77f8b08 100644
--- a/Source/WebCore/css/mediaControlsAndroid.css
+++ b/Source/WebCore/css/mediaControlsAndroid.css
@@ -49,7 +49,10 @@
 }
 
 audio::-webkit-media-controls-mute-button, video::-webkit-media-controls-mute-button {
-    display: none;
+    -webkit-appearance: media-mute-button;
+    display: -webkit-box;
+    width: 48px;
+    height: 48px;
 }
 
 audio::-webkit-media-controls-play-button, video::-webkit-media-controls-play-button {
diff --git a/Source/WebCore/dom/DOMTextContentWalker.cpp b/Source/WebCore/dom/DOMTextContentWalker.cpp
deleted file mode 100644
index 5e77db1..0000000
--- a/Source/WebCore/dom/DOMTextContentWalker.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "DOMTextContentWalker.h"
-
-#if OS(ANDROID)
-
-#include "Range.h"
-#include "TextIterator.h"
-#include "VisiblePosition.h"
-#include "VisibleSelection.h"
-#include "visible_units.h"
-
-namespace WebCore {
-
-static PassRefPtr<Range> getRange(const Position& start, const Position& end)
-{
-    return VisibleSelection(start.parentAnchoredEquivalent(), end.parentAnchoredEquivalent(), DOWNSTREAM).firstRange();
-}
-
-DOMTextContentWalker::DOMTextContentWalker(const VisiblePosition& position, unsigned maxLength)
-    : m_hitOffsetInContent(0)
-{
-    const unsigned halfMaxLength = maxLength / 2;
-    RefPtr<Range> forwardRange = makeRange(position, endOfDocument(position));
-    if (!forwardRange)
-        return;
-    CharacterIterator forwardChar(forwardRange.get(), TextIteratorStopsOnFormControls);
-    forwardChar.advance(maxLength - halfMaxLength);
-
-    // No forward contents, started inside form control.
-    if (getRange(position.deepEquivalent(), forwardChar.range()->startPosition())->text().length() == 0)
-        return;
-
-    RefPtr<Range> backwardsRange = makeRange(startOfDocument(position), position);
-    if (!backwardsRange)
-        return;
-    BackwardsCharacterIterator backwardsChar(backwardsRange.get(), TextIteratorStopsOnFormControls);
-    backwardsChar.advance(halfMaxLength);
-
-    m_hitOffsetInContent = getRange(backwardsChar.range()->endPosition(), position.deepEquivalent())->text().length();
-    m_contentRange = getRange(backwardsChar.range()->endPosition(), forwardChar.range()->startPosition());
-}
-
-PassRefPtr<Range> DOMTextContentWalker::contentOffsetsToRange(unsigned startInContent, unsigned endInContent)
-{
-    if (startInContent >= endInContent || endInContent > content().length())
-        return 0;
-
-    CharacterIterator iterator(m_contentRange.get());
-    iterator.advance(startInContent);
-
-    Position start = iterator.range()->startPosition();
-    iterator.advance(endInContent - startInContent);
-    Position end = iterator.range()->startPosition();
-    return getRange(start, end);
-}
-
-String DOMTextContentWalker::content() const
-{
-    if (m_contentRange)
-        return m_contentRange->text();
-    return String();
-}
-
-unsigned DOMTextContentWalker::hitOffsetInContent() const
-{
-    return m_hitOffsetInContent;
-}
-
-} // namespace WebCore
-
-#endif // OS(ANDROID)
diff --git a/Source/WebCore/dom/DOMTextContentWalker.h b/Source/WebCore/dom/DOMTextContentWalker.h
deleted file mode 100644
index 0d4259b..0000000
--- a/Source/WebCore/dom/DOMTextContentWalker.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DOMTextContentWalker_h
-#define DOMTextContentWalker_h
-
-#if OS(ANDROID)
-
-#include "PlatformString.h"
-
-namespace WebCore {
-
-class Range;
-class VisiblePosition;
-
-// Explore the DOM tree to find the text contents up to a limit
-// around a position in a given text node.
-class DOMTextContentWalker {
-  WTF_MAKE_NONCOPYABLE(DOMTextContentWalker);
-public:
-  DOMTextContentWalker(const VisiblePosition& position, unsigned maxLength);
-
-  String content() const;
-  unsigned hitOffsetInContent() const;
-
-  // Convert start/end positions in the content text string into a text range.
-  PassRefPtr<Range> contentOffsetsToRange(unsigned startInContent, unsigned endInContent);
-
-private:
-  RefPtr<Range> m_contentRange;
-  size_t m_hitOffsetInContent;
-};
-
-} // namespace WebCore
-
-#endif // OS(ANDROID)
-
-#endif // DOMTextContentWalker_h
-
diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp
index b6a1393..6e21dc3 100644
--- a/Source/WebCore/dom/Document.cpp
+++ b/Source/WebCore/dom/Document.cpp
@@ -189,6 +189,15 @@
 #include "Settings.h"
 #endif
 
+#ifdef ANDROID_RESET_SELECTION
+#include "CacheBuilder.h"
+#include "HTMLTextAreaElement.h"
+#endif
+
+#ifdef ANDROID_INSTRUMENT
+#include "TimeCounter.h"
+#endif
+
 #if ENABLE(TOUCH_EVENTS)
 #if USE(V8)
 #include "RuntimeEnabledFeatures.h"
@@ -561,8 +570,6 @@
             (*m_pageGroupUserSheets)[i]->clearOwnerNode();
     }
 
-    deleteRetiredCustomFonts();
-
     m_weakReference->clear();
 
     if (m_mediaQueryMatcher)
@@ -1468,6 +1475,10 @@
         frameView->beginDeferredRepaints();
     }
 
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::start(android::TimeCounter::CalculateStyleTimeCounter);
+#endif
+
     ASSERT(!renderer() || renderArena());
     if (!renderer() || !renderArena())
         goto bail_out;
@@ -1489,14 +1500,9 @@
         if (change >= Inherit || n->childNeedsStyleRecalc() || n->needsStyleRecalc())
             n->recalcStyle(change);
 
-    // FIXME: Disabling the deletion of retired custom font data until
-    // we fix all the stale style bugs (68804, 68624, etc). These bugs
-    // indicate problems where some styles were not updated in recalcStyle,
-    // thereby retaining stale copy of font data. To prevent that, we
-    // disable this code for now and only delete retired custom font data
-    // in Document destructor.
-    // Now that all RenderStyles that pointed to retired fonts have been updated, the fonts can safely be deleted.
-    // deleteRetiredCustomFonts();
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::record(android::TimeCounter::CalculateStyleTimeCounter, __FUNCTION__);
+#endif
 
 #if USE(ACCELERATED_COMPOSITING)
     if (view()) {
@@ -1634,20 +1640,6 @@
     return style.release();
 }
 
-void Document::retireCustomFont(FontData* fontData)
-{
-    m_retiredCustomFonts.append(adoptPtr(fontData));
-}
-
-void Document::deleteRetiredCustomFonts()
-{
-    size_t size = m_retiredCustomFonts.size();
-    for (size_t i = 0; i < size; ++i)
-        GlyphPageTreeNode::pruneTreeCustomFontData(m_retiredCustomFonts[i].get());
-
-    m_retiredCustomFonts.clear();
-}
-
 bool Document::isPageBoxVisible(int pageIndex)
 {
     RefPtr<RenderStyle> style = styleForPage(pageIndex);
@@ -2737,8 +2729,8 @@
 #ifdef ANDROID_META_SUPPORT
         if (frame())
             frame()->settings()->setMetadataSettings(keyString, valueString);
-        if (callback && data)
 #endif
+        if (callback && data)
             callback(keyString, valueString, this, data);
     }
 }
@@ -4108,8 +4100,6 @@
 void Document::setDesignMode(InheritedBool value)
 {
     m_designMode = value;
-    for (Frame* frame = m_frame; frame && frame->document(); frame = frame->tree()->traverseNext(m_frame))
-        frame->document()->scheduleForcedStyleRecalc();
 }
 
 Document::InheritedBool Document::getDesignMode() const
@@ -5064,9 +5054,15 @@
     // http://developer.apple.com/library/safari/#documentation/UserExperience/Reference/DocumentAdditionsReference/DocumentAdditions/DocumentAdditions.html
     // when this method should throw and nor is it by inspection of iOS behavior. It would be nice to verify any cases where it throws under iOS
     // and implement them here. See https://bugs.webkit.org/show_bug.cgi?id=47819
+    // Ditto for the createTouchList method below.
     Frame* frame = window ? window->frame() : this->frame();
     return Touch::create(frame, target, identifier, screenX, screenY, pageX, pageY);
 }
+
+PassRefPtr<TouchList> Document::createTouchList(ExceptionCode&) const
+{
+    return TouchList::create();
+}
 #endif
 
 DocumentLoader* Document::loader() const
diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h
index ce82b2e..7478e6c 100644
--- a/Source/WebCore/dom/Document.h
+++ b/Source/WebCore/dom/Document.h
@@ -76,7 +76,6 @@
 class Event;
 class EventListener;
 class EventQueue;
-class FontData;
 class FormAssociatedElement;
 class Frame;
 class FrameView;
@@ -527,8 +526,6 @@
     PassRefPtr<RenderStyle> styleForElementIgnoringPendingStylesheets(Element*);
     PassRefPtr<RenderStyle> styleForPage(int pageIndex);
 
-    void retireCustomFont(FontData*);
-
     // Returns true if page box (margin boxes and page borders) is visible.
     bool isPageBoxVisible(int pageIndex);
 
@@ -1085,6 +1082,7 @@
 
 #if ENABLE(TOUCH_EVENTS)
     PassRefPtr<Touch> createTouch(DOMWindow*, EventTarget*, int identifier, int pageX, int pageY, int screenX, int screenY, ExceptionCode&) const;
+    PassRefPtr<TouchList> createTouchList(ExceptionCode&) const;
 #endif
 
     const DocumentTiming* timing() const { return &m_documentTiming; }
@@ -1144,8 +1142,6 @@
 
     void createStyleSelector();
 
-    void deleteRetiredCustomFonts();
-
     PassRefPtr<NodeList> handleZeroPadding(const HitTestRequest&, HitTestResult&) const;
 
     void loadEventDelayTimerFired(Timer<Document>*);
@@ -1155,8 +1151,7 @@
     OwnPtr<CSSStyleSelector> m_styleSelector;
     bool m_didCalculateStyleSelector;
     bool m_hasDirtyStyleSelector;
-    Vector<OwnPtr<FontData> > m_retiredCustomFonts;
-
+    
     mutable RefPtr<CSSPrimitiveValueCache> m_cssPrimitiveValueCache;
 
     Frame* m_frame;
diff --git a/Source/WebCore/dom/Event.h b/Source/WebCore/dom/Event.h
index e913745..f6e5586 100644
--- a/Source/WebCore/dom/Event.h
+++ b/Source/WebCore/dom/Event.h
@@ -136,10 +136,6 @@
         virtual bool isErrorEvent() const;
 #if ENABLE(TOUCH_EVENTS)
         virtual bool isTouchEvent() const;
-#if PLATFORM(ANDROID)
-        virtual bool hitTouchHandler() const { return false; }
-        virtual void setHitTouchHandler() { }
-#endif
 #endif
 #if ENABLE(DEVICE_ORIENTATION)
         virtual bool isDeviceMotionEvent() const;
diff --git a/Source/WebCore/dom/EventTarget.cpp b/Source/WebCore/dom/EventTarget.cpp
index c9cece2..d84d66b 100644
--- a/Source/WebCore/dom/EventTarget.cpp
+++ b/Source/WebCore/dom/EventTarget.cpp
@@ -326,16 +326,6 @@
     EventListenerMap::iterator result = d->eventListenerMap.find(event->type());
     if (result != d->eventListenerMap.end())
         fireEventListeners(event, d, *result->second);
-
-#if ENABLE(TOUCH_EVENTS) && PLATFORM(ANDROID)
-    if (event->isTouchEvent() && !event->hitTouchHandler()) {
-        // Check for touchmove or touchend to see if we can skip
-        // the rest of the stream (we always get touchstart, don't need to check that)
-        if (d->eventListenerMap.contains(eventNames().touchmoveEvent)
-                || d->eventListenerMap.contains(eventNames().touchendEvent))
-            event->setHitTouchHandler();
-    }
-#endif
     
     return !event->defaultPrevented();
 }
@@ -344,11 +334,6 @@
 {
     RefPtr<EventTarget> protect = this;
 
-#if ENABLE(TOUCH_EVENTS) && PLATFORM(ANDROID)
-    if (event->isTouchEvent())
-        event->setHitTouchHandler();
-#endif
-
     // Fire all listeners registered for this event. Don't fire listeners removed
     // during event dispatch. Also, don't fire event listeners added during event
     // dispatch. Conveniently, all new event listeners will be added after 'end',
diff --git a/Source/WebCore/dom/Node.cpp b/Source/WebCore/dom/Node.cpp
index da4312c..1fd4b92 100644
--- a/Source/WebCore/dom/Node.cpp
+++ b/Source/WebCore/dom/Node.cpp
@@ -770,7 +770,7 @@
 
 bool Node::rendererIsEditable(EditableLevel editableLevel) const
 {
-    if (document()->frame() && document()->frame()->page() && document()->frame()->page()->isEditable())
+    if (document()->inDesignMode() || (document()->frame() && document()->frame()->page() && document()->frame()->page()->isEditable()))
         return true;
 
     // Ideally we'd call ASSERT(!needsStyleRecalc()) here, but
@@ -1614,7 +1614,7 @@
 }
 #endif
 
-Node* Node::shadowAncestorNode() const
+Node* Node::shadowAncestorNode()
 {
 #if ENABLE(SVG)
     // SVG elements living in a shadow tree only occur when <use> created them.
@@ -1622,18 +1622,18 @@
     // but the actual shadow tree element - as main difference to the HTML forms
     // shadow tree concept. (This function _could_ be made virtual - opinions?)
     if (isSVGElement())
-        return const_cast<Node*>(this);
+        return this;
 #endif
 
     Node* root = shadowTreeRootNode();
     if (root)
         return root->shadowHost();
-    return const_cast<Node*>(this);
+    return this;
 }
 
-Node* Node::shadowTreeRootNode() const
+Node* Node::shadowTreeRootNode()
 {
-    Node* root = const_cast<Node*>(this);
+    Node* root = this;
     while (root) {
         if (root->isShadowRoot() || root->isSVGShadowRoot())
             return root;
@@ -2498,6 +2498,39 @@
     return 0;
 }
 
+#ifdef ANDROID_INSTRUMENT
+static size_t nodeSize = 0;
+
+void* Node::operator new(size_t size)
+{
+    nodeSize += size;
+    return ::operator new(size);
+}
+
+void* Node::operator new[](size_t size)
+{
+    nodeSize += size;
+    return ::operator new[](size);
+}
+
+void Node::operator delete(void* p, size_t size)
+{
+    nodeSize -= size;
+    ::operator delete(p);
+}
+
+void Node::operator delete[](void* p, size_t size)
+{
+    nodeSize -= size;
+    ::operator delete[](p);
+}
+
+size_t Node::reportDOMNodesSize()
+{
+    return nodeSize;
+}
+#endif
+
 // --------
 
 ScriptExecutionContext* Node::scriptExecutionContext() const
diff --git a/Source/WebCore/dom/Node.h b/Source/WebCore/dom/Node.h
index 76355c3..1fe30ad 100644
--- a/Source/WebCore/dom/Node.h
+++ b/Source/WebCore/dom/Node.h
@@ -218,8 +218,8 @@
     virtual bool isShadowBoundary() const { return false; }
     virtual bool canHaveLightChildRendererWithShadow() const { return false; }
 
-    Node* shadowAncestorNode() const;
-    Node* shadowTreeRootNode() const;
+    Node* shadowAncestorNode();
+    Node* shadowTreeRootNode();
     bool isInShadowTree();
     // Node's parent, shadow tree host, or SVG use.
     ContainerNode* parentOrHostNode() const;
@@ -528,6 +528,18 @@
 
     unsigned short compareDocumentPosition(Node*);
 
+#ifdef ANDROID_INSTRUMENT
+    // Overridden to prevent the normal new from being called.
+    void* operator new(size_t size);
+    void* operator new[](size_t size);
+
+    // Overridden to prevent the normal delete from being called.
+    void operator delete(void* p, size_t size);
+    void operator delete[](void* p, size_t size);
+
+    static size_t reportDOMNodesSize();
+#endif
+
     virtual Node* toNode() { return this; }
 
     virtual InputElement* toInputElement();
diff --git a/Source/WebCore/dom/ProcessingInstruction.cpp b/Source/WebCore/dom/ProcessingInstruction.cpp
index 30111d8..7135644 100644
--- a/Source/WebCore/dom/ProcessingInstruction.cpp
+++ b/Source/WebCore/dom/ProcessingInstruction.cpp
@@ -297,4 +297,26 @@
     ContainerNode::finishParsingChildren();
 }
 
+#ifdef ANDROID_INSTRUMENT
+void* ProcessingInstruction::operator new(size_t size)
+{
+    return Node::operator new(size);
+}
+
+void* ProcessingInstruction::operator new[](size_t size)
+{
+    return Node::operator new[](size);
+}
+
+void ProcessingInstruction::operator delete(void* p, size_t size)
+{
+    Node::operator delete(p, size);
+}
+
+void ProcessingInstruction::operator delete[](void* p, size_t size)
+{
+    Node::operator delete[](p, size);
+}
+#endif
+
 } // namespace
diff --git a/Source/WebCore/dom/ProcessingInstruction.h b/Source/WebCore/dom/ProcessingInstruction.h
index 1be8710..fd98566 100644
--- a/Source/WebCore/dom/ProcessingInstruction.h
+++ b/Source/WebCore/dom/ProcessingInstruction.h
@@ -56,6 +56,14 @@
 private:
     ProcessingInstruction(Document*, const String& target, const String& data);
 
+#ifdef ANDROID_INSTRUMENT
+    // Overridden to resolve the ambiguous
+    void* operator new(size_t size);
+    void* operator new[](size_t size);
+    void operator delete(void* p, size_t size);
+    void operator delete[](void* p, size_t size);
+#endif
+
     virtual String nodeName() const;
     virtual NodeType nodeType() const;
     virtual String nodeValue() const;
diff --git a/Source/WebCore/dom/Range.cpp b/Source/WebCore/dom/Range.cpp
index 37d0193..469a94a 100644
--- a/Source/WebCore/dom/Range.cpp
+++ b/Source/WebCore/dom/Range.cpp
@@ -51,8 +51,6 @@
 static WTF::RefCountedLeakCounter rangeCounter("Range");
 #endif
 
-typedef Vector<RefPtr<Node> > NodeVector;
-
 inline Range::Range(PassRefPtr<Document> ownerDocument)
     : m_ownerDocument(ownerDocument)
     , m_start(m_ownerDocument)
@@ -623,9 +621,7 @@
 {
     ASSERT(container);
     ASSERT(commonRoot);
-    
-    if (!commonRoot->contains(container))
-        return 0;
+    ASSERT(commonRoot->contains(container));
 
     if (container == commonRoot) {
         container = container->firstChild();
@@ -666,6 +662,8 @@
 
 PassRefPtr<DocumentFragment> Range::processContents(ActionType action, ExceptionCode& ec)
 {
+    typedef Vector<RefPtr<Node> > NodeVector;
+
     RefPtr<DocumentFragment> fragment;
     if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
         fragment = DocumentFragment::create(m_ownerDocument.get());
@@ -676,7 +674,7 @@
     if (ec)
         return 0;
 
-    RefPtr<Node> commonRoot = commonAncestorContainer(ec);
+    Node* commonRoot = commonAncestorContainer(ec);
     if (ec)
         return 0;
     ASSERT(commonRoot);
@@ -687,8 +685,8 @@
     }
 
     // what is the highest node that partially selects the start / end of the range?
-    RefPtr<Node> partialStart = highestAncestorUnderCommonRoot(m_start.container(), commonRoot.get());
-    RefPtr<Node> partialEnd = highestAncestorUnderCommonRoot(m_end.container(), commonRoot.get());
+    Node* partialStart = highestAncestorUnderCommonRoot(m_start.container(), commonRoot);
+    Node* partialEnd = highestAncestorUnderCommonRoot(m_end.container(), commonRoot);
 
     // Start and end containers are different.
     // There are three possibilities here:
@@ -707,32 +705,29 @@
     //
     // These are deleted, cloned, or extracted (i.e. both) depending on action.
 
-    // Note that we are verifying that our common root hierarchy is still intact
-    // after any DOM mutation event, at various stages below. See webkit bug 60350.
-
     RefPtr<Node> leftContents;
-    if (m_start.container() != commonRoot && commonRoot->contains(m_start.container())) {
+    if (m_start.container() != commonRoot) {
         leftContents = processContentsBetweenOffsets(action, 0, m_start.container(), m_start.offset(), lengthOfContentsInNode(m_start.container()), ec);
-        leftContents = processAncestorsAndTheirSiblings(action, m_start.container(), ProcessContentsForward, leftContents, commonRoot.get(), ec);
+        leftContents = processAncestorsAndTheirSiblings(action, m_start.container(), ProcessContentsForward, leftContents, commonRoot, ec);
     }
 
     RefPtr<Node> rightContents;
-    if (m_end.container() != commonRoot && commonRoot->contains(m_end.container())) {
+    if (m_end.container() != commonRoot) {
         rightContents = processContentsBetweenOffsets(action, 0, m_end.container(), 0, m_end.offset(), ec);
-        rightContents = processAncestorsAndTheirSiblings(action, m_end.container(), ProcessContentsBackward, rightContents, commonRoot.get(), ec);
+        rightContents = processAncestorsAndTheirSiblings(action, m_end.container(), ProcessContentsBackward, rightContents, commonRoot, ec);
     }
 
     // delete all children of commonRoot between the start and end container
-    RefPtr<Node> processStart = childOfCommonRootBeforeOffset(m_start.container(), m_start.offset(), commonRoot.get());
-    if (processStart && m_start.container() != commonRoot) // processStart contains nodes before m_start.
+    Node* processStart = childOfCommonRootBeforeOffset(m_start.container(), m_start.offset(), commonRoot);
+    if (m_start.container() != commonRoot) // processStart contains nodes before m_start.
         processStart = processStart->nextSibling();
-    RefPtr<Node> processEnd = childOfCommonRootBeforeOffset(m_end.container(), m_end.offset(), commonRoot.get());
+    Node* processEnd = childOfCommonRootBeforeOffset(m_end.container(), m_end.offset(), commonRoot);
 
     // Collapse the range, making sure that the result is not within a node that was partially selected.
     if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {
-        if (partialStart && commonRoot->contains(partialStart.get()))
+        if (partialStart)
             setStart(partialStart->parentNode(), partialStart->nodeIndex() + 1, ec);
-        else if (partialEnd && commonRoot->contains(partialEnd.get()))
+        else if (partialEnd)
             setStart(partialEnd->parentNode(), partialEnd->nodeIndex(), ec);
         if (ec)
             return 0;
@@ -747,7 +742,7 @@
 
     if (processStart) {
         NodeVector nodes;
-        for (Node* n = processStart.get(); n && n != processEnd; n = n->nextSibling())
+        for (Node* n = processStart; n && n != processEnd; n = n->nextSibling())
             nodes.append(n);
         processNodes(action, nodes, commonRoot, fragment, ec);
     }
@@ -837,7 +832,7 @@
         break;
     }
 
-    return result.release();
+    return result;
 }
 
 void Range::processNodes(ActionType action, Vector<RefPtr<Node> >& nodes, PassRefPtr<Node> oldContainer, PassRefPtr<Node> newContainer, ExceptionCode& ec)
@@ -878,14 +873,9 @@
         // FIXME: This assertion may fail if DOM is modified during mutation event
         // FIXME: Share code with Range::processNodes
         ASSERT(!firstChildInAncestorToProcess || firstChildInAncestorToProcess->parentNode() == ancestor);
-        
-        NodeVector nodes;
-        for (Node* child = firstChildInAncestorToProcess.get(); child;
-            child = (direction == ProcessContentsForward) ? child->nextSibling() : child->previousSibling())
-            nodes.append(child);
-
-        for (NodeVector::const_iterator it = nodes.begin(); it != nodes.end(); it++) {
-            Node* child = it->get();
+        RefPtr<Node> next;
+        for (Node* child = firstChildInAncestorToProcess.get(); child; child = next.get()) {
+            next = direction == ProcessContentsForward ? child->nextSibling() : child->previousSibling();
             switch (action) {
             case DELETE_CONTENTS:
                 ancestor->removeChild(child, ec);
@@ -907,7 +897,7 @@
         firstChildInAncestorToProcess = direction == ProcessContentsForward ? ancestor->nextSibling() : ancestor->previousSibling();
     }
 
-    return clonedContainer.release();
+    return clonedContainer;
 }
 
 PassRefPtr<DocumentFragment> Range::extractContents(ExceptionCode& ec)
diff --git a/Source/WebCore/dom/Text.cpp b/Source/WebCore/dom/Text.cpp
index c4ea0a6..906e421 100644
--- a/Source/WebCore/dom/Text.cpp
+++ b/Source/WebCore/dom/Text.cpp
@@ -31,8 +31,6 @@
 #include "SVGNames.h"
 #endif
 
-#include <wtf/text/CString.h>
-
 #if ENABLE(WML)
 #include "WMLDocument.h"
 #include "WMLVariables.h"
diff --git a/Source/WebCore/dom/TouchEvent.cpp b/Source/WebCore/dom/TouchEvent.cpp
index bd1577d..225e3ae 100644
--- a/Source/WebCore/dom/TouchEvent.cpp
+++ b/Source/WebCore/dom/TouchEvent.cpp
@@ -33,9 +33,6 @@
 
 TouchEvent::TouchEvent()
 {
-#if PLATFORM(ANDROID)
-    m_hitTouchHandler = false;
-#endif
 }
 
 TouchEvent::TouchEvent(TouchList* touches, TouchList* targetTouches,
@@ -48,9 +45,6 @@
     , m_targetTouches(targetTouches)
     , m_changedTouches(changedTouches)
 {
-#if PLATFORM(ANDROID)
-    m_hitTouchHandler = false;
-#endif
 }
 
 TouchEvent::~TouchEvent()
diff --git a/Source/WebCore/dom/TouchEvent.h b/Source/WebCore/dom/TouchEvent.h
index fba613f..1514cf8 100644
--- a/Source/WebCore/dom/TouchEvent.h
+++ b/Source/WebCore/dom/TouchEvent.h
@@ -62,11 +62,6 @@
     TouchList* targetTouches() const { return m_targetTouches.get(); }
     TouchList* changedTouches() const { return m_changedTouches.get(); }
 
-#if PLATFORM(ANDROID)
-    virtual bool hitTouchHandler() const { return m_hitTouchHandler; }
-    virtual void setHitTouchHandler() { m_hitTouchHandler = true; }
-#endif
-
 private:
     TouchEvent();
     TouchEvent(TouchList* touches, TouchList* targetTouches,
@@ -77,10 +72,6 @@
 
     virtual bool isTouchEvent() const { return true; }
 
-#if PLATFORM(ANDROID)
-    bool m_hitTouchHandler;
-#endif
-
     RefPtr<TouchList> m_touches;
     RefPtr<TouchList> m_targetTouches;
     RefPtr<TouchList> m_changedTouches;
diff --git a/Source/WebCore/editing/ApplyStyleCommand.cpp b/Source/WebCore/editing/ApplyStyleCommand.cpp
index 4f1bc93..c9649d0 100644
--- a/Source/WebCore/editing/ApplyStyleCommand.cpp
+++ b/Source/WebCore/editing/ApplyStyleCommand.cpp
@@ -1316,10 +1316,8 @@
     RefPtr<Node> node = startNode;
     while (node) {
         RefPtr<Node> next = node->nextSibling();
-        if (node->isContentEditable()) {
-            removeNode(node);
-            appendNode(node, element);
-        }
+        removeNode(node);
+        appendNode(node, element);
         if (node == endNode)
             break;
         node = next;
diff --git a/Source/WebCore/editing/CompositeEditCommand.cpp b/Source/WebCore/editing/CompositeEditCommand.cpp
index bf515d7..cf2959a 100644
--- a/Source/WebCore/editing/CompositeEditCommand.cpp
+++ b/Source/WebCore/editing/CompositeEditCommand.cpp
@@ -781,7 +781,7 @@
     appendNode(topNode, blockElement);
     RefPtr<Node> lastNode = topNode;
 
-    if (start.deprecatedNode() != outerNode && lastNode->isElementNode()) {
+    if (start.deprecatedNode() != outerNode) {
         Vector<RefPtr<Node> > ancestors;
         
         // Insert each node from innerNode to outerNode (excluded) in a list.
diff --git a/Source/WebCore/editing/InsertIntoTextNodeCommand.cpp b/Source/WebCore/editing/InsertIntoTextNodeCommand.cpp
index bd6fb60..b1a455b 100644
--- a/Source/WebCore/editing/InsertIntoTextNodeCommand.cpp
+++ b/Source/WebCore/editing/InsertIntoTextNodeCommand.cpp
@@ -28,8 +28,6 @@
 
 #include "AXObjectCache.h"
 #include "Text.h"
-#include "RenderText.h"
-#include "Settings.h"
 
 namespace WebCore {
 
@@ -48,13 +46,7 @@
 {
     if (!m_node->rendererIsEditable())
         return;
-
-    if (document()->settings() && document()->settings()->passwordEchoEnabled()) {
-        RenderText* renderText = toRenderText(m_node->renderer());
-        if (renderText && renderText->isSecure())
-            renderText->momentarilyRevealLastTypedCharacter(m_offset + m_text.length() - 1);
-    }
-
+    
     ExceptionCode ec;
     m_node->insertData(m_offset, m_text, ec);
 
diff --git a/Source/WebCore/editing/SelectionController.cpp b/Source/WebCore/editing/SelectionController.cpp
index acae6bf..c5a33d3 100644
--- a/Source/WebCore/editing/SelectionController.cpp
+++ b/Source/WebCore/editing/SelectionController.cpp
@@ -1217,6 +1217,10 @@
 
 void SelectionController::paintCaret(GraphicsContext* context, int tx, int ty, const IntRect& clipRect)
 {
+#ifdef ANDROID_ALLOW_TURNING_OFF_CARET
+    if (m_frame && !android::WebViewCore::getWebViewCore(m_frame->view())->shouldPaintCaret())
+        return;
+#endif
 #if ENABLE(TEXT_CARET)
     if (!m_caretVisible)
         return;
@@ -1588,10 +1592,6 @@
     // We need to update style in case the node containing the selection is made display:none.
     m_frame->document()->updateStyleIfNeeded();
 
-#if PLATFORM(ANDROID)
-    return;
-#endif
-
     RenderView* view = m_frame->contentRenderer();
     if (!view)
         return;
diff --git a/Source/WebCore/editing/TextIterator.cpp b/Source/WebCore/editing/TextIterator.cpp
index 3aa68af..c3be277 100644
--- a/Source/WebCore/editing/TextIterator.cpp
+++ b/Source/WebCore/editing/TextIterator.cpp
@@ -239,20 +239,6 @@
     ASSERT(stack.size() == 1 + depthCrossingShadowBoundaries(node));
 }
 
-#if OS(ANDROID)
-static bool checkFormControlElement(Node* startNode)
-{
-    Node* node = startNode;
-    while (node) {
-        if (node->isElementNode() && static_cast<Element*>(node)->isFormControlElement())
-            return true;
-        node = node->parentNode();
-    }
-    return false;
-}
-#endif
-
-
 // --------
 
 TextIterator::TextIterator()
@@ -272,10 +258,6 @@
     , m_handledFirstLetter(false)
     , m_ignoresStyleVisibility(false)
     , m_emitsObjectReplacementCharacters(false)
-#if OS(ANDROID)
-    , m_stopsOnFormControls(false)
-    , m_shouldStop(false)
-#endif
 {
 }
 
@@ -295,10 +277,6 @@
     , m_handledFirstLetter(false)
     , m_ignoresStyleVisibility(behavior & TextIteratorIgnoresStyleVisibility)
     , m_emitsObjectReplacementCharacters(behavior & TextIteratorEmitsObjectReplacementCharacters)
-#if OS(ANDROID)
-    , m_stopsOnFormControls(behavior & TextIteratorStopsOnFormControls)
-    , m_shouldStop(false)
-#endif
 {
     if (!r)
         return;
@@ -356,21 +334,8 @@
 {
 }
 
-bool TextIterator::atEnd() const
-{
-#if OS(ANDROID)
-    return !m_positionNode || m_shouldStop;
-#else
-    return !m_positionNode;
-#endif
-}
-
 void TextIterator::advance()
 {
-#if OS(ANDROID)
-    if (m_shouldStop)
-        return;
-#endif
     // reset the run information
     m_positionNode = 0;
     m_textLength = 0;
@@ -403,10 +368,6 @@
     }
 
     while (m_node && m_node != m_pastEndNode) {
-#if OS(ANDROID)
-        if (!m_shouldStop && m_stopsOnFormControls && checkFormControlElement(m_node))
-            m_shouldStop = true;
-#endif
         // if the range ends at offset 0 of an element, represent the
         // position, but not the content, of that element e.g. if the
         // node is a blockflow element, emit a newline that
@@ -1073,10 +1034,6 @@
     : m_behavior(TextIteratorDefaultBehavior)
     , m_node(0)
     , m_positionNode(0)
-#if OS(ANDROID)
-    , m_stopsOnFormControls(false)
-    , m_shouldStop(false)
-#endif
 {
 }
 
@@ -1084,16 +1041,8 @@
     : m_behavior(behavior)
     , m_node(0)
     , m_positionNode(0)
-#if OS(ANDROID)
-    , m_stopsOnFormControls(behavior & TextIteratorStopsOnFormControls)
-    , m_shouldStop(false)
-#endif
 {
-#if OS(ANDROID)
-    ASSERT(m_behavior == TextIteratorDefaultBehavior || m_behavior == TextIteratorStopsOnFormControls);
-#else
     ASSERT(m_behavior == TextIteratorDefaultBehavior);
-#endif
 
     if (!r)
         return;
@@ -1142,30 +1091,10 @@
     advance();
 }
 
-bool SimplifiedBackwardsTextIterator::atEnd() const
-{
-#if OS(ANDROID)
-    return !m_positionNode || m_shouldStop;
-#else
-    return !m_positionNode;
-#endif
-}
-
 void SimplifiedBackwardsTextIterator::advance()
 {
     ASSERT(m_positionNode);
 
-#if OS(ANDROID)
-    if (m_shouldStop)
-        return;
-
-    // Prevent changing the iterator position if a form control element was found and advance should stop on it.
-    if (m_stopsOnFormControls && checkFormControlElement(m_node)) {
-        m_shouldStop = true;
-        return;
-    }
-#endif
-
     m_positionNode = 0;
     m_textLength = 0;
 
diff --git a/Source/WebCore/editing/TextIterator.h b/Source/WebCore/editing/TextIterator.h
index c4fc264..9fe4ceb 100644
--- a/Source/WebCore/editing/TextIterator.h
+++ b/Source/WebCore/editing/TextIterator.h
@@ -42,10 +42,7 @@
     TextIteratorEntersTextControls = 1 << 1,
     TextIteratorEmitsTextsWithoutTranscoding = 1 << 2,
     TextIteratorIgnoresStyleVisibility = 1 << 3,
-    TextIteratorEmitsObjectReplacementCharacters = 1 << 4,
-#if OS(ANDROID)
-    TextIteratorStopsOnFormControls = 1 << 6
-#endif
+    TextIteratorEmitsObjectReplacementCharacters = 1 << 4
 };
     
 // FIXME: Can't really answer this question correctly without knowing the white-space mode.
@@ -91,7 +88,7 @@
     ~TextIterator();
     explicit TextIterator(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior);
 
-    bool atEnd() const;
+    bool atEnd() const { return !m_positionNode; }
     void advance();
     
     int length() const { return m_textLength; }
@@ -185,12 +182,6 @@
     bool m_ignoresStyleVisibility;
     // Used when emitting the special 0xFFFC character is required.
     bool m_emitsObjectReplacementCharacters;
-#if OS(ANDROID)
-    // Used when the iteration should stop if form controls are reached.
-    bool m_stopsOnFormControls;
-    // Used when m_stopsOnFormControls is set to determine if the iterator should keep advancing.
-    bool m_shouldStop;
-#endif
 };
 
 // Iterates through the DOM range, returning all the text, and 0-length boundaries
@@ -201,7 +192,7 @@
     SimplifiedBackwardsTextIterator();
     explicit SimplifiedBackwardsTextIterator(const Range*, TextIteratorBehavior = TextIteratorDefaultBehavior);
     
-    bool atEnd() const;
+    bool atEnd() const { return !m_positionNode; }
     void advance();
     
     int length() const { return m_textLength; }
@@ -249,13 +240,6 @@
 
     // Whether m_node has advanced beyond the iteration range (i.e. m_startNode).
     bool m_havePassedStartNode;
-
-#if OS(ANDROID)
-    // Used when the iteration should stop if form controls are reached.
-    bool m_stopsOnFormControls;
-    // Used when m_stopsOnFormControls is set to determine if the iterator should keep advancing.
-    bool m_shouldStop;
-#endif
 };
 
 // Builds on the text iterator, adding a character position so we can walk one
diff --git a/Source/WebCore/fileapi/DOMFileSystemBase.cpp b/Source/WebCore/fileapi/DOMFileSystemBase.cpp
index 5a2627f..eafb815 100644
--- a/Source/WebCore/fileapi/DOMFileSystemBase.cpp
+++ b/Source/WebCore/fileapi/DOMFileSystemBase.cpp
@@ -63,7 +63,7 @@
         return false;
 
     KURL originURL(ParsedURLString, url.path());
-    String path = decodeURLEscapeSequences(originURL.path());
+    String path = originURL.path();
     if (path.isEmpty() || path[0] != '/')
         return false;
     path = path.substring(1);
diff --git a/Source/WebCore/history/android/AndroidWebHistoryBridge.h b/Source/WebCore/history/android/AndroidWebHistoryBridge.h
index d82aa35..a827b4a 100644
--- a/Source/WebCore/history/android/AndroidWebHistoryBridge.h
+++ b/Source/WebCore/history/android/AndroidWebHistoryBridge.h
@@ -26,20 +26,20 @@
 #ifndef AndroidWebHistoryBridge_h
 #define AndroidWebHistoryBridge_h
 
-#include <wtf/ThreadSafeRefCounted.h>
+#include <wtf/RefCounted.h>
 
 namespace WebCore {
 
 class HistoryItem;
 
-class AndroidWebHistoryBridge : public ThreadSafeRefCounted<AndroidWebHistoryBridge> {
+class AndroidWebHistoryBridge : public RefCounted<AndroidWebHistoryBridge> {
 public:
     AndroidWebHistoryBridge(HistoryItem* item)
         : m_scale(0)
         , m_textWrapScale(0)
         , m_active(false)
-        , m_historyItem(item) {}
-    virtual ~AndroidWebHistoryBridge() {}
+        , m_historyItem(item) { }
+    virtual ~AndroidWebHistoryBridge() { }
     virtual void updateHistoryItem(HistoryItem* item) = 0;
 
     void setScale(float s) { m_scale = s; }
diff --git a/Source/WebCore/html/HTMLAnchorElement.cpp b/Source/WebCore/html/HTMLAnchorElement.cpp
index b05e7f5..60f5b4a 100644
--- a/Source/WebCore/html/HTMLAnchorElement.cpp
+++ b/Source/WebCore/html/HTMLAnchorElement.cpp
@@ -405,10 +405,7 @@
 
 String HTMLAnchorElement::port() const
 {
-    if (href().hasPort())
-        return String::number(href().port());
-
-    return "";
+    return String::number(href().port());
 }
 
 void HTMLAnchorElement::setPort(const String& value)
@@ -534,11 +531,7 @@
 
 bool isEnterKeyKeydownEvent(Event* event)
 {
-#if OS(ANDROID)
-    return event->type() == eventNames().keyupEvent && event->isKeyboardEvent() && static_cast<KeyboardEvent*>(event)->keyIdentifier() == "Enter";
-#else
     return event->type() == eventNames().keydownEvent && event->isKeyboardEvent() && static_cast<KeyboardEvent*>(event)->keyIdentifier() == "Enter";
-#endif
 }
 
 bool isMiddleMouseButtonEvent(Event* event)
diff --git a/Source/WebCore/html/HTMLAttributeNames.in b/Source/WebCore/html/HTMLAttributeNames.in
index 578f717..5e0fe7b 100644
--- a/Source/WebCore/html/HTMLAttributeNames.in
+++ b/Source/WebCore/html/HTMLAttributeNames.in
@@ -58,7 +58,6 @@
 bgproperties
 border
 bordercolor
-capture
 cellpadding
 cellspacing
 char
diff --git a/Source/WebCore/html/HTMLCanvasElement.cpp b/Source/WebCore/html/HTMLCanvasElement.cpp
index e67cbf9..9f51f10 100644
--- a/Source/WebCore/html/HTMLCanvasElement.cpp
+++ b/Source/WebCore/html/HTMLCanvasElement.cpp
@@ -45,7 +45,6 @@
 #include "MIMETypeRegistry.h"
 #include "Page.h"
 #include "RenderHTMLCanvas.h"
-#include "RenderLayer.h"
 #include "Settings.h"
 #include <math.h>
 #include <stdio.h>
@@ -226,11 +225,6 @@
             return;
 
         m_dirtyRect.unite(r);
-#if PLATFORM(ANDROID)
-        // We handle invals ourselves and don't want webkit to repaint if we
-        // have put the canvas on a layer
-        if (!ro->hasLayer())
-#endif
         ro->repaintRectangle(enclosingIntRect(m_dirtyRect));
     }
 
diff --git a/Source/WebCore/html/HTMLCanvasElement.h b/Source/WebCore/html/HTMLCanvasElement.h
index e485835..9eab209 100644
--- a/Source/WebCore/html/HTMLCanvasElement.h
+++ b/Source/WebCore/html/HTMLCanvasElement.h
@@ -128,8 +128,20 @@
 
     void makeRenderingResultsAvailable();
 
-#if PLATFORM(ANDROID)
-    void clearDirtyRect() { m_dirtyRect = FloatRect(); }
+#ifdef ANDROID_INSTRUMENT
+    void* operator new(size_t size) {
+        return HTMLElement::operator new(size);
+    }
+    void* operator new[](size_t size) {
+        return HTMLElement::operator new[](size);
+    }
+
+    void operator delete(void* p, size_t size) {
+        HTMLElement::operator delete(p, size);
+    }
+    void operator delete[](void* p, size_t size) {
+        HTMLElement::operator delete[](p, size);
+    }
 #endif
 
 private:
diff --git a/Source/WebCore/html/HTMLDocument.cpp b/Source/WebCore/html/HTMLDocument.cpp
index a1be93d..dd41514 100644
--- a/Source/WebCore/html/HTMLDocument.cpp
+++ b/Source/WebCore/html/HTMLDocument.cpp
@@ -438,4 +438,26 @@
     return bodyElement && bodyElement->hasTagName(framesetTag);
 }
 
+#ifdef ANDROID_INSTRUMENT
+void* HTMLDocument::operator new(size_t size)
+{
+    return Node::operator new(size);
+}
+
+void* HTMLDocument::operator new[](size_t size)
+{
+    return Node::operator new[](size);
+}
+
+void HTMLDocument::operator delete(void* p, size_t size)
+{
+    Node::operator delete(p, size);
+}
+
+void HTMLDocument::operator delete[](void* p, size_t size)
+{
+    Node::operator delete[](p, size);
+}
+#endif
+
 }
diff --git a/Source/WebCore/html/HTMLDocument.h b/Source/WebCore/html/HTMLDocument.h
index d39f392..3310b71 100644
--- a/Source/WebCore/html/HTMLDocument.h
+++ b/Source/WebCore/html/HTMLDocument.h
@@ -82,6 +82,14 @@
 protected:
     HTMLDocument(Frame*, const KURL&);
 
+#ifdef ANDROID_INSTRUMENT
+    // Overridden to resolve the ambiguous
+    void* operator new(size_t size);
+    void* operator new[](size_t size);
+    void operator delete(void* p, size_t size);
+    void operator delete[](void* p, size_t size);
+#endif
+
 private:
     virtual PassRefPtr<Element> createElement(const AtomicString& tagName, ExceptionCode&);
 
diff --git a/Source/WebCore/html/HTMLElement.cpp b/Source/WebCore/html/HTMLElement.cpp
index 0aa9664..b2b57a2 100644
--- a/Source/WebCore/html/HTMLElement.cpp
+++ b/Source/WebCore/html/HTMLElement.cpp
@@ -570,7 +570,7 @@
 {
     if (equalIgnoringCase(where, "beforeBegin") || equalIgnoringCase(where, "afterEnd")) {
         ContainerNode* parent = element->parentNode();
-        if (parent && !parent->isElementNode()) {
+        if (parent && parent->isDocumentNode()) {
             ec = NO_MODIFICATION_ALLOWED_ERR;
             return 0;
         }
@@ -682,6 +682,11 @@
         attr->decl()->removeProperty(CSSPropertyWordWrap, false);
         attr->decl()->removeProperty(CSSPropertyWebkitNbspMode, false);
         attr->decl()->removeProperty(CSSPropertyWebkitLineBreak, false);
+    } else if (equalIgnoringCase(enabled, "inherit")) {
+        addCSSProperty(attr, CSSPropertyWebkitUserModify, CSSValueInherit);
+        attr->decl()->removeProperty(CSSPropertyWordWrap, false);
+        attr->decl()->removeProperty(CSSPropertyWebkitNbspMode, false);
+        attr->decl()->removeProperty(CSSPropertyWebkitLineBreak, false);
     } else if (equalIgnoringCase(enabled, "plaintext-only")) {
         addCSSProperty(attr, CSSPropertyWebkitUserModify, CSSValueReadWritePlaintextOnly);
         addCSSProperty(attr, CSSPropertyWordWrap, CSSValueBreakWord);
diff --git a/Source/WebCore/html/HTMLInputElement.cpp b/Source/WebCore/html/HTMLInputElement.cpp
index 36cdf51..2b262e4 100644
--- a/Source/WebCore/html/HTMLInputElement.cpp
+++ b/Source/WebCore/html/HTMLInputElement.cpp
@@ -1588,24 +1588,4 @@
     InputElement::handleBeforeTextInsertedEvent(m_data, this, this, event);
 }
 
-#if PLATFORM(ANDROID) && ENABLE(MEDIA_CAPTURE)
-String HTMLInputElement::capture() const
-{
-    if (!isFileUpload()) {
-        // capture has no meaning on anything other than file pickers.
-        return String();
-    }
-
-    String capture = fastGetAttribute(captureAttr).lower();
-    if (capture == "camera"
-        || capture == "camcorder"
-        || capture == "microphone"
-        || capture == "filesystem")
-        return capture;
-    // According to the HTML Media Capture specification, the invalid and
-    // missing default value is filesystem.
-    return "filesystem";
-}
-#endif
-
 } // namespace
diff --git a/Source/WebCore/html/HTMLInputElement.h b/Source/WebCore/html/HTMLInputElement.h
index 58d86ac..2a98b13 100644
--- a/Source/WebCore/html/HTMLInputElement.h
+++ b/Source/WebCore/html/HTMLInputElement.h
@@ -200,10 +200,6 @@
     void updateCheckedRadioButtons();
 
     bool lastChangeWasUserEdit() const;
-
-#if PLATFORM(ANDROID) && ENABLE(MEDIA_CAPTURE)
-    String capture() const;
-#endif
     
 protected:
     HTMLInputElement(const QualifiedName&, Document*, HTMLFormElement*, bool createdByParser);
diff --git a/Source/WebCore/html/HTMLInputElement.idl b/Source/WebCore/html/HTMLInputElement.idl
index e1937e4..f346e10 100644
--- a/Source/WebCore/html/HTMLInputElement.idl
+++ b/Source/WebCore/html/HTMLInputElement.idl
@@ -107,9 +107,6 @@
         attribute [Reflect, EnabledAtRuntime] boolean webkitGrammar;
         attribute [DontEnum] EventListener onwebkitspeechchange;
 #endif
-#if defined(WTF_PLATFORM_ANDROID) && defined(ENABLE_MEDIA_CAPTURE) && ENABLE_MEDIA_CAPTURE
-        attribute [Reflect] DOMString capture;
-#endif
     };
 
 }
diff --git a/Source/WebCore/html/HTMLLinkElement.cpp b/Source/WebCore/html/HTMLLinkElement.cpp
index 4673109..7cbf38b 100644
--- a/Source/WebCore/html/HTMLLinkElement.cpp
+++ b/Source/WebCore/html/HTMLLinkElement.cpp
@@ -504,6 +504,28 @@
         styleSheet->addSubresourceStyleURLs(urls);
 }
 
+#ifdef ANDROID_INSTRUMENT
+void* HTMLLinkElement::operator new(size_t size)
+{
+    return Node::operator new(size);
+}
+
+void* HTMLLinkElement::operator new[](size_t size)
+{
+    return Node::operator new[](size);
+}
+
+void HTMLLinkElement::operator delete(void* p, size_t size)
+{
+    Node::operator delete(p, size);
+}
+
+void HTMLLinkElement::operator delete[](void* p, size_t size)
+{
+    Node::operator delete[](p, size);
+}
+#endif
+
 void HTMLLinkElement::addPendingSheet(PendingSheetType type)
 {
     if (type <= m_pendingSheetType)
diff --git a/Source/WebCore/html/HTMLLinkElement.h b/Source/WebCore/html/HTMLLinkElement.h
index 1a6eba9..f602d38 100644
--- a/Source/WebCore/html/HTMLLinkElement.h
+++ b/Source/WebCore/html/HTMLLinkElement.h
@@ -120,6 +120,14 @@
     void addPendingSheet(PendingSheetType);
     void removePendingSheet();
 
+#ifdef ANDROID_INSTRUMENT
+    // Overridden to resolve the ambiguous
+    void* operator new(size_t size);
+    void* operator new[](size_t size);
+    void operator delete(void* p, size_t size);
+    void operator delete[](void* p, size_t size);
+#endif
+
 private:
     HTMLLinkElement(const QualifiedName&, Document*, bool createdByParser);
 
diff --git a/Source/WebCore/html/HTMLMediaElement.cpp b/Source/WebCore/html/HTMLMediaElement.cpp
index 328b6db..023e8d2 100644
--- a/Source/WebCore/html/HTMLMediaElement.cpp
+++ b/Source/WebCore/html/HTMLMediaElement.cpp
@@ -178,7 +178,6 @@
     , m_completelyLoaded(false)
 #if PLATFORM(ANDROID)
     , m_lastTouch(0)
-    , m_userGestureInitiated(false)
 #endif
 {
     LOG(Media, "HTMLMediaElement::HTMLMediaElement");
@@ -186,8 +185,10 @@
     document->registerForMediaVolumeCallbacks(this);
     document->registerForPrivateBrowsingStateChangedCallbacks(this);
 #if PLATFORM(ANDROID) && ENABLE(TOUCH_EVENTS)
-    m_restrictions |= RequireUserGestureForRateChangeRestriction;
+    // Enable the Media Element to listen to all the touch events
+    document->addListenerTypeIfNeeded(eventNames().touchstartEvent);
 #endif
+
 }
 
 HTMLMediaElement::~HTMLMediaElement()
@@ -236,9 +237,7 @@
 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
         if (controls()) {
             if (!hasMediaControls()) {
-                if (!createMediaControls())
-                    return;
-
+                ensureMediaControls();
                 mediaControls()->reset();
             }
             mediaControls()->show();
@@ -516,9 +515,6 @@
         ec = INVALID_STATE_ERR;
     else {
         m_loadInitiatedByUserGesture = isUserGesture;
-#if PLATFORM(ANDROID)
-        m_userGestureInitiated |= isUserGesture;
-#endif
         prepareForLoad();
         loadInternal();
     }
@@ -1421,19 +1417,9 @@
 {
     LOG(Media, "HTMLMediaElement::play(isUserGesture : %s)", boolString(isUserGesture));
 
-    if (m_restrictions & RequireUserGestureForRateChangeRestriction && !isUserGesture
-#if PLATFORM(ANDROID)
-        && !m_userGestureInitiated
-#endif
-        )
+    if (m_restrictions & RequireUserGestureForRateChangeRestriction && !isUserGesture)
         return;
 
-#if PLATFORM(ANDROID)
-    // B/c we set the restriction to require gesture for rate change for
-    // Android, when we don't early return, we can safely set this to true.
-    m_userGestureInitiated = true;
-#endif
-
     Document* doc = document();
     Settings* settings = doc->settings();
     if (settings && settings->needsSiteSpecificQuirks() && m_dispatchingCanPlayEvent && !m_loadInitiatedByUserGesture) {
@@ -1480,17 +1466,9 @@
 {
     LOG(Media, "HTMLMediaElement::pause(isUserGesture : %s)", boolString(isUserGesture));
 
-    if (m_restrictions & RequireUserGestureForRateChangeRestriction && !isUserGesture
-#if PLATFORM(ANDROID)
-        && !m_userGestureInitiated
-#endif
-        )
+    if (m_restrictions & RequireUserGestureForRateChangeRestriction && !isUserGesture)
         return;
-#if PLATFORM(ANDROID)
-    // B/c we set the restriction to require gesture for rate change for
-    // Android, when we don't early return, we can safely set this to true.
-    m_userGestureInitiated = true;
-#endif
+
     pauseInternal();
 }
 
@@ -2424,15 +2402,6 @@
     }
 #endif
 
-#if PLATFORM(ANDROID)
-    // It is really hard to hit the play/pause button on mobile devices.
-    // This allows user to click the video area to toggle play/pause state.
-    if (event->type() == eventNames().clickEvent
-        && !hasEventListeners(eventNames().clickEvent)) {
-        m_userGestureInitiated = processingUserGesture();
-        togglePlayState();
-    }
-#endif
     HTMLElement::defaultEventHandler(event);
 #endif
 }
@@ -2739,18 +2708,13 @@
     return node && node->isMediaControls();
 }
 
-bool HTMLMediaElement::createMediaControls()
+void HTMLMediaElement::ensureMediaControls()
 {
     if (hasMediaControls())
-        return true;
+        return;
 
     ExceptionCode ec;
-    RefPtr<MediaControls> controls = MediaControls::create(this);
-    if (!controls)
-        return false;
-
-    ensureShadowRoot()->appendChild(controls, ec);
-    return true;
+    ensureShadowRoot()->appendChild(MediaControls::create(this), ec);
 }
 
 void* HTMLMediaElement::preDispatchEventHandler(Event* event)
@@ -2758,9 +2722,7 @@
     if (event && event->type() == eventNames().webkitfullscreenchangeEvent) {
         if (controls()) {
             if (!hasMediaControls()) {
-                if (!createMediaControls())
-                    return 0;
-
+                ensureMediaControls();
                 mediaControls()->reset();
             }
             mediaControls()->show();
diff --git a/Source/WebCore/html/HTMLMediaElement.h b/Source/WebCore/html/HTMLMediaElement.h
index 0b11861..987cf87 100644
--- a/Source/WebCore/html/HTMLMediaElement.h
+++ b/Source/WebCore/html/HTMLMediaElement.h
@@ -325,7 +325,7 @@
     void refreshCachedTime() const;
 
     bool hasMediaControls();
-    bool createMediaControls();
+    void ensureMediaControls();
 
     virtual void* preDispatchEventHandler(Event*);
 
@@ -420,10 +420,6 @@
 
 #if PLATFORM(ANDROID)
     double m_lastTouch;
-    // When user gesture invoke load, play or pause, this turns to be true.
-    // After this becomes true, we ignore the user gesture requirement for play
-    // and pause.
-    bool m_userGestureInitiated;
 #endif
 };
 
diff --git a/Source/WebCore/html/canvas/ArrayBufferView.h b/Source/WebCore/html/canvas/ArrayBufferView.h
index d06fc8d..701abbc 100644
--- a/Source/WebCore/html/canvas/ArrayBufferView.h
+++ b/Source/WebCore/html/canvas/ArrayBufferView.h
@@ -46,7 +46,6 @@
     virtual bool isIntArray() const { return false; }
     virtual bool isUnsignedIntArray() const { return false; }
     virtual bool isFloatArray() const { return false; }
-    virtual bool isDoubleArray() const { return false; } 
     virtual bool isDataView() const { return false; }
 
     PassRefPtr<ArrayBuffer> buffer() const
diff --git a/Source/WebCore/html/canvas/Float64Array.cpp b/Source/WebCore/html/canvas/Float64Array.cpp
deleted file mode 100644
index 2dcb373..0000000
--- a/Source/WebCore/html/canvas/Float64Array.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "Float64Array.h"
-
-namespace WebCore {
-
-PassRefPtr<Float64Array> Float64Array::create(unsigned length)
-{
-    return TypedArrayBase<double>::create<Float64Array>(length);
-}
-
-PassRefPtr<Float64Array> Float64Array::create(const double* array, unsigned length)
-{
-    return TypedArrayBase<double>::create<Float64Array>(array, length);
-}
-
-PassRefPtr<Float64Array> Float64Array::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length)
-{
-    return TypedArrayBase<double>::create<Float64Array>(buffer, byteOffset, length);
-}
-
-Float64Array::Float64Array(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length)
-    : TypedArrayBase<double>(buffer, byteOffset, length)
-{
-}
-
-PassRefPtr<Float64Array> Float64Array::subarray(int start) const
-{
-    return subarray(start, length());
-}
-
-PassRefPtr<Float64Array> Float64Array::subarray(int start, int end) const
-{
-    return subarrayImpl<Float64Array>(start, end);
-}
-
-}
diff --git a/Source/WebCore/html/canvas/Float64Array.h b/Source/WebCore/html/canvas/Float64Array.h
deleted file mode 100644
index f45a21c..0000000
--- a/Source/WebCore/html/canvas/Float64Array.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef Float64Array_h
-#define Float64Array_h
-
-#include "TypedArrayBase.h"
-#include <wtf/MathExtras.h>
-
-namespace WebCore {
-
-class Float64Array : public TypedArrayBase<double> {
-public:
-    static PassRefPtr<Float64Array> create(unsigned length);
-    static PassRefPtr<Float64Array> create(const double* array, unsigned length);
-    static PassRefPtr<Float64Array> create(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length);
-
-    using TypedArrayBase<double>::set;
-
-    void set(unsigned index, double value)
-    {
-        if (index >= TypedArrayBase<double>::m_length)
-            return;
-        TypedArrayBase<double>::data()[index] = static_cast<double>(value);
-    }
-
-    // Invoked by the indexed getter. Does not perform range checks; caller
-    // is responsible for doing so and returning undefined as necessary.
-    double item(unsigned index) const
-    {
-        ASSERT(index < TypedArrayBase<double>::m_length);
-        double result = TypedArrayBase<double>::data()[index];
-        return result;
-    }
-
-    PassRefPtr<Float64Array> subarray(int start) const;
-    PassRefPtr<Float64Array> subarray(int start, int end) const;
-
-private:
-    Float64Array(PassRefPtr<ArrayBuffer>,
-                 unsigned byteOffset,
-                 unsigned length);
-    // Make constructor visible to superclass.
-    friend class TypedArrayBase<double>;
-
-    // Overridden from ArrayBufferView.
-    virtual bool isDoubleArray() const { return true; }
-};
-
-} // namespace WebCore
-
-#endif // Float64Array_h
diff --git a/Source/WebCore/html/canvas/Float64Array.idl b/Source/WebCore/html/canvas/Float64Array.idl
deleted file mode 100644
index 6057253..0000000
--- a/Source/WebCore/html/canvas/Float64Array.idl
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-module html {
-    interface [
-        CanBeConstructed,
-        CustomConstructFunction,
-        V8CustomConstructor,
-        HasNumericIndexGetter,
-        HasCustomIndexSetter,
-        GenerateNativeConverter,
-        NoStaticTables,
-        CustomToJS,
-        DontCheckEnums
-    ] Float64Array : ArrayBufferView {
-        const unsigned int BYTES_PER_ELEMENT = 8;
-
-        readonly attribute unsigned long length;
-        Float64Array subarray(in long start, in [Optional] long end);
-
-        // void set(in Float64Array array, [Optional] in unsigned long offset);
-        // void set(in sequence<long> array, [Optional] in unsigned long offset);
-        [Custom] void set();
-    };
-}
diff --git a/Source/WebCore/html/parser/HTMLDocumentParser.cpp b/Source/WebCore/html/parser/HTMLDocumentParser.cpp
index 46dddf0..8f95cc5 100644
--- a/Source/WebCore/html/parser/HTMLDocumentParser.cpp
+++ b/Source/WebCore/html/parser/HTMLDocumentParser.cpp
@@ -41,6 +41,10 @@
 #include "NestingLevelIncrementer.h"
 #include "Settings.h"
 
+#ifdef ANDROID_INSTRUMENT
+#include "TimeCounter.h"
+#endif
+
 namespace WebCore {
 
 using namespace HTMLNames;
@@ -314,6 +318,10 @@
     if (isStopped())
         return;
 
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::start(android::TimeCounter::ParsingTimeCounter);
+#endif
+
     // pumpTokenizer can cause this parser to be detached from the Document,
     // but we need to ensure it isn't deleted yet.
     RefPtr<HTMLDocumentParser> protect(this);
@@ -361,12 +369,18 @@
         // We've gotten data off the network in a nested write.
         // We don't want to consume any more of the input stream now.  Do
         // not worry.  We'll consume this data in a less-nested write().
+#ifdef ANDROID_INSTRUMENT
+        android::TimeCounter::record(android::TimeCounter::ParsingTimeCounter, __FUNCTION__);
+#endif
         return;
     }
 
     pumpTokenizerIfPossible(AllowYield);
 
     endIfDelayed();
+#ifdef ANDROID_INSTRUMENT
+    android::TimeCounter::record(android::TimeCounter::ParsingTimeCounter, __FUNCTION__);
+#endif
 }
 
 void HTMLDocumentParser::end()
diff --git a/Source/WebCore/html/shadow/SliderThumbElement.cpp b/Source/WebCore/html/shadow/SliderThumbElement.cpp
index 210fb7b..e68ab00 100644
--- a/Source/WebCore/html/shadow/SliderThumbElement.cpp
+++ b/Source/WebCore/html/shadow/SliderThumbElement.cpp
@@ -251,19 +251,11 @@
     HTMLDivElement::defaultEventHandler(event);
 }
 
-#if PLATFORM(ANDROID) && ENABLE(TOUCH_EVENTS)
-void SliderThumbElement::attach()
-{
-    HTMLDivElement::attach();
-    document()->addListenerTypeIfNeeded(eventNames().touchstartEvent);
-}
-#endif
-
 void SliderThumbElement::detach()
 {
     if (m_inDragMode) {
         if (Frame* frame = document()->frame())
-            frame->eventHandler()->setCapturingMouseEventsNode(0);
+            frame->eventHandler()->setCapturingMouseEventsNode(0);      
     }
     HTMLDivElement::detach();
 }
diff --git a/Source/WebCore/html/shadow/SliderThumbElement.h b/Source/WebCore/html/shadow/SliderThumbElement.h
index cdeb471..2fa60cb 100644
--- a/Source/WebCore/html/shadow/SliderThumbElement.h
+++ b/Source/WebCore/html/shadow/SliderThumbElement.h
@@ -54,9 +54,6 @@
 
     void dragFrom(const IntPoint&);
     virtual void defaultEventHandler(Event*);
-#if PLATFORM(ANDROID) && ENABLE(TOUCH_EVENTS)
-    virtual void attach();
-#endif
     virtual void detach();
     virtual const AtomicString& shadowPseudoId() const;
 
diff --git a/Source/WebCore/html/shadow/TextControlInnerElements.h b/Source/WebCore/html/shadow/TextControlInnerElements.h
index 886fbf8..2340970 100644
--- a/Source/WebCore/html/shadow/TextControlInnerElements.h
+++ b/Source/WebCore/html/shadow/TextControlInnerElements.h
@@ -101,8 +101,9 @@
 
     virtual void detach();
     virtual bool isSpinButtonElement() const { return true; }
-    virtual bool isEnabledFormControl() const { return static_cast<Element*>(shadowAncestorNode())->isEnabledFormControl(); }
-    virtual bool isReadOnlyFormControl() const { return static_cast<Element*>(shadowAncestorNode())->isReadOnlyFormControl(); }
+    // FIXME: shadowAncestorNode() should be const.
+    virtual bool isEnabledFormControl() const { return static_cast<Element*>(const_cast<SpinButtonElement*>(this)->shadowAncestorNode())->isEnabledFormControl(); }
+    virtual bool isReadOnlyFormControl() const { return static_cast<Element*>(const_cast<SpinButtonElement*>(this)->shadowAncestorNode())->isReadOnlyFormControl(); }
     virtual void defaultEventHandler(Event*);
     void startRepeatingTimer();
     void stopRepeatingTimer();
diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp
index 670cf1f..85b1541 100644
--- a/Source/WebCore/loader/FrameLoader.cpp
+++ b/Source/WebCore/loader/FrameLoader.cpp
@@ -119,6 +119,11 @@
 #include "ArchiveFactory.h"
 #endif
 
+#ifdef ANDROID_INSTRUMENT
+#include "TimeCounter.h"
+#include "RenderArena.h"
+#endif
+
 namespace WebCore {
 
 using namespace HTMLNames;
@@ -993,8 +998,7 @@
 ObjectContentType FrameLoader::defaultObjectContentType(const KURL& url, const String& mimeTypeIn, bool shouldPreferPlugInsForImages)
 {
     String mimeType = mimeTypeIn;
-    String decodedPath = decodeURLEscapeSequences(url.path());
-    String extension = decodedPath.substring(decodedPath.reverseFind('.') + 1);
+    String extension = url.path().substring(url.path().reverseFind('.') + 1);
 
     // We don't use MIMETypeRegistry::getMIMETypeForPath() because it returns "application/octet-stream" upon failure
     if (mimeType.isEmpty())
@@ -1110,7 +1114,11 @@
 }
 
 void FrameLoader::provisionalLoadStarted()
-{
+{    
+#ifdef ANDROID_INSTRUMENT
+    if (!m_frame->tree()->parent())
+        android::TimeCounter::reset();
+#endif
     if (m_stateMachine.firstLayoutDone())
         m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
     m_frame->navigationScheduler()->cancel(true);
@@ -2300,7 +2308,7 @@
     if (m_stateMachine.creatingInitialEmptyDocument())
         return;
 #endif
-
+    
 #if !ENABLE(WEB_ARCHIVE)
     m_client->finishedLoading(loader);
 #else
@@ -2491,6 +2499,12 @@
 
             if (Page* page = m_frame->page())
                 page->progress()->progressCompleted(m_frame);
+
+#ifdef ANDROID_INSTRUMENT
+            if (!m_frame->tree()->parent() && m_frame->document()->renderArena())
+                android::TimeCounter::report(m_URL, cache()->getLiveSize(), cache()->getDeadSize(),
+                        m_frame->document()->renderArena()->reportPoolSize());
+#endif
             return;
         }
         
diff --git a/Source/WebCore/loader/archive/android/WebArchiveAndroid.cpp b/Source/WebCore/loader/archive/android/WebArchiveAndroid.cpp
index 5f60163..55d7cec 100644
--- a/Source/WebCore/loader/archive/android/WebArchiveAndroid.cpp
+++ b/Source/WebCore/loader/archive/android/WebArchiveAndroid.cpp
@@ -36,7 +36,6 @@
 #include <libxml/tree.h>
 #include <libxml/xmlstring.h>
 #include <libxml/xmlwriter.h>
-#include <utils/Log.h>
 #include <wtf/text/CString.h>
 
 namespace WebCore {
@@ -118,7 +117,7 @@
         }
     }
     if (!base64Data) {
-        ALOGD("loadArchiveResourceField: Failed to load field.");
+        LOGD("loadArchiveResourceField: Failed to load field.");
         return false;
     }
 
@@ -126,7 +125,7 @@
 
     const int result = base64Decode(base64Data, base64Size, *outputData);
     if (!result) {
-        ALOGD("loadArchiveResourceField: Failed to decode field.");
+        LOGD("loadArchiveResourceField: Failed to decode field.");
         return false;
     }
 
@@ -166,37 +165,37 @@
 static PassRefPtr<ArchiveResource> loadArchiveResource(xmlNodePtr resourceNode)
 {
     if (!xmlStrEqual(resourceNode->name, archiveResourceTag)) {
-        ALOGD("loadArchiveResource: Malformed resource.");
+        LOGD("loadArchiveResource: Malformed resource.");
         return 0;
     }
 
     KURL url = loadArchiveResourceFieldURL(resourceNode, urlFieldTag);
     if (url.isNull()) {
-        ALOGD("loadArchiveResource: Failed to load resource.");
+        LOGD("loadArchiveResource: Failed to load resource.");
         return 0;
     }
 
     String mimeType = loadArchiveResourceFieldString(resourceNode, mimeFieldTag);
     if (mimeType.isNull()) {
-        ALOGD("loadArchiveResource: Failed to load resource.");
+        LOGD("loadArchiveResource: Failed to load resource.");
         return 0;
     }
 
     String textEncoding = loadArchiveResourceFieldString(resourceNode, encodingFieldTag);
     if (textEncoding.isNull()) {
-        ALOGD("loadArchiveResource: Failed to load resource.");
+        LOGD("loadArchiveResource: Failed to load resource.");
         return 0;
     }
 
     String frameName = loadArchiveResourceFieldString(resourceNode, frameFieldTag);
     if (frameName.isNull()) {
-        ALOGD("loadArchiveResource: Failed to load resource.");
+        LOGD("loadArchiveResource: Failed to load resource.");
         return 0;
     }
 
     PassRefPtr<SharedBuffer> data = loadArchiveResourceFieldBuffer(resourceNode, dataFieldTag);
     if (!data) {
-        ALOGD("loadArchiveResource: Failed to load resource.");
+        LOGD("loadArchiveResource: Failed to load resource.");
         return 0;
     }
 
@@ -212,7 +211,7 @@
     Vector<PassRefPtr<Archive> > subframes;
 
     if (!xmlStrEqual(archiveNode->name, archiveTag)) {
-        ALOGD("loadArchive: Malformed archive.");
+        LOGD("loadArchive: Malformed archive.");
         return 0;
     }
 
@@ -228,7 +227,7 @@
         }
     }
     if (!mainResource) {
-        ALOGD("loadArchive: Failed to load main resource.");
+        LOGD("loadArchive: Failed to load main resource.");
         return 0;
     }
 
@@ -241,7 +240,7 @@
                  resourceNode = resourceNode->next) {
                 PassRefPtr<ArchiveResource> subresource = loadArchiveResource(resourceNode);
                 if (!subresource) {
-                    ALOGD("loadArchive: Failed to load subresource.");
+                    LOGD("loadArchive: Failed to load subresource.");
                     break;
                 }
                 subresources.append(subresource);
@@ -259,7 +258,7 @@
                  resourceNode = resourceNode->next) {
                 PassRefPtr<WebArchiveAndroid> subframe = loadArchive(resourceNode);
                 if (!subframe) {
-                    ALOGD("loadArchive: Failed to load subframe.");
+                    LOGD("loadArchive: Failed to load subframe.");
                     break;
                 }
                 subframes.append(subframe);
@@ -291,20 +290,20 @@
 
     xmlDocPtr doc = xmlReadMemory(buffer->data(), buffer->size(), noBaseUrl, defaultEncoding, noParserOptions);
     if (!doc) {
-        ALOGD("create: Failed to parse document.");
+        LOGD("create: Failed to parse document.");
         return createArchiveForError();
     }
 
     xmlNodePtr root = xmlDocGetRootElement(doc);
     if (!root) {
-        ALOGD("create: Empty document.");
+        LOGD("create: Empty document.");
         xmlFreeDoc(doc);
         return createArchiveForError();
     }
 
     RefPtr<WebArchiveAndroid> archive = loadArchive(root);
     if (!archive) {
-        ALOGD("create: Failed to load archive.");
+        LOGD("create: Failed to load archive.");
         xmlFreeDoc(doc);
         return createArchiveForError();
     }
@@ -317,7 +316,7 @@
 {
     int result = xmlTextWriterStartElement(writer, tag);
     if (result < 0) {
-        ALOGD("saveArchiveResourceField: Failed to start element.");
+        LOGD("saveArchiveResourceField: Failed to start element.");
         return false;
     }
 
@@ -325,20 +324,20 @@
         Vector<char> base64Data;
         base64Encode(data, size, base64Data, false);
         if (base64Data.isEmpty()) {
-            ALOGD("saveArchiveResourceField: Failed to base64 encode data.");
+            LOGD("saveArchiveResourceField: Failed to base64 encode data.");
             return false;
         }
 
         result = xmlTextWriterWriteRawLen(writer, BAD_CAST base64Data.data(), base64Data.size());
         if (result < 0) {
-            ALOGD("saveArchiveResourceField: Failed to write data.");
+            LOGD("saveArchiveResourceField: Failed to write data.");
             return false;
         }
     }
 
     result = xmlTextWriterEndElement(writer);
     if (result < 0) {
-        ALOGD("saveArchiveResourceField: Failed to end element.");
+        LOGD("saveArchiveResourceField: Failed to end element.");
         return false;
     }
 
@@ -361,7 +360,7 @@
 {
     int result = xmlTextWriterStartElement(writer, archiveResourceTag);
     if (result < 0) {
-        ALOGD("saveArchiveResource: Failed to start element.");
+        LOGD("saveArchiveResource: Failed to start element.");
         return false;
     }
 
@@ -374,7 +373,7 @@
 
     result = xmlTextWriterEndElement(writer);
     if (result < 0) {
-        ALOGD("saveArchiveResource: Failed to end element.");
+        LOGD("saveArchiveResource: Failed to end element.");
         return false;
     }
 
@@ -385,13 +384,13 @@
 {
     int result = xmlTextWriterStartElement(writer, archiveTag);
     if (result < 0) {
-        ALOGD("saveArchive: Failed to start element.");
+        LOGD("saveArchive: Failed to start element.");
         return false;
     }
 
     result = xmlTextWriterStartElement(writer, mainResourceTag);
     if (result < 0) {
-        ALOGD("saveArchive: Failed to start element.");
+        LOGD("saveArchive: Failed to start element.");
         return false;
     }
 
@@ -400,13 +399,13 @@
 
     result = xmlTextWriterEndElement(writer);
     if (result < 0) {
-        ALOGD("saveArchive: Failed to end element.");
+        LOGD("saveArchive: Failed to end element.");
         return false;
     }
 
     result = xmlTextWriterStartElement(writer, subresourcesTag);
     if (result < 0) {
-        ALOGD("saveArchive: Failed to start element.");
+        LOGD("saveArchive: Failed to start element.");
         return false;
     }
 
@@ -419,13 +418,13 @@
 
     result = xmlTextWriterEndElement(writer);
     if (result < 0) {
-        ALOGD("saveArchive: Failed to end element.");
+        LOGD("saveArchive: Failed to end element.");
         return false;
     }
 
     result = xmlTextWriterStartElement(writer, subframesTag);
     if (result < 0) {
-        ALOGD("saveArchive: Failed to start element.");
+        LOGD("saveArchive: Failed to start element.");
         return false;
     }
 
@@ -438,7 +437,7 @@
 
     result = xmlTextWriterEndElement(writer);
     if (result < 0) {
-        ALOGD("saveArchive: Failed to end element.");
+        LOGD("saveArchive: Failed to end element.");
         return true;
     }
 
@@ -453,7 +452,7 @@
 
     int result = xmlTextWriterStartDocument(writer, defaultXmlVersion, defaultEncoding, defaultStandalone);
     if (result < 0) {
-        ALOGD("saveWebArchive: Failed to start document.");
+        LOGD("saveWebArchive: Failed to start document.");
         return false;
     }
 
@@ -462,7 +461,7 @@
 
     result = xmlTextWriterEndDocument(writer);
     if (result< 0) {
-        ALOGD("saveWebArchive: Failed to end document.");
+        LOGD("saveWebArchive: Failed to end document.");
         return false;
     }
 
diff --git a/Source/WebCore/loader/cache/CachedResourceLoader.cpp b/Source/WebCore/loader/cache/CachedResourceLoader.cpp
index fe25a93..91c0629 100644
--- a/Source/WebCore/loader/cache/CachedResourceLoader.cpp
+++ b/Source/WebCore/loader/cache/CachedResourceLoader.cpp
@@ -293,8 +293,6 @@
     }
 #if ENABLE(LINK_PREFETCH)
     case CachedResource::LinkResource:
-        if (!m_document->settings()->linkPrefetchEnabled())
-            return false;
         break;
 #endif
     }
diff --git a/Source/WebCore/loader/cache/MemoryCache.h b/Source/WebCore/loader/cache/MemoryCache.h
index c9b91f9..a092eac 100644
--- a/Source/WebCore/loader/cache/MemoryCache.h
+++ b/Source/WebCore/loader/cache/MemoryCache.h
@@ -171,6 +171,12 @@
     void removeResourcesWithOrigin(SecurityOrigin*);
     void getOriginsWithCache(SecurityOriginSet& origins);
 
+#ifdef ANDROID_INSTRUMENT
+    unsigned getLiveSize() { return m_liveSize; }
+    unsigned getDeadSize() { return m_deadSize; }
+#endif
+
+
 private:
     MemoryCache();
     ~MemoryCache(); // Not implemented to make sure nobody accidentally calls delete -- WebCore does not delete singletons.
diff --git a/Source/WebCore/loader/icon/IconDatabase.cpp b/Source/WebCore/loader/icon/IconDatabase.cpp
index 2bb22ec..3cefea7 100644
--- a/Source/WebCore/loader/icon/IconDatabase.cpp
+++ b/Source/WebCore/loader/icon/IconDatabase.cpp
@@ -73,7 +73,7 @@
 
 static bool checkIntegrityOnOpen = false;
 
-#if !LOG_DISABLED || !ERROR_DISABLED
+#ifndef NDEBUG
 static String urlForLogging(const String& url)
 {
     static unsigned urlTruncationLength = 120;
@@ -967,7 +967,7 @@
     
     LOG(IconDatabase, "(THREAD) IconDatabase sync thread started");
 
-#if !LOG_DISABLED
+#ifndef NDEBUG
     double startTime = currentTime();
 #endif
 
@@ -993,7 +993,7 @@
     if (shouldStopThreadActivity())
         return syncThreadMainLoop();
         
-#if !LOG_DISABLED
+#ifndef NDEBUG
     double timeStamp = currentTime();
     LOG(IconDatabase, "(THREAD) Open took %.4f seconds", timeStamp - startTime);
 #endif    
@@ -1002,7 +1002,7 @@
     if (shouldStopThreadActivity())
         return syncThreadMainLoop();
         
-#if !LOG_DISABLED
+#ifndef NDEBUG
     double newStamp = currentTime();
     LOG(IconDatabase, "(THREAD) performOpenInitialization() took %.4f seconds, now %.4f seconds from thread start", newStamp - timeStamp, newStamp - startTime);
     timeStamp = newStamp;
@@ -1025,7 +1025,7 @@
         if (shouldStopThreadActivity())
             return syncThreadMainLoop();
             
-#if !LOG_DISABLED
+#ifndef NDEBUG
         newStamp = currentTime();
         LOG(IconDatabase, "(THREAD) performImport() took %.4f seconds, now %.4f seconds from thread start", newStamp - timeStamp, newStamp - startTime);
         timeStamp = newStamp;
@@ -1042,7 +1042,7 @@
     if (shouldStopThreadActivity())
         return syncThreadMainLoop();
 
-#if !LOG_DISABLED
+#ifndef NDEBUG
     newStamp = currentTime();
     LOG(IconDatabase, "(THREAD) performURLImport() took %.4f seconds.  Entering main loop %.4f seconds from thread start", newStamp - timeStamp, newStamp - startTime);
 #endif 
@@ -1358,7 +1358,7 @@
     while (!m_threadTerminationRequested) {
         m_syncLock.unlock();
 
-#if !LOG_DISABLED
+#ifndef NDEBUG
         double timeStamp = currentTime();
 #endif
         LOG(IconDatabase, "(THREAD) Main work loop starting");
@@ -1391,7 +1391,7 @@
             // has asked to delay pruning
             static bool prunedUnretainedIcons = false;
             if (didWrite && !m_privateBrowsingEnabled && !prunedUnretainedIcons && !databaseCleanupCounter) {
-#if !LOG_DISABLED
+#ifndef NDEBUG
                 double time = currentTime();
 #endif
                 LOG(IconDatabase, "(THREAD) Starting pruneUnretainedIcons()");
@@ -1410,7 +1410,7 @@
                 break;
         }
         
-#if !LOG_DISABLED
+#ifndef NDEBUG
         double newstamp = currentTime();
         LOG(IconDatabase, "(THREAD) Main work loop ran for %.4f seconds, %s requested to terminate", newstamp - timeStamp, shouldStopThreadActivity() ? "was" : "was not");
 #endif
@@ -1458,7 +1458,7 @@
 {
     ASSERT_ICON_SYNC_THREAD();
     
-#if !LOG_DISABLED
+#ifndef NDEBUG
     double timeStamp = currentTime();
 #endif
 
@@ -1567,7 +1567,7 @@
 {
     ASSERT_ICON_SYNC_THREAD();
 
-#if !LOG_DISABLED
+#ifndef NDEBUG
     double timeStamp = currentTime();
 #endif
 
@@ -1772,7 +1772,7 @@
 {
     ASSERT_ICON_SYNC_THREAD();
     
-#if !LOG_DISABLED
+#ifndef NDEBUG
     double timeStamp = currentTime();
 #endif 
 
@@ -1792,7 +1792,7 @@
     deleteAllPreparedStatements();    
     m_syncDB.close();
     
-#if !LOG_DISABLED
+#ifndef NDEBUG
     LOG(IconDatabase, "(THREAD) Final closure took %.4f seconds", currentTime() - timeStamp);
 #endif
     
diff --git a/Source/WebCore/page/DOMWindow.idl b/Source/WebCore/page/DOMWindow.idl
index d5d3413..9f7313c 100644
--- a/Source/WebCore/page/DOMWindow.idl
+++ b/Source/WebCore/page/DOMWindow.idl
@@ -510,7 +510,6 @@
         attribute [JSCCustomGetter] Int32ArrayConstructor Int32Array; // Usable with new operator
         attribute [JSCCustomGetter] Uint32ArrayConstructor Uint32Array; // Usable with new operator
         attribute [JSCCustomGetter] Float32ArrayConstructor Float32Array; // Usable with new operator
-        attribute [JSCCustomGetter] Float64ArrayConstructor Float64Array; // Usable with new operator 
         attribute [JSCCustomGetter] DataViewConstructor DataView; // Usable with new operator
 
         attribute [JSCCustomGetter,Conditional=WEB_AUDIO,EnabledAtRuntime] AudioContextConstructor webkitAudioContext; // Usable with new operator
diff --git a/Source/WebCore/page/EventHandler.cpp b/Source/WebCore/page/EventHandler.cpp
index cbe01ed..e77809c 100644
--- a/Source/WebCore/page/EventHandler.cpp
+++ b/Source/WebCore/page/EventHandler.cpp
@@ -2415,10 +2415,16 @@
     if (!doc)
         return 0;
     Node* node = doc->focusedNode();
+#if defined(ANDROID_PLUGINS)
+    if (!node && doc->frame() && doc->frame()->view())
+        node = android::WebViewCore::getWebViewCore(doc->frame()->view())
+                                     ->cursorNodeIsPlugin();
+#else
     if (!node && doc->isPluginDocument()) {
         PluginDocument* pluginDocument = static_cast<PluginDocument*>(doc);
         node =  pluginDocument->pluginNode();
     }
+#endif
     if (!node && doc->isHTMLDocument())
         node = doc->body();
     if (!node)
@@ -3224,7 +3230,15 @@
         // When sending a touch cancel event, use empty touches and targetTouches lists.
         bool isTouchCancelEvent = (state == PlatformTouchPoint::TouchCancelled);
         RefPtr<TouchList>& effectiveTouches(isTouchCancelEvent ? emptyList : touches);
+#if PLATFORM(ANDROID)
+        AtomicString stateName(eventNameForTouchPointState(static_cast<PlatformTouchPoint::State>(state)));
+        if (event.type() == TouchLongPress)
+            stateName = eventNames().touchlongpressEvent;
+        else if (event.type() == TouchDoubleTap)
+            stateName = eventNames().touchdoubletapEvent;
+#else
         const AtomicString& stateName(eventNameForTouchPointState(static_cast<PlatformTouchPoint::State>(state)));
+#endif
         const EventTargetSet& targetsForState = changedTouches[state].m_targets;
 
         for (EventTargetSet::const_iterator it = targetsForState.begin(); it != targetsForState.end(); ++it) {
@@ -3239,10 +3253,6 @@
             ExceptionCode ec = 0;
             touchEventTarget->dispatchEvent(touchEvent.get(), ec);
             defaultPrevented |= touchEvent->defaultPrevented();
-#if PLATFORM(ANDROID)
-            if (touchEvent->hitTouchHandler())
-                const_cast<PlatformTouchEvent&>(event).setHitTouchHandler();
-#endif
         }
     }
 
diff --git a/Source/WebCore/page/Frame.cpp b/Source/WebCore/page/Frame.cpp
index 049f08b..8a1ad69 100644
--- a/Source/WebCore/page/Frame.cpp
+++ b/Source/WebCore/page/Frame.cpp
@@ -113,6 +113,10 @@
 #include "WMLNames.h"
 #endif
 
+#if PLATFORM(ANDROID)
+#include "WebViewCore.h"
+#endif
+
 using namespace std;
 
 namespace WebCore {
diff --git a/Source/WebCore/page/FrameView.cpp b/Source/WebCore/page/FrameView.cpp
index 8f2958c..49a7d0c 100644
--- a/Source/WebCore/page/FrameView.cpp
+++ b/Source/WebCore/page/FrameView.cpp
@@ -62,6 +62,11 @@
 #include "TextResourceDecoder.h"
 #include <wtf/CurrentTime.h>
 
+#ifdef ANDROID_INSTRUMENT
+#include "FrameTree.h"
+#include "TimeCounter.h"
+#endif
+
 #if USE(ACCELERATED_COMPOSITING)
 #include "RenderLayerCompositor.h"
 #endif
@@ -867,6 +872,11 @@
         return;
     }
 
+#ifdef ANDROID_INSTRUMENT
+    if (!m_frame->tree() || !m_frame->tree()->parent())
+        android::TimeCounter::start(android::TimeCounter::LayoutTimeCounter);
+#endif
+
     m_nestedLayoutCount++;
 
     if (!m_layoutRoot) {
@@ -1004,6 +1014,10 @@
     updateDashboardRegions();
 #endif
 
+#ifdef ANDROID_INSTRUMENT
+    if (!m_frame->tree()->parent())
+        android::TimeCounter::record(android::TimeCounter::LayoutTimeCounter, __FUNCTION__);
+#endif
     ASSERT(!root->needsLayout());
 
     updateCanBlitOnScrollRecursively();
@@ -1738,6 +1752,11 @@
     if (!m_frame->document()->shouldScheduleLayout())
         return;
 
+#ifdef ANDROID_FLATTEN_FRAMESET
+    if (m_frame->ownerRenderer())
+        m_frame->ownerRenderer()->setNeedsLayoutAndPrefWidthsRecalc();
+#endif
+
     // When frame flattening is enabled, the contents of the frame affects layout of the parent frames.
     // Also invalidate parent frame starting from the owner element of this frame.
     if (m_frame->settings() && m_frame->settings()->frameFlatteningEnabled() && m_frame->ownerRenderer()) {
@@ -1745,11 +1764,6 @@
             m_frame->ownerRenderer()->setNeedsLayout(true, true);
     }
 
-#ifdef ANDROID_FLATTEN_FRAMESET
-    if (m_frame->ownerRenderer() && m_frame->ownerElement()->hasTagName(frameTag))
-        m_frame->ownerRenderer()->setNeedsLayoutAndPrefWidthsRecalc();
-#endif
-
     int delay = m_frame->document()->minimumLayoutDelay();
     if (m_layoutTimer.isActive() && m_delayedLayout && !delay)
         unscheduleRelayout();
diff --git a/Source/WebCore/page/Location.cpp b/Source/WebCore/page/Location.cpp
index fb68a09..4835a83 100644
--- a/Source/WebCore/page/Location.cpp
+++ b/Source/WebCore/page/Location.cpp
@@ -63,7 +63,8 @@
     if (!m_frame)
         return String();
 
-    return url().string();
+    const KURL& url = this->url();
+    return url.hasPath() ? url.prettyURL() : url.prettyURL() + "/";
 }
 
 String Location::protocol() const
@@ -82,7 +83,7 @@
     // Note: this is the IE spec. The NS spec swaps the two, it says
     // "The hostname property is the concatenation of the host and port properties, separated by a colon."
     const KURL& url = this->url();
-    return url.hasPort() ? url.host() + ":" + String::number(url.port()) : url.host();
+    return url.port() ? url.host() + ":" + String::number(url.port()) : url.host();
 }
 
 String Location::hostname() const
@@ -99,7 +100,7 @@
         return String();
 
     const KURL& url = this->url();
-    return url.hasPort() ? String::number(url.port()) : "";
+    return url.port() ? String::number(url.port()) : "";
 }
 
 String Location::pathname() const
@@ -146,6 +147,15 @@
     return parameters.get(name);
 }
 
+String Location::toString() const
+{
+    if (!m_frame)
+        return String();
+
+    const KURL& url = this->url();
+    return url.hasPath() ? url.prettyURL() : url.prettyURL() + "/";
+}
+
 void Location::setHref(const String& urlString, DOMWindow* activeWindow, DOMWindow* firstWindow)
 {
     if (!m_frame)
@@ -189,7 +199,7 @@
         return;
     KURL url = m_frame->document()->url();
     int port = portString.toInt();
-    if (port < 0 || port > 0xFFFF || portString.isEmpty())
+    if (port < 0 || port > 0xFFFF)
         url.removePort();
     else
         url.setPort(port);
diff --git a/Source/WebCore/page/Location.h b/Source/WebCore/page/Location.h
index 0e89ecf..1b68cee 100644
--- a/Source/WebCore/page/Location.h
+++ b/Source/WebCore/page/Location.h
@@ -29,9 +29,9 @@
 #ifndef Location_h
 #define Location_h
 
+#include <wtf/Forward.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
-#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
@@ -71,7 +71,7 @@
     String hash() const;
     String origin() const;
 
-    String toString() const { return href(); }
+    String toString() const;
 
     String getParameter(const String&) const;
 
diff --git a/Source/WebCore/page/Settings.cpp b/Source/WebCore/page/Settings.cpp
index f668f3e..e2312a9 100644
--- a/Source/WebCore/page/Settings.cpp
+++ b/Source/WebCore/page/Settings.cpp
@@ -98,7 +98,6 @@
 #ifdef ANDROID_LAYOUT
     , m_layoutAlgorithm(kLayoutFitColumnToScreen)
 #endif
-    , m_passwordEchoDurationInSeconds(1)
     , m_isSpatialNavigationEnabled(false)
     , m_isJavaEnabled(false)
     , m_loadsImagesAutomatically(false)
@@ -149,9 +148,6 @@
     // they can't use by. Leaving enabled for now to not change existing behavior.
     , m_downloadableBinaryFontsEnabled(true)
     , m_xssAuditorEnabled(false)
-#if ENABLE(LINK_PREFETCH)
-    , m_linkPrefetchEnabled(true)
-#endif
     , m_acceleratedCompositingEnabled(true)
     , m_acceleratedCompositingFor3DTransformsEnabled(true)
     , m_acceleratedCompositingForVideoEnabled(true)
@@ -196,11 +192,6 @@
 #ifdef ANDROID_PLUGINS
     , m_pluginsOnDemand(false)
 #endif
-#if OS(SYMBIAN)
-    , m_passwordEchoEnabled(true)
-#else
-    , m_passwordEchoEnabled(false)
-#endif
 {
     // A Frame may not have been created yet, so we initialize the AtomicString 
     // hash before trying to use it.
@@ -826,13 +817,6 @@
     m_xssAuditorEnabled = xssAuditorEnabled;
 }
 
-#if ENABLE(LINK_PREFETCH)
-void Settings::setLinkPrefetchEnabled(bool linkPrefetchEnabled)
-{
-    m_linkPrefetchEnabled = linkPrefetchEnabled;
-}
-#endif
-
 void Settings::setAcceleratedCompositingEnabled(bool enabled)
 {
     if (m_acceleratedCompositingEnabled == enabled)
diff --git a/Source/WebCore/page/Settings.h b/Source/WebCore/page/Settings.h
index 2cf7715..31a5ad9 100644
--- a/Source/WebCore/page/Settings.h
+++ b/Source/WebCore/page/Settings.h
@@ -352,11 +352,6 @@
         void setXSSAuditorEnabled(bool);
         bool xssAuditorEnabled() const { return m_xssAuditorEnabled; }
 
-#if ENABLE(LINK_PREFETCH)
-        void setLinkPrefetchEnabled(bool);
-        bool linkPrefetchEnabled() const { return m_linkPrefetchEnabled; }
-#endif
-
         void setCanvasUsesAcceleratedDrawing(bool);
         bool canvasUsesAcceleratedDrawing() const { return m_canvasUsesAcceleratedDrawing; }
 
@@ -463,12 +458,6 @@
         void setShouldInjectUserScriptsInInitialEmptyDocument(bool flag) { m_shouldInjectUserScriptsInInitialEmptyDocument = flag; }
         bool shouldInjectUserScriptsInInitialEmptyDocument() { return m_shouldInjectUserScriptsInInitialEmptyDocument; }
 
-        void setPasswordEchoEnabled(bool flag) { m_passwordEchoEnabled = flag; }
-        bool passwordEchoEnabled() const { return m_passwordEchoEnabled; }
-
-        void setPasswordEchoDurationInSeconds(double durationInSeconds) { m_passwordEchoDurationInSeconds = durationInSeconds; }
-        double passwordEchoDurationInSeconds() const { return m_passwordEchoDurationInSeconds; }
-
 #if ENABLE(WEB_AUTOFILL)
         void setAutoFillEnabled(bool flag) { m_autoFillEnabled = flag; }
         bool autoFillEnabled() { return m_autoFillEnabled; }
@@ -522,8 +511,6 @@
 #ifdef ANDROID_LAYOUT
         LayoutAlgorithm m_layoutAlgorithm;
 #endif
-        double m_passwordEchoDurationInSeconds;
-
         bool m_isSpatialNavigationEnabled : 1;
         bool m_isJavaEnabled : 1;
         bool m_loadsImagesAutomatically : 1;
@@ -572,9 +559,6 @@
         bool m_acceleratedDrawingEnabled : 1;
         bool m_downloadableBinaryFontsEnabled : 1;
         bool m_xssAuditorEnabled : 1;
-#if ENABLE(LINK_PREFETCH)
-        bool m_linkPrefetchEnabled : 1;
-#endif
         bool m_acceleratedCompositingEnabled : 1;
         bool m_acceleratedCompositingFor3DTransformsEnabled : 1;
         bool m_acceleratedCompositingForVideoEnabled : 1;
@@ -633,7 +617,6 @@
 #ifdef ANDROID_PLUGINS
         bool m_pluginsOnDemand : 1;
 #endif
-        bool m_passwordEchoEnabled : 1;
 
 #if USE(SAFARI_THEME)
         static bool gShouldPaintNativeControls;
diff --git a/Source/WebCore/platform/Arena.cpp b/Source/WebCore/platform/Arena.cpp
index 33980ed..231e1b6 100644
--- a/Source/WebCore/platform/Arena.cpp
+++ b/Source/WebCore/platform/Arena.cpp
@@ -255,4 +255,16 @@
     FreeArenaList(pool, &pool->first, true);
 }
 
+#ifdef ANDROID_INSTRUMENT
+size_t ReportPoolSize(const ArenaPool* pool)
+{
+    size_t total = 0;
+    for (const Arena *a = &pool->first; a; a = a->next)
+        total += (a->limit - a->base);
+    for (const Arena *fa = arena_freelist; fa; fa = fa->next )
+        total += (fa->limit - fa->base);
+    return total;
+}
+#endif
+
 }
diff --git a/Source/WebCore/platform/Arena.h b/Source/WebCore/platform/Arena.h
index 06e09f2..e937955 100644
--- a/Source/WebCore/platform/Arena.h
+++ b/Source/WebCore/platform/Arena.h
@@ -134,6 +134,10 @@
          fastFree(a); \
          (a) = 0;
 
+#ifdef ANDROID_INSTRUMENT
+size_t ReportPoolSize(const ArenaPool* pool);
+#endif
+
 }
 
 #endif
diff --git a/Source/WebCore/platform/FileChooser.h b/Source/WebCore/platform/FileChooser.h
index 6c382d1..ac5e0e6 100644
--- a/Source/WebCore/platform/FileChooser.h
+++ b/Source/WebCore/platform/FileChooser.h
@@ -50,9 +50,6 @@
     virtual String acceptTypes() = 0;
     virtual void chooseIconForFiles(FileChooser*, const Vector<String>&) = 0;
     virtual ~FileChooserClient();
-#if PLATFORM(ANDROID) && ENABLE(MEDIA_CAPTURE)
-    virtual String capture() = 0;
-#endif
 };
 
 class FileChooser : public RefCounted<FileChooser> {
@@ -82,10 +79,6 @@
     // Acceptable MIME types.  It's an 'accept' attribute value of the corresponding INPUT element.
     String acceptTypes() const { return m_client ? m_client->acceptTypes() : String(); }
 
-#if PLATFORM(ANDROID) && ENABLE(MEDIA_CAPTURE)
-    String capture() const { return m_client ? m_client->capture() : String(); }
-#endif
-
 private:
     FileChooser(FileChooserClient*, const Vector<String>& initialFilenames);
     void initialize();
diff --git a/Source/WebCore/platform/KURL.cpp b/Source/WebCore/platform/KURL.cpp
index 234d749..88ad3d9 100644
--- a/Source/WebCore/platform/KURL.cpp
+++ b/Source/WebCore/platform/KURL.cpp
@@ -708,7 +708,7 @@
 
 String KURL::path() const
 {
-    return m_string.substring(m_portEnd, m_pathEnd - m_portEnd);
+    return decodeURLEscapeSequences(m_string.substring(m_portEnd, m_pathEnd - m_portEnd)); 
 }
 
 bool KURL::setProtocol(const String& s)
@@ -866,7 +866,7 @@
     parse(m_string.left(m_portEnd) + encodeWithURLEscapeSequences(path) + m_string.substring(m_pathEnd));
 }
 
-String KURL::deprecatedString() const
+String KURL::prettyURL() const
 {
     if (!m_isValid)
         return m_string;
@@ -996,7 +996,7 @@
     buffer = p;
 }
 
-static void escapeAndAppendNonHierarchicalPart(char*& buffer, const char* strStart, size_t length)
+static void escapeAndAppendFragment(char*& buffer, const char* strStart, size_t length)
 {
     char* p = buffer;
 
@@ -1137,23 +1137,6 @@
     return userEndChar == '@' && hostStart == portEnd;
 }
 
-static bool isNonFileHierarchicalScheme(const char* scheme, size_t schemeLength)
-{
-    switch (schemeLength) {
-    case 2:
-        return equal("ws", 2, scheme, schemeLength);
-    case 3:
-        return equal("ftp", 3, scheme, schemeLength) || equal("wss", 3, scheme, schemeLength);
-    case 4:
-        return equal("http", 4, scheme, schemeLength);
-    case 5:
-        return equal("https", 5, scheme, schemeLength);
-    case 6:
-        return equal("gopher", 6, scheme, schemeLength);
-    }
-    return false;
-}
-
 void KURL::parse(const char* url, const String* originalString)
 {
     if (!url || url[0] == '\0') {
@@ -1190,7 +1173,6 @@
     int portEnd;
 
     bool hierarchical = url[schemeEnd + 1] == '/';
-    bool hasSecondSlash = hierarchical && url[schemeEnd + 2] == '/';
 
     bool isFile = schemeEnd == 4
         && matchLetter(url[0], 'f')
@@ -1204,15 +1186,12 @@
         && matchLetter(url[3], 'p')
         && (url[4] == ':' || (matchLetter(url[4], 's') && url[5] == ':'));
 
-    if ((hierarchical && hasSecondSlash) || isNonFileHierarchicalScheme(url, schemeEnd)) {
+    if (hierarchical && url[schemeEnd + 2] == '/') {
         // The part after the scheme is either a net_path or an abs_path whose first path segment is empty.
         // Attempt to find an authority.
-        // FIXME: Authority characters may be scanned twice, and it would be nice to be faster.
 
-        if (hierarchical)
-            userStart++;
-        if (hasSecondSlash)
-            userStart++;
+        // FIXME: Authority characters may be scanned twice, and it would be nice to be faster.
+        userStart += 2;
         userEnd = userStart;
 
         int colonPos = 0;
@@ -1415,14 +1394,12 @@
         m_userStart = m_userEnd = m_passwordEnd = m_hostEnd = m_portEnd = p - buffer.data();
 
     // For canonicalization, ensure we have a '/' for no path.
-    // Do this only for URL with protocol http or https.
-    if (m_protocolInHTTPFamily && pathEnd == pathStart)
+    // Do this only for hierarchical URL with protocol http or https.
+    if (m_protocolInHTTPFamily && hierarchical && pathEnd == pathStart)
         *p++ = '/';
 
     // add path, escaping bad characters
-    if (!hierarchical)
-        escapeAndAppendNonHierarchicalPart(p, url + pathStart, pathEnd - pathStart);
-    else if (!hasSlashDotOrDotDot(url))
+    if (!hierarchical || !hasSlashDotOrDotDot(url))
         appendEscapingBadChars(p, url + pathStart, pathEnd - pathStart);
     else {
         CharBuffer pathBuffer(pathEnd - pathStart + 1);
@@ -1448,7 +1425,7 @@
     // add fragment, escaping bad characters
     if (fragmentEnd != queryEnd) {
         *p++ = '#';
-        escapeAndAppendNonHierarchicalPart(p, url + fragmentStart, fragmentEnd - fragmentStart);
+        escapeAndAppendFragment(p, url + fragmentStart, fragmentEnd - fragmentStart);
     }
     m_fragmentEnd = p - buffer.data();
 
diff --git a/Source/WebCore/platform/KURL.h b/Source/WebCore/platform/KURL.h
index 192c10b..db2dd42 100644
--- a/Source/WebCore/platform/KURL.h
+++ b/Source/WebCore/platform/KURL.h
@@ -152,9 +152,7 @@
 
     String baseAsString() const;
 
-    // This function is only used by location.href. It's likely we shouldn't
-    // use it for that purpose, but more study is necessary before we remove it.
-    String deprecatedString() const;
+    String prettyURL() const;
     String fileSystemPath() const;
 
     // Returns true if the current URL's protocol is the same as the null-
diff --git a/Source/WebCore/platform/KURLGoogle.cpp b/Source/WebCore/platform/KURLGoogle.cpp
index 54bcf16..0d11b99 100644
--- a/Source/WebCore/platform/KURLGoogle.cpp
+++ b/Source/WebCore/platform/KURLGoogle.cpp
@@ -593,6 +593,7 @@
 
 String KURL::path() const
 {
+    // Note: KURL.cpp unescapes here.
     return m_url.componentString(m_url.m_parsed.path);
 }
 
@@ -669,12 +670,16 @@
 {
     KURLGooglePrivate::Replacements replacements;
     String portStr;
+    if (i) {
+        portStr = String::number(i);
+        replacements.SetPort(
+            reinterpret_cast<const url_parse::UTF16Char*>(portStr.characters()),
+            url_parse::Component(0, portStr.length()));
 
-    portStr = String::number(i);
-    replacements.SetPort(
-        reinterpret_cast<const url_parse::UTF16Char*>(portStr.characters()),
-        url_parse::Component(0, portStr.length()));
-
+    } else {
+        // Clear any existing port when it is set to 0.
+        replacements.ClearPort();
+    }
     m_url.replaceComponents(replacements);
 }
 
@@ -767,7 +772,7 @@
 // On Mac, this just seems to return the same URL, but with "/foo/bar" for
 // file: URLs instead of file:///foo/bar. We don't bother with any of this,
 // at least for now.
-String KURL::deprecatedString() const
+String KURL::prettyURL() const
 {
     if (!m_url.m_isValid)
         return String();
diff --git a/Source/WebCore/platform/NotImplemented.h b/Source/WebCore/platform/NotImplemented.h
index e9758b0..a71e99c 100644
--- a/Source/WebCore/platform/NotImplemented.h
+++ b/Source/WebCore/platform/NotImplemented.h
@@ -38,7 +38,21 @@
     #define supressNotImplementedWarning() false
 #endif
 
-#if defined(NDEBUG)
+#if OS(ANDROID)
+
+#include <cutils/log.h>
+#ifndef LOG_TAG
+#define LOG_TAG "WebCore"
+#endif
+#define notImplemented() do { \
+        static bool havePrinted = false; \
+        if (!havePrinted && !supressNotImplementedWarning()) { \
+            LOGV("%s: notImplemented", __PRETTY_FUNCTION__); \
+            havePrinted = true; \
+        } \
+    } while (0)
+
+#elif defined(NDEBUG)
     #define notImplemented() ((void)0)
 #else
 
diff --git a/Source/WebCore/platform/PlatformTouchEvent.h b/Source/WebCore/platform/PlatformTouchEvent.h
index d1de018..2ca7c99 100644
--- a/Source/WebCore/platform/PlatformTouchEvent.h
+++ b/Source/WebCore/platform/PlatformTouchEvent.h
@@ -52,6 +52,10 @@
     , TouchMove
     , TouchEnd
     , TouchCancel
+#if PLATFORM(ANDROID)
+    , TouchLongPress
+    , TouchDoubleTap
+#endif
 };
 
 class PlatformTouchEvent {
@@ -68,8 +72,6 @@
     PlatformTouchEvent(QTouchEvent*);
 #elif PLATFORM(ANDROID)
     PlatformTouchEvent(const Vector<int>&, const Vector<IntPoint>&, TouchEventType, const Vector<PlatformTouchPoint::State>&, int metaState);
-    bool hitTouchHandler() { return m_hitTouchHandler; }
-    void setHitTouchHandler() { m_hitTouchHandler = true; }
 #elif PLATFORM(BREWMP)
     PlatformTouchEvent(AEEEvent, uint16 wParam, uint32 dwParam);
 #elif PLATFORM(EFL)
@@ -95,9 +97,6 @@
     bool m_shiftKey;
     bool m_metaKey;
     double m_timestamp;
-#if PLATFORM(ANDROID)
-    bool m_hitTouchHandler;
-#endif
 };
 
 }
diff --git a/Source/WebCore/platform/ScrollView.cpp b/Source/WebCore/platform/ScrollView.cpp
index 864fdc5..e79f049 100644
--- a/Source/WebCore/platform/ScrollView.cpp
+++ b/Source/WebCore/platform/ScrollView.cpp
@@ -27,13 +27,6 @@
 #include "ScrollView.h"
 
 #include "AXObjectCache.h"
-#if PLATFORM(ANDROID)
-#include "FrameView.h"
-#include "GraphicsLayerAndroid.h"
-#include "RenderLayer.h"
-#include "RenderLayerBacking.h"
-#include "RenderView.h"
-#endif
 #include "GraphicsContext.h"
 #include "GraphicsLayer.h"
 #include "HostWindow.h"
@@ -308,37 +301,33 @@
 }
 
 #if PLATFORM(ANDROID)
-int ScrollView::actualWidth() const {
+int ScrollView::actualWidth() const
+{
     if (platformWidget())
         return platformActualWidth();
     return width();
 }
 
-int ScrollView::actualHeight() const {
+int ScrollView::actualHeight() const
+{
     if (platformWidget())
         return platformActualHeight();
     return height();
 }
 
-int ScrollView::actualScrollX() const {
+int ScrollView::actualScrollX() const
+{
     if (platformWidget())
         return platformActualScrollX();
     return scrollX();
 }
 
-int ScrollView::actualScrollY() const {
+int ScrollView::actualScrollY() const
+{
     if (platformWidget())
         return platformActualScrollY();
     return scrollY();
 }
-
-FrameView* ScrollView::frameView() {
-    if (this->isFrameView()) {
-        FrameView* frameView = reinterpret_cast<FrameView*>(this);
-        return frameView;
-    }
-    return 0;
-}
 #endif
 
 IntPoint ScrollView::maximumScrollPosition() const
@@ -397,26 +386,6 @@
         return;
     m_scrollOffset = newOffset;
 
-#if PLATFORM(ANDROID)
-    if (parent()) {
-        FrameView* frameView = this->frameView();
-        // IFrames are composited on a layer, we do not need to repaint them
-        // when scrolling
-        if (frameView) {
-            RenderView* renderer = frameView->frame()->contentRenderer();
-            if (renderer) {
-                RenderLayer* layer = renderer->layer();
-                if (layer->backing()) {
-                    GraphicsLayerAndroid* backing = static_cast<GraphicsLayerAndroid*>(
-                        layer->backing()->graphicsLayer());
-                    backing->updateScrollOffset();
-                }
-            }
-            return;
-        }
-    }
-#endif
-
     if (scrollbarsSuppressed())
         return;
 
diff --git a/Source/WebCore/platform/ScrollView.h b/Source/WebCore/platform/ScrollView.h
index 3228870..558aee2 100644
--- a/Source/WebCore/platform/ScrollView.h
+++ b/Source/WebCore/platform/ScrollView.h
@@ -53,10 +53,6 @@
 class HostWindow;
 class Scrollbar;
 
-#if PLATFORM(ANDROID)
-class FrameView;
-#endif
-
 class ScrollView : public Widget, public ScrollableArea {
 public:
     ~ScrollView();
@@ -176,7 +172,6 @@
     int actualHeight() const;
     int actualScrollX() const;
     int actualScrollY() const;
-    FrameView* frameView();
 #endif
 
     // Functions for querying the current scrolled position (both as a point, a size, or as individual X and Y values).
diff --git a/Source/WebCore/platform/android/KeyEventAndroid.cpp b/Source/WebCore/platform/android/KeyEventAndroid.cpp
index dd1f37d..eaf34a9 100644
--- a/Source/WebCore/platform/android/KeyEventAndroid.cpp
+++ b/Source/WebCore/platform/android/KeyEventAndroid.cpp
@@ -33,7 +33,7 @@
 
 #include "NotImplemented.h"
 #include "WindowsKeyboardCodes.h"
-#include <androidfw/KeycodeLabels.h>
+#include <ui/KeycodeLabels.h>
 
 namespace WebCore {
 
@@ -191,7 +191,7 @@
         return "U+00007F";
     default:
         char upper[16];
-        sprintf(upper, "U+%04X", windowsKeyCodeForKeyEvent(keyCode));
+        sprintf(upper, "U+%06X", windowsKeyCodeForKeyEvent(keyCode));
         return String(upper);
     }
 }
diff --git a/Source/WebCore/platform/android/PlatformTouchEventAndroid.cpp b/Source/WebCore/platform/android/PlatformTouchEventAndroid.cpp
index 579461a..dd06400 100644
--- a/Source/WebCore/platform/android/PlatformTouchEventAndroid.cpp
+++ b/Source/WebCore/platform/android/PlatformTouchEventAndroid.cpp
@@ -42,7 +42,6 @@
     : m_type(type)
     , m_metaKey(false)
     , m_timestamp(WTF::currentTime())
-    , m_hitTouchHandler(false)
 {
     m_touchPoints.reserveCapacity(windowPoints.size());
     for (unsigned c = 0; c < windowPoints.size(); c++)
diff --git a/Source/WebCore/platform/android/PopupMenuAndroid.cpp b/Source/WebCore/platform/android/PopupMenuAndroid.cpp
index a5758bb..f4c351f 100644
--- a/Source/WebCore/platform/android/PopupMenuAndroid.cpp
+++ b/Source/WebCore/platform/android/PopupMenuAndroid.cpp
@@ -25,13 +25,10 @@
 #include "config.h"
 #include "PopupMenuAndroid.h"
 
-#include "IntRect.h"
 #include "PopupMenuClient.h"
 #include "SkTDArray.h"
 #include "WebViewCore.h"
 
-using namespace WebCore;
-
 class PopupReply : public android::WebCoreReply {
 public:
     PopupReply(const IntRect& rect, android::WebViewCore* view, ListPopupMenuClient* client)
diff --git a/Source/WebCore/platform/android/RenderThemeAndroid.cpp b/Source/WebCore/platform/android/RenderThemeAndroid.cpp
index 86380e7..93c99a4 100644
--- a/Source/WebCore/platform/android/RenderThemeAndroid.cpp
+++ b/Source/WebCore/platform/android/RenderThemeAndroid.cpp
@@ -38,8 +38,10 @@
 #include "RenderMediaControls.h"
 #endif
 #include "RenderSkinAndroid.h"
+#include "RenderSkinButton.h"
+#include "RenderSkinCombo.h"
 #include "RenderSkinMediaButton.h"
-#include "RoundedIntRect.h"
+#include "RenderSkinRadio.h"
 #include "SkCanvas.h"
 #include "UserAgentStyleSheets.h"
 #include "WebCoreFrameBridge.h"
@@ -61,34 +63,9 @@
 
 const RGBA32 selectionColor = makeRGB(181, 224, 136);
 
-// Colors copied from the holo resources
-const RGBA32 defaultBgColor = makeRGBA(204, 204, 204, 197);
-const RGBA32 defaultBgBright = makeRGBA(213, 213, 213, 221);
-const RGBA32 defaultBgDark = makeRGBA(92, 92, 92, 160);
-const RGBA32 defaultBgMedium = makeRGBA(132, 132, 132, 111);
-const RGBA32 defaultFgColor = makeRGBA(101, 101, 101, 225);
-const RGBA32 defaultCheckColor = makeRGBA(154, 204, 2, 255);
-
-const RGBA32 disabledBgColor = makeRGBA(205, 205, 205, 107);
-const RGBA32 disabledBgBright = makeRGBA(213, 213, 213, 133);
-const RGBA32 disabledBgDark = makeRGBA(92, 92, 92, 96);
-const RGBA32 disabledBgMedium = makeRGBA(132, 132, 132, 111);
-const RGBA32 disabledFgColor = makeRGBA(148, 148, 148, 137);
-
-const int paddingButton = 2;
-const int cornerButton = 2;
-
-// scale factors for various resolutions
-const float scaleFactor[RenderSkinAndroid::ResolutionCount] = {
-    1.0f, // medium res
-    1.5f, // high res
-    2.0f  // extra high res
-};
-
-
 static SkCanvas* getCanvasFromInfo(const PaintInfo& info)
 {
-    return info.context->platformContext()->getCanvas();
+    return info.context->platformContext()->mCanvas;
 }
 
 static android::WebFrame* getWebFrame(const Node* node)
@@ -181,16 +158,6 @@
     return Color(Color::transparent);
 }
 
-Color RenderThemeAndroid::platformActiveTextSearchHighlightColor() const
-{
-    return Color(0x00, 0x99, 0xcc, 0x99); // HOLO_DARK
-}
-
-Color RenderThemeAndroid::platformInactiveTextSearchHighlightColor() const
-{
-    return Color(0x33, 0xb5, 0xe5, 0x66); // HOLO_LIGHT
-}
-
 int RenderThemeAndroid::baselinePosition(const RenderObject* obj) const
 {
     // From the description of this function in RenderTheme.h:
@@ -199,7 +166,7 @@
     // controls that need to do this.
     //
     // Our checkboxes and radio buttons need to be offset to line up properly.
-    return RenderTheme::baselinePosition(obj) - 8;
+    return RenderTheme::baselinePosition(obj) - 2;
 }
 
 void RenderThemeAndroid::addIntrinsicMargins(RenderStyle* style) const
@@ -207,10 +174,10 @@
     // Cut out the intrinsic margins completely if we end up using a small font size
     if (style->fontSize() < 11)
         return;
-
+    
     // Intrinsic margin value.
     const int m = 2;
-
+    
     // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
     if (style->width().isIntrinsicOrAuto()) {
         if (style->marginLeft().quirk())
@@ -243,11 +210,22 @@
 
 void RenderThemeAndroid::adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, WebCore::Element*) const
 {
+    // Code is taken from RenderThemeSafari.cpp
+    // It makes sure we have enough space for the button text.
+    const int paddingHoriz = 12;
+    const int paddingVert = 8;
+    style->setPaddingLeft(Length(paddingHoriz, Fixed));
+    style->setPaddingRight(Length(paddingHoriz, Fixed));
+    style->setPaddingTop(Length(paddingVert, Fixed));
+    style->setPaddingBottom(Length(paddingVert, Fixed));
+
+    // Set a min-height so that we can't get smaller than the mini button.
+    style->setMinHeight(Length(15, Fixed));
 }
 
 bool RenderThemeAndroid::paintCheckbox(RenderObject* obj, const PaintInfo& info, const IntRect& rect)
 {
-    paintRadio(obj, info, rect);
+    RenderSkinRadio::Draw(getCanvasFromInfo(info), obj->node(), rect, true);
     return false;
 }
 
@@ -259,50 +237,16 @@
     if (formControlElement) {
         android::WebFrame* webFrame = getWebFrame(node);
         if (webFrame) {
-            GraphicsContext *context = info.context;
-            IntRect innerrect = IntRect(rect.x() + paddingButton, rect.y() + paddingButton,
-                    rect.width() - 2 * paddingButton, rect.height() - 2 * paddingButton);
-            IntSize cornerrect = IntSize(cornerButton, cornerButton);
-            Color bg, bright, dark, medium;
-            if (formControlElement->isEnabledFormControl()) {
-                bg = Color(defaultBgColor);
-                bright = Color(defaultBgBright);
-                dark = Color(defaultBgDark);
-                medium = Color(defaultBgMedium);
-            } else {
-                bg = Color(disabledBgColor);
-                bright = Color(disabledBgBright);
-                dark = Color(disabledBgDark);
-                medium = Color(disabledBgMedium);
+            RenderSkinAndroid* skins = webFrame->renderSkins();
+            if (skins) {
+                RenderSkinAndroid::State state = RenderSkinAndroid::kNormal;
+                if (!formControlElement->isEnabledFormControl())
+                    state = RenderSkinAndroid::kDisabled;
+                skins->renderSkinButton()->draw(getCanvasFromInfo(info), rect, state);
             }
-            context->save();
-            context->clip(
-                    IntRect(innerrect.x(), innerrect.y(), innerrect.width(), 1));
-            context->fillRoundedRect(innerrect, cornerrect, cornerrect,
-                    cornerrect, cornerrect, bright, context->fillColorSpace());
-            context->restore();
-            context->save();
-            context->clip(IntRect(innerrect.x(), innerrect.y() + innerrect.height() - 1,
-                    innerrect.width(), 1));
-            context->fillRoundedRect(innerrect, cornerrect, cornerrect,
-                    cornerrect, cornerrect, dark, context->fillColorSpace());
-            context->restore();
-            context->save();
-            context->clip(IntRect(innerrect.x(), innerrect.y() + 1, innerrect.width(),
-                    innerrect.height() - 2));
-            context->fillRoundedRect(innerrect, cornerrect, cornerrect,
-                    cornerrect, cornerrect, bg, context->fillColorSpace());
-            context->restore();
-            context->setStrokeColor(medium, context->strokeColorSpace());
-            context->setStrokeThickness(1.0f);
-            context->drawLine(IntPoint(innerrect.x(), innerrect.y() + cornerButton),
-                    IntPoint(innerrect.x(), innerrect.y() + innerrect.height() - cornerButton));
-            context->drawLine(IntPoint(innerrect.x() + innerrect.width(), innerrect.y() + cornerButton),
-                    IntPoint(innerrect.x() + innerrect.width(), innerrect.y() + innerrect.height() - cornerButton));
         }
     }
 
-
     // We always return false so we do not request to be redrawn.
     return false;
 }
@@ -341,8 +285,6 @@
       bool translucent = false;
       if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
           translucent = true;
-      if (!getCanvasFromInfo(paintInfo))
-          return true;
       RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::FULLSCREEN, translucent);
       return false;
 }
@@ -352,8 +294,6 @@
       bool translucent = false;
       if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
           translucent = true;
-      if (!getCanvasFromInfo(paintInfo))
-          return true;
       RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::MUTE, translucent);
       return false;
 }
@@ -364,8 +304,6 @@
       if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
           translucent = true;
       if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(o->node())) {
-          if (!getCanvasFromInfo(paintInfo))
-              return true;
           if (btn->displayType() == MediaPlayButton)
               RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::PLAY, translucent);
           else
@@ -380,8 +318,6 @@
       bool translucent = false;
       if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
           translucent = true;
-      if (!getCanvasFromInfo(paintInfo))
-          return true;
       RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::REWIND, translucent);
       return false;
 }
@@ -391,8 +327,6 @@
       bool translucent = false;
       if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
           translucent = true;
-      if (!getCanvasFromInfo(paintInfo))
-          return true;
       RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::FORWARD, translucent);
       return false;
 }
@@ -402,11 +336,7 @@
       bool translucent = false;
       if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
           translucent = true;
-      if (!getCanvasFromInfo(paintInfo))
-          return true;
-      RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect,
-                                  RenderSkinMediaButton::BACKGROUND_SLIDER,
-                                  translucent, 0, false);
+      RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::BACKGROUND_SLIDER, translucent);
       return false;
 }
 
@@ -415,8 +345,6 @@
       bool translucent = false;
       if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
           translucent = true;
-      if (!getCanvasFromInfo(paintInfo))
-          return true;
       RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect,
                                   RenderSkinMediaButton::SLIDER_TRACK, translucent, o);
       return false;
@@ -427,11 +355,7 @@
       bool translucent = false;
       if (o && toParentMediaElement(o) && toParentMediaElement(o)->hasTagName(HTMLNames::videoTag))
           translucent = true;
-      if (!getCanvasFromInfo(paintInfo))
-          return true;
-      RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect,
-                                  RenderSkinMediaButton::SLIDER_THUMB,
-                                  translucent, 0, false);
+      RenderSkinMediaButton::Draw(getCanvasFromInfo(paintInfo), rect, RenderSkinMediaButton::SLIDER_THUMB, translucent);
       return false;
 }
 
@@ -439,57 +363,17 @@
 {
     static const int sliderThumbWidth = RenderSkinMediaButton::sliderThumbWidth();
     static const int sliderThumbHeight = RenderSkinMediaButton::sliderThumbHeight();
-    o->style()->setWidth(Length(sliderThumbWidth, Fixed));
-    o->style()->setHeight(Length(sliderThumbHeight, Fixed));
+    if (o->style()->appearance() == MediaSliderThumbPart) {
+        o->style()->setWidth(Length(sliderThumbWidth, Fixed));
+        o->style()->setHeight(Length(sliderThumbHeight, Fixed));
+    }
 }
 
 #endif
 
 bool RenderThemeAndroid::paintRadio(RenderObject* obj, const PaintInfo& info, const IntRect& rect)
 {
-    Node* node = obj->node();
-    Element* element = static_cast<Element*>(node);
-    if (element) {
-        InputElement* input = element->toInputElement();
-        GraphicsContext* context = info.context;
-        if (!element->isEnabledFormControl()) {
-            context->setAlpha(0.5f);
-        }
-        const IntRect inner = IntRect(rect.x() - 2, rect.y() - 2, rect.width() - 4, rect.height() - 4);
-        context->setFillColor(Color(defaultBgBright), context->fillColorSpace());
-        context->setStrokeColor(Color(defaultBgBright), context->strokeColorSpace());
-        context->setStrokeThickness(1.0f);
-        if (input->isCheckbox()) {
-            context->drawRect(inner);
-        } else {
-            context->drawEllipse(inner);
-        }
-        context->setStrokeColor(Color(defaultFgColor), context->strokeColorSpace());
-        if (input->isCheckbox()) {
-            context->drawRect(IntRect(inner.x() + 2, inner.y() + 2, inner.width() -4, inner.height() - 4));
-        } else {
-            context->drawEllipse(IntRect(inner.x() + 2, inner.y() + 2, inner.width() -4, inner.height() - 4));
-        }
-        if (input->isChecked()) {
-            context->setFillColor(Color(defaultCheckColor), context->fillColorSpace());
-            context->setStrokeColor(Color(defaultCheckColor), context->strokeColorSpace());
-            if (input->isCheckbox()) {
-                const float w2 = ((float) rect.width() / 2);
-                const float cx = ((float) rect.x());
-                const float cy = ((float) rect.y());
-                context->save();
-                // magic numbers due to weird scale in context
-                context->translate(cx + w2 / 2.2f, cy + w2 / 1.2f);
-                context->rotate(3.93f); // 225 degrees
-                context->drawRect(IntRect(0, 0, rect.width() / 4, 2));
-                context->rotate(1.57f); // 90 degrees
-                context->drawRect(IntRect(0, 0, rect.width() / 2, 2));
-                context->restore();
-            } else {
-                context->drawEllipse(IntRect(inner.x() + 5, inner.y() + 5, inner.width() - 10, inner.height() - 10));
-            }
-        }
-    }
+    RenderSkinRadio::Draw(getCanvasFromInfo(info), obj->node(), rect, false);
     return false;
 }
 
@@ -512,7 +396,7 @@
 
 bool RenderThemeAndroid::paintTextField(RenderObject*, const PaintInfo&, const IntRect&)
 {
-    return true;
+    return true;    
 }
 
 void RenderThemeAndroid::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle* style, WebCore::Element*) const
@@ -534,29 +418,25 @@
 
 bool RenderThemeAndroid::paintSearchField(RenderObject*, const PaintInfo&, const IntRect&)
 {
-    return true;
+    return true;    
 }
 
 static void adjustMenuListStyleCommon(RenderStyle* style)
 {
     // Added to make room for our arrow and make the touch target less cramped.
-    const int padding = (int)(scaleFactor[RenderSkinAndroid::DrawableResolution()] + 0.5f);
-    style->setPaddingLeft(Length(padding,Fixed));
-    style->setPaddingTop(Length(padding, Fixed));
-    style->setPaddingBottom(Length(padding, Fixed));
-    // allocate height as arrow size
-    int arrow = std::max(18, style->fontMetrics().height() + 2 * padding);
-    style->setPaddingRight(Length(arrow, Fixed));
-    style->setMinHeight(Length(arrow, Fixed));
-    style->setHeight(Length(arrow, Fixed));
+    style->setPaddingLeft(Length(RenderSkinCombo::padding(), Fixed));
+    style->setPaddingTop(Length(RenderSkinCombo::padding(), Fixed));
+    style->setPaddingBottom(Length(RenderSkinCombo::padding(), Fixed));
+    style->setPaddingRight(Length(RenderSkinCombo::extraWidth(), Fixed));
+    style->setMinHeight(Length(RenderSkinCombo::minHeight(), Fixed));
 }
 
-void RenderThemeAndroid::adjustListboxStyle(CSSStyleSelector*, RenderStyle* style, Element* e) const
+void RenderThemeAndroid::adjustListboxStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
 {
     adjustMenuListButtonStyle(0, style, 0);
 }
 
-void RenderThemeAndroid::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+void RenderThemeAndroid::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, Element* e) const
 {
     adjustMenuListStyleCommon(style);
     addIntrinsicMargins(style);
@@ -566,55 +446,11 @@
 {
   if (obj->style() && !obj->style()->visitedDependentColor(CSSPropertyBackgroundColor).alpha())
         return true;
-    Node* node = obj->node();
-    Element* element = static_cast<Element*>(node);
-    if (element) {
-        InputElement* input = element->toInputElement();
-        GraphicsContext* context = info.context;
-        if (!element->isEnabledFormControl()) {
-            context->setAlpha(0.5f);
-        }
-        IntRect bounds = IntRect(rect.x(), rect.y(), rect.width(), rect.height());
-        // paint bg color
-        RenderStyle* style = obj->style();
-        context->setFillColor(style->visitedDependentColor(CSSPropertyBackgroundColor),
-                context->fillColorSpace());
-        context->fillRect(FloatRect(bounds));
-        // copied form the original RenderSkinCombo:
-        // If this is an appearance where RenderTheme::paint returns true
-        // without doing anything, this means that
-        // RenderBox::PaintBoxDecorationWithSize will end up painting the
-        // border, so we shouldn't paint a border here.
-        if (style->appearance() != MenulistButtonPart &&
-                style->appearance() != ListboxPart &&
-                style->appearance() != TextFieldPart &&
-                style->appearance() != TextAreaPart) {
-            const int arrowSize = bounds.height();
-            // dropdown button bg
-            context->setFillColor(Color(defaultBgColor), context->fillColorSpace());
-            context->fillRect(FloatRect(bounds.maxX() - arrowSize + 0.5f, bounds.y() + .5f,
-                    arrowSize - 1, bounds.height() - 1));
-            // outline
-            context->setStrokeThickness(1.0f);
-            context->setStrokeColor(Color(defaultBgDark), context->strokeColorSpace());
-            context->strokeRect(bounds, 1.0f);
-            // arrow
-            context->setFillColor(Color(defaultFgColor), context->fillColorSpace());
-            Path tri = Path();
-            tri.clear();
-            const float aw = arrowSize - 10;
-            FloatPoint br = FloatPoint(bounds.maxX() - 4, bounds.maxY() - 4);
-            tri.moveTo(br);
-            tri.addLineTo(FloatPoint(br.x() - aw, br.y()));
-            tri.addLineTo(FloatPoint(br.x(), br.y() - aw));
-            context->fillPath(tri);
-        }
-    }
-    return false;
+    return RenderSkinCombo::Draw(getCanvasFromInfo(info), obj->node(), rect.x(), rect.y(), rect.width(), rect.height());
 }
 
-bool RenderThemeAndroid::paintMenuList(RenderObject* obj, const PaintInfo& info, const IntRect& rect)
-{
+bool RenderThemeAndroid::paintMenuList(RenderObject* obj, const PaintInfo& info, const IntRect& rect) 
+{ 
     return paintCombo(obj, info, rect);
 }
 
@@ -625,13 +461,13 @@
     const float baseFontSize = 11.0f;
     const int baseBorderRadius = 5;
     float fontScale = style->fontSize() / baseFontSize;
-
+    
     style->resetPadding();
     style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up?
 
     const int minHeight = 15;
     style->setMinHeight(Length(minHeight, Fixed));
-
+    
     style->setLineHeight(RenderStyle::initialLineHeight());
     // Found these padding numbers by trial and error.
     const int padding = 4;
@@ -640,47 +476,26 @@
     adjustMenuListStyleCommon(style);
 }
 
-bool RenderThemeAndroid::paintMenuListButton(RenderObject* obj, const PaintInfo& info, const IntRect& rect)
+bool RenderThemeAndroid::paintMenuListButton(RenderObject* obj, const PaintInfo& info, const IntRect& rect) 
 {
     return paintCombo(obj, info, rect);
 }
 
-bool RenderThemeAndroid::paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& r)
-{
-    SkCanvas* canvas = getCanvasFromInfo(i);
-    if (!canvas)
-        return true;
-    static const bool translucent = true;
-    RenderSkinMediaButton::Draw(canvas, r,
-                                RenderSkinMediaButton::SLIDER_TRACK,
-                                translucent, o, false);
-    return false;
-}
-
-bool RenderThemeAndroid::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& r)
-{
-    SkCanvas* canvas = getCanvasFromInfo(i);
-    if (!canvas)
-        return true;
-    static const bool translucent = true;
-    RenderSkinMediaButton::Draw(canvas, r,
-                                RenderSkinMediaButton::SLIDER_THUMB,
-                                translucent, 0, false);
-    return false;
-}
-
-Color RenderThemeAndroid::platformFocusRingColor() const
-{
-    static Color focusRingColor(0x33, 0xB5, 0xE5, 0x66);
-    return focusRingColor;
-}
-
 bool RenderThemeAndroid::supportsFocusRing(const RenderStyle* style) const
 {
-    // Draw the focus ring ourselves unless it is a text area (webkit does borders better)
-    if (!style || !style->hasAppearance())
-        return true;
-    return style->appearance() != TextFieldPart && style->appearance() != TextAreaPart;
+    return style->opacity() > 0
+        && style->hasAppearance() 
+        && style->appearance() != TextFieldPart 
+        && style->appearance() != SearchFieldPart 
+        && style->appearance() != TextAreaPart 
+        && style->appearance() != CheckboxPart
+        && style->appearance() != RadioPart
+        && style->appearance() != PushButtonPart
+        && style->appearance() != SquareButtonPart
+        && style->appearance() != ButtonPart
+        && style->appearance() != ButtonBevelPart
+        && style->appearance() != MenulistPart
+        && style->appearance() != MenulistButtonPart;
 }
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/android/RenderThemeAndroid.h b/Source/WebCore/platform/android/RenderThemeAndroid.h
index 06d272b..e3922a1 100644
--- a/Source/WebCore/platform/android/RenderThemeAndroid.h
+++ b/Source/WebCore/platform/android/RenderThemeAndroid.h
@@ -31,6 +31,10 @@
 
 namespace WebCore {
 
+class RenderSkinButton;
+class RenderSkinRadio;
+class RenderSkinCombo;
+
 struct ThemeData {
     ThemeData()
         : m_part(0)
@@ -48,7 +52,7 @@
     ~RenderThemeAndroid();
     
     virtual bool stateChanged(RenderObject*, ControlState) const;
-
+       
     virtual bool supportsFocusRing(const RenderStyle*) const;
     // A method asking if the theme's controls actually care about redrawing when hovered.
     virtual bool supportsHover(const RenderStyle* style) const { return style->affectedByHoverRules(); }
@@ -60,16 +64,12 @@
     virtual Color platformActiveSelectionForegroundColor() const;
     virtual Color platformInactiveSelectionForegroundColor() const;
     virtual Color platformTextSearchHighlightColor() const;
-    virtual Color platformFocusRingColor() const;
 
     virtual Color platformActiveListBoxSelectionBackgroundColor() const;
     virtual Color platformInactiveListBoxSelectionBackgroundColor() const;
     virtual Color platformActiveListBoxSelectionForegroundColor() const;
     virtual Color platformInactiveListBoxSelectionForegroundColor() const;
 
-    virtual Color platformActiveTextSearchHighlightColor() const;
-    virtual Color platformInactiveTextSearchHighlightColor() const;
-
     virtual void systemFont(int, WebCore::FontDescription&) const {}
 
     virtual int minimumMenuListSize(RenderStyle*) const { return 0; }
@@ -118,9 +118,6 @@
     virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
     virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
 
-    virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
-    virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
-
 private:
     RenderThemeAndroid();
     void addIntrinsicMargins(RenderStyle*) const;
diff --git a/Source/WebCore/platform/android/ScrollViewAndroid.cpp b/Source/WebCore/platform/android/ScrollViewAndroid.cpp
index e7300a1..f29e998 100644
--- a/Source/WebCore/platform/android/ScrollViewAndroid.cpp
+++ b/Source/WebCore/platform/android/ScrollViewAndroid.cpp
@@ -98,6 +98,8 @@
 
 void ScrollView::platformSetScrollPosition(const WebCore::IntPoint& pt)
 {
+    if (parent()) // don't attempt to scroll subframes; they're fully visible
+        return;
     PlatformBridge::setScrollPosition(this, m_scrollOrigin.x() + pt.x(),
             m_scrollOrigin.y() + pt.y());
 }
@@ -131,7 +133,13 @@
     android::WebViewCore* core = android::WebViewCore::getWebViewCore(this);
     if (!core) // SVG does not instantiate webviewcore
         return; // and doesn't need to record drawing offscreen
-    core->offInvalidate(rect);
+    SkRegion rectRgn = SkRegion(rect);
+    rectRgn.op(vis, SkRegion::kDifference_Op);
+    SkRegion::Iterator iter(rectRgn);
+    for (; !iter.done(); iter.next()) {
+        const SkIRect& diff = iter.rect();
+        core->offInvalidate(diff);
+    }
 }
 #endif
 
diff --git a/Source/WebCore/platform/android/SharedTimerAndroid.cpp b/Source/WebCore/platform/android/SharedTimerAndroid.cpp
index 92223d5..e4f3b36 100644
--- a/Source/WebCore/platform/android/SharedTimerAndroid.cpp
+++ b/Source/WebCore/platform/android/SharedTimerAndroid.cpp
@@ -51,7 +51,7 @@
 {
     long long timeInMs = static_cast<long long>((fireTime - WTF::currentTime()) * 1000);
 
-    ALOGV("setSharedTimerFireTime: in %d millisec", (int)timeInMs);
+    LOGV("setSharedTimerFireTime: in %ld millisec", timeInMs);
     if (JavaSharedClient::GetTimerClient())
         JavaSharedClient::GetTimerClient()->setSharedTimer(timeInMs);
 }
diff --git a/Source/WebCore/platform/android/TemporaryLinkStubs.cpp b/Source/WebCore/platform/android/TemporaryLinkStubs.cpp
index 7df3e8c..ca9f24d 100644
--- a/Source/WebCore/platform/android/TemporaryLinkStubs.cpp
+++ b/Source/WebCore/platform/android/TemporaryLinkStubs.cpp
@@ -80,6 +80,13 @@
 #include <wtf/MainThread.h>
 #include <wtf/text/CString.h>
 
+#if USE(JSC)
+#include "API/JSClassRef.h"
+#include "JNIUtilityPrivate.h"
+#include "JavaScriptCallFrame.h"
+#include "ScriptDebugServer.h"
+#endif
+
 using namespace WebCore;
 
 /********************************************************/
@@ -387,6 +394,18 @@
 }
 
 
+#if USE(JSC)
+namespace JSC { namespace Bindings {
+bool dispatchJNICall(ExecState*, const void* targetAppletView, jobject obj, bool isStatic, JavaType returnType,
+        jmethodID methodID, jvalue* args, jvalue& result, const char* callingURL, JSValue& exceptionDescription)
+{
+    notImplemented();
+    return false;
+}
+
+} }  // namespace Bindings
+#endif
+
 char* dirname(const char*)
 {
     notImplemented();
diff --git a/Source/WebCore/platform/android/WidgetAndroid.cpp b/Source/WebCore/platform/android/WidgetAndroid.cpp
index 3c5b1c8..10326f9 100644
--- a/Source/WebCore/platform/android/WidgetAndroid.cpp
+++ b/Source/WebCore/platform/android/WidgetAndroid.cpp
@@ -61,6 +61,10 @@
 
 void Widget::paint(GraphicsContext* ctx, const IntRect& r)
 {
+    // FIXME: in what case, will this be called for the top frame?
+    if (!platformWidget())
+        return;
+    platformWidget()->draw(ctx, r);
 }
 
 void Widget::releasePlatformWidget()
diff --git a/Source/WebCore/platform/graphics/Color.h b/Source/WebCore/platform/graphics/Color.h
index 0fb355b..02ec005 100644
--- a/Source/WebCore/platform/graphics/Color.h
+++ b/Source/WebCore/platform/graphics/Color.h
@@ -162,8 +162,15 @@
     static const RGBA32 lightGray = 0xFFC0C0C0;
     static const RGBA32 transparent = 0x00000000;
 
+#ifdef ANDROID_CSS_RING
+    static const RGBA32 ringFill = 0x666699FF;
+    static const RGBA32 ringPressedInner = 0x006699FF;
+    static const RGBA32 ringPressedOuter = 0x336699FF;
+    static const RGBA32 ringSelectedInner = 0xAA6699FF;
+    static const RGBA32 ringSelectedOuter = 0x336699FF;
+#endif
 #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
-    static const RGBA32 tap = 0x6633B5E5;
+    static const RGBA32 tap = 0x4D1A1A1A;
 #endif
 
 private:
diff --git a/Source/WebCore/platform/graphics/Font.h b/Source/WebCore/platform/graphics/Font.h
index 664c3af..beafdc7 100644
--- a/Source/WebCore/platform/graphics/Font.h
+++ b/Source/WebCore/platform/graphics/Font.h
@@ -171,13 +171,7 @@
     float getGlyphsAndAdvancesForSimpleText(const TextRun&, int from, int to, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const;
     void drawSimpleText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
     void drawEmphasisMarksForSimpleText(GraphicsContext*, const TextRun&, const AtomicString& mark, const FloatPoint&, int from, int to) const;
-#if PLATFORM(ANDROID)
-public:
-#endif
     void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const;
-#if PLATFORM(ANDROID)
-private:
-#endif
     void drawGlyphBuffer(GraphicsContext*, const GlyphBuffer&, const FloatPoint&) const;
     void drawEmphasisMarks(GraphicsContext* context, const GlyphBuffer&, const AtomicString&, const FloatPoint&) const;
     float floatWidthForSimpleText(const TextRun&, GlyphBuffer*, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
diff --git a/Source/WebCore/platform/graphics/FontPlatformData.h b/Source/WebCore/platform/graphics/FontPlatformData.h
index 36ccbb0..a32215d 100644
--- a/Source/WebCore/platform/graphics/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/FontPlatformData.h
@@ -36,7 +36,7 @@
 #elif (PLATFORM(EFL) || PLATFORM(GTK)) && USE(PANGO)
 #include "pango/FontPlatformData.h"
 #elif PLATFORM(ANDROID)
-#include "android/fonts/FontPlatformData.h"
+#include "android/FontPlatformData.h"
 #else
 
 #ifndef FontPlatformData_h
diff --git a/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp b/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp
index 126b3b4..951cf56 100644
--- a/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp
+++ b/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp
@@ -47,19 +47,12 @@
 
 GlyphPageTreeNode* GlyphPageTreeNode::getRoot(unsigned pageNumber)
 {
-#if !PLATFORM(ANDROID)
     static bool initialized;
     if (!initialized) {
         initialized = true;
         roots = new HashMap<int, GlyphPageTreeNode*>;
         pageZeroRoot = new GlyphPageTreeNode;
     }
-#else
-    if (!roots)
-        roots = new HashMap<int, GlyphPageTreeNode*>;
-    if (!pageZeroRoot)
-        pageZeroRoot = new GlyphPageTreeNode;
-#endif
 
     GlyphPageTreeNode* node = pageNumber ? roots->get(pageNumber) : pageZeroRoot;
     if (!node) {
@@ -75,29 +68,6 @@
     return node;
 }
 
-#if PLATFORM(ANDROID)
-void GlyphPageTreeNode::resetRoots()
-{
-    if (roots) {
-        HashMap<int, GlyphPageTreeNode*>::iterator end = roots->end();
-        for (HashMap<int, GlyphPageTreeNode*>::iterator it = roots->begin(); it != end; ++it)
-            it->second->resetChildren();
-    }
-    if (pageZeroRoot) {
-        pageZeroRoot->resetChildren();
-    }
-}
-
-void GlyphPageTreeNode::resetChildren()
-{
-    HashMap<const FontData*, GlyphPageTreeNode*>::const_iterator end = m_children.end();
-    for (HashMap<const FontData*, GlyphPageTreeNode*>::const_iterator it = m_children.begin(); it != end; ++it) {
-        pruneTreeFontData(static_cast<const SimpleFontData*>(it->first));
-        pruneTreeCustomFontData(it->first);
-    }
-}
-#endif
-
 size_t GlyphPageTreeNode::treeGlyphPageCount()
 {
     size_t count = 0;
@@ -377,11 +347,7 @@
 
 void GlyphPageTreeNode::pruneCustomFontData(const FontData* fontData)
 {
-#if !PLATFORM(ANDROID)
     if (!fontData || !m_customFontCount)
-#else
-    if (!fontData || !m_customFontCount || fontData == (SimpleFontData*)-1)
-#endif
         return;
         
     // Prune any branch that contains this FontData.
@@ -405,11 +371,7 @@
 void GlyphPageTreeNode::pruneFontData(const SimpleFontData* fontData, unsigned level)
 {
     ASSERT(fontData);
-#if !PLATFORM(ANDROID)
     if (!fontData)
-#else
-    if (!fontData || fontData == (SimpleFontData*)-1)
-#endif
         return;
 
     // Prune any branch that contains this FontData.
diff --git a/Source/WebCore/platform/graphics/GlyphPageTreeNode.h b/Source/WebCore/platform/graphics/GlyphPageTreeNode.h
index 72a62ea..b68c0ed 100644
--- a/Source/WebCore/platform/graphics/GlyphPageTreeNode.h
+++ b/Source/WebCore/platform/graphics/GlyphPageTreeNode.h
@@ -196,11 +196,6 @@
     void pruneCustomFontData(const FontData*);
     void pruneFontData(const SimpleFontData*, unsigned level = 0);
 
-#if PLATFORM(ANDROID)
-    static void resetRoots();
-    void resetChildren();
-#endif
-
     GlyphPageTreeNode* parent() const { return m_parent; }
     GlyphPageTreeNode* getChild(const FontData*, unsigned pageNumber);
 
diff --git a/Source/WebCore/platform/graphics/Gradient.cpp b/Source/WebCore/platform/graphics/Gradient.cpp
index 7e3984f..7541646 100644
--- a/Source/WebCore/platform/graphics/Gradient.cpp
+++ b/Source/WebCore/platform/graphics/Gradient.cpp
@@ -221,7 +221,7 @@
     setPlatformGradientSpaceTransform(gradientSpaceTransformation);
 }
 
-#if !USE(SKIA) && !USE(CAIRO)
+#if !(USE(SKIA) && !PLATFORM(ANDROID)) && !USE(CAIRO)
 void Gradient::setPlatformGradientSpaceTransform(const AffineTransform&)
 {
 }
diff --git a/Source/WebCore/platform/graphics/Gradient.h b/Source/WebCore/platform/graphics/Gradient.h
index ec22efe..7595896 100644
--- a/Source/WebCore/platform/graphics/Gradient.h
+++ b/Source/WebCore/platform/graphics/Gradient.h
@@ -58,9 +58,14 @@
 typedef struct _cairo_pattern cairo_pattern_t;
 typedef cairo_pattern_t* PlatformGradient;
 #elif USE(SKIA)
+#if PLATFORM(ANDROID)
+#include "SkShader.h"
+typedef class PlatformGradientRec* PlatformGradient;
+#else
 class SkShader;
 typedef class SkShader* PlatformGradient;
 typedef class SkShader* PlatformPattern;
+#endif
 #elif PLATFORM(HAIKU)
 class BGradient;
 typedef BGradient* PlatformGradient;
@@ -111,6 +116,9 @@
 #if OS(WINCE) && !PLATFORM(QT)
         const Vector<ColorStop, 2>& getStops() const;
 #else
+#if PLATFORM(ANDROID)
+        SkShader* getShader(SkShader::TileMode);
+#endif
         PlatformGradient platformGradient();
 #endif
 
diff --git a/Source/WebCore/platform/graphics/GraphicsContext.cpp b/Source/WebCore/platform/graphics/GraphicsContext.cpp
index d8ea160..65cc6df 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext.cpp
+++ b/Source/WebCore/platform/graphics/GraphicsContext.cpp
@@ -432,7 +432,6 @@
     bidiRuns.deleteRuns();
 }
 
-#if !PLATFORM(ANDROID)
 void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, const FloatPoint& point, int h, const Color& backgroundColor, ColorSpace colorSpace, int from, int to)
 {
     if (paintingDisabled())
@@ -440,7 +439,6 @@
 
     fillRect(font.selectionRectForText(run, point, h, from, to), backgroundColor, colorSpace);
 }
-#endif
 
 void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op, bool useLowQualityScale)
 {
@@ -662,7 +660,7 @@
     return m_state.compositeOperator;
 }
 
-#if !USE(SKIA)
+#if !(USE(SKIA) && !PLATFORM(ANDROID))
 void GraphicsContext::setPlatformFillGradient(Gradient*)
 {
 }
@@ -688,7 +686,7 @@
 }
 #endif
 
-#if !PLATFORM(QT) && !USE(CAIRO) && !USE(SKIA) && !PLATFORM(OPENVG)
+#if !PLATFORM(QT) && !USE(CAIRO) && !(USE(SKIA) && !PLATFORM(ANDROID)) && !PLATFORM(HAIKU) && !PLATFORM(OPENVG)
 void GraphicsContext::setPlatformStrokeStyle(StrokeStyle)
 {
 }
diff --git a/Source/WebCore/platform/graphics/GraphicsContext.h b/Source/WebCore/platform/graphics/GraphicsContext.h
index 5c60e98..2b41c2e 100644
--- a/Source/WebCore/platform/graphics/GraphicsContext.h
+++ b/Source/WebCore/platform/graphics/GraphicsContext.h
@@ -287,6 +287,8 @@
 #endif
 
 #if PLATFORM(ANDROID)
+        // initialize a paint for bitmaps
+        void setupBitmapPaint(SkPaint*);
         // initialize a paint for filling
         void setupFillPaint(SkPaint*);
         // initialize a paint for stroking
@@ -299,6 +301,10 @@
         // returns true if there is a valid (non-transparent) stroke color
         bool willStroke() const;
 
+        // may return NULL, since we lazily allocate the path. This is the path
+        // that is drawn by drawPath()
+        const SkPath* getCurrPath() const;
+
         /** platform-specific factory method to return a bitmap graphicscontext,
          called by <canvas> when we need to draw offscreen. Caller is responsible for
          deleting the context. Use drawOffscreenContext() to draw the context's image
@@ -376,11 +382,7 @@
         void drawText(const Font&, const TextRun&, const FloatPoint&, int from = 0, int to = -1);
         void drawEmphasisMarks(const Font&, const TextRun& , const AtomicString& mark, const FloatPoint&, int from = 0, int to = -1);
         void drawBidiText(const Font&, const TextRun&, const FloatPoint&);
-#if PLATFORM(ANDROID)
-        void drawHighlightForText(const Font&, const TextRun&, const FloatPoint&, int h, const Color& backgroundColor, ColorSpace, int from = 0, int to = -1, bool isActive = true);
-#else
         void drawHighlightForText(const Font&, const TextRun&, const FloatPoint&, int h, const Color& backgroundColor, ColorSpace, int from = 0, int to = -1);
-#endif
 
         enum RoundingMode {
             RoundAllSides,
diff --git a/Source/WebCore/platform/graphics/GraphicsLayerClient.h b/Source/WebCore/platform/graphics/GraphicsLayerClient.h
index 3f09f32..aab176b 100644
--- a/Source/WebCore/platform/graphics/GraphicsLayerClient.h
+++ b/Source/WebCore/platform/graphics/GraphicsLayerClient.h
@@ -43,9 +43,6 @@
     GraphicsLayerPaintBackground = (1 << 0),
     GraphicsLayerPaintForeground = (1 << 1),
     GraphicsLayerPaintMask = (1 << 2),
-#if PLATFORM(ANDROID)
-    GraphicsLayerPaintBackgroundDecorations = (1 << 3),
-#endif
     GraphicsLayerPaintAll = (GraphicsLayerPaintBackground | GraphicsLayerPaintForeground | GraphicsLayerPaintMask)
 };
 
diff --git a/Source/WebCore/platform/graphics/android/layers/AndroidAnimation.cpp b/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp
similarity index 92%
rename from Source/WebCore/platform/graphics/android/layers/AndroidAnimation.cpp
rename to Source/WebCore/platform/graphics/android/AndroidAnimation.cpp
index 0ef84b9..6b22359 100644
--- a/Source/WebCore/platform/graphics/android/layers/AndroidAnimation.cpp
+++ b/Source/WebCore/platform/graphics/android/AndroidAnimation.cpp
@@ -14,22 +14,39 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "AndroidAnimation"
-#define LOG_NDEBUG 1
-
 #include "config.h"
 #include "AndroidAnimation.h"
 
 #if USE(ACCELERATED_COMPOSITING)
 
-#include "AndroidLog.h"
 #include "Animation.h"
 #include "GraphicsLayerAndroid.h"
+
 #include "Timer.h"
 #include "TimingFunction.h"
 #include "TranslateTransformOperation.h"
 #include "UnitBezier.h"
 
+#include <wtf/CurrentTime.h>
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "AndroidAnimation", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "AndroidAnimation", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+
 namespace WebCore {
 
 static int gUniqueId;
@@ -234,10 +251,10 @@
     FloatAnimationValue* fromValue = (FloatAnimationValue*) m_operations->at(from);
     FloatAnimationValue* toValue = (FloatAnimationValue*) m_operations->at(to);
 
-    ALOGV("[layer %d] opacity fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f",
-          layer->uniqueId(),
-          fromValue, fromValue->keyTime(),
-          toValue, toValue->keyTime(), progress);
+    XLOG("[layer %d] opacity fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f",
+         layer->uniqueId(),
+         fromValue, fromValue->keyTime(),
+         toValue, toValue->keyTime(), progress);
 
     // We now have the correct two values to work with, let's compute the
     // progress value
@@ -276,10 +293,10 @@
     TransformAnimationValue* fromValue = (TransformAnimationValue*) m_operations->at(from);
     TransformAnimationValue* toValue = (TransformAnimationValue*) m_operations->at(to);
 
-    ALOGV("[layer %d] fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f",
-          layer->uniqueId(),
-          fromValue, fromValue->keyTime(),
-          toValue, toValue->keyTime(), progress);
+    XLOG("[layer %d] fromValue %x, key %.2f, toValue %x, key %.2f for progress %.2f",
+         layer->uniqueId(),
+         fromValue, fromValue->keyTime(),
+         toValue, toValue->keyTime(), progress);
 
     // We now have the correct two values to work with, let's compute the
     // progress value
@@ -287,8 +304,8 @@
     const TimingFunction* timingFunction = fromValue->timingFunction();
     float p = applyTimingFunction(fromValue->keyTime(), toValue->keyTime(),
                                   progress, timingFunction);
-    ALOGV("progress %.2f => %.2f from: %.2f to: %.2f", progress, p, fromValue->keyTime(),
-          toValue->keyTime());
+    XLOG("progress %.2f => %.2f from: %.2f to: %.2f", progress, p, fromValue->keyTime(),
+         toValue->keyTime());
     progress = p;
 
     // With both values and the progress, we also need to check out that
diff --git a/Source/WebCore/platform/graphics/android/layers/AndroidAnimation.h b/Source/WebCore/platform/graphics/android/AndroidAnimation.h
similarity index 100%
rename from Source/WebCore/platform/graphics/android/layers/AndroidAnimation.h
rename to Source/WebCore/platform/graphics/android/AndroidAnimation.h
diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
new file mode 100644
index 0000000..9c7716c
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
@@ -0,0 +1,390 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "BaseLayerAndroid.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+#include "ClassTracker.h"
+#include "GLUtils.h"
+#include "ShaderProgram.h"
+#include "SkCanvas.h"
+#include "TilesManager.h"
+#include <GLES2/gl2.h>
+#include <wtf/CurrentTime.h>
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "BaseLayerAndroid", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseLayerAndroid", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+// TODO: dynamically determine based on DPI
+#define PREFETCH_SCALE_MODIFIER 0.3
+#define PREFETCH_OPACITY 1
+#define PREFETCH_X_DIST 0
+#define PREFETCH_Y_DIST 1
+
+namespace WebCore {
+
+using namespace android;
+
+BaseLayerAndroid::BaseLayerAndroid()
+#if USE(ACCELERATED_COMPOSITING)
+    : m_color(Color::white)
+    , m_scrollState(NotScrolling)
+#endif
+{
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->increment("BaseLayerAndroid");
+#endif
+}
+
+BaseLayerAndroid::~BaseLayerAndroid()
+{
+    m_content.clear();
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->decrement("BaseLayerAndroid");
+#endif
+}
+
+void BaseLayerAndroid::setContent(const PictureSet& src)
+{
+#if USE(ACCELERATED_COMPOSITING)
+    // FIXME: We lock here because we do not want
+    // to paint and change the m_content concurrently.
+    // We should instead refactor PictureSet to use
+    // an atomic refcounting scheme and use atomic operations
+    // to swap PictureSets.
+    android::Mutex::Autolock lock(m_drawLock);
+#endif
+    m_content.set(src);
+    // FIXME: We cannot set the size of the base layer because it will screw up
+    // the matrix used.  We need to fix matrix computation for the base layer
+    // and then we can set the size.
+    // setSize(src.width(), src.height());
+}
+
+bool BaseLayerAndroid::drawCanvas(SkCanvas* canvas)
+{
+#if USE(ACCELERATED_COMPOSITING)
+    android::Mutex::Autolock lock(m_drawLock);
+#endif
+    if (!m_content.isEmpty())
+        m_content.draw(canvas);
+    return true;
+}
+
+#if USE(ACCELERATED_COMPOSITING)
+
+void BaseLayerAndroid::prefetchBasePicture(SkRect& viewport, float currentScale,
+                                           TiledPage* prefetchTiledPage, bool draw)
+{
+    SkIRect bounds;
+    float prefetchScale = currentScale * PREFETCH_SCALE_MODIFIER;
+
+    float invTileWidth = (prefetchScale)
+        / TilesManager::instance()->tileWidth();
+    float invTileHeight = (prefetchScale)
+        / TilesManager::instance()->tileHeight();
+    bool goingDown = m_state->goingDown();
+    bool goingLeft = m_state->goingLeft();
+
+
+    XLOG("fetch rect %f %f %f %f, scale %f",
+         viewport.fLeft,
+         viewport.fTop,
+         viewport.fRight,
+         viewport.fBottom,
+         scale);
+
+    bounds.fLeft = static_cast<int>(floorf(viewport.fLeft * invTileWidth)) - PREFETCH_X_DIST;
+    bounds.fTop = static_cast<int>(floorf(viewport.fTop * invTileHeight)) - PREFETCH_Y_DIST;
+    bounds.fRight = static_cast<int>(ceilf(viewport.fRight * invTileWidth)) + PREFETCH_X_DIST;
+    bounds.fBottom = static_cast<int>(ceilf(viewport.fBottom * invTileHeight)) + PREFETCH_Y_DIST;
+
+    XLOG("prefetch rect %d %d %d %d, scale %f, preparing page %p",
+         bounds.fLeft, bounds.fTop,
+         bounds.fRight, bounds.fBottom,
+         scale * PREFETCH_SCALE,
+         prefetchTiledPage);
+
+    prefetchTiledPage->setScale(prefetchScale);
+    prefetchTiledPage->updateTileDirtiness(bounds);
+    prefetchTiledPage->prepare(goingDown, goingLeft, bounds,
+                               TiledPage::ExpandedBounds);
+    prefetchTiledPage->swapBuffersIfReady(bounds,
+                                          prefetchScale);
+    if (draw)
+        prefetchTiledPage->prepareForDrawGL(PREFETCH_OPACITY, bounds);
+}
+
+bool BaseLayerAndroid::isReady()
+{
+    ZoomManager* zoomManager = m_state->zoomManager();
+    if (ZoomManager::kNoScaleRequest != zoomManager->scaleRequestState()) {
+        XLOG("base layer not ready, still zooming");
+        return false; // still zooming
+    }
+
+    if (!m_state->frontPage()->isReady(m_state->preZoomBounds())) {
+        XLOG("base layer not ready, front page not done painting");
+        return false;
+    }
+
+    LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0));
+    if (compositedRoot) {
+        XLOG("base layer is ready, how about children?");
+        return compositedRoot->isReady();
+    }
+
+    return true;
+}
+
+void BaseLayerAndroid::swapTiles()
+{
+    if (countChildren())
+        getChild(0)->swapTiles(); // TODO: move to parent impl
+
+    m_state->frontPage()->swapBuffersIfReady(m_state->preZoomBounds(),
+                                             m_state->zoomManager()->currentScale());
+
+    m_state->backPage()->swapBuffersIfReady(m_state->preZoomBounds(),
+                                            m_state->zoomManager()->currentScale());
+}
+
+void BaseLayerAndroid::setIsDrawing(bool isDrawing)
+{
+    if (countChildren())
+        getChild(0)->setIsDrawing(isDrawing); // TODO: move to parent impl
+}
+
+void BaseLayerAndroid::setIsPainting(Layer* drawingTree)
+{
+    XLOG("BLA %p painting, dirty %d", this, isDirty());
+    if (drawingTree)
+        drawingTree = drawingTree->getChild(0);
+
+    if (countChildren())
+        getChild(0)->setIsPainting(drawingTree); // TODO: move to parent impl
+
+    m_state->invalRegion(m_dirtyRegion);
+    m_dirtyRegion.setEmpty();
+}
+
+void BaseLayerAndroid::mergeInvalsInto(Layer* replacementTree)
+{
+    XLOG("merging invals (empty=%d) from BLA %p to %p", m_dirtyRegion.isEmpty(), this, replacementTree);
+    if (countChildren() && replacementTree->countChildren())
+        getChild(0)->mergeInvalsInto(replacementTree->getChild(0));
+
+    replacementTree->markAsDirty(m_dirtyRegion);
+}
+
+bool BaseLayerAndroid::prepareBasePictureInGL(SkRect& viewport, float scale,
+                                              double currentTime)
+{
+    ZoomManager* zoomManager = m_state->zoomManager();
+
+    bool goingDown = m_state->goingDown();
+    bool goingLeft = m_state->goingLeft();
+
+    const SkIRect& viewportTileBounds = m_state->viewportTileBounds();
+    XLOG("drawBasePicture, TX: %d, TY: %d scale %.2f", viewportTileBounds.fLeft,
+            viewportTileBounds.fTop, scale);
+
+    // Query the resulting state from the zoom manager
+    bool prepareNextTiledPage = zoomManager->needPrepareNextTiledPage();
+
+    // Display the current page
+    TiledPage* tiledPage = m_state->frontPage();
+    TiledPage* nextTiledPage = m_state->backPage();
+    tiledPage->setScale(zoomManager->currentScale());
+
+    // Let's prepare the page if needed so that it will start painting
+    if (prepareNextTiledPage) {
+        nextTiledPage->setScale(scale);
+        m_state->setFutureViewport(viewportTileBounds);
+
+        // ignore dirtiness return value since while zooming we repaint regardless
+        nextTiledPage->updateTileDirtiness(viewportTileBounds);
+
+        nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds,
+                               TiledPage::VisibleBounds);
+        // Cancel pending paints for the foreground page
+        TilesManager::instance()->removePaintOperationsForPage(tiledPage, false);
+    }
+
+    // If we fired a request, let's check if it's ready to use
+    if (zoomManager->didFireRequest()) {
+        if (nextTiledPage->swapBuffersIfReady(viewportTileBounds,
+                                              zoomManager->futureScale()))
+            zoomManager->setReceivedRequest(); // transition to received request state
+    }
+
+    float transparency = 1;
+    bool doZoomPageSwap = false;
+
+    // If the page is ready, display it. We do a short transition between
+    // the two pages (current one and future one with the new scale factor)
+    if (zoomManager->didReceivedRequest()) {
+        float nextTiledPageTransparency = 1;
+        m_state->resetFrameworkInval();
+        zoomManager->processTransition(currentTime, scale, &doZoomPageSwap,
+                                       &nextTiledPageTransparency, &transparency);
+        nextTiledPage->prepareForDrawGL(nextTiledPageTransparency, viewportTileBounds);
+    }
+
+    const SkIRect& preZoomBounds = m_state->preZoomBounds();
+
+    bool zooming = ZoomManager::kNoScaleRequest != zoomManager->scaleRequestState();
+
+    if (doZoomPageSwap) {
+        zoomManager->setCurrentScale(scale);
+        m_state->swapPages();
+    }
+
+    bool needsRedraw = zooming;
+
+    // if applied invals mark tiles dirty, need to redraw
+    needsRedraw |= tiledPage->updateTileDirtiness(preZoomBounds);
+
+    // paint what's needed unless we're zooming, since the new tiles won't
+    // be relevant soon anyway
+    if (!zooming)
+        tiledPage->prepare(goingDown, goingLeft, preZoomBounds,
+                           TiledPage::ExpandedBounds);
+
+    XLOG("scrolling %d, zooming %d, needsRedraw %d",
+         scrolling, zooming, needsRedraw);
+
+    // prefetch in the nextTiledPage if unused by zooming (even if not scrolling
+    // since we want the tiles to be ready before they're needed)
+    bool usePrefetchPage = !zooming;
+    nextTiledPage->setIsPrefetchPage(usePrefetchPage);
+    if (usePrefetchPage) {
+        // if the non-prefetch page isn't missing tiles, don't bother drawing
+        // prefetch page
+        bool drawPrefetchPage = tiledPage->hasMissingContent(preZoomBounds);
+        prefetchBasePicture(viewport, scale, nextTiledPage, drawPrefetchPage);
+    }
+
+    tiledPage->prepareForDrawGL(transparency, preZoomBounds);
+
+    return needsRedraw;
+}
+
+void BaseLayerAndroid::drawBasePictureInGL()
+{
+    m_state->backPage()->drawGL();
+    m_state->frontPage()->drawGL();
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+void BaseLayerAndroid::updateLayerPositions(SkRect& visibleRect)
+{
+    LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0));
+    TransformationMatrix ident;
+    compositedRoot->updateFixedLayersPositions(visibleRect);
+    FloatRect clip(0, 0, content()->width(), content()->height());
+    compositedRoot->updateGLPositionsAndScale(
+        ident, clip, 1, m_state->zoomManager()->layersScale());
+
+#ifdef DEBUG
+    compositedRoot->showLayer(0);
+    XLOG("We have %d layers, %d textured",
+         compositedRoot->nbLayers(),
+         compositedRoot->nbTexturedLayers());
+#endif
+}
+
+bool BaseLayerAndroid::prepare(double currentTime, IntRect& viewRect,
+                               SkRect& visibleRect, float scale)
+{
+    XLOG("preparing BLA %p", this);
+
+    // base layer is simply drawn in prepare, since there is always a base layer it doesn't matter
+    bool needsRedraw = prepareBasePictureInGL(visibleRect, scale, currentTime);
+
+    LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0));
+    if (compositedRoot) {
+        updateLayerPositions(visibleRect);
+
+        XLOG("preparing BLA %p, root %p", this, compositedRoot);
+        compositedRoot->prepare();
+    }
+
+    return needsRedraw;
+}
+
+bool BaseLayerAndroid::drawGL(IntRect& viewRect, SkRect& visibleRect,
+                              float scale)
+{
+    XLOG("drawing BLA %p", this);
+
+    // TODO: consider moving drawBackground outside of prepare (into tree manager)
+    m_state->drawBackground(m_color);
+    drawBasePictureInGL();
+
+    bool needsRedraw = false;
+
+#if USE(ACCELERATED_COMPOSITING)
+
+    LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0));
+    if (compositedRoot) {
+        updateLayerPositions(visibleRect);
+        // For now, we render layers only if the rendering mode
+        // is kAllTextures or kClippedTextures
+        if (compositedRoot->drawGL()) {
+            if (TilesManager::instance()->layerTexturesRemain()) {
+                // only try redrawing for layers if layer textures remain,
+                // otherwise we'll repaint without getting anything done
+                needsRedraw = true;
+            }
+        }
+    }
+
+#endif // USE(ACCELERATED_COMPOSITING)
+#ifdef DEBUG
+    ClassTracker::instance()->show();
+#endif
+    return needsRedraw;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
new file mode 100644
index 0000000..f0c2766
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BaseLayerAndroid_h
+#define BaseLayerAndroid_h
+
+#include <utils/threads.h>
+
+#include "Color.h"
+#include "GLWebViewState.h"
+#include "IntRect.h"
+#include "Layer.h"
+#include "PictureSet.h"
+#include "SkPicture.h"
+
+namespace WebCore {
+
+class BaseLayerAndroid : public Layer {
+
+public:
+    enum ScrollState {
+        NotScrolling = 0,
+        Scrolling = 1,
+        ScrollingFinishPaint = 2
+    };
+
+    BaseLayerAndroid();
+    virtual ~BaseLayerAndroid();
+
+#if USE(ACCELERATED_COMPOSITING)
+    void setBackgroundColor(Color& color) { m_color = color; }
+    Color getBackgroundColor() { return m_color; }
+#endif
+    void setContent(const android::PictureSet& src);
+    android::PictureSet* content() { return &m_content; }
+    // This method will paint using the current PictureSet onto
+    // the passed canvas. We used it to paint the GL tiles as well as
+    // WebView::copyBaseContentToPicture(), so a lock is necessary as
+    // we are running in different threads.
+    virtual bool drawCanvas(SkCanvas* canvas);
+
+    void updateLayerPositions(SkRect& visibleRect);
+    bool prepare(double currentTime, IntRect& viewRect,
+                 SkRect& visibleRect, float scale);
+    bool drawGL(IntRect& viewRect, SkRect& visibleRect, float scale);
+
+    // rendering asset management
+    void swapTiles();
+    void setIsDrawing(bool isDrawing);
+    void setIsPainting(Layer* drawingTree);
+    void mergeInvalsInto(Layer* replacementTree);
+    bool isReady();
+
+private:
+#if USE(ACCELERATED_COMPOSITING)
+    void prefetchBasePicture(SkRect& viewport, float currentScale,
+                             TiledPage* prefetchTiledPage, bool draw);
+    bool prepareBasePictureInGL(SkRect& viewport, float scale, double currentTime);
+    void drawBasePictureInGL();
+
+    android::Mutex m_drawLock;
+    Color m_color;
+#endif
+    android::PictureSet m_content;
+
+    ScrollState m_scrollState;
+};
+
+} // namespace WebCore
+
+#endif // BaseLayerAndroid_h
diff --git a/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp b/Source/WebCore/platform/graphics/android/BaseRenderer.cpp
similarity index 60%
rename from Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp
rename to Source/WebCore/platform/graphics/android/BaseRenderer.cpp
index 6f679da..57baee8 100644
--- a/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.cpp
+++ b/Source/WebCore/platform/graphics/android/BaseRenderer.cpp
@@ -23,15 +23,12 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#define LOG_TAG "BaseRenderer"
-#define LOG_NDEBUG 1
 
 #include "config.h"
 #include "BaseRenderer.h"
 
 #if USE(ACCELERATED_COMPOSITING)
 
-#include "AndroidLog.h"
 #include "GaneshRenderer.h"
 #include "GLUtils.h"
 #include "RasterRenderer.h"
@@ -40,14 +37,24 @@
 #include "SkCanvas.h"
 #include "SkDevice.h"
 #include "SkPicture.h"
-#include "SkTypeface.h"
-#include "Tile.h"
 #include "TilesManager.h"
 
 #include <wtf/text/CString.h>
 
-#define UPDATE_COUNT_MASK 0xFF // displayed count wraps at 256
-#define UPDATE_COUNT_ALPHA_MASK 0x1F // alpha wraps at 32
+#ifdef DEBUG
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseRenderer", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
 
 namespace WebCore {
 
@@ -72,24 +79,40 @@
 }
 
 void BaseRenderer::drawTileInfo(SkCanvas* canvas,
-        const TileRenderInfo& renderInfo, int updateCount, double renderDuration)
+        const TileRenderInfo& renderInfo, int pictureCount)
 {
-    static SkTypeface* s_typeface = 0;
-    if (!s_typeface)
-        s_typeface = SkTypeface::CreateFromName("", SkTypeface::kBold);
     SkPaint paint;
-    paint.setTextSize(17);
     char str[256];
-    snprintf(str, 256, " (%d,%d)   %.2fx   %d   %.1fms", renderInfo.x, renderInfo.y,
-            renderInfo.scale, updateCount, renderDuration);
-    paint.setARGB(128, 255, 255, 255);
-    canvas->drawRectCoords(0, 0, renderInfo.tileSize.fWidth, 17, paint);
+    snprintf(str, 256, "(%d,%d) %.2f, tl%x p%x c%d", renderInfo.x, renderInfo.y,
+            renderInfo.scale, this, renderInfo.tilePainter, pictureCount);
+    paint.setARGB(255, 0, 0, 0);
+    canvas->drawText(str, strlen(str), 0, 10, paint);
     paint.setARGB(255, 255, 0, 0);
-    paint.setTypeface(s_typeface);
-    canvas->drawText(str, strlen(str), 20, 15, paint);
+    canvas->drawText(str, strlen(str), 0, 11, paint);
+
+    int tagCount = 0;
+    const String* tags = getPerformanceTags(tagCount);
+
+    float total = 0;
+    for (int i = 0; i < tagCount; i++) {
+        float tagDuration = m_perfMon.getAverageDuration(tags[i]);
+        total += tagDuration;
+        snprintf(str, 256, "%s: %.2f", tags[i].utf8().data(), tagDuration);
+        paint.setARGB(255, 0, 0, 0);
+        int textY = (i * 12) + 25;
+        canvas->drawText(str, strlen(str), 0, textY, paint);
+        paint.setARGB(255, 255, 0, 0);
+        canvas->drawText(str, strlen(str), 0, textY + 1, paint);
+    }
+    snprintf(str, 256, "total: %.2f", total);
+    paint.setARGB(255, 0, 0, 0);
+    int textY = (tagCount * 12) + 30;
+    canvas->drawText(str, strlen(str), 0, textY, paint);
+    paint.setARGB(255, 255, 0, 0);
+    canvas->drawText(str, strlen(str), 0, textY + 1, paint);
 }
 
-void BaseRenderer::renderTiledContent(TileRenderInfo& renderInfo)
+int BaseRenderer::renderTiledContent(const TileRenderInfo& renderInfo)
 {
     const bool visualIndicator = TilesManager::instance()->getShowVisualIndicator();
     const SkSize& tileSize = renderInfo.tileSize;
@@ -98,50 +121,45 @@
     setupCanvas(renderInfo, &canvas);
 
     if (!canvas.getDevice()) {
-        // TODO: consider ALOGE
-        ALOGV("Error: No Device");
-        return;
+        XLOG("Error: No Device");
+        return 0;
     }
 
-    double before;
-    if (visualIndicator) {
+    if (visualIndicator)
         canvas.save();
-        before = currentTimeMS();
-    }
 
+    setupPartialInval(renderInfo, &canvas);
     canvas.translate(-renderInfo.x * tileSize.width(), -renderInfo.y * tileSize.height());
     canvas.scale(renderInfo.scale, renderInfo.scale);
-    renderInfo.tilePainter->paint(&canvas);
-    if (renderInfo.baseTile && renderInfo.baseTile->backTexture())
-        checkForPureColor(renderInfo, &canvas);
-    else
-        renderInfo.isPureColor = false;
+    unsigned int pictureCount = 0;
+    renderInfo.tilePainter->paint(renderInfo.baseTile, &canvas, &pictureCount);
 
     if (visualIndicator) {
-        double after = currentTimeMS();
         canvas.restore();
-        unsigned int updateCount = renderInfo.tilePainter->getUpdateCount() & UPDATE_COUNT_MASK;
-        const int color = updateCount & UPDATE_COUNT_ALPHA_MASK;
+        const int color = 20 + (pictureCount % 100);
 
         // only color the invalidated area
-        SkPaint paint;
-        paint.setARGB(color, 0, 255, 0);
-        SkIRect rect;
-        rect.set(0, 0, tileSize.width(), tileSize.height());
-        canvas.drawIRect(rect, paint);
-
-        drawTileInfo(&canvas, renderInfo, updateCount, after - before);
+        SkPaint invalPaint;
+        invalPaint.setARGB(color, 0, 255, 0);
+        canvas.drawIRect(*renderInfo.invalRect, invalPaint);
 
         // paint the tile boundaries
-        paint.setARGB(64, 255, 0, 0);
+        SkPaint paint;
+        paint.setARGB(128, 255, 0, 0);
         paint.setStrokeWidth(3);
         canvas.drawLine(0, 0, tileSize.width(), tileSize.height(), paint);
-        paint.setARGB(64, 0, 255, 0);
+        paint.setARGB(128, 0, 255, 0);
         canvas.drawLine(0, tileSize.height(), tileSize.width(), 0, paint);
         paint.setARGB(128, 0, 0, 255);
+        canvas.drawLine(0, 0, tileSize.width(), 0, paint);
         canvas.drawLine(tileSize.width(), 0, tileSize.width(), tileSize.height(), paint);
+
+        if (renderInfo.measurePerf)
+            drawTileInfo(&canvas, renderInfo, pictureCount);
     }
+    renderInfo.textureInfo->m_pictureCount = pictureCount;
     renderingComplete(renderInfo, &canvas);
+    return pictureCount;
 }
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h b/Source/WebCore/platform/graphics/android/BaseRenderer.h
similarity index 83%
rename from Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h
rename to Source/WebCore/platform/graphics/android/BaseRenderer.h
index b25a50e..7780db1 100644
--- a/Source/WebCore/platform/graphics/android/rendering/BaseRenderer.h
+++ b/Source/WebCore/platform/graphics/android/BaseRenderer.h
@@ -28,9 +28,8 @@
 
 #if USE(ACCELERATED_COMPOSITING)
 
-#include "Color.h"
+#include "PerformanceMonitor.h"
 #include "SkRect.h"
-#include <wtf/text/StringHash.h>
 
 class SkCanvas;
 class SkDevice;
@@ -39,7 +38,7 @@
 
 class TextureInfo;
 class TilePainter;
-class Tile;
+class BaseTile;
 
 struct TileRenderInfo {
     // coordinates of the tile
@@ -49,6 +48,9 @@
     // current scale factor
     float scale;
 
+    // inval rectangle with coordinates in the tile's coordinate space
+    SkIRect* invalRect;
+
     // the expected size of the tile
     SkSize tileSize;
 
@@ -56,13 +58,13 @@
     TilePainter* tilePainter;
 
     // the base tile calling us
-    Tile* baseTile;
+    BaseTile* baseTile;
 
     // info about the texture that we are to render into
     TextureInfo* textureInfo;
 
-    bool isPureColor;
-    Color pureColor;
+    // specifies whether or not to measure the rendering performance
+    bool measurePerf;
 };
 
 /**
@@ -74,7 +76,7 @@
     BaseRenderer(RendererType type) : m_type(type) {}
     virtual ~BaseRenderer() {}
 
-    void renderTiledContent(TileRenderInfo& renderInfo);
+    int renderTiledContent(const TileRenderInfo& renderInfo);
 
     RendererType getType() { return m_type; }
 
@@ -86,11 +88,16 @@
 protected:
 
     virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas) = 0;
+    virtual void setupPartialInval(const TileRenderInfo& renderInfo, SkCanvas* canvas) {}
     virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas) = 0;
-    virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) = 0;
 
     void drawTileInfo(SkCanvas* canvas, const TileRenderInfo& renderInfo,
-            int updateCount, double renderDuration);
+            int pictureCount);
+
+    virtual const String* getPerformanceTags(int& tagCount) = 0;
+
+    // Performance tracking
+    PerformanceMonitor m_perfMon;
 
 private:
     RendererType m_type;
diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/BaseTile.cpp
new file mode 100644
index 0000000..27bd482
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/BaseTile.cpp
@@ -0,0 +1,615 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "BaseTile.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "GLUtils.h"
+#include "RasterRenderer.h"
+#include "TextureInfo.h"
+#include "TilesManager.h"
+
+#include <cutils/atomic.h>
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTile", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTile", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+namespace WebCore {
+
+BaseTile::BaseTile(bool isLayerTile)
+    : m_glWebViewState(0)
+    , m_painter(0)
+    , m_x(-1)
+    , m_y(-1)
+    , m_page(0)
+    , m_frontTexture(0)
+    , m_backTexture(0)
+    , m_scale(1)
+    , m_dirty(true)
+    , m_repaintPending(false)
+    , m_lastDirtyPicture(0)
+    , m_isTexturePainted(false)
+    , m_isLayerTile(isLayerTile)
+    , m_drawCount(0)
+    , m_state(Unpainted)
+{
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->increment("BaseTile");
+#endif
+    m_currentDirtyAreaIndex = 0;
+
+    // For EglImage Mode, the internal buffer should be 2.
+    // For Surface Texture mode, we only need one.
+    if (TilesManager::instance()->getSharedTextureMode() == EglImageMode)
+        m_maxBufferNumber = 2;
+    else
+        m_maxBufferNumber = 1;
+
+    m_dirtyArea = new SkRegion[m_maxBufferNumber];
+    m_fullRepaint = new bool[m_maxBufferNumber];
+    for (int i = 0; i < m_maxBufferNumber; i++)
+        m_fullRepaint[i] = true;
+
+    m_renderer = BaseRenderer::createRenderer();
+}
+
+BaseTile::~BaseTile()
+{
+    if (m_backTexture)
+        m_backTexture->release(this);
+    if (m_frontTexture)
+        m_frontTexture->release(this);
+
+    delete m_renderer;
+    delete[] m_dirtyArea;
+    delete[] m_fullRepaint;
+
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->decrement("BaseTile");
+#endif
+}
+
+// All the following functions must be called from the main GL thread.
+
+void BaseTile::setContents(TilePainter* painter, int x, int y, float scale)
+{
+    if ((m_painter != painter)
+        || (m_x != x)
+        || (m_y != y)
+        || (m_scale != scale)) {
+        // neither texture is relevant
+        discardTextures();
+    }
+
+    android::AutoMutex lock(m_atomicSync);
+    m_painter = painter;
+    m_x = x;
+    m_y = y;
+    m_scale = scale;
+    m_drawCount = TilesManager::instance()->getDrawGLCount();
+}
+
+void BaseTile::reserveTexture()
+{
+    BaseTileTexture* texture = TilesManager::instance()->getAvailableTexture(this);
+
+    android::AutoMutex lock(m_atomicSync);
+    if (texture && m_backTexture != texture) {
+        XLOG("tile %p reserving texture %p, back was %p (front %p)",
+             this, texture, m_backTexture, m_frontTexture);
+        m_state = Unpainted;
+        m_backTexture = texture;
+    }
+
+    if (m_state == UpToDate) {
+        XLOG("moving tile %p to unpainted, since it reserved while up to date", this);
+        m_dirty = true;
+        m_state = Unpainted;
+    }
+}
+
+bool BaseTile::removeTexture(BaseTileTexture* texture)
+{
+    XLOG("%p removeTexture %p, back %p front %p... page %p",
+         this, texture, m_backTexture, m_frontTexture, m_page);
+    // We update atomically, so paintBitmap() can see the correct value
+    android::AutoMutex lock(m_atomicSync);
+    if (m_frontTexture == texture) {
+        if (m_state == UpToDate) {
+            XLOG("front texture removed, state was UpToDate, now becoming unpainted, bt is %p", m_backTexture);
+            m_state = Unpainted;
+        }
+
+        m_frontTexture = 0;
+    }
+    if (m_backTexture == texture) {
+        m_state = Unpainted;
+        m_backTexture = 0;
+    }
+
+    // mark dirty regardless of which texture was taken - the back texture may
+    // have been ready to swap
+    m_dirty = true;
+
+    return true;
+}
+
+void BaseTile::markAsDirty(int unsigned pictureCount,
+                           const SkRegion& dirtyArea)
+{
+    if (dirtyArea.isEmpty())
+        return;
+    android::AutoMutex lock(m_atomicSync);
+    m_lastDirtyPicture = pictureCount;
+    for (int i = 0; i < m_maxBufferNumber; i++)
+        m_dirtyArea[i].op(dirtyArea, SkRegion::kUnion_Op);
+
+    // Check if we actually intersect with the area
+    bool intersect = false;
+    SkRegion::Iterator cliperator(dirtyArea);
+    int tileWidth = TilesManager::instance()->tileWidth();
+    int tileHeight = TilesManager::instance()->tileHeight();
+    if (m_isLayerTile) {
+        tileWidth = TilesManager::instance()->layerTileWidth();
+        tileHeight = TilesManager::instance()->layerTileHeight();
+    }
+    SkRect realTileRect;
+    SkRect dirtyRect;
+    while (!cliperator.done()) {
+        dirtyRect.set(cliperator.rect());
+        if (intersectWithRect(m_x, m_y, tileWidth, tileHeight,
+                              m_scale, dirtyRect, realTileRect)) {
+            intersect = true;
+            break;
+        }
+        cliperator.next();
+    }
+
+    if (!intersect)
+        return;
+
+    m_dirty = true;
+    if (m_state == UpToDate) {
+        // We only mark a tile as unpainted in 'markAsDirty' if its status is
+        // UpToDate: marking dirty means we need to repaint, but don't stop the
+        // current paint
+        m_state = Unpainted;
+    } else if (m_state != Unpainted) {
+        // TODO: fix it so that they can paint while deferring the markAsDirty
+        // call (or block updates)
+        XLOG("Warning: tried to mark tile %p at %d, %d islayertile %d as dirty, state %d, page %p",
+              this, m_x, m_y, isLayerTile(), m_state, m_page);
+
+        // prefetch tiles can be marked dirty while in the process of painting,
+        // due to not using an update lock. force them to fail validate step.
+        m_state = Unpainted;
+    }
+}
+
+bool BaseTile::isDirty()
+{
+    android::AutoMutex lock(m_atomicSync);
+    return m_dirty;
+}
+
+bool BaseTile::isRepaintPending()
+{
+    android::AutoMutex lock(m_atomicSync);
+    return m_repaintPending;
+}
+
+void BaseTile::setRepaintPending(bool pending)
+{
+    android::AutoMutex lock(m_atomicSync);
+    m_repaintPending = pending;
+}
+
+void BaseTile::draw(float transparency, SkRect& rect, float scale)
+{
+    if (m_x < 0 || m_y < 0 || m_scale != scale)
+        return;
+
+    // No need to mutex protect reads of m_backTexture as it is only written to by
+    // the consumer thread.
+    if (!m_frontTexture)
+        return;
+
+    // Early return if set to un-usable in purpose!
+    m_atomicSync.lock();
+    bool isTexturePainted = m_isTexturePainted;
+    m_atomicSync.unlock();
+
+    if (!isTexturePainted)
+        return;
+
+    TextureInfo* textureInfo = m_frontTexture->consumerLock();
+    if (!textureInfo) {
+        m_frontTexture->consumerRelease();
+        return;
+    }
+
+    if (m_frontTexture->readyFor(this)) {
+        if (isLayerTile() && m_painter && m_painter->transform())
+            TilesManager::instance()->shader()->drawLayerQuad(*m_painter->transform(),
+                                                              rect, m_frontTexture->m_ownTextureId,
+                                                              transparency, true);
+        else
+            TilesManager::instance()->shader()->drawQuad(rect, m_frontTexture->m_ownTextureId,
+                                                         transparency);
+    } else {
+        XLOG("tile %p at %d, %d not readyfor (at draw),", this, m_x, m_y);
+    }
+
+    m_frontTexture->consumerRelease();
+}
+
+bool BaseTile::isTileReady()
+{
+    // Return true if the tile's most recently drawn texture is up to date
+    android::AutoMutex lock(m_atomicSync);
+    BaseTileTexture * texture = (m_state == ReadyToSwap) ? m_backTexture : m_frontTexture;
+
+    if (!texture)
+        return false;
+
+    if (texture->owner() != this)
+        return false;
+
+    if (m_dirty)
+        return false;
+
+    if (m_state != ReadyToSwap && m_state != UpToDate)
+        return false;
+
+    texture->consumerLock();
+    bool ready = texture->readyFor(this);
+    texture->consumerRelease();
+
+    if (ready)
+        return true;
+
+    XLOG("tile %p at %d, %d not readyfor (at isTileReady)", this, m_x, m_y);
+
+    return false;
+}
+
+bool BaseTile::intersectWithRect(int x, int y, int tileWidth, int tileHeight,
+                                 float scale, const SkRect& dirtyRect,
+                                 SkRect& realTileRect)
+{
+    // compute the rect to corresponds to pixels
+    realTileRect.fLeft = x * tileWidth;
+    realTileRect.fTop = y * tileHeight;
+    realTileRect.fRight = realTileRect.fLeft + tileWidth;
+    realTileRect.fBottom = realTileRect.fTop + tileHeight;
+
+    // scale the dirtyRect for intersect computation.
+    SkRect realDirtyRect = SkRect::MakeWH(dirtyRect.width() * scale,
+                                          dirtyRect.height() * scale);
+    realDirtyRect.offset(dirtyRect.fLeft * scale, dirtyRect.fTop * scale);
+
+    if (!realTileRect.intersect(realDirtyRect))
+        return false;
+    return true;
+}
+
+bool BaseTile::isTileVisible(const IntRect& viewTileBounds)
+{
+    return (m_x >= viewTileBounds.x()
+            && m_x < viewTileBounds.x() + viewTileBounds.width()
+            && m_y >= viewTileBounds.y()
+            && m_y < viewTileBounds.y() + viewTileBounds.height());
+}
+
+// This is called from the texture generation thread
+void BaseTile::paintBitmap()
+{
+    // We acquire the values below atomically. This ensures that we are reading
+    // values correctly across cores. Further, once we have these values they
+    // can be updated by other threads without consequence.
+    m_atomicSync.lock();
+    bool dirty = m_dirty;
+    BaseTileTexture* texture = m_backTexture;
+    SkRegion dirtyArea = m_dirtyArea[m_currentDirtyAreaIndex];
+    float scale = m_scale;
+    const int x = m_x;
+    const int y = m_y;
+    TilePainter* painter = m_painter;
+
+    if (!dirty || !texture) {
+        m_atomicSync.unlock();
+        return;
+    }
+    if (m_state != Unpainted) {
+        XLOG("Warning: started painting tile %p, but was at state %d, ft %p bt %p",
+              this, m_state, m_frontTexture, m_backTexture);
+    }
+    m_state = PaintingStarted;
+
+    texture->producerAcquireContext();
+    TextureInfo* textureInfo = texture->producerLock();
+    m_atomicSync.unlock();
+
+    // at this point we can safely check the ownership (if the texture got
+    // transferred to another BaseTile under us)
+    if (texture->owner() != this) {
+        texture->producerRelease();
+        return;
+    }
+
+    unsigned int pictureCount = 0;
+
+    // swap out the renderer if necessary
+    BaseRenderer::swapRendererIfNeeded(m_renderer);
+
+    // setup the common renderInfo fields;
+    TileRenderInfo renderInfo;
+    renderInfo.x = x;
+    renderInfo.y = y;
+    renderInfo.scale = scale;
+    renderInfo.tileSize = texture->getSize();
+    renderInfo.tilePainter = painter;
+    renderInfo.baseTile = this;
+    renderInfo.textureInfo = textureInfo;
+
+    const float tileWidth = renderInfo.tileSize.width();
+    const float tileHeight = renderInfo.tileSize.height();
+
+    SkRegion::Iterator cliperator(dirtyArea);
+
+    bool fullRepaint = false;
+
+    if (m_fullRepaint[m_currentDirtyAreaIndex]
+        || textureInfo->m_width != tileWidth
+        || textureInfo->m_height != tileHeight) {
+        fullRepaint = true;
+    }
+
+    bool surfaceTextureMode = textureInfo->getSharedTextureMode() == SurfaceTextureMode;
+
+    if (surfaceTextureMode)
+        fullRepaint = true;
+
+    while (!fullRepaint && !cliperator.done()) {
+        SkRect realTileRect;
+        SkRect dirtyRect;
+        dirtyRect.set(cliperator.rect());
+        bool intersect = intersectWithRect(x, y, tileWidth, tileHeight,
+                                           scale, dirtyRect, realTileRect);
+
+        // With SurfaceTexture, just repaint the entire tile if we intersect
+        // TODO: Implement the partial invalidate in Surface Texture Mode
+        if (intersect && surfaceTextureMode) {
+            fullRepaint = true;
+            break;
+        }
+
+        if (intersect && !surfaceTextureMode) {
+            // initialize finalRealRect to the rounded values of realTileRect
+            SkIRect finalRealRect;
+            realTileRect.roundOut(&finalRealRect);
+
+            // stash the int values of the current width and height
+            const int iWidth = finalRealRect.width();
+            const int iHeight = finalRealRect.height();
+
+            if (iWidth == tileWidth || iHeight == tileHeight) {
+                fullRepaint = true;
+                break;
+            }
+
+            // translate the rect into tile space coordinates
+            finalRealRect.fLeft = finalRealRect.fLeft % static_cast<int>(tileWidth);
+            finalRealRect.fTop = finalRealRect.fTop % static_cast<int>(tileHeight);
+            finalRealRect.fRight = finalRealRect.fLeft + iWidth;
+            finalRealRect.fBottom = finalRealRect.fTop + iHeight;
+
+            renderInfo.invalRect = &finalRealRect;
+            renderInfo.measurePerf = false;
+
+            pictureCount = m_renderer->renderTiledContent(renderInfo);
+        }
+
+        cliperator.next();
+    }
+
+    // Do a full repaint if needed
+    if (fullRepaint) {
+        SkIRect rect;
+        rect.set(0, 0, tileWidth, tileHeight);
+
+        renderInfo.invalRect = &rect;
+        renderInfo.measurePerf = TilesManager::instance()->getShowVisualIndicator();
+
+        pictureCount = m_renderer->renderTiledContent(renderInfo);
+    }
+
+    m_atomicSync.lock();
+
+#if DEPRECATED_SURFACE_TEXTURE_MODE
+    texture->setTile(textureInfo, x, y, scale, painter, pictureCount);
+#endif
+    texture->producerReleaseAndSwap();
+    if (texture == m_backTexture) {
+        m_isTexturePainted = true;
+
+        // set the fullrepaint flags
+        m_fullRepaint[m_currentDirtyAreaIndex] = false;
+
+        // The various checks to see if we are still dirty...
+
+        m_dirty = false;
+
+        if (m_scale != scale)
+            m_dirty = true;
+
+        if (fullRepaint)
+            m_dirtyArea[m_currentDirtyAreaIndex].setEmpty();
+        else
+            m_dirtyArea[m_currentDirtyAreaIndex].op(dirtyArea, SkRegion::kDifference_Op);
+
+        if (!m_dirtyArea[m_currentDirtyAreaIndex].isEmpty())
+            m_dirty = true;
+
+        // Now we can swap the dirty areas
+        // TODO: For surface texture in Async mode, the index will be updated
+        // according to the current buffer just dequeued.
+        m_currentDirtyAreaIndex = (m_currentDirtyAreaIndex+1) % m_maxBufferNumber;
+
+        if (!m_dirtyArea[m_currentDirtyAreaIndex].isEmpty())
+            m_dirty = true;
+
+        XLOG("painted tile %p (%d, %d), texture %p, dirty=%d", this, x, y, texture, m_dirty);
+
+        validatePaint();
+    } else {
+        XLOG("tile %p no longer owns texture %p, m_state %d. ft %p bt %p",
+             this, texture, m_state, m_frontTexture, m_backTexture);
+    }
+
+    m_atomicSync.unlock();
+}
+
+void BaseTile::discardTextures() {
+    android::AutoMutex lock(m_atomicSync);
+    XLOG("%p discarding bt %p, ft %p",
+         this, m_backTexture, m_frontTexture);
+    if (m_frontTexture) {
+        m_frontTexture->release(this);
+        m_frontTexture = 0;
+    }
+    if (m_backTexture) {
+        m_backTexture->release(this);
+        m_backTexture = 0;
+    }
+    for (int i = 0; i < m_maxBufferNumber; i++) {
+        m_dirtyArea[i].setEmpty();
+        m_fullRepaint[i] = true;
+    }
+    m_dirty = true;
+    m_state = Unpainted;
+}
+
+void BaseTile::discardBackTexture() {
+    android::AutoMutex lock(m_atomicSync);
+    if (m_backTexture) {
+        m_backTexture->release(this);
+        m_backTexture = 0;
+    }
+    m_state = Unpainted;
+    m_dirty = true;
+}
+
+bool BaseTile::swapTexturesIfNeeded() {
+    android::AutoMutex lock(m_atomicSync);
+    if (m_state == ReadyToSwap) {
+        // discard old texture and swap the new one in its place
+        if (m_frontTexture)
+            m_frontTexture->release(this);
+
+        m_frontTexture = m_backTexture;
+        m_backTexture = 0;
+        m_state = UpToDate;
+        XLOG("display texture for %p at %d, %d front is now %p, back is %p",
+             this, m_x, m_y, m_frontTexture, m_backTexture);
+
+        return true;
+    }
+    return false;
+}
+
+void BaseTile::backTextureTransfer() {
+    android::AutoMutex lock(m_atomicSync);
+    if (m_state == PaintingStarted)
+        m_state = TransferredUnvalidated;
+    else if (m_state == ValidatedUntransferred)
+        m_state = ReadyToSwap;
+    else {
+        // shouldn't have transferred a tile in any other state, log
+        XLOG("Note: transferred tile %p at %d %d, state wasn't paintingstarted or validated: %d",
+             this, m_x, m_y, m_state);
+    }
+}
+
+void BaseTile::backTextureTransferFail() {
+    // transfer failed for some reason, mark dirty so it will (repaint and) be
+    // retransferred.
+    android::AutoMutex lock(m_atomicSync);
+    m_state = Unpainted;
+    m_dirty = true;
+    // whether validatePaint is called before or after, it won't do anything
+}
+
+void BaseTile::validatePaint() {
+    // ONLY CALL while m_atomicSync is locked (at the end of paintBitmap())
+
+    if (!m_dirty) {
+        // since after the paint, the tile isn't dirty, 'validate' it - this
+        // may happed before or after the transfer queue operation. Only
+        // when both have happened, mark as 'ReadyToSwap'
+        if (m_state == PaintingStarted)
+            m_state = ValidatedUntransferred;
+        else if (m_state == TransferredUnvalidated)
+            m_state = ReadyToSwap;
+        else {
+            XLOG("Note: validated tile %p at %d %d, state wasn't paintingstarted or transferred %d",
+                  this, m_x, m_y, m_state);
+            // failed transferring, in which case mark dirty (since
+            // paintBitmap() may have cleared m_dirty)
+            m_dirty = true;
+        }
+
+        if (m_deferredDirty) {
+            XLOG("Note: deferred dirty flag set, possibly a missed paint on tile %p", this);
+            m_deferredDirty = false;
+        }
+    } else {
+        XLOG("Note: paint was unsuccessful.");
+        m_state = Unpainted;
+    }
+
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/rendering/Tile.h b/Source/WebCore/platform/graphics/android/BaseTile.h
similarity index 76%
rename from Source/WebCore/platform/graphics/android/rendering/Tile.h
rename to Source/WebCore/platform/graphics/android/BaseTile.h
index b045f1f..685ca43 100644
--- a/Source/WebCore/platform/graphics/android/rendering/Tile.h
+++ b/Source/WebCore/platform/graphics/android/BaseTile.h
@@ -23,13 +23,12 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef Tile_h
-#define Tile_h
+#ifndef BaseTile_h
+#define BaseTile_h
 
 #if USE(ACCELERATED_COMPOSITING)
 
 #include "BaseRenderer.h"
-#include "FloatPoint.h"
 #include "SkRect.h"
 #include "SkRegion.h"
 #include "TextureOwner.h"
@@ -40,7 +39,8 @@
 namespace WebCore {
 
 class TextureInfo;
-class TileTexture;
+class TiledPage;
+class BaseTileTexture;
 class GLWebViewState;
 
 /**
@@ -54,12 +54,12 @@
  *    the BaseLayer's most recent PictureSet to a bitmap which is then uploaded
  *    to the GPU.
  * 3. After the bitmap is uploaded to the GPU the main GL thread then uses the
- *    tile's drawGL() function to display the tile to the screen.
+ *    tile's draw() function to display the tile to the screen.
  * 4. Steps 2-3 are repeated as necessary.
  * 5. The tile is destroyed when the user navigates to a new page.
  *
  */
-class Tile : public TextureOwner {
+class BaseTile : public TextureOwner {
 public:
 
     // eventually, m_dirty might be rolled into the state machine, but note
@@ -89,45 +89,40 @@
         UpToDate = 5,
     };
 
-    Tile(bool isLayerTile = false);
-    ~Tile();
+    BaseTile(bool isLayerTile = false);
+    ~BaseTile();
 
     bool isLayerTile() { return m_isLayerTile; }
 
-    void setContents(int x, int y, float scale, bool isExpandedPrefetchTile);
+    void setContents(TilePainter* painter, int x, int y, float scale);
+    void setPage(TiledPage* page) { m_page = page; }
 
     void reserveTexture();
 
     bool isTileReady();
 
-    // Return false when real draw didn't happen for any reason.
-    bool drawGL(float opacity, const SkRect& rect, float scale,
-                const TransformationMatrix* transform,
-                bool forceBlending, bool usePointSampling,
-                const FloatRect& fillPortion);
+    void draw(float transparency, SkRect& rect, float scale);
 
     // the only thread-safe function called by the background thread
-    void paintBitmap(TilePainter* painter);
+    void paintBitmap();
 
     bool intersectWithRect(int x, int y, int tileWidth, int tileHeight,
                            float scale, const SkRect& dirtyRect,
                            SkRect& realTileRect);
     bool isTileVisible(const IntRect& viewTileBounds);
 
-    void markAsDirty();
-    void markAsDirty(const SkRegion& dirtyArea);
+    void markAsDirty(const unsigned int pictureCount,
+                     const SkRegion& dirtyArea);
     bool isDirty();
-    const SkRegion& dirtyArea() { return m_dirtyArea; }
-    virtual bool isRepaintPending();
+    bool isRepaintPending();
     void setRepaintPending(bool pending);
     float scale() const { return m_scale; }
     TextureState textureState() const { return m_state; }
 
     int x() const { return m_x; }
     int y() const { return m_y; }
-    TileTexture* frontTexture() { return m_frontTexture; }
-    TileTexture* backTexture() { return m_backTexture; }
-    TileTexture* lastDrawnTexture() { return m_lastDrawnTexture; }
+    BaseTileTexture* frontTexture() { return m_frontTexture; }
+    BaseTileTexture* backTexture() { return m_backTexture; }
 
     // only used for prioritization - the higher, the more relevant the tile is
     unsigned long long drawCount() { return m_drawCount; }
@@ -136,35 +131,54 @@
     bool swapTexturesIfNeeded();
     void backTextureTransfer();
     void backTextureTransferFail();
-    void onBlitUpdate();
+
+    void setGLWebViewState(GLWebViewState* state) { m_glWebViewState = state; }
 
     // TextureOwner implementation
-    virtual bool removeTexture(TileTexture* texture);
+    virtual bool removeTexture(BaseTileTexture* texture);
+    virtual TiledPage* page() { return m_page; }
+    virtual GLWebViewState* state() { return m_glWebViewState; }
+    TilePainter* painter() { return m_painter; }
 
 private:
-    void markAsDirtyInternal();
     void validatePaint();
 
+    GLWebViewState* m_glWebViewState;
+
+    TilePainter* m_painter;
     int m_x;
     int m_y;
 
+    TiledPage* m_page;
+
     // The remaining variables can be updated throughout the lifetime of the object
 
-    TileTexture* m_frontTexture;
-    TileTexture* m_backTexture;
-    TileTexture* m_lastDrawnTexture;
+    BaseTileTexture* m_frontTexture;
+    BaseTileTexture* m_backTexture;
     float m_scale;
 
     // used to signal that the that the tile is out-of-date and needs to be
     // redrawn in the backTexture
     bool m_dirty;
 
-    // number of repaints pending
-    int m_repaintsPending;
+    // currently only for debugging, to be used for tracking down dropped repaints
+    bool m_deferredDirty;
+
+    // used to signal that a repaint is pending
+    bool m_repaintPending;
+    // stores the id of the latest picture from webkit that caused this tile to
+    // become dirty. A tile is no longer dirty when it has been painted with a
+    // picture that is newer than this value.
+    unsigned int m_lastDirtyPicture;
 
     // store the dirty region
-    SkRegion m_dirtyArea;
-    bool m_fullRepaint;
+    SkRegion* m_dirtyArea;
+    bool* m_fullRepaint;
+    int m_maxBufferNumber;
+    int m_currentDirtyAreaIndex;
+
+    // flag used to know if we have a texture that was painted at least once
+    bool m_isTexturePainted;
 
     // This mutex serves two purposes. (1) It ensures that certain operations
     // happen atomically and (2) it makes sure those operations are synchronized
@@ -193,4 +207,4 @@
 } // namespace WebCore
 
 #endif // USE(ACCELERATED_COMPOSITING)
-#endif // Tile_h
+#endif // BaseTile_h
diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp
new file mode 100644
index 0000000..caaf116
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "BaseTileTexture.h"
+
+#include "BaseTile.h"
+#include "ClassTracker.h"
+#include "DeleteTextureOperation.h"
+#include "GLUtils.h"
+#include "TilesManager.h"
+
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTileTexture", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTileTexture", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+namespace WebCore {
+
+BaseTileTexture::BaseTileTexture(uint32_t w, uint32_t h)
+    : DoubleBufferedTexture(eglGetCurrentContext(),
+                            TilesManager::instance()->getSharedTextureMode())
+    , m_owner(0)
+    , m_busy(false)
+{
+    m_size.set(w, h);
+    m_ownTextureId = 0;
+
+    // Make sure they are created on the UI thread.
+    TilesManager::instance()->transferQueue()->initSharedSurfaceTextures(w, h);
+
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->increment("BaseTileTexture");
+#endif
+}
+
+BaseTileTexture::~BaseTileTexture()
+{
+    if (m_sharedTextureMode == EglImageMode) {
+        SharedTexture* textures[3] = { m_textureA, m_textureB, 0 };
+        destroyTextures(textures);
+    }
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->decrement("BaseTileTexture");
+#endif
+}
+
+void BaseTileTexture::requireGLTexture()
+{
+    if (!m_ownTextureId)
+        m_ownTextureId = GLUtils::createBaseTileGLTexture(m_size.width(), m_size.height());
+}
+
+void BaseTileTexture::discardGLTexture()
+{
+    if (m_ownTextureId)
+        GLUtils::deleteTexture(&m_ownTextureId);
+
+    if (m_owner) {
+        // clear both Tile->Texture and Texture->Tile links
+        m_owner->removeTexture(this);
+        release(m_owner);
+    }
+}
+
+void BaseTileTexture::destroyTextures(SharedTexture** textures)
+{
+    int x = 0;
+    while (textures[x]) {
+        // We need to delete the source texture and EGLImage in the texture
+        // generation thread. In theory we should be able to delete the EGLImage
+        // from either thread, but it currently throws an error if not deleted
+        // in the same EGLContext from which it was created.
+        textures[x]->lock();
+        DeleteTextureOperation* operation = new DeleteTextureOperation(
+            textures[x]->getSourceTextureId(), textures[x]->getEGLImage());
+        textures[x]->unlock();
+        TilesManager::instance()->scheduleOperation(operation);
+        x++;
+    }
+}
+
+TextureInfo* BaseTileTexture::producerLock()
+{
+    m_busyLock.lock();
+    m_busy = true;
+    m_busyLock.unlock();
+    return DoubleBufferedTexture::producerLock();
+}
+
+void BaseTileTexture::producerRelease()
+{
+    DoubleBufferedTexture::producerRelease();
+    setNotBusy();
+}
+
+void BaseTileTexture::producerReleaseAndSwap()
+{
+    DoubleBufferedTexture::producerReleaseAndSwap();
+    setNotBusy();
+}
+
+void BaseTileTexture::setNotBusy()
+{
+    android::Mutex::Autolock lock(m_busyLock);
+    m_busy = false;
+    m_busyCond.signal();
+}
+
+bool BaseTileTexture::busy()
+{
+    android::Mutex::Autolock lock(m_busyLock);
+    return m_busy;
+}
+
+void BaseTileTexture::producerUpdate(TextureInfo* textureInfo, const SkBitmap& bitmap)
+{
+    // no need to upload a texture since the bitmap is empty
+    if (!bitmap.width() && !bitmap.height()) {
+        producerRelease();
+        return;
+    }
+
+    // After the tiled layer checked in, this is not called anyway.
+    // TODO: cleanup the old code path for layer painting
+    // GLUtils::paintTextureWithBitmap(info, m_size, bitmap, 0, 0);
+
+    producerReleaseAndSwap();
+}
+
+bool BaseTileTexture::acquire(TextureOwner* owner, bool force)
+{
+    if (m_owner == owner)
+        return true;
+
+    return setOwner(owner, force);
+}
+
+bool BaseTileTexture::setOwner(TextureOwner* owner, bool force)
+{
+    // if the writable texture is busy (i.e. currently being written to) then we
+    // can't change the owner out from underneath that texture
+    m_busyLock.lock();
+    while (m_busy && force)
+        m_busyCond.wait(m_busyLock);
+    bool busy = m_busy;
+    m_busyLock.unlock();
+
+    if (!busy) {
+        // if we are not busy we can try to remove the texture from the layer;
+        // LayerAndroid::removeTexture() is protected by the same lock as
+        // LayerAndroid::paintBitmapGL(), so either we execute removeTexture()
+        // first and paintBitmapGL() will bail out, or we execute it after,
+        // and paintBitmapGL() will mark the texture as busy before
+        // relinquishing the lock. LayerAndroid::removeTexture() will call
+        // BaseTileTexture::release(), which will then do nothing
+        // if the texture is busy and we then don't return true.
+        bool proceed = true;
+        if (m_owner && m_owner != owner)
+            proceed = m_owner->removeTexture(this);
+
+        if (proceed) {
+            m_owner = owner;
+            return true;
+        }
+    }
+    return false;
+}
+
+bool BaseTileTexture::release(TextureOwner* owner)
+{
+    android::Mutex::Autolock lock(m_busyLock);
+    XLOG("texture %p releasing tile %p, m_owner %p, m_busy %d", this, owner, m_owner, m_busy);
+    if (m_owner != owner)
+        return false;
+
+    m_owner = 0;
+    return true;
+}
+
+void BaseTileTexture::setTile(TextureInfo* info, int x, int y,
+                                          float scale, TilePainter* painter,
+                                          unsigned int pictureCount)
+{
+    TextureTileInfo* textureInfo = m_texturesInfo.get(getWriteableTexture());
+    if (!textureInfo) {
+        textureInfo = new TextureTileInfo();
+    }
+    textureInfo->m_x = x;
+    textureInfo->m_y = y;
+    textureInfo->m_scale = scale;
+    textureInfo->m_painter = painter;
+    textureInfo->m_picture = pictureCount;
+    m_texturesInfo.set(getWriteableTexture(), textureInfo);
+}
+
+float BaseTileTexture::scale()
+{
+    TextureTileInfo* textureInfo = &m_ownTextureTileInfo;
+    return textureInfo->m_scale;
+}
+
+// This function + TilesManager::addItemInTransferQueue() is replacing the
+// setTile().
+void BaseTileTexture::setOwnTextureTileInfoFromQueue(const TextureTileInfo* info)
+{
+    m_ownTextureTileInfo.m_x = info->m_x;
+    m_ownTextureTileInfo.m_y = info->m_y;
+    m_ownTextureTileInfo.m_scale = info->m_scale;
+    m_ownTextureTileInfo.m_painter = info->m_painter;
+    m_ownTextureTileInfo.m_picture = info->m_picture;
+    m_ownTextureTileInfo.m_inverted = TilesManager::instance()->invertedScreen();
+    if (m_owner) {
+        BaseTile* owner = static_cast<BaseTile*>(m_owner);
+        owner->backTextureTransfer();
+    }
+
+}
+
+bool BaseTileTexture::readyFor(BaseTile* baseTile)
+{
+    const TextureTileInfo* info = &m_ownTextureTileInfo;
+    if (info &&
+        (info->m_x == baseTile->x()) &&
+        (info->m_y == baseTile->y()) &&
+        (info->m_scale == baseTile->scale()) &&
+        (info->m_painter == baseTile->painter()) &&
+        (info->m_inverted == TilesManager::instance()->invertedScreen()))
+        return true;
+
+    XLOG("texture %p readyFor return false for tile x, y (%d %d) texId %d ,"
+         " BaseTileTexture %p, BaseTile is %p, SCALE %f, painter %p, inv %d",
+         this, baseTile->x(), baseTile->y(), m_ownTextureId, this, baseTile,
+         baseTile->scale(), baseTile->painter(), TilesManager::instance()->invertedScreen());
+    return false;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.h b/Source/WebCore/platform/graphics/android/BaseTileTexture.h
new file mode 100644
index 0000000..cd8e78b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BaseTileTexture_h
+#define BaseTileTexture_h
+
+#include "DoubleBufferedTexture.h"
+#include "GLWebViewState.h"
+#include "TextureOwner.h"
+#include "TilePainter.h"
+#include <SkBitmap.h>
+
+class SkCanvas;
+
+namespace WebCore {
+
+class BaseTile;
+
+class TextureTileInfo {
+public:
+    TextureTileInfo()
+    : m_x(-1)
+    , m_y(-1)
+    , m_layerId(-1)
+    , m_scale(0)
+    , m_texture(0)
+    , m_painter(0)
+    , m_picture(0)
+    , m_inverted(false)
+    {
+    }
+    int m_x;
+    int m_y;
+    int m_layerId;
+    float m_scale;
+    TextureInfo* m_texture;
+    TilePainter* m_painter;
+    unsigned int m_picture;
+    bool m_inverted;
+};
+
+// DoubleBufferedTexture using a SkBitmap as backing mechanism
+class BaseTileTexture : public DoubleBufferedTexture {
+public:
+    // This object is to be constructed on the consumer's thread and must have
+    // a width and height greater than 0.
+    BaseTileTexture(uint32_t w, uint32_t h);
+    virtual ~BaseTileTexture();
+
+    // these functions override their parent
+    virtual TextureInfo* producerLock();
+    virtual void producerRelease();
+    virtual void producerReleaseAndSwap();
+
+    // updates the texture with current bitmap and releases (and if needed also
+    // swaps) the texture.
+    virtual void producerUpdate(TextureInfo* textureInfo, const SkBitmap& bitmap);
+
+    // allows consumer thread to assign ownership of the texture to the tile. It
+    // returns false if ownership cannot be transferred because the tile is busy
+    bool acquire(TextureOwner* owner, bool force = false);
+    bool release(TextureOwner* owner);
+
+    // removes Tile->Texture, and Texture->Tile links to fully discard the texture
+    void releaseAndRemoveFromTile();
+
+    // set the texture owner if not busy. Return false if busy, true otherwise.
+    bool setOwner(TextureOwner* owner, bool force = false);
+
+    // private member accessor functions
+    TextureOwner* owner() { return m_owner; } // only used by the consumer thread
+
+    bool busy();
+    void setNotBusy();
+
+    const SkSize& getSize() const { return m_size; }
+
+    void setTile(TextureInfo* info, int x, int y, float scale,
+                 TilePainter* painter, unsigned int pictureCount);
+    bool readyFor(BaseTile* baseTile);
+    float scale();
+
+    // OpenGL ID of backing texture, 0 when not allocated
+    GLuint m_ownTextureId;
+    // these are used for dynamically (de)allocating backing graphics memory
+    void requireGLTexture();
+    void discardGLTexture();
+
+    void setOwnTextureTileInfoFromQueue(const TextureTileInfo* info);
+
+protected:
+    HashMap<SharedTexture*, TextureTileInfo*> m_texturesInfo;
+
+private:
+    void destroyTextures(SharedTexture** textures);
+    TextureTileInfo m_ownTextureTileInfo;
+
+    SkSize m_size;
+    SkBitmap::Config m_config;
+
+    // BaseTile owning the texture, only modified by UI thread
+    TextureOwner* m_owner;
+
+    // This values signals that the texture is currently in use by the consumer.
+    // This allows us to prevent the owner of the texture from changing while the
+    // consumer is holding a lock on the texture.
+    bool m_busy;
+    // We mutex protect the reads/writes of m_busy to ensure that we are reading
+    // the most up-to-date value even across processors in an SMP system.
+    android::Mutex m_busyLock;
+    // We use this condition variable to signal that the texture
+    // is not busy anymore
+    android::Condition m_busyCond;
+};
+
+} // namespace WebCore
+
+#endif // BaseTileTexture_h
diff --git a/Source/WebCore/platform/graphics/android/utils/ClassTracker.cpp b/Source/WebCore/platform/graphics/android/ClassTracker.cpp
similarity index 73%
rename from Source/WebCore/platform/graphics/android/utils/ClassTracker.cpp
rename to Source/WebCore/platform/graphics/android/ClassTracker.cpp
index a73ece8..eb810a8 100644
--- a/Source/WebCore/platform/graphics/android/utils/ClassTracker.cpp
+++ b/Source/WebCore/platform/graphics/android/ClassTracker.cpp
@@ -23,18 +23,19 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#define LOG_TAG "ClassTracker"
-#define LOG_NDEBUG 1
-
 #include "config.h"
 #include "ClassTracker.h"
 
-#include "AndroidLog.h"
 #include "LayerAndroid.h"
 #include "TilesManager.h"
 
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
 #include <wtf/text/CString.h>
 
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ClassTracker", __VA_ARGS__)
+
 #define DEBUG_LAYERS
 #undef DEBUG_LAYERS
 
@@ -84,12 +85,12 @@
 void ClassTracker::show()
 {
    android::Mutex::Autolock lock(m_lock);
-   ALOGD("*** Tracking %d classes ***", m_classes.size());
+   XLOG("*** Tracking %d classes ***", m_classes.size());
    for (HashMap<String, int>::iterator iter = m_classes.begin(); iter != m_classes.end(); ++iter) {
-       ALOGD("class %s has %d instances",
-             iter->first.ascii().data(), iter->second);
+       XLOG("class %s has %d instances",
+            iter->first.latin1().data(), iter->second);
    }
-   ALOGD("*** %d Layers ***", m_layers.size());
+   XLOG("*** %d Layers ***", m_layers.size());
    int nbTextures = 0;
    int nbAllocatedTextures = 0;
    int nbLayerTextures = 0;
@@ -97,23 +98,23 @@
    float textureSize = 256 * 256 * 4 / 1024.0 / 1024.0;
    TilesManager::instance()->gatherTexturesNumbers(&nbTextures, &nbAllocatedTextures,
                                                    &nbLayerTextures, &nbAllocatedLayerTextures);
-   ALOGD("*** textures: %d/%d (%.2f Mb), layer textures: %d/%d (%.2f Mb) : total used %.2f Mb",
-         nbAllocatedTextures, nbTextures,
-         nbAllocatedTextures * textureSize,
-         nbAllocatedLayerTextures, nbLayerTextures,
-         nbAllocatedLayerTextures * textureSize,
-         (nbAllocatedTextures + nbAllocatedLayerTextures) * textureSize);
+   XLOG("*** textures: %d/%d (%.2f Mb), layer textures: %d/%d (%.2f Mb) : total used %.2f Mb",
+        nbAllocatedTextures, nbTextures,
+        nbAllocatedTextures * textureSize,
+        nbAllocatedLayerTextures, nbLayerTextures,
+        nbAllocatedLayerTextures * textureSize,
+        (nbAllocatedTextures + nbAllocatedLayerTextures) * textureSize);
 
 #ifdef DEBUG_LAYERS
    for (unsigned int i = 0; i < m_layers.size(); i++) {
        LayerAndroid* layer = m_layers[i];
-       ALOGD("[%d/%d] layer %x (%.2f, %.2f) of type %d, refcount(%d) has texture %x has image ref %x (%x) root: %x parent: %x",
-             i, m_layers.size(), layer,
-             layer->getWidth(), layer->getHeight(),
-             layer->type(), layer->getRefCnt(),
-             layer->texture(), layer->imageRef(),
-             layer->imageTexture(), (LayerAndroid*) layer->getRootLayer(),
-             (LayerAndroid*) layer->getParent());
+       XLOG("[%d/%d] layer %x (%.2f, %.2f) of type %d, refcount(%d) has texture %x has image ref %x (%x) root: %x parent: %x",
+            i, m_layers.size(), layer,
+            layer->getWidth(), layer->getHeight(),
+            layer->type(), layer->getRefCnt(),
+            layer->texture(), layer->imageRef(),
+            layer->imageTexture(), (LayerAndroid*) layer->getRootLayer(),
+            (LayerAndroid*) layer->getParent());
    }
 #endif
 }
diff --git a/Source/WebCore/platform/graphics/android/utils/ClassTracker.h b/Source/WebCore/platform/graphics/android/ClassTracker.h
similarity index 100%
rename from Source/WebCore/platform/graphics/android/utils/ClassTracker.h
rename to Source/WebCore/platform/graphics/android/ClassTracker.h
diff --git a/Source/WebCore/platform/graphics/android/DeleteTextureOperation.h b/Source/WebCore/platform/graphics/android/DeleteTextureOperation.h
new file mode 100644
index 0000000..f3cb57c
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/DeleteTextureOperation.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DeleteTextureOperation_h
+#define DeleteTextureOperation_h
+
+#include "GLUtils.h"
+#include "QueuedOperation.h"
+
+namespace WebCore {
+
+class DeleteTextureOperation : public QueuedOperation {
+public:
+    DeleteTextureOperation(GLuint textureId, EGLImageKHR eglImage)
+        : QueuedOperation(QueuedOperation::DeleteTexture, 0)
+        , m_textureId(textureId)
+        , m_eglImage(eglImage) {}
+    virtual bool operator==(const QueuedOperation* operation)
+    {
+        if (operation->type() != type())
+            return false;
+        const DeleteTextureOperation* op = static_cast<const DeleteTextureOperation*>(operation);
+        return op->m_textureId == m_textureId;
+    }
+    virtual void run()
+    {
+        if (m_textureId)
+            GLUtils::deleteTexture(&m_textureId);
+        if (m_eglImage)
+            eglDestroyImageKHR(eglGetCurrentDisplay(), m_eglImage);
+    }
+private:
+    GLuint m_textureId;
+    EGLImageKHR m_eglImage;
+};
+
+}
+
+#endif // DeleteTextureOperation_h
diff --git a/Source/WebCore/platform/graphics/android/DoubleBufferedTexture.cpp b/Source/WebCore/platform/graphics/android/DoubleBufferedTexture.cpp
new file mode 100644
index 0000000..4c5af9e
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/DoubleBufferedTexture.cpp
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DoubleBufferedTexture.h"
+
+#include "ClassTracker.h"
+#include "GLUtils.h"
+
+#define LOG_NDEBUG 1
+#define LOG_TAG "DoubleBufferedTexture.cpp"
+#include <utils/Log.h>
+
+namespace WebCore {
+
+DoubleBufferedTexture::DoubleBufferedTexture(EGLContext sharedContext, SharedTextureMode mode)
+{
+    m_sharedTextureMode = mode;
+
+    m_textureA = new SharedTexture(m_sharedTextureMode);
+    if (m_sharedTextureMode == EglImageMode)
+        m_textureB = new SharedTexture(m_sharedTextureMode);
+    else
+        m_textureB = 0;
+
+    m_display = eglGetCurrentDisplay();
+    m_pContext = EGL_NO_CONTEXT;
+    m_cContext = sharedContext;
+    m_writeableTexture = m_textureA;
+    m_lockedConsumerTexture = GL_NO_TEXTURE;
+    m_supportsEGLImage = GLUtils::isEGLImageSupported();
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->increment("DoubleBufferedTexture");
+#endif
+}
+
+DoubleBufferedTexture::~DoubleBufferedTexture()
+{
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->decrement("DoubleBufferedTexture");
+#endif
+    delete m_textureA;
+    delete m_textureB;
+}
+
+SharedTexture* DoubleBufferedTexture::getWriteableTexture()
+{
+    if (m_sharedTextureMode == SurfaceTextureMode)
+        return m_textureA;
+    return reinterpret_cast<SharedTexture*>(
+        android_atomic_release_load((int32_t*)&m_writeableTexture));
+}
+
+SharedTexture* DoubleBufferedTexture::getReadableTexture()
+{
+    if (m_sharedTextureMode == SurfaceTextureMode)
+        return m_textureA;
+    return (getWriteableTexture() != m_textureA) ? m_textureA : m_textureB;
+}
+
+EGLContext DoubleBufferedTexture::producerAcquireContext()
+{
+    if (m_sharedTextureMode == SurfaceTextureMode)
+        return EGL_NO_CONTEXT;
+
+    if (m_pContext != EGL_NO_CONTEXT) {
+        LOGV("AquireContext has previously generated a context.\n");
+        return m_pContext;
+    }
+
+    // check to see if a context already exists on this thread
+    EGLContext context = eglGetCurrentContext();
+
+    // if no context exists then create one
+    if (context == EGL_NO_CONTEXT) {
+        EGLContext sharedContext = m_supportsEGLImage ? EGL_NO_CONTEXT : m_cContext;
+        context = GLUtils::createBackgroundContext(sharedContext);
+    }
+
+    if (context == EGL_NO_CONTEXT) {
+        LOGE("eglCreateContext failed");
+        return EGL_NO_CONTEXT;
+    }
+
+    // initialize the producer's textures
+    m_textureA->lock();
+    if (m_sharedTextureMode == EglImageMode)
+        m_textureB->lock();
+
+    m_textureA->initSourceTexture();
+    LOGV("Initialized Textures A (%d)", m_textureA->getSourceTextureId());
+    if (m_sharedTextureMode == EglImageMode) {
+        m_textureB->initSourceTexture();
+        LOGV("Initialized Textures B (%d)", m_textureB->getSourceTextureId());
+    }
+
+    m_textureA->unlock();
+    if (m_sharedTextureMode == EglImageMode)
+        m_textureB->unlock();
+
+    m_pContext = context;
+    return context;
+}
+
+// For MediaTexture only
+void DoubleBufferedTexture::producerDeleteTextures()
+{
+    m_textureA->lock();
+    if (m_sharedTextureMode == EglImageMode)
+        m_textureB->lock();
+
+    LOGV("Deleting Producer Textures A (%d)", m_textureA->getSourceTextureId());
+    m_textureA->deleteSourceTexture();
+    if (m_sharedTextureMode == EglImageMode){
+        LOGV("Deleting Producer Textures B (%d)", m_textureB->getSourceTextureId());
+        m_textureB->deleteSourceTexture();
+    }
+
+    m_textureA->unlock();
+    if (m_sharedTextureMode == EglImageMode)
+        m_textureB->unlock();
+}
+
+// For MediaTexture only
+void DoubleBufferedTexture::consumerDeleteTextures()
+{
+    m_textureA->lock();
+    if (m_sharedTextureMode == EglImageMode)
+        m_textureB->lock();
+
+    LOGV("Deleting Consumer Textures A (%d)", m_textureA->getTargetTextureId());
+    m_textureA->deleteTargetTexture();
+    if (m_sharedTextureMode == EglImageMode) {
+        LOGV("Deleting Consumer Textures B (%d)", m_textureB->getTargetTextureId());
+        m_textureB->deleteTargetTexture();
+    }
+
+    m_textureA->unlock();
+    if (m_sharedTextureMode == EglImageMode)
+        m_textureB->unlock();
+}
+
+TextureInfo* DoubleBufferedTexture::producerLock()
+{
+    SharedTexture* sharedTex = getWriteableTexture();
+    LOGV("Acquiring P Lock (%d)", sharedTex->getSourceTextureId());
+    TextureInfo* texInfo = sharedTex->lockSource();
+    LOGV("Acquired P Lock");
+
+    return texInfo;
+}
+
+void DoubleBufferedTexture::producerRelease()
+{
+    // get the writable texture and unlock it
+    SharedTexture* sharedTex = getWriteableTexture();
+    LOGV("Releasing P Lock (%d)", sharedTex->getSourceTextureId());
+    sharedTex->releaseSource();
+    LOGV("Released P Lock (%d)", sharedTex->getSourceTextureId());
+}
+
+void DoubleBufferedTexture::producerReleaseAndSwap()
+{
+    producerRelease();
+    if (m_sharedTextureMode == EglImageMode) {
+        // swap the front and back buffers using an atomic op for the memory barrier
+        android_atomic_acquire_store((int32_t)getReadableTexture(), (int32_t*)&m_writeableTexture);
+    }
+}
+
+TextureInfo* DoubleBufferedTexture::consumerLock()
+{
+    SharedTexture* sharedTex = getReadableTexture();
+    LOGV("Acquiring C Lock (%d)", sharedTex->getSourceTextureId());
+    m_lockedConsumerTexture = sharedTex;
+
+    TextureInfo* texInfo = sharedTex->lockTarget();
+    LOGV("Acquired C Lock");
+
+    if (!texInfo)
+        LOGV("Released C Lock (Empty)");
+
+    return texInfo;
+}
+
+void DoubleBufferedTexture::consumerRelease()
+{
+    // we must check to see what texture the consumer had locked since the
+    // producer may have swapped out the readable buffer
+    SharedTexture* sharedTex = m_lockedConsumerTexture;
+    sharedTex->releaseTarget();
+    LOGV("Released C Lock (%d)", sharedTex->getSourceTextureId());
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/DoubleBufferedTexture.h b/Source/WebCore/platform/graphics/android/DoubleBufferedTexture.h
new file mode 100644
index 0000000..821b79b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/DoubleBufferedTexture.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DoubleBufferedTexture_h
+#define DoubleBufferedTexture_h
+
+#include "SharedTexture.h"
+#include <EGL/egl.h>
+
+namespace WebCore {
+
+class DoubleBufferedTexture {
+public:
+    // consumer thread functions
+    DoubleBufferedTexture(EGLContext sharedContext, SharedTextureMode mode);
+    virtual ~DoubleBufferedTexture();
+
+    // provider thread functions
+    virtual TextureInfo* producerLock();
+    virtual void producerRelease();
+    virtual void producerReleaseAndSwap();
+    EGLContext producerAcquireContext();
+    void producerDeleteTextures();
+
+    // consumer thread functions
+    TextureInfo* consumerLock();
+    void consumerRelease();
+    void consumerDeleteTextures();
+
+protected:
+    SharedTexture* getReadableTexture();
+    SharedTexture* getWriteableTexture();
+
+    SharedTexture* m_textureA;
+    SharedTexture* m_textureB;
+
+    SharedTextureMode m_sharedTextureMode;
+private:
+
+    SharedTexture* m_writeableTexture;
+    SharedTexture* m_lockedConsumerTexture; // only used by the consumer
+
+    EGLDisplay m_display;
+    EGLContext m_pContext;
+    EGLContext m_cContext;
+
+    bool m_supportsEGLImage;
+};
+
+} // namespace WebCore
+
+#endif // DoubleBufferedTexture_h
diff --git a/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp b/Source/WebCore/platform/graphics/android/FontAndroid.cpp
similarity index 85%
rename from Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp
rename to Source/WebCore/platform/graphics/android/FontAndroid.cpp
index 7bed5bb..0a8c0c1 100644
--- a/Source/WebCore/platform/graphics/android/fonts/FontAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/FontAndroid.cpp
@@ -27,8 +27,6 @@
 #include "config.h"
 
 #include "EmojiFont.h"
-#include "GraphicsOperationCollection.h"
-#include "GraphicsOperation.h"
 #include "Font.h"
 #include "FontData.h"
 #include "FontFallbackList.h"
@@ -54,7 +52,6 @@
 #include <wtf/OwnPtr.h>
 #include <wtf/PassOwnArrayPtr.h>
 #include <wtf/PassOwnPtr.h>
-#include <wtf/unicode/CharacterNames.h>
 #include <wtf/unicode/Unicode.h>
 #endif
 
@@ -63,7 +60,6 @@
 namespace WebCore {
 
 typedef std::pair<int, float> FallbackFontKey;
-
 typedef HashMap<FallbackFontKey, FontPlatformData*> FallbackHash;
 
 static void updateForFont(SkPaint* paint, const SimpleFontData* font) {
@@ -91,16 +87,10 @@
     if (!mode)
         return false;
 
-    paint->setVerticalText(font->platformData().orientation() == Vertical);
-
     FloatSize shadowOffset;
     float shadowBlur;
     Color shadowColor;
     ColorSpace shadowColorSpace;
-
-    if (RenderSkinAndroid::DrawableResolution() >= RenderSkinAndroid::HighRes)
-        paint->setAutohinted(false);
-
     bool hasShadow = gc->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
     bool hasBothStrokeAndFill =
         (mode & (TextModeStroke | TextModeFill)) == (TextModeStroke | TextModeFill);
@@ -202,16 +192,15 @@
     const GlyphBufferAdvance*   adv = glyphBuffer.advances(from);
     SkAutoSTMalloc<32, SkPoint> storage(numGlyphs), storage2(numGlyphs), storage3(numGlyphs);
     SkPoint*                    pos = storage.get();
+    SkPoint*                    vPosBegin = storage2.get();
+    SkPoint*                    vPosEnd = storage3.get();
 
-    SkCanvas* canvas = gc->platformContext()->recordingCanvas();
+    SkCanvas* canvas = gc->platformContext()->mCanvas;
 
     /*  We need an array of [x,y,x,y,x,y,...], but webkit is giving us
         point.xy + [width, height, width, height, ...], so we have to convert
      */
 
-    if (font->platformData().orientation() == Vertical)
-        y += SkFloatToScalar(font->fontMetrics().floatAscent(IdeographicBaseline) - font->fontMetrics().floatAscent());
-
     if (EmojiFont::IsAvailable()) {
         // set filtering, to make scaled images look nice(r)
         paint.setFilterBitmap(true);
@@ -241,27 +230,28 @@
                                 localCount * sizeof(uint16_t),
                                 &pos[localIndex], paint);
     } else {
+        bool isVertical = font->platformData().orientation() == Vertical;
         for (int i = 0; i < numGlyphs; i++) {
             pos[i].set(x, y);
             y += SkFloatToScalar(adv[i].height());
-            x += SkFloatToScalar(adv[i].width());
+            if (isVertical) {
+                SkScalar myWidth = SkFloatToScalar(adv[i].width());
+                vPosBegin[i].set(x + myWidth, y);
+                vPosEnd[i].set(x + myWidth, y - myWidth);
+                x += myWidth;
+
+                SkPath path;
+                path.reset();
+                path.moveTo(vPosBegin[i]);
+                path.lineTo(vPosEnd[i]);
+                canvas->drawTextOnPath(glyphs + i, 2, path, 0, paint);
+            }
+            else
+                x += SkFloatToScalar(adv[i].width());
         }
-
-        if (font->platformData().orientation() == Vertical) {
-            canvas->save();
-            canvas->rotate(-90);
-            SkMatrix rotator;
-            rotator.reset();
-            rotator.setRotate(90);
-            rotator.mapPoints(pos, numGlyphs);
-        }
-
-        canvas->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, paint);
-
-        if (font->platformData().orientation() == Vertical)
-            canvas->restore();
+        if (!isVertical)
+            canvas->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, paint);
     }
-    gc->platformContext()->endRecording();
 }
 
 void Font::drawEmphasisMarksForComplexText(WebCore::GraphicsContext*, WebCore::TextRun const&, WTF::AtomicString const&, WebCore::FloatPoint const&, int, int) const
@@ -389,7 +379,7 @@
 // can call |reset| to start over again.
 class TextRunWalker {
 public:
-    TextRunWalker(const TextRun&, int, int, const Font*);
+    TextRunWalker(const TextRun&, unsigned, const Font*);
     ~TextRunWalker();
 
     bool isWordBreak(unsigned, bool);
@@ -435,10 +425,10 @@
     // Return the length of the array returned by |glyphs|
     unsigned length() const { return m_item.num_glyphs; }
 
-    // Return the offset for each of the glyphs. Note that this is translated
+    // Return the x offset for each of the glyphs. Note that this is translated
     // by the current x offset and that the x offset is updated for each script
     // run.
-    const SkPoint* positions() const { return m_positions; }
+    const SkScalar* xPositions() const { return m_xPositions; }
 
     // Get the advances (widths) for each glyph.
     const HB_Fixed* advances() const { return m_item.advances; }
@@ -466,12 +456,8 @@
         Devanagari,
         Hebrew,
         HebrewBold,
-        Kannada,
-        Malayalam,
         Naskh,
         Tamil,
-        TamilBold,
-        Telugu,
         Thai,
         NUM_SCRIPTS
     };
@@ -486,7 +472,7 @@
     void createGlyphArrays(int);
     void resetGlyphArrays();
     void shapeGlyphs();
-    void setGlyphPositions(bool);
+    void setGlyphXPositions(bool);
 
     static void normalizeSpacesAndMirrorChars(const UChar* source, bool rtl,
         UChar* destination, int length);
@@ -499,11 +485,10 @@
     const Font* const m_font;
     HB_ShaperItem m_item;
     uint16_t* m_glyphs16; // A vector of 16-bit glyph ids.
-    SkPoint* m_positions; // A vector of positions for each glyph.
+    SkScalar* m_xPositions; // A vector of x positions for each glyph.
     ssize_t m_indexOfNextScriptRun; // Indexes the script run in |m_run|.
-    const int m_startingX; // Offset in pixels of the first script run.
-    const int m_startingY; // Offset in pixels of the first script run.
-    int m_offsetX; // Offset in pixels to the start of the next script run.
+    const unsigned m_startingX; // Offset in pixels of the first script run.
+    unsigned m_offsetX; // Offset in pixels to the start of the next script run.
     unsigned m_pixelWidth; // Width (in px) of the current script run.
     unsigned m_numCodePoints; // Code points in current script run.
     unsigned m_glyphsArrayCapacity; // Current size of all the Harfbuzz arrays.
@@ -526,22 +511,17 @@
 // Indexed using enum CustomScript
 const char* TextRunWalker::paths[] = {
     "/system/fonts/Lohit-Bengali.ttf",
-    "/system/fonts/DroidSansDevanagari-Regular.ttf",
+    "/system/fonts/Lohit-Devanagari.ttf",
     "/system/fonts/DroidSansHebrew-Regular.ttf",
     "/system/fonts/DroidSansHebrew-Bold.ttf",
-    "/system/fonts/Lohit-Kannada.ttf",
-    "/system/fonts/AnjaliNewLipi-light.ttf",
     "/system/fonts/DroidNaskh-Regular.ttf",
-    "/system/fonts/DroidSansTamil-Regular.ttf",
-    "/system/fonts/DroidSansTamil-Bold.ttf",
-    "/system/fonts/Lohit-Telugu.ttf",
+    "/system/fonts/Lohit-Tamil.ttf",
     "/system/fonts/DroidSansThai.ttf"
 };
 
-TextRunWalker::TextRunWalker(const TextRun& run, int startingX, int startingY, const Font* font)
+TextRunWalker::TextRunWalker(const TextRun& run, unsigned startingX, const Font* font)
     : m_font(font)
     , m_startingX(startingX)
-    , m_startingY(startingY)
     , m_offsetX(m_startingX)
     , m_run(getNormalizedTextRun(run, m_normalizedRun, m_normalizedBuffer))
     , m_iterateBackwards(m_run.rtl())
@@ -670,7 +650,7 @@
 
     setupFontForScriptRun();
     shapeGlyphs();
-    setGlyphPositions(rtl());
+    setGlyphXPositions(rtl());
 
     return true;
 }
@@ -697,17 +677,7 @@
 {
     static FallbackHash fallbackPlatformData;
 
-    // generate scriptStyleIndex - we need unique hash IDs for each style
-    // of each script - normal, bold, italic, bolditalic. the first set of
-    // NUM_SCRIPTS are the normal style version, followed by bold, then
-    // italic, then bold italic. additional fake style bits can be added.
-    int scriptStyleIndex = script;
-    if (platformData.isFakeBold())
-        scriptStyleIndex += NUM_SCRIPTS;
-    if (platformData.isFakeItalic())
-        scriptStyleIndex += NUM_SCRIPTS << 1;
-
-    FallbackFontKey key(scriptStyleIndex, platformData.size());
+    FallbackFontKey key(script, platformData.size());
     FontPlatformData* newPlatformData = 0;
 
     if (!fallbackPlatformData.contains(key)) {
@@ -736,7 +706,7 @@
           complexPlatformData = setupComplexFont(Bengali, platformData);
           break;
         case HB_Script_Devanagari:
-          complexPlatformData = setupComplexFont(Devanagari, platformData);
+            complexPlatformData = setupComplexFont(Devanagari, platformData);
             break;
         case HB_Script_Hebrew:
             switch (platformData.typeface()->style()) {
@@ -751,30 +721,11 @@
                     break;
             }
             break;
-        case HB_Script_Kannada:
-            complexPlatformData = setupComplexFont(Kannada, platformData);
-            break;
-        case HB_Script_Malayalam:
-            complexPlatformData = setupComplexFont(Malayalam, platformData);
-            break;
         case HB_Script_Arabic:
             complexPlatformData = setupComplexFont(Naskh, platformData);
             break;
         case HB_Script_Tamil:
-            switch (platformData.typeface()->style()) {
-                case SkTypeface::kBold:
-                case SkTypeface::kBoldItalic:
-                    complexPlatformData = setupComplexFont(TamilBold, platformData);
-                    break;
-                case SkTypeface::kNormal:
-                case SkTypeface::kItalic:
-                default:
-                    complexPlatformData = setupComplexFont(Tamil, platformData);
-                    break;
-            }
-            break;
-        case HB_Script_Telugu:
-            complexPlatformData = setupComplexFont(Telugu, platformData);
+            complexPlatformData = setupComplexFont(Tamil, platformData);
             break;
         case HB_Script_Thai:
             complexPlatformData = setupComplexFont(Thai, platformData);
@@ -786,16 +737,6 @@
     }
     m_item.face = complexPlatformData->harfbuzzFace();
     m_item.font->userData = const_cast<FontPlatformData*>(complexPlatformData);
-
-    int size = complexPlatformData->size();
-    m_item.font->x_ppem = size;
-    m_item.font->y_ppem = size;
-    // x_ and y_scale are the conversion factors from font design space (fEmSize) to 1/64th of device pixels in 16.16 format.
-    const int devicePixelFraction = 64;
-    const int multiplyFor16Dot16 = 1 << 16;
-    int scale = devicePixelFraction * size * multiplyFor16Dot16 / complexPlatformData->emSizeInFontUnits();
-    m_item.font->x_scale = scale;
-    m_item.font->y_scale = scale;
 }
 
 HB_FontRec* TextRunWalker::allocHarfbuzzFont()
@@ -804,6 +745,13 @@
     memset(font, 0, sizeof(HB_FontRec));
     font->klass = &harfbuzzSkiaClass;
     font->userData = 0;
+    // The values which harfbuzzSkiaClass returns are already scaled to
+    // pixel units, so we just set all these to one to disable further
+    // scaling.
+    font->x_ppem = 1;
+    font->y_ppem = 1;
+    font->x_scale = 1;
+    font->y_scale = 1;
 
     return font;
 }
@@ -815,7 +763,7 @@
     delete[] m_item.advances;
     delete[] m_item.offsets;
     delete[] m_glyphs16;
-    delete[] m_positions;
+    delete[] m_xPositions;
 }
 
 void TextRunWalker::createGlyphArrays(int size)
@@ -826,7 +774,7 @@
     m_item.offsets = new HB_FixedPoint[size];
 
     m_glyphs16 = new uint16_t[size];
-    m_positions = new SkPoint[size];
+    m_xPositions = new SkScalar[size];
 
     m_item.num_glyphs = size;
     m_glyphsArrayCapacity = size; // Save the GlyphArrays size.
@@ -842,7 +790,7 @@
     memset(m_item.advances, 0, size * sizeof(m_item.advances[0]));
     memset(m_item.offsets, 0, size * sizeof(m_item.offsets[0]));
     memset(m_glyphs16, 0, size * sizeof(m_glyphs16[0]));
-    memset(m_positions, 0, size * sizeof(m_positions[0]));
+    memset(m_xPositions, 0, size * sizeof(m_xPositions[0]));
 }
 
 void TextRunWalker::shapeGlyphs()
@@ -862,7 +810,7 @@
     }
 }
 
-void TextRunWalker::setGlyphPositions(bool isRTL)
+void TextRunWalker::setGlyphXPositions(bool isRTL)
 {
     int position = 0;
     // logClustersIndex indexes logClusters for the first (or last when
@@ -877,9 +825,7 @@
         int i = isRTL ? m_item.num_glyphs - iter - 1 : iter;
 
         m_glyphs16[i] = m_item.glyphs[i];
-        int offsetX = truncateFixedPointToInteger(m_item.offsets[i].x);
-        int offsetY = truncateFixedPointToInteger(m_item.offsets[i].y);
-        m_positions[i].set(SkIntToScalar(m_offsetX + position) + offsetX, m_startingY + offsetY);
+        m_xPositions[i] = SkIntToScalar(m_offsetX + position);
 
         int advance = truncateFixedPointToInteger(m_item.advances[i]);
         // The first half of the conjunction works around the case where
@@ -900,21 +846,6 @@
             }
         }
 
-        // ZeroWidthJoiners and ZeroWidthNonJoiners should be stripped by
-        // Harfbuzz, but aren't. Check for zwj and zwnj and replace with a
-        // zero width space. We get the glyph data for space instead of
-        // zeroWidthSpace because the latter was seen to render with an
-        // unexpected code point (the symbol for a cloud). Since the standard
-        // space is in page zero and since we've also confirmed that there is
-        // no advance on this glyph, that should be ok.
-        if (0 == m_item.advances[i]) {
-            const HB_UChar16 c = m_item.string[m_item.item.pos + logClustersIndex];
-            if ((c == zeroWidthJoiner) || (c == zeroWidthNonJoiner)) {
-                static Glyph spaceGlyph = m_font->glyphDataForCharacter(space, false).glyph;
-                m_glyphs16[i] = spaceGlyph;
-            }
-        }
-
         // TODO We would like to add m_letterSpacing after each cluster, but I
         // don't know where the cluster information is. This is typically
         // fine for Roman languages, but breaks more complex languages
@@ -947,14 +878,10 @@
         UChar32 character;
         int nextPosition = position;
         U16_NEXT(source, nextPosition, length, character);
-
         if (Font::treatAsSpace(character))
-            character = space;
-        else if (Font::treatAsZeroWidthSpaceInComplexScript(character))
-            character = zeroWidthSpace;
+            character = ' ';
         else if (rtl)
             character = u_charMirror(character);
-
         U16_APPEND(destination, position, length, character, error);
         ASSERT(!error);
         position = nextPosition;
@@ -1018,9 +945,9 @@
 FloatRect Font::selectionRectForComplexText(const TextRun& run,
     const FloatPoint& point, int height, int from, int to) const
 {
-    int fromX = -1;
-    int toX = -1;
-    TextRunWalker walker(run, 0, 0, this);
+
+    int fromX = -1, toX = -1, fromAdvance = -1, toAdvance = -1;
+    TextRunWalker walker(run, 0, this);
     walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing());
 
     // Base will point to the x offset for the current script run. Note that, in
@@ -1031,10 +958,6 @@
     // We want to enumerate the script runs in code point order in the following
     // code. This call also resets |walker|.
     walker.setBackwardsIteration(false);
-    if (!from)
-        fromX = leftEdge;
-    if (!to)
-        toX = leftEdge;
 
     while (walker.nextScriptRun() && (fromX == -1 || toX == -1)) {
         // TextRunWalker will helpfully accumulate the x offsets for different
@@ -1051,17 +974,15 @@
             // find which glyph this code-point contributed to and find its x
             // position.
             int glyph = walker.logClusters()[from];
-            fromX = base + walker.positions()[glyph].x();
-            if (walker.rtl())
-                fromX += truncateFixedPointToInteger(walker.advances()[glyph]);
+            fromX = base + walker.xPositions()[glyph];
+            fromAdvance = walker.advances()[glyph];
         } else
             from -= numCodePoints;
 
         if (toX == -1 && to < numCodePoints) {
             int glyph = walker.logClusters()[to];
-            toX = base + walker.positions()[glyph].x();
-            if (walker.rtl())
-                toX += truncateFixedPointToInteger(walker.advances()[glyph]);
+            toX = base + walker.xPositions()[glyph];
+            toAdvance = walker.advances()[glyph];
         } else
             to -= numCodePoints;
 
@@ -1072,7 +993,10 @@
     // The position in question might be just after the text.
     const int rightEdge = base;
     if (fromX == -1 && !from)
-        fromX = rightEdge;
+        fromX = leftEdge;
+    else if (walker.rtl())
+       fromX += truncateFixedPointToInteger(fromAdvance);
+
     if (toX == -1 && !to)
         toX = rightEdge;
 
@@ -1102,10 +1026,9 @@
     if (stroke)
         setupStroke(&strokePaint, gc, primaryFont());
 
-    SkCanvas* canvas = gc->platformContext()->recordingCanvas();
-
+    SkCanvas* canvas = gc->platformContext()->mCanvas;
     bool haveMultipleLayers = isCanvasMultiLayered(canvas);
-    TextRunWalker walker(run, point.x(), point.y(), this);
+    TextRunWalker walker(run, point.x(), this);
     walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing());
     walker.setPadding(run.expansion());
 
@@ -1113,24 +1036,22 @@
         if (fill) {
             walker.fontPlatformDataForScriptRun()->setupPaint(&fillPaint);
             adjustTextRenderMode(&fillPaint, haveMultipleLayers);
-            canvas->drawPosText(walker.glyphs(), walker.length() << 1,
-                                walker.positions(), fillPaint);
+            canvas->drawPosTextH(walker.glyphs(), walker.length() << 1,
+                                 walker.xPositions(), point.y(), fillPaint);
         }
         if (stroke) {
             walker.fontPlatformDataForScriptRun()->setupPaint(&strokePaint);
             adjustTextRenderMode(&strokePaint, haveMultipleLayers);
-            canvas->drawPosText(walker.glyphs(), walker.length() << 1,
-                                walker.positions(), strokePaint);
+            canvas->drawPosTextH(walker.glyphs(), walker.length() << 1,
+                                 walker.xPositions(), point.y(), strokePaint);
         }
     }
-
-    gc->platformContext()->endRecording();
 }
 
 float Font::floatWidthForComplexText(const TextRun& run,
             HashSet<const SimpleFontData*>*, GlyphOverflow*) const
 {
-    TextRunWalker walker(run, 0, 0, this);
+    TextRunWalker walker(run, 0, this);
     walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing());
     return walker.widthOfFullRun();
 }
@@ -1162,7 +1083,7 @@
 {
     // (Mac code ignores includePartialGlyphs, and they don't know what it's
     // supposed to do, so we just ignore it as well.)
-    TextRunWalker walker(run, 0, 0, this);
+    TextRunWalker walker(run, 0, this);
     walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing());
 
     // If this is RTL text, the first glyph from the left is actually the last
diff --git a/Source/WebCore/platform/graphics/android/fonts/FontCacheAndroid.cpp b/Source/WebCore/platform/graphics/android/FontCacheAndroid.cpp
similarity index 98%
rename from Source/WebCore/platform/graphics/android/fonts/FontCacheAndroid.cpp
rename to Source/WebCore/platform/graphics/android/FontCacheAndroid.cpp
index 4bb388c..4fc3b4e 100644
--- a/Source/WebCore/platform/graphics/android/fonts/FontCacheAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/FontCacheAndroid.cpp
@@ -34,6 +34,7 @@
 #include "SkPaint.h"
 #include "SkTypeface.h"
 #include "SkUtils.h"
+#include <wtf/text/CString.h>
 
 namespace WebCore {
 
@@ -175,7 +176,7 @@
         }
 
         result = new FontPlatformData(tf, fontDescription.computedSize(),
-                            (style & SkTypeface::kBold),
+                            (style & SkTypeface::kBold) && !tf->isBold(),
                             (style & SkTypeface::kItalic) && !tf->isItalic(),
                             fontDescription.orientation(),
                             fontDescription.textOrientation());
diff --git a/Source/WebCore/platform/graphics/android/fonts/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/android/FontCustomPlatformData.cpp
similarity index 100%
rename from Source/WebCore/platform/graphics/android/fonts/FontCustomPlatformData.cpp
rename to Source/WebCore/platform/graphics/android/FontCustomPlatformData.cpp
diff --git a/Source/WebCore/platform/graphics/android/fonts/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/android/FontCustomPlatformData.h
similarity index 100%
rename from Source/WebCore/platform/graphics/android/fonts/FontCustomPlatformData.h
rename to Source/WebCore/platform/graphics/android/FontCustomPlatformData.h
diff --git a/Source/WebCore/platform/graphics/android/fonts/FontDataAndroid.cpp b/Source/WebCore/platform/graphics/android/FontDataAndroid.cpp
similarity index 94%
rename from Source/WebCore/platform/graphics/android/fonts/FontDataAndroid.cpp
rename to Source/WebCore/platform/graphics/android/FontDataAndroid.cpp
index 88822df..c6dd174 100644
--- a/Source/WebCore/platform/graphics/android/fonts/FontDataAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/FontDataAndroid.cpp
@@ -56,12 +56,8 @@
     m_fontMetrics.setAscent(a);
     m_fontMetrics.setDescent(d);
     m_fontMetrics.setXHeight(SkScalarToFloat(-skiaFontMetrics.fAscent) * 0.56f);   // hack I stole from the window's port
-    float lineGap = SkScalarToFloat(skiaFontMetrics.fLeading);
-    if (platformData().orientation() == Vertical && lineGap == 0) {
-        lineGap = skiaFontMetrics.fAvgCharWidth * 0.56f;
-    }
-    m_fontMetrics.setLineGap(lineGap);
-    m_fontMetrics.setLineSpacing(a + d + lineGap);
+    m_fontMetrics.setLineSpacing(a + d);
+    m_fontMetrics.setLineGap(SkScalarToFloat(skiaFontMetrics.fLeading));
 
     if (platformData().orientation() == Vertical && !isTextOrientationFallback()) {
         static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a');
diff --git a/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h b/Source/WebCore/platform/graphics/android/FontPlatformData.h
similarity index 95%
rename from Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h
rename to Source/WebCore/platform/graphics/android/FontPlatformData.h
index 02a0cea..5c3313e 100644
--- a/Source/WebCore/platform/graphics/android/fonts/FontPlatformData.h
+++ b/Source/WebCore/platform/graphics/android/FontPlatformData.h
@@ -82,7 +82,6 @@
 
     float size() const { return mTextSize; }
     unsigned hash() const;
-    int emSizeInFontUnits() const;
     bool isFixedPitch() const;
 
 #ifndef NDEBUG
@@ -92,9 +91,6 @@
     HB_FaceRec_* harfbuzzFace() const;
     SkTypeface* typeface() const { return mTypeface; }
 
-    bool isFakeBold() const { return mFakeBold; }
-    bool isFakeItalic() const { return mFakeItalic; }
-
 private:
     class RefCountedHarfbuzzFace : public RefCounted<RefCountedHarfbuzzFace> {
     public:
@@ -117,7 +113,6 @@
 
     SkTypeface* mTypeface;
     float       mTextSize;
-    mutable int mEmSizeInFontUnits;
     bool        mFakeBold;
     bool        mFakeItalic;
     FontOrientation mOrientation;
diff --git a/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp b/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp
similarity index 81%
rename from Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp
rename to Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp
index fc254c0..3c90246 100644
--- a/Source/WebCore/platform/graphics/android/fonts/FontPlatformDataAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp
@@ -33,7 +33,6 @@
 #ifdef SUPPORT_COMPLEX_SCRIPTS
 #include "HarfbuzzSkia.h"
 #endif
-#include "SkAdvancedTypefaceMetrics.h"
 #include "SkPaint.h"
 #include "SkTypeface.h"
 
@@ -75,7 +74,7 @@
 }
 
 FontPlatformData::FontPlatformData()
-    : mTypeface(NULL), mTextSize(0), mEmSizeInFontUnits(0), mFakeBold(false), mFakeItalic(false),
+    : mTypeface(NULL), mTextSize(0), mFakeBold(false), mFakeItalic(false),
       mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight)
 {
     inc_count();
@@ -88,10 +87,10 @@
         SkSafeRef(src.mTypeface);
     }
 
-    mTypeface = src.mTypeface;
-    mTextSize = src.mTextSize;
-    mEmSizeInFontUnits = src.mEmSizeInFontUnits;
-    mFakeBold = src.mFakeBold;
+    mTypeface   = src.mTypeface;
+
+    mTextSize   = src.mTextSize;
+    mFakeBold   = src.mFakeBold;
     mFakeItalic = src.mFakeItalic;
     m_harfbuzzFace = src.m_harfbuzzFace;
     mOrientation = src.mOrientation;
@@ -103,7 +102,7 @@
 
 FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold, bool fakeItalic,
     FontOrientation orientation, TextOrientation textOrientation)
-    : mTypeface(tf), mTextSize(textSize), mEmSizeInFontUnits(0), mFakeBold(fakeBold), mFakeItalic(fakeItalic),
+    : mTypeface(tf), mTextSize(textSize), mFakeBold(fakeBold), mFakeItalic(fakeItalic),
       mOrientation(orientation), mTextOrientation(textOrientation)
 {
     if (hashTableDeletedFontValue() != mTypeface) {
@@ -115,8 +114,8 @@
 }
 
 FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize)
-    : mTypeface(src.mTypeface), mTextSize(textSize), mEmSizeInFontUnits(src.mEmSizeInFontUnits), mFakeBold(src.mFakeBold), mFakeItalic(src.mFakeItalic),
-      mOrientation(src.mOrientation), mTextOrientation(src.mTextOrientation), m_harfbuzzFace(src.m_harfbuzzFace)
+    : mTypeface(src.mTypeface), mTextSize(textSize), mFakeBold(src.mFakeBold), mFakeItalic(src.mFakeItalic),
+      m_harfbuzzFace(src.m_harfbuzzFace), mOrientation(src.mOrientation), mTextOrientation(src.mTextOrientation)
 {
     if (hashTableDeletedFontValue() != mTypeface) {
         SkSafeRef(mTypeface);
@@ -127,7 +126,7 @@
 }
 
 FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
-    : mTypeface(NULL), mTextSize(size),  mEmSizeInFontUnits(0), mFakeBold(bold), mFakeItalic(oblique),
+    : mTypeface(NULL), mTextSize(size), mFakeBold(bold), mFakeItalic(oblique),
       mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight)
 {
     inc_count();
@@ -135,7 +134,7 @@
 }
 
 FontPlatformData::FontPlatformData(const FontPlatformData& src, SkTypeface* tf)
-    : mTypeface(tf), mTextSize(src.mTextSize),  mEmSizeInFontUnits(0), mFakeBold(src.mFakeBold),
+    : mTypeface(tf), mTextSize(src.mTextSize), mFakeBold(src.mFakeBold),
       mFakeItalic(src.mFakeItalic), mOrientation(src.mOrientation),
       mTextOrientation(src.mTextOrientation)
 {
@@ -159,22 +158,6 @@
     }
 }
 
-int FontPlatformData::emSizeInFontUnits() const
-{
-    if (mEmSizeInFontUnits)
-        return mEmSizeInFontUnits;
-
-    SkAdvancedTypefaceMetrics* metrics = 0;
-    if (mTypeface)
-        metrics = mTypeface->getAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo);
-    if (metrics) {
-        mEmSizeInFontUnits = metrics->fEmSize;
-        metrics->unref();
-    } else
-        mEmSizeInFontUnits = 1000;  // default value copied from Skia.
-    return mEmSizeInFontUnits;
-}
-
 FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src)
 {
     if (hashTableDeletedFontValue() != src.mTypeface) {
@@ -184,10 +167,9 @@
         SkSafeUnref(mTypeface);
     }
 
-    mTypeface = src.mTypeface;
-    mEmSizeInFontUnits = src.mEmSizeInFontUnits;
-    mTextSize = src.mTextSize;
-    mFakeBold = src.mFakeBold;
+    mTypeface   = src.mTypeface;
+    mTextSize   = src.mTextSize;
+    mFakeBold   = src.mFakeBold;
     mFakeItalic = src.mFakeItalic;
     m_harfbuzzFace = src.m_harfbuzzFace;
     mOrientation = src.mOrientation;
@@ -198,6 +180,10 @@
 
 void FontPlatformData::setupPaint(SkPaint* paint) const
 {
+    float ts = mTextSize;
+    if (!(ts > 0))
+        ts = 12;
+
     if (hashTableDeletedFontValue() == mTypeface)
         paint->setTypeface(0);
     else
@@ -206,7 +192,7 @@
     paint->setAntiAlias(true);
     paint->setSubpixelText(true);
     paint->setHinting(SkPaint::kSlight_Hinting);
-    paint->setTextSize(SkFloatToScalar(mTextSize));
+    paint->setTextSize(SkFloatToScalar(ts));
     paint->setFakeBoldText(mFakeBold);
     paint->setTextSkewX(mFakeItalic ? -SK_Scalar1/4 : 0);
 #ifndef SUPPORT_COMPLEX_SCRIPTS
diff --git a/Source/WebCore/platform/graphics/android/GLExtras.cpp b/Source/WebCore/platform/graphics/android/GLExtras.cpp
new file mode 100644
index 0000000..873ea33
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/GLExtras.cpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "DrawExtra.h"
+#include "FindCanvas.h"
+#include "GLExtras.h"
+#include "IntRect.h"
+#include "TilesManager.h"
+#include "android_graphics.h"
+
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "GLExtras", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GLExtras", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+// Touch ring border width. This is doubled if the ring is not pressed
+#define RING_BORDER_WIDTH 1
+// Color of the ring is 0x6633b5e5 (copied from framework's holo_light)
+#define COLOR_HOLO_LIGHT &m_lightRingTexture, 0x33, 0xb5, 0xe5, 0.4f
+// Color of the ring is 0x660099cc (copied from framework's holo_dark)
+#define COLOR_HOLO_DARK &m_darkRingTexture, 0x00, 0x99, 0xcc, 0.6f
+// Put a cap on the number of matches to draw.  If the current page has more
+// matches than this, only draw the focused match. This both prevents clutter
+// on the page and keeps the performance happy
+#define MAX_NUMBER_OF_MATCHES_TO_DRAW 101
+
+GLExtras::GLExtras()
+    : m_findOnPage(0)
+    , m_ring(0)
+    , m_drawExtra(0)
+    , m_lightRingTexture(-1)
+    , m_darkRingTexture(-1)
+{
+}
+
+GLExtras::~GLExtras()
+{
+}
+
+void GLExtras::drawRing(SkRect& srcRect, int* texture, int r, int g, int b, float a)
+{
+    if (*texture == -1)
+        *texture = GLUtils::createSampleColorTexture(r, g, b);
+
+    if (srcRect.fRight <= srcRect.fLeft || srcRect.fBottom <= srcRect.fTop) {
+        // Invalid rect, reject it
+        return;
+    }
+    XLOG("drawQuad [%fx%f, %f, %f]", srcRect.fLeft, srcRect.fTop,
+         srcRect.width(), srcRect.height());
+    TilesManager::instance()->shader()->drawQuad(srcRect, *texture, a);
+}
+
+void GLExtras::drawRegion(const SkRegion& region, bool fill,
+                          bool drawBorder, bool useDark)
+{
+    if (region.isEmpty())
+        return;
+    if (fill) {
+        SkRegion::Iterator rgnIter(region);
+        while (!rgnIter.done()) {
+            const SkIRect& ir = rgnIter.rect();
+            SkRect r;
+            r.set(ir.fLeft, ir.fTop, ir.fRight, ir.fBottom);
+            if (useDark)
+                drawRing(r, COLOR_HOLO_DARK);
+            else
+                drawRing(r, COLOR_HOLO_LIGHT);
+            rgnIter.next();
+        }
+    }
+    if (fill && !drawBorder)
+        return;
+    SkPath path;
+    if (!region.getBoundaryPath(&path))
+        return;
+    SkPath::Iter iter(path, true);
+    SkPath::Verb verb;
+    SkPoint pts[4];
+    SkRegion clip;
+    SkIRect startRect;
+    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
+        if (verb == SkPath::kLine_Verb) {
+            SkRect r;
+            r.set(pts, 2);
+            SkIRect line;
+            int borderWidth = RING_BORDER_WIDTH;
+            if (!fill)
+                borderWidth *= 2;
+            line.fLeft = r.fLeft - borderWidth;
+            line.fRight = r.fRight + borderWidth;
+            line.fTop = r.fTop - borderWidth;
+            line.fBottom = r.fBottom + borderWidth;
+            if (clip.intersects(line)) {
+                clip.op(line, SkRegion::kReverseDifference_Op);
+                if (clip.isEmpty())
+                    continue; // Nothing to draw, continue
+                line = clip.getBounds();
+                if (SkIRect::Intersects(startRect, line)) {
+                    clip.op(startRect, SkRegion::kDifference_Op);
+                    if (clip.isEmpty())
+                        continue; // Nothing to draw, continue
+                    line = clip.getBounds();
+                }
+            } else {
+                clip.setRect(line);
+            }
+            r.set(line.fLeft, line.fTop, line.fRight, line.fBottom);
+            if (useDark)
+                drawRing(r, COLOR_HOLO_DARK);
+            else
+                drawRing(r, COLOR_HOLO_LIGHT);
+            if (startRect.isEmpty()) {
+                startRect.set(line.fLeft, line.fTop, line.fRight, line.fBottom);
+            }
+        }
+        if (verb == SkPath::kMove_Verb) {
+            startRect.setEmpty();
+        }
+    }
+}
+
+void GLExtras::drawCursorRings()
+{
+    SkRegion region;
+    for (size_t i = 0; i < m_ring->rings().size(); i++) {
+        IntRect rect = m_ring->rings().at(i);
+        if (i == 0)
+            region.setRect(rect);
+        else
+            region.op(rect, SkRegion::kUnion_Op);
+    }
+    drawRegion(region, m_ring->m_isPressed, !m_ring->m_isButton, false);
+}
+
+void GLExtras::drawFindOnPage(SkRect& viewport)
+{
+    WTF::Vector<MatchInfo>* matches = m_findOnPage->matches();
+    XLOG("drawFindOnPage, matches: %p", matches);
+    if (!matches || !m_findOnPage->isCurrentLocationValid())
+        return;
+    int count = matches->size();
+    int current = m_findOnPage->currentMatchIndex();
+    XLOG("match count: %d", count);
+    if (count < MAX_NUMBER_OF_MATCHES_TO_DRAW)
+        for (int i = 0; i < count; i++) {
+            MatchInfo& info = matches->at(i);
+            const SkRegion& region = info.getLocation();
+            SkIRect rect = region.getBounds();
+            if (rect.intersect(viewport.fLeft, viewport.fTop,
+                               viewport.fRight, viewport.fBottom))
+                drawRegion(region, i == current, false, true);
+#ifdef DEBUG
+            else
+                XLOG("Quick rejecting [%dx%d, %d, %d", rect.fLeft, rect.fTop,
+                     rect.width(), rect.height());
+#endif // DEBUG
+        }
+    else {
+        MatchInfo& info = matches->at(current);
+        drawRegion(info.getLocation(), true, false, true);
+    }
+}
+
+void GLExtras::drawGL(IntRect& webViewRect, SkRect& viewport, int titleBarHeight)
+{
+    if (m_drawExtra) {
+        if (m_drawExtra == m_ring)
+            drawCursorRings();
+        else if (m_drawExtra == m_findOnPage)
+            drawFindOnPage(viewport);
+        else
+            XLOGC("m_drawExtra %p is unknown! (cursor: %p, find: %p",
+                  m_drawExtra, m_ring, m_findOnPage);
+    }
+}
diff --git a/Source/WebCore/platform/graphics/android/rendering/GLExtras.h b/Source/WebCore/platform/graphics/android/GLExtras.h
similarity index 72%
rename from Source/WebCore/platform/graphics/android/rendering/GLExtras.h
rename to Source/WebCore/platform/graphics/android/GLExtras.h
index e9f697a..c52e951 100644
--- a/Source/WebCore/platform/graphics/android/rendering/GLExtras.h
+++ b/Source/WebCore/platform/graphics/android/GLExtras.h
@@ -26,36 +26,41 @@
 #ifndef GLExtras_h
 #define GLExtras_h
 
-#include "Color.h"
-#include "DrawExtra.h"
 #include "SkRect.h"
 #include "SkRegion.h"
 
-namespace WebCore {
+namespace android {
+    class FindOnPage;
+    class CursorRing;
+    class DrawExtra;
+}
 
-class LayerAndroid;
-class TransformationMatrix;
+namespace WebCore {
 
 class GLExtras {
 public:
     GLExtras();
     virtual ~GLExtras();
 
-    void drawGL(const LayerAndroid* layer);
-    void setDrawExtra(android::DrawExtra* extra) { m_drawExtra = extra; }
-    void setVisibleContentRect(const SkRect & visibleContentRect)
-    {
-        m_visibleContentRect = visibleContentRect;
+    void drawGL(IntRect& webViewRect, SkRect& viewport, int titleBarHeight);
+    void setFindOnPageExtra(android::FindOnPage* findOnPage) {
+        m_findOnPage = findOnPage;
     }
-
-    void drawRegion(const SkRegion& region, bool fill, bool drawBorder,
-                    const TransformationMatrix* drawMat, Color color = COLOR_HOLO_LIGHT);
+    void setCursorRingExtra(android::CursorRing* ring) { m_ring = ring; }
+    void setDrawExtra(android::DrawExtra* extra) { m_drawExtra = extra; }
 
 private:
-    void drawRing(SkRect& srcRect, Color color, const TransformationMatrix* drawMat);
+    void drawRing(SkRect& srcRect, int* texture, int r, int g, int b, float a);
+    void drawRegion(const SkRegion& region, bool fill, bool drawBorder,
+                    bool useDark = false);
+    void drawCursorRings();
+    void drawFindOnPage(SkRect& viewport);
 
+    android::FindOnPage* m_findOnPage;
+    android::CursorRing* m_ring;
     android::DrawExtra* m_drawExtra;
-    SkRect m_visibleContentRect;
+    int m_lightRingTexture;
+    int m_darkRingTexture;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/GLUtils.cpp b/Source/WebCore/platform/graphics/android/GLUtils.cpp
new file mode 100644
index 0000000..97a53fe
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/GLUtils.cpp
@@ -0,0 +1,576 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "GLUtils.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "ShaderProgram.h"
+#include "TilesManager.h"
+
+#include <cutils/log.h>
+#include <gui/SurfaceTexture.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+
+
+#ifdef DEBUG
+
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GLUtils", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+struct ANativeWindowBuffer;
+
+namespace WebCore {
+
+using namespace android;
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Matrix utilities
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void GLUtils::toGLMatrix(GLfloat* flattened, const TransformationMatrix& m)
+{
+    flattened[0] = m.m11(); // scaleX
+    flattened[1] = m.m12(); // skewY
+    flattened[2] = m.m13();
+    flattened[3] = m.m14(); // persp0
+    flattened[4] = m.m21(); // skewX
+    flattened[5] = m.m22(); // scaleY
+    flattened[6] = m.m23();
+    flattened[7] = m.m24(); // persp1
+    flattened[8] = m.m31();
+    flattened[9] = m.m32();
+    flattened[10] = m.m33();
+    flattened[11] = m.m34();
+    flattened[12] = m.m41(); // transX
+    flattened[13] = m.m42(); // transY
+    flattened[14] = m.m43();
+    flattened[15] = m.m44(); // persp2
+}
+
+void GLUtils::toSkMatrix(SkMatrix& matrix, const TransformationMatrix& m)
+{
+    matrix[0] = m.m11(); // scaleX
+    matrix[1] = m.m21(); // skewX
+    matrix[2] = m.m41(); // transX
+    matrix[3] = m.m12(); // skewY
+    matrix[4] = m.m22(); // scaleY
+    matrix[5] = m.m42(); // transY
+    matrix[6] = m.m14(); // persp0
+    matrix[7] = m.m24(); // persp1
+    matrix[8] = m.m44(); // persp2
+}
+
+void GLUtils::setOrthographicMatrix(TransformationMatrix& ortho, float left, float top,
+                                    float right, float bottom, float nearZ, float farZ)
+{
+    float deltaX = right - left;
+    float deltaY = top - bottom;
+    float deltaZ = farZ - nearZ;
+    if (!deltaX || !deltaY || !deltaZ)
+        return;
+
+    ortho.setM11(2.0f / deltaX);
+    ortho.setM41(-(right + left) / deltaX);
+    ortho.setM22(2.0f / deltaY);
+    ortho.setM42(-(top + bottom) / deltaY);
+    ortho.setM33(-2.0f / deltaZ);
+    ortho.setM43(-(nearZ + farZ) / deltaZ);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// GL & EGL error checks
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static void crashIfOOM(GLint errorCode) {
+    const GLint OOM_ERROR_CODE = 0x505;
+    if (errorCode == OOM_ERROR_CODE) {
+        XLOG("Fatal OOM detected.");
+        CRASH();
+    }
+}
+
+void GLUtils::checkEglError(const char* op, EGLBoolean returnVal)
+{
+    if (returnVal != EGL_TRUE) {
+        XLOG("EGL ERROR - %s() returned %d\n", op, returnVal);
+    }
+
+    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error = eglGetError()) {
+        XLOG("after %s() eglError (0x%x)\n", op, error);
+        crashIfOOM(error);
+    }
+}
+
+bool GLUtils::checkGlError(const char* op)
+{
+    bool ret = false;
+    for (GLint error = glGetError(); error; error = glGetError()) {
+        XLOG("GL ERROR - after %s() glError (0x%x)\n", op, error);
+        crashIfOOM(error);
+        ret = true;
+    }
+    return ret;
+}
+
+bool GLUtils::checkGlErrorOn(void* p, const char* op)
+{
+    bool ret = false;
+    for (GLint error = glGetError(); error; error = glGetError()) {
+        XLOG("GL ERROR on %x - after %s() glError (0x%x)\n", p, op, error);
+        crashIfOOM(error);
+        ret = true;
+    }
+    return ret;
+}
+
+void GLUtils::checkSurfaceTextureError(const char* functionName, int status)
+{
+    if (status !=  NO_ERROR) {
+        XLOG("ERROR at calling %s status is (%d)", functionName, status);
+    }
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+// GL & EGL extension checks
+/////////////////////////////////////////////////////////////////////////////////////////
+
+bool GLUtils::isEGLImageSupported()
+{
+    const char* eglExtensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS);
+    const char* glExtensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
+
+    return eglExtensions && glExtensions
+        && strstr(eglExtensions, "EGL_KHR_image_base")
+        && strstr(eglExtensions, "EGL_KHR_gl_texture_2D_image")
+        && strstr(glExtensions, "GL_OES_EGL_image");
+}
+
+bool GLUtils::isEGLFenceSyncSupported()
+{
+    const char* eglExtensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS);
+    return eglExtensions && strstr(eglExtensions, "EGL_KHR_fence_sync");
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Textures utilities
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static GLenum getInternalFormat(SkBitmap::Config config)
+{
+    switch (config) {
+    case SkBitmap::kA8_Config:
+        return GL_ALPHA;
+    case SkBitmap::kARGB_4444_Config:
+        return GL_RGBA;
+    case SkBitmap::kARGB_8888_Config:
+        return GL_RGBA;
+    case SkBitmap::kRGB_565_Config:
+        return GL_RGB;
+    default:
+        return -1;
+    }
+}
+
+static GLenum getType(SkBitmap::Config config)
+{
+    switch (config) {
+    case SkBitmap::kA8_Config:
+        return GL_UNSIGNED_BYTE;
+    case SkBitmap::kARGB_4444_Config:
+        return GL_UNSIGNED_SHORT_4_4_4_4;
+    case SkBitmap::kARGB_8888_Config:
+        return GL_UNSIGNED_BYTE;
+    case SkBitmap::kIndex8_Config:
+        return -1; // No type for compressed data.
+    case SkBitmap::kRGB_565_Config:
+        return GL_UNSIGNED_SHORT_5_6_5;
+    default:
+        return -1;
+    }
+}
+
+static EGLConfig defaultPbufferConfig(EGLDisplay display)
+{
+    EGLConfig config;
+    EGLint numConfigs;
+
+    static const EGLint configAttribs[] = {
+        EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+        EGL_NONE
+    };
+
+    eglChooseConfig(display, configAttribs, &config, 1, &numConfigs);
+    GLUtils::checkEglError("eglPbufferConfig");
+    if (numConfigs != 1)
+        LOGI("eglPbufferConfig failed (%d)\n", numConfigs);
+
+    return config;
+}
+
+static EGLSurface createPbufferSurface(EGLDisplay display, const EGLConfig& config,
+                                       EGLint* errorCode)
+{
+    const EGLint attribList[] = {
+        EGL_WIDTH, 1,
+        EGL_HEIGHT, 1,
+        EGL_NONE
+    };
+    EGLSurface surface = eglCreatePbufferSurface(display, config, attribList);
+
+    if (errorCode)
+        *errorCode = eglGetError();
+    else
+        GLUtils::checkEglError("eglCreatePbufferSurface");
+
+    if (surface == EGL_NO_SURFACE)
+        return EGL_NO_SURFACE;
+
+    return surface;
+}
+
+EGLContext GLUtils::createBackgroundContext(EGLContext sharedContext)
+{
+    checkEglError("<init>");
+    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    checkEglError("eglGetDisplay");
+    if (display == EGL_NO_DISPLAY) {
+        XLOG("eglGetDisplay returned EGL_NO_DISPLAY");
+        return EGL_NO_CONTEXT;
+    }
+
+    EGLint majorVersion;
+    EGLint minorVersion;
+    EGLBoolean returnValue = eglInitialize(display, &majorVersion, &minorVersion);
+    checkEglError("eglInitialize", returnValue);
+    if (returnValue != EGL_TRUE) {
+        XLOG("eglInitialize failed\n");
+        return EGL_NO_CONTEXT;
+    }
+
+    EGLConfig config = defaultPbufferConfig(display);
+    EGLSurface surface = createPbufferSurface(display, config, 0);
+
+    EGLint surfaceConfigId;
+    EGLBoolean success = eglGetConfigAttrib(display, config, EGL_CONFIG_ID, &surfaceConfigId);
+
+    EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+    EGLContext context = eglCreateContext(display, config, sharedContext, contextAttribs);
+    checkEglError("eglCreateContext");
+    if (context == EGL_NO_CONTEXT) {
+        XLOG("eglCreateContext failed\n");
+        return EGL_NO_CONTEXT;
+    }
+
+    returnValue = eglMakeCurrent(display, surface, surface, context);
+    checkEglError("eglMakeCurrent", returnValue);
+    if (returnValue != EGL_TRUE) {
+        XLOG("eglMakeCurrent failed\n");
+        return EGL_NO_CONTEXT;
+    }
+
+    return context;
+}
+
+void GLUtils::deleteTexture(GLuint* texture)
+{
+    glDeleteTextures(1, texture);
+    GLUtils::checkGlError("glDeleteTexture");
+    *texture = 0;
+}
+
+GLuint GLUtils::createSampleColorTexture(int r, int g, int b) {
+    GLuint texture;
+    glGenTextures(1, &texture);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    GLubyte pixels[4 *3] = {
+        r, g, b,
+        r, g, b,
+        r, g, b,
+        r, g, b
+    };
+    glBindTexture(GL_TEXTURE_2D, texture);
+    GLUtils::checkGlError("glBindTexture");
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
+    GLUtils::checkGlError("glTexImage2D");
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    return texture;
+}
+
+GLuint GLUtils::createSampleTexture()
+{
+    GLuint texture;
+    glGenTextures(1, &texture);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    GLubyte pixels[4 *3] = {
+        255, 0, 0,
+        0, 255, 0,
+        0, 0, 255,
+        255, 255, 0
+    };
+    glBindTexture(GL_TEXTURE_2D, texture);
+    GLUtils::checkGlError("glBindTexture");
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
+    GLUtils::checkGlError("glTexImage2D");
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    return texture;
+}
+
+GLuint GLUtils::createBaseTileGLTexture(int width, int height)
+{
+    GLuint texture;
+    glGenTextures(1, &texture);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    GLubyte* pixels = 0;
+#ifdef DEBUG
+    int length = width * height * 4;
+    pixels = new GLubyte[length];
+    for (int i = 0; i < length; i++)
+        pixels[i] = i % 256;
+#endif
+    glBindTexture(GL_TEXTURE_2D, texture);
+    GLUtils::checkGlError("glBindTexture");
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+    GLUtils::checkGlError("glTexImage2D");
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    return texture;
+}
+
+void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo,
+                                     const SkBitmap& bitmap)
+{
+    if (!renderInfo)
+        return;
+    const int x = renderInfo->invalRect->fLeft;
+    const int y = renderInfo->invalRect->fTop;
+    const SkSize& requiredSize = renderInfo->tileSize;
+    TextureInfo* textureInfo = renderInfo->textureInfo;
+    SharedTextureMode mode = textureInfo->getSharedTextureMode();
+    if (requiredSize.equals(textureInfo->m_width, textureInfo->m_height)) {
+        if (mode == EglImageMode)
+            GLUtils::updateTextureWithBitmap(textureInfo->m_textureId, x, y, bitmap);
+        else if (mode == SurfaceTextureMode)
+#if DEPRECATED_SURFACE_TEXTURE_MODE
+            GLUtils::updateSurfaceTextureWithBitmap(renderInfo, x, y, bitmap);
+#else
+            GLUtils::updateSharedSurfaceTextureWithBitmap(renderInfo, x, y, bitmap);
+#endif
+    } else {
+
+        if (!requiredSize.equals(bitmap.width(), bitmap.height())) {
+            XLOG("The bitmap size (%d,%d) does not equal the texture size (%d,%d)",
+                    bitmap.width(), bitmap.height(),
+                    requiredSize.width(), requiredSize.height());
+        }
+
+        if (mode == EglImageMode)
+            GLUtils::createTextureWithBitmap(textureInfo->m_textureId, bitmap);
+        else if (mode == SurfaceTextureMode)
+#if DEPRECATED_SURFACE_TEXTURE_MODE
+            GLUtils::createSurfaceTextureWithBitmap(renderInfo, bitmap);
+#else
+            GLUtils::updateSharedSurfaceTextureWithBitmap(renderInfo, 0, 0, bitmap);
+#endif
+        textureInfo->m_width = bitmap.width();
+        textureInfo->m_height = bitmap.height();
+        textureInfo->m_internalFormat = GL_RGBA;
+    }
+}
+
+#if DEPRECATED_SURFACE_TEXTURE_MODE
+void GLUtils::createSurfaceTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap, GLint filter)
+{
+
+    TextureInfo* texture = renderInfo->textureInfo;
+
+    texture->m_width = bitmap.width();
+    texture->m_height = bitmap.height();
+    texture->m_internalFormat = GL_RGBA;
+
+    sp<android::SurfaceTexture> surfaceTexture = texture->m_surfaceTexture;
+    sp<ANativeWindow> ANW = texture->m_ANW;
+
+    int result;
+    result = native_window_set_buffers_geometry(ANW.get(),
+            texture->m_width, texture->m_height, HAL_PIXEL_FORMAT_RGBA_8888);
+    checkSurfaceTextureError("native_window_set_buffers_geometry", result);
+    result = native_window_set_usage(ANW.get(),
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+    checkSurfaceTextureError("native_window_set_usage", result);
+
+    updateSurfaceTextureWithBitmap(renderInfo, 0, 0, bitmap, filter);
+}
+
+void GLUtils::updateSurfaceTextureWithBitmap(const TileRenderInfo* renderInfo, int x, int y, const SkBitmap& bitmap, GLint filter)
+{
+    TextureInfo* texture = renderInfo->textureInfo;
+    sp<android::SurfaceTexture> surfaceTexture = texture->m_surfaceTexture;
+    sp<ANativeWindow> ANW = texture->m_ANW;
+
+    ANativeWindowBuffer* anb;
+    int status = ANW->dequeueBuffer(ANW.get(), &anb);
+    checkSurfaceTextureError("dequeueBuffer", status);
+
+    if (status != NO_ERROR) { // FIXME: add proper error handling!
+        native_window_set_buffer_count(ANW.get(), 3);
+        return;
+    }
+
+    sp<android::GraphicBuffer> buf(new android::GraphicBuffer(anb, false));
+    status |= ANW->lockBuffer(ANW.get(), buf->getNativeBuffer());
+    checkSurfaceTextureError("lockBuffer", status);
+
+    // Fill the buffer with the content of the bitmap
+    uint8_t* img = 0;
+    status |= buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+    checkSurfaceTextureError("lock", status);
+
+    if (status == NO_ERROR) {
+        int row, col;
+        int bpp = 4; // Now only deal with RGBA8888 format.
+
+        bitmap.lockPixels();
+        uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels());
+        // Copied line by line since we need to handle the offsets and stride.
+        for (row = 0 ; row < bitmap.height(); row ++) {
+            uint8_t* dst = &(img[(buf->getStride() * (row + x) + y) * bpp]);
+            uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]);
+            memcpy(dst, src, bpp * bitmap.width());
+        }
+        bitmap.unlockPixels();
+    }
+    buf->unlock();
+    status = ANW->queueBuffer(ANW.get(), buf->getNativeBuffer());
+    checkSurfaceTextureError("queueBuffer", status);
+}
+#endif
+
+void GLUtils::updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* renderInfo, int x, int y, const SkBitmap& bitmap)
+{
+    if (!renderInfo
+        || !renderInfo->textureInfo
+        || !renderInfo->baseTile)
+        return;
+
+    TilesManager::instance()->transferQueue()->updateQueueWithBitmap(renderInfo, x, y, bitmap);
+}
+
+void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter)
+{
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    GLUtils::checkGlError("glBindTexture");
+    SkBitmap::Config config = bitmap.getConfig();
+    int internalformat = getInternalFormat(config);
+    int type = getType(config);
+    bitmap.lockPixels();
+    glTexImage2D(GL_TEXTURE_2D, 0, internalformat, bitmap.width(), bitmap.height(),
+                 0, internalformat, type, bitmap.getPixels());
+    bitmap.unlockPixels();
+    if (GLUtils::checkGlError("glTexImage2D")) {
+        XLOG("GL ERROR: glTexImage2D parameters are : bitmap.width() %d, bitmap.height() %d,"
+             " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p",
+             bitmap.width(), bitmap.height(), internalformat, type, bitmap.getPixels());
+    }
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
+
+    // The following is a workaround -- remove when EGLImage texture upload is fixed.
+    GLuint fboID;
+    glGenFramebuffers(1, &fboID);
+    glBindFramebuffer(GL_FRAMEBUFFER, fboID);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+    glCheckFramebufferStatus(GL_FRAMEBUFFER); // should return GL_FRAMEBUFFER_COMPLETE
+
+    glBindFramebuffer(GL_FRAMEBUFFER, 0); // rebind the standard FBO
+    glDeleteFramebuffers(1, &fboID);
+}
+
+void GLUtils::updateTextureWithBitmap(GLuint texture, int x, int y, const SkBitmap& bitmap, GLint filter)
+{
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    glBindTexture(GL_TEXTURE_2D, texture);
+    GLUtils::checkGlError("glBindTexture");
+    SkBitmap::Config config = bitmap.getConfig();
+    int internalformat = getInternalFormat(config);
+    int type = getType(config);
+    bitmap.lockPixels();
+    glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, bitmap.width(), bitmap.height(),
+                    internalformat, type, bitmap.getPixels());
+    bitmap.unlockPixels();
+    if (GLUtils::checkGlError("glTexSubImage2D")) {
+        XLOG("GL ERROR: glTexSubImage2D parameters are : bitmap.width() %d, bitmap.height() %d,"
+             " x %d, y %d, internalformat 0x%x, type 0x%x, bitmap.getPixels() %p",
+             bitmap.width(), bitmap.height(), x, y, internalformat, type, bitmap.getPixels());
+    }
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
+}
+
+void GLUtils::createEGLImageFromTexture(GLuint texture, EGLImageKHR* image)
+{
+    EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(texture);
+    static const EGLint attr[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
+    *image = eglCreateImageKHR(eglGetCurrentDisplay(), eglGetCurrentContext(),
+                               EGL_GL_TEXTURE_2D_KHR, buffer, attr);
+    GLUtils::checkEglError("eglCreateImage", (*image != EGL_NO_IMAGE_KHR));
+}
+
+void GLUtils::createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter)
+{
+    glBindTexture(GL_TEXTURE_2D, texture);
+    GLUtils::checkGlError("glBindTexture");
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
+}
+
+void GLUtils::convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix)
+{
+    transformMatrix.setMatrix(
+        matrix[0], matrix[1], matrix[2], matrix[3],
+        matrix[4], matrix[5], matrix[6], matrix[7],
+        matrix[8], matrix[9], matrix[10], matrix[11],
+        matrix[12], matrix[13], matrix[14], matrix[15]);
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/rendering/GLUtils.h b/Source/WebCore/platform/graphics/android/GLUtils.h
similarity index 74%
rename from Source/WebCore/platform/graphics/android/rendering/GLUtils.h
rename to Source/WebCore/platform/graphics/android/GLUtils.h
index c2dec7d..68acbab 100644
--- a/Source/WebCore/platform/graphics/android/rendering/GLUtils.h
+++ b/Source/WebCore/platform/graphics/android/GLUtils.h
@@ -28,10 +28,10 @@
 
 #if USE(ACCELERATED_COMPOSITING)
 
-#include "Color.h"
-#include "IntRect.h"
 #include "SkBitmap.h"
 #include "SkMatrix.h"
+#include "SkSize.h"
+#include "TextureInfo.h"
 #include "TransformationMatrix.h"
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
@@ -46,8 +46,6 @@
 
 namespace WebCore {
 
-class TileRenderInfo;
-
 class GLUtils {
 
 public:
@@ -56,7 +54,6 @@
     static void toSkMatrix(SkMatrix& skmatrix, const TransformationMatrix& matrix);
     static void setOrthographicMatrix(TransformationMatrix& ortho, float left, float top,
                                       float right, float bottom, float nearZ, float farZ);
-    static bool has3dTransform(const TransformationMatrix& matrix);
 
     // GL & EGL error checks
     static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE);
@@ -69,31 +66,24 @@
     static bool isEGLFenceSyncSupported();
 
     // Texture utilities
+    static EGLContext createBackgroundContext(EGLContext sharedContext);
     static void deleteTexture(GLuint* texture);
     static GLuint createSampleColorTexture(int r, int g, int b);
     static GLuint createSampleTexture();
-    static GLuint createTileGLTexture(int width, int height);
+    static GLuint createBaseTileGLTexture(int width, int height);
 
     static void createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter = GL_LINEAR);
-    static void updateTextureWithBitmap(GLuint texture, const SkBitmap& bitmap,
-                                        const IntRect& inval = IntRect(), GLint filter = GL_LINEAR);
+    static void updateTextureWithBitmap(GLuint texture, int x, int y, const SkBitmap& bitmap, GLint filter = GL_LINEAR);
     static void createEGLImageFromTexture(GLuint texture, EGLImageKHR* image);
     static void createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter = GL_LINEAR);
 
     static void paintTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap);
-    static void updateQueueWithBitmap(const TileRenderInfo* , const SkBitmap& bitmap);
-    static bool updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkBitmap& bitmap);
+#if DEPRECATED_SURFACE_TEXTURE_MODE
+    static void createSurfaceTextureWithBitmap(const TileRenderInfo* , const SkBitmap& bitmap, GLint filter  = GL_LINEAR);
+    static void updateSurfaceTextureWithBitmap(const TileRenderInfo* , int x, int y, const SkBitmap& bitmap, GLint filter  = GL_LINEAR);
+#endif
+    static void updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* , int x, int y, const SkBitmap& bitmap);
     static void convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix);
-
-    static bool deepCopyBitmapSubset(const SkBitmap& sourceBitmap,
-                                     SkBitmap& subset, int left, int top);
-    static bool isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor);
-    static bool skipTransferForPureColor(const TileRenderInfo* renderInfo,
-                                         const SkBitmap& bitmap);
-    static void clearBackgroundIfOpaque(const Color* backgroundColor);
-    static bool allowGLLog();
-    static double m_previousLogTime;
-    static int m_currentLogCounter;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
index 55c4eec..3bcda9a 100644
--- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
+++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
@@ -23,57 +23,78 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#define LOG_TAG "GLWebViewState"
-#define LOG_NDEBUG 1
-
 #include "config.h"
 #include "GLWebViewState.h"
 
 #if USE(ACCELERATED_COMPOSITING)
 
-#include "AndroidLog.h"
 #include "BaseLayerAndroid.h"
 #include "ClassTracker.h"
 #include "GLUtils.h"
 #include "ImagesManager.h"
 #include "LayerAndroid.h"
-#include "private/hwui/DrawGlInfo.h"
 #include "ScrollableLayerAndroid.h"
 #include "SkPath.h"
 #include "TilesManager.h"
-#include "TransferQueue.h"
-#include "SurfaceCollection.h"
-#include "SurfaceCollectionManager.h"
-#include <pthread.h>
+#include "TilesTracker.h"
+#include "TreeManager.h"
 #include <wtf/CurrentTime.h>
 
+#include <pthread.h>
+
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "GLWebViewState", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GLWebViewState", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+#define FIRST_TILED_PAGE_ID 1
+#define SECOND_TILED_PAGE_ID 2
+
+#define FRAMERATE_CAP 0.01666 // We cap at 60 fps
+
 // log warnings if scale goes outside this range
 #define MIN_SCALE_WARNING 0.1
 #define MAX_SCALE_WARNING 10
 
-// fps indicator is FPS_INDICATOR_HEIGHT pixels high.
-// The max width is equal to MAX_FPS_VALUE fps.
-#define FPS_INDICATOR_HEIGHT 10
-#define MAX_FPS_VALUE 60
-
-#define COLLECTION_SWAPPED_COUNTER_MODULE 10
-
 namespace WebCore {
 
-using namespace android::uirenderer;
+using namespace android;
 
 GLWebViewState::GLWebViewState()
-    : m_frameworkLayersInval(0, 0, 0, 0)
-    , m_doFrameworkFullInval(false)
+    : m_zoomManager(this)
+    , m_currentPictureCounter(0)
+    , m_usePageA(true)
+    , m_frameworkInval(0, 0, 0, 0)
+    , m_frameworkLayersInval(0, 0, 0, 0)
     , m_isScrolling(false)
-    , m_isVisibleContentRectScrolling(false)
     , m_goingDown(true)
     , m_goingLeft(false)
+    , m_expandedTileBoundsX(0)
+    , m_expandedTileBoundsY(0)
+    , m_highEndGfx(false)
     , m_scale(1)
     , m_layersRenderingMode(kAllTextures)
-    , m_surfaceCollectionManager()
 {
-    m_visibleContentRect.setEmpty();
+    m_viewport.setEmpty();
+    m_futureViewportTileBounds.setEmpty();
+    m_viewportTileBounds.setEmpty();
+    m_preZoomBounds.setEmpty();
+
+    m_tiledPageA = new TiledPage(FIRST_TILED_PAGE_ID, this);
+    m_tiledPageB = new TiledPage(SECOND_TILED_PAGE_ID, this);
 
 #ifdef DEBUG_COUNT
     ClassTracker::instance()->increment("GLWebViewState");
@@ -87,26 +108,39 @@
 
 GLWebViewState::~GLWebViewState()
 {
+    // Take care of the transfer queue such that Tex Gen thread will not stuck
+    TilesManager::instance()->unregisterGLWebViewState(this);
+
+    // We have to destroy the two tiled pages first as their destructor
+    // may depend on the existence of this GLWebViewState and some of its
+    // instance variables in order to complete.
+    // Explicitely, currently we need to have the m_paintingBaseLayer around
+    // in order to complete any pending paint operations (the tiled pages
+    // will remove any pending operations, and wait if one is underway).
+    delete m_tiledPageA;
+    delete m_tiledPageB;
 #ifdef DEBUG_COUNT
     ClassTracker::instance()->decrement("GLWebViewState");
 #endif
 
 }
 
-bool GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, bool showVisualIndicator,
-                                  bool isPictureAfterFirstLayout)
+void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval,
+                                  bool showVisualIndicator, bool isPictureAfterFirstLayout)
 {
-    if (!layer || isPictureAfterFirstLayout)
+    if (!layer || isPictureAfterFirstLayout) {
+        // TODO: move this into TreeManager
+        m_zoomManager.swapPages(); // reset zoom state
+        m_tiledPageA->discardTextures();
+        m_tiledPageB->discardTextures();
         m_layersRenderingMode = kAllTextures;
-
-    SurfaceCollection* collection = 0;
-    if (layer) {
-        ALOGV("layer tree %p, with child %p", layer, layer->getChild(0));
-        layer->setState(this);
-        collection = new SurfaceCollection(layer);
     }
-    bool queueFull = m_surfaceCollectionManager.updateWithSurfaceCollection(
-        collection, isPictureAfterFirstLayout);
+    if (layer) {
+        XLOG("new base layer %p, (inval region empty %d) with child %p", layer, inval.isEmpty(), layer->getChild(0));
+        layer->setState(this);
+        layer->markAsDirty(inval); // TODO: set in webview.cpp
+    }
+    m_treeManager.updateWithTree(layer, isPictureAfterFirstLayout);
     m_glExtras.setDrawExtra(0);
 
 #ifdef MEASURES_PERF
@@ -116,58 +150,135 @@
 #endif
 
     TilesManager::instance()->setShowVisualIndicator(showVisualIndicator);
-    return queueFull;
 }
 
 void GLWebViewState::scrollLayer(int layerId, int x, int y)
 {
-    m_surfaceCollectionManager.updateScrollableLayer(layerId, x, y);
+    m_treeManager.updateScrollableLayer(layerId, x, y);
+
+    // TODO: only inval the area of the scrolled layer instead of
+    // doing a fullInval()
+    if (m_layersRenderingMode == kSingleSurfaceRendering)
+        fullInval();
 }
 
-void GLWebViewState::setVisibleContentRect(const SkRect& visibleContentRect, float scale)
+void GLWebViewState::invalRegion(const SkRegion& region)
 {
-    // allocate max possible number of tiles visible with this visibleContentRect / expandedTileBounds
+    if (m_layersRenderingMode == kSingleSurfaceRendering) {
+        // TODO: do the union of both layers tree to compute
+        //the minimum inval instead of doing a fullInval()
+        fullInval();
+        return;
+    }
+    SkRegion::Iterator iterator(region);
+    while (!iterator.done()) {
+        SkIRect r = iterator.rect();
+        IntRect ir(r.fLeft, r.fTop, r.width(), r.height());
+        inval(ir);
+        iterator.next();
+    }
+}
+
+void GLWebViewState::inval(const IntRect& rect)
+{
+    m_currentPictureCounter++;
+    if (!rect.isEmpty()) {
+        // find which tiles fall within the invalRect and mark them as dirty
+        m_tiledPageA->invalidateRect(rect, m_currentPictureCounter);
+        m_tiledPageB->invalidateRect(rect, m_currentPictureCounter);
+        if (m_frameworkInval.isEmpty())
+            m_frameworkInval = rect;
+        else
+            m_frameworkInval.unite(rect);
+        XLOG("intermediate invalRect(%d, %d, %d, %d) after unite with rect %d %d %d %d", m_frameworkInval.x(),
+             m_frameworkInval.y(), m_frameworkInval.width(), m_frameworkInval.height(),
+             rect.x(), rect.y(), rect.width(), rect.height());
+    }
+    TilesManager::instance()->getProfiler()->nextInval(rect, zoomManager()->currentScale());
+}
+
+unsigned int GLWebViewState::paintBaseLayerContent(SkCanvas* canvas)
+{
+    m_treeManager.drawCanvas(canvas, m_layersRenderingMode == kSingleSurfaceRendering);
+    return m_currentPictureCounter;
+}
+
+TiledPage* GLWebViewState::sibling(TiledPage* page)
+{
+    return (page == m_tiledPageA) ? m_tiledPageB : m_tiledPageA;
+}
+
+TiledPage* GLWebViewState::frontPage()
+{
+    android::Mutex::Autolock lock(m_tiledPageLock);
+    return m_usePageA ? m_tiledPageA : m_tiledPageB;
+}
+
+TiledPage* GLWebViewState::backPage()
+{
+    android::Mutex::Autolock lock(m_tiledPageLock);
+    return m_usePageA ? m_tiledPageB : m_tiledPageA;
+}
+
+void GLWebViewState::swapPages()
+{
+    android::Mutex::Autolock lock(m_tiledPageLock);
+    m_usePageA ^= true;
+    TiledPage* oldPage = m_usePageA ? m_tiledPageB : m_tiledPageA;
+    zoomManager()->swapPages();
+    oldPage->discardTextures();
+}
+
+int GLWebViewState::baseContentWidth()
+{
+    return m_treeManager.baseContentWidth();
+}
+int GLWebViewState::baseContentHeight()
+{
+    return m_treeManager.baseContentHeight();
+}
+
+void GLWebViewState::setViewport(SkRect& viewport, float scale)
+{
+    if ((m_viewport == viewport) &&
+        (zoomManager()->futureScale() == scale))
+        return;
+
+    m_goingDown = m_viewport.fTop - viewport.fTop <= 0;
+    m_goingLeft = m_viewport.fLeft - viewport.fLeft >= 0;
+    m_viewport = viewport;
+
+    XLOG("New VIEWPORT %.2f - %.2f %.2f - %.2f (w: %2.f h: %.2f scale: %.2f currentScale: %.2f futureScale: %.2f)",
+         m_viewport.fLeft, m_viewport.fTop, m_viewport.fRight, m_viewport.fBottom,
+         m_viewport.width(), m_viewport.height(), scale,
+         zoomManager()->currentScale(), zoomManager()->futureScale());
+
     const float invTileContentWidth = scale / TilesManager::tileWidth();
     const float invTileContentHeight = scale / TilesManager::tileHeight();
 
-    int viewMaxTileX =
-        static_cast<int>(ceilf((visibleContentRect.width()-1) * invTileContentWidth)) + 1;
-    int viewMaxTileY =
-        static_cast<int>(ceilf((visibleContentRect.height()-1) * invTileContentHeight)) + 1;
+    m_viewportTileBounds.set(
+            static_cast<int>(floorf(viewport.fLeft * invTileContentWidth)),
+            static_cast<int>(floorf(viewport.fTop * invTileContentHeight)),
+            static_cast<int>(ceilf(viewport.fRight * invTileContentWidth)),
+            static_cast<int>(ceilf(viewport.fBottom * invTileContentHeight)));
 
-    TilesManager* tilesManager = TilesManager::instance();
-    int maxTextureCount = viewMaxTileX * viewMaxTileY * (tilesManager->highEndGfx() ? 4 : 2);
+    // allocate max possible number of tiles visible with this viewport
+    int viewMaxTileX = static_cast<int>(ceilf((viewport.width()-1) * invTileContentWidth)) + 1;
+    int viewMaxTileY = static_cast<int>(ceilf((viewport.height()-1) * invTileContentHeight)) + 1;
 
-    tilesManager->setCurrentTextureCount(maxTextureCount);
+    int maxTextureCount = (viewMaxTileX + m_expandedTileBoundsX * 2) *
+        (viewMaxTileY + m_expandedTileBoundsY * 2) * (m_highEndGfx ? 4 : 2);
 
-    // TODO: investigate whether we can move this return earlier.
-    if ((m_visibleContentRect == visibleContentRect)
-        && (m_scale == scale)) {
-        // everything below will stay the same, early return.
-        m_isVisibleContentRectScrolling = false;
-        return;
-    }
-    m_scale = scale;
-
-    m_goingDown = m_visibleContentRect.fTop - visibleContentRect.fTop <= 0;
-    m_goingLeft = m_visibleContentRect.fLeft - visibleContentRect.fLeft >= 0;
-
-    // detect visibleContentRect scrolling from short programmatic scrolls/jumps
-    m_isVisibleContentRectScrolling = m_visibleContentRect != visibleContentRect
-        && SkRect::Intersects(m_visibleContentRect, visibleContentRect);
-    m_visibleContentRect = visibleContentRect;
-
-    ALOGV("New visibleContentRect %.2f - %.2f %.2f - %.2f (w: %2.f h: %.2f scale: %.2f )",
-          m_visibleContentRect.fLeft, m_visibleContentRect.fTop,
-          m_visibleContentRect.fRight, m_visibleContentRect.fBottom,
-          m_visibleContentRect.width(), m_visibleContentRect.height(), scale);
+    TilesManager::instance()->setMaxTextureCount(maxTextureCount);
+    m_tiledPageA->updateBaseTileSize();
+    m_tiledPageB->updateBaseTileSize();
 }
 
 #ifdef MEASURES_PERF
 void GLWebViewState::dumpMeasures()
 {
     for (int i = 0; i < m_timeCounter; i++) {
-        ALOGD("%d delay: %d ms", m_totalTimeCounter + i,
+        XLOGC("%d delay: %d ms", m_totalTimeCounter + i,
              static_cast<int>(m_delayTimes[i]*1000));
         m_delayTimes[i] = 0;
     }
@@ -176,6 +287,14 @@
 }
 #endif // MEASURES_PERF
 
+void GLWebViewState::resetFrameworkInval()
+{
+    m_frameworkInval.setX(0);
+    m_frameworkInval.setY(0);
+    m_frameworkInval.setWidth(0);
+    m_frameworkInval.setHeight(0);
+}
+
 void GLWebViewState::addDirtyArea(const IntRect& rect)
 {
     if (rect.isEmpty())
@@ -195,41 +314,54 @@
     m_frameworkLayersInval.setY(0);
     m_frameworkLayersInval.setWidth(0);
     m_frameworkLayersInval.setHeight(0);
-    m_doFrameworkFullInval = false;
 }
 
-void GLWebViewState::doFrameworkFullInval()
+void GLWebViewState::drawBackground(Color& backgroundColor)
 {
-    m_doFrameworkFullInval = true;
+    if (TilesManager::instance()->invertedScreen()) {
+        float color = 1.0 - ((((float) backgroundColor.red() / 255.0) +
+                      ((float) backgroundColor.green() / 255.0) +
+                      ((float) backgroundColor.blue() / 255.0)) / 3.0);
+        glClearColor(color, color, color, 1);
+    } else {
+        glClearColor((float)backgroundColor.red() / 255.0,
+                     (float)backgroundColor.green() / 255.0,
+                     (float)backgroundColor.blue() / 255.0, 1);
+    }
+    glClear(GL_COLOR_BUFFER_BIT);
 }
 
-double GLWebViewState::setupDrawing(const IntRect& invScreenRect,
-                                    const SkRect& visibleContentRect,
-                                    const IntRect& screenRect, int titleBarHeight,
-                                    const IntRect& screenClip, float scale)
+double GLWebViewState::setupDrawing(IntRect& viewRect, SkRect& visibleRect,
+                                    IntRect& webViewRect, int titleBarHeight,
+                                    IntRect& screenClip, float scale)
 {
-    TilesManager* tilesManager = TilesManager::instance();
+    int left = viewRect.x();
+    int top = viewRect.y();
+    int width = viewRect.width();
+    int height = viewRect.height();
 
-    // Make sure GL resources are created on the UI thread.
-    // They are created either for the first time, or after EGL context
-    // recreation caused by onTrimMemory in the framework.
-    ShaderProgram* shader = tilesManager->shader();
-    if (shader->needsInit()) {
-        ALOGD("Reinit shader");
-        shader->initGLResources();
+    ShaderProgram* shader = TilesManager::instance()->shader();
+    if (shader->program() == -1) {
+        XLOG("Reinit shader");
+        shader->init();
     }
-    TransferQueue* transferQueue = tilesManager->transferQueue();
-    if (transferQueue->needsInit()) {
-        ALOGD("Reinit transferQueue");
-        transferQueue->initGLResources(TilesManager::tileWidth(),
-                                       TilesManager::tileHeight());
-    }
-    shader->setupDrawing(invScreenRect, visibleContentRect, screenRect,
-                         titleBarHeight, screenClip, scale);
+    shader->setViewport(visibleRect, scale);
+    shader->setViewRect(viewRect);
+    shader->setWebViewRect(webViewRect);
+    shader->setTitleBarHeight(titleBarHeight);
+    shader->setScreenClip(screenClip);
+    shader->resetBlending();
+
+    shader->calculateAnimationDelta();
+
+    glViewport(left + shader->getAnimationDeltaX(),
+               top - shader->getAnimationDeltaY(),
+               width, height);
 
     double currentTime = WTF::currentTime();
 
-    setVisibleContentRect(visibleContentRect, scale);
+    setViewport(visibleRect, scale);
+    m_zoomManager.processNewScale(currentTime, scale);
 
     return currentTime;
 }
@@ -239,11 +371,11 @@
     bool invalBase = false;
 
     if (!nbTexturesNeeded.full)
-        TilesManager::instance()->setCurrentLayerTextureCount(0);
+        TilesManager::instance()->setMaxLayerTextureCount(0);
     else
-        TilesManager::instance()->setCurrentLayerTextureCount((2 * nbTexturesNeeded.full) + 1);
+        TilesManager::instance()->setMaxLayerTextureCount((2*nbTexturesNeeded.full)+1);
 
-    int maxTextures = TilesManager::instance()->currentLayerTextureCount();
+    int maxTextures = TilesManager::instance()->maxLayerTextureCount();
     LayersRenderingMode layersRenderingMode = m_layersRenderingMode;
 
     if (m_layersRenderingMode == kSingleSurfaceRendering) {
@@ -277,7 +409,7 @@
     if (m_layersRenderingMode != layersRenderingMode) {
         char* mode[] = { "kAllTextures", "kClippedTextures",
             "kScrollableAndFixedLayers", "kFixedLayers", "kSingleSurfaceRendering" };
-        ALOGD("Change from mode %s to %s -- We need textures: fixed: %d,"
+        XLOGC("Change from mode %s to %s -- We need textures: fixed: %d,"
               " scrollable: %d, clipped: %d, full: %d, max textures: %d",
               static_cast<char*>(mode[layersRenderingMode]),
               static_cast<char*>(mode[m_layersRenderingMode]),
@@ -295,118 +427,138 @@
         m_layersRenderingMode = kSingleSurfaceRendering;
 
     // update the base surface if needed
-    // TODO: inval base layergroup when going into single surface mode
-    return (m_layersRenderingMode != layersRenderingMode && invalBase);
+    if (m_layersRenderingMode != layersRenderingMode
+        && invalBase) {
+        m_tiledPageA->discardTextures();
+        m_tiledPageB->discardTextures();
+        fullInval();
+        return true;
+    }
+    return false;
 }
 
-// -invScreenRect is the webView's rect with inverted Y screen coordinate.
-// -visibleContentRect is the visible area in content coordinate.
-// They are both based on  webView's rect and calculated in Java side.
-//
-// -screenClip is in screen coordinate, so we need to invert the Y axis before
-// passing into GL functions. Clip can be smaller than the webView's rect.
-//
-// TODO: Try to decrease the number of parameters as some info is redundant.
-int GLWebViewState::drawGL(IntRect& invScreenRect, SkRect& visibleContentRect,
-                           IntRect* invalRect, IntRect& screenRect, int titleBarHeight,
-                           IntRect& screenClip, float scale,
-                           bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr,
-                           bool shouldDraw)
+void GLWebViewState::fullInval()
 {
-    TilesManager* tilesManager = TilesManager::instance();
-    if (shouldDraw)
-        tilesManager->getProfiler()->nextFrame(visibleContentRect.fLeft,
-                                               visibleContentRect.fTop,
-                                               visibleContentRect.fRight,
-                                               visibleContentRect.fBottom,
-                                               scale);
-    tilesManager->incDrawGLCount();
+    // TODO -- use base layer's size.
+    IntRect ir(0, 0, 1E6, 1E6);
+    inval(ir);
+}
 
-    ALOGV("drawGL, invScreenRect(%d, %d, %d, %d), visibleContentRect(%.2f, %.2f, %.2f, %.2f)",
-          invScreenRect.x(), invScreenRect.y(), invScreenRect.width(), invScreenRect.height(),
-          visibleContentRect.fLeft, visibleContentRect.fTop,
-          visibleContentRect.fRight, visibleContentRect.fBottom);
+bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
+                            IntRect& webViewRect, int titleBarHeight,
+                            IntRect& clip, float scale,
+                            bool* treesSwappedPtr, bool* newTreeHasAnimPtr)
+{
+    m_scale = scale;
+    TilesManager::instance()->getProfiler()->nextFrame(viewport.fLeft,
+                                                       viewport.fTop,
+                                                       viewport.fRight,
+                                                       viewport.fBottom,
+                                                       scale);
+    TilesManager::instance()->incDrawGLCount();
 
-    ALOGV("drawGL, invalRect(%d, %d, %d, %d), screenRect(%d, %d, %d, %d)"
-          "screenClip (%d, %d, %d, %d), scale %f titleBarHeight %d",
-          invalRect->x(), invalRect->y(), invalRect->width(), invalRect->height(),
-          screenRect.x(), screenRect.y(), screenRect.width(), screenRect.height(),
-          screenClip.x(), screenClip.y(), screenClip.width(), screenClip.height(), scale, titleBarHeight);
+#ifdef DEBUG
+    TilesManager::instance()->getTilesTracker()->clear();
+#endif
 
-    m_inUnclippedDraw = shouldDraw && (screenRect == screenClip);
+    float viewWidth = (viewport.fRight - viewport.fLeft) * TILE_PREFETCH_RATIO;
+    float viewHeight = (viewport.fBottom - viewport.fTop) * TILE_PREFETCH_RATIO;
+    bool useMinimalMemory = TilesManager::instance()->useMinimalMemory();
+    bool useHorzPrefetch = useMinimalMemory ? 0 : viewWidth < baseContentWidth();
+    bool useVertPrefetch = useMinimalMemory ? 0 : viewHeight < baseContentHeight();
+    m_expandedTileBoundsX = (useHorzPrefetch) ? TILE_PREFETCH_DISTANCE : 0;
+    m_expandedTileBoundsY = (useVertPrefetch) ? TILE_PREFETCH_DISTANCE : 0;
+
+    XLOG("drawGL, rect(%d, %d, %d, %d), viewport(%.2f, %.2f, %.2f, %.2f)",
+         rect.x(), rect.y(), rect.width(), rect.height(),
+         viewport.fLeft, viewport.fTop, viewport.fRight, viewport.fBottom);
 
     resetLayersDirtyArea();
 
+    // when adding or removing layers, use the the paintingBaseLayer's tree so
+    // that content that moves to the base layer from a layer is synchronized
+
     if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING)
-        ALOGW("WARNING, scale seems corrupted before update: %e", scale);
+        XLOGC("WARNING, scale seems corrupted before update: %e", scale);
 
-    tilesManager->updateTilesIfContextVerified();
-
-    // gather the textures we can use, make sure this happens before any
-    // texture preparation work.
-    tilesManager->gatherTextures();
+    // Here before we draw, update the BaseTile which has updated content.
+    // Inside this function, just do GPU blits from the transfer queue into
+    // the BaseTiles' texture.
+    TilesManager::instance()->transferQueue()->updateDirtyBaseTiles();
 
     // Upload any pending ImageTexture
     // Return true if we still have some images to upload.
     // TODO: upload as many textures as possible within a certain time limit
-    int returnFlags = 0;
-    if (ImagesManager::instance()->prepareTextures(this))
-        returnFlags |= DrawGlInfo::kStatusDraw;
+    bool ret = ImagesManager::instance()->prepareTextures(this);
 
-    if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING) {
-        ALOGW("WARNING, scale seems corrupted after update: %e", scale);
-        scale = 1.0f; // WORKAROUND for corrupted scale: use 1.0
-    }
+    if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING)
+        XLOGC("WARNING, scale seems corrupted after update: %e", scale);
 
-    double currentTime = setupDrawing(invScreenRect, visibleContentRect, screenRect,
-                                      titleBarHeight, screenClip, scale);
+    // gather the textures we can use
+    TilesManager::instance()->gatherLayerTextures();
+
+    double currentTime = setupDrawing(rect, viewport, webViewRect, titleBarHeight, clip, scale);
+
 
     TexturesResult nbTexturesNeeded;
-    bool scrolling = isScrolling();
-    bool singleSurfaceMode = m_layersRenderingMode == kSingleSurfaceRendering;
-    m_glExtras.setVisibleContentRect(visibleContentRect);
-
-    returnFlags |= m_surfaceCollectionManager.drawGL(currentTime, invScreenRect,
-                                                     visibleContentRect,
-                                                     scale, scrolling,
-                                                     singleSurfaceMode,
-                                                     collectionsSwappedPtr,
-                                                     newCollectionHasAnimPtr,
-                                                     &nbTexturesNeeded, shouldDraw);
+    bool fastSwap = isScrolling() || m_layersRenderingMode == kSingleSurfaceRendering;
+    ret |= m_treeManager.drawGL(currentTime, rect, viewport,
+                                scale, fastSwap,
+                                treesSwappedPtr, newTreeHasAnimPtr,
+                                &nbTexturesNeeded);
+    if (!ret)
+        resetFrameworkInval();
 
     int nbTexturesForImages = ImagesManager::instance()->nbTextures();
-    ALOGV("*** We have %d textures for images, %d full, %d clipped, total %d / %d",
+    XLOG("*** We have %d textures for images, %d full, %d clipped, total %d / %d",
           nbTexturesForImages, nbTexturesNeeded.full, nbTexturesNeeded.clipped,
           nbTexturesNeeded.full + nbTexturesForImages,
           nbTexturesNeeded.clipped + nbTexturesForImages);
     nbTexturesNeeded.full += nbTexturesForImages;
     nbTexturesNeeded.clipped += nbTexturesForImages;
+    ret |= setLayersRenderingMode(nbTexturesNeeded);
 
-    if (setLayersRenderingMode(nbTexturesNeeded)) {
-        TilesManager::instance()->dirtyAllTiles();
-        returnFlags |= DrawGlInfo::kStatusDraw | DrawGlInfo::kStatusInvoke;
-    }
+    FloatRect extrasclip(0, 0, rect.width(), rect.height());
+    TilesManager::instance()->shader()->clip(extrasclip);
+
+    m_glExtras.drawGL(webViewRect, viewport, titleBarHeight);
 
     glBindBuffer(GL_ARRAY_BUFFER, 0);
 
-    if (returnFlags & DrawGlInfo::kStatusDraw) {
-        // returnFlags & kStatusDraw && empty inval region means we've inval'd everything,
+    // Clean up GL textures for video layer.
+    TilesManager::instance()->videoLayerManager()->deleteUnusedTextures();
+    ret |= TilesManager::instance()->invertedScreenSwitch();
+
+    if (ret) {
+        // ret==true && empty inval region means we've inval'd everything,
         // but don't have new content. Keep redrawing full view (0,0,0,0)
         // until tile generation catches up and we swap pages.
-        bool fullScreenInval = m_frameworkLayersInval.isEmpty() || m_doFrameworkFullInval;
+        bool fullScreenInval = m_frameworkInval.isEmpty();
+
+        if (TilesManager::instance()->invertedScreenSwitch()) {
+            fullScreenInval = true;
+            TilesManager::instance()->setInvertedScreenSwitch(false);
+        }
 
         if (!fullScreenInval) {
-            m_frameworkLayersInval.inflate(1);
+            FloatRect frameworkInval = TilesManager::instance()->shader()->rectInInvScreenCoord(
+                    m_frameworkInval);
+            // Inflate the invalidate rect to avoid precision lost.
+            frameworkInval.inflate(1);
+            IntRect inval(frameworkInval.x(), frameworkInval.y(),
+                    frameworkInval.width(), frameworkInval.height());
 
-            invalRect->setX(m_frameworkLayersInval.x());
-            invalRect->setY(m_frameworkLayersInval.y());
-            invalRect->setWidth(m_frameworkLayersInval.width());
-            invalRect->setHeight(m_frameworkLayersInval.height());
+            inval.unite(m_frameworkLayersInval);
 
-            ALOGV("invalRect(%d, %d, %d, %d)", invalRect->x(),
-                  invalRect->y(), invalRect->width(), invalRect->height());
+            invalRect->setX(inval.x());
+            invalRect->setY(inval.y());
+            invalRect->setWidth(inval.width());
+            invalRect->setHeight(inval.height());
 
-            if (!invalRect->intersects(invScreenRect)) {
+            XLOG("invalRect(%d, %d, %d, %d)", inval.x(),
+                    inval.y(), inval.width(), inval.height());
+
+            if (!invalRect->intersects(rect)) {
                 // invalidate is occurring offscreen, do full inval to guarantee redraw
                 fullScreenInval = true;
             }
@@ -418,29 +570,10 @@
             invalRect->setWidth(0);
             invalRect->setHeight(0);
         }
+    } else {
+        resetFrameworkInval();
     }
 
-    if (shouldDraw)
-        showFrameInfo(invScreenRect, *collectionsSwappedPtr);
-
-    return returnFlags;
-}
-
-void GLWebViewState::showFrameInfo(const IntRect& rect, bool collectionsSwapped)
-{
-    bool showVisualIndicator = TilesManager::instance()->getShowVisualIndicator();
-
-    bool drawOrDumpFrameInfo = showVisualIndicator;
-#ifdef MEASURES_PERF
-    drawOrDumpFrameInfo |= m_measurePerfs;
-#endif
-    if (!drawOrDumpFrameInfo)
-        return;
-
-    double currentDrawTime = WTF::currentTime();
-    double delta = currentDrawTime - m_prevDrawTime;
-    m_prevDrawTime = currentDrawTime;
-
 #ifdef MEASURES_PERF
     if (m_measurePerfs) {
         m_delayTimes[m_timeCounter++] = delta;
@@ -449,37 +582,12 @@
     }
 #endif
 
-    IntRect frameInfoRect = rect;
-    frameInfoRect.setHeight(FPS_INDICATOR_HEIGHT);
-    double ratio = (1.0 / delta) / MAX_FPS_VALUE;
+#ifdef DEBUG
+    TilesManager::instance()->getTilesTracker()->showTrackTextures();
+    ImagesManager::instance()->showImages();
+#endif
 
-    clearRectWithColor(frameInfoRect, 1, 1, 1, 1);
-    frameInfoRect.setWidth(frameInfoRect.width() * ratio);
-    clearRectWithColor(frameInfoRect, 1, 0, 0, 1);
-
-    // Draw the collection swap counter as a circling progress bar.
-    // This will basically show how fast we are updating the collection.
-    static int swappedCounter = 0;
-    if (collectionsSwapped)
-        swappedCounter = (swappedCounter + 1) % COLLECTION_SWAPPED_COUNTER_MODULE;
-
-    frameInfoRect = rect;
-    frameInfoRect.setHeight(FPS_INDICATOR_HEIGHT);
-    frameInfoRect.move(0, FPS_INDICATOR_HEIGHT);
-
-    clearRectWithColor(frameInfoRect, 1, 1, 1, 1);
-    ratio = (swappedCounter + 1.0) / COLLECTION_SWAPPED_COUNTER_MODULE;
-
-    frameInfoRect.setWidth(frameInfoRect.width() * ratio);
-    clearRectWithColor(frameInfoRect, 0, 1, 0, 1);
-}
-
-void GLWebViewState::clearRectWithColor(const IntRect& rect, float r, float g,
-                                      float b, float a)
-{
-    glScissor(rect.x(), rect.y(), rect.width(), rect.height());
-    glClearColor(r, g, b, a);
-    glClear(GL_COLOR_BUFFER_BIT);
+    return ret;
 }
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.h b/Source/WebCore/platform/graphics/android/GLWebViewState.h
index e325590..8d89704 100644
--- a/Source/WebCore/platform/graphics/android/GLWebViewState.h
+++ b/Source/WebCore/platform/graphics/android/GLWebViewState.h
@@ -35,7 +35,9 @@
 #include "SkCanvas.h"
 #include "SkRect.h"
 #include "SkRegion.h"
-#include "SurfaceCollectionManager.h"
+#include "TiledPage.h"
+#include "TreeManager.h"
+#include "ZoomManager.h"
 #include <utils/threads.h>
 
 // Performance measurements probe
@@ -49,6 +51,9 @@
 // HW limit or save further in the GPU memory consumption.
 #define TILE_PREFETCH_DISTANCE 1
 
+// ratio of content to view required for prefetching to enable
+#define TILE_PREFETCH_RATIO 1.2
+
 namespace WebCore {
 
 class BaseLayerAndroid;
@@ -75,7 +80,7 @@
 //
 // The rendering model is to use tiles to display the BaseLayer (as obviously a
 // BaseLayer's area can be arbitrarly large). The idea is to compute a set of
-// tiles covering the visibleContentRect's area, paint those tiles using the webview's
+// tiles covering the viewport's area, paint those tiles using the webview's
 // content (i.e. the BaseLayer's PictureSet), then display those tiles.
 // We check which tile we should use at every frame.
 //
@@ -86,14 +91,14 @@
 // the BaseLayer's surface. When drawing, we ask the TiledPage to prepare()
 // itself then draw itself on screen. The prepare() function is the one
 // that schedules tiles to be painted -- i.e. the subset of tiles that intersect
-// with the current visibleContentRect. When they are ready, we can display
+// with the current viewport. When they are ready, we can display
 // the TiledPage.
 //
 // Note that BaseLayerAndroid::drawGL() will return true to the java side if
 // there is a need to be called again (i.e. if we do not have up to date
 // textures or a transition is going on).
 //
-// Tiles are implemented as a Tile. It knows how to paint itself with the
+// Tiles are implemented as a BaseTile. It knows how to paint itself with the
 // PictureSet, and to display itself. A GL texture is usually associated to it.
 //
 // We also works with two TiledPages -- one to display the page at the
@@ -102,30 +107,30 @@
 // accordingly (and therefore possible loss of quality): this is fast as it's
 // purely a hardware operation. When the user is done zooming, we ask for
 // TiledPage B to be painted at the new scale factor, covering the
-// visibleContentRect's area. When B is ready, we swap it with A.
+// viewport's area. When B is ready, we swap it with A.
 //
 // Texture allocation
 // ------------------
 //
-// Obviously we cannot have every Tile having a GL texture -- we need to
+// Obviously we cannot have every BaseTile having a GL texture -- we need to
 // get the GL textures from an existing pool, and reuse them.
 //
 // The way we do it is that when we call TiledPage::prepare(), we group the
-// tiles we need (i.e. in the visibleContentRect and dirty) into a TilesSet and call
-// Tile::reserveTexture() for each tile (which ensures there is a specific
-// GL textures backing the Tiles).
+// tiles we need (i.e. in the viewport and dirty) into a TilesSet and call
+// BaseTile::reserveTexture() for each tile (which ensures there is a specific
+// GL textures backing the BaseTiles).
 //
 // reserveTexture() will ask the TilesManager for a texture. The allocation
 // mechanism goal is to (in order):
 // - prefers to allocate the same texture as the previous time
-// - prefers to allocate textures that are as far from the visibleContentRect as possible
+// - prefers to allocate textures that are as far from the viewport as possible
 // - prefers to allocate textures that are used by different TiledPages
 //
-// Note that to compute the distance of each tile from the visibleContentRect, each time
+// Note that to compute the distance of each tile from the viewport, each time
 // we prepare() a TiledPage. Also during each prepare() we compute which tiles
 // are dirty based on the info we have received from webkit.
 //
-// Tile Invalidation
+// BaseTile Invalidation
 // ------------------
 //
 // We do not want to redraw a tile if the tile is up-to-date. A tile is
@@ -149,9 +154,9 @@
 //
 // The next operation is to schedule this TilesSet to be painted
 // (TilesManager::schedulePaintForTilesSet()). TexturesGenerator
-// will get the TilesSet and ask the Tiles in it to be painted.
+// will get the TilesSet and ask the BaseTiles in it to be painted.
 //
-// Tile::paintBitmap() will paint the texture using the BaseLayer's
+// BaseTile::paintBitmap() will paint the texture using the BaseLayer's
 // PictureSet (calling TiledPage::paintBaseLayerContent() which in turns
 // calls GLWebViewState::paintBaseLayerContent()).
 //
@@ -166,39 +171,73 @@
     GLWebViewState();
     ~GLWebViewState();
 
-    bool setBaseLayer(BaseLayerAndroid* layer, bool showVisualIndicator,
+    ZoomManager* zoomManager() { return &m_zoomManager; }
+    const SkIRect& futureViewport() const { return m_futureViewportTileBounds; }
+    void setFutureViewport(const SkIRect& viewport) { m_futureViewportTileBounds = viewport; }
+
+    unsigned int paintBaseLayerContent(SkCanvas* canvas);
+    void setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval, bool showVisualIndicator,
                       bool isPictureAfterFirstLayout);
     void paintExtras();
 
     GLExtras* glExtras() { return &m_glExtras; }
 
+    TiledPage* sibling(TiledPage* page);
+    TiledPage* frontPage();
+    TiledPage* backPage();
+    void swapPages();
+
+    // dimensions of the current base layer
+    int baseContentWidth();
+    int baseContentHeight();
+
+    void setViewport(SkRect& viewport, float scale);
+
+    // a rect containing the coordinates of all tiles in the current viewport
+    const SkIRect& viewportTileBounds() const { return m_viewportTileBounds; }
+    // a rect containing the viewportTileBounds before there was a scale change
+    const SkIRect& preZoomBounds() const { return m_preZoomBounds; }
+    void setPreZoomBounds(const SkIRect& bounds) { m_preZoomBounds = bounds; }
+
+    unsigned int currentPictureCounter() const { return m_currentPictureCounter; }
+
     void setIsScrolling(bool isScrolling) { m_isScrolling = isScrolling; }
-    bool isScrolling() { return m_isScrolling || m_isVisibleContentRectScrolling; }
+    bool isScrolling() { return m_isScrolling; }
+
+    void drawBackground(Color& backgroundColor);
+    double setupDrawing(IntRect& viewRect, SkRect& visibleRect,
+                        IntRect& webViewRect, int titleBarHeight,
+                        IntRect& screenClip, float scale);
 
     bool setLayersRenderingMode(TexturesResult&);
+    void fullInval();
 
-    int drawGL(IntRect& rect, SkRect& visibleContentRect, IntRect* invalRect,
-               IntRect& screenRect, int titleBarHeight,
-               IntRect& clip, float scale,
-               bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr,
-               bool shouldDraw);
+    bool drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
+                IntRect& webViewRect, int titleBarHeight,
+                IntRect& clip, float scale,
+                bool* treesSwappedPtr, bool* newTreeHasAnimPtr);
 
 #ifdef MEASURES_PERF
     void dumpMeasures();
 #endif
 
+    void resetFrameworkInval();
     void addDirtyArea(const IntRect& rect);
     void resetLayersDirtyArea();
-    void doFrameworkFullInval();
-    bool inUnclippedDraw() { return m_inUnclippedDraw; }
 
     bool goingDown() { return m_goingDown; }
     bool goingLeft() { return m_goingLeft; }
+    void setDirection(bool goingDown, bool goingLeft) {
+        m_goingDown = goingDown;
+        m_goingLeft = goingLeft;
+    }
+
+    int expandedTileBoundsX() { return m_expandedTileBoundsX; }
+    int expandedTileBoundsY() { return m_expandedTileBoundsY; }
+    void setHighEndGfx(bool highEnd) { m_highEndGfx = highEnd; }
 
     float scale() { return m_scale; }
 
-    // Currently, we only use 3 modes : kAllTextures, kClippedTextures and
-    // kSingleSurfaceRendering ( for every mode > kClippedTextures ) .
     enum LayersRenderingMode {
         kAllTextures              = 0, // all layers are drawn with textures fully covering them
         kClippedTextures          = 1, // all layers are drawn, but their textures will be clipped
@@ -209,23 +248,27 @@
     };
 
     LayersRenderingMode layersRenderingMode() { return m_layersRenderingMode; }
-    bool isSingleSurfaceRenderingMode() { return m_layersRenderingMode == kSingleSurfaceRendering; }
     void scrollLayer(int layerId, int x, int y);
 
-private:
-    void setVisibleContentRect(const SkRect& visibleContentRect, float scale);
-    double setupDrawing(const IntRect& invScreenRect, const SkRect& visibleContentRect,
-                        const IntRect& screenRect, int titleBarHeight,
-                        const IntRect& screenClip, float scale);
-    void showFrameInfo(const IntRect& rect, bool collectionsSwapped);
-    void clearRectWithColor(const IntRect& rect, float r, float g,
-                            float b, float a);
-    double m_prevDrawTime;
+    void invalRegion(const SkRegion& region);
 
-    SkRect m_visibleContentRect;
+private:
+    void inval(const IntRect& rect);
+
+    ZoomManager m_zoomManager;
+    android::Mutex m_tiledPageLock;
+    SkRect m_viewport;
+    SkIRect m_viewportTileBounds;
+    SkIRect m_futureViewportTileBounds;
+    SkIRect m_preZoomBounds;
+
+    unsigned int m_currentPictureCounter;
+    bool m_usePageA;
+    TiledPage* m_tiledPageA;
+    TiledPage* m_tiledPageB;
+    IntRect m_lastInval;
+    IntRect m_frameworkInval;
     IntRect m_frameworkLayersInval;
-    bool m_doFrameworkFullInval;
-    bool m_inUnclippedDraw;
 
 #ifdef MEASURES_PERF
     unsigned int m_totalTimeCounter;
@@ -236,14 +279,17 @@
     GLExtras m_glExtras;
 
     bool m_isScrolling;
-    bool m_isVisibleContentRectScrolling;
     bool m_goingDown;
     bool m_goingLeft;
 
+    int m_expandedTileBoundsX;
+    int m_expandedTileBoundsY;
+    bool m_highEndGfx;
+
     float m_scale;
 
     LayersRenderingMode m_layersRenderingMode;
-    SurfaceCollectionManager m_surfaceCollectionManager;
+    TreeManager m_treeManager;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/GaneshContext.cpp b/Source/WebCore/platform/graphics/android/GaneshContext.cpp
similarity index 83%
rename from Source/WebCore/platform/graphics/android/rendering/GaneshContext.cpp
rename to Source/WebCore/platform/graphics/android/GaneshContext.cpp
index 5c4b453..80fe749 100644
--- a/Source/WebCore/platform/graphics/android/rendering/GaneshContext.cpp
+++ b/Source/WebCore/platform/graphics/android/GaneshContext.cpp
@@ -23,27 +23,35 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#define LOG_TAG "GaneshContext"
-#define LOG_NDEBUG 1
 
 #include "config.h"
 #include "GaneshContext.h"
-
-#include "AndroidLog.h"
 #include "GLUtils.h"
-#include "TextureInfo.h"
-#include "TilesManager.h"
-#include "TransferQueue.h"
 
 #include "android/native_window.h"
 
 #if USE(ACCELERATED_COMPOSITING)
 
+#ifdef DEBUG
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GaneshContext", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
 namespace WebCore {
 
 GaneshContext::GaneshContext()
     : m_grContext(0)
-    , m_tileDeviceSurface(0)
+    , m_baseTileDeviceSurface(0)
     , m_surfaceConfig(0)
     , m_surfaceContext(EGL_NO_CONTEXT)
 {
@@ -60,8 +68,9 @@
 
 GrContext* GaneshContext::getGrContext()
 {
-    if (!m_grContext)
-        m_grContext = GrContext::Create(kOpenGL_Shaders_GrEngine, 0);
+    if (!m_grContext) {
+        m_grContext = GrContext::Create(kOpenGL_Shaders_GrEngine, NULL);
+    }
     return m_grContext;
 }
 
@@ -71,15 +80,15 @@
         m_grContext->flush();
 }
 
-SkDevice* GaneshContext::getDeviceForTile(const TileRenderInfo& renderInfo)
+SkDevice* GaneshContext::getDeviceForBaseTile(const TileRenderInfo& renderInfo)
 {
     // Ganesh should be the only code in the rendering thread that is using GL
     // and setting the EGLContext.  If this is not the case then we need to
     // reset the Ganesh context to prevent rendering issues.
     bool contextNeedsReset = false;
     if (eglGetCurrentContext() != m_surfaceContext) {
-        ALOGV("Warning: EGLContext has Changed! %p, %p",
-              m_surfaceContext, eglGetCurrentContext());
+        XLOG("Warning: EGLContext has Changed! %p, %p", m_surfaceContext,
+                                                        eglGetCurrentContext());
         contextNeedsReset = true;
     }
 
@@ -87,8 +96,9 @@
 
     if (!m_surfaceContext) {
 
-        if(eglGetCurrentContext() != EGL_NO_CONTEXT)
-            ALOGV("ERROR: should not have a context yet");
+        if(eglGetCurrentContext() != EGL_NO_CONTEXT) {
+            XLOG("ERROR: should not have a context yet");
+        }
 
         display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
         GLUtils::checkEglError("eglGetDisplay");
@@ -140,14 +150,14 @@
         tileQueue->m_eglSurface = eglCreateWindowSurface(display, m_surfaceConfig, anw, NULL);
 
         GLUtils::checkEglError("eglCreateWindowSurface");
-        ALOGV("eglCreateWindowSurface");
+        XLOG("eglCreateWindowSurface");
     }
 
     EGLBoolean returnValue = eglMakeCurrent(display, tileQueue->m_eglSurface, tileQueue->m_eglSurface, m_surfaceContext);
     GLUtils::checkEglError("eglMakeCurrent", returnValue);
-    ALOGV("eglMakeCurrent");
+    XLOG("eglMakeCurrent");
 
-    if (!m_tileDeviceSurface) {
+    if (!m_baseTileDeviceSurface) {
 
         GrPlatformRenderTargetDesc renderTargetDesc;
         renderTargetDesc.fWidth = TilesManager::tileWidth();
@@ -160,19 +170,19 @@
         GrContext* grContext = getGrContext();
         GrRenderTarget* renderTarget = grContext->createPlatformRenderTarget(renderTargetDesc);
 
-        m_tileDeviceSurface = new SkGpuDevice(grContext, renderTarget);
+        m_baseTileDeviceSurface = new SkGpuDevice(grContext, renderTarget);
         renderTarget->unref();
-        ALOGV("generated device %p", m_tileDeviceSurface);
+        XLOG("generated device %p", m_baseTileDeviceSurface);
     }
 
-    GLUtils::checkGlError("getDeviceForTile");
+    GLUtils::checkGlError("getDeviceForBaseTile");
 
     // We must reset the Ganesh context only after we are sure we have
     // re-established our EGLContext as the current context.
-    if (m_tileDeviceSurface && contextNeedsReset)
+    if (m_baseTileDeviceSurface && contextNeedsReset)
         getGrContext()->resetContext();
 
-    return m_tileDeviceSurface;
+    return m_baseTileDeviceSurface;
 }
 
 
diff --git a/Source/WebCore/platform/graphics/android/rendering/GaneshContext.h b/Source/WebCore/platform/graphics/android/GaneshContext.h
similarity index 93%
rename from Source/WebCore/platform/graphics/android/rendering/GaneshContext.h
rename to Source/WebCore/platform/graphics/android/GaneshContext.h
index 57e8e19..def35e5 100644
--- a/Source/WebCore/platform/graphics/android/rendering/GaneshContext.h
+++ b/Source/WebCore/platform/graphics/android/GaneshContext.h
@@ -31,7 +31,7 @@
 #include "BaseRenderer.h"
 #include "GrContext.h"
 #include "SkGpuDevice.h"
-#include <EGL/egl.h>
+#include "TilesManager.h"
 
 namespace WebCore {
 
@@ -39,7 +39,7 @@
 public:
     static GaneshContext* instance();
 
-    SkDevice* getDeviceForTile(const TileRenderInfo& renderInfo);
+    SkDevice* getDeviceForBaseTile(const TileRenderInfo& renderInfo);
 
     void flush();
 
@@ -50,7 +50,7 @@
     GrContext* getGrContext();
     GrContext* m_grContext;
 
-    SkGpuDevice* m_tileDeviceSurface;
+    SkGpuDevice* m_baseTileDeviceSurface;
     EGLConfig  m_surfaceConfig;
     EGLContext m_surfaceContext;
 
diff --git a/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp b/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp
new file mode 100644
index 0000000..29acb2b
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+#include "GaneshRenderer.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "GaneshContext.h"
+#include "SkCanvas.h"
+#include "SkGpuDevice.h"
+#include "TilesManager.h"
+
+
+#ifdef DEBUG
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GaneshRenderer", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+namespace WebCore {
+
+static const String TAG_CREATE_FBO = "create_fbo";
+static const String TAG_DRAW_PICTURE = "draw_picture";
+static const String TAG_UPDATE_TEXTURE = "update_texture";
+#define TAG_COUNT 3
+static const String TAGS[] = {
+    TAG_CREATE_FBO,
+    TAG_DRAW_PICTURE,
+    TAG_UPDATE_TEXTURE,
+};
+
+GaneshRenderer::GaneshRenderer() : BaseRenderer(BaseRenderer::Ganesh)
+{
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->increment("GaneshRenderer");
+#endif
+}
+
+GaneshRenderer::~GaneshRenderer()
+{
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->decrement("GaneshRenderer");
+#endif
+}
+
+void GaneshRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas)
+{
+    if (renderInfo.measurePerf)
+        m_perfMon.start(TAG_CREATE_FBO);
+
+    GaneshContext* ganesh = GaneshContext::instance();
+
+#if !DEPRECATED_SURFACE_TEXTURE_MODE
+    if (renderInfo.textureInfo->getSharedTextureMode() == SurfaceTextureMode) {
+        TransferQueue* tileQueue = TilesManager::instance()->transferQueue();
+
+        tileQueue->lockQueue();
+
+        bool ready = tileQueue->readyForUpdate();
+        if (!ready) {
+            XLOG("!ready");
+            tileQueue->unlockQueue();
+            return;
+        }
+    }
+#endif
+
+    SkDevice* device = NULL;
+    if (renderInfo.tileSize.width() == TilesManager::tileWidth()
+            && renderInfo.tileSize.height() == TilesManager::tileHeight()) {
+        device = ganesh->getDeviceForBaseTile(renderInfo);
+    } else {
+        // TODO support arbitrary sizes for layers
+        XLOG("ERROR: expected (%d,%d) actual (%d,%d)",
+                TilesManager::tileWidth(), TilesManager::tileHeight(),
+                renderInfo.tileSize.width(), renderInfo.tileSize.height());
+    }
+
+    if (renderInfo.measurePerf) {
+        m_perfMon.stop(TAG_CREATE_FBO);
+        m_perfMon.start(TAG_DRAW_PICTURE);
+    }
+
+    // set the GPU device to the canvas
+    canvas->setDevice(device);
+
+    // invert canvas contents
+    if (renderInfo.textureInfo->getSharedTextureMode() == EglImageMode) {
+        canvas->scale(SK_Scalar1, -SK_Scalar1);
+        canvas->translate(0, -renderInfo.tileSize.height());
+    }
+}
+
+void GaneshRenderer::setupPartialInval(const TileRenderInfo& renderInfo, SkCanvas* canvas)
+{
+    // set the clip to our invalRect
+    SkRect clipRect = SkRect::MakeLTRB(renderInfo.invalRect->fLeft,
+                                       renderInfo.invalRect->fTop,
+                                       renderInfo.invalRect->fRight,
+                                       renderInfo.invalRect->fBottom);
+    canvas->clipRect(clipRect);
+}
+
+void GaneshRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas)
+{
+    if (renderInfo.measurePerf) {
+        m_perfMon.stop(TAG_DRAW_PICTURE);
+        m_perfMon.start(TAG_UPDATE_TEXTURE);
+    }
+
+    XLOG("rendered to tile (%d,%d)", renderInfo.x, renderInfo.y);
+
+    GaneshContext::instance()->flush();
+
+    // In SurfaceTextureMode we must call swapBuffers to unlock and post the
+    // tile's ANativeWindow (i.e. SurfaceTexture) buffer
+    if (renderInfo.textureInfo->getSharedTextureMode() == SurfaceTextureMode) {
+#if !DEPRECATED_SURFACE_TEXTURE_MODE
+        TransferQueue* tileQueue = TilesManager::instance()->transferQueue();
+        eglSwapBuffers(eglGetCurrentDisplay(), tileQueue->m_eglSurface);
+        tileQueue->addItemInTransferQueue(&renderInfo, GpuUpload, 0);
+        tileQueue->unlockQueue();
+#endif
+    }
+
+    if (renderInfo.measurePerf)
+        m_perfMon.stop(TAG_UPDATE_TEXTURE);
+}
+
+const String* GaneshRenderer::getPerformanceTags(int& tagCount)
+{
+    tagCount = TAG_COUNT;
+    return TAGS;
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h b/Source/WebCore/platform/graphics/android/GaneshRenderer.h
similarity index 92%
rename from Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h
rename to Source/WebCore/platform/graphics/android/GaneshRenderer.h
index cdd9f3e..0e1d41e 100644
--- a/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.h
+++ b/Source/WebCore/platform/graphics/android/GaneshRenderer.h
@@ -47,10 +47,9 @@
 protected:
 
     virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas);
+    virtual void setupPartialInval(const TileRenderInfo& renderInfo, SkCanvas* canvas);
     virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas);
-    virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas) {
-        renderInfo.isPureColor = false;
-    }
+    virtual const String* getPerformanceTags(int& tagCount);
 
 };
 
diff --git a/Source/WebCore/platform/graphics/android/fonts/GlyphMapAndroid.cpp b/Source/WebCore/platform/graphics/android/GlyphMapAndroid.cpp
similarity index 100%
rename from Source/WebCore/platform/graphics/android/fonts/GlyphMapAndroid.cpp
rename to Source/WebCore/platform/graphics/android/GlyphMapAndroid.cpp
diff --git a/Source/WebCore/platform/graphics/android/GradientAndroid.cpp b/Source/WebCore/platform/graphics/android/GradientAndroid.cpp
new file mode 100644
index 0000000..b8dc9dd
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/GradientAndroid.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2006, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "Gradient.h"
+
+#include "android_graphics.h"
+#include "CSSParser.h"
+#include "GraphicsContext.h"
+#include "NotImplemented.h"
+#include "SkCanvas.h"
+#include "SkColorShader.h"
+#include "SkGradientShader.h"
+#include "SkPaint.h"
+
+class PlatformGradientRec {
+public:
+    PlatformGradientRec() : m_shader(NULL) {}
+    ~PlatformGradientRec() { SkSafeUnref(m_shader); }
+
+    SkShader*           m_shader;
+    SkShader::TileMode  m_tileMode;
+    int                 m_colorCountWhenShaderWasBuilt;
+};
+
+namespace WebCore {
+
+void Gradient::platformDestroy()
+{
+    delete m_gradient;
+    m_gradient = 0;
+}
+
+static U8CPU F2B(float x)
+{
+    return (int)(x * 255);
+}
+
+SkShader* Gradient::getShader(SkShader::TileMode mode)
+{
+    if (NULL == m_gradient)
+        m_gradient = new PlatformGradientRec;
+    else if (mode == m_gradient->m_tileMode)
+        return m_gradient->m_shader;
+
+    // need to ensure that the m_stops array is sorted. We call getColor()
+    // which, as a side effect, does the sort.
+    // TODO: refactor Gradient.h to formally expose a sort method
+    {
+        float r, g, b, a;
+        this->getColor(0, &r, &g, &b, &a);
+    }
+
+    SkPoint pts[2] = { m_p0, m_p1 };    // convert to SkPoint
+
+    const size_t count = m_stops.size();
+    SkAutoMalloc    storage(count * (sizeof(SkColor) + sizeof(SkScalar)));
+    SkColor*        colors = (SkColor*)storage.get();
+    SkScalar*       pos = (SkScalar*)(colors + count);
+
+    Vector<ColorStop>::iterator iter = m_stops.begin();
+    for (int i = 0; iter != m_stops.end(); i++) {
+        pos[i] = SkFloatToScalar(iter->stop);
+        colors[i] = SkColorSetARGB(F2B(iter->alpha), F2B(iter->red),
+                                   F2B(iter->green), F2B(iter->blue));
+        ++iter;
+    }
+
+    SkShader* s;
+    if (m_radial)
+        s = SkGradientShader::CreateTwoPointRadial(pts[0],
+                                                   SkFloatToScalar(m_r0),
+                                                   pts[1],
+                                                   SkFloatToScalar(m_r1),
+                                                   colors, pos, count, mode);
+    else
+        s = SkGradientShader::CreateLinear(pts, colors, pos, count, mode);
+
+    if (NULL == s)
+        s = new SkColorShader(0);
+
+    // zap our previous shader, if present
+    SkSafeUnref(m_gradient->m_shader);
+    m_gradient->m_shader = s;
+    m_gradient->m_tileMode = mode;
+    SkMatrix matrix = m_gradientSpaceTransformation;
+    s->setLocalMatrix(matrix);
+
+    return s;
+}
+
+void Gradient::fill(GraphicsContext* context, const FloatRect& rect)
+{
+    SkRect r;
+    SkPaint paint;
+    // we don't care about the mode, so try to use the existing one
+    SkShader::TileMode mode = m_gradient ? m_gradient->m_tileMode :
+                                            SkShader::kClamp_TileMode;
+
+    paint.setAntiAlias(true);
+    paint.setShader(this->getShader(mode));
+    android_gc2canvas(context)->drawRect(rect, paint);
+}
+
+
+} //namespace
diff --git a/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp
new file mode 100644
index 0000000..a490d5f
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/GraphicsContextAndroid.cpp
@@ -0,0 +1,1301 @@
+/*
+ * Copyright 2006, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "config.h"
+#include "GraphicsContext.h"
+
+#include "AffineTransform.h"
+#include "Gradient.h"
+#include "NotImplemented.h"
+#include "Path.h"
+#include "Pattern.h"
+#include "PlatformGraphicsContext.h"
+#include "SkBitmapRef.h"
+#include "SkBlurDrawLooper.h"
+#include "SkBlurMaskFilter.h"
+#include "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkDashPathEffect.h"
+#include "SkDevice.h"
+#include "SkGradientShader.h"
+#include "SkPaint.h"
+#include "SkString.h"
+#include "SkiaUtils.h"
+#include "TransformationMatrix.h"
+#include "android_graphics.h"
+
+using namespace std;
+
+#define GC2CANVAS(ctx)  (ctx)->m_data->getPlatformGfxCtx()->mCanvas
+
+namespace WebCore {
+
+static int RoundToInt(float x)
+{
+    return (int)roundf(x);
+}
+
+template <typename T> T* deepCopyPtr(const T* src)
+{
+    return src ? new T(*src) : 0;
+}
+
+// Set a bitmap shader that mimics dashing by width-on, width-off.
+// Returns false if it could not succeed (e.g. there was an existing shader)
+static bool setBitmapDash(SkPaint* paint, int width) {
+    if (width <= 0 || paint->getShader())
+        return false;
+
+    SkColor c = paint->getColor();
+
+    SkBitmap bm;
+    bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 1);
+    bm.allocPixels();
+    bm.lockPixels();
+
+    // set the ON pixel
+    *bm.getAddr32(0, 0) = SkPreMultiplyARGB(0xFF, SkColorGetR(c),
+                                            SkColorGetG(c), SkColorGetB(c));
+    // set the OFF pixel
+    *bm.getAddr32(1, 0) = 0;
+    bm.unlockPixels();
+
+    SkMatrix matrix;
+    matrix.setScale(SkIntToScalar(width), SK_Scalar1);
+
+    SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
+                                               SkShader::kClamp_TileMode);
+    s->setLocalMatrix(matrix);
+
+    paint->setShader(s)->unref();
+    return true;
+}
+
+// TODO / questions
+
+// alpha: how does this interact with the alpha in Color? multiply them together?
+// mode: do I always respect this? If so, then
+// the rgb() & 0xFF000000 check will abort drawing too often
+// Is Color premultiplied or not? If it is, then I can't blindly pass it to paint.setColor()
+
+struct ShadowRec {
+    SkScalar blur;
+    SkScalar dx;
+    SkScalar dy;
+    SkColor color;  // alpha>0 means valid shadow
+    ShadowRec(SkScalar b = 0,
+              SkScalar x = 0,
+              SkScalar y = 0,
+              SkColor c = 0) // by default, alpha=0, so no shadow
+            : blur(b), dx(x), dy(y), color(c)
+        {};
+};
+
+class GraphicsContextPlatformPrivate {
+public:
+    struct State {
+        SkPathEffect* pathEffect;
+        float miterLimit;
+        float alpha;
+        float strokeThickness;
+        SkPaint::Cap lineCap;
+        SkPaint::Join lineJoin;
+        SkXfermode::Mode mode;
+        int dashRatio; // Ratio of the length of a dash to its width
+        ShadowRec shadow;
+        SkColor fillColor;
+        SkColor strokeColor;
+        bool useAA;
+        // This is a list of clipping paths which are currently active, in the
+        // order in which they were pushed.
+        WTF::Vector<SkPath> antiAliasClipPaths;
+
+        State()
+            : pathEffect(0)
+            , miterLimit(4)
+            , alpha(1)
+            , strokeThickness(0) // Same as default in GraphicsContextPrivate.h
+            , lineCap(SkPaint::kDefault_Cap)
+            , lineJoin(SkPaint::kDefault_Join)
+            , mode(SkXfermode::kSrcOver_Mode)
+            , dashRatio(3)
+            , fillColor(SK_ColorBLACK)
+            , strokeColor(SK_ColorBLACK)
+            , useAA(true)
+        {
+        }
+
+        State(const State& other)
+            : pathEffect(other.pathEffect)
+            , miterLimit(other.miterLimit)
+            , alpha(other.alpha)
+            , strokeThickness(other.strokeThickness)
+            , lineCap(other.lineCap)
+            , lineJoin(other.lineJoin)
+            , mode(other.mode)
+            , dashRatio(other.dashRatio)
+            , shadow(other.shadow)
+            , fillColor(other.fillColor)
+            , strokeColor(other.strokeColor)
+            , useAA(other.useAA)
+        {
+            SkSafeRef(pathEffect);
+        }
+
+        ~State()
+        {
+            SkSafeUnref(pathEffect);
+        }
+
+        void setShadow(int radius, int dx, int dy, SkColor c)
+        {
+            // Cut the radius in half, to visually match the effect seen in
+            // safari browser
+            shadow.blur = SkScalarHalf(SkIntToScalar(radius));
+            shadow.dx = SkIntToScalar(dx);
+            shadow.dy = SkIntToScalar(dy);
+            shadow.color = c;
+        }
+
+        bool setupShadowPaint(GraphicsContext* ctx, SkPaint* paint, SkPoint* offset)
+        {
+            paint->setAntiAlias(true);
+            paint->setDither(true);
+            paint->setXfermodeMode(mode);
+            paint->setColor(shadow.color);
+            offset->set(shadow.dx, shadow.dy);
+
+            // Currently, only GraphicsContexts associated with the
+            // HTMLCanvasElement have shadows ignore transforms set.  This
+            // allows us to distinguish between CSS and Canvas shadows which
+            // have different rendering specifications.
+            uint32_t flags = SkBlurMaskFilter::kHighQuality_BlurFlag;
+            if (ctx->shadowsIgnoreTransforms()) {
+                offset->fY = -offset->fY;
+                flags |= SkBlurMaskFilter::kIgnoreTransform_BlurFlag;
+            }
+
+            if (shadow.blur > 0) {
+                paint->setMaskFilter(SkBlurMaskFilter::Create(shadow.blur,
+                                     SkBlurMaskFilter::kNormal_BlurStyle))->unref();
+            }
+            return SkColorGetA(shadow.color) && (shadow.blur || shadow.dx || shadow.dy);
+        }
+
+        SkColor applyAlpha(SkColor c) const
+        {
+            int s = RoundToInt(alpha * 256);
+            if (s >= 256)
+                return c;
+            if (s < 0)
+                return 0;
+
+            int a = SkAlphaMul(SkColorGetA(c), s);
+            return (c & 0x00FFFFFF) | (a << 24);
+        }
+    };
+
+    GraphicsContextPlatformPrivate(GraphicsContext* gfxCtx, PlatformGraphicsContext* platformGfxCtx)
+        : m_parentGfxCtx(gfxCtx)
+        , m_platformGfxCtx(platformGfxCtx)
+        , m_stateStack(sizeof(State))
+    {
+        State* state = static_cast<State*>(m_stateStack.push_back());
+        new (state) State();
+        m_state = state;
+    }
+
+    ~GraphicsContextPlatformPrivate()
+    {
+        // We force restores so we don't leak any subobjects owned by our
+        // stack of State records.
+        while (m_stateStack.count() > 0)
+            this->restore();
+
+        if (m_platformGfxCtx && m_platformGfxCtx->deleteUs())
+            delete m_platformGfxCtx;
+    }
+
+    void save()
+    {
+        State* newState = static_cast<State*>(m_stateStack.push_back());
+        new (newState) State(*m_state);
+        m_state = newState;
+    }
+
+    void restore()
+    {
+        if (!m_state->antiAliasClipPaths.isEmpty())
+            applyAntiAliasedClipPaths(m_state->antiAliasClipPaths);
+
+        m_state->~State();
+        m_stateStack.pop_back();
+        m_state = static_cast<State*>(m_stateStack.back());
+    }
+
+    void setFillColor(const Color& c)
+    {
+        m_state->fillColor = c.rgb();
+    }
+
+    void setStrokeColor(const Color& c)
+    {
+        m_state->strokeColor = c.rgb();
+    }
+
+    void setStrokeThickness(float f)
+    {
+        m_state->strokeThickness = f;
+    }
+
+    void setupPaintCommon(SkPaint* paint) const
+    {
+        paint->setAntiAlias(m_state->useAA);
+        paint->setDither(true);
+        paint->setXfermodeMode(m_state->mode);
+        if (SkColorGetA(m_state->shadow.color) > 0) {
+
+            // Currently, only GraphicsContexts associated with the
+            // HTMLCanvasElement have shadows ignore transforms set.  This
+            // allows us to distinguish between CSS and Canvas shadows which
+            // have different rendering specifications.
+            SkScalar dy = m_state->shadow.dy;
+            uint32_t flags = SkBlurDrawLooper::kHighQuality_BlurFlag;
+            if (m_parentGfxCtx->shadowsIgnoreTransforms()) {
+                dy = -dy;
+                flags |= SkBlurDrawLooper::kIgnoreTransform_BlurFlag;
+                flags |= SkBlurDrawLooper::kOverrideColor_BlurFlag;
+            }
+
+            SkDrawLooper* looper = new SkBlurDrawLooper(m_state->shadow.blur,
+                                                        m_state->shadow.dx,
+                                                        dy,
+                                                        m_state->shadow.color,
+                                                        flags);
+            paint->setLooper(looper)->unref();
+        }
+    }
+
+    void setupPaintFill(SkPaint* paint) const
+    {
+        this->setupPaintCommon(paint);
+        paint->setColor(m_state->applyAlpha(m_state->fillColor));
+    }
+
+    void setupPaintBitmap(SkPaint* paint) const
+    {
+        this->setupPaintCommon(paint);
+        // We only want the global alpha for bitmaps,
+        // so just give applyAlpha opaque black
+        paint->setColor(m_state->applyAlpha(0xFF000000));
+    }
+
+    // Sets up the paint for stroking. Returns true if the style is really
+    // just a dash of squares (the size of the paint's stroke-width.
+    bool setupPaintStroke(SkPaint* paint, SkRect* rect, bool isHLine = false)
+    {
+        this->setupPaintCommon(paint);
+        paint->setColor(m_state->applyAlpha(m_state->strokeColor));
+
+        float width = m_state->strokeThickness;
+
+        // This allows dashing and dotting to work properly for hairline strokes
+        // FIXME: Should we only do this for dashed and dotted strokes?
+        if (!width)
+            width = 1;
+
+        paint->setStyle(SkPaint::kStroke_Style);
+        paint->setStrokeWidth(SkFloatToScalar(width));
+        paint->setStrokeCap(m_state->lineCap);
+        paint->setStrokeJoin(m_state->lineJoin);
+        paint->setStrokeMiter(SkFloatToScalar(m_state->miterLimit));
+
+        if (rect && (RoundToInt(width) & 1))
+            rect->inset(-SK_ScalarHalf, -SK_ScalarHalf);
+
+        SkPathEffect* pe = m_state->pathEffect;
+        if (pe) {
+            paint->setPathEffect(pe);
+            return false;
+        }
+        switch (m_parentGfxCtx->strokeStyle()) {
+        case NoStroke:
+        case SolidStroke:
+            width = 0;
+            break;
+        case DashedStroke:
+            width = m_state->dashRatio * width;
+            break;
+            // No break
+        case DottedStroke:
+            break;
+        }
+
+        if (width > 0) {
+            // Return true if we're basically a dotted dash of squares
+            bool justSqrs = RoundToInt(width) == RoundToInt(paint->getStrokeWidth());
+
+            if (justSqrs || !isHLine || !setBitmapDash(paint, width)) {
+#if 0
+                // this is slow enough that we just skip it for now
+                // see http://b/issue?id=4163023
+                SkScalar intervals[] = { width, width };
+                pe = new SkDashPathEffect(intervals, 2, 0);
+                paint->setPathEffect(pe)->unref();
+#endif
+            }
+            return justSqrs;
+        }
+        return false;
+    }
+
+    void clipPathAntiAliased(const SkPath& clipPath)
+    {
+        // If we are currently tracking any anti-alias clip paths, then we already
+        // have a layer in place and don't need to add another.
+        bool haveLayerOutstanding = m_state->antiAliasClipPaths.size();
+
+        // See comments in applyAntiAliasedClipPaths about how this works.
+        m_state->antiAliasClipPaths.append(clipPath);
+        if (!haveLayerOutstanding) {
+            SkRect bounds = clipPath.getBounds();
+            if (m_platformGfxCtx && m_platformGfxCtx->mCanvas) {
+                m_platformGfxCtx->mCanvas->saveLayerAlpha(&bounds, 255,
+                    static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag
+                        | SkCanvas::kFullColorLayer_SaveFlag
+                        | SkCanvas::kClipToLayer_SaveFlag));
+                m_platformGfxCtx->mCanvas->save();
+            } else
+                ASSERT(0);
+        }
+    }
+
+    void applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths)
+    {
+        // Anti-aliased clipping:
+        //
+        // Refer to PlatformContextSkia.cpp's applyAntiAliasedClipPaths() for more details
+
+        if (m_platformGfxCtx && m_platformGfxCtx->mCanvas)
+            m_platformGfxCtx->mCanvas->restore();
+
+        SkPaint paint;
+        paint.setXfermodeMode(SkXfermode::kClear_Mode);
+        paint.setAntiAlias(true);
+        paint.setStyle(SkPaint::kFill_Style);
+
+        if (m_platformGfxCtx && m_platformGfxCtx->mCanvas)  {
+            for (size_t i = paths.size() - 1; i < paths.size(); --i) {
+                paths[i].setFillType(SkPath::kInverseWinding_FillType);
+                m_platformGfxCtx->mCanvas->drawPath(paths[i], paint);
+            }
+            m_platformGfxCtx->mCanvas->restore();
+        } else
+            ASSERT(0);
+    }
+
+    PlatformGraphicsContext* getPlatformGfxCtx()
+    {
+        return m_platformGfxCtx;
+    }
+
+    State* getState()
+    {
+        return m_state;
+    }
+private:
+    State* m_state;
+    GraphicsContext* m_parentGfxCtx; // Back-ptr to our parent
+    PlatformGraphicsContext* m_platformGfxCtx;
+    SkDeque m_stateStack;
+    // Not supported yet
+    State& operator=(const State&);
+};
+
+static SkShader::TileMode SpreadMethod2TileMode(GradientSpreadMethod sm)
+{
+    SkShader::TileMode mode = SkShader::kClamp_TileMode;
+
+    switch (sm) {
+    case SpreadMethodPad:
+        mode = SkShader::kClamp_TileMode;
+        break;
+    case SpreadMethodReflect:
+        mode = SkShader::kMirror_TileMode;
+        break;
+    case SpreadMethodRepeat:
+        mode = SkShader::kRepeat_TileMode;
+        break;
+    }
+    return mode;
+}
+
+static void extactShader(SkPaint* paint, Pattern* pat, Gradient* grad)
+{
+    if (pat) {
+        // platformPattern() returns a cached obj
+        paint->setShader(pat->platformPattern(AffineTransform()));
+    } else if (grad) {
+        // grad->getShader() returns a cached obj
+        GradientSpreadMethod sm = grad->spreadMethod();
+        paint->setShader(grad->getShader(SpreadMethod2TileMode(sm)));
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+GraphicsContext* GraphicsContext::createOffscreenContext(int width, int height)
+{
+    PlatformGraphicsContext* pgc = new PlatformGraphicsContext();
+
+    SkBitmap bitmap;
+
+    bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
+    bitmap.allocPixels();
+    bitmap.eraseColor(0);
+    pgc->mCanvas->setBitmapDevice(bitmap);
+
+    GraphicsContext* ctx = new GraphicsContext(pgc);
+    return ctx;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+void GraphicsContext::platformInit(PlatformGraphicsContext* gc)
+{
+    m_data = new GraphicsContextPlatformPrivate(this, gc);
+    setPaintingDisabled(!gc || !gc->mCanvas);
+}
+
+void GraphicsContext::platformDestroy()
+{
+    delete m_data;
+}
+
+void GraphicsContext::savePlatformState()
+{
+    // Save our private State
+    m_data->save();
+    // Save our native canvas
+    GC2CANVAS(this)->save();
+}
+
+void GraphicsContext::restorePlatformState()
+{
+    // Restore our private State
+    m_data->restore();
+    // Restore our native canvas
+    GC2CANVAS(this)->restore();
+}
+
+bool GraphicsContext::willFill() const
+{
+    return m_data->getState()->fillColor;
+}
+
+bool GraphicsContext::willStroke() const
+{
+    return m_data->getState()->strokeColor;
+}
+
+// Draws a filled rectangle with a stroked border.
+void GraphicsContext::drawRect(const IntRect& rect)
+{
+    if (paintingDisabled())
+        return;
+
+    SkPaint paint;
+    SkRect r(rect);
+
+    if (fillColor().alpha()) {
+        m_data->setupPaintFill(&paint);
+        GC2CANVAS(this)->drawRect(r, paint);
+    }
+
+    // According to GraphicsContext.h, stroking inside drawRect always means
+    // a stroke of 1 inside the rect.
+    if (strokeStyle() != NoStroke && strokeColor().alpha()) {
+        paint.reset();
+        m_data->setupPaintStroke(&paint, &r);
+        paint.setPathEffect(0); // No dashing please
+        paint.setStrokeWidth(SK_Scalar1); // Always just 1.0 width
+        r.inset(SK_ScalarHalf, SK_ScalarHalf); // Ensure we're "inside"
+        GC2CANVAS(this)->drawRect(r, paint);
+    }
+}
+
+// This is only used to draw borders.
+void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
+{
+    if (paintingDisabled())
+        return;
+
+    StrokeStyle style = strokeStyle();
+    if (style == NoStroke)
+        return;
+
+    SkPaint paint;
+    SkCanvas* canvas = GC2CANVAS(this);
+    const int idx = SkAbs32(point2.x() - point1.x());
+    const int idy = SkAbs32(point2.y() - point1.y());
+
+    // Special-case horizontal and vertical lines that are really just dots
+    if (m_data->setupPaintStroke(&paint, 0, !idy) && (!idx || !idy)) {
+        const SkScalar diameter = paint.getStrokeWidth();
+        const SkScalar radius = SkScalarHalf(diameter);
+        SkScalar x = SkIntToScalar(SkMin32(point1.x(), point2.x()));
+        SkScalar y = SkIntToScalar(SkMin32(point1.y(), point2.y()));
+        SkScalar dx, dy;
+        int count;
+        SkRect bounds;
+
+        if (!idy) { // Horizontal
+            bounds.set(x, y - radius, x + SkIntToScalar(idx), y + radius);
+            x += radius;
+            dx = diameter * 2;
+            dy = 0;
+            count = idx;
+        } else { // Vertical
+            bounds.set(x - radius, y, x + radius, y + SkIntToScalar(idy));
+            y += radius;
+            dx = 0;
+            dy = diameter * 2;
+            count = idy;
+        }
+
+        // The actual count is the number of ONs we hit alternating
+        // ON(diameter), OFF(diameter), ...
+        {
+            SkScalar width = SkScalarDiv(SkIntToScalar(count), diameter);
+            // Now compute the number of cells (ON and OFF)
+            count = SkScalarRound(width);
+            // Now compute the number of ONs
+            count = (count + 1) >> 1;
+        }
+
+        SkAutoMalloc storage(count * sizeof(SkPoint));
+        SkPoint* verts = (SkPoint*)storage.get();
+        // Now build the array of vertices to past to drawPoints
+        for (int i = 0; i < count; i++) {
+            verts[i].set(x, y);
+            x += dx;
+            y += dy;
+        }
+
+        paint.setStyle(SkPaint::kFill_Style);
+        paint.setPathEffect(0);
+
+        // Clipping to bounds is not required for correctness, but it does
+        // allow us to reject the entire array of points if we are completely
+        // offscreen. This is common in a webpage for android, where most of
+        // the content is clipped out. If drawPoints took an (optional) bounds
+        // parameter, that might even be better, as we would *just* use it for
+        // culling, and not both wacking the canvas' save/restore stack.
+        canvas->save(SkCanvas::kClip_SaveFlag);
+        canvas->clipRect(bounds);
+        canvas->drawPoints(SkCanvas::kPoints_PointMode, count, verts, paint);
+        canvas->restore();
+    } else {
+        SkPoint pts[2] = { point1, point2 };
+        canvas->drawLine(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, paint);
+    }
+}
+
+static void setrectForUnderline(SkRect* r, GraphicsContext* context, const FloatPoint& point, int yOffset, float width)
+{
+    float lineThickness = context->strokeThickness();
+#if 0
+    if (lineThickness < 1) // Do we really need/want this?
+        lineThickness = 1;
+#endif
+    r->fLeft    = point.x();
+    r->fTop     = point.y() + yOffset;
+    r->fRight   = r->fLeft + width;
+    r->fBottom  = r->fTop + lineThickness;
+}
+
+void GraphicsContext::drawLineForText(const FloatPoint& pt, float width, bool)
+{
+    if (paintingDisabled())
+        return;
+
+    SkRect r;
+    setrectForUnderline(&r, this, pt, 0, width);
+
+    SkPaint paint;
+    paint.setAntiAlias(true);
+    paint.setColor(this->strokeColor().rgb());
+
+    GC2CANVAS(this)->drawRect(r, paint);
+}
+
+// TODO: Should we draw different based on TextCheckingLineStyle?
+void GraphicsContext::drawLineForTextChecking(const FloatPoint& pt, float width, TextCheckingLineStyle)
+{
+    if (paintingDisabled())
+        return;
+
+    SkRect r;
+    setrectForUnderline(&r, this, pt, 0, width);
+
+    SkPaint paint;
+    paint.setAntiAlias(true);
+    paint.setColor(SK_ColorRED); // Is this specified somewhere?
+
+    GC2CANVAS(this)->drawRect(r, paint);
+}
+
+// This method is only used to draw the little circles used in lists.
+void GraphicsContext::drawEllipse(const IntRect& rect)
+{
+    if (paintingDisabled())
+        return;
+
+    SkPaint paint;
+    SkRect oval(rect);
+
+    if (fillColor().rgb() & 0xFF000000) {
+        m_data->setupPaintFill(&paint);
+        GC2CANVAS(this)->drawOval(oval, paint);
+    }
+    if (strokeStyle() != NoStroke) {
+        paint.reset();
+        m_data->setupPaintStroke(&paint, &oval);
+        GC2CANVAS(this)->drawOval(oval, paint);
+    }
+}
+
+static inline int fastMod(int value, int max)
+{
+    int sign = SkExtractSign(value);
+
+    value = SkApplySign(value, sign);
+    if (value >= max)
+        value %= max;
+    return SkApplySign(value, sign);
+}
+
+void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan)
+{
+    if (paintingDisabled())
+        return;
+
+    SkPath path;
+    SkPaint paint;
+    SkRect oval(r);
+
+    if (strokeStyle() == NoStroke) {
+        m_data->setupPaintFill(&paint); // We want the fill color
+        paint.setStyle(SkPaint::kStroke_Style);
+        paint.setStrokeWidth(SkFloatToScalar(this->strokeThickness()));
+    } else
+        m_data->setupPaintStroke(&paint, 0);
+
+    // We do this before converting to scalar, so we don't overflow SkFixed
+    startAngle = fastMod(startAngle, 360);
+    angleSpan = fastMod(angleSpan, 360);
+
+    path.addArc(oval, SkIntToScalar(-startAngle), SkIntToScalar(-angleSpan));
+    GC2CANVAS(this)->drawPath(path, paint);
+}
+
+void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias)
+{
+    if (paintingDisabled())
+        return;
+
+    if (numPoints <= 1)
+        return;
+
+    SkPaint paint;
+    SkPath path;
+
+    path.incReserve(numPoints);
+    path.moveTo(SkFloatToScalar(points[0].x()), SkFloatToScalar(points[0].y()));
+    for (size_t i = 1; i < numPoints; i++)
+        path.lineTo(SkFloatToScalar(points[i].x()), SkFloatToScalar(points[i].y()));
+
+    if (GC2CANVAS(this)->quickReject(path, shouldAntialias ?
+            SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType)) {
+        return;
+    }
+
+    if (fillColor().rgb() & 0xFF000000) {
+        m_data->setupPaintFill(&paint);
+        paint.setAntiAlias(shouldAntialias);
+        GC2CANVAS(this)->drawPath(path, paint);
+    }
+
+    if (strokeStyle() != NoStroke) {
+        paint.reset();
+        m_data->setupPaintStroke(&paint, 0);
+        paint.setAntiAlias(shouldAntialias);
+        GC2CANVAS(this)->drawPath(path, paint);
+    }
+}
+
+void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
+                                      const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace)
+{
+    if (paintingDisabled())
+        return;
+
+    SkPaint paint;
+    SkPath path;
+    SkScalar radii[8];
+
+    radii[0] = SkIntToScalar(topLeft.width());
+    radii[1] = SkIntToScalar(topLeft.height());
+    radii[2] = SkIntToScalar(topRight.width());
+    radii[3] = SkIntToScalar(topRight.height());
+    radii[4] = SkIntToScalar(bottomRight.width());
+    radii[5] = SkIntToScalar(bottomRight.height());
+    radii[6] = SkIntToScalar(bottomLeft.width());
+    radii[7] = SkIntToScalar(bottomLeft.height());
+    path.addRoundRect(rect, radii);
+
+    m_data->setupPaintFill(&paint);
+    paint.setColor(color.rgb());
+    GC2CANVAS(this)->drawPath(path, paint);
+}
+
+void GraphicsContext::fillRect(const FloatRect& rect)
+{
+    save();
+    SkPaint paint;
+
+    m_data->setupPaintFill(&paint);
+
+    extactShader(&paint,
+                 m_state.fillPattern.get(),
+                 m_state.fillGradient.get());
+
+    GC2CANVAS(this)->drawRect(rect, paint);
+    restore();
+}
+
+void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace)
+{
+    if (paintingDisabled())
+        return;
+
+    if (color.rgb() & 0xFF000000) {
+        save();
+        SkPaint paint;
+
+        m_data->setupPaintCommon(&paint);
+        paint.setColor(color.rgb()); // Punch in the specified color
+        paint.setShader(0); // In case we had one set
+
+        // Sometimes we record and draw portions of the page, using clips
+        // for each portion. The problem with this is that webkit, sometimes,
+        // sees that we're only recording a portion, and they adjust some of
+        // their rectangle coordinates accordingly (e.g.
+        // RenderBoxModelObject::paintFillLayerExtended() which calls
+        // rect.intersect(paintInfo.rect) and then draws the bg with that
+        // rect. The result is that we end up drawing rects that are meant to
+        // seam together (one for each portion), but if the rects have
+        // fractional coordinates (e.g. we are zoomed by a fractional amount)
+        // we will double-draw those edges, resulting in visual cracks or
+        // artifacts.
+
+        // The fix seems to be to just turn off antialasing for rects (this
+        // entry-point in GraphicsContext seems to have been sufficient,
+        // though perhaps we'll find we need to do this as well in fillRect(r)
+        // as well.) Currently setupPaintCommon() enables antialiasing.
+
+        // Since we never show the page rotated at a funny angle, disabling
+        // antialiasing seems to have no real down-side, and it does fix the
+        // bug when we're zoomed (and drawing portions that need to seam).
+        paint.setAntiAlias(false);
+
+        GC2CANVAS(this)->drawRect(rect, paint);
+        restore();
+    }
+}
+
+void GraphicsContext::clip(const FloatRect& rect)
+{
+    if (paintingDisabled())
+        return;
+
+    GC2CANVAS(this)->clipRect(rect);
+}
+
+void GraphicsContext::clip(const Path& path)
+{
+    if (paintingDisabled())
+        return;
+
+    m_data->clipPathAntiAliased(*path.platformPath());
+}
+
+void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
+{
+    if (paintingDisabled())
+        return;
+
+    SkPath path;
+    SkRect r(rect);
+
+    path.addOval(r, SkPath::kCW_Direction);
+    // Only perform the inset if we won't invert r
+    if (2 * thickness < rect.width() && 2 * thickness < rect.height()) {
+        // Adding one to the thickness doesn't make the border too thick as
+        // it's painted over afterwards. But without this adjustment the
+        // border appears a little anemic after anti-aliasing.
+        r.inset(SkIntToScalar(thickness + 1), SkIntToScalar(thickness + 1));
+        path.addOval(r, SkPath::kCCW_Direction);
+    }
+    m_data->clipPathAntiAliased(path);
+}
+
+void GraphicsContext::canvasClip(const Path& path)
+{
+    clip(path);
+}
+
+void GraphicsContext::clipOut(const IntRect& r)
+{
+    if (paintingDisabled())
+        return;
+
+    GC2CANVAS(this)->clipRect(r, SkRegion::kDifference_Op);
+}
+
+#if ENABLE(SVG)
+void GraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule)
+{
+    if (paintingDisabled())
+        return;
+
+    SkPath path = *pathToClip.platformPath();
+    path.setFillType(clipRule == RULE_EVENODD ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
+    GC2CANVAS(this)->clipPath(path);
+}
+#endif
+
+void GraphicsContext::clipOut(const Path& p)
+{
+    if (paintingDisabled())
+        return;
+
+    GC2CANVAS(this)->clipPath(*p.platformPath(), SkRegion::kDifference_Op);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+#if SVG_SUPPORT
+KRenderingDeviceContext* GraphicsContext::createRenderingDeviceContext()
+{
+    return new KRenderingDeviceContextQuartz(platformContext());
+}
+#endif
+
+// These are the flags we need when we call saveLayer for transparency.
+// Since it does not appear that webkit intends this to also save/restore
+// the matrix or clip, I do not give those flags (for performance)
+#define TRANSPARENCY_SAVEFLAGS                                  \
+    (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag |   \
+                          SkCanvas::kFullColorLayer_SaveFlag)
+
+void GraphicsContext::beginTransparencyLayer(float opacity)
+{
+    if (paintingDisabled())
+        return;
+
+    SkCanvas* canvas = GC2CANVAS(this);
+    canvas->saveLayerAlpha(0, (int)(opacity * 255), TRANSPARENCY_SAVEFLAGS);
+}
+
+void GraphicsContext::endTransparencyLayer()
+{
+    if (paintingDisabled())
+        return;
+
+    GC2CANVAS(this)->restore();
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+void GraphicsContext::setupBitmapPaint(SkPaint* paint)
+{
+    m_data->setupPaintBitmap(paint);
+}
+
+void GraphicsContext::setupFillPaint(SkPaint* paint)
+{
+    m_data->setupPaintFill(paint);
+}
+
+void GraphicsContext::setupStrokePaint(SkPaint* paint)
+{
+    m_data->setupPaintStroke(paint, 0);
+}
+
+bool GraphicsContext::setupShadowPaint(SkPaint* paint, SkPoint* offset)
+{
+    return m_data->getState()->setupShadowPaint(this, paint, offset);
+}
+
+void GraphicsContext::setPlatformStrokeColor(const Color& c, ColorSpace)
+{
+    m_data->setStrokeColor(c);
+}
+
+void GraphicsContext::setPlatformStrokeThickness(float f)
+{
+    m_data->setStrokeThickness(f);
+}
+
+void GraphicsContext::setPlatformFillColor(const Color& c, ColorSpace)
+{
+    m_data->setFillColor(c);
+}
+
+void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const Color& color, ColorSpace)
+{
+    if (paintingDisabled())
+        return;
+
+    if (blur <= 0)
+        this->clearPlatformShadow();
+
+    SkColor c;
+    if (color.isValid())
+        c = color.rgb();
+    else
+        c = SkColorSetARGB(0xFF / 3, 0, 0, 0); // "std" Apple shadow color
+    m_data->getState()->setShadow(blur, size.width(), size.height(), c);
+}
+
+void GraphicsContext::clearPlatformShadow()
+{
+    if (paintingDisabled())
+        return;
+
+    m_data->getState()->setShadow(0, 0, 0, 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void GraphicsContext::drawFocusRing(const Vector<IntRect>&, int, int, const Color&)
+{
+    // Do nothing, since we draw the focus ring independently.
+}
+
+void GraphicsContext::drawFocusRing(const Path&, int, int, const Color&)
+{
+    // Do nothing, since we draw the focus ring independently.
+}
+
+PlatformGraphicsContext* GraphicsContext::platformContext() const
+{
+    ASSERT(!paintingDisabled());
+    return m_data->getPlatformGfxCtx();
+}
+
+void GraphicsContext::setMiterLimit(float limit)
+{
+    m_data->getState()->miterLimit = limit;
+}
+
+void GraphicsContext::setAlpha(float alpha)
+{
+    m_data->getState()->alpha = alpha;
+}
+
+void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op)
+{
+    m_data->getState()->mode = WebCoreCompositeToSkiaComposite(op);
+}
+
+void GraphicsContext::clearRect(const FloatRect& rect)
+{
+    if (paintingDisabled())
+        return;
+
+    SkPaint paint;
+
+    m_data->setupPaintFill(&paint);
+    paint.setXfermodeMode(SkXfermode::kClear_Mode);
+    GC2CANVAS(this)->drawRect(rect, paint);
+}
+
+void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
+{
+    if (paintingDisabled())
+        return;
+
+    SkPaint paint;
+
+    m_data->setupPaintStroke(&paint, 0);
+    paint.setStrokeWidth(SkFloatToScalar(lineWidth));
+    GC2CANVAS(this)->drawRect(rect, paint);
+}
+
+void GraphicsContext::setLineCap(LineCap cap)
+{
+    switch (cap) {
+    case ButtCap:
+        m_data->getState()->lineCap = SkPaint::kButt_Cap;
+        break;
+    case RoundCap:
+        m_data->getState()->lineCap = SkPaint::kRound_Cap;
+        break;
+    case SquareCap:
+        m_data->getState()->lineCap = SkPaint::kSquare_Cap;
+        break;
+    default:
+        SkDEBUGF(("GraphicsContext::setLineCap: unknown LineCap %d\n", cap));
+        break;
+    }
+}
+
+#if ENABLE(SVG)
+void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
+{
+    if (paintingDisabled())
+        return;
+
+    size_t dashLength = dashes.size();
+    if (!dashLength)
+        return;
+
+    size_t count = !(dashLength % 2) ? dashLength : dashLength * 2;
+    SkScalar* intervals = new SkScalar[count];
+
+    for (unsigned int i = 0; i < count; i++)
+        intervals[i] = SkFloatToScalar(dashes[i % dashLength]);
+    SkPathEffect **effectPtr = &m_data->getState()->pathEffect;
+    SkSafeUnref(*effectPtr);
+    *effectPtr = new SkDashPathEffect(intervals, count, SkFloatToScalar(dashOffset));
+
+    delete[] intervals;
+}
+#endif
+
+void GraphicsContext::setLineJoin(LineJoin join)
+{
+    switch (join) {
+    case MiterJoin:
+        m_data->getState()->lineJoin = SkPaint::kMiter_Join;
+        break;
+    case RoundJoin:
+        m_data->getState()->lineJoin = SkPaint::kRound_Join;
+        break;
+    case BevelJoin:
+        m_data->getState()->lineJoin = SkPaint::kBevel_Join;
+        break;
+    default:
+        SkDEBUGF(("GraphicsContext::setLineJoin: unknown LineJoin %d\n", join));
+        break;
+    }
+}
+
+void GraphicsContext::scale(const FloatSize& size)
+{
+    if (paintingDisabled())
+        return;
+    GC2CANVAS(this)->scale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height()));
+}
+
+void GraphicsContext::rotate(float angleInRadians)
+{
+    if (paintingDisabled())
+        return;
+    GC2CANVAS(this)->rotate(SkFloatToScalar(angleInRadians * (180.0f / 3.14159265f)));
+}
+
+void GraphicsContext::translate(float x, float y)
+{
+    if (paintingDisabled())
+        return;
+    GC2CANVAS(this)->translate(SkFloatToScalar(x), SkFloatToScalar(y));
+}
+
+void GraphicsContext::concatCTM(const AffineTransform& affine)
+{
+    if (paintingDisabled())
+        return;
+    GC2CANVAS(this)->concat(affine);
+}
+
+// This is intended to round the rect to device pixels (through the CTM)
+// and then invert the result back into source space, with the hope that when
+// it is drawn (through the matrix), it will land in the "right" place (i.e.
+// on pixel boundaries).
+
+// For android, we record this geometry once and then draw it though various
+// scale factors as the user zooms, without re-recording. Thus this routine
+// should just leave the original geometry alone.
+
+// If we instead draw into bitmap tiles, we should then perform this
+// transform -> round -> inverse step.
+
+FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect, RoundingMode)
+{
+    return rect;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+
+void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
+{
+// Appears to be PDF specific, so we ignore it
+#if 0
+if (paintingDisabled())
+    return;
+
+CFURLRef urlRef = link.createCFURL();
+if (urlRef) {
+    CGContextRef context = platformContext();
+
+    // Get the bounding box to handle clipping.
+    CGRect box = CGContextGetClipBoundingBox(context);
+
+    IntRect intBox((int)box.origin.x, (int)box.origin.y, (int)box.size.width, (int)box.size.height);
+    IntRect rect = destRect;
+    rect.intersect(intBox);
+
+    CGPDFContextSetURLForRect(context, urlRef,
+        CGRectApplyAffineTransform(rect, CGContextGetCTM(context)));
+
+    CFRelease(urlRef);
+}
+#endif
+}
+
+void GraphicsContext::setPlatformShouldAntialias(bool useAA)
+{
+    if (paintingDisabled())
+        return;
+    m_data->getState()->useAA = useAA;
+}
+
+AffineTransform GraphicsContext::getCTM() const
+{
+    const SkMatrix& m = GC2CANVAS(this)->getTotalMatrix();
+    return AffineTransform(SkScalarToDouble(m.getScaleX()), // a
+                           SkScalarToDouble(m.getSkewY()), // b
+                           SkScalarToDouble(m.getSkewX()), // c
+                           SkScalarToDouble(m.getScaleY()), // d
+                           SkScalarToDouble(m.getTranslateX()), // e
+                           SkScalarToDouble(m.getTranslateY())); // f
+}
+
+void GraphicsContext::setCTM(const AffineTransform& transform)
+{
+    // The SkPicture mode of Skia does not support SkCanvas::setMatrix(), so we
+    // can not simply use that method here. We could calculate the transform
+    // required to achieve the desired matrix and use SkCanvas::concat(), but
+    // there's currently no need for this.
+    ASSERT_NOT_REACHED();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void GraphicsContext::fillPath(const Path& pathToFill)
+{
+    SkPath* path = pathToFill.platformPath();
+    if (paintingDisabled() || !path)
+        return;
+
+    switch (this->fillRule()) {
+    case RULE_NONZERO:
+        path->setFillType(SkPath::kWinding_FillType);
+        break;
+    case RULE_EVENODD:
+        path->setFillType(SkPath::kEvenOdd_FillType);
+        break;
+    }
+
+    SkPaint paint;
+    m_data->setupPaintFill(&paint);
+
+    extactShader(&paint,
+                 m_state.fillPattern.get(),
+                 m_state.fillGradient.get());
+
+    GC2CANVAS(this)->drawPath(*path, paint);
+}
+
+void GraphicsContext::strokePath(const Path& pathToStroke)
+{
+    const SkPath* path = pathToStroke.platformPath();
+    if (paintingDisabled() || !path)
+        return;
+
+    SkPaint paint;
+    m_data->setupPaintStroke(&paint, 0);
+
+    extactShader(&paint,
+                 m_state.strokePattern.get(),
+                 m_state.strokeGradient.get());
+
+    GC2CANVAS(this)->drawPath(*path, paint);
+}
+
+InterpolationQuality GraphicsContext::imageInterpolationQuality() const
+{
+    notImplemented();
+    return InterpolationDefault;
+}
+
+void GraphicsContext::setImageInterpolationQuality(InterpolationQuality mode)
+{
+#if 0
+    enum InterpolationQuality {
+        InterpolationDefault,
+        InterpolationNone,
+        InterpolationLow,
+        InterpolationMedium,
+        InterpolationHigh
+    };
+#endif
+    // TODO: record this, so we can know when to use bitmap-filtering when we draw
+    // ... not sure how meaningful this will be given our playback model.
+
+    // Certainly safe to do nothing for the present.
+}
+
+void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias)
+{
+    if (paintingDisabled())
+        return;
+
+    if (numPoints <= 1)
+        return;
+
+    // FIXME: IMPLEMENT!
+}
+
+} // namespace WebCore
+
+///////////////////////////////////////////////////////////////////////////////
+
+SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc)
+{
+    return gc->platformContext()->mCanvas;
+}
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
index 779dba5..567b54b 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
@@ -14,35 +14,22 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "GraphicsLayerAndroid"
-#define LOG_NDEBUG 1
-
 #include "config.h"
 #include "GraphicsLayerAndroid.h"
 
 #if USE(ACCELERATED_COMPOSITING)
 
 #include "AndroidAnimation.h"
-#include "AndroidLog.h"
 #include "Animation.h"
-#include "BaseLayerAndroid.h"
-#include "CachedImage.h"
-#include "CanvasLayer.h"
-#include "FixedBackgroundLayerAndroid.h"
-#include "FixedPositioning.h"
 #include "FloatRect.h"
 #include "GraphicsContext.h"
-#include "IFrameContentLayerAndroid.h"
-#include "IFrameLayerAndroid.h"
 #include "Image.h"
 #include "ImagesManager.h"
 #include "Layer.h"
-#include "LayerAndroid.h"
 #include "Length.h"
 #include "MediaLayer.h"
-#include "PictureLayerContent.h"
 #include "PlatformBridge.h"
-#include "PlatformGraphicsContextSkia.h"
+#include "PlatformGraphicsContext.h"
 #include "RenderLayerBacking.h"
 #include "RenderView.h"
 #include "RotateTransformOperation.h"
@@ -50,13 +37,26 @@
 #include "ScrollableLayerAndroid.h"
 #include "SkCanvas.h"
 #include "SkRegion.h"
-#include "StyleCachedImage.h"
 #include "TransformationMatrix.h"
 #include "TranslateTransformOperation.h"
 
+#include <cutils/log.h>
 #include <wtf/CurrentTime.h>
 #include <wtf/text/CString.h>
 
+#undef LOG
+#define LOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
+#define MLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
+#define TLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GraphicsLayer", __VA_ARGS__)
+
+#undef LOG
+#define LOG(...)
+#undef MLOG
+#define MLOG(...)
+#undef TLOG
+#define TLOG(...)
+#undef LAYER_DEBUG
+
 using namespace std;
 
 static bool gPaused;
@@ -91,6 +91,22 @@
     return new GraphicsLayerAndroid(client);
 }
 
+SkLength convertLength(Length len)
+{
+    SkLength length;
+    length.type = SkLength::Undefined;
+    length.value = 0;
+    if (len.type() == WebCore::Percent) {
+        length.type = SkLength::Percent;
+        length.value = len.percent();
+    }
+    if (len.type() == WebCore::Fixed) {
+        length.type = SkLength::Fixed;
+        length.value = len.value();
+    }
+    return length;
+}
+
 static RenderLayer* renderLayerFromClient(GraphicsLayerClient* client)
 {
     return client ? client->owningLayer() : 0;
@@ -105,16 +121,11 @@
     m_haveContents(false),
     m_newImage(false),
     m_image(0),
-    m_fixedBackgroundLayer(0),
     m_foregroundLayer(0),
     m_foregroundClipLayer(0)
 {
     RenderLayer* renderLayer = renderLayerFromClient(m_client);
-    if (renderLayer && renderLayer->renderer()->isCanvas()) {
-        m_contentLayer = new CanvasLayer(renderLayer,
-                static_cast<HTMLCanvasElement*>(renderLayer->renderer()->node()));
-    } else
-        m_contentLayer = new LayerAndroid(renderLayer);
+    m_contentLayer = new LayerAndroid(renderLayer);
     m_dirtyRegion.setEmpty();
     gDebugGraphicsLayerAndroidInstances++;
 }
@@ -124,8 +135,7 @@
     if (m_image)
         m_image->deref();
 
-    SkSafeUnref(m_contentLayer);
-    SkSafeUnref(m_fixedBackgroundLayer);
+    m_contentLayer->unref();
     SkSafeUnref(m_foregroundLayer);
     SkSafeUnref(m_foregroundClipLayer);
     gDebugGraphicsLayerAndroidInstances--;
@@ -138,7 +148,7 @@
 
 NativeLayer GraphicsLayerAndroid::nativeLayer() const
 {
-    ALOGV("(%x) nativeLayer", this);
+    LOG("(%x) nativeLayer", this);
     return 0;
 }
 
@@ -157,7 +167,7 @@
 {
 #ifndef NDEBUG
     const String& name = childLayer->name();
-    ALOGV("(%x) addChild: %x (%s)", this, childLayer, name.ascii().data());
+    LOG("(%x) addChild: %x (%s)", this, childLayer, name.latin1().data());
 #endif
     GraphicsLayer::addChild(childLayer);
     m_needsSyncChildren = true;
@@ -166,7 +176,7 @@
 
 void GraphicsLayerAndroid::addChildAtIndex(GraphicsLayer* childLayer, int index)
 {
-    ALOGV("(%x) addChild %x AtIndex %d", this, childLayer, index);
+    LOG("(%x) addChild %x AtIndex %d", this, childLayer, index);
     GraphicsLayer::addChildAtIndex(childLayer, index);
     m_needsSyncChildren = true;
     askForSync();
@@ -174,7 +184,7 @@
 
 void GraphicsLayerAndroid::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
 {
-    ALOGV("(%x) addChild %x Below %x", this, childLayer, sibling);
+    LOG("(%x) addChild %x Below %x", this, childLayer, sibling);
     GraphicsLayer::addChildBelow(childLayer, sibling);
     m_needsSyncChildren = true;
     askForSync();
@@ -182,7 +192,7 @@
 
 void GraphicsLayerAndroid::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
 {
-    ALOGV("(%x) addChild %x Above %x", this, childLayer, sibling);
+    LOG("(%x) addChild %x Above %x", this, childLayer, sibling);
     GraphicsLayer::addChildAbove(childLayer, sibling);
     m_needsSyncChildren = true;
     askForSync();
@@ -190,7 +200,7 @@
 
 bool GraphicsLayerAndroid::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
 {
-    ALOGV("(%x) replaceChild %x by %x", this, oldChild, newChild);
+    LOG("(%x) replaceChild %x by %x", this, oldChild, newChild);
     bool ret = GraphicsLayer::replaceChild(oldChild, newChild);
     if (ret) {
         m_needsSyncChildren = true;
@@ -199,25 +209,9 @@
     return ret;
 }
 
-void GraphicsLayerAndroid::setReplicatedLayer(GraphicsLayer* layer)
-{
-    GraphicsLayer::setReplicatedLayer(layer);
-    if (m_replicatedLayer) {
-        GraphicsLayerAndroid* graphicsLayer = static_cast<GraphicsLayerAndroid*>(m_replicatedLayer);
-        if (graphicsLayer->m_contentLayer)
-            graphicsLayer->m_contentLayer->setReplicatedLayer(m_contentLayer);
-        if (maskLayer()) {
-            GraphicsLayerAndroid* maskLayer = static_cast<GraphicsLayerAndroid*>(GraphicsLayer::maskLayer());
-            m_contentLayer->setMaskLayer(maskLayer->m_contentLayer);
-        }
-        m_contentLayer->setReplicatedLayerPosition(replicatedLayerPosition());
-        askForSync();
-    }
-}
-
 void GraphicsLayerAndroid::removeFromParent()
 {
-    ALOGV("(%x) removeFromParent()", this);
+    LOG("(%x) removeFromParent()", this);
     GraphicsLayerAndroid* parent = static_cast<GraphicsLayerAndroid*>(m_parent);
     GraphicsLayer::removeFromParent();
     // Update the parent's children.
@@ -227,7 +221,7 @@
     }
 }
 
-void GraphicsLayerAndroid::updatePositionedLayers()
+void GraphicsLayerAndroid::updateFixedPosition()
 {
     RenderLayer* renderLayer = renderLayerFromClient(m_client);
     if (!renderLayer)
@@ -238,28 +232,23 @@
         return;
 
     // We will need the Iframe flag in the LayerAndroid tree for fixed position
-    if (view->isRenderIFrame() && !m_contentLayer->isIFrame()) {
-        LayerAndroid* layer = new IFrameLayerAndroid(*m_contentLayer);
-        m_contentLayer->unref();
-        m_contentLayer = layer;
-    }
-
+    if (view->isRenderIFrame())
+        m_contentLayer->setIsIframe(true);
     // If we are a fixed position layer, just set it
     if (view->isPositioned() && view->style()->position() == FixedPosition) {
-        m_contentLayer->setAbsolutePosition(false);
         // We need to get the passed CSS properties for the element
         SkLength left, top, right, bottom;
-        left = SkLength::convertLength(view->style()->left());
-        top = SkLength::convertLength(view->style()->top());
-        right = SkLength::convertLength(view->style()->right());
-        bottom = SkLength::convertLength(view->style()->bottom());
+        left = convertLength(view->style()->left());
+        top = convertLength(view->style()->top());
+        right = convertLength(view->style()->right());
+        bottom = convertLength(view->style()->bottom());
 
         // We also need to get the margin...
         SkLength marginLeft, marginTop, marginRight, marginBottom;
-        marginLeft = SkLength::convertLength(view->style()->marginLeft());
-        marginTop = SkLength::convertLength(view->style()->marginTop());
-        marginRight = SkLength::convertLength(view->style()->marginRight());
-        marginBottom = SkLength::convertLength(view->style()->marginBottom());
+        marginLeft = convertLength(view->style()->marginLeft());
+        marginTop = convertLength(view->style()->marginTop());
+        marginRight = convertLength(view->style()->marginRight());
+        marginBottom = convertLength(view->style()->marginBottom());
 
         // In order to compute the fixed element's position, we need the width
         // and height of the element when bottom or right is defined.
@@ -274,24 +263,12 @@
 
         SkRect viewRect;
         viewRect.set(paintingOffsetX, paintingOffsetY, paintingOffsetX + w, paintingOffsetY + h);
-        IntPoint renderLayerPos(position().x(), position().y());
-
-        FixedPositioning* fixedPosition = m_contentLayer->fixedPosition();
-        if (!fixedPosition) {
-            fixedPosition = new FixedPositioning();
-            m_contentLayer->setFixedPosition(fixedPosition);
-        }
-
-        fixedPosition->setFixedPosition(left, top, right, bottom,
-                                        marginLeft, marginTop,
-                                        marginRight, marginBottom,
-                                        renderLayerPos,
-                                        viewRect);
-    } else if (view->isPositioned() && view->style()->position() == AbsolutePosition) {
-        m_contentLayer->setAbsolutePosition(true);
-    } else {
-        m_contentLayer->setFixedPosition(0);
-        m_contentLayer->setAbsolutePosition(false);
+        IntPoint renderLayerPos(renderLayer->x(), renderLayer->y());
+        m_contentLayer->setFixedPosition(left, top, right, bottom,
+                                         marginLeft, marginTop,
+                                         marginRight, marginBottom,
+                                         renderLayerPos,
+                                         viewRect);
     }
 }
 
@@ -302,10 +279,11 @@
 
     GraphicsLayer::setPosition(point);
 
-    ALOGV("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)",
+#ifdef LAYER_DEBUG_2
+    LOG("(%x) setPosition(%.2f,%.2f) pos(%.2f, %.2f) anchor(%.2f,%.2f) size(%.2f, %.2f)",
         this, point.x(), point.y(), m_position.x(), m_position.y(),
         m_anchorPoint.x(), m_anchorPoint.y(), m_size.width(), m_size.height());
-
+#endif
     m_contentLayer->setPosition(point.x(), point.y());
     askForSync();
 }
@@ -334,8 +312,7 @@
 {
     if (size == m_size)
         return;
-    ALOGV("(%x) layer %d setSize (%.2f,%.2f)", this,
-          m_contentLayer->uniqueId(), size.width(), size.height());
+    MLOG("(%x) setSize (%.2f,%.2f)", this, size.width(), size.height());
     GraphicsLayer::setSize(size);
 
     // If it is a media layer the size may have changed as a result of the media
@@ -346,8 +323,8 @@
         RenderBox* box = layer->renderBox();
         int outline = box->view()->maximalOutlineSize();
         static_cast<MediaLayer*>(m_contentLayer)->setOutlineSize(outline);
-        ALOGV("Media Outline: %d %p %p %p", outline, m_client, layer, box);
-        ALOGV("Media Size: %g,%g", size.width(), size.height());
+        LOG("Media Outline: %d %p %p %p", outline, m_client, layer, box);
+        LOG("Media Size: %g,%g", size.width(), size.height());
     }
 
     m_contentLayer->setSize(size.width(), size.height());
@@ -379,7 +356,7 @@
 {
     if (t == m_childrenTransform)
        return;
-    ALOGV("(%x) setChildrenTransform", this);
+    LOG("(%x) setChildrenTransform", this);
 
     GraphicsLayer::setChildrenTransform(t);
     m_contentLayer->setChildrenTransform(t);
@@ -428,7 +405,7 @@
 {
     if (color == m_backgroundColor && m_backgroundColorSet)
         return;
-    ALOGV("(%x) setBackgroundColor", this);
+    LOG("(%x) setBackgroundColor", this);
     GraphicsLayer::setBackgroundColor(color);
     SkColor c = SkColorSetARGB(color.alpha(), color.red(), color.green(), color.blue());
     m_contentLayer->setBackgroundColor(c);
@@ -441,7 +418,7 @@
     if (!m_backgroundColorSet)
         return;
 
-    ALOGV("(%x) clearBackgroundColor", this);
+    LOG("(%x) clearBackgroundColor", this);
     GraphicsLayer::clearBackgroundColor();
     askForSync();
 }
@@ -450,7 +427,7 @@
 {
     if (opaque == m_contentsOpaque)
         return;
-    ALOGV("(%x) setContentsOpaque (%d)", this, opaque);
+    LOG("(%x) setContentsOpaque (%d)", this, opaque);
     GraphicsLayer::setContentsOpaque(opaque);
     m_haveContents = true;
     askForSync();
@@ -458,13 +435,13 @@
 
 void GraphicsLayerAndroid::setOpacity(float opacity)
 {
-    ALOGV("(%x) setOpacity: %.2f", this, opacity);
+    LOG("(%x) setOpacity: %.2f", this, opacity);
     float clampedOpacity = max(0.0f, min(opacity, 1.0f));
 
     if (clampedOpacity == m_opacity)
         return;
 
-    ALOGV("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this,
+    MLOG("(%x) setFinalOpacity: %.2f=>%.2f (%.2f)", this,
         opacity, clampedOpacity, m_opacity);
     GraphicsLayer::setOpacity(clampedOpacity);
     m_contentLayer->setOpacity(clampedOpacity);
@@ -473,7 +450,7 @@
 
 void GraphicsLayerAndroid::setNeedsDisplay()
 {
-    ALOGV("(%x) setNeedsDisplay()", this);
+    LOG("(%x) setNeedsDisplay()", this);
     FloatRect rect(0, 0, m_size.width(), m_size.height());
     setNeedsDisplayInRect(rect);
 }
@@ -531,8 +508,6 @@
         if (layerNeedsOverflow) {
             ASSERT(!m_foregroundLayer && !m_foregroundClipLayer);
             m_foregroundLayer = new ScrollableLayerAndroid(layer);
-            m_foregroundLayer->setIntrinsicallyComposited(true);
-
             m_foregroundClipLayer = new LayerAndroid(layer);
             m_foregroundClipLayer->setMasksToBounds(true);
             m_foregroundClipLayer->addChild(m_foregroundLayer);
@@ -543,7 +518,7 @@
             // No need to copy the children as they will be removed and synced.
             m_contentLayer->removeChildren();
             // Replace the content layer with a scrollable layer.
-            LayerAndroid* layer = new IFrameContentLayerAndroid(*m_contentLayer);
+            LayerAndroid* layer = new ScrollableLayerAndroid(*m_contentLayer);
             m_contentLayer->unref();
             m_contentLayer = layer;
             if (m_parent) {
@@ -554,7 +529,7 @@
         }
         // Need to rebuild our children based on the new structure.
         m_needsSyncChildren = true;
-    } else if (!m_contentLayer->isFixedBackground()) {
+    } else {
         ASSERT(hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow);
         ASSERT(m_contentLayer);
         // Remove the foreground layers.
@@ -580,108 +555,10 @@
 #endif
 }
 
-void GraphicsLayerAndroid::updateFixedBackgroundLayers() {
-    RenderLayer* renderLayer = renderLayerFromClient(m_client);
-    if (!renderLayer)
-        return;
-    RenderView* view = static_cast<RenderView*>(renderLayer->renderer());
-    if (!view)
-        return;
-    if (view->isBody()) // body element is already handled
-        return;
-    if (!view->style()->hasFixedBackgroundImage())
-        return;
-
-    Image* image = FixedBackgroundImageLayerAndroid::GetCachedImage(view->style());
-    if (!image)
-        return;
-
-    if (image->width() == 1 && image->height() == 1)
-        return;
-
-    SkSafeUnref(m_foregroundClipLayer);
-    SkSafeUnref(m_fixedBackgroundLayer);
-    SkSafeUnref(m_foregroundLayer);
-
-    // we will have:
-    // m_contentLayer
-    //   \- m_foregroundClipLayer
-    //     \- m_fixedBackgroundLayer
-    //   \- m_foregroundLayer
-
-    // use the background image and create a layer for it
-    // the layer will be fixed positioned.
-
-    m_fixedBackgroundLayer = new FixedBackgroundImageLayerAndroid(view->style(),
-                                                                  view->width(),
-                                                                  view->height());
-
-    Color color = view->style()->visitedDependentColor(CSSPropertyBackgroundColor);
-    SkColor skiaColor = SkColorSetARGB(color.alpha(),
-                                       color.red(),
-                                       color.green(),
-                                       color.blue());
-    m_fixedBackgroundLayer->setBackgroundColor(skiaColor);
-
-    // We need to clip the background image to the bounds of the original element
-    m_foregroundClipLayer = new LayerAndroid(renderLayer);
-    m_foregroundClipLayer->setMasksToBounds(true);
-    m_foregroundClipLayer->addChild(m_fixedBackgroundLayer);
-
-    // We then want to display the content above the image background; webkit
-    // allow to paint background and foreground separately. For now, we'll create
-    // two layers; the one containing the background will be painted *without* the
-    // background image (but with the decorations, e.g. border)
-    m_foregroundLayer = new LayerAndroid(renderLayer);
-    m_foregroundLayer->setIntrinsicallyComposited(true);
-
-    // Finally, let's assemble all the layers under a FixedBackgroundLayerAndroid layer
-    if (!m_contentLayer->isFixedBackground()) {
-        m_contentLayer->removeChildren();
-        LayerAndroid* layer = new FixedBackgroundLayerAndroid(*m_contentLayer);
-        m_contentLayer->unref();
-        m_contentLayer = layer;
-    }
-
-    if (m_parent) {
-        // The content layer has changed so the parent needs to sync
-        // children.
-        static_cast<GraphicsLayerAndroid*>(m_parent)->m_needsSyncChildren = true;
-    }
-    // Children are all re-parented.
-    m_needsSyncChildren = true;
-
-    setNeedsDisplay();
-    askForSync();
-}
-
-void GraphicsLayerAndroid::updateScrollOffset() {
-    RenderLayer* layer = renderLayerFromClient(m_client);
-    if (!layer || !(m_foregroundLayer || m_contentLayer->contentIsScrollable()))
-        return;
-    if (m_foregroundLayer) {
-        IntSize scroll = layer->scrolledContentOffset();
-        m_foregroundLayer->setScrollOffset(IntPoint(scroll.width(), scroll.height()));
-    } else if (m_contentLayer->isIFrameContent()) {
-        IntPoint p(layer->renderer()->frame()->view()->scrollX(),
-                   layer->renderer()->frame()->view()->scrollY());
-        static_cast<IFrameContentLayerAndroid*>(m_contentLayer)->setIFrameScrollOffset(p);
-    }
-    askForSync();
-}
-
-static void setScrollLimits(ScrollableLayerAndroid* scrollableLayer, RenderLayer* renderLayer)
-{
-    RenderBox* box = renderLayer->renderBox();
-    scrollableLayer->setScrollLimits(0, 0,
-            renderLayer->scrollWidth() - box->clientWidth(),
-            renderLayer->scrollHeight() - box->clientHeight());
-}
-
 bool GraphicsLayerAndroid::repaint()
 {
-    ALOGV("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ",
-          this, gPaused, m_needsRepaint, m_haveContents);
+    LOG("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ",
+        this, gPaused, m_needsRepaint, m_haveContents);
 
     if (!gPaused && m_haveContents && m_needsRepaint && !m_image) {
         // with SkPicture, we request the entire layer's content.
@@ -690,21 +567,20 @@
         RenderLayer* layer = renderLayerFromClient(m_client);
         if (!layer)
             return false;
-        if (m_foregroundLayer && !m_contentLayer->isFixedBackground()) {
+        if (m_foregroundLayer) {
             PaintingPhase phase(this);
             // Paint the background into a separate context.
             phase.set(GraphicsLayerPaintBackground);
-            if (!paintContext(m_contentLayer, layerBounds))
+            if (!paintContext(m_contentLayer->recordContext(), layerBounds))
                 return false;
+            m_contentLayer->checkTextPresence();
 
             // Construct the foreground layer and draw.
             RenderBox* box = layer->renderBox();
             int outline = box->view()->maximalOutlineSize();
             IntRect contentsRect(0, 0,
-                                 box->borderLeft() + box->borderRight() + layer->scrollWidth()
-                                 + layer->verticalScrollbarWidth(),
-                                 box->borderTop() + box->borderBottom() + layer->scrollHeight()
-                                 + layer->horizontalScrollbarHeight());
+                                 box->borderLeft() + box->borderRight() + layer->scrollWidth(),
+                                 box->borderTop() + box->borderBottom() + layer->scrollHeight());
             contentsRect.inflate(outline);
             // Update the foreground layer size.
             m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height());
@@ -715,7 +591,8 @@
             IntSize scroll = layer->scrolledContentOffset();
             layer->scrollToOffset(0, 0);
             // At this point, it doesn't matter if painting failed.
-            (void) paintContext(m_foregroundLayer, contentsRect);
+            (void) paintContext(m_foregroundLayer->recordContext(), contentsRect);
+            m_foregroundLayer->checkTextPresence();
             layer->scrollToOffset(scroll.width(), scroll.height());
 
             // Construct the clip layer for masking the contents.
@@ -729,16 +606,11 @@
             m_foregroundClipLayer->setPosition(x, y);
             m_foregroundClipLayer->setSize(width, height);
 
-            int rtlOffset = 0; // LTR uses no offset.
-            if (!layer->renderer()->style()->isLeftToRightDirection())
-                rtlOffset = layer->scrollWidth() - width; // Scroll all the way right.
-            m_foregroundLayer->setScrollOffset(IntPoint(scroll.width() + rtlOffset,
-                    scroll.height()));
             // Need to offset the foreground layer by the clip layer in order
             // for the contents to be in the correct position.
             m_foregroundLayer->setPosition(-x, -y);
             // Set the scrollable bounds of the layer.
-            setScrollLimits(static_cast<ScrollableLayerAndroid*>(m_foregroundLayer), layer);
+            m_foregroundLayer->setScrollLimits(-x, -y, m_size.width(), m_size.height());
 
             // Invalidate the entire layer for now, as webkit will only send the
             // setNeedsDisplayInRect() for the visible (clipped) scrollable area,
@@ -747,71 +619,32 @@
             SkRegion region;
             region.setRect(0, 0, contentsRect.width(), contentsRect.height());
             m_foregroundLayer->markAsDirty(region);
-        } else if (m_contentLayer->isFixedBackground()) {
-            SkPicture* picture = new SkPicture();
-            SkCanvas* canvas = picture->beginRecording(layerBounds.width(),
-                                                       layerBounds.height(), 0);
-            if (canvas) {
-                  PaintingPhase phase(this);
-                  PlatformGraphicsContextSkia platformContext(canvas);
-                  GraphicsContext graphicsContext(&platformContext);
-
-                  // Paint the background (without the fixed image)...
-                  phase.set(GraphicsLayerPaintBackgroundDecorations);
-                  paintGraphicsLayerContents(graphicsContext, layerBounds);
-                  phase.clear(GraphicsLayerPaintBackgroundDecorations);
-
-                  // Paint the foreground...
-                  phase.set(GraphicsLayerPaintForeground);
-                  paintGraphicsLayerContents(graphicsContext, layerBounds);
-                  picture->endRecording();
-
-                  // Now set the content for that layer.
-                  PictureLayerContent* layerContent = new PictureLayerContent(picture);
-                  m_foregroundLayer->setContent(layerContent);
-                  SkSafeUnref(layerContent);
-            }
-            SkSafeUnref(picture);
-
-            m_foregroundLayer->setSize(layerBounds.width(), layerBounds.height());
-            m_foregroundClipLayer->setPosition(layerBounds.x(), layerBounds.y());
-            m_foregroundClipLayer->setSize(layerBounds.width(), layerBounds.height());
+            m_foregroundLayer->needsRepaint();
         } else {
-
-            // If we are replicated, paint the mask
-            if (isReplicated()) {
-                GraphicsLayerAndroid* replicatedLayer = static_cast<GraphicsLayerAndroid*>(replicaLayer());
-                if (replicatedLayer->maskLayer()) {
-                     GraphicsLayerAndroid* mask = static_cast<GraphicsLayerAndroid*>(replicatedLayer->maskLayer());
-                     mask->paintContext(mask->m_contentLayer, layerBounds, false);
-                }
-            }
-
             // If there is no contents clip, we can draw everything into one
             // picture.
-            bool painting = paintContext(m_contentLayer, layerBounds);
-            if (!painting)
+            if (!paintContext(m_contentLayer->recordContext(), layerBounds))
                 return false;
+            m_contentLayer->checkTextPresence();
             // Check for a scrollable iframe and report the scrolling
             // limits based on the view size.
-            if (m_contentLayer->isIFrameContent()) {
+            if (m_contentLayer->contentIsScrollable()) {
                 FrameView* view = layer->renderer()->frame()->view();
-                setScrollLimits(static_cast<ScrollableLayerAndroid*>(m_contentLayer), layer);
-                ALOGV("setScrollLimits(%.2f, %.2f, w: %d h: %d) layer %d, frame scroll position is %d, %d",
-                      m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight(),
-                      m_contentLayer->uniqueId(), view->scrollX(), view->scrollY());
+                static_cast<ScrollableLayerAndroid*>(m_contentLayer)->setScrollLimits(
+                    m_position.x(), m_position.y(), view->layoutWidth(), view->layoutHeight());
             }
         }
 
-        ALOGV("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!",
-              this, m_size.width(), m_size.height(),
-              m_contentLayer->getPosition().fX,
-              m_contentLayer->getPosition().fY,
-              m_contentLayer->getSize().width(),
-              m_contentLayer->getSize().height());
+        LOG("(%x) repaint() on (%.2f,%.2f) contentlayer(%.2f,%.2f,%.2f,%.2f)paintGraphicsLayer called!",
+            this, m_size.width(), m_size.height(),
+            m_contentLayer->getPosition().fX,
+            m_contentLayer->getPosition().fY,
+            m_contentLayer->getSize().width(),
+            m_contentLayer->getSize().height());
 
         m_contentLayer->markAsDirty(m_dirtyRegion);
         m_dirtyRegion.setEmpty();
+        m_contentLayer->needsRepaint();
         m_needsRepaint = false;
 
         return true;
@@ -821,6 +654,7 @@
         // texture. Only do so if we effectively have a new image!
         m_contentLayer->markAsDirty(m_dirtyRegion);
         m_dirtyRegion.setEmpty();
+        m_contentLayer->needsRepaint();
         m_newImage = false;
         m_needsRepaint = false;
         return true;
@@ -828,44 +662,19 @@
     return false;
 }
 
-SkPicture* GraphicsLayerAndroid::paintPicture(const IntRect& rect)
+bool GraphicsLayerAndroid::paintContext(SkPicture* context,
+                                        const IntRect& rect)
 {
-    SkPicture* picture = new SkPicture();
-    SkCanvas* canvas = picture->beginRecording(rect.width(), rect.height(), 0);
-    if (!canvas) {
-        picture->endRecording();
-        SkSafeUnref(picture);
-        return 0;
-    }
+    SkAutoPictureRecord arp(context, rect.width(), rect.height());
+    SkCanvas* canvas = arp.getRecordingCanvas();
 
-    PlatformGraphicsContextSkia platformContext(canvas);
+    if (!canvas)
+        return false;
+
+    PlatformGraphicsContext platformContext(canvas);
     GraphicsContext graphicsContext(&platformContext);
 
     paintGraphicsLayerContents(graphicsContext, rect);
-
-    return picture;
-}
-
-bool GraphicsLayerAndroid::paintContext(LayerAndroid* layer,
-                                        const IntRect& rect,
-                                        bool checkOptimisations)
-{
-    if (!layer)
-        return false;
-
-    SkPicture* picture = paintPicture(rect);
-    if (!picture)
-        return false;
-    picture->endRecording();
-
-    PictureLayerContent* layerContent = new PictureLayerContent(picture);
-    if (checkOptimisations)
-        layerContent->checkForOptimisations();
-    else
-        layerContent->setCheckForOptimisations(false);
-    layer->setContent(layerContent);
-    SkSafeUnref(layerContent);
-    SkSafeUnref(picture);
     return true;
 }
 
@@ -874,8 +683,8 @@
     // rect is in the render object coordinates
 
     if (!m_image && !drawsContent()) {
-        ALOGV("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...",
-              this, rect.x(), rect.y(), rect.width(), rect.height());
+        LOG("(%x) setNeedsDisplay(%.2f,%.2f,%.2f,%.2f) doesn't have content, bypass...",
+            this, rect.x(), rect.y(), rect.width(), rect.height());
         return;
     }
 
@@ -927,20 +736,20 @@
      const Animation* animation, const String& keyframesName, double beginTime)
 {
     bool isKeyframe = valueList.size() > 2;
-    ALOGV("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)",
-          isKeyframe, keyframesName.ascii().data(), beginTime);
+    TLOG("createAnimationFromKeyframes(%d), name(%s) beginTime(%.2f)",
+        isKeyframe, keyframesName.latin1().data(), beginTime);
 
     switch (valueList.property()) {
     case AnimatedPropertyInvalid: break;
     case AnimatedPropertyWebkitTransform: break;
     case AnimatedPropertyBackgroundColor: break;
     case AnimatedPropertyOpacity: {
-        ALOGV("ANIMATEDPROPERTYOPACITY");
+        MLOG("ANIMATEDPROPERTYOPACITY");
 
         KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyOpacity);
         for (unsigned int i = 0; i < valueList.size(); i++) {
             FloatAnimationValue* originalValue = (FloatAnimationValue*)valueList.at(i);
-            RefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
+            PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
             FloatAnimationValue* value = new FloatAnimationValue(originalValue->keyTime(),
                                                                  originalValue->value(),
                                                                  timingFunction);
@@ -976,13 +785,13 @@
                                                                   const IntSize& boxSize)
 {
     ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
-    ALOGV("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)",
-          keyframesName.ascii().data(), beginTime);
+    TLOG("createTransformAnimationFromKeyframes, name(%s) beginTime(%.2f)",
+        keyframesName.latin1().data(), beginTime);
 
     KeyframeValueList* operationsList = new KeyframeValueList(AnimatedPropertyWebkitTransform);
     for (unsigned int i = 0; i < valueList.size(); i++) {
         TransformAnimationValue* originalValue = (TransformAnimationValue*)valueList.at(i);
-        RefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
+        PassRefPtr<TimingFunction> timingFunction(const_cast<TimingFunction*>(originalValue->timingFunction()));
         TransformAnimationValue* value = new TransformAnimationValue(originalValue->keyTime(),
                                                                      originalValue->value(),
                                                                      timingFunction);
@@ -1007,36 +816,36 @@
 
 void GraphicsLayerAndroid::removeAnimationsForProperty(AnimatedPropertyID anID)
 {
-    ALOGV("NRO removeAnimationsForProperty(%d)", anID);
+    TLOG("NRO removeAnimationsForProperty(%d)", anID);
     m_contentLayer->removeAnimationsForProperty(anID);
     askForSync();
 }
 
 void GraphicsLayerAndroid::removeAnimationsForKeyframes(const String& keyframesName)
 {
-    ALOGV("NRO removeAnimationsForKeyframes(%s)", keyframesName.ascii().data());
+    TLOG("NRO removeAnimationsForKeyframes(%s)", keyframesName.latin1().data());
     m_contentLayer->removeAnimationsForKeyframes(keyframesName);
     askForSync();
 }
 
 void GraphicsLayerAndroid::pauseAnimation(const String& keyframesName)
 {
-    ALOGV("NRO pauseAnimation(%s)", keyframesName.ascii().data());
+    TLOG("NRO pauseAnimation(%s)", keyframesName.latin1().data());
 }
 
 void GraphicsLayerAndroid::suspendAnimations(double time)
 {
-    ALOGV("NRO suspendAnimations(%.2f)", time);
+    TLOG("NRO suspendAnimations(%.2f)", time);
 }
 
 void GraphicsLayerAndroid::resumeAnimations()
 {
-    ALOGV("NRO resumeAnimations()");
+    TLOG("NRO resumeAnimations()");
 }
 
 void GraphicsLayerAndroid::setContentsToImage(Image* image)
 {
-    ALOGV("(%x) setContentsToImage", this, image);
+    TLOG("(%x) setContentsToImage", this, image);
     if (image && image != m_image) {
         image->ref();
         if (m_image)
@@ -1090,7 +899,7 @@
 
 PlatformLayer* GraphicsLayerAndroid::platformLayer() const
 {
-    ALOGV("platformLayer");
+    LOG("platformLayer");
     return m_contentLayer;
 }
 
@@ -1108,7 +917,7 @@
 {
     if (position == m_zPosition)
         return;
-    ALOGV("(%x) setZPosition: %.2f", this, position);
+    LOG("(%x) setZPosition: %.2f", this, position);
     GraphicsLayer::setZPosition(position);
     askForSync();
 }
@@ -1124,32 +933,20 @@
 
 void GraphicsLayerAndroid::syncChildren()
 {
-    if (m_needsSyncChildren || isReplicated()) {
+    if (m_needsSyncChildren) {
         m_contentLayer->removeChildren();
         LayerAndroid* layer = m_contentLayer;
-
-        if (isReplicated()) {
-            GraphicsLayerAndroid* replicatedLayer = static_cast<GraphicsLayerAndroid*>(replicaLayer());
-            m_contentLayer->addChild(replicatedLayer->m_contentLayer);
-        }
-
-        if (m_contentLayer->isFixedBackground()) {
-            m_contentLayer->addChild(m_foregroundClipLayer);
-            m_contentLayer->addChild(m_foregroundLayer);
-            layer = m_foregroundLayer;
-            layer->removeChildren();
-        } else if (m_foregroundClipLayer) {
+        if (m_foregroundClipLayer) {
             m_contentLayer->addChild(m_foregroundClipLayer);
             // Use the scrollable content layer as the parent of the children so
             // that they move with the content.
             layer = m_foregroundLayer;
             layer->removeChildren();
         }
-
         for (unsigned int i = 0; i < m_children.size(); i++)
             layer->addChild(m_children[i]->platformLayer());
+        m_needsSyncChildren = false;
     }
-    m_needsSyncChildren = false;
 }
 
 void GraphicsLayerAndroid::syncMask()
@@ -1191,15 +988,8 @@
 
 void GraphicsLayerAndroid::syncCompositingStateForThisLayerOnly()
 {
-    if (m_contentLayer) {
-        RenderLayer* renderLayer = renderLayerFromClient(m_client);
-        int intrinsicallyComposited = renderLayer ? renderLayer->intrinsicallyComposited() : true;
-        m_contentLayer->setIntrinsicallyComposited(intrinsicallyComposited);
-    }
-
     updateScrollingLayers();
-    updateFixedBackgroundLayers();
-    updatePositionedLayers();
+    updateFixedPosition();
     syncChildren();
     syncMask();
 
diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
index 460e00f..e6d75b0 100644
--- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.h
@@ -23,21 +23,18 @@
 #include "Frame.h"
 #include "GraphicsLayer.h"
 #include "GraphicsLayerClient.h"
-#include "LayerContent.h"
+#include "LayerAndroid.h"
 #include "RefPtr.h"
-#include "ScrollableLayerAndroid.h"
 #include "SkBitmapRef.h"
 #include "Vector.h"
 
+class FloatPoint3D;
+class Image;
 class SkBitmapRef;
 class SkRegion;
 
 namespace WebCore {
 
-class FloatPoint3D;
-class Image;
-class LayerAndroid;
-class FixedBackgroundImageLayerAndroid;
 class ScrollableLayerAndroid;
 
 class GraphicsLayerAndroid : public GraphicsLayer {
@@ -57,7 +54,6 @@
     virtual void addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling);
     virtual void addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling);
     virtual bool replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild);
-    virtual void setReplicatedLayer(GraphicsLayer* layer);
 
     virtual void removeFromParent();
 
@@ -126,12 +122,9 @@
     void notifyClientAnimationStarted();
 
     LayerAndroid* contentLayer() { return m_contentLayer; }
-    LayerAndroid* foregroundLayer() { return m_foregroundLayer; }
 
     static int instancesCount();
 
-    virtual void updateScrollOffset();
-
 private:
 
     void askForSync();
@@ -139,18 +132,14 @@
     void syncChildren();
     void syncMask();
 
-    void updatePositionedLayers();
+    void updateFixedPosition();
     void updateScrollingLayers();
-    void updateFixedBackgroundLayers();
 
     // with SkPicture, we always repaint the entire layer's content.
     bool repaint();
     void needsNotifyClient();
 
-    SkPicture* paintPicture(const IntRect& rect);
-    bool paintContext(LayerAndroid* layer,
-                      const IntRect& rect,
-                      bool checkOptimisations = true);
+    bool paintContext(SkPicture* context, const IntRect& rect);
 
     bool m_needsSyncChildren;
     bool m_needsSyncMask;
@@ -164,8 +153,7 @@
     SkRegion m_dirtyRegion;
 
     LayerAndroid* m_contentLayer;
-    FixedBackgroundImageLayerAndroid* m_fixedBackgroundLayer;
-    LayerAndroid* m_foregroundLayer;
+    ScrollableLayerAndroid* m_foregroundLayer;
     LayerAndroid* m_foregroundClipLayer;
 };
 
diff --git a/Source/WebCore/platform/graphics/android/fonts/HarfbuzzSkia.cpp b/Source/WebCore/platform/graphics/android/HarfbuzzSkia.cpp
similarity index 100%
rename from Source/WebCore/platform/graphics/android/fonts/HarfbuzzSkia.cpp
rename to Source/WebCore/platform/graphics/android/HarfbuzzSkia.cpp
diff --git a/Source/WebCore/platform/graphics/android/fonts/HarfbuzzSkia.h b/Source/WebCore/platform/graphics/android/HarfbuzzSkia.h
similarity index 100%
rename from Source/WebCore/platform/graphics/android/fonts/HarfbuzzSkia.h
rename to Source/WebCore/platform/graphics/android/HarfbuzzSkia.h
diff --git a/Source/WebCore/platform/graphics/android/ImageAndroid.cpp b/Source/WebCore/platform/graphics/android/ImageAndroid.cpp
index 08f72e0..01fe272 100644
--- a/Source/WebCore/platform/graphics/android/ImageAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/ImageAndroid.cpp
@@ -44,7 +44,7 @@
 #include "SkTemplates.h"
 #include "SkiaUtils.h"
 
-#include <androidfw/AssetManager.h>
+#include <utils/AssetManager.h>
 
 //#define TRACE_SUBSAMPLED_BITMAPS
 //#define TRACE_SKIPPED_BITMAPS
@@ -172,7 +172,20 @@
              SkScalarRound(SkFloatToScalar((src.y() + src.height()) * sy)));
 }
 
-void BitmapImage::draw(GraphicsContext* gc, const FloatRect& dstRect,
+static inline void fixPaintForBitmapsThatMaySeam(SkPaint* paint) {
+    /*  Bitmaps may be drawn to seem next to other images. If we are drawn
+        zoomed, or at fractional coordinates, we may see cracks/edges if
+        we antialias, because that will cause us to draw the same pixels
+        more than once (e.g. from the left and right bitmaps that share
+        an edge).
+
+        Disabling antialiasing fixes this, and since so far we are never
+        rotated at non-multiple-of-90 angles, this seems to do no harm
+     */
+    paint->setAntiAlias(false);
+}
+
+void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect,
                    const FloatRect& srcRect, ColorSpace,
                    CompositeOperator compositeOp)
 {
@@ -209,7 +222,14 @@
         return;
     }
 
-    gc->platformContext()->drawBitmapRect(bitmap, &srcR, dstR, compositeOp);
+    SkCanvas*   canvas = ctxt->platformContext()->mCanvas;
+    SkPaint     paint;
+
+    ctxt->setupBitmapPaint(&paint);   // need global alpha among other things
+    paint.setFilterBitmap(true);
+    paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp));
+    fixPaintForBitmapsThatMaySeam(&paint);
+    canvas->drawBitmapRect(bitmap, &srcR, dstR, &paint);
 
 #ifdef TRACE_SUBSAMPLED_BITMAPS
     if (bitmap.width() != image->origWidth() ||
@@ -228,19 +248,26 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void Image::drawPattern(GraphicsContext* gc, const FloatRect& srcRect,
+void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect,
                         const AffineTransform& patternTransform,
                         const FloatPoint& phase, ColorSpace,
                         CompositeOperator compositeOp, const FloatRect& destRect)
 {
     SkBitmapRef* image = this->nativeImageForCurrentFrame();
-    if (!image || destRect.isEmpty())
+    if (!image) { // If it's too early we won't have an image yet.
         return;
+    }
 
     // in case we get called with an incomplete bitmap
     const SkBitmap& origBitmap = image->bitmap();
-    if (origBitmap.getPixels() == NULL && origBitmap.pixelRef() == NULL)
+    if (origBitmap.getPixels() == NULL && origBitmap.pixelRef() == NULL) {
         return;
+    }
+
+    SkRect  dstR(destRect);
+    if (dstR.isEmpty()) {
+        return;
+    }
 
     SkIRect srcR;
     // we may have to scale if the image has been subsampled (so save RAM)
@@ -251,9 +278,11 @@
     if (imageIsSubSampled) {
         scaleX = (float)image->origWidth() / origBitmap.width();
         scaleY = (float)image->origHeight() / origBitmap.height();
+//        SkDebugf("----- subsampled %g %g\n", scaleX, scaleY);
         round_scaled(&srcR, srcRect, 1 / scaleX, 1 / scaleY);
-    } else
+    } else {
         round(&srcR, srcRect);
+    }
 
     // now extract the proper subset of the src image
     SkBitmap bitmap;
@@ -262,6 +291,19 @@
         return;
     }
 
+    SkCanvas*   canvas = ctxt->platformContext()->mCanvas;
+    SkPaint     paint;
+    ctxt->setupBitmapPaint(&paint);   // need global alpha among other things
+
+    SkShader* shader = SkShader::CreateBitmapShader(bitmap,
+                                                    SkShader::kRepeat_TileMode,
+                                                    SkShader::kRepeat_TileMode);
+    paint.setShader(shader)->unref();
+    // now paint is the only owner of shader
+    paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp));
+    paint.setFilterBitmap(true);
+    fixPaintForBitmapsThatMaySeam(&paint);
+
     SkMatrix matrix(patternTransform);
 
     if (imageIsSubSampled) {
@@ -274,8 +316,26 @@
     float tx = phase.x() + srcRect.x() * patternTransform.a();
     float ty = phase.y() + srcRect.y() * patternTransform.d();
     matrix.postTranslate(SkFloatToScalar(tx), SkFloatToScalar(ty));
+    shader->setLocalMatrix(matrix);
+#if 0
+    SkDebugf("--- drawPattern: src [%g %g %g %g] dst [%g %g %g %g] transform [%g %g %g %g %g %g] matrix [%g %g %g %g %g %g]\n",
+             srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height(),
+             destRect.x(), destRect.y(), destRect.width(), destRect.height(),
+             patternTransform.a(), patternTransform.b(), patternTransform.c(),
+             patternTransform.d(), patternTransform.e(), patternTransform.f(),
+             matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
+#endif
+    canvas->drawRect(dstR, paint);
 
-    gc->platformContext()->drawBitmapPattern(bitmap, matrix, compositeOp, destRect);
+#ifdef TRACE_SUBSAMPLED_BITMAPS
+    if (bitmap.width() != image->origWidth() ||
+        bitmap.height() != image->origHeight()) {
+        SkDebugf("--- Image::drawPattern [%d %d] orig [%d %d] dst [%g %g]\n",
+                 bitmap.width(), bitmap.height(),
+                 image->origWidth(), image->origHeight(),
+                 SkScalarToFloat(dstR.width()), SkScalarToFloat(dstR.height()));
+    }
+#endif
 }
 
 // missingImage, textAreaResizeCorner
diff --git a/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp b/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
index e56f424..751a08f 100644
--- a/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/ImageBufferAndroid.cpp
@@ -82,10 +82,7 @@
 {
     ASSERT(context());
 
-    SkCanvas* canvas = context()->platformContext()->getCanvas();
-    if (!canvas)
-      return 0;
-
+    SkCanvas* canvas = context()->platformContext()->mCanvas;
     SkDevice* device = canvas->getDevice();
     const SkBitmap& orig = device->accessBitmap(false);
 
@@ -199,7 +196,7 @@
     ASSERT(destx >= 0);
     ASSERT(destx < m_size.width());
     ASSERT(originx >= 0);
-    ASSERT(originx <= sourceRect.maxX());
+    ASSERT(originx <= sourceRect.right());
 
     int endx = destPoint.x() + sourceRect.maxX();
     ASSERT(endx <= m_size.width());
@@ -211,7 +208,7 @@
     ASSERT(desty >= 0);
     ASSERT(desty < m_size.height());
     ASSERT(originy >= 0);
-    ASSERT(originy <= sourceRect.maxY());
+    ASSERT(originy <= sourceRect.bottom());
 
     int endy = destPoint.y() + sourceRect.maxY();
     ASSERT(endy <= m_size.height());
diff --git a/Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp b/Source/WebCore/platform/graphics/android/ImageTexture.cpp
similarity index 65%
rename from Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp
rename to Source/WebCore/platform/graphics/android/ImageTexture.cpp
index c9c887a..577e7f0 100644
--- a/Source/WebCore/platform/graphics/android/rendering/ImageTexture.cpp
+++ b/Source/WebCore/platform/graphics/android/ImageTexture.cpp
@@ -23,20 +23,34 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#define LOG_TAG "ImageTexture"
-#define LOG_NDEBUG 1
-
 #include "config.h"
 #include "ImageTexture.h"
 
-#include "AndroidLog.h"
-#include "ClassTracker.h"
 #include "ImagesManager.h"
 #include "LayerAndroid.h"
 #include "SkDevice.h"
 #include "SkPicture.h"
-#include "TileGrid.h"
 #include "TilesManager.h"
+#include "TiledTexture.h"
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "ImageTexture", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ImageTexture", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
 
 namespace WebCore {
 
@@ -72,7 +86,7 @@
 
 ImageTexture::ImageTexture(SkBitmap* bmp, unsigned crc)
     : m_image(bmp)
-    , m_tileGrid(0)
+    , m_texture(0)
     , m_layer(0)
     , m_picture(0)
     , m_crc(crc)
@@ -85,7 +99,7 @@
 
     // NOTE: This constructor is called on the webcore thread
 
-    // Create a picture containing the image (needed for TileGrid)
+    // Create a picture containing the image (needed for TiledTexture)
     m_picture = new SkPicture();
     SkCanvas* pcanvas = m_picture->beginRecording(m_image->width(), m_image->height());
     pcanvas->clear(SkColorSetARGBInline(0, 0, 0, 0));
@@ -99,7 +113,7 @@
     ClassTracker::instance()->decrement("ImageTexture");
 #endif
     delete m_image;
-    delete m_tileGrid;
+    delete m_texture;
     SkSafeUnref(m_picture);
 }
 
@@ -141,24 +155,18 @@
     return m_crc == crc;
 }
 
-// Return 0 if the image does not meet the repeatable criteria.
-unsigned int ImageTexture::getImageTextureId()
-{
-    return m_tileGrid ? m_tileGrid->getImageTextureId() : 0;
-}
-
 int ImageTexture::nbTextures()
 {
     if (!hasContentToShow())
         return 0;
-    if (!m_tileGrid)
+    if (!m_texture)
         return 0;
 
     // TODO: take in account the visible clip (need to maintain
     // a list of the clients layer, etc.)
-    IntRect visibleContentArea(0, 0, m_image->width(), m_image->height());
-    int nbTextures = m_tileGrid->nbTextures(visibleContentArea, 1.0);
-    ALOGV("ImageTexture %p, %d x %d needs %d textures",
+    IntRect visibleArea(0, 0, m_image->width(), m_image->height());
+    int nbTextures = m_texture->nbTextures(visibleArea, 1.0);
+    XLOG("ImageTexture %p, %d x %d needs %d textures",
           this, m_image->width(), m_image->height(),
           nbTextures);
     return nbTextures;
@@ -179,21 +187,20 @@
     if (!hasContentToShow())
         return false;
 
-    if (!m_tileGrid && m_picture) {
-        bool isBaseSurface = false;
-        m_tileGrid = new TileGrid(isBaseSurface);
+    if (!m_texture && m_picture) {
+        m_texture = new TiledTexture(this);
         SkRegion region;
         region.setRect(0, 0, m_image->width(), m_image->height());
-        m_tileGrid->markAsDirty(region);
+        m_texture->update(region, m_picture);
     }
 
-    if (!m_tileGrid)
+    if (!m_texture)
         return false;
 
-    IntRect fullContentArea(0, 0, m_image->width(), m_image->height());
-    m_tileGrid->prepareGL(state, 1.0, fullContentArea, fullContentArea, this);
-    if (m_tileGrid->isReady()) {
-        m_tileGrid->swapTiles();
+    IntRect visibleArea(0, 0, m_image->width(), m_image->height());
+    m_texture->prepare(state, 1.0, true, true, visibleArea);
+    if (m_texture->ready()) {
+        m_texture->swapTiles();
         return false;
     }
     return true;
@@ -204,12 +211,13 @@
     if (!m_layer)
         return 0;
 
+    FloatPoint p(0, 0);
+    p = m_layer->drawTransform()->mapPoint(p);
+    IntRect layerArea = m_layer->unclippedArea();
+    float scaleW = static_cast<float>(layerArea.width()) / static_cast<float>(m_image->width());
+    float scaleH = static_cast<float>(layerArea.height()) / static_cast<float>(m_image->height());
     TransformationMatrix d = *(m_layer->drawTransform());
     TransformationMatrix m;
-    float scaleW = 1.0f;
-    float scaleH = 1.0f;
-    getImageToLayerScale(&scaleW, &scaleH);
-
     m.scaleNonUniform(scaleW, scaleH);
     m_layerMatrix = d.multiply(m);
     return &m_layerMatrix;
@@ -222,66 +230,18 @@
     return m_layer->drawOpacity();
 }
 
-bool ImageTexture::paint(SkCanvas* canvas)
-{
-    if (!m_picture) {
-        ALOGV("IT %p COULDNT PAINT, NO PICTURE", this);
-        return false;
-    }
-
-    ALOGV("IT %p painting with picture %p", this, m_picture);
-    canvas->drawPicture(*m_picture);
-
-    return true;
-}
-
-void ImageTexture::getImageToLayerScale(float* scaleW, float* scaleH) const
-{
-    if (!scaleW || !scaleH)
-        return;
-
-
-    IntRect layerArea = m_layer->fullContentArea();
-
-    if (layerArea.width() == 0 || layerArea.height() == 0)
-        return;
-
-    // calculate X, Y scale difference between image pixel coordinates and layer
-    // content coordinates
-
-    *scaleW = static_cast<float>(layerArea.width()) / static_cast<float>(m_image->width());
-    *scaleH = static_cast<float>(layerArea.height()) / static_cast<float>(m_image->height());
-}
-
-void ImageTexture::drawGL(LayerAndroid* layer,
-                         float opacity, FloatPoint* offset)
+void ImageTexture::drawGL(LayerAndroid* layer)
 {
     if (!layer)
         return;
     if (!hasContentToShow())
         return;
 
-    // TileGrid::draw() will call us back to know the
+    // TiledTexture::draw() will call us back to know the
     // transform and opacity, so we need to set m_layer
     m_layer = layer;
-    if (m_tileGrid) {
-        bool force3dContentVisible = true;
-        IntRect visibleContentArea = m_layer->visibleContentArea(force3dContentVisible);
-
-        // transform visibleContentArea size to image size
-        float scaleW = 1.0f;
-        float scaleH = 1.0f;
-        getImageToLayerScale(&scaleW, &scaleH);
-        visibleContentArea.setX(visibleContentArea.x() / scaleW);
-        visibleContentArea.setWidth(visibleContentArea.width() / scaleW);
-        visibleContentArea.setY(visibleContentArea.y() / scaleH);
-        visibleContentArea.setHeight(visibleContentArea.height() / scaleH);
-
-        const TransformationMatrix* transformation = transform();
-        if (offset)
-            m_layerMatrix.translate(offset->x(), offset->y());
-        m_tileGrid->drawGL(visibleContentArea, opacity, transformation);
-    }
+    if (m_texture)
+        m_texture->draw();
     m_layer = 0;
 }
 
diff --git a/Source/WebCore/platform/graphics/android/rendering/ImageTexture.h b/Source/WebCore/platform/graphics/android/ImageTexture.h
similarity index 86%
rename from Source/WebCore/platform/graphics/android/rendering/ImageTexture.h
rename to Source/WebCore/platform/graphics/android/ImageTexture.h
index 53df6f9..6c6a075 100644
--- a/Source/WebCore/platform/graphics/android/rendering/ImageTexture.h
+++ b/Source/WebCore/platform/graphics/android/ImageTexture.h
@@ -31,14 +31,13 @@
 #include "SkBitmapRef.h"
 #include "SkPicture.h"
 #include "SkRefCnt.h"
-#include "TilePainter.h"
+#include "LayerAndroid.h"
 
 namespace WebCore {
 
-class GLWebViewState;
 class LayerAndroid;
 class TexturesResult;
-class TileGrid;
+class TiledTexture;
 
 /////////////////////////////////////////////////////////////////////////////////
 // Image sharing codepath for layers
@@ -64,17 +63,17 @@
 // ImageTexture at draw time.
 //
 // ImageTexture recopy the original SkBitmap so that they can safely be used
-// on a different thread; it uses TileGrid to allocate and paint the image,
+// on a different thread; it uses TiledTexture to allocate and paint the image,
 // so that we can share the same textures and limits as the rest of the layers.
 //
 /////////////////////////////////////////////////////////////////////////////////
-class ImageTexture : public TilePainter {
+class ImageTexture : public SurfacePainter {
 public:
     ImageTexture(SkBitmap* bmp, unsigned crc);
     virtual ~ImageTexture();
 
     bool prepareGL(GLWebViewState*);
-    void drawGL(LayerAndroid* layer, float opacity, FloatPoint* offset = 0);
+    void drawGL(LayerAndroid* painter);
     void drawCanvas(SkCanvas*, SkRect&);
     bool hasContentToShow();
     SkBitmap* bitmap() { return m_image; }
@@ -85,21 +84,19 @@
     static unsigned computeCRC(const SkBitmap* bitmap);
     bool equalsCRC(unsigned crc);
 
-    // methods used by TileGrid
-    virtual bool paint(SkCanvas* canvas);
+    // methods used by TiledTexture
+    virtual const TransformationMatrix* transform();
     virtual float opacity();
 
     int nbTextures();
 
-    virtual SurfaceType type() { return TilePainter::Image; }
-    unsigned int getImageTextureId();
+    virtual SurfaceType type() { return SurfacePainter::ImageSurface; }
+
 private:
-    const TransformationMatrix* transform();
-    void getImageToLayerScale(float* scaleW, float* scaleH) const;
 
     SkBitmapRef* m_imageRef;
     SkBitmap* m_image;
-    TileGrid* m_tileGrid;
+    TiledTexture* m_texture;
     LayerAndroid* m_layer;
     SkPicture* m_picture;
     TransformationMatrix m_layerMatrix;
diff --git a/Source/WebCore/platform/graphics/android/rendering/ImagesManager.cpp b/Source/WebCore/platform/graphics/android/ImagesManager.cpp
similarity index 90%
rename from Source/WebCore/platform/graphics/android/rendering/ImagesManager.cpp
rename to Source/WebCore/platform/graphics/android/ImagesManager.cpp
index 82ea3fa..65c41d1 100644
--- a/Source/WebCore/platform/graphics/android/rendering/ImagesManager.cpp
+++ b/Source/WebCore/platform/graphics/android/ImagesManager.cpp
@@ -23,18 +23,33 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#define LOG_TAG "ImagesManager"
-#define LOG_NDEBUG 1
-
 #include "config.h"
 #include "ImagesManager.h"
 
-#include "AndroidLog.h"
 #include "SkCanvas.h"
 #include "SkDevice.h"
 #include "SkRefCnt.h"
 #include "ImageTexture.h"
 
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "ImagesManager", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ImagesManager", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
 namespace WebCore {
 
 ImagesManager* ImagesManager::instance()
@@ -52,13 +67,13 @@
     if (!imgRef)
         return 0;
 
-    TRACE_METHOD();
     SkBitmap* bitmap = &imgRef->bitmap();
     ImageTexture* image = 0;
     SkBitmap* img = 0;
     unsigned crc = 0;
 
-    crc = ImageTexture::computeCRC(bitmap);
+    img = ImageTexture::convertBitmap(bitmap);
+    crc = ImageTexture::computeCRC(img);
 
     {
         android::Mutex::Autolock lock(m_imagesLock);
@@ -71,7 +86,6 @@
 
     // the image is not in the map, we add it
 
-    img = ImageTexture::convertBitmap(bitmap);
     image = new ImageTexture(img, crc);
 
     android::Mutex::Autolock lock(m_imagesLock);
diff --git a/Source/WebCore/platform/graphics/android/rendering/ImagesManager.h b/Source/WebCore/platform/graphics/android/ImagesManager.h
similarity index 100%
rename from Source/WebCore/platform/graphics/android/rendering/ImagesManager.h
rename to Source/WebCore/platform/graphics/android/ImagesManager.h
diff --git a/Source/WebCore/platform/graphics/android/layers/Layer.cpp b/Source/WebCore/platform/graphics/android/Layer.cpp
similarity index 93%
rename from Source/WebCore/platform/graphics/android/layers/Layer.cpp
rename to Source/WebCore/platform/graphics/android/Layer.cpp
index 6eb1e91..9280461 100644
--- a/Source/WebCore/platform/graphics/android/layers/Layer.cpp
+++ b/Source/WebCore/platform/graphics/android/Layer.cpp
@@ -1,10 +1,5 @@
-#define LOG_TAG "Layer"
-#define LOG_NDEBUG 1
-
 #include "config.h"
 #include "Layer.h"
-
-#include "AndroidLog.h"
 #include "SkCanvas.h"
 
 //#define DEBUG_DRAW_LAYER_BOUNDS
@@ -41,7 +36,6 @@
     m_opacity = src.m_opacity;
     m_size = src.m_size;
     m_position = src.m_position;
-    m_scrollOffset = src.m_scrollOffset;
     m_anchorPoint = src.m_anchorPoint;
 
     m_matrix = src.m_matrix;
@@ -123,8 +117,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 void Layer::getLocalTransform(SkMatrix* matrix) const {
-    matrix->setTranslate(m_position.fX - m_scrollOffset.x(),
-                         m_position.fY - m_scrollOffset.y());
+    matrix->setTranslate(m_position.fX, m_position.fY);
 
     SkScalar tx = SkScalarMul(m_anchorPoint.fX, m_size.width());
     SkScalar ty = SkScalarMul(m_anchorPoint.fY, m_size.height());
@@ -165,9 +158,13 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+void Layer::onDraw(SkCanvas*, SkScalar opacity) {
+//    SkDebugf("----- no onDraw for %p\n", this);
+}
+
 #include "SkString.h"
 
-void Layer::draw(SkCanvas* canvas, android::DrawExtra* extra, SkScalar opacity) {
+void Layer::draw(SkCanvas* canvas, SkScalar opacity) {
 #if 0
     SkString str1, str2;
  //   getMatrix().toDumpString(&str1);
@@ -196,7 +193,7 @@
         canvas->concat(tmp);
     }
 
-    onDraw(canvas, opacity, extra, FlattenedLayers);
+    onDraw(canvas, opacity);
 
 #ifdef DEBUG_DRAW_LAYER_BOUNDS
     {
@@ -216,7 +213,7 @@
     if (count > 0) {
         canvas->concat(getChildrenMatrix());
         for (int i = 0; i < count; i++) {
-            getChild(i)->draw(canvas, extra, opacity);
+            getChild(i)->draw(canvas, opacity);
         }
     }
 }
diff --git a/Source/WebCore/platform/graphics/android/layers/Layer.h b/Source/WebCore/platform/graphics/android/Layer.h
similarity index 84%
rename from Source/WebCore/platform/graphics/android/layers/Layer.h
rename to Source/WebCore/platform/graphics/android/Layer.h
index cbdab37..5200a3d 100644
--- a/Source/WebCore/platform/graphics/android/layers/Layer.h
+++ b/Source/WebCore/platform/graphics/android/Layer.h
@@ -17,7 +17,6 @@
 #ifndef Layer_DEFINED
 #define Layer_DEFINED
 
-#include "DrawExtra.h"
 #include "TestExport.h"
 #include "SkRefCnt.h"
 #include "SkTDArray.h"
@@ -49,7 +48,6 @@
     SkScalar getOpacity() const { return m_opacity; }
     const SkSize& getSize() const { return m_size; }
     const SkPoint& getPosition() const { return m_position; }
-    const IntPoint& getScrollOffset() const { return m_scrollOffset; }
     const SkPoint& getAnchorPoint() const { return m_anchorPoint; }
     const SkMatrix& getMatrix() const { return m_matrix; }
     const SkMatrix& getChildrenMatrix() const { return m_childrenMatrix; }
@@ -61,12 +59,24 @@
     void setOpacity(SkScalar opacity) { m_opacity = opacity; }
     void setSize(SkScalar w, SkScalar h) { m_size.set(w, h); }
     void setPosition(SkScalar x, SkScalar y) { m_position.set(x, y); }
-    void setScrollOffset(IntPoint scrollOffset) { m_scrollOffset = scrollOffset; }
     void setAnchorPoint(SkScalar x, SkScalar y) { m_anchorPoint.set(x, y); }
     void setMatrix(const SkMatrix& matrix) { m_matrix = matrix; }
     void setChildrenMatrix(const SkMatrix& matrix) { m_childrenMatrix = matrix; }
 
 // rendering asset management
+
+    // tell rendering assets to update their tile content with most recent painted data
+    virtual void swapTiles() {}
+
+    // tell rendering assets to use this layer tree for drawing
+    virtual void setIsDrawing(bool isDrawing) {}
+
+    // take rendering assets from drawing tree, or create if they don't exist
+    virtual void setIsPainting(Layer* drawingTree) {}
+
+    // if a similar layer exists in the replacement tree, add invals to it
+    virtual void mergeInvalsInto(Layer* replacementTree) {}
+
     void markAsDirty(const SkRegion& invalRegion) {
         m_dirtyRegion.op(invalRegion, SkRegion::kUnion_Op);
     }
@@ -77,6 +87,14 @@
 
 // drawing
 
+    virtual bool isReady() { return false; }
+
+    // TODO: clean out several of these, leave them in GLWebViewState
+
+    virtual bool prepare(double currentTime, WebCore::IntRect& viewRect,
+                         SkRect& visibleRect, float scale) { return 0; }
+    virtual bool drawGL(WebCore::IntRect& viewRect,
+                        SkRect& visibleRect, float scale) { return 0; }
     WebCore::GLWebViewState* state() { return m_state; }
     void setState(WebCore::GLWebViewState* state);
 
@@ -122,7 +140,7 @@
         This does not include the childrenMatrix, since that is only applied
         after this layer draws (but before its children draw).
      */
-    virtual void getLocalTransform(SkMatrix* matrix) const;
+    void getLocalTransform(SkMatrix* matrix) const;
 
     /** Return, in matrix, the concatenation of transforms that are applied
         from this layer's root parent to the layer itself.
@@ -147,21 +165,20 @@
     // paint method
 
     virtual bool drawCanvas(SkCanvas*) { return false; }
-    void draw(SkCanvas*, android::DrawExtra* extra, SkScalar opacity = SK_Scalar1);
+    void draw(SkCanvas*, SkScalar opacity);
+    void draw(SkCanvas* canvas) {
+        this->draw(canvas, SK_Scalar1);
+    }
 
     void setHasOverflowChildren(bool value) { m_hasOverflowChildren = value; }
 
     virtual bool contentIsScrollable() const { return false; }
 
-    typedef enum { MergedLayers, UnmergedLayers, FlattenedLayers } PaintStyle;
 protected:
-    virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra, PaintStyle style) {}
+    virtual void onDraw(SkCanvas*, SkScalar opacity);
 
     bool m_hasOverflowChildren;
 
-    // invalidation region
-    SkRegion m_dirtyRegion;
-private:
     bool isAncestor(const Layer*) const;
 
     Layer* fParent;
@@ -169,8 +186,6 @@
     SkSize m_size;
     // The position of the origin of the layer, relative to the parent layer.
     SkPoint m_position;
-    // The scroll offset of the layer
-    IntPoint m_scrollOffset;
     // The point in the layer used as the origin for local transformations,
     // expressed as a fraction of the layer size.
     SkPoint m_anchorPoint;
@@ -180,6 +195,9 @@
 
     SkTDArray<Layer*> m_children;
 
+    // invalidation region
+    SkRegion m_dirtyRegion;
+
     WebCore::GLWebViewState* m_state;
 
     typedef SkRefCnt INHERITED;
diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
new file mode 100644
index 0000000..962bcdf
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp
@@ -0,0 +1,1476 @@
+#include "config.h"
+#include "LayerAndroid.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "AndroidAnimation.h"
+#include "ClassTracker.h"
+#include "DrawExtra.h"
+#include "GLUtils.h"
+#include "ImagesManager.h"
+#include "MediaLayer.h"
+#include "PaintedSurface.h"
+#include "ParseCanvas.h"
+#include "SkBitmapRef.h"
+#include "SkBounder.h"
+#include "SkDrawFilter.h"
+#include "SkPaint.h"
+#include "SkPicture.h"
+#include "TilesManager.h"
+
+#include <wtf/CurrentTime.h>
+#include <math.h>
+
+#define LAYER_DEBUG // Add diagonals for debugging
+#undef LAYER_DEBUG
+
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "LayerAndroid", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "LayerAndroid", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+namespace WebCore {
+
+static int gUniqueId;
+
+class OpacityDrawFilter : public SkDrawFilter {
+public:
+    OpacityDrawFilter(int opacity) : m_opacity(opacity) { }
+    virtual void filter(SkPaint* paint, Type)
+    {
+        paint->setAlpha(m_opacity);
+    }
+private:
+    int m_opacity;
+};
+
+class HasTextBounder : public SkBounder {
+    virtual bool onIRect(const SkIRect& rect)
+    {
+        return false;
+    }
+};
+
+class HasTextCanvas : public SkCanvas {
+public:
+    HasTextCanvas(SkBounder* bounder, SkPicture* picture)
+        : m_picture(picture)
+        , m_hasText(false)
+    {
+        setBounder(bounder);
+    }
+
+    void setHasText()
+    {
+        m_hasText = true;
+        m_picture->abortPlayback();
+    }
+
+    bool hasText()
+    {
+        return m_hasText;
+    }
+
+    virtual bool clipPath(const SkPath&, SkRegion::Op) {
+        return true;
+    }
+
+    virtual void commonDrawBitmap(const SkBitmap& bitmap,
+                                  const SkIRect* rect,
+                                  const SkMatrix&,
+                                  const SkPaint&) {}
+
+    virtual void drawPaint(const SkPaint& paint) {}
+    virtual void drawPath(const SkPath&, const SkPaint& paint) {}
+    virtual void drawPoints(PointMode, size_t,
+                            const SkPoint [], const SkPaint& paint) {}
+
+    virtual void drawRect(const SkRect& , const SkPaint& paint) {}
+    virtual void drawSprite(const SkBitmap& , int , int ,
+                            const SkPaint* paint = NULL) {}
+
+    virtual void drawText(const void*, size_t byteLength, SkScalar,
+                          SkScalar, const SkPaint& paint)
+    {
+        setHasText();
+    }
+
+    virtual void drawPosText(const void* , size_t byteLength,
+                             const SkPoint [], const SkPaint& paint)
+    {
+        setHasText();
+    }
+
+    virtual void drawPosTextH(const void*, size_t byteLength,
+                              const SkScalar [], SkScalar,
+                              const SkPaint& paint)
+    {
+        setHasText();
+    }
+
+    virtual void drawTextOnPath(const void*, size_t byteLength,
+                                const SkPath&, const SkMatrix*,
+                                const SkPaint& paint)
+    {
+        setHasText();
+    }
+
+    virtual void drawPicture(SkPicture& picture) {
+        SkCanvas::drawPicture(picture);
+    }
+
+private:
+
+    SkPicture* m_picture;
+    bool m_hasText;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(),
+    m_haveClip(false),
+    m_isFixed(false),
+    m_isIframe(false),
+    m_backfaceVisibility(true),
+    m_visible(true),
+    m_preserves3D(false),
+    m_anchorPointZ(0),
+    m_recordingPicture(0),
+    m_uniqueId(++gUniqueId),
+    m_texture(0),
+    m_imageCRC(0),
+    m_pictureUsed(0),
+    m_scale(1),
+    m_lastComputeTextureSize(0),
+    m_owningLayer(owner),
+    m_type(LayerAndroid::WebCoreLayer),
+    m_hasText(true)
+{
+    m_backgroundColor = 0;
+
+    m_preserves3D = false;
+    m_iframeOffset.set(0,0);
+    m_dirtyRegion.setEmpty();
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->increment("LayerAndroid");
+    ClassTracker::instance()->add(this);
+#endif
+}
+
+LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer),
+    m_haveClip(layer.m_haveClip),
+    m_isIframe(layer.m_isIframe),
+    m_uniqueId(layer.m_uniqueId),
+    m_texture(0),
+    m_owningLayer(layer.m_owningLayer),
+    m_type(LayerAndroid::UILayer),
+    m_hasText(true)
+{
+    m_isFixed = layer.m_isFixed;
+    m_imageCRC = layer.m_imageCRC;
+    if (m_imageCRC)
+        ImagesManager::instance()->retainImage(m_imageCRC);
+
+    m_renderLayerPos = layer.m_renderLayerPos;
+    m_transform = layer.m_transform;
+    m_backfaceVisibility = layer.m_backfaceVisibility;
+    m_visible = layer.m_visible;
+    m_backgroundColor = layer.m_backgroundColor;
+
+    m_fixedLeft = layer.m_fixedLeft;
+    m_fixedTop = layer.m_fixedTop;
+    m_fixedRight = layer.m_fixedRight;
+    m_fixedBottom = layer.m_fixedBottom;
+    m_fixedMarginLeft = layer.m_fixedMarginLeft;
+    m_fixedMarginTop = layer.m_fixedMarginTop;
+    m_fixedMarginRight = layer.m_fixedMarginRight;
+    m_fixedMarginBottom = layer.m_fixedMarginBottom;
+    m_fixedRect = layer.m_fixedRect;
+    m_iframeOffset = layer.m_iframeOffset;
+    m_recordingPicture = layer.m_recordingPicture;
+    SkSafeRef(m_recordingPicture);
+
+    m_preserves3D = layer.m_preserves3D;
+    m_anchorPointZ = layer.m_anchorPointZ;
+    m_drawTransform = layer.m_drawTransform;
+    m_childrenTransform = layer.m_childrenTransform;
+    m_pictureUsed = layer.m_pictureUsed;
+    m_dirtyRegion = layer.m_dirtyRegion;
+    m_scale = layer.m_scale;
+    m_lastComputeTextureSize = 0;
+
+    for (int i = 0; i < layer.countChildren(); i++)
+        addChild(layer.getChild(i)->copy())->unref();
+
+    KeyframesMap::const_iterator end = layer.m_animations.end();
+    for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) {
+        m_animations.add(it->first, it->second);
+    }
+
+    m_hasText = layer.m_hasText;
+
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->increment("LayerAndroid - recopy (UI)");
+    ClassTracker::instance()->add(this);
+#endif
+}
+
+void LayerAndroid::checkTextPresence()
+{
+    if (m_recordingPicture) {
+        // Let's check if we have text or not. If we don't, we can limit
+        // ourselves to scale 1!
+        HasTextBounder hasTextBounder;
+        HasTextCanvas checker(&hasTextBounder, m_recordingPicture);
+        SkBitmap bitmap;
+        bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+                         m_recordingPicture->width(),
+                         m_recordingPicture->height());
+        checker.setBitmapDevice(bitmap);
+        checker.drawPicture(*m_recordingPicture);
+        m_hasText = checker.hasText();
+    }
+}
+
+LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(),
+    m_haveClip(false),
+    m_isFixed(false),
+    m_isIframe(false),
+    m_recordingPicture(picture),
+    m_uniqueId(++gUniqueId),
+    m_texture(0),
+    m_imageCRC(0),
+    m_scale(1),
+    m_lastComputeTextureSize(0),
+    m_owningLayer(0),
+    m_type(LayerAndroid::NavCacheLayer),
+    m_hasText(true)
+{
+    m_backgroundColor = 0;
+    SkSafeRef(m_recordingPicture);
+    m_iframeOffset.set(0,0);
+    m_dirtyRegion.setEmpty();
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->increment("LayerAndroid - from picture");
+    ClassTracker::instance()->add(this);
+#endif
+}
+
+LayerAndroid::~LayerAndroid()
+{
+    if (m_imageCRC)
+        ImagesManager::instance()->releaseImage(m_imageCRC);
+
+    SkSafeUnref(m_recordingPicture);
+    m_animations.clear();
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->remove(this);
+    if (m_type == LayerAndroid::WebCoreLayer)
+        ClassTracker::instance()->decrement("LayerAndroid");
+    else if (m_type == LayerAndroid::UILayer)
+        ClassTracker::instance()->decrement("LayerAndroid - recopy (UI)");
+    else if (m_type == LayerAndroid::NavCacheLayer)
+        ClassTracker::instance()->decrement("LayerAndroid - from picture");
+#endif
+}
+
+static int gDebugNbAnims = 0;
+
+bool LayerAndroid::evaluateAnimations()
+{
+    double time = WTF::currentTime();
+    gDebugNbAnims = 0;
+    return evaluateAnimations(time);
+}
+
+bool LayerAndroid::hasAnimations() const
+{
+    for (int i = 0; i < countChildren(); i++) {
+        if (getChild(i)->hasAnimations())
+            return true;
+    }
+    return !!m_animations.size();
+}
+
+bool LayerAndroid::evaluateAnimations(double time)
+{
+    bool hasRunningAnimations = false;
+    for (int i = 0; i < countChildren(); i++) {
+        if (getChild(i)->evaluateAnimations(time))
+            hasRunningAnimations = true;
+    }
+
+    m_hasRunningAnimations = false;
+    int nbAnims = 0;
+    KeyframesMap::const_iterator end = m_animations.end();
+    for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
+        gDebugNbAnims++;
+        nbAnims++;
+        LayerAndroid* currentLayer = const_cast<LayerAndroid*>(this);
+        m_hasRunningAnimations |= (it->second)->evaluate(currentLayer, time);
+    }
+
+    return hasRunningAnimations || m_hasRunningAnimations;
+}
+
+void LayerAndroid::initAnimations() {
+    // tell auto-initializing animations to start now
+    for (int i = 0; i < countChildren(); i++)
+        getChild(i)->initAnimations();
+
+    KeyframesMap::const_iterator localBegin = m_animations.begin();
+    KeyframesMap::const_iterator localEnd = m_animations.end();
+    for (KeyframesMap::const_iterator localIt = localBegin; localIt != localEnd; ++localIt)
+        (localIt->second)->suggestBeginTime(WTF::currentTime());
+}
+
+void LayerAndroid::addDirtyArea()
+{
+    IntSize layerSize(getSize().width(), getSize().height());
+
+    FloatRect area = TilesManager::instance()->shader()->rectInInvScreenCoord(m_drawTransform, layerSize);
+    FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(m_clippingRect);
+    FloatRect clip = TilesManager::instance()->shader()->convertScreenCoordToInvScreenCoord(clippingRect);
+
+    area.intersect(clip);
+    IntRect dirtyArea(area.x(), area.y(), area.width(), area.height());
+    m_state->addDirtyArea(dirtyArea);
+}
+
+void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> prpAnim)
+{
+    RefPtr<AndroidAnimation> anim = prpAnim;
+    pair<String, int> key(anim->name(), anim->type());
+    removeAnimationsForProperty(anim->type());
+    m_animations.add(key, anim);
+}
+
+void LayerAndroid::removeAnimationsForProperty(AnimatedPropertyID property)
+{
+    KeyframesMap::const_iterator end = m_animations.end();
+    Vector<pair<String, int> > toDelete;
+    for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
+        if ((it->second)->type() == property)
+            toDelete.append(it->first);
+    }
+
+    for (unsigned int i = 0; i < toDelete.size(); i++)
+        m_animations.remove(toDelete[i]);
+}
+
+void LayerAndroid::removeAnimationsForKeyframes(const String& name)
+{
+    KeyframesMap::const_iterator end = m_animations.end();
+    Vector<pair<String, int> > toDelete;
+    for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
+        if ((it->second)->name() == name)
+            toDelete.append(it->first);
+    }
+
+    for (unsigned int i = 0; i < toDelete.size(); i++)
+        m_animations.remove(toDelete[i]);
+}
+
+// We only use the bounding rect of the layer as mask...
+// FIXME: use a real mask?
+void LayerAndroid::setMaskLayer(LayerAndroid* layer)
+{
+    if (layer)
+        m_haveClip = true;
+}
+
+void LayerAndroid::setBackgroundColor(SkColor color)
+{
+    m_backgroundColor = color;
+}
+
+static int gDebugChildLevel;
+
+FloatPoint LayerAndroid::translation() const
+{
+    TransformationMatrix::DecomposedType tDecomp;
+    m_transform.decompose(tDecomp);
+    FloatPoint p(tDecomp.translateX, tDecomp.translateY);
+    return p;
+}
+
+SkRect LayerAndroid::bounds() const
+{
+    SkRect rect;
+    bounds(&rect);
+    return rect;
+}
+
+void LayerAndroid::bounds(SkRect* rect) const
+{
+    const SkPoint& pos = this->getPosition();
+    const SkSize& size = this->getSize();
+
+    // The returned rect has the translation applied
+    // FIXME: apply the full transform to the rect,
+    // and fix the text selection accordingly
+    FloatPoint p(pos.fX, pos.fY);
+    p = m_transform.mapPoint(p);
+    rect->fLeft = p.x();
+    rect->fTop = p.y();
+    rect->fRight = p.x() + size.width();
+    rect->fBottom = p.y() + size.height();
+}
+
+static bool boundsIsUnique(const SkTDArray<SkRect>& region,
+                           const SkRect& local)
+{
+    for (int i = 0; i < region.count(); i++) {
+        if (region[i].contains(local))
+            return false;
+    }
+    return true;
+}
+
+void LayerAndroid::clipArea(SkTDArray<SkRect>* region) const
+{
+    SkRect local;
+    local.set(0, 0, std::numeric_limits<float>::max(),
+        std::numeric_limits<float>::max());
+    clipInner(region, local);
+}
+
+void LayerAndroid::clipInner(SkTDArray<SkRect>* region,
+                             const SkRect& local) const
+{
+    SkRect localBounds;
+    bounds(&localBounds);
+    localBounds.intersect(local);
+    if (localBounds.isEmpty())
+        return;
+    if (m_recordingPicture && boundsIsUnique(*region, localBounds))
+        *region->append() = localBounds;
+    for (int i = 0; i < countChildren(); i++)
+        getChild(i)->clipInner(region, m_haveClip ? localBounds : local);
+}
+
+class FindCheck : public SkBounder {
+public:
+    FindCheck()
+        : m_drew(false)
+        , m_drewText(false)
+    {
+    }
+
+    bool drew() const { return m_drew; }
+    bool drewText() const { return m_drewText; }
+    void reset() { m_drew = m_drewText = false; }
+
+protected:
+    virtual bool onIRect(const SkIRect& )
+    {
+        m_drew = true;
+        return false;
+    }
+
+    virtual bool onIRectGlyph(const SkIRect& , const SkBounder::GlyphRec& )
+    {
+        m_drew = m_drewText = true;
+        return false;
+    }
+
+    bool m_drew;
+    bool m_drewText;
+};
+
+class FindCanvas : public ParseCanvas {
+public:
+    void draw(SkPicture* picture, SkScalar offsetX, SkScalar offsetY)
+    {
+        save();
+        translate(-offsetX, -offsetY);
+        picture->draw(this);
+        restore();
+    }
+};
+
+class LayerAndroid::FindState {
+public:
+    static const int TOUCH_SLOP = 10;
+
+    FindState(int x, int y)
+        : m_x(x)
+        , m_y(y)
+        , m_bestX(x)
+        , m_bestY(y)
+        , m_best(0)
+    {
+        m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, TOUCH_SLOP * 2,
+             TOUCH_SLOP * 2);
+        m_checker.setBounder(&m_findCheck);
+        m_checker.setBitmapDevice(m_bitmap);
+    }
+
+    const LayerAndroid* best() const { return m_best; }
+    int bestX() const { return m_bestX; }
+    int bestY() const { return m_bestY; }
+
+    bool drew(SkPicture* picture, const SkRect& localBounds)
+    {
+        m_findCheck.reset();
+        SkScalar localX = SkIntToScalar(m_x - TOUCH_SLOP) - localBounds.fLeft;
+        SkScalar localY = SkIntToScalar(m_y - TOUCH_SLOP) - localBounds.fTop;
+        m_checker.draw(picture, localX, localY);
+        return m_findCheck.drew();
+    }
+
+    bool drewText() { return m_findCheck.drewText(); }
+
+    void setBest(const LayerAndroid* best, int x, int y)
+    {
+        m_best = best;
+        m_bestX = x;
+        m_bestY = y;
+    }
+    int x() const { return m_x; }
+    int y() const { return m_y; }
+
+    void setLocation(int x, int y)
+    {
+        m_x = x;
+        m_y = y;
+    }
+
+protected:
+    int m_x;
+    int m_y;
+    int m_bestX;
+    int m_bestY;
+    const LayerAndroid* m_best;
+    FindCheck m_findCheck;
+    SkBitmap m_bitmap;
+    FindCanvas m_checker;
+};
+
+void LayerAndroid::findInner(LayerAndroid::FindState& state) const
+{
+    int x = state.x();
+    int y = state.y();
+    SkRect localBounds;
+    bounds(&localBounds);
+    if (!localBounds.contains(x, y))
+        return;
+    // Move into local coordinates.
+    state.setLocation(x - localBounds.fLeft, y - localBounds.fTop);
+    for (int i = 0; i < countChildren(); i++)
+        getChild(i)->findInner(state);
+    // Move back into the parent coordinates.
+    int testX = state.x();
+    int testY = state.y();
+    state.setLocation(x + localBounds.fLeft, y + localBounds.fTop);
+    if (!m_recordingPicture)
+        return;
+    if (!contentIsScrollable() && !state.drew(m_recordingPicture, localBounds))
+        return;
+    state.setBest(this, testX, testY); // set last match (presumably on top)
+}
+
+const LayerAndroid* LayerAndroid::find(int* xPtr, int* yPtr, SkPicture* root) const
+{
+    FindState state(*xPtr, *yPtr);
+    SkRect rootBounds;
+    rootBounds.setEmpty();
+    if (root && state.drew(root, rootBounds) && state.drewText())
+        return 0; // use the root picture only if it contains the text
+    findInner(state);
+    *xPtr = state.bestX();
+    *yPtr = state.bestY();
+    return state.best();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* parentIframeLayer)
+{
+    bool hasFixedElements = false;
+    XLOG("updating fixed positions, using viewport %fx%f - %fx%f",
+         viewport.fLeft, viewport.fTop,
+         viewport.width(), viewport.height());
+    // If this is an iframe, accumulate the offset from the parent with
+    // current position, and change the parent pointer.
+    if (m_isIframe) {
+        // If this is the top level, take the current position
+        SkPoint parentOffset;
+        parentOffset.set(0,0);
+        if (parentIframeLayer)
+            parentOffset = parentIframeLayer->getPosition();
+
+        m_iframeOffset = parentOffset + getPosition();
+
+        parentIframeLayer = this;
+    }
+
+    if (m_isFixed) {
+        hasFixedElements = true;
+        // So if this is a fixed layer inside a iframe, use the iframe offset
+        // and the iframe's size as the viewport and pass to the children
+        if (parentIframeLayer) {
+            viewport = SkRect::MakeXYWH(parentIframeLayer->m_iframeOffset.fX,
+                                 parentIframeLayer->m_iframeOffset.fY,
+                                 parentIframeLayer->getSize().width(),
+                                 parentIframeLayer->getSize().height());
+        }
+        float w = viewport.width();
+        float h = viewport.height();
+        float dx = viewport.fLeft;
+        float dy = viewport.fTop;
+        float x = dx;
+        float y = dy;
+
+        // It turns out that when it is 'auto', we should use the webkit value
+        // from the original render layer's X,Y, that will take care of alignment
+        // with the parent's layer and fix Margin etc.
+        if (!(m_fixedLeft.defined() || m_fixedRight.defined()))
+            x += m_renderLayerPos.x();
+        else if (m_fixedLeft.defined() || !m_fixedRight.defined())
+            x += m_fixedMarginLeft.calcFloatValue(w) + m_fixedLeft.calcFloatValue(w) - m_fixedRect.fLeft;
+        else
+            x += w - m_fixedMarginRight.calcFloatValue(w) - m_fixedRight.calcFloatValue(w) - m_fixedRect.fRight;
+
+        if (!(m_fixedTop.defined() || m_fixedBottom.defined()))
+            y += m_renderLayerPos.y();
+        else if (m_fixedTop.defined() || !m_fixedBottom.defined())
+            y += m_fixedMarginTop.calcFloatValue(h) + m_fixedTop.calcFloatValue(h) - m_fixedRect.fTop;
+        else
+            y += h - m_fixedMarginBottom.calcFloatValue(h) - m_fixedBottom.calcFloatValue(h) - m_fixedRect.fBottom;
+
+        this->setPosition(x, y);
+    }
+
+    int count = this->countChildren();
+    for (int i = 0; i < count; i++)
+        hasFixedElements |= this->getChild(i)->updateFixedLayersPositions(viewport, parentIframeLayer);
+
+    return hasFixedElements;
+}
+
+void LayerAndroid::updatePositions()
+{
+    // apply the viewport to us
+    if (!m_isFixed) {
+        // turn our fields into a matrix.
+        //
+        // FIXME: this should happen in the caller, and we should remove these
+        // fields from our subclass
+        SkMatrix matrix;
+        GLUtils::toSkMatrix(matrix, m_transform);
+        this->setMatrix(matrix);
+    }
+
+    // now apply it to our children
+    int count = this->countChildren();
+    for (int i = 0; i < count; i++)
+        this->getChild(i)->updatePositions();
+}
+
+void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentMatrix,
+                                             const FloatRect& clipping, float opacity, float scale)
+{
+    m_atomicSync.lock();
+    IntSize layerSize(getSize().width(), getSize().height());
+    FloatPoint anchorPoint(getAnchorPoint().fX, getAnchorPoint().fY);
+    FloatPoint position(getPosition().fX, getPosition().fY);
+    float centerOffsetX = (0.5f - anchorPoint.x()) * layerSize.width();
+    float centerOffsetY = (0.5f - anchorPoint.y()) * layerSize.height();
+    float originX = anchorPoint.x() * layerSize.width();
+    float originY = anchorPoint.y() * layerSize.height();
+    TransformationMatrix localMatrix;
+    if (!m_isFixed)
+        localMatrix = parentMatrix;
+    localMatrix.translate3d(originX + position.x(),
+                            originY + position.y(),
+                            anchorPointZ());
+    localMatrix.multiply(m_transform);
+    localMatrix.translate3d(-originX,
+                            -originY,
+                            -anchorPointZ());
+
+    m_atomicSync.unlock();
+    setDrawTransform(localMatrix);
+    if (m_drawTransform.isIdentityOrTranslation()) {
+        // adjust the translation coordinates of the draw transform matrix so
+        // that layers (defined in content coordinates) will align to display/view pixels
+        float desiredContentX = round(m_drawTransform.m41() * scale) / scale;
+        float desiredContentY = round(m_drawTransform.m42() * scale) / scale;
+        XLOG("fudging translation from %f, %f to %f, %f",
+             m_drawTransform.m41(), m_drawTransform.m42(),
+             desiredContentX, desiredContentY);
+        m_drawTransform.setM41(desiredContentX);
+        m_drawTransform.setM42(desiredContentY);
+    }
+
+    m_zValue = TilesManager::instance()->shader()->zValue(m_drawTransform, getSize().width(), getSize().height());
+
+    m_atomicSync.lock();
+    m_scale = scale;
+    m_atomicSync.unlock();
+
+    opacity *= getOpacity();
+    setDrawOpacity(opacity);
+
+    if (m_haveClip) {
+        // The clipping rect calculation and intersetion will be done in documents coordinates.
+        FloatRect rect(0, 0, layerSize.width(), layerSize.height());
+        FloatRect clip = m_drawTransform.mapRect(rect);
+        clip.intersect(clipping);
+        setDrawClip(clip);
+    } else {
+        setDrawClip(clipping);
+    }
+
+    if (!m_backfaceVisibility
+         && m_drawTransform.inverse().m33() < 0) {
+         setVisible(false);
+         return;
+    } else {
+         setVisible(true);
+    }
+
+    int count = this->countChildren();
+    if (!count)
+        return;
+
+    // Flatten to 2D if the layer doesn't preserve 3D.
+    if (!preserves3D()) {
+        localMatrix.setM13(0);
+        localMatrix.setM23(0);
+        localMatrix.setM31(0);
+        localMatrix.setM32(0);
+        localMatrix.setM33(1);
+        localMatrix.setM34(0);
+        localMatrix.setM43(0);
+    }
+
+    // now apply it to our children
+
+    if (!m_childrenTransform.isIdentity()) {
+        localMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f);
+        localMatrix.multiply(m_childrenTransform);
+        localMatrix.translate(-getSize().width() * 0.5f, -getSize().height() * 0.5f);
+    }
+    for (int i = 0; i < count; i++)
+        this->getChild(i)->updateGLPositionsAndScale(localMatrix, drawClip(), opacity, scale);
+}
+
+void LayerAndroid::setContentsImage(SkBitmapRef* img)
+{
+    ImageTexture* image = ImagesManager::instance()->setImage(img);
+    ImagesManager::instance()->releaseImage(m_imageCRC);
+    m_imageCRC = image ? image->imageCRC() : 0;
+}
+
+bool LayerAndroid::needsTexture()
+{
+    return m_imageCRC || (m_recordingPicture
+        && m_recordingPicture->width() && m_recordingPicture->height());
+}
+
+void LayerAndroid::removeTexture(PaintedSurface* texture)
+{
+    if (texture == m_texture)
+        m_texture = 0;
+}
+
+IntRect LayerAndroid::clippedRect() const
+{
+    IntRect r(0, 0, getWidth(), getHeight());
+    IntRect tr = m_drawTransform.mapRect(r);
+    IntRect cr = TilesManager::instance()->shader()->clippedRectWithViewport(tr);
+    IntRect rect = m_drawTransform.inverse().mapRect(cr);
+    return rect;
+}
+
+int LayerAndroid::nbLayers()
+{
+    int nb = 0;
+    int count = this->countChildren();
+    for (int i = 0; i < count; i++)
+        nb += this->getChild(i)->nbLayers();
+    return nb+1;
+}
+
+int LayerAndroid::nbTexturedLayers()
+{
+    int nb = 0;
+    int count = this->countChildren();
+    for (int i = 0; i < count; i++)
+        nb += this->getChild(i)->nbTexturedLayers();
+    if (needsTexture())
+        nb++;
+    return nb;
+}
+
+void LayerAndroid::computeTexturesAmount(TexturesResult* result)
+{
+    if (!result)
+        return;
+
+    int count = this->countChildren();
+    for (int i = 0; i < count; i++)
+        this->getChild(i)->computeTexturesAmount(result);
+    if (m_texture && m_visible)
+        m_texture->computeTexturesAmount(result);
+}
+
+void LayerAndroid::showLayer(int indent)
+{
+    char spaces[256];
+    memset(spaces, 0, 256);
+    for (int i = 0; i < indent; i++)
+        spaces[i] = ' ';
+
+    if (!indent) {
+        XLOGC("\n\n--- LAYERS TREE ---");
+        IntRect documentViewport(TilesManager::instance()->shader()->documentViewport());
+        XLOGC("documentViewport(%d, %d, %d, %d)",
+              documentViewport.x(), documentViewport.y(),
+              documentViewport.width(), documentViewport.height());
+    }
+
+    IntRect r(0, 0, getWidth(), getHeight());
+    IntRect tr = m_drawTransform.mapRect(r);
+    IntRect visible = visibleArea();
+    IntRect clip(m_clippingRect.x(), m_clippingRect.y(),
+                 m_clippingRect.width(), m_clippingRect.height());
+    XLOGC("%s [%d:0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) "
+          "clip (%d, %d, %d, %d) %s %s prepareContext(%x), pic w: %d h: %d",
+          spaces, uniqueId(), m_owningLayer,
+          needsTexture() ? "needs a texture" : "no texture",
+          m_imageCRC ? "has an image" : "no image",
+          tr.x(), tr.y(), tr.width(), tr.height(),
+          visible.x(), visible.y(), visible.width(), visible.height(),
+          clip.x(), clip.y(), clip.width(), clip.height(),
+          contentIsScrollable() ? "SCROLLABLE" : "",
+          isFixed() ? "FIXED" : "",
+          m_recordingPicture,
+          m_recordingPicture ? m_recordingPicture->width() : -1,
+          m_recordingPicture ? m_recordingPicture->height() : -1);
+
+    int count = this->countChildren();
+    for (int i = 0; i < count; i++)
+        this->getChild(i)->showLayer(indent + 1);
+}
+
+void LayerAndroid::swapTiles()
+{
+    int count = this->countChildren();
+    for (int i = 0; i < count; i++)
+        this->getChild(i)->swapTiles();
+
+    if (m_texture)
+        m_texture->swapTiles();
+}
+
+void LayerAndroid::setIsDrawing(bool isDrawing)
+{
+    int count = this->countChildren();
+    for (int i = 0; i < count; i++)
+        this->getChild(i)->setIsDrawing(isDrawing);
+
+    if (m_texture) {
+        m_texture->setDrawingLayer(isDrawing ? this : 0);
+        m_texture->clearPaintingLayer();
+    }
+}
+
+void LayerAndroid::setIsPainting(Layer* drawingTree)
+{
+    XLOG("setting layer %p as painting, needs texture %d, drawing tree %p",
+         this, needsTexture(), drawingTree);
+    int count = this->countChildren();
+    for (int i = 0; i < count; i++)
+        this->getChild(i)->setIsPainting(drawingTree);
+
+
+    LayerAndroid* drawingLayer = 0;
+    if (drawingTree)
+        drawingLayer = static_cast<LayerAndroid*>(drawingTree)->findById(uniqueId());
+
+    obtainTextureForPainting(drawingLayer);
+}
+
+void LayerAndroid::mergeInvalsInto(Layer* replacementTree)
+{
+    int count = this->countChildren();
+    for (int i = 0; i < count; i++)
+        this->getChild(i)->mergeInvalsInto(replacementTree);
+
+    LayerAndroid* replacementLayer = static_cast<LayerAndroid*>(replacementTree)->findById(uniqueId());
+    if (replacementLayer)
+        replacementLayer->markAsDirty(m_dirtyRegion);
+}
+
+bool LayerAndroid::isReady()
+{
+    int count = countChildren();
+    for (int i = 0; i < count; i++)
+        if (!getChild(i)->isReady())
+            return false;
+
+    if (m_texture)
+        return m_texture->isReady();
+    // TODO: image, check if uploaded?
+    return true;
+}
+
+bool LayerAndroid::updateWithTree(LayerAndroid* newTree)
+{
+// Disable fast update for now
+#if (0)
+    bool needsRepaint = false;
+    int count = this->countChildren();
+    for (int i = 0; i < count; i++)
+        needsRepaint |= this->getChild(i)->updateWithTree(newTree);
+
+    if (newTree) {
+        LayerAndroid* newLayer = newTree->findById(uniqueId());
+        needsRepaint |= updateWithLayer(newLayer);
+    }
+    return needsRepaint;
+#else
+    return true;
+#endif
+}
+
+// Return true to indicate to WebViewCore that the updates
+// are too complicated to be fully handled and we need a full
+// call to webkit (e.g. handle repaints)
+bool LayerAndroid::updateWithLayer(LayerAndroid* layer)
+{
+    if (!layer)
+        return true;
+
+    android::AutoMutex lock(m_atomicSync);
+    m_position = layer->m_position;
+    m_anchorPoint = layer->m_anchorPoint;
+    m_size = layer->m_size;
+    m_opacity = layer->m_opacity;
+    m_transform = layer->m_transform;
+
+    if (m_imageCRC != layer->m_imageCRC)
+        m_visible = false;
+
+    if ((m_recordingPicture != layer->m_recordingPicture)
+        || (m_imageCRC != layer->m_imageCRC))
+        return true;
+
+    return false;
+}
+
+void LayerAndroid::obtainTextureForPainting(LayerAndroid* drawingLayer)
+{
+    if (!needsTexture())
+        return;
+
+    if (m_imageCRC) {
+        if (m_texture) {
+            m_texture->setDrawingLayer(0);
+            m_texture->clearPaintingLayer();
+            m_texture = 0;
+        }
+    } else {
+        if (drawingLayer) {
+            // if a previous tree had the same layer, paint with that painted surface
+            m_texture = drawingLayer->m_texture;
+        }
+
+        if (!m_texture)
+            m_texture = new PaintedSurface();
+
+        // pass the invalidated regions to the PaintedSurface
+        m_texture->setPaintingLayer(this, m_dirtyRegion);
+    }
+    m_dirtyRegion.setEmpty();
+}
+
+
+static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b)
+{
+    return a->zValue() > b->zValue();
+}
+
+// We call this in WebViewCore, when copying the tree of layers.
+// As we construct a new tree that will be passed on the UI,
+// we mark the webkit-side tree as having no more dirty region
+// (otherwise we would continuously have those dirty region UI-side)
+void LayerAndroid::clearDirtyRegion()
+{
+    int count = this->countChildren();
+    for (int i = 0; i < count; i++)
+        this->getChild(i)->clearDirtyRegion();
+
+    m_dirtyRegion.setEmpty();
+}
+
+void LayerAndroid::prepare()
+{
+    XLOG("LA %p preparing, m_texture %p", this, m_texture);
+
+    int count = this->countChildren();
+    if (count > 0) {
+        Vector <LayerAndroid*> sublayers;
+        for (int i = 0; i < count; i++)
+            sublayers.append(this->getChild(i));
+
+        // now we sort for the transparency
+        std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
+
+        // iterate in reverse so top layers get textures first
+        for (int i = count-1; i >= 0; i--)
+            sublayers[i]->prepare();
+    }
+
+    if (m_texture)
+        m_texture->prepare(m_state);
+}
+
+IntRect LayerAndroid::unclippedArea()
+{
+    IntRect area;
+    area.setX(0);
+    area.setY(0);
+    area.setWidth(getSize().width());
+    area.setHeight(getSize().height());
+    return area;
+}
+
+IntRect LayerAndroid::visibleArea()
+{
+    IntRect area = unclippedArea();
+    // First, we get the transformed area of the layer,
+    // in document coordinates
+    IntRect rect = m_drawTransform.mapRect(area);
+    int dx = rect.x();
+    int dy = rect.y();
+
+    // Then we apply the clipping
+    IntRect clip(m_clippingRect);
+    rect.intersect(clip);
+
+    // Now clip with the viewport in documents coordinate
+    IntRect documentViewport(TilesManager::instance()->shader()->documentViewport());
+    rect.intersect(documentViewport);
+
+    // Finally, let's return the visible area, in layers coordinate
+    rect.move(-dx, -dy);
+    return rect;
+}
+
+bool LayerAndroid::drawCanvas(SkCanvas* canvas)
+{
+    if (!m_visible)
+        return false;
+
+    bool askScreenUpdate = false;
+
+    {
+        SkAutoCanvasRestore acr(canvas, true);
+        SkRect r;
+        r.set(m_clippingRect.x(), m_clippingRect.y(),
+              m_clippingRect.x() + m_clippingRect.width(),
+              m_clippingRect.y() + m_clippingRect.height());
+        canvas->clipRect(r);
+        SkMatrix matrix;
+        GLUtils::toSkMatrix(matrix, m_drawTransform);
+        SkMatrix canvasMatrix = canvas->getTotalMatrix();
+        matrix.postConcat(canvasMatrix);
+        canvas->setMatrix(matrix);
+        SkRect layerRect;
+        layerRect.fLeft = 0;
+        layerRect.fTop = 0;
+        layerRect.fRight = getWidth();
+        layerRect.fBottom = getHeight();
+        onDraw(canvas, m_drawOpacity);
+    }
+
+    // When the layer is dirty, the UI thread should be notified to redraw.
+    askScreenUpdate |= drawChildrenCanvas(canvas);
+    m_atomicSync.lock();
+    if (askScreenUpdate || m_hasRunningAnimations || m_drawTransform.hasPerspective())
+        addDirtyArea();
+
+    m_atomicSync.unlock();
+    return askScreenUpdate;
+}
+
+bool LayerAndroid::drawGL()
+{
+    FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(m_clippingRect);
+    TilesManager::instance()->shader()->clip(clippingRect);
+    if (!m_visible)
+        return false;
+
+    bool askScreenUpdate = false;
+
+    if (m_state->layersRenderingMode() < GLWebViewState::kScrollableAndFixedLayers) {
+        if (m_texture)
+            askScreenUpdate |= m_texture->draw();
+        if (m_imageCRC) {
+            ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC);
+            if (imageTexture)
+                imageTexture->drawGL(this);
+            ImagesManager::instance()->releaseImage(m_imageCRC);
+        }
+    }
+
+    // When the layer is dirty, the UI thread should be notified to redraw.
+    askScreenUpdate |= drawChildrenGL();
+    m_atomicSync.lock();
+    if (askScreenUpdate || m_hasRunningAnimations || m_drawTransform.hasPerspective())
+        addDirtyArea();
+
+    m_atomicSync.unlock();
+    return askScreenUpdate;
+}
+
+bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas)
+{
+    bool askScreenUpdate = false;
+    int count = this->countChildren();
+    if (count > 0) {
+        Vector <LayerAndroid*> sublayers;
+        for (int i = 0; i < count; i++)
+            sublayers.append(this->getChild(i));
+
+        // now we sort for the transparency
+        std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
+        for (int i = 0; i < count; i++) {
+            LayerAndroid* layer = sublayers[i];
+            askScreenUpdate |= layer->drawCanvas(canvas);
+        }
+    }
+
+    return askScreenUpdate;
+}
+
+bool LayerAndroid::drawChildrenGL()
+{
+    bool askScreenUpdate = false;
+    int count = this->countChildren();
+    if (count > 0) {
+        Vector <LayerAndroid*> sublayers;
+        for (int i = 0; i < count; i++)
+            sublayers.append(this->getChild(i));
+
+        // now we sort for the transparency
+        std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
+        for (int i = 0; i < count; i++) {
+            LayerAndroid* layer = sublayers[i];
+            askScreenUpdate |= layer->drawGL();
+        }
+    }
+
+    return askScreenUpdate;
+}
+
+void LayerAndroid::contentDraw(SkCanvas* canvas)
+{
+    if (m_recordingPicture)
+      canvas->drawPicture(*m_recordingPicture);
+
+    if (TilesManager::instance()->getShowVisualIndicator()) {
+        float w = getSize().width();
+        float h = getSize().height();
+        SkPaint paint;
+        paint.setARGB(128, 255, 0, 0);
+        canvas->drawLine(0, 0, w, h, paint);
+        canvas->drawLine(0, h, w, 0, paint);
+        paint.setARGB(128, 0, 255, 0);
+        canvas->drawLine(0, 0, 0, h, paint);
+        canvas->drawLine(0, h, w, h, paint);
+        canvas->drawLine(w, h, w, 0, paint);
+        canvas->drawLine(w, 0, 0, 0, paint);
+
+        if (m_isFixed) {
+          SkPaint paint;
+          paint.setARGB(80, 255, 0, 0);
+          canvas->drawRect(m_fixedRect, paint);
+        }
+    }
+}
+
+void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity)
+{
+    if (m_haveClip) {
+        SkRect r;
+        r.set(0, 0, getSize().width(), getSize().height());
+        canvas->clipRect(r);
+        return;
+    }
+
+    if (!prepareContext())
+        return;
+
+    // we just have this save/restore for opacity...
+    SkAutoCanvasRestore restore(canvas, true);
+
+    int canvasOpacity = SkScalarRound(opacity * 255);
+    if (canvasOpacity < 255)
+        canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity));
+
+    if (m_imageCRC) {
+        ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC);
+        m_dirtyRegion.setEmpty();
+        if (imageTexture) {
+            SkRect dest;
+            dest.set(0, 0, getSize().width(), getSize().height());
+            imageTexture->drawCanvas(canvas, dest);
+        }
+        ImagesManager::instance()->releaseImage(m_imageCRC);
+    }
+    contentDraw(canvas);
+}
+
+SkPicture* LayerAndroid::recordContext()
+{
+    if (prepareContext(true))
+        return m_recordingPicture;
+    return 0;
+}
+
+bool LayerAndroid::prepareContext(bool force)
+{
+    if (masksToBounds())
+        return false;
+
+    if (force || !m_recordingPicture ||
+        (m_recordingPicture &&
+         ((m_recordingPicture->width() != (int) getSize().width()) ||
+          (m_recordingPicture->height() != (int) getSize().height())))) {
+        SkSafeUnref(m_recordingPicture);
+        m_recordingPicture = new SkPicture();
+    }
+
+    return m_recordingPicture;
+}
+
+SkRect LayerAndroid::subtractLayers(const SkRect& visibleRect) const
+{
+    SkRect result;
+    if (m_recordingPicture) {
+        // FIXME: This seems wrong. localToGlobal() applies the full local transform,
+        // se surely we should operate globalMatrix on size(), not bounds() with
+        // the position removed? Perhaps we never noticed the bug because most
+        // layers don't use a local transform?
+        // See http://b/5338388
+        SkRect globalRect = bounds();
+        globalRect.offset(-getPosition()); // localToGlobal adds in position
+        SkMatrix globalMatrix;
+        localToGlobal(&globalMatrix);
+        globalMatrix.mapRect(&globalRect);
+        SkIRect roundedGlobal;
+        globalRect.round(&roundedGlobal);
+        SkIRect iVisibleRect;
+        visibleRect.round(&iVisibleRect);
+        SkRegion visRegion(iVisibleRect);
+        visRegion.op(roundedGlobal, SkRegion::kDifference_Op);
+        result.set(visRegion.getBounds());
+#if DEBUG_NAV_UI
+        SkDebugf("%s visibleRect=(%g,%g,r=%g,b=%g) globalRect=(%g,%g,r=%g,b=%g)"
+            "result=(%g,%g,r=%g,b=%g)", __FUNCTION__,
+            visibleRect.fLeft, visibleRect.fTop,
+            visibleRect.fRight, visibleRect.fBottom,
+            globalRect.fLeft, globalRect.fTop,
+            globalRect.fRight, globalRect.fBottom,
+            result.fLeft, result.fTop, result.fRight, result.fBottom);
+#endif
+    } else
+        result = visibleRect;
+    for (int i = 0; i < countChildren(); i++)
+        result = getChild(i)->subtractLayers(result);
+    return result;
+}
+
+// Debug tools : dump the layers tree in a file.
+// The format is simple:
+// properties have the form: key = value;
+// all statements are finished with a semi-colon.
+// value can be:
+// - int
+// - float
+// - array of elements
+// - composed type
+// a composed type enclose properties in { and }
+// an array enclose composed types in { }, separated with a comma.
+// exemple:
+// {
+//   x = 3;
+//   y = 4;
+//   value = {
+//     x = 3;
+//     y = 4;
+//   };
+//   anarray = [
+//     { x = 3; },
+//     { y = 4; }
+//   ];
+// }
+
+void lwrite(FILE* file, const char* str)
+{
+    fwrite(str, sizeof(char), strlen(str), file);
+}
+
+void writeIndent(FILE* file, int indentLevel)
+{
+    if (indentLevel)
+        fprintf(file, "%*s", indentLevel*2, " ");
+}
+
+void writeln(FILE* file, int indentLevel, const char* str)
+{
+    writeIndent(file, indentLevel);
+    lwrite(file, str);
+    lwrite(file, "\n");
+}
+
+void writeIntVal(FILE* file, int indentLevel, const char* str, int value)
+{
+    writeIndent(file, indentLevel);
+    fprintf(file, "%s = %d;\n", str, value);
+}
+
+void writeHexVal(FILE* file, int indentLevel, const char* str, int value)
+{
+    writeIndent(file, indentLevel);
+    fprintf(file, "%s = %x;\n", str, value);
+}
+
+void writeFloatVal(FILE* file, int indentLevel, const char* str, float value)
+{
+    writeIndent(file, indentLevel);
+    fprintf(file, "%s = %.3f;\n", str, value);
+}
+
+void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point)
+{
+    writeIndent(file, indentLevel);
+    fprintf(file, "%s = { x = %.3f; y = %.3f; };\n", str, point.fX, point.fY);
+}
+
+void writeSize(FILE* file, int indentLevel, const char* str, SkSize size)
+{
+    writeIndent(file, indentLevel);
+    fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height());
+}
+
+void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect)
+{
+    writeIndent(file, indentLevel);
+    fprintf(file, "%s = { x = %.3f; y = %.3f; w = %.3f; h = %.3f; };\n",
+            str, rect.fLeft, rect.fTop, rect.width(), rect.height());
+}
+
+void writeLength(FILE* file, int indentLevel, const char* str, SkLength length)
+{
+    if (!length.defined())
+        return;
+    writeIndent(file, indentLevel);
+    fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value);
+}
+
+void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix)
+{
+    writeIndent(file, indentLevel);
+    fprintf(file, "%s = { (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f),"
+            "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) };\n",
+            str,
+            matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
+            matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
+            matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
+            matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44());
+}
+
+void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const
+{
+    writeln(file, indentLevel, "{");
+
+    writeHexVal(file, indentLevel + 1, "layer", (int)this);
+    writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId);
+    writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip);
+    writeIntVal(file, indentLevel + 1, "isFixed", m_isFixed);
+    writeIntVal(file, indentLevel + 1, "m_isIframe", m_isIframe);
+    writePoint(file, indentLevel + 1, "m_iframeOffset", m_iframeOffset);
+
+    writeFloatVal(file, indentLevel + 1, "opacity", getOpacity());
+    writeSize(file, indentLevel + 1, "size", getSize());
+    writePoint(file, indentLevel + 1, "position", getPosition());
+    writePoint(file, indentLevel + 1, "anchor", getAnchorPoint());
+
+    writeMatrix(file, indentLevel + 1, "drawMatrix", m_drawTransform);
+    writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform);
+    writeRect(file, indentLevel + 1, "clippingRect", SkRect(m_clippingRect));
+
+    if (m_isFixed) {
+        writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft);
+        writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop);
+        writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight);
+        writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom);
+        writeLength(file, indentLevel + 1, "fixedMarginLeft", m_fixedMarginLeft);
+        writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop);
+        writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight);
+        writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom);
+        writeRect(file, indentLevel + 1, "fixedRect", m_fixedRect);
+    }
+
+    if (m_recordingPicture) {
+        writeIntVal(file, indentLevel + 1, "m_recordingPicture.width", m_recordingPicture->width());
+        writeIntVal(file, indentLevel + 1, "m_recordingPicture.height", m_recordingPicture->height());
+    }
+
+    if (countChildren()) {
+        writeln(file, indentLevel + 1, "children = [");
+        for (int i = 0; i < countChildren(); i++) {
+            if (i > 0)
+                writeln(file, indentLevel + 1, ", ");
+            getChild(i)->dumpLayers(file, indentLevel + 1);
+        }
+        writeln(file, indentLevel + 1, "];");
+    }
+    writeln(file, indentLevel, "}");
+}
+
+void LayerAndroid::dumpToLog() const
+{
+    FILE* file = fopen("/data/data/com.android.browser/layertmp", "w");
+    dumpLayers(file, 0);
+    fclose(file);
+    file = fopen("/data/data/com.android.browser/layertmp", "r");
+    char buffer[512];
+    bzero(buffer, sizeof(buffer));
+    while (fgets(buffer, sizeof(buffer), file))
+        SkDebugf("%s", buffer);
+    fclose(file);
+}
+
+LayerAndroid* LayerAndroid::findById(int match)
+{
+    if (m_uniqueId == match)
+        return this;
+    for (int i = 0; i < countChildren(); i++) {
+        LayerAndroid* result = getChild(i)->findById(match);
+        if (result)
+            return result;
+    }
+    return 0;
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h
new file mode 100644
index 0000000..c1f1bc9
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h
@@ -0,0 +1,443 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LayerAndroid_h
+#define LayerAndroid_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "FloatPoint.h"
+#include "FloatPoint3D.h"
+#include "FloatRect.h"
+#include "GraphicsLayerClient.h"
+#include "ImageTexture.h"
+#include "Layer.h"
+#include "RefPtr.h"
+#include "SkBitmap.h"
+#include "SkColor.h"
+#include "SkRegion.h"
+#include "SkStream.h"
+#include "TransformationMatrix.h"
+
+#include <wtf/HashMap.h>
+
+#ifndef BZERO_DEFINED
+#define BZERO_DEFINED
+// http://www.opengroup.org/onlinepubs/000095399/functions/bzero.html
+// For maximum portability, it is recommended to replace the function call to bzero() as follows:
+#define bzero(b, len) (memset((b), '\0', (len)), (void) 0)
+#endif
+
+class SkBitmapRef;
+class SkCanvas;
+class SkMatrix;
+class SkPicture;
+
+namespace WebCore {
+class LayerAndroid;
+class ImageTexture;
+}
+
+namespace android {
+class DrawExtra;
+void serializeLayer(WebCore::LayerAndroid* layer, SkWStream* stream);
+WebCore::LayerAndroid* deserializeLayer(SkStream* stream);
+void cleanupImageRefs(WebCore::LayerAndroid* layer);
+}
+
+using namespace android;
+
+struct SkLength {
+    enum SkLengthType { Undefined, Auto, Relative, Percent, Fixed, Static, Intrinsic, MinIntrinsic };
+    SkLengthType type;
+    SkScalar value;
+    SkLength()
+    {
+        type = Undefined;
+        value = 0;
+    }
+    bool defined() const
+    {
+        if (type == Undefined)
+            return false;
+        return true;
+    }
+    float calcFloatValue(float max) const
+    {
+        switch (type) {
+        case Percent:
+            return (max * value) / 100.0f;
+        case Fixed:
+            return value;
+        default:
+            return value;
+        }
+    }
+};
+
+namespace WebCore {
+
+class AndroidAnimation;
+class BaseTileTexture;
+class GLWebViewState;
+class LayerAndroidFindState;
+class RenderLayer;
+class TiledPage;
+class PaintedSurface;
+
+class TexturesResult {
+public:
+    TexturesResult()
+        : fixed(0)
+        , scrollable(0)
+        , clipped(0)
+        , full(0)
+    {}
+
+    int fixed;
+    int scrollable;
+    int clipped;
+    int full;
+};
+
+class TEST_EXPORT LayerAndroid : public Layer {
+public:
+    enum LayerType { UndefinedLayer, WebCoreLayer, UILayer, NavCacheLayer };
+
+    LayerAndroid(RenderLayer* owner);
+    LayerAndroid(const LayerAndroid& layer);
+    LayerAndroid(SkPicture*);
+    virtual ~LayerAndroid();
+
+    virtual TiledPage* page() { return 0; }
+
+    void setBackfaceVisibility(bool value) { m_backfaceVisibility = value; }
+    void setTransform(const TransformationMatrix& matrix) { m_transform = matrix; }
+    FloatPoint translation() const;
+    // Returns a rect describing the bounds of the layer with the local
+    // transformation applied, expressed relative to the parent layer.
+    // FIXME: Currently we use only the translation component of the local
+    // transformation.
+    SkRect bounds() const;
+    IntRect clippedRect() const;
+    bool outsideViewport();
+
+    IntRect unclippedArea();
+    IntRect visibleArea();
+
+    virtual bool needsTexture();
+    void removeTexture(PaintedSurface*);
+
+    // Debug helper methods
+    int nbLayers();
+    int nbTexturedLayers();
+    void showLayer(int indent = 0);
+
+    void computeTexturesAmount(TexturesResult*);
+
+    float getScale() { return m_scale; }
+
+    // draw layer and its children via Z, pre-order traversal
+    virtual bool drawGL();
+    bool drawChildrenGL();
+    virtual bool drawCanvas(SkCanvas*);
+    bool drawChildrenCanvas(SkCanvas*);
+
+    // prepare layer and its children via reverse-Z, post-order traversal
+    void prepare();
+
+    void updateGLPositionsAndScale(const TransformationMatrix& parentMatrix,
+                                   const FloatRect& clip, float opacity, float scale);
+    void setDrawOpacity(float opacity) { m_drawOpacity = opacity; }
+    float drawOpacity() { return m_drawOpacity; }
+    void setVisible(bool value) { m_visible = value; }
+
+    bool preserves3D() { return m_preserves3D; }
+    void setPreserves3D(bool value) { m_preserves3D = value; }
+    void setAnchorPointZ(float z) { m_anchorPointZ = z; }
+    float anchorPointZ() { return m_anchorPointZ; }
+    void setDrawTransform(const TransformationMatrix& transform) { m_drawTransform = transform; }
+    const TransformationMatrix* drawTransform() const { return &m_drawTransform; }
+    void setChildrenTransform(const TransformationMatrix& t) { m_childrenTransform = t; }
+    void setDrawClip(const FloatRect& rect) { m_clippingRect = rect; }
+    const FloatRect& drawClip() { return m_clippingRect; }
+
+    void setFixedPosition(SkLength left, // CSS left property
+                          SkLength top, // CSS top property
+                          SkLength right, // CSS right property
+                          SkLength bottom, // CSS bottom property
+                          SkLength marginLeft, // CSS margin-left property
+                          SkLength marginTop, // CSS margin-top property
+                          SkLength marginRight, // CSS margin-right property
+                          SkLength marginBottom, // CSS margin-bottom property
+                          const IntPoint& renderLayerPos, // For undefined fixed position
+                          SkRect viewRect) { // view rect, can be smaller than the layer's
+        m_fixedLeft = left;
+        m_fixedTop = top;
+        m_fixedRight = right;
+        m_fixedBottom = bottom;
+        m_fixedMarginLeft = marginLeft;
+        m_fixedMarginTop = marginTop;
+        m_fixedMarginRight = marginRight;
+        m_fixedMarginBottom = marginBottom;
+        m_fixedRect = viewRect;
+        m_isFixed = true;
+        m_renderLayerPos = renderLayerPos;
+        setShouldInheritFromRootTransform(true);
+    }
+
+    void setBackgroundColor(SkColor color);
+    void setMaskLayer(LayerAndroid*);
+    void setMasksToBounds(bool masksToBounds)
+    {
+        m_haveClip = masksToBounds;
+    }
+    bool masksToBounds() const { return m_haveClip; }
+
+    SkPicture* recordContext();
+
+    void addAnimation(PassRefPtr<AndroidAnimation> anim);
+    void removeAnimationsForProperty(AnimatedPropertyID property);
+    void removeAnimationsForKeyframes(const String& name);
+    bool evaluateAnimations();
+    bool evaluateAnimations(double time);
+    void initAnimations();
+    bool hasAnimations() const;
+    void addDirtyArea();
+
+    SkPicture* picture() const { return m_recordingPicture; }
+
+    // Given a rect in global space, subtracts from it the bounds of this layer
+    // and of all of its children. Returns the bounding rectangle of the result,
+    // in global space.
+    SkRect subtractLayers(const SkRect&) const;
+
+    void dumpLayers(FILE*, int indentLevel) const;
+    void dumpToLog() const;
+
+    /** Call this with the current viewport (scrolling, zoom) to update
+        the position of the fixed layers.
+
+        This call is recursive, so it should be called on the root of the
+        hierarchy.
+    */
+    bool updateFixedLayersPositions(SkRect viewPort, LayerAndroid* parentIframeLayer = 0);
+
+    /** Call this to update the position attribute, so that later calls
+        like bounds() will report the corrected position.
+
+        This call is recursive, so it should be called on the root of the
+        hierarchy.
+     */
+    void updatePositions();
+
+    void clipArea(SkTDArray<SkRect>* region) const;
+    const LayerAndroid* find(int* xPtr, int* yPtr, SkPicture* root) const;
+    const LayerAndroid* findById(int uniqueID) const
+    {
+        return const_cast<LayerAndroid*>(this)->findById(uniqueID);
+    }
+    LayerAndroid* findById(int uniqueID);
+    LayerAndroid* getChild(int index) const
+    {
+        return static_cast<LayerAndroid*>(this->INHERITED::getChild(index));
+    }
+    int uniqueId() const { return m_uniqueId; }
+    bool isFixed() { return m_isFixed; }
+
+    /** This sets a content image -- calling it means we will use
+        the image directly when drawing the layer instead of using
+        the content painted by WebKit.
+        Images are handled in ImagesManager, as they can be shared
+        between layers.
+    */
+    void setContentsImage(SkBitmapRef* img);
+
+    void bounds(SkRect*) const;
+
+    virtual LayerAndroid* copy() const { return new LayerAndroid(*this); }
+
+    void needsRepaint() { m_pictureUsed++; }
+    unsigned int pictureUsed() { return m_pictureUsed; }
+
+    void clearDirtyRegion();
+
+    void contentDraw(SkCanvas*);
+
+    virtual bool isMedia() const { return false; }
+    virtual bool isVideo() const { return false; }
+
+    RenderLayer* owningLayer() const { return m_owningLayer; }
+
+    void setIsIframe(bool isIframe) { m_isIframe = isIframe; }
+    float zValue() const { return m_zValue; }
+
+    // ViewStateSerializer friends
+    friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream);
+    friend LayerAndroid* android::deserializeLayer(SkStream* stream);
+    friend void android::cleanupImageRefs(LayerAndroid* layer);
+
+    PaintedSurface* texture() { return m_texture; }
+    void obtainTextureForPainting(LayerAndroid* drawingLayer);
+
+    // Update layers using another tree. Only works for basic properties
+    // such as the position, the transform. Return true if anything more
+    // complex is needed.
+    bool updateWithTree(LayerAndroid*);
+    virtual bool updateWithLayer(LayerAndroid*);
+
+    int type() { return m_type; }
+
+    bool hasText() { return m_hasText; }
+    void checkTextPresence();
+
+    void copyAnimationStartTimesRecursive(LayerAndroid* oldTree);
+
+// rendering asset management
+    void swapTiles();
+    void setIsDrawing(bool isDrawing);
+    void setIsPainting(Layer* drawingTree);
+    void mergeInvalsInto(Layer* replacementTree);
+    bool isReady();
+
+protected:
+    virtual void onDraw(SkCanvas*, SkScalar opacity);
+
+    TransformationMatrix m_drawTransform;
+
+private:
+    class FindState;
+#if DUMP_NAV_CACHE
+    friend class CachedLayer::Debug; // debugging access only
+#endif
+
+    void copyAnimationStartTimes(LayerAndroid* oldLayer);
+    void findInner(FindState&) const;
+    bool prepareContext(bool force = false);
+    void clipInner(SkTDArray<SkRect>* region, const SkRect& local) const;
+
+    // -------------------------------------------------------------------
+    // Fields to be serialized
+    // -------------------------------------------------------------------
+
+    bool m_haveClip;
+    bool m_isFixed;
+    bool m_backgroundColorSet;
+    bool m_isIframe;
+
+    SkLength m_fixedLeft;
+    SkLength m_fixedTop;
+    SkLength m_fixedRight;
+    SkLength m_fixedBottom;
+    SkLength m_fixedMarginLeft;
+    SkLength m_fixedMarginTop;
+    SkLength m_fixedMarginRight;
+    SkLength m_fixedMarginBottom;
+    SkRect m_fixedRect;
+
+    // When fixed element is undefined or auto, the render layer's position
+    // is needed for offset computation
+    IntPoint m_renderLayerPos;
+
+    bool m_backfaceVisibility;
+    bool m_visible;
+
+    SkColor m_backgroundColor;
+
+    bool m_preserves3D;
+    float m_anchorPointZ;
+    float m_drawOpacity;
+
+    // Note that m_recordingPicture and m_imageRef are mutually exclusive;
+    // m_recordingPicture is used when WebKit is asked to paint the layer's
+    // content, while m_imageRef contains an image that we directly
+    // composite, using the layer's dimensions as a destination rect.
+    // We do this as if the layer only contains an image, directly compositing
+    // it is a much faster method than using m_recordingPicture.
+    SkPicture* m_recordingPicture;
+
+    typedef HashMap<pair<String, int>, RefPtr<AndroidAnimation> > KeyframesMap;
+    KeyframesMap m_animations;
+
+    TransformationMatrix m_transform;
+    TransformationMatrix m_childrenTransform;
+
+    // -------------------------------------------------------------------
+    // Fields that are not serialized (generated, cached, or non-serializable)
+    // -------------------------------------------------------------------
+
+    SkPoint m_iframeOffset;
+
+    float m_zValue;
+
+    FloatRect m_clippingRect;
+
+    int m_uniqueId;
+
+    PaintedSurface* m_texture;
+    unsigned m_imageCRC;
+
+    unsigned int m_pictureUsed;
+
+    // used to signal the framework we need a repaint
+    bool m_hasRunningAnimations;
+
+    float m_scale;
+
+    // We try to not always compute the texture size, as this is quite heavy
+    static const double s_computeTextureDelay = 0.2; // 200 ms
+    double m_lastComputeTextureSize;
+
+    // This mutex serves two purposes. (1) It ensures that certain operations
+    // happen atomically and (2) it makes sure those operations are synchronized
+    // across all threads and cores.
+    android::Mutex m_atomicSync;
+
+    RenderLayer* m_owningLayer;
+
+    int m_type;
+
+    bool m_hasText;
+
+    typedef Layer INHERITED;
+};
+
+}
+
+#else
+
+class SkPicture;
+
+namespace WebCore {
+
+class LayerAndroid {
+public:
+    LayerAndroid(SkPicture* picture) :
+        m_recordingPicture(picture), // does not assign ownership
+        m_uniqueId(-1)
+    {}
+    SkPicture* picture() const { return m_recordingPicture; }
+    int uniqueId() const { return m_uniqueId; }
+private:
+    SkPicture* m_recordingPicture;
+    int m_uniqueId;
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // LayerAndroid_h
diff --git a/Source/WebCore/platform/graphics/android/layers/MediaLayer.cpp b/Source/WebCore/platform/graphics/android/MediaLayer.cpp
similarity index 83%
rename from Source/WebCore/platform/graphics/android/layers/MediaLayer.cpp
rename to Source/WebCore/platform/graphics/android/MediaLayer.cpp
index 7a3730b..12cfe38 100644
--- a/Source/WebCore/platform/graphics/android/layers/MediaLayer.cpp
+++ b/Source/WebCore/platform/graphics/android/MediaLayer.cpp
@@ -13,29 +13,41 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#define LOG_TAG "MediaLayer"
-#define LOG_NDEBUG 1
-
 #include "config.h"
 #include "MediaLayer.h"
-
-#include "AndroidLog.h"
 #include "MediaTexture.h"
 #include "TilesManager.h"
 
 #if USE(ACCELERATED_COMPOSITING)
 
+#define LAYER_DEBUG
+#undef LAYER_DEBUG
+
+#ifdef DEBUG
+
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "MediaLayer", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
 namespace WebCore {
 
-MediaLayer::MediaLayer(jobject webViewRef, jobject webViewCoreRef) : LayerAndroid((RenderLayer*) NULL)
+MediaLayer::MediaLayer(jobject webViewRef) : LayerAndroid((RenderLayer*) NULL)
 {
-    m_mediaTexture = new MediaTexture(webViewRef, webViewCoreRef);
+    m_mediaTexture = new MediaTexture(webViewRef);
     m_mediaTexture->incStrong(this);
 
     m_isCopy = false;
     m_outlineSize = 0;
-    ALOGV("Creating Media Layer %p", this);
+    XLOG("Creating Media Layer %p", this);
 }
 
 MediaLayer::MediaLayer(const MediaLayer& layer) : LayerAndroid(layer)
@@ -45,18 +57,18 @@
 
     m_isCopy = true;
     m_outlineSize = layer.m_outlineSize;
-    ALOGV("Creating Media Layer Copy %p -> %p", &layer, this);
+    XLOG("Creating Media Layer Copy %p -> %p", &layer, this);
 }
 
 MediaLayer::~MediaLayer()
 {
-    ALOGV("Deleting Media Layer");
+    XLOG("Deleting Media Layer");
     m_mediaTexture->decStrong(this);
 }
 
-bool MediaLayer::drawGL(bool layerTilesDisabled)
+bool MediaLayer::drawGL()
 {
-    FloatRect clippingRect = TilesManager::instance()->shader()->rectInInvViewCoord(drawClip());
+    FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(drawClip());
     TilesManager::instance()->shader()->clip(clippingRect);
 
     // when the plugin gains focus webkit applies an outline to the
@@ -80,7 +92,8 @@
 
     // draw any content or video if present
     m_mediaTexture->draw(m, m_drawTransform, mediaBounds);
-    return false;
+
+    return drawChildrenGL();
 }
 
 ANativeWindow* MediaLayer::acquireNativeWindowForContent()
diff --git a/Source/WebCore/platform/graphics/android/layers/MediaLayer.h b/Source/WebCore/platform/graphics/android/MediaLayer.h
similarity index 92%
rename from Source/WebCore/platform/graphics/android/layers/MediaLayer.h
rename to Source/WebCore/platform/graphics/android/MediaLayer.h
index 8e04681..b94ec53 100644
--- a/Source/WebCore/platform/graphics/android/layers/MediaLayer.h
+++ b/Source/WebCore/platform/graphics/android/MediaLayer.h
@@ -32,14 +32,13 @@
 class MediaLayer : public LayerAndroid {
 
 public:
-    MediaLayer(jobject webViewRef, jobject webViewCoreRef);
+    MediaLayer(jobject webViewRef);
     MediaLayer(const MediaLayer& layer);
     virtual ~MediaLayer();
 
-    virtual bool drawGL(bool layerTilesDisabled);
+    virtual bool drawGL();
     virtual void paintBitmapGL() const { };
     virtual bool needsTexture() { return false; }
-    virtual bool needsIsolatedSurface() { return true; }
 
     virtual bool isMedia() const { return true; }
     virtual LayerAndroid* copy() const { return new MediaLayer(*this); }
diff --git a/Source/WebCore/platform/graphics/android/layers/MediaListener.h b/Source/WebCore/platform/graphics/android/MediaListener.h
similarity index 92%
rename from Source/WebCore/platform/graphics/android/layers/MediaListener.h
rename to Source/WebCore/platform/graphics/android/MediaListener.h
index 2dfc08b..5fcbbb2 100644
--- a/Source/WebCore/platform/graphics/android/layers/MediaListener.h
+++ b/Source/WebCore/platform/graphics/android/MediaListener.h
@@ -26,6 +26,21 @@
 #include "MediaTexture.h"
 #include "WebCoreJni.h"
 
+#ifdef DEBUG
+
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "MediaListener", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
 namespace WebCore {
 
 class MediaListener : public android::SurfaceTexture::FrameAvailableListener {
diff --git a/Source/WebCore/platform/graphics/android/layers/MediaPlayerPrivateAndroid.h b/Source/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h
similarity index 98%
rename from Source/WebCore/platform/graphics/android/layers/MediaPlayerPrivateAndroid.h
rename to Source/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h
index 17fd4d8..404ef08 100644
--- a/Source/WebCore/platform/graphics/android/layers/MediaPlayerPrivateAndroid.h
+++ b/Source/WebCore/platform/graphics/android/MediaPlayerPrivateAndroid.h
@@ -91,12 +91,10 @@
 
     virtual void onPrepared(int duration, int width, int height) { }
     void onEnded();
-    void onRequestPlay();
     void onPaused();
     virtual void onPosterFetched(SkBitmap*) { }
     void onBuffering(int percent);
     void onTimeupdate(int position);
-    void onRestoreState();
 
     // These following two functions are used to turn on inline video support
     bool supportsAcceleratedRendering() const { return true; }
diff --git a/Source/WebCore/platform/graphics/android/layers/MediaTexture.cpp b/Source/WebCore/platform/graphics/android/MediaTexture.cpp
similarity index 84%
rename from Source/WebCore/platform/graphics/android/layers/MediaTexture.cpp
rename to Source/WebCore/platform/graphics/android/MediaTexture.cpp
index dffe6c2..1676186 100644
--- a/Source/WebCore/platform/graphics/android/layers/MediaTexture.cpp
+++ b/Source/WebCore/platform/graphics/android/MediaTexture.cpp
@@ -13,15 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-#define LOG_TAG "MediaTexture"
-#define LOG_NDEBUG 1
-
 #include "config.h"
 #include "MediaTexture.h"
-
-#include "AndroidLog.h"
-#include "DrawQuadData.h"
 #include "TilesManager.h"
 #include "GLUtils.h"
 #include "MediaListener.h"
@@ -31,9 +24,28 @@
 #include <android/native_window.h>
 #include <gui/SurfaceTexture.h>
 #include <gui/SurfaceTextureClient.h>
+#include <wtf/CurrentTime.h>
 #include <JNIUtility.h>
 #include "WebCoreJni.h"
 
+#define LAYER_DEBUG
+#undef LAYER_DEBUG
+
+#ifdef DEBUG
+
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "MediaTexture", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
 // Limits the number of ANativeWindows that can be allocated for video playback.
 // The limit is currently set to 2 as that is the current max number of
 // simultaneous HW decodes that our OMX implementation allows.  This forces the
@@ -42,11 +54,14 @@
 
 namespace WebCore {
 
-MediaTexture::MediaTexture(jobject webViewRef, jobject webViewCoreRef) : android::LightRefBase<MediaTexture>()
+MediaTexture::MediaTexture(jobject webViewRef) : android::LightRefBase<MediaTexture>()
 {
-    JNIEnv* env = JSC::Bindings::getJNIEnv();
-    m_weakWebViewRef = env->NewWeakGlobalRef(webViewRef);
-    m_weakWebViewCoreRef = env->NewWeakGlobalRef(webViewCoreRef);
+    if (webViewRef) {
+        JNIEnv* env = JSC::Bindings::getJNIEnv();
+        m_weakWebViewRef = env->NewWeakGlobalRef(webViewRef);
+    } else {
+        m_weakWebViewRef = 0;
+    }
 
     m_contentTexture = 0;
     m_isContentInverted = false;
@@ -61,9 +76,10 @@
         deleteTexture(m_videoTextures[i], true);
     }
 
-    JNIEnv* env = JSC::Bindings::getJNIEnv();
-    env->DeleteWeakGlobalRef(m_weakWebViewRef);
-    env->DeleteWeakGlobalRef(m_weakWebViewCoreRef);
+    if (m_weakWebViewRef) {
+        JNIEnv* env = JSC::Bindings::getJNIEnv();
+        env->DeleteWeakGlobalRef(m_weakWebViewRef);
+    }
 }
 
 bool MediaTexture::isContentInverted()
@@ -95,16 +111,16 @@
             m_contentTexture = createTexture();
 
             // send a message to the WebKit thread to notify the plugin that it can draw
-            if (m_weakWebViewCoreRef) {
+            if (m_weakWebViewRef) {
                 JNIEnv* env = JSC::Bindings::getJNIEnv();
-                jobject localWebViewCoreRef = env->NewLocalRef(m_weakWebViewCoreRef);
-                if (localWebViewCoreRef) {
-                    jclass wvClass = env->GetObjectClass(localWebViewCoreRef);
+                jobject localWebViewRef = env->NewLocalRef(m_weakWebViewRef);
+                if (localWebViewRef) {
+                    jclass wvClass = env->GetObjectClass(localWebViewRef);
                     jmethodID sendPluginDrawMsg =
                             env->GetMethodID(wvClass, "sendPluginDrawMsg", "()V");
-                    env->CallVoidMethod(localWebViewCoreRef, sendPluginDrawMsg);
+                    env->CallVoidMethod(localWebViewRef, sendPluginDrawMsg);
                     env->DeleteLocalRef(wvClass);
-                    env->DeleteLocalRef(localWebViewCoreRef);
+                    env->DeleteLocalRef(localWebViewRef);
                 }
                 checkException(env);
             }
@@ -155,7 +171,7 @@
 
 #ifdef DEBUG
         if (!mediaBounds.contains(dimensions)) {
-            ALOGV("The video exceeds is parent's bounds.");
+            XLOG("The video exceeds is parent's bounds.");
         }
 #endif // DEBUG
 
@@ -175,12 +191,14 @@
     bool forceAlphaBlending = !(
         PIXEL_FORMAT_RGBX_8888 == f ||
         PIXEL_FORMAT_RGB_888 == f ||
-        PIXEL_FORMAT_RGB_565 == f);
+        PIXEL_FORMAT_RGB_565 == f ||
+        PIXEL_FORMAT_RGB_332 == f);
 
-    TextureQuadData data(m_contentTexture->textureId, GL_TEXTURE_EXTERNAL_OES,
-                         GL_LINEAR, LayerQuad, &contentMatrix, &mediaBounds,
-                         1.0f, forceAlphaBlending);
-    TilesManager::instance()->shader()->drawQuad(&data);
+    TilesManager::instance()->shader()->drawLayerQuad(contentMatrix,
+                                                      mediaBounds,
+                                                      m_contentTexture->textureId,
+                                                      1.0f, forceAlphaBlending,
+                                                      GL_TEXTURE_EXTERNAL_OES);
 }
 
 ANativeWindow* MediaTexture::requestNativeWindowForVideo()
@@ -265,6 +283,7 @@
 void MediaTexture::setFramerateCallback(const ANativeWindow* window,
                                         FramerateCallbackProc callback)
 {
+    XLOG("Release ANW %p (%p):(%p)", this, m_surfaceTexture.get(), m_surfaceTextureClient.get());
     android::Mutex::Autolock lock(m_mediaLock);
     for (unsigned int i = 0; i < m_videoTextures.size(); i++) {
         if (m_videoTextures[i]->nativeWindow.get() == window) {
diff --git a/Source/WebCore/platform/graphics/android/layers/MediaTexture.h b/Source/WebCore/platform/graphics/android/MediaTexture.h
similarity index 96%
rename from Source/WebCore/platform/graphics/android/layers/MediaTexture.h
rename to Source/WebCore/platform/graphics/android/MediaTexture.h
index 9ea7be2..97bb530 100644
--- a/Source/WebCore/platform/graphics/android/layers/MediaTexture.h
+++ b/Source/WebCore/platform/graphics/android/MediaTexture.h
@@ -40,7 +40,7 @@
 class MediaTexture : public android::LightRefBase<MediaTexture> {
 
 public:
-    MediaTexture(jobject webViewRef, jobject webViewCoreRef);
+    MediaTexture(jobject webViewRef);
     ~MediaTexture();
 
     bool isContentInverted();
@@ -83,7 +83,6 @@
     sp<ANativeWindow> m_newWindow;
 
     jobject m_weakWebViewRef;
-    jobject m_weakWebViewCoreRef;
 
     android::Mutex m_mediaLock;
     android::Condition m_newMediaRequestCond;
diff --git a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp b/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp
similarity index 68%
rename from Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp
rename to Source/WebCore/platform/graphics/android/PaintTileOperation.cpp
index 3fcbdb2..2d69706 100644
--- a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.cpp
+++ b/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp
@@ -23,36 +23,23 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#define LOG_TAG "PaintTileOperation"
-#define LOG_NDEBUG 1
-
 #include "config.h"
 #include "PaintTileOperation.h"
-
-#include "AndroidLog.h"
-#include "ClassTracker.h"
-#include "GLWebViewState.h"
 #include "ImageTexture.h"
 #include "ImagesManager.h"
 #include "LayerAndroid.h"
-#include "TexturesGenerator.h"
-#include "TilesManager.h"
+#include "PaintedSurface.h"
 
 namespace WebCore {
 
-PaintTileOperation::PaintTileOperation(Tile* tile, TilePainter* painter,
-                                       GLWebViewState* state, bool isLowResPrefetch)
-    : m_tile(tile)
-    , m_painter(painter)
-    , m_state(state)
-    , m_isLowResPrefetch(isLowResPrefetch)
+PaintTileOperation::PaintTileOperation(BaseTile* tile, SurfacePainter* surface)
+    : QueuedOperation(QueuedOperation::PaintTile, tile->page())
+    , m_tile(tile)
+    , m_surface(surface)
 {
     if (m_tile)
         m_tile->setRepaintPending(true);
-    SkSafeRef(m_painter);
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->increment("PaintTileOperation");
-#endif
+    SkSafeRef(m_surface);
 }
 
 PaintTileOperation::~PaintTileOperation()
@@ -62,29 +49,26 @@
         m_tile = 0;
     }
 
-    if (m_painter && m_painter->type() == TilePainter::Image) {
-        ImageTexture* image = static_cast<ImageTexture*>(m_painter);
+    if (m_surface && m_surface->type() == SurfacePainter::ImageSurface) {
+        ImageTexture* image = static_cast<ImageTexture*>(m_surface);
         ImagesManager::instance()->releaseImage(image->imageCRC());
     } else {
-        SkSafeUnref(m_painter);
+        SkSafeUnref(m_surface);
     }
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->decrement("PaintTileOperation");
-#endif
 }
 
 bool PaintTileOperation::operator==(const QueuedOperation* operation)
 {
+    if (operation->type() != type())
+        return false;
     const PaintTileOperation* op = static_cast<const PaintTileOperation*>(operation);
     return op->m_tile == m_tile;
 }
 
 void PaintTileOperation::run()
 {
-    TRACE_METHOD();
-
     if (m_tile) {
-        m_tile->paintBitmap(m_painter);
+        m_tile->paintBitmap();
         m_tile->setRepaintPending(false);
         m_tile = 0;
     }
@@ -97,9 +81,14 @@
 
     int priority = 200000;
 
-    // prioritize low res while scrolling, otherwise set priority above gDeferPriorityCutoff
-    if (m_isLowResPrefetch)
-        priority = m_state->isScrolling() ? 0 : TexturesGenerator::gDeferPriorityCutoff;
+    // if scrolling, prioritize the prefetch page, otherwise deprioritize
+    TiledPage* page = m_tile->page();
+    if (page && page->isPrefetchPage()) {
+        if (page->glWebViewState()->isScrolling())
+            priority = 0;
+        else
+            priority = 400000;
+    }
 
     // prioritize higher draw count
     unsigned long long currentDraw = TilesManager::instance()->getDrawGLCount();
@@ -112,7 +101,7 @@
 
     // for base tiles, prioritize based on position
     if (!m_tile->isLayerTile()) {
-        bool goingDown = m_state->goingDown();
+        bool goingDown = m_tile->page()->scrollingDown();
         priority += m_tile->x();
 
         if (goingDown)
@@ -124,14 +113,4 @@
     return priority;
 }
 
-void PaintTileOperation::updatePainter(TilePainter* painter)
-{
-    if (m_painter == painter)
-        return;
-
-    SkSafeRef(painter);
-    SkSafeUnref(m_painter);
-    m_painter = painter;
-}
-
 }
diff --git a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h b/Source/WebCore/platform/graphics/android/PaintTileOperation.h
similarity index 74%
rename from Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h
rename to Source/WebCore/platform/graphics/android/PaintTileOperation.h
index c82cdcd..bc74d03 100644
--- a/Source/WebCore/platform/graphics/android/rendering/PaintTileOperation.h
+++ b/Source/WebCore/platform/graphics/android/PaintTileOperation.h
@@ -26,50 +26,48 @@
 #ifndef PaintTileSetOperation_h
 #define PaintTileSetOperation_h
 
-#include "Tile.h"
+#include "BaseTile.h"
 #include "QueuedOperation.h"
 #include "SkRefCnt.h"
 
 namespace WebCore {
 
 class LayerAndroid;
-class TilePainter;
+class SurfacePainter;
 class ImageTexture;
 
 class PaintTileOperation : public QueuedOperation {
 public:
-    PaintTileOperation(Tile* tile, TilePainter* painter,
-                       GLWebViewState* state, bool isLowResPrefetch);
+    PaintTileOperation(BaseTile* tile, SurfacePainter* surface = 0);
     virtual ~PaintTileOperation();
     virtual bool operator==(const QueuedOperation* operation);
     virtual void run();
-    virtual void* uniquePtr() { return m_tile; }
     // returns a rendering priority for m_tile, lower values are processed faster
     virtual int priority();
-
-    TilePainter* painter() { return m_painter; }
-    void updatePainter(TilePainter* painter);
+    TilePainter* painter() { return m_tile->painter(); }
     float scale() { return m_tile->scale(); }
 
 private:
-    Tile* m_tile;
-    TilePainter* m_painter;
-    GLWebViewState* m_state;
-    bool m_isLowResPrefetch;
+    BaseTile* m_tile;
+    SurfacePainter* m_surface;
 };
 
 class ScaleFilter : public OperationFilter {
 public:
-    ScaleFilter(const TilePainter* painter, float scale)
+    ScaleFilter(TilePainter* painter, float scale)
         : m_painter(painter)
         , m_scale(scale) {}
     virtual bool check(QueuedOperation* operation)
     {
-        PaintTileOperation* op = static_cast<PaintTileOperation*>(operation);
-        return ((op->painter() == m_painter) && (op->scale() != m_scale));
+        if (operation->type() == QueuedOperation::PaintTile) {
+            PaintTileOperation* op = static_cast<PaintTileOperation*>(operation);
+            if ((op->painter() == m_painter) && (op->scale() != m_scale))
+                return true;
+        }
+        return false;
     }
 private:
-    const TilePainter* m_painter;
+    TilePainter* m_painter;
     float m_scale;
 };
 
@@ -79,8 +77,12 @@
     TilePainterFilter(TilePainter* painter) : m_painter(painter) {}
     virtual bool check(QueuedOperation* operation)
     {
-        PaintTileOperation* op = static_cast<PaintTileOperation*>(operation);
-        return op->painter() == m_painter;
+        if (operation->type() == QueuedOperation::PaintTile) {
+            PaintTileOperation* op = static_cast<PaintTileOperation*>(operation);
+            if (op->painter() == m_painter)
+                return true;
+        }
+        return false;
     }
 private:
     TilePainter* m_painter;
diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.cpp b/Source/WebCore/platform/graphics/android/PaintedSurface.cpp
new file mode 100644
index 0000000..45c7579
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/PaintedSurface.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PaintedSurface.h"
+
+
+#include "LayerAndroid.h"
+#include "TiledTexture.h"
+#include "TilesManager.h"
+#include "SkCanvas.h"
+#include "SkPicture.h"
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "PaintedSurface", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "PaintedSurface", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+// Layers with an area larger than 2048*2048 should never be unclipped
+#define MAX_UNCLIPPED_AREA 4194304
+
+namespace WebCore {
+
+PaintedSurface::PaintedSurface()
+    : m_drawingLayer(0)
+    , m_paintingLayer(0)
+    , m_tiledTexture(0)
+    , m_scale(0)
+    , m_pictureUsed(0)
+{
+    TilesManager::instance()->addPaintedSurface(this);
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->increment("PaintedSurface");
+#endif
+    m_tiledTexture = new DualTiledTexture(this);
+}
+
+PaintedSurface::~PaintedSurface()
+{
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->decrement("PaintedSurface");
+#endif
+    delete m_tiledTexture;
+}
+
+void PaintedSurface::prepare(GLWebViewState* state)
+{
+    XLOG("PS %p has PL %p, DL %p", this, m_paintingLayer, m_drawingLayer);
+    LayerAndroid* paintingLayer = m_paintingLayer;
+    if (!paintingLayer)
+        paintingLayer = m_drawingLayer;
+
+    if (!paintingLayer)
+        return;
+
+    bool startFastSwap = false;
+    if (state->isScrolling()) {
+        // when scrolling, block updates and swap tiles as soon as they're ready
+        startFastSwap = true;
+    }
+
+    XLOG("prepare layer %d %x at scale %.2f",
+         paintingLayer->uniqueId(), paintingLayer,
+         paintingLayer->getScale());
+
+    IntRect visibleArea = computeVisibleArea(paintingLayer);
+
+    m_scale = state->scale();
+
+    // If we do not have text, we may as well limit ourselves to
+    // a scale factor of one... this saves up textures.
+    if (m_scale > 1 && !paintingLayer->hasText())
+        m_scale = 1;
+
+    m_tiledTexture->prepare(state, m_scale, m_pictureUsed != paintingLayer->pictureUsed(),
+                            startFastSwap, visibleArea);
+}
+
+bool PaintedSurface::draw()
+{
+    if (!m_drawingLayer || !m_drawingLayer->needsTexture())
+        return false;
+
+    bool askRedraw = false;
+    if (m_tiledTexture)
+        askRedraw = m_tiledTexture->draw();
+
+    return askRedraw;
+}
+
+void PaintedSurface::setPaintingLayer(LayerAndroid* layer, const SkRegion& dirtyArea)
+{
+    m_paintingLayer = layer;
+    if (m_tiledTexture)
+        m_tiledTexture->update(dirtyArea, layer->picture());
+}
+
+bool PaintedSurface::isReady()
+{
+    if (m_tiledTexture)
+        return m_tiledTexture->isReady();
+    return false;
+}
+
+void PaintedSurface::swapTiles()
+{
+    if (m_tiledTexture)
+        m_tiledTexture->swapTiles();
+}
+
+float PaintedSurface::opacity() {
+    if (m_drawingLayer)
+        return m_drawingLayer->drawOpacity();
+    return 1.0;
+}
+
+const TransformationMatrix* PaintedSurface::transform() {
+    // used exclusively for drawing, so only use m_drawingLayer
+    if (!m_drawingLayer)
+        return 0;
+
+    return m_drawingLayer->drawTransform();
+}
+
+void PaintedSurface::computeTexturesAmount(TexturesResult* result)
+{
+    if (!m_tiledTexture)
+        return;
+
+    // for now, always done on drawinglayer
+    LayerAndroid* layer = m_drawingLayer;
+
+    if (!layer)
+        return;
+
+    IntRect unclippedArea = layer->unclippedArea();
+    IntRect clippedVisibleArea = layer->visibleArea();
+    // get two numbers here:
+    // - textures needed for a clipped area
+    // - textures needed for an un-clipped area
+    int nbTexturesUnclipped = m_tiledTexture->nbTextures(unclippedArea, m_scale);
+    int nbTexturesClipped = m_tiledTexture->nbTextures(clippedVisibleArea, m_scale);
+
+    // Set kFixedLayers level
+    if (layer->isFixed())
+        result->fixed += nbTexturesClipped;
+
+    // Set kScrollableAndFixedLayers level
+    if (layer->contentIsScrollable()
+        || layer->isFixed())
+        result->scrollable += nbTexturesClipped;
+
+    // Set kClippedTextures level
+    result->clipped += nbTexturesClipped;
+
+    // Set kAllTextures level
+    if (layer->contentIsScrollable())
+        result->full += nbTexturesClipped;
+    else
+        result->full += nbTexturesUnclipped;
+}
+
+IntRect PaintedSurface::computeVisibleArea(LayerAndroid* layer) {
+    IntRect area;
+    if (!layer)
+        return area;
+
+    if (!layer->contentIsScrollable()
+        && layer->state()->layersRenderingMode() == GLWebViewState::kAllTextures) {
+        area = layer->unclippedArea();
+        double total = ((double) area.width()) * ((double) area.height());
+        if (total > MAX_UNCLIPPED_AREA)
+            area = layer->visibleArea();
+    } else {
+        area = layer->visibleArea();
+    }
+
+    return area;
+}
+
+bool PaintedSurface::owns(BaseTileTexture* texture)
+{
+    if (m_tiledTexture)
+        return m_tiledTexture->owns(texture);
+    return false;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.h b/Source/WebCore/platform/graphics/android/PaintedSurface.h
new file mode 100644
index 0000000..b8ab7b8
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/PaintedSurface.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PaintedSurface_h
+#define PaintedSurface_h
+
+#include "BaseTileTexture.h"
+#include "ClassTracker.h"
+#include "IntRect.h"
+#include "LayerAndroid.h"
+#include "SkRefCnt.h"
+#include "TextureOwner.h"
+#include "TilesManager.h"
+#include "TilePainter.h"
+#include "TransformationMatrix.h"
+
+class SkCanvas;
+class SkRegion;
+
+namespace WebCore {
+
+class DualTiledTexture;
+
+class PaintedSurface : public SurfacePainter {
+public:
+    PaintedSurface();
+    virtual ~PaintedSurface();
+
+    // PaintedSurface methods
+
+    void prepare(GLWebViewState*);
+    bool draw();
+    bool paint(SkCanvas*);
+
+    void setDrawingLayer(LayerAndroid* layer) { m_drawingLayer = layer; }
+    LayerAndroid* drawingLayer() { return m_drawingLayer; }
+
+    void setPaintingLayer(LayerAndroid* layer, const SkRegion& dirtyArea);
+    void clearPaintingLayer() { m_paintingLayer = 0; }
+    LayerAndroid* paintingLayer() { return m_paintingLayer; }
+
+    void swapTiles();
+    bool isReady();
+
+    bool owns(BaseTileTexture* texture);
+
+    void computeTexturesAmount(TexturesResult*);
+    IntRect computeVisibleArea(LayerAndroid*);
+
+    // TilePainter methods for TiledTexture
+    virtual const TransformationMatrix* transform();
+    virtual float opacity();
+
+    // used by TiledTexture
+    float scale() { return m_scale; }
+    unsigned int pictureUsed() { return m_pictureUsed; }
+
+private:
+    LayerAndroid* m_drawingLayer;
+    LayerAndroid* m_paintingLayer;
+    DualTiledTexture* m_tiledTexture;
+
+    float m_scale;
+
+    unsigned int m_pictureUsed;
+
+    android::Mutex m_layerLock;
+};
+
+} // namespace WebCore
+
+#endif // PaintedSurface_h
diff --git a/Source/WebCore/platform/graphics/android/PathAndroid.cpp b/Source/WebCore/platform/graphics/android/PathAndroid.cpp
index 554e187..436da59 100644
--- a/Source/WebCore/platform/graphics/android/PathAndroid.cpp
+++ b/Source/WebCore/platform/graphics/android/PathAndroid.cpp
@@ -286,7 +286,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const
-{
+{   
     GraphicsContext* scratch = scratchContext();
     scratch->save();
 
diff --git a/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp b/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp
new file mode 100644
index 0000000..241cbef
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "PerformanceMonitor.h"
+
+#include <wtf/text/CString.h>
+
+#include <wtf/CurrentTime.h>
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "PerformanceMonitor", __VA_ARGS__)
+
+namespace WebCore {
+
+PerformanceMonitor::PerformanceMonitor()
+{
+}
+
+PerformanceMonitor::~PerformanceMonitor()
+{
+}
+
+void PerformanceMonitor::start(const String &tag)
+{
+    if (tag.isEmpty())
+        return;
+    PerfItem *item;
+    if (m_tags.contains(tag))
+        item = m_tags.get(tag);
+    else {
+        item = new PerfItem();
+        m_tags.set(tag, item);
+    }
+    gettimeofday(&(item->start_time), NULL);
+}
+
+void PerformanceMonitor::stop(const String &tag)
+{
+    if (!m_tags.contains(tag))
+        return;
+    PerfItem *item = m_tags.get(tag);
+    struct timeval end;
+    gettimeofday(&end, NULL);
+    long seconds, useconds;
+    seconds  = end.tv_sec  - item->start_time.tv_sec;
+    useconds = end.tv_usec - item->start_time.tv_usec;
+
+    float mtime = (seconds * 1000.0) + (useconds/1000.0);
+
+    float avg = 0;
+    if (item->average_ms) {
+        item->average_ms = (item->average_ms + mtime) / 2;
+    } else
+        item->average_ms = mtime;
+}
+
+float PerformanceMonitor::getAverageDuration(const String &tag)
+{
+    if (tag.isEmpty() || !m_tags.contains(tag))
+        return 0;
+    return m_tags.get(tag)->average_ms;
+}
+
+void PerformanceMonitor::display(int limit)
+{
+    bool shown = false;
+    HashMap<String, PerfItem*, StringHash>::iterator end = m_tags.end();
+    for (HashMap<String, PerfItem*, StringHash>::iterator it = m_tags.begin(); it != end; ++it) {
+        PerfItem* item = it->second;
+        if (item->average_ms > limit) {
+           if (!shown) {
+                XLOGC("=== DISPLAY MONITOR ====");
+                shown = true;
+           }
+           XLOGC("item %s took longer than %d ms: %.2f", it->first.latin1().data(), limit, item->average_ms);
+        }
+    }
+    if (shown)
+        XLOGC("=== END DISPLAY MONITOR ====");
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/GaneshContext.h b/Source/WebCore/platform/graphics/android/PerformanceMonitor.h
similarity index 68%
copy from Source/WebCore/platform/graphics/android/rendering/GaneshContext.h
copy to Source/WebCore/platform/graphics/android/PerformanceMonitor.h
index 57e8e19..4ebbf6a 100644
--- a/Source/WebCore/platform/graphics/android/rendering/GaneshContext.h
+++ b/Source/WebCore/platform/graphics/android/PerformanceMonitor.h
@@ -23,41 +23,37 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef GaneshContext_h
-#define GaneshContext_h
+#ifndef PerformanceMonitor_h
+#define PerformanceMonitor_h
 
-#if USE(ACCELERATED_COMPOSITING)
+#include "config.h"
 
-#include "BaseRenderer.h"
-#include "GrContext.h"
-#include "SkGpuDevice.h"
-#include <EGL/egl.h>
+#include <wtf/HashMap.h>
+#include <wtf/text/StringHash.h>
+#include <sys/time.h>
+#include <unistd.h>
 
 namespace WebCore {
 
-class GaneshContext {
-public:
-    static GaneshContext* instance();
-
-    SkDevice* getDeviceForTile(const TileRenderInfo& renderInfo);
-
-    void flush();
-
-private:
-
-    GaneshContext();
-
-    GrContext* getGrContext();
-    GrContext* m_grContext;
-
-    SkGpuDevice* m_tileDeviceSurface;
-    EGLConfig  m_surfaceConfig;
-    EGLContext m_surfaceContext;
-
-    static GaneshContext* gInstance;
+struct PerfItem {
+    PerfItem() : average_ms(0), start_time() {}
+    float average_ms;
+    struct timeval start_time;
 };
 
-} // namespace WebCore
+class PerformanceMonitor {
+public:
+    PerformanceMonitor();
+    virtual ~PerformanceMonitor();
+    void start(const String &tag);
+    void stop(const String &tag);
+    float getAverageDuration(const String &tag);
+    void display(int limit);
 
-#endif // USE(ACCELERATED_COMPOSITING)
-#endif // GaneshContext_h
+private:
+    HashMap<String, PerfItem*, StringHash> m_tags;
+};
+
+}
+
+#endif // PerformanceMonitor_h
diff --git a/Source/WebCore/platform/graphics/android/rendering/TextureOwner.h b/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp
similarity index 69%
copy from Source/WebCore/platform/graphics/android/rendering/TextureOwner.h
copy to Source/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp
index b12d8b7..098534c 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TextureOwner.h
+++ b/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2006, The Android Open Source Project
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -23,25 +23,29 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef TextureOwner_h
-#define TextureOwner_h
-
-class SkCanvas;
-class Layer;
+#include "config.h"
+#include "Node.h"
+#include "PlatformGraphicsContext.h"
+#include "SkCanvas.h"
 
 namespace WebCore {
 
-class TileTexture;
-class GLWebViewState;
-
-class TextureOwner {
-public:
-    virtual ~TextureOwner() { }
-    virtual bool removeTexture(TileTexture* texture) = 0;
-    virtual bool isRepaintPending() = 0;
-    virtual unsigned long long drawCount() = 0;
-};
-
+PlatformGraphicsContext::PlatformGraphicsContext(SkCanvas* canvas)
+        : mCanvas(canvas), m_deleteCanvas(false)
+{
 }
 
-#endif // TextureOwner_h
+PlatformGraphicsContext::PlatformGraphicsContext()
+        : mCanvas(new SkCanvas), m_deleteCanvas(true)
+{
+}
+
+PlatformGraphicsContext::~PlatformGraphicsContext()
+{
+    if (m_deleteCanvas) {
+//        printf("-------------------- deleting offscreen canvas\n");
+        delete mCanvas;
+    }
+}
+
+}   // WebCore
diff --git a/Source/WebCore/platform/graphics/android/context/android_graphics.h b/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h
similarity index 66%
copy from Source/WebCore/platform/graphics/android/context/android_graphics.h
copy to Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h
index 7faa781..d22dbd8 100644
--- a/Source/WebCore/platform/graphics/android/context/android_graphics.h
+++ b/Source/WebCore/platform/graphics/android/PlatformGraphicsContext.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007, The Android Open Source Project
+ * Copyright 2006, The Android Open Source Project
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -23,20 +23,36 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef android_graphics_DEFINED
-#define android_graphics_DEFINED
+#ifndef platform_graphics_context_h
+#define platform_graphics_context_h
 
-namespace WebCore {
-    class GraphicsContext;
-}
+#include "IntRect.h"
+#include "RenderSkinAndroid.h"
+#include "RenderSkinButton.h"
+#include "SkCanvas.h"
+#include "SkPicture.h"
+#include "SkTDArray.h"
+
 class SkCanvas;
 
-// TODO: Move this somewhere else. The implementation for this is actually in
-// GraphicsContextAndroid.cpp, but this is used by a handful of other files
-SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc);
+namespace WebCore {
 
-// used to inflate node cache entry
-#define CURSOR_RING_HIT_TEST_RADIUS 5
+    class GraphicsContext;
+    
+class PlatformGraphicsContext {
+public:
+    PlatformGraphicsContext();
+    // Pass in a recording canvas, and an array of button information to be 
+    // updated.
+    PlatformGraphicsContext(SkCanvas* canvas);
+    ~PlatformGraphicsContext();
+    
+    SkCanvas*                   mCanvas;
+    
+    bool deleteUs() const { return m_deleteCanvas; }
+private:
+    bool                     m_deleteCanvas;
+};
 
-
+}
 #endif
diff --git a/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h b/Source/WebCore/platform/graphics/android/QueuedOperation.h
similarity index 62%
rename from Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h
rename to Source/WebCore/platform/graphics/android/QueuedOperation.h
index 7625528..1a83f65 100644
--- a/Source/WebCore/platform/graphics/android/rendering/QueuedOperation.h
+++ b/Source/WebCore/platform/graphics/android/QueuedOperation.h
@@ -28,13 +28,23 @@
 
 namespace WebCore {
 
+class TiledPage;
+
 class QueuedOperation {
 public:
+    enum OperationType { Undefined, PaintTile, PaintLayer, DeleteTexture };
+    QueuedOperation(OperationType type, TiledPage* page)
+        : m_type(type)
+        , m_page(page) {}
     virtual ~QueuedOperation() {}
     virtual void run() = 0;
     virtual bool operator==(const QueuedOperation* operation) = 0;
-    virtual void* uniquePtr() = 0;
-    virtual int priority() = 0;
+    virtual int priority() { return -1; }
+    OperationType type() const { return m_type; }
+    TiledPage* page() const { return m_page; }
+private:
+    OperationType m_type;
+    TiledPage* m_page;
 };
 
 class OperationFilter {
@@ -43,6 +53,33 @@
     virtual bool check(QueuedOperation* operation) = 0;
 };
 
+class PageFilter : public OperationFilter {
+public:
+    PageFilter(TiledPage* page) : m_page(page) {}
+    virtual bool check(QueuedOperation* operation)
+    {
+        if (operation->page() == m_page)
+            return true;
+        return false;
+    }
+private:
+    TiledPage* m_page;
+};
+
+class PagePaintFilter : public OperationFilter {
+public:
+    PagePaintFilter(TiledPage* page) : m_page(page) {}
+    virtual bool check(QueuedOperation* operation)
+    {
+        if (operation->type() == QueuedOperation::PaintTile
+                && operation->page() == m_page)
+            return true;
+        return false;
+    }
+private:
+    TiledPage* m_page;
+};
+
 }
 
 #endif // QueuedOperation_h
diff --git a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp
similarity index 68%
rename from Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp
rename to Source/WebCore/platform/graphics/android/RasterRenderer.cpp
index 47e5c17..9991fbd 100644
--- a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.cpp
+++ b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp
@@ -23,25 +23,48 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#define LOG_TAG "RasterRenderer"
-#define LOG_NDEBUG 1
 
 #include "config.h"
 #include "RasterRenderer.h"
 
 #if USE(ACCELERATED_COMPOSITING)
 
-#include "AndroidLog.h"
 #include "GLUtils.h"
 #include "SkBitmap.h"
 #include "SkBitmapRef.h"
 #include "SkCanvas.h"
 #include "SkDevice.h"
-#include "Tile.h"
 #include "TilesManager.h"
 
+#include <wtf/text/CString.h>
+
+#ifdef DEBUG
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "RasterRenderer", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
 namespace WebCore {
 
+static const String TAG_CREATE_BITMAP = "create_bitmap";
+static const String TAG_DRAW_PICTURE = "draw_picture";
+static const String TAG_UPDATE_TEXTURE = "update_texture";
+#define TAG_COUNT 3
+static const String TAGS[] = {
+    TAG_CREATE_BITMAP,
+    TAG_DRAW_PICTURE,
+    TAG_UPDATE_TEXTURE,
+};
+
 SkBitmap* RasterRenderer::g_bitmap = 0;
 
 RasterRenderer::RasterRenderer() : BaseRenderer(BaseRenderer::Raster)
@@ -67,39 +90,51 @@
 
 void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas)
 {
+    if (renderInfo.measurePerf)
+        m_perfMon.start(TAG_CREATE_BITMAP);
+
     if (renderInfo.baseTile->isLayerTile()) {
         g_bitmap->setIsOpaque(false);
         g_bitmap->eraseARGB(0, 0, 0, 0);
     } else {
-        Color defaultBackground = Color::white;
-        Color* background = renderInfo.tilePainter->background();
-        if (!background) {
-            ALOGV("No background color for base layer!");
-            background = &defaultBackground;
-        }
-        ALOGV("setupCanvas use background on Base Layer %x", background->rgb());
-        g_bitmap->setIsOpaque(!background->hasAlpha());
-        g_bitmap->eraseARGB(background->alpha(), background->red(),
-                          background->green(), background->blue());
+        g_bitmap->setIsOpaque(true);
+        g_bitmap->eraseARGB(255, 255, 255, 255);
     }
 
     SkDevice* device = new SkDevice(*g_bitmap);
 
+    if (renderInfo.measurePerf) {
+        m_perfMon.stop(TAG_CREATE_BITMAP);
+        m_perfMon.start(TAG_DRAW_PICTURE);
+    }
+
     canvas->setDevice(device);
 
     device->unref();
+
+    // ensure the canvas origin is translated to the coordinates of our inval rect
+    canvas->translate(-renderInfo.invalRect->fLeft, -renderInfo.invalRect->fTop);
 }
 
 void RasterRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas)
 {
+    if (renderInfo.measurePerf) {
+        m_perfMon.stop(TAG_DRAW_PICTURE);
+        m_perfMon.start(TAG_UPDATE_TEXTURE);
+    }
+
     const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false);
+
     GLUtils::paintTextureWithBitmap(&renderInfo, bitmap);
+
+    if (renderInfo.measurePerf)
+        m_perfMon.stop(TAG_UPDATE_TEXTURE);
 }
 
-void RasterRenderer::checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas)
+const String* RasterRenderer::getPerformanceTags(int& tagCount)
 {
-    const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false);
-    renderInfo.isPureColor = GLUtils::isPureColorBitmap(bitmap, renderInfo.pureColor);
+    tagCount = TAG_COUNT;
+    return TAGS;
 }
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h b/Source/WebCore/platform/graphics/android/RasterRenderer.h
similarity index 95%
rename from Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h
rename to Source/WebCore/platform/graphics/android/RasterRenderer.h
index 39e00f2..96b3f58 100644
--- a/Source/WebCore/platform/graphics/android/rendering/RasterRenderer.h
+++ b/Source/WebCore/platform/graphics/android/RasterRenderer.h
@@ -49,7 +49,7 @@
 
     virtual void setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas);
     virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas);
-    virtual void checkForPureColor(TileRenderInfo& renderInfo, SkCanvas* canvas);
+    virtual const String* getPerformanceTags(int& tagCount);
 
 private:
     static SkBitmap* g_bitmap;
diff --git a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp
new file mode 100644
index 0000000..3c2ced5
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp
@@ -0,0 +1,68 @@
+#include "config.h"
+#include "ScrollableLayerAndroid.h"
+
+#include "GLWebViewState.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+namespace WebCore {
+
+bool ScrollableLayerAndroid::scrollTo(int x, int y)
+{
+    SkIRect scrollBounds;
+    getScrollRect(&scrollBounds);
+    if (!scrollBounds.fRight && !scrollBounds.fBottom)
+        return false;
+
+    SkScalar newX = SkScalarPin(x, 0, scrollBounds.fRight);
+    SkScalar newY = SkScalarPin(y, 0, scrollBounds.fBottom);
+    // Check for no change.
+    if (newX == scrollBounds.fLeft && newY == scrollBounds.fTop)
+        return false;
+
+    setPosition(m_scrollLimits.fLeft - newX, m_scrollLimits.fTop - newY);
+
+    return true;
+}
+
+void ScrollableLayerAndroid::getScrollRect(SkIRect* out) const
+{
+    const SkPoint& pos = getPosition();
+    out->fLeft = m_scrollLimits.fLeft - pos.fX;
+    out->fTop = m_scrollLimits.fTop - pos.fY;
+    out->fRight = getSize().width() - m_scrollLimits.width();
+    out->fBottom = getSize().height() - m_scrollLimits.height();
+}
+
+bool ScrollableLayerAndroid::scrollRectIntoView(const SkIRect& rect)
+{
+    // Apply the local transform to the rect to get it relative to the parent
+    // layer.
+    SkMatrix localTransform;
+    getLocalTransform(&localTransform);
+    SkRect transformedRect;
+    transformedRect.set(rect);
+    localTransform.mapRect(&transformedRect);
+
+    // Test left before right to prioritize left alignment if transformedRect is wider than
+    // visible area.
+    int x = m_scrollLimits.fLeft;
+    if (transformedRect.fLeft < m_scrollLimits.fLeft)
+        x = transformedRect.fLeft;
+    else if (transformedRect.fRight > m_scrollLimits.fRight)
+        x = transformedRect.fRight - std::max(m_scrollLimits.width(), transformedRect.width());
+
+    // Test top before bottom to prioritize top alignment if transformedRect is taller than
+    // visible area.
+    int y = m_scrollLimits.fTop;
+    if (transformedRect.fTop < m_scrollLimits.fTop)
+        y = transformedRect.fTop;
+    else if (transformedRect.fBottom > m_scrollLimits.fBottom)
+        y = transformedRect.fBottom - std::max(m_scrollLimits.height(), transformedRect.height());
+
+    return scrollTo(x - getPosition().fX, y - getPosition().fY);
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.h b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h
similarity index 86%
rename from Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.h
rename to Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h
index b3c828f..5cba5d9 100644
--- a/Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.h
@@ -41,20 +41,24 @@
     virtual bool contentIsScrollable() const { return true; }
 
     virtual LayerAndroid* copy() const { return new ScrollableLayerAndroid(*this); }
-    virtual SubclassType subclassType() const { return LayerAndroid::ScrollableLayer; }
+
+    virtual bool updateWithLayer(LayerAndroid*) { return true; }
 
     // Scrolls to the given position in the layer.
     // Returns whether or not any scrolling was required.
-    virtual bool scrollTo(int x, int y);
+    bool scrollTo(int x, int y);
 
     // Fills the rect with the current scroll offset and the maximum scroll offset.
     // fLeft   = scrollX
     // fTop    = scrollY
     // fRight  = maxScrollX
     // fBottom = maxScrollY
-    virtual void getScrollRect(SkIRect*) const;
+    void getScrollRect(SkIRect*) const;
 
-    void setScrollLimits(float minX, float minY, float maxX, float maxY);
+    void setScrollLimits(float x, float y, float width, float height)
+    {
+        m_scrollLimits.set(x, y, x + width, y + height);
+    }
 
     // Given a rect in the layer, scrolls to bring the rect into view. Uses a
     // lazy approach, whereby we scroll as little as possible to bring the
@@ -64,12 +68,9 @@
     bool scrollRectIntoView(const SkIRect&);
 
     friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream);
-    friend LayerAndroid* android::deserializeLayer(int version, SkStream* stream);
+    friend LayerAndroid* android::deserializeLayer(SkStream* stream);
 
-protected:
-
-    void getScrollBounds(IntRect*) const;
-
+private:
     // The position of the visible area of the layer, relative to the parent
     // layer. This is fixed during scrolling. We acheive scrolling by modifying
     // the position of the layer.
diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp
new file mode 100644
index 0000000..2a6a488
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp
@@ -0,0 +1,684 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ShaderProgram.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "FloatPoint3D.h"
+#include "GLUtils.h"
+#include "TilesManager.h"
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ShaderProgram", __VA_ARGS__)
+
+namespace WebCore {
+
+static const char gVertexShader[] =
+    "attribute vec4 vPosition;\n"
+    "uniform mat4 projectionMatrix;\n"
+    "varying vec2 v_texCoord;\n"
+    "void main() {\n"
+    "  gl_Position = projectionMatrix * vPosition;\n"
+    "  v_texCoord = vec2(vPosition);\n"
+    "}\n";
+
+static const char gFragmentShader[] =
+    "precision mediump float;\n"
+    "varying vec2 v_texCoord; \n"
+    "uniform float alpha; \n"
+    "uniform sampler2D s_texture; \n"
+    "void main() {\n"
+    "  gl_FragColor = texture2D(s_texture, v_texCoord); \n"
+    "  gl_FragColor *= alpha; "
+    "}\n";
+
+static const char gFragmentShaderInverted[] =
+    "precision mediump float;\n"
+    "varying vec2 v_texCoord; \n"
+    "uniform float alpha; \n"
+    "uniform float contrast; \n"
+    "uniform sampler2D s_texture; \n"
+    "void main() {\n"
+    "  vec4 pixel = texture2D(s_texture, v_texCoord); \n"
+    "  float a = pixel.a; \n"
+    "  float color = a - (0.2989 * pixel.r + 0.5866 * pixel.g + 0.1145 * pixel.b);\n"
+    "  color = ((color - a/2.0) * contrast) + a/2.0; \n"
+    "  pixel.rgb = vec3(color, color, color); \n "
+    "  gl_FragColor = pixel; \n"
+    "  gl_FragColor *= alpha; \n"
+    "}\n";
+
+static const char gVideoVertexShader[] =
+    "attribute vec4 vPosition;\n"
+    "uniform mat4 textureMatrix;\n"
+    "uniform mat4 projectionMatrix;\n"
+    "varying vec2 v_texCoord;\n"
+    "void main() {\n"
+    "  gl_Position = projectionMatrix * vPosition;\n"
+    "  v_texCoord = vec2(textureMatrix * vec4(vPosition.x, 1.0 - vPosition.y, 0.0, 1.0));\n"
+    "}\n";
+
+static const char gVideoFragmentShader[] =
+    "#extension GL_OES_EGL_image_external : require\n"
+    "precision mediump float;\n"
+    "uniform samplerExternalOES s_yuvTexture;\n"
+    "varying vec2 v_texCoord;\n"
+    "void main() {\n"
+    "  gl_FragColor = texture2D(s_yuvTexture, v_texCoord);\n"
+    "}\n";
+
+static const char gSurfaceTextureOESFragmentShader[] =
+    "#extension GL_OES_EGL_image_external : require\n"
+    "precision mediump float;\n"
+    "varying vec2 v_texCoord; \n"
+    "uniform float alpha; \n"
+    "uniform samplerExternalOES s_texture; \n"
+    "void main() {\n"
+    "  gl_FragColor = texture2D(s_texture, v_texCoord); \n"
+    "  gl_FragColor *= alpha; "
+    "}\n";
+
+static const char gSurfaceTextureOESFragmentShaderInverted[] =
+    "#extension GL_OES_EGL_image_external : require\n"
+    "precision mediump float;\n"
+    "varying vec2 v_texCoord; \n"
+    "uniform float alpha; \n"
+    "uniform float contrast; \n"
+    "uniform samplerExternalOES s_texture; \n"
+    "void main() {\n"
+    "  vec4 pixel = texture2D(s_texture, v_texCoord); \n"
+    "  float a = pixel.a; \n"
+    "  float color = a - (0.2989 * pixel.r + 0.5866 * pixel.g + 0.1145 * pixel.b);\n"
+    "  color = ((color - a/2.0) * contrast) + a/2.0; \n"
+    "  pixel.rgb = vec3(color, color, color); \n "
+    "  gl_FragColor = pixel; \n"
+    "  gl_FragColor *= alpha; \n"
+    "}\n";
+
+GLuint ShaderProgram::loadShader(GLenum shaderType, const char* pSource)
+{
+    GLuint shader = glCreateShader(shaderType);
+    if (shader) {
+        glShaderSource(shader, 1, &pSource, 0);
+        glCompileShader(shader);
+        GLint compiled = 0;
+        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+        if (!compiled) {
+            GLint infoLen = 0;
+            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
+            if (infoLen) {
+                char* buf = (char*) malloc(infoLen);
+                if (buf) {
+                glGetShaderInfoLog(shader, infoLen, 0, buf);
+                XLOG("could not compile shader %d:\n%s\n", shaderType, buf);
+                free(buf);
+            }
+            glDeleteShader(shader);
+            shader = 0;
+            }
+        }
+    }
+    return shader;
+}
+
+GLuint ShaderProgram::createProgram(const char* pVertexSource, const char* pFragmentSource)
+{
+    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
+    if (!vertexShader) {
+        XLOG("couldn't load the vertex shader!");
+        return -1;
+    }
+
+    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
+    if (!pixelShader) {
+        XLOG("couldn't load the pixel shader!");
+        return -1;
+    }
+
+    GLuint program = glCreateProgram();
+    if (program) {
+        glAttachShader(program, vertexShader);
+        GLUtils::checkGlError("glAttachShader vertex");
+        glAttachShader(program, pixelShader);
+        GLUtils::checkGlError("glAttachShader pixel");
+        glLinkProgram(program);
+        GLint linkStatus = GL_FALSE;
+        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+        if (linkStatus != GL_TRUE) {
+            GLint bufLength = 0;
+            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
+            if (bufLength) {
+                char* buf = (char*) malloc(bufLength);
+                if (buf) {
+                    glGetProgramInfoLog(program, bufLength, 0, buf);
+                    XLOG("could not link program:\n%s\n", buf);
+                    free(buf);
+                }
+            }
+            glDeleteProgram(program);
+            program = -1;
+        }
+    }
+    return program;
+}
+
+ShaderProgram::ShaderProgram()
+    : m_blendingEnabled(false)
+    , m_contrast(1)
+    , m_alphaLayer(false)
+    , m_currentScale(1.0f)
+{
+    init();
+}
+
+void ShaderProgram::init()
+{
+    m_program = createProgram(gVertexShader, gFragmentShader);
+    m_programInverted = createProgram(gVertexShader, gFragmentShaderInverted);
+    m_videoProgram = createProgram(gVideoVertexShader, gVideoFragmentShader);
+    m_surfTexOESProgram =
+        createProgram(gVertexShader, gSurfaceTextureOESFragmentShader);
+    m_surfTexOESProgramInverted =
+        createProgram(gVertexShader, gSurfaceTextureOESFragmentShaderInverted);
+
+    if (m_program == -1
+        || m_programInverted == -1
+        || m_videoProgram == -1
+        || m_surfTexOESProgram == -1
+        || m_surfTexOESProgramInverted == -1)
+        return;
+
+    m_hProjectionMatrix = glGetUniformLocation(m_program, "projectionMatrix");
+    m_hAlpha = glGetUniformLocation(m_program, "alpha");
+    m_hTexSampler = glGetUniformLocation(m_program, "s_texture");
+    m_hPosition = glGetAttribLocation(m_program, "vPosition");
+
+    m_hProjectionMatrixInverted = glGetUniformLocation(m_programInverted, "projectionMatrix");
+    m_hAlphaInverted = glGetUniformLocation(m_programInverted, "alpha");
+    m_hContrastInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "contrast");
+    m_hTexSamplerInverted = glGetUniformLocation(m_programInverted, "s_texture");
+    m_hPositionInverted = glGetAttribLocation(m_programInverted, "vPosition");
+
+    m_hVideoProjectionMatrix =
+        glGetUniformLocation(m_videoProgram, "projectionMatrix");
+    m_hVideoTextureMatrix = glGetUniformLocation(m_videoProgram, "textureMatrix");
+    m_hVideoTexSampler = glGetUniformLocation(m_videoProgram, "s_yuvTexture");
+    m_hVideoPosition = glGetAttribLocation(m_program, "vPosition");
+
+    m_hSTOESProjectionMatrix =
+        glGetUniformLocation(m_surfTexOESProgram, "projectionMatrix");
+    m_hSTOESAlpha = glGetUniformLocation(m_surfTexOESProgram, "alpha");
+    m_hSTOESTexSampler = glGetUniformLocation(m_surfTexOESProgram, "s_texture");
+    m_hSTOESPosition = glGetAttribLocation(m_surfTexOESProgram, "vPosition");
+
+    m_hSTOESProjectionMatrixInverted =
+        glGetUniformLocation(m_surfTexOESProgramInverted, "projectionMatrix");
+    m_hSTOESAlphaInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "alpha");
+    m_hSTOESContrastInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "contrast");
+    m_hSTOESTexSamplerInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "s_texture");
+    m_hSTOESPositionInverted = glGetAttribLocation(m_surfTexOESProgramInverted, "vPosition");
+
+
+    const GLfloat coord[] = {
+        0.0f, 0.0f, // C
+        1.0f, 0.0f, // D
+        0.0f, 1.0f, // A
+        1.0f, 1.0f // B
+    };
+
+    glGenBuffers(1, m_textureBuffer);
+    glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
+    glBufferData(GL_ARRAY_BUFFER, 2 * 4 * sizeof(GLfloat), coord, GL_STATIC_DRAW);
+
+    GLUtils::checkGlError("init");
+}
+
+void ShaderProgram::resetBlending()
+{
+    glDisable(GL_BLEND);
+    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+    glBlendEquation(GL_FUNC_ADD);
+    m_blendingEnabled = false;
+}
+
+void ShaderProgram::setBlendingState(bool enableBlending)
+{
+    if (enableBlending == m_blendingEnabled)
+        return;
+
+    if (enableBlending)
+        glEnable(GL_BLEND);
+    else
+        glDisable(GL_BLEND);
+
+    m_blendingEnabled = enableBlending;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Drawing
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void ShaderProgram::setViewport(SkRect& viewport, float scale)
+{
+    TransformationMatrix ortho;
+    GLUtils::setOrthographicMatrix(ortho, viewport.fLeft, viewport.fTop,
+                                   viewport.fRight, viewport.fBottom, -1000, 1000);
+    m_projectionMatrix = ortho;
+    m_viewport = viewport;
+    m_currentScale = scale;
+}
+
+void ShaderProgram::setProjectionMatrix(SkRect& geometry, GLint projectionMatrixHandle)
+{
+    TransformationMatrix translate;
+    translate.translate3d(geometry.fLeft, geometry.fTop, 0.0);
+    TransformationMatrix scale;
+    scale.scale3d(geometry.width(), geometry.height(), 1.0);
+
+    TransformationMatrix total;
+    if (!m_alphaLayer)
+        total = m_projectionMatrix * m_repositionMatrix * m_webViewMatrix
+                * translate * scale;
+    else
+        total = m_projectionMatrix * translate * scale;
+
+    GLfloat projectionMatrix[16];
+    GLUtils::toGLMatrix(projectionMatrix, total);
+    glUniformMatrix4fv(projectionMatrixHandle, 1, GL_FALSE, projectionMatrix);
+}
+
+void ShaderProgram::drawQuadInternal(SkRect& geometry,
+                                     GLint textureId,
+                                     float opacity,
+                                     GLint program,
+                                     GLint projectionMatrixHandle,
+                                     GLint texSampler,
+                                     GLenum textureTarget,
+                                     GLint position,
+                                     GLint alpha,
+                                     GLint texFilter,
+                                     GLint contrast)
+{
+    glUseProgram(program);
+
+    if (!geometry.isEmpty())
+         setProjectionMatrix(geometry, projectionMatrixHandle);
+    else {
+        TransformationMatrix matrix;
+        // Map x,y from (0,1) to (-1, 1)
+        matrix.scale3d(2, 2, 1);
+        matrix.translate3d(-0.5, -0.5, 0);
+        GLfloat projectionMatrix[16];
+        GLUtils::toGLMatrix(projectionMatrix, matrix);
+        glUniformMatrix4fv(projectionMatrixHandle, 1, GL_FALSE, projectionMatrix);
+    }
+
+    glActiveTexture(GL_TEXTURE0);
+    glUniform1i(texSampler, 0);
+    glBindTexture(textureTarget, textureId);
+    glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, texFilter);
+    glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, texFilter);
+    glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
+    glEnableVertexAttribArray(position);
+    glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, 0);
+    glUniform1f(alpha, opacity);
+    if (contrast != -1)
+        glUniform1f(contrast, m_contrast);
+
+    setBlendingState(opacity < 1.0);
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+}
+
+void ShaderProgram::drawQuad(SkRect& geometry, int textureId, float opacity,
+                             GLenum textureTarget, GLint texFilter)
+{
+    if (textureTarget == GL_TEXTURE_2D) {
+        if (!TilesManager::instance()->invertedScreen()) {
+            drawQuadInternal(geometry, textureId, opacity, m_program,
+                             m_hProjectionMatrix,
+                             m_hTexSampler, GL_TEXTURE_2D,
+                             m_hPosition, m_hAlpha, texFilter);
+        } else {
+            // With the new GPU texture upload path, we do not use an FBO
+            // to blit the texture we receive from the TexturesGenerator thread.
+            // To implement inverted rendering, we thus have to do the rendering
+            // live, by using a different shader.
+            drawQuadInternal(geometry, textureId, opacity, m_programInverted,
+                             m_hProjectionMatrixInverted,
+                             m_hTexSamplerInverted, GL_TEXTURE_2D,
+                             m_hPositionInverted, m_hAlphaInverted, texFilter,
+                             m_hContrastInverted);
+        }
+    } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
+               && !TilesManager::instance()->invertedScreen()) {
+        drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgram,
+                         m_hSTOESProjectionMatrix,
+                         m_hSTOESTexSampler, GL_TEXTURE_EXTERNAL_OES,
+                         m_hSTOESPosition, m_hSTOESAlpha, texFilter);
+    } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
+               && TilesManager::instance()->invertedScreen()) {
+        drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgramInverted,
+                         m_hSTOESProjectionMatrixInverted,
+                         m_hSTOESTexSamplerInverted, GL_TEXTURE_EXTERNAL_OES,
+                         m_hSTOESPositionInverted, m_hSTOESAlphaInverted,
+                         texFilter, m_hSTOESContrastInverted);
+    }
+    GLUtils::checkGlError("drawQuad");
+}
+
+void ShaderProgram::setViewRect(const IntRect& viewRect)
+{
+    m_viewRect = viewRect;
+
+    // We do clipping using glScissor, which needs to take
+    // coordinates in screen space. The following matrix transform
+    // content coordinates in screen coordinates.
+    TransformationMatrix translate;
+    translate.translate(1.0, 1.0);
+
+    TransformationMatrix scale;
+    scale.scale3d(m_viewRect.width() * 0.5f, m_viewRect.height() * 0.5f, 1);
+
+    m_documentToScreenMatrix = scale * translate * m_projectionMatrix;
+
+    translate.scale3d(1, -1, 1);
+    m_documentToInvScreenMatrix = scale * translate * m_projectionMatrix;
+
+    IntRect rect(0, 0, m_webViewRect.width(), m_webViewRect.height());
+    m_documentViewport = m_documentToScreenMatrix.inverse().mapRect(rect);
+}
+
+// This function transform a clip rect extracted from the current layer
+// into a clip rect in screen coordinates -- used by the clipping rects
+FloatRect ShaderProgram::rectInScreenCoord(const TransformationMatrix& drawMatrix, const IntSize& size)
+{
+    FloatRect srect(0, 0, size.width(), size.height());
+    TransformationMatrix renderMatrix = m_documentToScreenMatrix * drawMatrix;
+    return renderMatrix.mapRect(srect);
+}
+
+// used by the partial screen invals
+FloatRect ShaderProgram::rectInInvScreenCoord(const TransformationMatrix& drawMatrix, const IntSize& size)
+{
+    FloatRect srect(0, 0, size.width(), size.height());
+    TransformationMatrix renderMatrix = m_documentToInvScreenMatrix * drawMatrix;
+    return renderMatrix.mapRect(srect);
+}
+
+FloatRect ShaderProgram::rectInInvScreenCoord(const FloatRect& rect)
+{
+    return m_documentToInvScreenMatrix.mapRect(rect);
+}
+
+FloatRect ShaderProgram::rectInScreenCoord(const FloatRect& rect)
+{
+    return m_documentToScreenMatrix.mapRect(rect);
+}
+
+FloatRect ShaderProgram::convertScreenCoordToDocumentCoord(const FloatRect& rect)
+{
+    return m_documentToScreenMatrix.inverse().mapRect(rect);
+}
+
+FloatRect ShaderProgram::convertInvScreenCoordToScreenCoord(const FloatRect& rect)
+{
+    FloatRect documentRect = m_documentToInvScreenMatrix.inverse().mapRect(rect);
+    return rectInScreenCoord(documentRect);
+}
+
+FloatRect ShaderProgram::convertScreenCoordToInvScreenCoord(const FloatRect& rect)
+{
+    FloatRect documentRect = m_documentToScreenMatrix.inverse().mapRect(rect);
+    return rectInInvScreenCoord(documentRect);
+}
+
+void ShaderProgram::setScreenClip(const IntRect& clip)
+{
+    m_screenClip = clip;
+    IntRect mclip = clip;
+
+    // the clip from frameworks is in full screen coordinates
+    mclip.setY(clip.y() - m_webViewRect.y() - m_titleBarHeight);
+    FloatRect tclip = convertInvScreenCoordToScreenCoord(mclip);
+    IntRect screenClip(tclip.x(), tclip.y(), tclip.width(), tclip.height());
+    m_screenClip = screenClip;
+}
+
+// clip is in screen coordinates
+void ShaderProgram::clip(const FloatRect& clip)
+{
+    if (clip == m_clipRect)
+        return;
+
+    // we should only call glScissor in this function, so that we can easily
+    // track the current clipping rect.
+
+    IntRect screenClip(clip.x(),
+                       clip.y(),
+                       clip.width(), clip.height());
+
+    if (!m_screenClip.isEmpty())
+        screenClip.intersect(m_screenClip);
+
+    screenClip.setY(screenClip.y() + m_viewRect.y());
+    if (screenClip.x() < 0) {
+        int w = screenClip.width();
+        w += screenClip.x();
+        screenClip.setX(0);
+        screenClip.setWidth(w);
+    }
+    if (screenClip.y() < 0) {
+        int h = screenClip.height();
+        h += screenClip.y();
+        screenClip.setY(0);
+        screenClip.setHeight(h);
+    }
+
+    glScissor(screenClip.x(), screenClip.y(), screenClip.width(), screenClip.height());
+
+    m_clipRect = clip;
+}
+
+IntRect ShaderProgram::clippedRectWithViewport(const IntRect& rect, int margin)
+{
+    IntRect viewport(m_viewport.fLeft - margin, m_viewport.fTop - margin,
+                     m_viewport.width() + margin, m_viewport.height() + margin);
+    viewport.intersect(rect);
+    return viewport;
+}
+
+float ShaderProgram::zValue(const TransformationMatrix& drawMatrix, float w, float h)
+{
+    TransformationMatrix modifiedDrawMatrix = drawMatrix;
+    modifiedDrawMatrix.scale3d(w, h, 1);
+    TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
+    FloatPoint3D point(0.5, 0.5, 0.0);
+    FloatPoint3D result = renderMatrix.mapPoint(point);
+    return result.z();
+}
+
+void ShaderProgram::drawLayerQuadInternal(const GLfloat* projectionMatrix,
+                                          int textureId, float opacity,
+                                          GLenum textureTarget, GLint program,
+                                          GLint matrix, GLint texSample,
+                                          GLint position, GLint alpha,
+                                          GLint contrast)
+{
+    glUseProgram(program);
+    glUniformMatrix4fv(matrix, 1, GL_FALSE, projectionMatrix);
+
+    glActiveTexture(GL_TEXTURE0);
+    glUniform1i(texSample, 0);
+    glBindTexture(textureTarget, textureId);
+    glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+
+    glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
+    glEnableVertexAttribArray(position);
+    glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, 0);
+    glUniform1f(alpha, opacity);
+    if (contrast != -1)
+        glUniform1f(contrast, m_contrast);
+}
+
+
+void ShaderProgram::drawLayerQuad(const TransformationMatrix& drawMatrix,
+                                  const SkRect& geometry, int textureId,
+                                  float opacity, bool forceBlending,
+                                  GLenum textureTarget)
+{
+
+    TransformationMatrix modifiedDrawMatrix = drawMatrix;
+    // move the drawing depending on where the texture is on the layer
+    modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop);
+    modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1);
+
+    TransformationMatrix renderMatrix;
+    if (!m_alphaLayer)
+        renderMatrix = m_projectionMatrix * m_repositionMatrix
+                       * m_webViewMatrix * modifiedDrawMatrix;
+    else
+        renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
+
+    GLfloat projectionMatrix[16];
+    GLUtils::toGLMatrix(projectionMatrix, renderMatrix);
+    if (textureTarget == GL_TEXTURE_2D) {
+        if (!TilesManager::instance()->invertedScreen()) {
+            drawLayerQuadInternal(projectionMatrix, textureId, opacity,
+                                  GL_TEXTURE_2D, m_program,
+                                  m_hProjectionMatrix, m_hTexSampler,
+                                  m_hPosition, m_hAlpha);
+        } else {
+            drawLayerQuadInternal(projectionMatrix, textureId, opacity,
+                                  GL_TEXTURE_2D, m_programInverted,
+                                  m_hProjectionMatrixInverted, m_hTexSamplerInverted,
+                                  m_hPositionInverted, m_hAlphaInverted,
+                                  m_hContrastInverted);
+        }
+    } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
+               && !TilesManager::instance()->invertedScreen()) {
+        drawLayerQuadInternal(projectionMatrix, textureId, opacity,
+                              GL_TEXTURE_EXTERNAL_OES, m_surfTexOESProgram,
+                              m_hSTOESProjectionMatrix, m_hSTOESTexSampler,
+                              m_hSTOESPosition, m_hSTOESAlpha);
+    } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
+               && TilesManager::instance()->invertedScreen()) {
+        drawLayerQuadInternal(projectionMatrix, textureId, opacity,
+                              GL_TEXTURE_EXTERNAL_OES, m_surfTexOESProgramInverted,
+                              m_hSTOESProjectionMatrixInverted, m_hSTOESTexSamplerInverted,
+                              m_hSTOESPositionInverted, m_hSTOESAlphaInverted,
+                              m_hSTOESContrastInverted);
+    }
+
+    setBlendingState(forceBlending || opacity < 1.0);
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+    GLUtils::checkGlError("drawLayerQuad");
+}
+
+void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix,
+                                       float* textureMatrix, SkRect& geometry,
+                                       int textureId)
+{
+    // switch to our custom yuv video rendering program
+    glUseProgram(m_videoProgram);
+
+    TransformationMatrix modifiedDrawMatrix = drawMatrix;
+    modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop);
+    modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1);
+    TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
+
+    GLfloat projectionMatrix[16];
+    GLUtils::toGLMatrix(projectionMatrix, renderMatrix);
+    glUniformMatrix4fv(m_hVideoProjectionMatrix, 1, GL_FALSE, projectionMatrix);
+    glUniformMatrix4fv(m_hVideoTextureMatrix, 1, GL_FALSE, textureMatrix);
+
+    glActiveTexture(GL_TEXTURE0);
+    glUniform1i(m_hVideoTexSampler, 0);
+    glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId);
+
+    glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
+    glEnableVertexAttribArray(m_hVideoPosition);
+    glVertexAttribPointer(m_hVideoPosition, 2, GL_FLOAT, GL_FALSE, 0, 0);
+
+    setBlendingState(false);
+    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+}
+
+void ShaderProgram::setWebViewMatrix(const float* matrix, bool alphaLayer)
+{
+    GLUtils::convertToTransformationMatrix(matrix, m_webViewMatrix);
+    m_alphaLayer = alphaLayer;
+}
+
+void ShaderProgram::calculateAnimationDelta()
+{
+    // The matrix contains the scrolling info, so this rect is starting from
+    // the m_viewport.
+    // So we just need to map the webview's visible rect using the matrix,
+    // calculate the difference b/t transformed rect and the webViewRect,
+    // then we can get the delta x , y caused by the animation.
+    // Note that the Y is for reporting back to GL viewport, so it is inverted.
+    // When it is alpha animation, then we rely on the framework implementation
+    // such that there is no matrix applied in native webkit.
+    if (!m_alphaLayer) {
+        FloatRect rect(m_viewport.fLeft * m_currentScale,
+                       m_viewport.fTop * m_currentScale,
+                       m_webViewRect.width(),
+                       m_webViewRect.height());
+        rect = m_webViewMatrix.mapRect(rect);
+        m_animationDelta.setX(rect.x() - m_webViewRect.x() );
+        m_animationDelta.setY(rect.y() + rect.height() - m_webViewRect.y()
+                              - m_webViewRect.height() - m_titleBarHeight);
+
+        m_repositionMatrix.makeIdentity();
+        m_repositionMatrix.translate3d(-m_webViewRect.x(), -m_webViewRect.y() - m_titleBarHeight, 0);
+        m_repositionMatrix.translate3d(m_viewport.fLeft * m_currentScale, m_viewport.fTop * m_currentScale, 0);
+        m_repositionMatrix.translate3d(-m_animationDelta.x(), -m_animationDelta.y(), 0);
+    } else {
+        m_animationDelta.setX(0);
+        m_animationDelta.setY(0);
+        m_repositionMatrix.makeIdentity();
+    }
+
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.h b/Source/WebCore/platform/graphics/android/ShaderProgram.h
new file mode 100644
index 0000000..9ab7a46
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/ShaderProgram.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ShaderProgram_h
+#define ShaderProgram_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "FloatRect.h"
+#include "IntRect.h"
+#include "SkRect.h"
+#include "TransformationMatrix.h"
+#include <GLES2/gl2.h>
+
+#define MAX_CONTRAST 5
+
+namespace WebCore {
+
+class ShaderProgram {
+public:
+    ShaderProgram();
+    void init();
+    int program() { return m_program; }
+
+    // Drawing
+    void setViewport(SkRect& viewport, float scale);
+    float zValue(const TransformationMatrix& drawMatrix, float w, float h);
+
+    // For drawQuad and drawLayerQuad, they can handle 3 cases for now:
+    // 1) textureTarget == GL_TEXTURE_2D
+    // Normal texture in GL_TEXTURE_2D target.
+    // 2) textureTarget == GL_TEXTURE_EXTERNAL_OES
+    // Surface texture in GL_TEXTURE_EXTERNAL_OES target.
+    // 3) textureTarget == 0 (Will be deprecated soon)
+    // Surface texture in GL_TEXTURE_2D target.
+    //
+    // TODO: Shrink the support modes into 2 (1 and 2) after media framework
+    // support Surface texture in GL_TEXTURE_EXTERNAL_OES target on all
+    // platforms.
+    void drawQuad(SkRect& geometry, int textureId, float opacity,
+                  GLenum textureTarget = GL_TEXTURE_2D,
+                  GLint texFilter = GL_LINEAR);
+    void drawLayerQuad(const TransformationMatrix& drawMatrix,
+                       const SkRect& geometry, int textureId, float opacity,
+                       bool forceBlending = false,
+                       GLenum textureTarget = GL_TEXTURE_2D);
+    void drawVideoLayerQuad(const TransformationMatrix& drawMatrix,
+                     float* textureMatrix, SkRect& geometry, int textureId);
+    void setViewRect(const IntRect& viewRect);
+    FloatRect rectInScreenCoord(const TransformationMatrix& drawMatrix,
+                                const IntSize& size);
+    FloatRect rectInInvScreenCoord(const TransformationMatrix& drawMatrix,
+                                const IntSize& size);
+
+    FloatRect rectInInvScreenCoord(const FloatRect& rect);
+    FloatRect rectInScreenCoord(const FloatRect& rect);
+    FloatRect convertScreenCoordToDocumentCoord(const FloatRect& rect);
+    FloatRect convertInvScreenCoordToScreenCoord(const FloatRect& rect);
+    FloatRect convertScreenCoordToInvScreenCoord(const FloatRect& rect);
+
+    void setTitleBarHeight(int height) { m_titleBarHeight = height; }
+    void setWebViewRect(const IntRect& rect) { m_webViewRect = rect; }
+    void setScreenClip(const IntRect& clip);
+    void clip(const FloatRect& rect);
+    IntRect clippedRectWithViewport(const IntRect& rect, int margin = 0);
+    FloatRect documentViewport() { return m_documentViewport; }
+
+    void resetBlending();
+    float contrast() { return m_contrast; }
+    void setContrast(float c) {
+        float contrast = c;
+        if (contrast < 0)
+            contrast = 0;
+        if (contrast > MAX_CONTRAST)
+            contrast = MAX_CONTRAST;
+        m_contrast = contrast;
+    }
+    void setWebViewMatrix(const float* matrix, bool alphaLayer);
+
+    // This delta is the delta from the layout pos and the current animation pos.
+    // Basically, in terms of layout, the webview is still in the original layout
+    // pos, as without animation. Such that the viewport and visible rect etc are
+    // still in that pos, too, except the clipping info.
+    // Our rendering approach is after applying all the matrix, webView is
+    // rendered as if it was at the original layout pos, but then offset the
+    // glViewport to match the animation.
+    void calculateAnimationDelta();
+    int getAnimationDeltaX() { return m_animationDelta.x(); }
+    int getAnimationDeltaY() { return m_animationDelta.y(); }
+
+private:
+    GLuint loadShader(GLenum shaderType, const char* pSource);
+    GLuint createProgram(const char* vertexSource, const char* fragmentSource);
+    void setProjectionMatrix(SkRect& geometry, GLint projectionMatrixHandle);
+
+    void setBlendingState(bool enableBlending);
+
+    void drawQuadInternal(SkRect& geometry, GLint textureId, float opacity,
+                          GLint program, GLint projectionMatrixHandle,
+                          GLint texSampler, GLenum textureTarget,
+                          GLint position, GLint alpha,
+                          GLint texFilter, GLint contrast = -1);
+
+    void drawLayerQuadInternal(const GLfloat* projectionMatrix, int textureId,
+                               float opacity, GLenum textureTarget, GLint program,
+                               GLint matrix, GLint texSample,
+                               GLint position, GLint alpha, GLint contrast = -1);
+
+    bool m_blendingEnabled;
+
+    int m_program;
+    int m_programInverted;
+    int m_videoProgram;
+    int m_surfTexOESProgram;
+    int m_surfTexOESProgramInverted;
+
+    TransformationMatrix m_projectionMatrix;
+    GLuint m_textureBuffer[1];
+
+    TransformationMatrix m_documentToScreenMatrix;
+    TransformationMatrix m_documentToInvScreenMatrix;
+    SkRect m_viewport;
+    IntRect m_viewRect;
+    FloatRect m_clipRect;
+    IntRect m_screenClip;
+    int m_titleBarHeight;
+    IntRect m_webViewRect;
+
+    FloatRect m_documentViewport;
+
+    // uniforms
+    GLint m_hProjectionMatrix;
+    GLint m_hAlpha;
+    GLint m_hTexSampler;
+    GLint m_hProjectionMatrixInverted;
+    GLint m_hAlphaInverted;
+    GLint m_hContrastInverted;
+    GLint m_hTexSamplerInverted;
+    GLint m_hVideoProjectionMatrix;
+    GLint m_hVideoTextureMatrix;
+    GLint m_hVideoTexSampler;
+
+    GLint m_hSTOESProjectionMatrix;
+    GLint m_hSTOESAlpha;
+    GLint m_hSTOESTexSampler;
+    GLint m_hSTOESPosition;
+
+    GLint m_hSTOESProjectionMatrixInverted;
+    GLint m_hSTOESAlphaInverted;
+    GLint m_hSTOESContrastInverted;
+    GLint m_hSTOESTexSamplerInverted;
+    GLint m_hSTOESPositionInverted;
+
+    float m_contrast;
+
+    // attribs
+    GLint m_hPosition;
+    GLint m_hPositionInverted;
+    GLint m_hVideoPosition;
+
+    bool  m_alphaLayer;
+    TransformationMatrix m_webViewMatrix;
+    float m_currentScale;
+
+    // After the webViewTranform, we need to reposition the rect to match our viewport.
+    // Basically, the webViewTransformMatrix should apply on the screen resolution.
+    // So we start by doing the scale and translate to get each tile into screen coordinates.
+    // After applying the webViewTransformMatrix, b/c the way it currently set up
+    // for scroll and titlebar, we need to offset both of them.
+    // Finally, map everything back to (-1, 1) by using the m_projectionMatrix.
+    // TODO: Given that m_webViewMatrix contains most of the tranformation
+    // information, we should be able to get rid of some parameter we got from
+    // Java side and simplify our code.
+    TransformationMatrix  m_repositionMatrix;
+    IntPoint m_animationDelta;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+#endif // ShaderProgram_h
diff --git a/Source/WebCore/platform/graphics/android/SharedTexture.cpp b/Source/WebCore/platform/graphics/android/SharedTexture.cpp
new file mode 100644
index 0000000..74cd2c6
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/SharedTexture.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "SharedTexture.h"
+
+#include "GLUtils.h"
+#include <android/native_window.h>
+#include <gui/SurfaceTexture.h>
+#include <gui/SurfaceTextureClient.h>
+
+#define LOG_NDEBUG 1
+#define LOG_TAG "SharedTexture.cpp"
+#include <utils/Log.h>
+
+namespace WebCore {
+
+SharedTexture::SharedTexture(SharedTextureMode mode)
+{
+    m_sharedTextureMode = mode;
+
+    m_sourceTexture = new TextureInfo(m_sharedTextureMode);
+    m_targetTexture = 0;
+
+    if (m_sharedTextureMode == EglImageMode) {
+        m_targetTexture = new TextureInfo(m_sharedTextureMode);
+        m_eglImage = EGL_NO_IMAGE_KHR;
+        m_isNewImage = true;
+        m_syncObject = EGL_NO_SYNC_KHR;
+
+        // Defer initialization of these values until we initialize the source
+        // texture. This ensures that this initialization happens in the appropriate
+        // thread.
+        m_display = 0;
+        m_supportsEGLImage = false;
+        m_supportsEGLFenceSyncKHR = false;
+    } else if (m_sharedTextureMode == SurfaceTextureMode) {
+#if DEPRECATED_SURFACE_TEXTURE_MODE
+        glGenTextures(1, &m_sourceTexture->m_textureId);
+
+        m_sourceTexture->m_surfaceTexture =
+            new android::SurfaceTexture(m_sourceTexture->m_textureId, false);
+        m_sourceTexture->m_ANW =
+            new android::SurfaceTextureClient(m_sourceTexture->m_surfaceTexture);
+#endif
+    }
+}
+
+// called by the consumer when it no longer wants to consume and after it has
+// terminated all providers. If EGLImages are used, the deletion of the
+// source texture and EGLImage is the responsibility of the caller.
+SharedTexture::~SharedTexture()
+{
+    if (m_sharedTextureMode == EglImageMode)
+        deleteTargetTexture();
+    else if (m_sharedTextureMode == SurfaceTextureMode) {
+#if DEPRECATED_SURFACE_TEXTURE_MODE
+        m_sourceTexture->m_surfaceTexture.clear();
+        m_sourceTexture->m_ANW.clear();
+        GLUtils::deleteTexture(&m_sourceTexture->m_textureId);
+#endif
+    }
+    delete m_sourceTexture;
+    delete m_targetTexture;
+}
+
+
+void SharedTexture::initSourceTexture()
+{
+    if (m_sharedTextureMode == SurfaceTextureMode)
+        return;
+
+    m_display = eglGetCurrentDisplay();
+    m_supportsEGLImage = GLUtils::isEGLImageSupported();
+    m_supportsEGLFenceSyncKHR = GLUtils::isEGLFenceSyncSupported();
+
+    // TODO temporarily disable fence sync until the EGL framework fixes
+    // performance issues that result from consistently adding/removing fences.
+    m_supportsEGLFenceSyncKHR = false;
+
+    LOGI("imageEGL: %d syncKHR: %d", m_supportsEGLImage, m_supportsEGLFenceSyncKHR);
+
+    glGenTextures(1, &m_sourceTexture->m_textureId);
+
+}
+
+// For MediaTexture only
+void SharedTexture::deleteSourceTexture()
+{
+    if (m_sharedTextureMode == SurfaceTextureMode)
+        return;
+    // We need to delete the source texture and EGLImage in the thread in which
+    // it was created. In theory we should be able to delete the EGLImage
+    // from either thread, but it currently throws an error if not deleted
+    // in the same EGLContext from which it was created.
+    if (m_supportsEGLImage) {
+        GLUtils::deleteTexture(&m_sourceTexture->m_textureId);
+        if (m_eglImage != EGL_NO_IMAGE_KHR) {
+            eglDestroyImageKHR(eglGetCurrentDisplay(), m_eglImage);
+            m_eglImage = EGL_NO_IMAGE_KHR;
+            m_isNewImage = true;
+        }
+        LOGI("Deleted Source Texture and EGLImage");
+    }
+}
+
+// For MediaTexture only
+void SharedTexture::deleteTargetTexture()
+{
+    if (m_sharedTextureMode == SurfaceTextureMode)
+        return;
+
+    if (m_supportsEGLImage)
+        GLUtils::deleteTexture(&m_targetTexture->m_textureId);
+    else
+        GLUtils::deleteTexture(&m_sourceTexture->m_textureId);
+}
+
+TextureInfo* SharedTexture::lockSource()
+{
+    if (m_sharedTextureMode == SurfaceTextureMode)
+        return m_sourceTexture;
+
+    m_lock.lock();
+
+    if (m_supportsEGLFenceSyncKHR && m_syncObject != EGL_NO_SYNC_KHR) {
+
+        EGLint status = eglClientWaitSyncKHR(m_display, m_syncObject, 0, 1000000);
+
+        if (status == EGL_TIMEOUT_EXPIRED_KHR)
+            LOGE("Sync timeout for shared texture (%d)", m_sourceTexture->m_textureId);
+
+        eglDestroySyncKHR(m_display, m_syncObject);
+        m_syncObject = EGL_NO_SYNC_KHR;
+    }
+    return m_sourceTexture;
+}
+
+void SharedTexture::releaseSource()
+{
+    if (m_sharedTextureMode == SurfaceTextureMode)
+        return;
+
+    if (m_supportsEGLImage) {
+        // delete the existing image if needed
+        if (!m_sourceTexture->equalsAttributes(m_targetTexture)) {
+            if (m_eglImage != EGL_NO_IMAGE_KHR) {
+                eglDestroyImageKHR(m_display, m_eglImage);
+                m_eglImage = EGL_NO_IMAGE_KHR;
+                m_isNewImage = true;
+            }
+            m_targetTexture->copyAttributes(m_sourceTexture);
+        }
+
+        // create an image from the texture, only when the texture is valid
+        if (m_eglImage == EGL_NO_IMAGE_KHR && m_sourceTexture->m_width
+            && m_sourceTexture->m_height) {
+            GLUtils::createEGLImageFromTexture(m_sourceTexture->m_textureId, &m_eglImage);
+            LOGV("Generating Image (%d) 0x%x", m_sourceTexture->m_textureId, m_eglImage);
+
+            glFinish(); // ensures the texture is ready to be used by the consumer
+        }
+
+    } else {
+
+        m_targetTexture = m_sourceTexture;
+
+        // in the case of shared contexts we must flush the texture edits to the
+        // GPU. This ensures the edits complete prior to allowing the texture to
+        // be bound on the producers context.
+        glFlush();
+    }
+
+    m_lock.unlock();
+}
+
+TextureInfo* SharedTexture::lockTarget()
+{
+    // Note that the source and targe are the same when using Surface Texture.
+    if (m_sharedTextureMode == SurfaceTextureMode) {
+#if DEPRECATED_SURFACE_TEXTURE_MODE
+        m_sourceTexture->m_surfaceTexture->updateTexImage();
+#endif
+        return m_sourceTexture;
+    }
+
+    m_lock.lock();
+
+    if ((!m_supportsEGLImage && m_targetTexture->m_textureId == GL_NO_TEXTURE)
+        || (m_supportsEGLImage && m_eglImage == EGL_NO_IMAGE_KHR)) {
+        m_lock.unlock();
+        return 0;
+    }
+
+    if (m_supportsEGLImage && (m_isNewImage || m_targetTexture->m_textureId == GL_NO_TEXTURE)) {
+        if (m_targetTexture->m_textureId == GL_NO_TEXTURE)
+            glGenTextures(1, &m_targetTexture->m_textureId);
+
+        GLUtils::createTextureFromEGLImage(m_targetTexture->m_textureId, m_eglImage);
+        LOGV("Generating Consumer Texture from 0x%x", m_eglImage);
+        m_isNewImage = false;
+    }
+    return m_targetTexture;
+}
+
+void SharedTexture::releaseTarget()
+{
+    if (m_sharedTextureMode == SurfaceTextureMode)
+        return;
+
+    if (m_supportsEGLFenceSyncKHR) {
+        if (m_syncObject != EGL_NO_SYNC_KHR)
+            eglDestroySyncKHR(m_display, m_syncObject);
+        m_syncObject = eglCreateSyncKHR(m_display, EGL_SYNC_FENCE_KHR, 0);
+    } else {
+        // TODO the flush currently prevents the screen from getting partial
+        // updates but the only way to guarantee this is to call glFinish. Until
+        // we support an EGL sync we will leave flush enable in order to test
+        // with modest performance.
+        glFlush();
+    }
+
+    m_lock.unlock();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/SharedTexture.h b/Source/WebCore/platform/graphics/android/SharedTexture.h
new file mode 100644
index 0000000..305a442
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/SharedTexture.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SharedTexture_h
+#define SharedTexture_h
+
+#include "TextureInfo.h"
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <utils/threads.h>
+
+namespace WebCore {
+
+/**
+ * SharedTexture is a class that encapsulates all the necessary variables
+ * needed to share a single texture across threads. In the case that threads
+ * communicate using EGL's sharedContext mechanism or do not support the proper
+ * EGLImage extensions the targetTexture, eglImage, and isNewImage variables are
+ * not used.
+ */
+class SharedTexture {
+public:
+    // consumer thread functions
+    SharedTexture(SharedTextureMode mode);
+    ~SharedTexture();
+
+    TextureInfo* lockSource();
+    void releaseSource();
+
+    TextureInfo* lockTarget();
+    void releaseTarget();
+
+    // these locks are only used for the methods below
+    void lock() { m_lock.lock(); }
+    void unlock() { m_lock.unlock(); }
+
+    void initSourceTexture(); // producer thread only
+    void deleteSourceTexture(); // producer thread only
+    void deleteTargetTexture(); // consumer thread only
+    GLuint getSourceTextureId() { return m_sourceTexture->m_textureId; }
+    GLuint getTargetTextureId() { return m_targetTexture->m_textureId; }
+    EGLImageKHR getEGLImage() { return m_eglImage; }
+
+private:
+    /**
+     * The mutex is used to ensure that the contents of the struct are current across
+     * threads and that only one thread is manipulating the texture at a given time.
+     */
+    android::Mutex m_lock;
+    /**
+     * The texture and its associated metadata that is used by the producer. The
+     * texture is created in the producer's thread and can only be read by the
+     * consumer when the consumer shares the same context as the producer. The
+     * metadata is used to track changes to the texture that would orphan the
+     * target texture and require a new EGLImage to be constructed.
+     */
+    TextureInfo* m_sourceTexture;
+    /**
+     * The target texture stores the id and metadata of the texture that is to be
+     * used by the consumer. In the case where EGLImages are supported this hold
+     * the current eglImage target.
+     */
+    TextureInfo* m_targetTexture;
+    /**
+     * The EGLImage is used to share the texture between EGLContexts on two
+     * different threads. This serves as an alternative to sharing the contexts
+     * but is only used if GL and EGL support the required extensions.
+     */
+    EGLImageKHR m_eglImage;
+    /**
+     * This flag is used to determine if the eglImage has been updated. This
+     * signals the consumer thread to rebind the targetTexture to the new image.
+     */
+    bool m_isNewImage;
+    /**
+     * The sync allows the consumer to release the lock prior to the commands
+     * executing on the GPU. Prior to releasing the lock the consumer creates
+     * a sync object and stores it here. After locking the texture the client
+     * must check that the sync has completed prior to manipulating the texture.
+     * This value is only used if the proper EGL extensions are supported.
+     */
+    EGLSyncKHR m_syncObject;
+
+    EGLDisplay m_display;
+
+    bool m_supportsEGLImage;
+    bool m_supportsEGLFenceSyncKHR;
+
+    SharedTextureMode m_sharedTextureMode;
+};
+
+} // namespace WebCore
+
+#endif // SharedTexture_h
diff --git a/Source/WebCore/platform/graphics/android/utils/TestExport.h b/Source/WebCore/platform/graphics/android/TestExport.h
similarity index 100%
rename from Source/WebCore/platform/graphics/android/utils/TestExport.h
rename to Source/WebCore/platform/graphics/android/TestExport.h
diff --git a/Source/WebCore/platform/graphics/android/rendering/TextureInfo.cpp b/Source/WebCore/platform/graphics/android/TextureInfo.cpp
similarity index 95%
rename from Source/WebCore/platform/graphics/android/rendering/TextureInfo.cpp
rename to Source/WebCore/platform/graphics/android/TextureInfo.cpp
index f5c8b02..aff9a3d 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TextureInfo.cpp
+++ b/Source/WebCore/platform/graphics/android/TextureInfo.cpp
@@ -35,12 +35,14 @@
 
 namespace WebCore {
 
-TextureInfo::TextureInfo()
+TextureInfo::TextureInfo(SharedTextureMode mode)
 {
     m_textureId = GL_NO_TEXTURE;
     m_width = 0;
     m_height = 0;
     m_internalFormat = 0;
+    m_sharedTextureMode = mode;
+    m_pictureCount = 0;
 }
 
 bool TextureInfo::equalsAttributes(const TextureInfo* otherTexture)
diff --git a/Source/WebCore/platform/graphics/android/rendering/TextureInfo.h b/Source/WebCore/platform/graphics/android/TextureInfo.h
similarity index 81%
rename from Source/WebCore/platform/graphics/android/rendering/TextureInfo.h
rename to Source/WebCore/platform/graphics/android/TextureInfo.h
index 7d182c3..aca74b7 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TextureInfo.h
+++ b/Source/WebCore/platform/graphics/android/TextureInfo.h
@@ -31,8 +31,11 @@
 #include <jni.h>
 #include <ui/GraphicBuffer.h>
 #include <utils/RefBase.h>
+#include "BaseTile.h"
 using android::sp;
 
+#define DEPRECATED_SURFACE_TEXTURE_MODE 0
+
 namespace android {
 class SurfaceTexture;
 }
@@ -44,20 +47,34 @@
  * TextureInfo is a class that stores both the texture and metadata about the
  * texture.
  */
+enum SharedTextureMode {
+    EglImageMode,
+    SurfaceTextureMode
+};
 
 class TextureInfo {
 public:
-    TextureInfo();
+
+    TextureInfo(SharedTextureMode mode);
 
     bool equalsAttributes(const TextureInfo* otherTexture);
     void copyAttributes(const TextureInfo* sourceTexture);
 
+    SharedTextureMode getSharedTextureMode() { return m_sharedTextureMode; }
     bool operator==(const TextureInfo& otherTexture);
 
     GLuint m_textureId;
     int32_t m_width;
     int32_t m_height;
     GLenum m_internalFormat;
+
+    // Surface Texture specific data
+#if DEPRECATED_SURFACE_TEXTURE_MODE
+    sp<android::SurfaceTexture> m_surfaceTexture;
+#endif
+    int m_pictureCount;
+private:
+    SharedTextureMode m_sharedTextureMode;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/TextureOwner.h b/Source/WebCore/platform/graphics/android/TextureOwner.h
similarity index 87%
rename from Source/WebCore/platform/graphics/android/rendering/TextureOwner.h
rename to Source/WebCore/platform/graphics/android/TextureOwner.h
index b12d8b7..5434dbf 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TextureOwner.h
+++ b/Source/WebCore/platform/graphics/android/TextureOwner.h
@@ -31,13 +31,17 @@
 
 namespace WebCore {
 
-class TileTexture;
+class TiledPage;
+class BaseTileTexture;
 class GLWebViewState;
 
 class TextureOwner {
 public:
     virtual ~TextureOwner() { }
-    virtual bool removeTexture(TileTexture* texture) = 0;
+    virtual bool removeTexture(BaseTileTexture* texture) = 0;
+    virtual TiledPage* page() = 0;
+    virtual GLWebViewState* state() = 0;
+    virtual bool samePageAs(Layer* root) { return false; }
     virtual bool isRepaintPending() = 0;
     virtual unsigned long long drawCount() = 0;
 };
diff --git a/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp b/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp
new file mode 100644
index 0000000..ff41689
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "TexturesGenerator.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "BaseLayerAndroid.h"
+#include "GLUtils.h"
+#include "PaintTileOperation.h"
+#include "TilesManager.h"
+
+#ifdef DEBUG
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TexturesGenerator", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+namespace WebCore {
+
+void TexturesGenerator::scheduleOperation(QueuedOperation* operation)
+{
+    {
+        android::Mutex::Autolock lock(mRequestedOperationsLock);
+        mRequestedOperations.append(operation);
+    }
+    mRequestedOperationsCond.signal();
+}
+
+void TexturesGenerator::removeOperationsForPage(TiledPage* page)
+{
+    removeOperationsForFilter(new PageFilter(page));
+}
+
+void TexturesGenerator::removePaintOperationsForPage(TiledPage* page, bool waitForRunning)
+{
+    removeOperationsForFilter(new PagePaintFilter(page), waitForRunning);
+}
+
+void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter)
+{
+    removeOperationsForFilter(filter, true);
+}
+
+void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter, bool waitForRunning)
+{
+    if (!filter)
+        return;
+
+    android::Mutex::Autolock lock(mRequestedOperationsLock);
+    for (unsigned int i = 0; i < mRequestedOperations.size();) {
+        QueuedOperation* operation = mRequestedOperations[i];
+        if (filter->check(operation)) {
+            mRequestedOperations.remove(i);
+            delete operation;
+        } else {
+            i++;
+        }
+    }
+
+    if (waitForRunning && m_currentOperation) {
+        QueuedOperation* operation = m_currentOperation;
+
+        if (operation && filter->check(operation)) {
+            m_waitForCompletion = true;
+            // The reason we are signaling the transferQueue is :
+            // TransferQueue may be waiting a slot to work on, but now UI
+            // thread is waiting for Tex Gen thread to finish first before the
+            // UI thread can free a slot for the transferQueue.
+            // Therefore, it could be a deadlock.
+            // The solution is use this as a flag to tell Tex Gen thread that
+            // UI thread is waiting now, Tex Gen thread should not wait for the
+            // queue any more.
+            m_tilesManager->transferQueue()->interruptTransferQueue(true);
+        }
+
+        delete filter;
+
+        // At this point, it means that we are currently executing an operation that
+        // we want to be removed -- we should wait until it is done, so that
+        // when we return our caller can be sure that there is no more operations
+        // in the queue matching the given filter.
+        while (m_waitForCompletion)
+            mRequestedOperationsCond.wait(mRequestedOperationsLock);
+    } else {
+        delete filter;
+    }
+}
+
+status_t TexturesGenerator::readyToRun()
+{
+    XLOG("Thread ready to run");
+    return NO_ERROR;
+}
+
+// Must be called from within a lock!
+QueuedOperation* TexturesGenerator::popNext()
+{
+    // Priority can change between when it was added and now
+    // Hence why the entire queue is rescanned
+    QueuedOperation* current = mRequestedOperations.last();
+    int currentPriority = current->priority();
+    if (currentPriority < 0) {
+        mRequestedOperations.removeLast();
+        return current;
+    }
+    int currentIndex = mRequestedOperations.size() - 1;
+    // Scan from the back to make removing faster (less items to copy)
+    for (int i = mRequestedOperations.size() - 2; i >= 0; i--) {
+        QueuedOperation *next = mRequestedOperations[i];
+        int nextPriority = next->priority();
+        if (nextPriority < 0) {
+            // Found a very high priority item, go ahead and just handle it now
+            mRequestedOperations.remove(i);
+            return next;
+        }
+        // pick items preferrably by priority, or if equal, by order of
+        // insertion (as we add items at the back of the queue)
+        if (nextPriority <= currentPriority) {
+            current = next;
+            currentPriority = nextPriority;
+            currentIndex = i;
+        }
+    }
+    mRequestedOperations.remove(currentIndex);
+    return current;
+}
+
+bool TexturesGenerator::threadLoop()
+{
+    // Check if we have any pending operations.
+    mRequestedOperationsLock.lock();
+    while (!mRequestedOperations.size())
+        mRequestedOperationsCond.wait(mRequestedOperationsLock);
+
+    XLOG("threadLoop, got signal");
+    mRequestedOperationsLock.unlock();
+
+    m_currentOperation = 0;
+    bool stop = false;
+    while (!stop) {
+        mRequestedOperationsLock.lock();
+        XLOG("threadLoop, %d operations in the queue", mRequestedOperations.size());
+        if (mRequestedOperations.size())
+            m_currentOperation = popNext();
+        mRequestedOperationsLock.unlock();
+
+        if (m_currentOperation) {
+            XLOG("threadLoop, painting the request with priority %d", m_currentOperation->priority());
+            m_currentOperation->run();
+        }
+
+        QueuedOperation* oldOperation = m_currentOperation;
+        mRequestedOperationsLock.lock();
+        if (m_currentOperation)
+            m_currentOperation = 0;
+        if (!mRequestedOperations.size())
+            stop = true;
+        if (m_waitForCompletion) {
+            m_waitForCompletion = false;
+            m_tilesManager->transferQueue()->interruptTransferQueue(false);
+            mRequestedOperationsCond.signal();
+        }
+        mRequestedOperationsLock.unlock();
+        if (oldOperation)
+            delete oldOperation; // delete outside lock
+    }
+    XLOG("threadLoop empty");
+
+    return true;
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h b/Source/WebCore/platform/graphics/android/TexturesGenerator.h
similarity index 75%
rename from Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h
rename to Source/WebCore/platform/graphics/android/TexturesGenerator.h
index 290ad08..9299e87 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.h
+++ b/Source/WebCore/platform/graphics/android/TexturesGenerator.h
@@ -29,50 +29,43 @@
 #if USE(ACCELERATED_COMPOSITING)
 
 #include "QueuedOperation.h"
+#include "TiledPage.h"
 #include "TilePainter.h"
-#include <wtf/HashMap.h>
-#include <wtf/Vector.h>
-
 #include <utils/threads.h>
 
 namespace WebCore {
 
 using namespace android;
 
+class BaseLayerAndroid;
+class LayerAndroid;
 class TilesManager;
 
 class TexturesGenerator : public Thread {
 public:
     TexturesGenerator(TilesManager* instance) : Thread(false)
-        , m_tilesManager(instance)
-        , m_deferredMode(false) { }
+        , m_waitForCompletion(false)
+        , m_currentOperation(0)
+        , m_tilesManager(instance) { }
     virtual ~TexturesGenerator() { }
     virtual status_t readyToRun();
 
-    bool tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter);
-
+    void removeOperationsForPage(TiledPage* page);
+    void removePaintOperationsForPage(TiledPage* page, bool waitForRunning);
     void removeOperationsForFilter(OperationFilter* filter);
+    void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning);
 
     void scheduleOperation(QueuedOperation* operation);
 
-    // low res tiles are put at or above this cutoff when not scrolling,
-    // signifying that they should be deferred
-    static const int gDeferPriorityCutoff = 500000000;
-
 private:
     QueuedOperation* popNext();
     virtual bool threadLoop();
-    WTF::Vector<QueuedOperation*> mRequestedOperations;
-    WTF::HashMap<void*, QueuedOperation*> mRequestedOperationsHash;
+    Vector<QueuedOperation*> mRequestedOperations;
     android::Mutex mRequestedOperationsLock;
     android::Condition mRequestedOperationsCond;
+    bool m_waitForCompletion;
+    QueuedOperation* m_currentOperation;
     TilesManager* m_tilesManager;
-
-    bool m_deferredMode;
-
-    // defer painting for one second if best in queue has priority
-    // QueuedOperation::gDeferPriorityCutoff or higher
-    static const nsecs_t gDeferNsecs = 1000000000;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/TilePainter.h b/Source/WebCore/platform/graphics/android/TilePainter.h
similarity index 71%
rename from Source/WebCore/platform/graphics/android/rendering/TilePainter.h
rename to Source/WebCore/platform/graphics/android/TilePainter.h
index 901db66..4d0f5dc 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TilePainter.h
+++ b/Source/WebCore/platform/graphics/android/TilePainter.h
@@ -33,25 +33,22 @@
 
 namespace WebCore {
 
-class Color;
-class Tile;
+class BaseTile;
 
-class TilePainter : public SkRefCnt {
-// TODO: investigate webkit threadsafe ref counting
+class TilePainter {
 public:
-    virtual ~TilePainter() { }
-    virtual bool paint(SkCanvas* canvas) = 0;
-    virtual float opacity() { return 1.0; }
-    enum SurfaceType { Painted, Image };
-    virtual SurfaceType type() { return Painted; }
-    virtual Color* background() { return 0; }
-    virtual bool blitFromContents(Tile* tile) { return false; }
+   virtual ~TilePainter() { }
+   virtual bool paint(BaseTile* tile, SkCanvas*, unsigned int*) = 0;
+   virtual const TransformationMatrix* transform() { return 0; }
+};
 
-    unsigned int getUpdateCount() { return m_updateCount; }
-    void setUpdateCount(unsigned int updateCount) { m_updateCount = updateCount; }
-
-private:
-    unsigned int m_updateCount;
+class SurfacePainter : public SkRefCnt {
+public:
+   virtual ~SurfacePainter() { }
+   virtual const TransformationMatrix* transform() { return 0; }
+   virtual float opacity() { return 1.0; }
+   enum SurfaceType { PaintedSurface, ImageSurface };
+   virtual SurfaceType type() { return PaintedSurface; }
 };
 
 }
diff --git a/Source/WebCore/platform/graphics/android/TiledPage.cpp b/Source/WebCore/platform/graphics/android/TiledPage.cpp
new file mode 100644
index 0000000..31a0593
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/TiledPage.cpp
@@ -0,0 +1,413 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "TiledPage.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "GLUtils.h"
+#include "IntRect.h"
+#include "PaintTileOperation.h"
+#include "SkPaint.h"
+#include "SkPaintFlagsDrawFilter.h"
+#include "TilesManager.h"
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "TiledPage", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TiledPage", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+namespace WebCore {
+
+using namespace android;
+
+TiledPage::TiledPage(int id, GLWebViewState* state)
+    : m_baseTiles(0)
+    , m_baseTileSize(0)
+    , m_id(id)
+    , m_scale(1)
+    , m_invScale(1)
+    , m_glWebViewState(state)
+    , m_latestPictureInval(0)
+    , m_prepare(false)
+    , m_isPrefetchPage(false)
+    , m_willDraw(false)
+{
+    m_baseTiles = new BaseTile[TilesManager::getMaxTextureAllocation() + 1];
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->increment("TiledPage");
+#endif
+}
+
+void TiledPage::updateBaseTileSize()
+{
+    // This value must be at least 1 greater than the max number of allowed
+    // textures. This is because prepare() asks for a tile before it reserves
+    // a texture for that tile. If all textures are currently in use by the
+    // page then there will be no available tile and having the extra tile
+    // ensures that this does not happen. After claiming the extra tile the call
+    // to reserveTexture() will cause some other tile in the page to lose it's
+    // texture and become available, thus ensuring that we always have at least
+    // one tile that is available.
+    int baseTileSize = TilesManager::instance()->maxTextureCount() + 1;
+    if (baseTileSize > m_baseTileSize)
+        m_baseTileSize = baseTileSize;
+}
+
+TiledPage::~TiledPage()
+{
+    // In order to delete the page we must ensure that none of its BaseTiles are
+    // currently painting or scheduled to be painted by the TextureGenerator
+    TilesManager::instance()->removeOperationsForPage(this);
+    delete[] m_baseTiles;
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->decrement("TiledPage");
+#endif
+}
+
+BaseTile* TiledPage::getBaseTile(int x, int y) const
+{
+    // TODO: replace loop over array with HashMap indexing
+    for (int j = 0; j < m_baseTileSize; j++) {
+        BaseTile& tile = m_baseTiles[j];
+        if (tile.x() == x && tile.y() == y)
+            return &tile;
+    }
+    return 0;
+}
+
+void TiledPage::discardTextures()
+{
+    for (int j = 0; j < m_baseTileSize; j++) {
+        BaseTile& tile = m_baseTiles[j];
+        tile.discardTextures();
+    }
+    return;
+}
+
+void TiledPage::invalidateRect(const IntRect& inval, const unsigned int pictureCount)
+{
+    // Given the current scale level we need to mark the appropriate tiles as dirty
+    const float invTileContentWidth = m_scale / TilesManager::tileWidth();
+    const float invTileContentHeight = m_scale / TilesManager::tileHeight();
+
+    const int firstDirtyTileX = static_cast<int>(floorf(inval.x() * invTileContentWidth));
+    const int firstDirtyTileY = static_cast<int>(floorf(inval.y() * invTileContentHeight));
+    const int lastDirtyTileX = static_cast<int>(ceilf(inval.maxX() * invTileContentWidth));
+    const int lastDirtyTileY = static_cast<int>(ceilf(inval.maxY() * invTileContentHeight));
+
+    XLOG("Marking X %d-%d and Y %d-%d dirty", firstDirtyTileX, lastDirtyTileX, firstDirtyTileY, lastDirtyTileY);
+    // We defer marking the tile as dirty until the next time we need to prepare
+    // to draw.
+    m_invalRegion.op(firstDirtyTileX, firstDirtyTileY, lastDirtyTileX, lastDirtyTileY, SkRegion::kUnion_Op);
+    m_invalTilesRegion.op(inval.x(), inval.y(), inval.maxX(), inval.maxY(), SkRegion::kUnion_Op);
+    m_latestPictureInval = pictureCount;
+}
+
+void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, const SkIRect& tileBounds)
+{
+    for (int i = 0; i < tilesInRow; i++) {
+        int x = firstTileX;
+
+        // If we are goingLeft, we want to schedule the tiles starting from the
+        // right (and to the left if not). This is because tiles are appended to
+        // the list and the texture uploader goes through the set front to back.
+        if (goingLeft)
+            x += (tilesInRow - 1) - i;
+        else
+            x += i;
+
+        BaseTile* currentTile = 0;
+        BaseTile* availableTile = 0;
+        for (int j = 0; j < m_baseTileSize; j++) {
+            BaseTile& tile = m_baseTiles[j];
+            if (tile.x() == x && tile.y() == y) {
+                currentTile = &tile;
+                break;
+            }
+
+            if (!availableTile || (tile.drawCount() < availableTile->drawCount()))
+                availableTile = &tile;
+        }
+
+        if (!currentTile && availableTile) {
+            XLOG("STEALING tile %d, %d (draw count %llu) for tile %d, %d",
+                  availableTile->x(), availableTile->y(), availableTile->drawCount(), x, y);
+            availableTile->discardTextures(); // don't wait for textures to be stolen
+            currentTile = availableTile;
+        }
+
+        if (!currentTile) {
+            XLOG("ERROR: No tile available for tile %d %d", x, y);
+        }
+
+        if (currentTile) {
+            currentTile->setGLWebViewState(m_glWebViewState);
+            currentTile->setPage(this);
+
+            currentTile->setContents(this, x, y, m_scale);
+
+            // TODO: move below (which is largely the same for layers / tiled
+            // page) into prepare() function
+
+            // ensure there is a texture associated with the tile and then check to
+            // see if the texture is dirty and in need of repainting
+            if (currentTile->isDirty() || !currentTile->frontTexture())
+                currentTile->reserveTexture();
+            if (currentTile->backTexture()
+                    && currentTile->isDirty()
+                    && !currentTile->isRepaintPending()) {
+                PaintTileOperation *operation = new PaintTileOperation(currentTile);
+                TilesManager::instance()->scheduleOperation(operation);
+            }
+        }
+    }
+}
+
+bool TiledPage::updateTileDirtiness(const SkIRect& tileBounds)
+{
+    if (!m_glWebViewState || tileBounds.isEmpty()) {
+        m_invalRegion.setEmpty();
+        m_invalTilesRegion.setEmpty();
+        return false;
+    }
+
+    bool visibleTileIsDirty = false;
+    for (int x = 0; x < m_baseTileSize; x++) {
+
+        BaseTile& tile = m_baseTiles[x];
+
+        // if the tile is in the dirty region then we must invalidate it
+        if (m_invalRegion.contains(tile.x(), tile.y())) {
+            tile.markAsDirty(m_latestPictureInval, m_invalTilesRegion);
+            if (tileBounds.contains(tile.x(), tile.y()))
+                visibleTileIsDirty = true;
+        }
+    }
+
+    // clear the invalidated region as all tiles within that region have now
+    // been marked as dirty.
+    m_invalRegion.setEmpty();
+    m_invalTilesRegion.setEmpty();
+    return visibleTileIsDirty;
+}
+
+void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds, PrepareBounds bounds)
+{
+    if (!m_glWebViewState)
+        return;
+
+    TilesManager::instance()->gatherTextures();
+    m_scrollingDown = goingDown;
+
+    int firstTileX = tileBounds.fLeft;
+    int firstTileY = tileBounds.fTop;
+    int nbTilesWidth = tileBounds.width();
+    int nbTilesHeight = tileBounds.height();
+
+    // Expand number of tiles to allow tiles outside of viewport to be prepared for
+    // smoother scrolling.
+    int nTilesToPrepare = nbTilesWidth * nbTilesHeight;
+    int nMaxTilesPerPage = m_baseTileSize / 2;
+
+    if (bounds == ExpandedBounds) {
+        // prepare tiles outside of the visible bounds
+        int expandX = m_glWebViewState->expandedTileBoundsX();
+        int expandY = m_glWebViewState->expandedTileBoundsY();
+
+        firstTileX -= expandX;
+        nbTilesWidth += expandX * 2;
+
+        firstTileY -= expandY;
+        nbTilesHeight += expandY * 2;
+    }
+
+    // crop the tile bounds in each dimension to the larger of the base layer or viewport
+    float maxBaseX = m_glWebViewState->baseContentWidth() * m_scale / TilesManager::tileWidth();
+    float maxBaseY = m_glWebViewState->baseContentHeight() * m_scale / TilesManager::tileHeight();
+    int maxX = std::max(static_cast<int>(ceilf(maxBaseX)),
+                        m_glWebViewState->viewportTileBounds().width());
+    int maxY = std::max(static_cast<int>(ceilf(maxBaseY)),
+                        m_glWebViewState->viewportTileBounds().height());
+
+    // adjust perimeter to not go outside cropped region
+    if (firstTileX < 0) {
+        nbTilesWidth += firstTileX;
+        firstTileX = 0;
+    }
+    if (firstTileY < 0) {
+        nbTilesHeight += firstTileY;
+        firstTileY = 0;
+    }
+    nbTilesWidth = std::min(nbTilesWidth, maxX - firstTileX);
+    nbTilesHeight = std::min(nbTilesHeight, maxY - firstTileY);
+
+    // check against corrupted scale values giving bad height/width (use float to avoid overflow)
+    float numTiles = static_cast<float>(nbTilesHeight) * static_cast<float>(nbTilesWidth);
+    if (numTiles > TilesManager::getMaxTextureAllocation() || nbTilesHeight < 1 || nbTilesWidth < 1)
+    {
+        XLOGC("ERROR: We don't have enough tiles for this page!"
+              " nbTilesHeight %d nbTilesWidth %d", nbTilesHeight, nbTilesWidth);
+        return;
+    }
+    for (int i = 0; i < nbTilesHeight; i++)
+        prepareRow(goingLeft, nbTilesWidth, firstTileX, firstTileY + i, tileBounds);
+
+    m_prepare = true;
+}
+
+bool TiledPage::hasMissingContent(const SkIRect& tileBounds)
+{
+    int neededTiles = tileBounds.width() * tileBounds.height();
+    for (int j = 0; j < m_baseTileSize; j++) {
+        BaseTile& tile = m_baseTiles[j];
+        if (tileBounds.contains(tile.x(), tile.y())) {
+            if (tile.frontTexture())
+                neededTiles--;
+        }
+    }
+    return neededTiles > 0;
+}
+
+bool TiledPage::isReady(const SkIRect& tileBounds)
+{
+    int neededTiles = tileBounds.width() * tileBounds.height();
+    XLOG("tiled page %p needs %d ready tiles", this, neededTiles);
+    for (int j = 0; j < m_baseTileSize; j++) {
+        BaseTile& tile = m_baseTiles[j];
+        if (tileBounds.contains(tile.x(), tile.y())) {
+            if (tile.isTileReady())
+                neededTiles--;
+        }
+    }
+    XLOG("tiled page %p still needs %d ready tiles", this, neededTiles);
+    return neededTiles == 0;
+}
+
+bool TiledPage::swapBuffersIfReady(const SkIRect& tileBounds, float scale)
+{
+    if (!m_glWebViewState)
+        return false;
+
+    if (!m_invalRegion.isEmpty() && !m_prepare)
+        return false;
+
+    if (m_scale != scale)
+        return false;
+
+    int swaps = 0;
+    bool fullSwap = true;
+    for (int x = tileBounds.fLeft; x < tileBounds.fRight; x++) {
+        for (int y = tileBounds.fTop; y < tileBounds.fBottom; y++) {
+            BaseTile* t = getBaseTile(x, y);
+            if (!t || !t->isTileReady())
+                fullSwap = false;
+        }
+    }
+
+    // swap every tile on page (even if off screen)
+    for (int j = 0; j < m_baseTileSize; j++) {
+        BaseTile& tile = m_baseTiles[j];
+        if (tile.swapTexturesIfNeeded())
+            swaps++;
+    }
+
+    XLOG("%p greedy swapped %d textures, returning true", this, swaps);
+    return fullSwap;
+}
+
+void TiledPage::prepareForDrawGL(float transparency, const SkIRect& tileBounds)
+{
+    m_willDraw = true;
+    m_transparency = transparency;
+    m_tileBounds = tileBounds;
+}
+
+void TiledPage::drawGL()
+{
+    if (!m_glWebViewState || m_transparency == 0 || !m_willDraw)
+        return;
+
+    const float tileWidth = TilesManager::tileWidth() * m_invScale;
+    const float tileHeight = TilesManager::tileHeight() * m_invScale;
+
+    for (int j = 0; j < m_baseTileSize; j++) {
+        BaseTile& tile = m_baseTiles[j];
+        bool tileInView = m_tileBounds.contains(tile.x(), tile.y());
+        if (tileInView) {
+            SkRect rect;
+            rect.fLeft = tile.x() * tileWidth;
+            rect.fTop = tile.y() * tileHeight;
+            rect.fRight = rect.fLeft + tileWidth;
+            rect.fBottom = rect.fTop + tileHeight;
+
+            tile.draw(m_transparency, rect, m_scale);
+        }
+
+        TilesManager::instance()->getProfiler()->nextTile(tile, m_invScale, tileInView);
+    }
+    m_willDraw = false; // don't redraw until re-prepared
+}
+
+bool TiledPage::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed)
+{
+    static SkPaintFlagsDrawFilter prefetchFilter(SkPaint::kAllFlags,
+                                                 SkPaint::kAntiAlias_Flag);
+
+    if (!m_glWebViewState)
+        return false;
+
+    if (isPrefetchPage())
+        canvas->setDrawFilter(&prefetchFilter);
+
+    *pictureUsed = m_glWebViewState->paintBaseLayerContent(canvas);
+    return true;
+}
+
+TiledPage* TiledPage::sibling()
+{
+    if (!m_glWebViewState)
+        return 0;
+    return m_glWebViewState->sibling(this);
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/TiledPage.h b/Source/WebCore/platform/graphics/android/TiledPage.h
new file mode 100644
index 0000000..791e1f6
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/TiledPage.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TiledPage_h
+#define TiledPage_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "BaseTile.h"
+#include "SkCanvas.h"
+#include "SkRegion.h"
+
+#include "TilePainter.h"
+
+namespace WebCore {
+
+class GLWebViewState;
+class IntRect;
+
+/**
+ * The TiledPage represents a map of BaseTiles covering the viewport. Each
+ * GLWebViewState contains two TiledPages, one to display the page at the
+ * current scale factor, and another in the background that we use to paint the
+ * page at a different scale factor.  For instance, when we zoom using one
+ * TiledPage its tiles are scaled in hardware and therefore are subject to a
+ * loss of quality. To address this when the user finishes zooming we paint the
+ * background TilePage at the new scale factor.  When the background TilePage is
+ * ready, we swap it with the currently displaying TiledPage.
+ */
+class TiledPage : public TilePainter {
+public:
+    enum PrepareBounds {
+        ExpandedBounds = 0,
+        VisibleBounds = 1
+    };
+
+    TiledPage(int id, GLWebViewState* state);
+    ~TiledPage();
+
+    // returns the other TiledPage who shares the same GLWebViewState
+    TiledPage* sibling();
+
+    // prepare the page for display on the screen
+    void prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds, PrepareBounds bounds);
+
+    // update tiles with inval information, return true if visible ones are
+    // dirty (and thus repaint needed)
+    bool updateTileDirtiness(const SkIRect& tileBounds);
+
+    // returns true if the page can't draw the entire region (may still be stale)
+    bool hasMissingContent(const SkIRect& tileBounds);
+
+    bool isReady(const SkIRect& tileBounds);
+
+    // swap 'buffers' by swapping each modified texture
+    bool swapBuffersIfReady(const SkIRect& tileBounds, float scale);
+    // save the transparency and bounds to be drawn in drawGL()
+    void prepareForDrawGL(float transparency, const SkIRect& tileBounds);
+    // draw the page on the screen
+    void drawGL();
+
+    // TilePainter implementation
+    // used by individual tiles to generate the bitmap for their tile
+    bool paint(BaseTile*, SkCanvas*, unsigned int*);
+
+    // used by individual tiles to get the information about the current picture
+    GLWebViewState* glWebViewState() { return m_glWebViewState; }
+
+    float scale() const { return m_scale; }
+
+    //TODO: clear all textures if this is called with a new value
+    void setScale(float scale) { m_scale = scale; m_invScale = 1 / scale; }
+
+    void invalidateRect(const IntRect& invalRect, const unsigned int pictureCount);
+    void discardTextures();
+    void updateBaseTileSize();
+    bool scrollingDown() { return m_scrollingDown; }
+    bool isPrefetchPage() { return m_isPrefetchPage; }
+    void setIsPrefetchPage(bool isPrefetch) { m_isPrefetchPage = isPrefetch; }
+
+private:
+    void prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, const SkIRect& tileBounds);
+
+    BaseTile* getBaseTile(int x, int y) const;
+
+    // array of tiles used to compose a page. The tiles are allocated in the
+    // constructor to prevent them from potentially being allocated on the stack
+    BaseTile* m_baseTiles;
+    // stores the number of tiles in the m_baseTiles array. This enables us to
+    // quickly iterate over the array without have to check it's size
+    int m_baseTileSize;
+    int m_id;
+    float m_scale;
+    float m_invScale;
+    GLWebViewState* m_glWebViewState;
+
+    // used to identify the tiles that have been invalidated (marked dirty) since
+    // the last time updateTileState() has been called. The region is stored in
+    // terms of the (x,y) coordinates used to determine the location of the tile
+    // within the page, not in content/view pixel coordinates.
+    SkRegion m_invalRegion;
+
+    // inval regions in content coordinates
+    SkRegion m_invalTilesRegion;
+    unsigned int m_latestPictureInval;
+    bool m_prepare;
+    bool m_scrollingDown;
+    bool m_isPrefetchPage;
+
+    // info saved in prepare, used in drawGL()
+    bool m_willDraw;
+    SkIRect m_tileBounds;
+    float m_transparency;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+#endif // TiledPage_h
diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.cpp b/Source/WebCore/platform/graphics/android/TiledTexture.cpp
new file mode 100644
index 0000000..d538416
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/TiledTexture.cpp
@@ -0,0 +1,426 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "TiledTexture.h"
+
+#include "TilesManager.h"
+#include "TilesTracker.h"
+
+#include "PaintedSurface.h"
+#include "PaintTileOperation.h"
+#include "SkCanvas.h"
+#include "SkPicture.h"
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "TiledTexture", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TiledTexture", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+namespace WebCore {
+
+TiledTexture::~TiledTexture()
+{
+    SkSafeUnref(m_paintingPicture);
+#ifdef DEBUG_COUNT
+    ClassTracker::instance()->decrement("TiledTexture");
+#endif
+    removeTiles();
+}
+
+bool TiledTexture::ready()
+{
+    bool tilesAllReady = true;
+    bool tilesVisible = false;
+    for (unsigned int i = 0; i < m_tiles.size(); i++) {
+        BaseTile* tile = m_tiles[i];
+        if (tile->isTileVisible(m_area)) {
+            tilesVisible = true;
+            if (!tile->isTileReady()) {
+                tilesAllReady = false;
+                break;
+            }
+        }
+    }
+    // For now, if no textures are available, consider ourselves as ready
+    // in order to unblock the zooming process.
+    // FIXME: have a better system -- maybe keeping the last scale factor
+    // able to fully render everything
+    XLOG("TT %p, ready %d, visible %d, texturesRemain %d",
+         this, tilesAllReady, tilesVisible,
+         TilesManager::instance()->layerTexturesRemain());
+
+    return !TilesManager::instance()->layerTexturesRemain()
+            || !tilesVisible || tilesAllReady;
+}
+
+void TiledTexture::swapTiles()
+{
+    int swaps = 0;
+    for (unsigned int i = 0; i < m_tiles.size(); i++)
+        if (m_tiles[i]->swapTexturesIfNeeded())
+            swaps++;
+    XLOG("TT %p swapping, swaps = %d", this, swaps);
+}
+
+IntRect TiledTexture::computeTilesArea(IntRect& visibleArea, float scale)
+{
+    IntRect computedArea;
+    IntRect area(visibleArea.x() * scale,
+                 visibleArea.y() * scale,
+                 ceilf(visibleArea.width() * scale),
+                 ceilf(visibleArea.height() * scale));
+
+    XLOG("TT %p prepare, scale %f, area %d x %d", this, scale, area.width(), area.height());
+
+    if (area.width() == 0 && area.height() == 0) {
+        computedArea.setWidth(0);
+        computedArea.setHeight(0);
+        return computedArea;
+    }
+
+    int tileWidth = TilesManager::instance()->layerTileWidth();
+    int tileHeight = TilesManager::instance()->layerTileHeight();
+
+    computedArea.setX(area.x() / tileWidth);
+    computedArea.setY(area.y() / tileHeight);
+    float right = (area.x() + area.width()) / (float) tileWidth;
+    float bottom = (area.y() + area.height()) / (float) tileHeight;
+    computedArea.setWidth(ceilf(right) - computedArea.x());
+    computedArea.setHeight(ceilf(bottom) - computedArea.y());
+    return computedArea;
+}
+
+void TiledTexture::prepare(GLWebViewState* state, float scale, bool repaint,
+                           bool startFastSwap, IntRect& visibleArea)
+{
+    if (!m_surface)
+        return;
+
+    // first, how many tiles do we need
+    m_area = computeTilesArea(visibleArea, scale);
+    if (m_area.isEmpty())
+        return;
+
+    XLOG("for TiledTexture %p, we prepare with scale %.2f, have a visible area of "
+         " %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles",
+         this, scale,
+         visibleArea.x(), visibleArea.y(),
+         visibleArea.width(), visibleArea.height(),
+         m_area.x(), m_area.y(),
+         m_area.width(), m_area.height());
+
+    bool goingDown = m_prevTileY < m_area.y();
+    m_prevTileY = m_area.y();
+
+    if (scale != m_scale)
+        TilesManager::instance()->removeOperationsForFilter(new ScaleFilter(this, scale));
+
+    m_scale = scale;
+
+    // apply dirty region to affected tiles
+    if (!m_dirtyRegion.isEmpty()) {
+        for (unsigned int i = 0; i < m_tiles.size(); i++) {
+            // TODO: don't mark all tiles dirty
+            m_tiles[i]->markAsDirty(1, m_dirtyRegion);
+        }
+    }
+    m_dirtyRegion.setEmpty();
+
+    for (int i = 0; i < m_area.width(); i++) {
+        if (goingDown) {
+            for (int j = 0; j < m_area.height(); j++) {
+                prepareTile(repaint, m_area.x() + i, m_area.y() + j);
+            }
+        } else {
+            for (int j = m_area.height() - 1; j >= 0; j--) {
+                prepareTile(repaint, m_area.x() + i, m_area.y() + j);
+            }
+        }
+    }
+}
+
+void TiledTexture::update(const SkRegion& invalRegion, SkPicture* picture)
+{
+    XLOG("TT %p update, current region empty %d, new empty %d, painting picture %p",
+          this, m_dirtyRegion.isEmpty(), invalRegion.isEmpty(), picture);
+    m_dirtyRegion.op(invalRegion, SkRegion::kUnion_Op);
+
+    android::Mutex::Autolock lock(m_paintingPictureSync);
+    SkSafeRef(picture);
+    SkSafeUnref(m_paintingPicture);
+    m_paintingPicture = picture;
+}
+
+void TiledTexture::prepareTile(bool repaint, int x, int y)
+{
+    BaseTile* tile = getTile(x, y);
+    if (!tile) {
+        tile = new BaseTile(true);
+        m_tiles.append(tile);
+    }
+
+    XLOG("preparing tile %p at %d, %d, painter is this %p", tile, x, y, this);
+    tile->setContents(this, x, y, m_scale);
+
+    // TODO: move below (which is largely the same for layers / tiled page) into
+    // prepare() function
+
+    if (tile->isDirty() || !tile->frontTexture())
+        tile->reserveTexture();
+
+    bool hasPicture = m_paintingPicture != 0; // safely read on UI thread, since only UI thread writes
+    if (tile->backTexture() && tile->isDirty() && !tile->isRepaintPending() && hasPicture) {
+        PaintTileOperation *operation = new PaintTileOperation(tile, m_surface);
+        TilesManager::instance()->scheduleOperation(operation);
+    }
+}
+
+BaseTile* TiledTexture::getTile(int x, int y)
+{
+    for (unsigned int i = 0; i <m_tiles.size(); i++) {
+        BaseTile* tile = m_tiles[i];
+        if (tile->x() == x && tile->y() == y)
+            return tile;
+    }
+    return 0;
+}
+
+int TiledTexture::nbTextures(IntRect& area, float scale)
+{
+    IntRect tileBounds = computeTilesArea(area, scale);
+    int numberTextures = tileBounds.width() * tileBounds.height();
+
+    // add the number of dirty tiles in the bounds, as they take up double
+    // textures for double buffering
+    for (unsigned int i = 0; i <m_tiles.size(); i++) {
+        BaseTile* tile = m_tiles[i];
+        if (tile->isDirty()
+                && tile->x() >= tileBounds.x() && tile->x() <= tileBounds.maxX()
+                && tile->y() >= tileBounds.y() && tile->y() <= tileBounds.maxY())
+            numberTextures++;
+    }
+    return numberTextures;
+}
+
+bool TiledTexture::draw()
+{
+    if (!m_surface)
+        return true;
+
+    XLOG("TT %p draw", this);
+
+#ifdef DEBUG
+    TilesManager::instance()->getTilesTracker()->trackLayer();
+#endif
+
+    if (m_area.width() == 0 || m_area.height() == 0)
+        return false;
+
+#ifdef DEBUG
+    TilesManager::instance()->getTilesTracker()->trackVisibleLayer();
+#endif
+
+    float m_invScale = 1 / m_scale;
+    const float tileWidth = TilesManager::layerTileWidth() * m_invScale;
+    const float tileHeight = TilesManager::layerTileHeight() * m_invScale;
+
+    bool askRedraw = false;
+    for (unsigned int i = 0; i < m_tiles.size(); i++) {
+        BaseTile* tile = m_tiles[i];
+
+        if (tile->isTileVisible(m_area)) {
+            askRedraw |= !tile->isTileReady();
+            SkRect rect;
+            rect.fLeft = tile->x() * tileWidth;
+            rect.fTop = tile->y() * tileHeight;
+            rect.fRight = rect.fLeft + tileWidth;
+            rect.fBottom = rect.fTop + tileHeight;
+            XLOG("- [%d], { painter %x vs %x }, tile %x (layer tile: %d) %d,%d at scale %.2f vs %.2f [ready: %d] dirty: %d",
+                 i, this, tile->painter(), tile, tile->isLayerTile(), tile->x(), tile->y(),
+                 tile->scale(), m_scale, tile->isTileReady(), tile->isDirty());
+            tile->draw(m_surface->opacity(), rect, m_scale);
+#ifdef DEBUG
+            TilesManager::instance()->getTilesTracker()->track(tile->isTileReady(), tile->backTexture());
+#endif
+        }
+    }
+
+    // need to redraw if some visible tile wasn't ready
+    return askRedraw;
+}
+
+bool TiledTexture::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed)
+{
+    m_paintingPictureSync.lock();
+    SkPicture* picture = m_paintingPicture;
+    SkSafeRef(picture);
+    m_paintingPictureSync.unlock();
+
+    if (!picture) {
+        XLOG("TT %p COULDNT PAINT, NO PICTURE", this);
+        return false;
+    }
+
+    XLOG("TT %p painting tile %d, %d with picture %p", this, tile->x(), tile->y(), picture);
+
+    canvas->drawPicture(*picture);
+
+    SkSafeUnref(picture);
+
+    return true;
+}
+
+const TransformationMatrix* TiledTexture::transform()
+{
+    if (!m_surface)
+        return 0;
+    return m_surface->transform();
+}
+
+void TiledTexture::removeTiles()
+{
+    for (unsigned int i = 0; i < m_tiles.size(); i++) {
+        delete m_tiles[i];
+    }
+    m_tiles.clear();
+}
+
+void TiledTexture::discardTextures()
+{
+    for (unsigned int i = 0; i < m_tiles.size(); i++)
+        m_tiles[i]->discardTextures();
+}
+
+bool TiledTexture::owns(BaseTileTexture* texture)
+{
+    for (unsigned int i = 0; i < m_tiles.size(); i++) {
+        BaseTile* tile = m_tiles[i];
+        if (tile->frontTexture() == texture)
+            return true;
+        if (tile->backTexture() == texture)
+            return true;
+    }
+    return false;
+}
+
+DualTiledTexture::DualTiledTexture(SurfacePainter* surface)
+{
+    m_textureA = new TiledTexture(surface);
+    m_textureB = new TiledTexture(surface);
+    m_frontTexture = m_textureA;
+    m_backTexture = m_textureB;
+    m_scale = -1;
+    m_futureScale = -1;
+    m_zooming = false;
+}
+
+DualTiledTexture::~DualTiledTexture()
+{
+    delete m_textureA;
+    delete m_textureB;
+}
+
+void DualTiledTexture::prepare(GLWebViewState* state, float scale, bool repaint,
+                               bool startFastSwap, IntRect& visibleArea)
+{
+    // If we are zooming, we will use the previously used area, to prevent the
+    // frontTexture to try to allocate more tiles than what it has already
+    if (!m_zooming)
+        m_preZoomVisibleArea = visibleArea;
+
+    if (m_futureScale != scale) {
+        m_futureScale = scale;
+        m_zoomUpdateTime = WTF::currentTime() + DualTiledTexture::s_zoomUpdateDelay;
+        m_zooming = true;
+    }
+
+    XLOG("Preparing DTT %p with scale %.2f, m_scale %.2f, futureScale: %.2f, zooming: %d",
+          this, scale, m_scale, m_futureScale, m_zooming);
+
+    if (m_scale > 0)
+        m_frontTexture->prepare(state, m_scale, repaint, startFastSwap, m_preZoomVisibleArea);
+
+    // If we had a scheduled update
+    if (m_zooming && m_zoomUpdateTime < WTF::currentTime()) {
+        m_backTexture->prepare(state, m_futureScale, repaint, startFastSwap, visibleArea);
+        if (m_backTexture->ready()) {
+            m_backTexture->swapTiles();
+            swap();
+            m_zooming = false;
+        }
+    }
+}
+
+void DualTiledTexture::swap()
+{
+    m_frontTexture = m_frontTexture == m_textureA ? m_textureB : m_textureA;
+    m_backTexture = m_backTexture == m_textureA ? m_textureB : m_textureA;
+    m_scale = m_futureScale;
+    m_backTexture->discardTextures();
+}
+
+bool DualTiledTexture::draw()
+{
+    bool needsRepaint = m_frontTexture->draw();
+    needsRepaint |= m_zooming;
+    needsRepaint |= (m_scale <= 0);
+    return needsRepaint;
+}
+
+void DualTiledTexture::update(const SkRegion& dirtyArea, SkPicture* picture)
+{
+    m_backTexture->update(dirtyArea, picture);
+    m_frontTexture->update(dirtyArea, picture);
+}
+
+void DualTiledTexture::swapTiles()
+{
+    m_backTexture->swapTiles();
+    m_frontTexture->swapTiles();
+}
+
+bool DualTiledTexture::owns(BaseTileTexture* texture)
+{
+    bool owns = m_textureA->owns(texture);
+    owns |= m_textureB->owns(texture);
+    return owns;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.h b/Source/WebCore/platform/graphics/android/TiledTexture.h
new file mode 100644
index 0000000..444ab14
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/TiledTexture.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TiledTexture_h
+#define TiledTexture_h
+
+#include "BaseTile.h"
+#include "BaseTileTexture.h"
+#include "ClassTracker.h"
+#include "IntRect.h"
+#include "LayerAndroid.h"
+#include "SkRegion.h"
+#include "TextureOwner.h"
+#include "TilePainter.h"
+
+class SkCanvas;
+
+namespace WebCore {
+
+class TiledTexture : public TilePainter {
+public:
+    TiledTexture(SurfacePainter* surface)
+        : m_paintingPicture(0)
+        , m_surface(surface)
+        , m_prevTileX(0)
+        , m_prevTileY(0)
+        , m_scale(1)
+        , m_swapWhateverIsReady(false)
+    {
+        m_dirtyRegion.setEmpty();
+#ifdef DEBUG_COUNT
+        ClassTracker::instance()->increment("TiledTexture");
+#endif
+    }
+
+    virtual ~TiledTexture();
+
+    IntRect computeTilesArea(IntRect& visibleArea, float scale);
+
+    void prepare(GLWebViewState* state, float scale, bool repaint,
+                 bool startFastSwap, IntRect& visibleArea);
+    void swapTiles();
+    bool draw();
+
+    void prepareTile(bool repaint, int x, int y);
+    void update(const SkRegion& dirtyArea, SkPicture* picture);
+
+    BaseTile* getTile(int x, int y);
+
+    void removeTiles();
+    void discardTextures();
+    bool owns(BaseTileTexture* texture);
+
+    // TilePainter methods
+    bool paint(BaseTile* tile, SkCanvas*, unsigned int*);
+    virtual const TransformationMatrix* transform();
+
+    float scale() { return m_scale; }
+    bool ready();
+
+    int nbTextures(IntRect& area, float scale);
+
+private:
+    bool tileIsVisible(BaseTile* tile);
+
+    // protect m_paintingPicture
+    //    update() on UI thread modifies
+    //    paint() on texture gen thread reads
+    android::Mutex m_paintingPictureSync;
+    SkPicture* m_paintingPicture;
+
+    SurfacePainter* m_surface;
+    Vector<BaseTile*> m_tiles;
+
+    // tile coordinates in viewport, set in prepare()
+    IntRect m_area;
+
+    SkRegion m_dirtyRegion;
+
+    int m_prevTileX;
+    int m_prevTileY;
+    float m_scale;
+
+    bool m_swapWhateverIsReady;
+};
+
+class DualTiledTexture {
+public:
+    DualTiledTexture(SurfacePainter* surface);
+    ~DualTiledTexture();
+    void prepare(GLWebViewState* state, float scale, bool repaint,
+                 bool startFastSwap, IntRect& area);
+    void swapTiles();
+    void swap();
+    bool draw();
+    void update(const SkRegion& dirtyArea, SkPicture* picture);
+    bool owns(BaseTileTexture* texture);
+    bool isReady()
+    {
+        return !m_zooming && m_frontTexture->ready();
+    }
+
+    int nbTextures(IntRect& area, float scale)
+    {
+        // TODO: consider the zooming case for the backTexture
+        if (!m_frontTexture)
+            return 0;
+        return m_frontTexture->nbTextures(area, scale);
+    }
+
+private:
+    // Delay before we schedule a new tile at the new scale factor
+    static const double s_zoomUpdateDelay = 0.2; // 200 ms
+
+    TiledTexture* m_frontTexture;
+    TiledTexture* m_backTexture;
+    TiledTexture* m_textureA;
+    TiledTexture* m_textureB;
+    float m_scale;
+    float m_futureScale;
+    double m_zoomUpdateTime;
+    bool m_zooming;
+    IntRect m_preZoomVisibleArea;
+};
+
+} // namespace WebCore
+
+#endif // TiledTexture_h
diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp
new file mode 100644
index 0000000..e329524
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp
@@ -0,0 +1,498 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "TilesManager.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "BaseTile.h"
+#include "PaintedSurface.h"
+#include "SkCanvas.h"
+#include "SkDevice.h"
+#include "SkPaint.h"
+#include <android/native_window.h>
+#include <cutils/atomic.h>
+#include <gui/SurfaceTexture.h>
+#include <gui/SurfaceTextureClient.h>
+
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "TilesManager", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TilesManager", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+// Important: We need at least twice as many textures as is needed to cover
+// one viewport, otherwise the allocation may stall.
+// We need n textures for one TiledPage, and another n textures for the
+// second page used when scaling.
+// In our case, we use 256*256 textures. On the tablet, this equates to
+// at least 60 textures, or 112 with expanded tile boundaries.
+// 112(tiles)*256*256*4(bpp)*2(pages) = 56MB
+// It turns out the viewport dependent value m_maxTextureCount is a reasonable
+// number to cap the layer tile texturs, it worked on both phones and tablets.
+// TODO: after merge the pool of base tiles and layer tiles, we should revisit
+// the logic of allocation management.
+#define MAX_TEXTURE_ALLOCATION ((6+TILE_PREFETCH_DISTANCE*2)*(5+TILE_PREFETCH_DISTANCE*2)*4)
+#define TILE_WIDTH 256
+#define TILE_HEIGHT 256
+#define LAYER_TILE_WIDTH 256
+#define LAYER_TILE_HEIGHT 256
+
+#define BYTES_PER_PIXEL 4 // 8888 config
+
+#define LAYER_TEXTURES_DESTROY_TIMEOUT 60 // If we do not need layers for 60 seconds, free the textures
+
+namespace WebCore {
+
+GLint TilesManager::getMaxTextureSize()
+{
+    static GLint maxTextureSize = 0;
+    if (!maxTextureSize)
+        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
+    return maxTextureSize;
+}
+
+int TilesManager::getMaxTextureAllocation()
+{
+    return MAX_TEXTURE_ALLOCATION;
+}
+
+TilesManager::TilesManager()
+    : m_layerTexturesRemain(true)
+    , m_maxTextureCount(0)
+    , m_maxLayerTextureCount(0)
+    , m_generatorReady(false)
+    , m_showVisualIndicator(false)
+    , m_invertedScreen(false)
+    , m_invertedScreenSwitch(false)
+    , m_useMinimalMemory(true)
+    , m_drawGLCount(1)
+    , m_lastTimeLayersUsed(0)
+    , m_hasLayerTextures(false)
+{
+    XLOG("TilesManager ctor");
+    m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
+    m_availableTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
+    m_tilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
+    m_availableTilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
+    m_pixmapsGenerationThread = new TexturesGenerator(this);
+    m_pixmapsGenerationThread->run("TexturesGenerator");
+}
+
+void TilesManager::allocateTiles()
+{
+    int nbTexturesToAllocate = m_maxTextureCount - m_textures.size();
+    XLOG("%d tiles to allocate (%d textures planned)", nbTexturesToAllocate, m_maxTextureCount);
+    int nbTexturesAllocated = 0;
+    for (int i = 0; i < nbTexturesToAllocate; i++) {
+        BaseTileTexture* texture = new BaseTileTexture(
+            tileWidth(), tileHeight());
+        // the atomic load ensures that the texture has been fully initialized
+        // before we pass a pointer for other threads to operate on
+        BaseTileTexture* loadedTexture =
+            reinterpret_cast<BaseTileTexture*>(
+            android_atomic_acquire_load(reinterpret_cast<int32_t*>(&texture)));
+        m_textures.append(loadedTexture);
+        nbTexturesAllocated++;
+    }
+
+    int nbLayersTexturesToAllocate = m_maxLayerTextureCount - m_tilesTextures.size();
+    XLOG("%d layers tiles to allocate (%d textures planned)",
+         nbLayersTexturesToAllocate, m_maxLayerTextureCount);
+    int nbLayersTexturesAllocated = 0;
+    for (int i = 0; i < nbLayersTexturesToAllocate; i++) {
+        BaseTileTexture* texture = new BaseTileTexture(
+            layerTileWidth(), layerTileHeight());
+        // the atomic load ensures that the texture has been fully initialized
+        // before we pass a pointer for other threads to operate on
+        BaseTileTexture* loadedTexture =
+            reinterpret_cast<BaseTileTexture*>(
+            android_atomic_acquire_load(reinterpret_cast<int32_t*>(&texture)));
+        m_tilesTextures.append(loadedTexture);
+        nbLayersTexturesAllocated++;
+    }
+    XLOG("allocated %d textures for base (total: %d, %d Mb), %d textures for layers (total: %d, %d Mb)",
+         nbTexturesAllocated, m_textures.size(),
+         m_textures.size() * TILE_WIDTH * TILE_HEIGHT * 4 / 1024 / 1024,
+         nbLayersTexturesAllocated, m_tilesTextures.size(),
+         m_tilesTextures.size() * LAYER_TILE_WIDTH * LAYER_TILE_HEIGHT * 4 / 1024 / 1024);
+}
+
+void TilesManager::deallocateTextures(bool allTextures)
+{
+    const unsigned int max = m_textures.size();
+
+    unsigned long long sparedDrawCount = ~0; // by default, spare no textures
+    if (!allTextures) {
+        // if we're not deallocating all textures, spare those with max drawcount
+        sparedDrawCount = 0;
+        for (unsigned int i = 0; i < max; i++) {
+            TextureOwner* owner = m_textures[i]->owner();
+            if (owner)
+                sparedDrawCount = std::max(sparedDrawCount, owner->drawCount());
+        }
+    }
+    deallocateTexturesVector(sparedDrawCount, m_textures);
+    deallocateTexturesVector(sparedDrawCount, m_tilesTextures);
+}
+
+void TilesManager::deallocateTexturesVector(unsigned long long sparedDrawCount,
+                                            WTF::Vector<BaseTileTexture*>& textures)
+{
+    const unsigned int max = textures.size();
+    int dealloc = 0;
+    for (unsigned int i = 0; i < max; i++) {
+        TextureOwner* owner = textures[i]->owner();
+        if (!owner || owner->drawCount() < sparedDrawCount) {
+            textures[i]->discardGLTexture();
+            dealloc++;
+        }
+    }
+    XLOG("Deallocated %d gl textures (out of %d base tiles and %d layer tiles)",
+         dealloc, max, maxLayer);
+}
+
+void TilesManager::gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextures,
+                                        int* nbLayerTextures, int* nbAllocatedLayerTextures)
+{
+    *nbTextures = m_textures.size();
+    for (unsigned int i = 0; i < m_textures.size(); i++) {
+        BaseTileTexture* texture = m_textures[i];
+        if (texture->m_ownTextureId)
+            *nbAllocatedTextures += 1;
+    }
+    *nbLayerTextures = m_tilesTextures.size();
+    for (unsigned int i = 0; i < m_tilesTextures.size(); i++) {
+        BaseTileTexture* texture = m_tilesTextures[i];
+        if (texture->m_ownTextureId)
+            *nbAllocatedLayerTextures += 1;
+    }
+}
+
+void TilesManager::printTextures()
+{
+#ifdef DEBUG
+    XLOG("++++++");
+    for (unsigned int i = 0; i < m_textures.size(); i++) {
+        BaseTileTexture* texture = m_textures[i];
+        BaseTile* o = 0;
+        if (texture->owner())
+            o = (BaseTile*) texture->owner();
+        int x = -1;
+        int y = -1;
+        if (o) {
+            x = o->x();
+            y = o->y();
+        }
+        XLOG("[%d] texture %x  busy: %d owner: %x (%d, %d) page: %x scale: %.2f",
+               i, texture,
+               texture->busy(), o, x, y, o ? o->page() : 0, o ? o->scale() : 0);
+    }
+    XLOG("------");
+#endif // DEBUG
+}
+
+void TilesManager::addPaintedSurface(PaintedSurface* surface)
+{
+    m_paintedSurfaces.append(surface);
+}
+
+void TilesManager::gatherTextures()
+{
+    android::Mutex::Autolock lock(m_texturesLock);
+    m_availableTextures = m_textures;
+}
+
+void TilesManager::gatherLayerTextures()
+{
+    android::Mutex::Autolock lock(m_texturesLock);
+    m_availableTilesTextures = m_tilesTextures;
+    m_layerTexturesRemain = true;
+}
+
+BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner)
+{
+    android::Mutex::Autolock lock(m_texturesLock);
+
+    // Sanity check that the tile does not already own a texture
+    if (owner->backTexture() && owner->backTexture()->owner() == owner) {
+        XLOG("same owner (%d, %d), getAvailableBackTexture(%x) => texture %x",
+             owner->x(), owner->y(), owner, owner->backTexture());
+        if (owner->isLayerTile())
+            m_availableTilesTextures.remove(m_availableTilesTextures.find(owner->backTexture()));
+        else
+            m_availableTextures.remove(m_availableTextures.find(owner->backTexture()));
+        return owner->backTexture();
+    }
+
+    WTF::Vector<BaseTileTexture*>* availableTexturePool;
+    if (owner->isLayerTile()) {
+        availableTexturePool = &m_availableTilesTextures;
+    } else {
+        availableTexturePool = &m_availableTextures;
+    }
+
+    // The heuristic for selecting a texture is as follows:
+    //  1. Skip textures currently being painted, they can't be painted while
+    //         busy anyway
+    //  2. If a tile isn't owned, break with that one
+    //  3. Don't let tiles acquire their front textures
+    //  4. If we find a tile in the same page with a different scale,
+    //         it's old and not visible. Break with that one
+    //  5. Otherwise, use the least recently prepared tile, but ignoring tiles
+    //         drawn in the last frame to avoid flickering
+
+    BaseTileTexture* farthestTexture = 0;
+    unsigned long long oldestDrawCount = getDrawGLCount() - 1;
+    const unsigned int max = availableTexturePool->size();
+    for (unsigned int i = 0; i < max; i++) {
+        BaseTileTexture* texture = (*availableTexturePool)[i];
+        BaseTile* currentOwner = static_cast<BaseTile*>(texture->owner());
+
+        if (texture->busy()) {
+            // don't bother, since the acquire() will likely fail
+            continue;
+        }
+
+        if (!currentOwner) {
+            // unused texture! take it!
+            farthestTexture = texture;
+            break;
+        }
+
+        if (currentOwner == owner) {
+            // Don't let a tile acquire its own front texture, as the
+            // acquisition logic doesn't handle that
+            continue;
+        }
+
+        if (currentOwner->painter() == owner->painter() && texture->scale() != owner->scale()) {
+            // if we render the back page with one scale, then another while
+            // still zooming, we recycle the tiles with the old scale instead of
+            // taking ones from the front page
+            farthestTexture = texture;
+            break;
+        }
+
+        unsigned long long textureDrawCount = currentOwner->drawCount();
+        if (oldestDrawCount > textureDrawCount) {
+            farthestTexture = texture;
+            oldestDrawCount = textureDrawCount;
+        }
+    }
+
+    if (farthestTexture) {
+        BaseTile* previousOwner = static_cast<BaseTile*>(farthestTexture->owner());
+        if (farthestTexture->acquire(owner)) {
+            if (previousOwner) {
+                previousOwner->removeTexture(farthestTexture);
+
+                XLOG("%s texture %p stolen from tile %d, %d for %d, %d, drawCount was %llu (now %llu)",
+                     owner->isLayerTile() ? "LAYER" : "BASE",
+                     farthestTexture, previousOwner->x(), previousOwner->y(),
+                     owner->x(), owner->y(),
+                     oldestDrawCount, getDrawGLCount());
+            }
+
+            availableTexturePool->remove(availableTexturePool->find(farthestTexture));
+            return farthestTexture;
+        }
+    } else {
+        if (owner->isLayerTile()) {
+            // couldn't find a tile for a layer, layers shouldn't request redraw
+            // TODO: once we do layer prefetching, don't set this for those
+            // tiles
+            m_layerTexturesRemain = false;
+        }
+    }
+
+    XLOG("Couldn't find an available texture for %s tile %x (%d, %d) out of %d available",
+          owner->isLayerTile() ? "LAYER" : "BASE",
+          owner, owner->x(), owner->y(), max);
+#ifdef DEBUG
+    printTextures();
+#endif // DEBUG
+    return 0;
+}
+
+int TilesManager::maxTextureCount()
+{
+    android::Mutex::Autolock lock(m_texturesLock);
+    return m_maxTextureCount;
+}
+
+int TilesManager::maxLayerTextureCount()
+{
+    android::Mutex::Autolock lock(m_texturesLock);
+    return m_maxLayerTextureCount;
+}
+
+void TilesManager::setMaxTextureCount(int max)
+{
+    XLOG("setMaxTextureCount: %d (current: %d, total:%d)",
+         max, m_maxTextureCount, MAX_TEXTURE_ALLOCATION);
+    if (m_maxTextureCount == MAX_TEXTURE_ALLOCATION ||
+         max <= m_maxTextureCount)
+        return;
+
+    android::Mutex::Autolock lock(m_texturesLock);
+
+    if (max < MAX_TEXTURE_ALLOCATION)
+        m_maxTextureCount = max;
+    else
+        m_maxTextureCount = MAX_TEXTURE_ALLOCATION;
+
+    allocateTiles();
+}
+
+void TilesManager::setMaxLayerTextureCount(int max)
+{
+    XLOG("setMaxLayerTextureCount: %d (current: %d, total:%d)",
+         max, m_maxLayerTextureCount, MAX_TEXTURE_ALLOCATION);
+    if (!max && m_hasLayerTextures) {
+        double secondsSinceLayersUsed = WTF::currentTime() - m_lastTimeLayersUsed;
+        if (secondsSinceLayersUsed > LAYER_TEXTURES_DESTROY_TIMEOUT) {
+            unsigned long long sparedDrawCount = ~0; // by default, spare no textures
+            deallocateTexturesVector(sparedDrawCount, m_tilesTextures);
+            m_hasLayerTextures = false;
+        }
+        return;
+    }
+    m_lastTimeLayersUsed = WTF::currentTime();
+    if (m_maxLayerTextureCount == MAX_TEXTURE_ALLOCATION ||
+         max <= m_maxLayerTextureCount)
+        return;
+
+    android::Mutex::Autolock lock(m_texturesLock);
+
+    if (max < MAX_TEXTURE_ALLOCATION)
+        m_maxLayerTextureCount = max;
+    else
+        m_maxLayerTextureCount = MAX_TEXTURE_ALLOCATION;
+
+    allocateTiles();
+    m_hasLayerTextures = true;
+}
+
+float TilesManager::tileWidth()
+{
+    return TILE_WIDTH;
+}
+
+float TilesManager::tileHeight()
+{
+    return TILE_HEIGHT;
+}
+
+float TilesManager::layerTileWidth()
+{
+    return LAYER_TILE_WIDTH;
+}
+
+float TilesManager::layerTileHeight()
+{
+    return LAYER_TILE_HEIGHT;
+}
+
+void TilesManager::paintedSurfacesCleanup(GLWebViewState* state)
+{
+    // PaintedSurfaces are created by LayerAndroid with a refcount of 1,
+    // and just transferred to new (corresponding) layers when a new layer tree
+    // is received.
+    // PaintedSurface also keep a reference on the Layer it currently has, so
+    // when we unref the tree of layer, those layers with a PaintedSurface will
+    // still be around if we do nothing.
+    // Here, if the surface does not have any associated layer, it means that we
+    // received a new layer tree without a corresponding layer (i.e. a layer
+    // using a texture has been removed by webkit).
+    // In that case, we remove the PaintedSurface from our list, and unref it.
+    // If the surface does have a layer, but the GLWebViewState associated to
+    // that layer is different from the one passed in parameter, it means we can
+    // also remove the surface (and we also remove/unref any layer that surface
+    // has). We do this when we deallocate GLWebViewState (i.e. the webview has
+    // been destroyed) and also when we switch to a page without
+    // composited layers.
+
+    WTF::Vector<PaintedSurface*> collect;
+    for (unsigned int i = 0; i < m_paintedSurfaces.size(); i++) {
+        PaintedSurface* surface = m_paintedSurfaces[i];
+
+        Layer* drawing = surface->drawingLayer();
+        Layer* painting = surface->paintingLayer();
+
+        XLOG("considering PS %p, drawing %p, painting %p", surface, drawing, painting);
+
+        bool drawingMatchesState = state && drawing && (drawing->state() == state);
+        bool paintingMatchesState = state && painting && (painting->state() == state);
+
+        if ((!painting && !drawing) || drawingMatchesState || paintingMatchesState) {
+            XLOG("trying to remove PS %p, painting %p, drawing %p, DMS %d, PMS %d",
+                 surface, painting, drawing, drawingMatchesState, paintingMatchesState);
+            collect.append(surface);
+        }
+    }
+    for (unsigned int i = 0; i < collect.size(); i++) {
+        PaintedSurface* surface = collect[i];
+        m_paintedSurfaces.remove(m_paintedSurfaces.find(surface));
+        SkSafeUnref(surface);
+    }
+}
+
+void TilesManager::unregisterGLWebViewState(GLWebViewState* state)
+{
+    // Discard the whole queue b/c we lost GL context already.
+    // Note the real updateTexImage will still wait for the next draw.
+    transferQueue()->discardQueue();
+}
+
+TilesManager* TilesManager::instance()
+{
+    if (!gInstance) {
+        gInstance = new TilesManager();
+        XLOG("instance(), new gInstance is %x", gInstance);
+    }
+    return gInstance;
+}
+
+TilesManager* TilesManager::gInstance = 0;
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesManager.h b/Source/WebCore/platform/graphics/android/TilesManager.h
similarity index 60%
rename from Source/WebCore/platform/graphics/android/rendering/TilesManager.h
rename to Source/WebCore/platform/graphics/android/TilesManager.h
index f0d2eac..9493855 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TilesManager.h
+++ b/Source/WebCore/platform/graphics/android/TilesManager.h
@@ -28,39 +28,50 @@
 
 #if USE(ACCELERATED_COMPOSITING)
 
+#include "BaseTile.h"
+#include "BaseTileTexture.h"
+#include "ImageTexture.h"
 #include "LayerAndroid.h"
 #include "ShaderProgram.h"
+#include "SkBitmapRef.h"
 #include "TexturesGenerator.h"
+#include "TiledPage.h"
 #include "TilesProfiler.h"
+#include "TilesTracker.h"
+#include "TransferQueue.h"
 #include "VideoLayerManager.h"
 #include <utils/threads.h>
 #include <wtf/HashMap.h>
 
 namespace WebCore {
 
-class OperationFilter;
-class Tile;
-class TileTexture;
-class TransferQueue;
+class PaintedSurface;
 
 class TilesManager {
 public:
     // May only be called from the UI thread
     static TilesManager* instance();
+    static GLint getMaxTextureSize();
+    static int getMaxTextureAllocation();
 
     static bool hardwareAccelerationEnabled()
     {
         return gInstance != 0;
     }
 
-    void removeOperationsForFilter(OperationFilter* filter)
+    void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning = false)
     {
-        m_pixmapsGenerationThread->removeOperationsForFilter(filter);
+        m_pixmapsGenerationThread->removeOperationsForFilter(filter, waitForRunning);
     }
 
-    bool tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter)
+    void removeOperationsForPage(TiledPage* page)
     {
-        return m_pixmapsGenerationThread->tryUpdateOperationWithPainter(tile, painter);
+        m_pixmapsGenerationThread->removeOperationsForPage(page);
+    }
+
+    void removePaintOperationsForPage(TiledPage* page, bool waitForCompletion)
+    {
+        m_pixmapsGenerationThread->removePaintOperationsForPage(page, waitForCompletion);
     }
 
     void scheduleOperation(QueuedOperation* operation)
@@ -68,39 +79,40 @@
         m_pixmapsGenerationThread->scheduleOperation(operation);
     }
 
+    void swapLayersTextures(LayerAndroid* newTree, LayerAndroid* oldTree);
+    void addPaintedSurface(PaintedSurface* surface);
+
     ShaderProgram* shader() { return &m_shader; }
-    TransferQueue* transferQueue();
+    TransferQueue* transferQueue() { return &m_queue; }
     VideoLayerManager* videoLayerManager() { return &m_videoLayerManager; }
 
-    void updateTilesIfContextVerified();
-    void cleanupGLResources();
-
+    void gatherLayerTextures();
     void gatherTextures();
     bool layerTexturesRemain() { return m_layerTexturesRemain; }
     void gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextures,
                                int* nbLayerTextures, int* nbAllocatedLayerTextures);
 
-    TileTexture* getAvailableTexture(Tile* owner);
-
-    void dirtyAllTiles();
+    BaseTileTexture* getAvailableTexture(BaseTile* owner);
 
     void printTextures();
 
-    // m_highEndGfx is written/read only on UI thread, no need for a lock.
-    void setHighEndGfx(bool highEnd);
-    bool highEndGfx();
+    void resetTextureUsage(TiledPage* page);
 
-    int currentTextureCount();
-    int currentLayerTextureCount();
-    void setCurrentTextureCount(int newTextureCount);
-    void setCurrentLayerTextureCount(int newTextureCount);
-    static int tileWidth();
-    static int tileHeight();
+    int maxTextureCount();
+    int maxLayerTextureCount();
+    void setMaxTextureCount(int max);
+    void setMaxLayerTextureCount(int max);
+    static float tileWidth();
+    static float tileHeight();
+    static float layerTileWidth();
+    static float layerTileHeight();
+    void paintedSurfacesCleanup(GLWebViewState* state = 0);
+    void unregisterGLWebViewState(GLWebViewState* state);
 
-    void allocateTextures();
+    void allocateTiles();
 
-    // remove all tiles from textures (and optionally deallocate gl memory)
-    void discardTextures(bool allTextures, bool glTextures);
+    // Called when webview is hidden to discard graphics memory
+    void deallocateTextures(bool allTextures);
 
     bool getShowVisualIndicator()
     {
@@ -112,21 +124,43 @@
         m_showVisualIndicator = showVisualIndicator;
     }
 
+    SharedTextureMode getSharedTextureMode()
+    {
+        return SurfaceTextureMode;
+    }
+
     TilesProfiler* getProfiler()
     {
         return &m_profiler;
     }
 
+    TilesTracker* getTilesTracker()
+    {
+        return &m_tilesTracker;
+    }
+
     bool invertedScreen()
     {
         return m_invertedScreen;
     }
 
+    bool invertedScreenSwitch()
+    {
+        return m_invertedScreenSwitch;
+    }
+
     void setInvertedScreen(bool invert)
     {
+        if (m_invertedScreen != invert)
+            m_invertedScreenSwitch = true;
         m_invertedScreen = invert;
     }
 
+    void setInvertedScreenSwitch(bool invertedSwitch)
+    {
+        m_invertedScreenSwitch = invertedSwitch;
+    }
+
     void setInvertedScreenContrast(float contrast)
     {
         m_shader.setContrast(contrast);
@@ -142,19 +176,6 @@
         return m_useMinimalMemory;
     }
 
-    void setUseDoubleBuffering(bool useDoubleBuffering)
-    {
-        m_useDoubleBuffering = useDoubleBuffering;
-    }
-    bool useDoubleBuffering() { return m_useDoubleBuffering; }
-
-
-    unsigned int incWebkitContentUpdates() { return m_webkitContentUpdates++; }
-
-    void incContentUpdates() { m_contentUpdates++; }
-    unsigned int getContentUpdates() { return m_contentUpdates; }
-    void clearContentUpdates() { m_contentUpdates = 0; }
-
     void incDrawGLCount()
     {
         m_drawGLCount++;
@@ -165,39 +186,37 @@
         return m_drawGLCount;
     }
 
+    int getPaintedSurfaceCount()
+    {
+        return m_paintedSurfaces.size();
+    }
+
 private:
     TilesManager();
 
-    void discardTexturesVector(unsigned long long sparedDrawCount,
-                               WTF::Vector<TileTexture*>& textures,
-                               bool deallocateGLTextures);
-    void dirtyTexturesVector(WTF::Vector<TileTexture*>& textures);
-    void markAllGLTexturesZero();
-    int getMaxTextureAllocation();
+    void deallocateTexturesVector(unsigned long long sparedDrawCount,
+                                  WTF::Vector<BaseTileTexture*>& textures);
 
-    WTF::Vector<TileTexture*> m_textures;
-    WTF::Vector<TileTexture*> m_availableTextures;
+    Vector<BaseTileTexture*> m_textures;
+    Vector<BaseTileTexture*> m_availableTextures;
 
-    WTF::Vector<TileTexture*> m_tilesTextures;
-    WTF::Vector<TileTexture*> m_availableTilesTextures;
+    Vector<BaseTileTexture*> m_tilesTextures;
+    Vector<BaseTileTexture*> m_availableTilesTextures;
     bool m_layerTexturesRemain;
 
-    bool m_highEndGfx;
-    int m_currentTextureCount;
-    int m_currentLayerTextureCount;
-    int m_maxTextureAllocation;
+    Vector<PaintedSurface*> m_paintedSurfaces;
+
+    int m_maxTextureCount;
+    int m_maxLayerTextureCount;
 
     bool m_generatorReady;
 
     bool m_showVisualIndicator;
     bool m_invertedScreen;
+    bool m_invertedScreenSwitch;
 
     bool m_useMinimalMemory;
 
-    bool m_useDoubleBuffering;
-    unsigned int m_contentUpdates; // nr of successful tiled paints
-    unsigned int m_webkitContentUpdates; // nr of paints from webkit
-
     sp<TexturesGenerator> m_pixmapsGenerationThread;
 
     android::Mutex m_texturesLock;
@@ -205,16 +224,15 @@
     static TilesManager* gInstance;
 
     ShaderProgram m_shader;
-    TransferQueue* m_queue;
+    TransferQueue m_queue;
 
     VideoLayerManager m_videoLayerManager;
 
     TilesProfiler m_profiler;
+    TilesTracker m_tilesTracker;
     unsigned long long m_drawGLCount;
     double m_lastTimeLayersUsed;
     bool m_hasLayerTextures;
-
-    EGLContext m_eglContext;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesProfiler.cpp b/Source/WebCore/platform/graphics/android/TilesProfiler.cpp
similarity index 73%
rename from Source/WebCore/platform/graphics/android/rendering/TilesProfiler.cpp
rename to Source/WebCore/platform/graphics/android/TilesProfiler.cpp
index 4f0c6b5..0271ee3 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TilesProfiler.cpp
+++ b/Source/WebCore/platform/graphics/android/TilesProfiler.cpp
@@ -23,19 +23,29 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#define LOG_TAG "TilesProfiler"
-#define LOG_NDEBUG 1
-
 #include "config.h"
 #include "TilesProfiler.h"
 
 #if USE(ACCELERATED_COMPOSITING)
 
-#include "AndroidLog.h"
-#include "Tile.h"
 #include "TilesManager.h"
 #include <wtf/CurrentTime.h>
 
+#ifdef DEBUG
+
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TilesProfiler", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
 // Hard limit on amount of frames (and thus memory) profiling can take
 #define MAX_PROF_FRAMES 400
 #define INVAL_CODE -2
@@ -53,19 +63,19 @@
     m_badTiles = 0;
     m_records.clear();
     m_time = currentTimeMS();
-    ALOGV("initializing tileprofiling");
+    XLOG("initializing tileprofiling");
 }
 
 float TilesProfiler::stop()
 {
     m_enabled = false;
-    ALOGV("completed tile profiling, observed %d frames", m_records.size());
+    XLOG("completed tile profiling, observed %d frames", m_records.size());
     return (1.0 * m_goodTiles) / (m_goodTiles + m_badTiles);
 }
 
 void TilesProfiler::clear()
 {
-    ALOGV("clearing tile profiling of its %d frames", m_records.size());
+    XLOG("clearing tile profiling of its %d frames", m_records.size());
     m_records.clear();
 }
 
@@ -80,8 +90,8 @@
 
 #ifdef DEBUG
     if (m_records.size() != 0) {
-        ALOGD("completed tile profiling frame, observed %d tiles. %f ms since last",
-              m_records[0].size(), timeDelta);
+        XLOG("completed tile profiling frame, observed %d tiles. %f ms since last",
+             m_records[0].size(), timeDelta);
     }
 #endif // DEBUG
 
@@ -93,14 +103,14 @@
                                 scale, true, (int)(timeDelta * 1000)));
 }
 
-void TilesProfiler::nextTile(Tile* tile, float scale, bool inView)
+void TilesProfiler::nextTile(BaseTile& tile, float scale, bool inView)
 {
     if (!m_enabled || (m_records.size() > MAX_PROF_FRAMES) || (m_records.size() == 0))
         return;
 
-    bool isReady = tile->isTileReady();
-    int left = tile->x() * TilesManager::tileWidth();
-    int top = tile->y() * TilesManager::tileWidth();
+    bool isReady = tile.isTileReady();
+    int left = tile.x() * TilesManager::tileWidth();
+    int top = tile.y() * TilesManager::tileWidth();
     int right = left + TilesManager::tileWidth();
     int bottom = top + TilesManager::tileWidth();
 
@@ -112,20 +122,20 @@
     }
     m_records.last().append(TileProfileRecord(
                                 left, top, right, bottom,
-                                scale, isReady, (int)tile->drawCount()));
-    ALOGV("adding tile %d %d %d %d, scale %f", left, top, right, bottom, scale);
+                                scale, isReady, (int)tile.drawCount()));
+    XLOG("adding tile %d %d %d %d, scale %f", left, top, right, bottom, scale);
 }
 
-void TilesProfiler::nextInval(const SkIRect& rect, float scale)
+void TilesProfiler::nextInval(const IntRect& rect, float scale)
 {
     if (!m_enabled || (m_records.size() > MAX_PROF_FRAMES) || (m_records.size() == 0))
         return;
 
     m_records.last().append(TileProfileRecord(
                                 rect.x(), rect.y(),
-                                rect.right(), rect.bottom(), scale, false, INVAL_CODE));
-    ALOGV("adding inval region %d %d %d %d, scale %f", rect.x(), rect.y(),
-          rect.right(), rect.bottom(), scale);
+                                rect.maxX(), rect.maxY(), scale, false, INVAL_CODE));
+    XLOG("adding inval region %d %d %d %d, scale %f", rect.x(), rect.y(),
+         rect.maxX(), rect.maxY(), scale);
 }
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesProfiler.h b/Source/WebCore/platform/graphics/android/TilesProfiler.h
similarity index 90%
rename from Source/WebCore/platform/graphics/android/rendering/TilesProfiler.h
rename to Source/WebCore/platform/graphics/android/TilesProfiler.h
index b39ae2f..286d350 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TilesProfiler.h
+++ b/Source/WebCore/platform/graphics/android/TilesProfiler.h
@@ -28,14 +28,12 @@
 
 #if USE(ACCELERATED_COMPOSITING)
 
+#include "BaseTile.h"
 #include "IntRect.h"
-#include "SkRect.h"
-#include <wtf/Vector.h>
+#include "Vector.h"
 
 namespace WebCore {
 
-class Tile;
-
 struct TileProfileRecord {
     TileProfileRecord(int left, int top, int right, int bottom, float scale, int isReady, int level) {
         this->left = left;
@@ -60,8 +58,8 @@
     float stop();
     void clear();
     void nextFrame(int left, int top, int right, int bottom, float scale);
-    void nextTile(Tile* tile, float scale, bool inView);
-    void nextInval(const SkIRect& rect, float scale);
+    void nextTile(BaseTile& tile, float scale, bool inView);
+    void nextInval(const IntRect& rect, float scale);
     int numFrames() {
         return m_records.size();
     };
@@ -74,13 +72,11 @@
         return &m_records[frame][tile];
     }
 
-    bool enabled() { return m_enabled; }
-
 private:
     bool m_enabled;
     unsigned int m_goodTiles;
     unsigned int m_badTiles;
-    WTF::Vector<WTF::Vector<TileProfileRecord> > m_records;
+    Vector<Vector<TileProfileRecord> > m_records;
     double m_time;
 };
 
diff --git a/Source/WebCore/platform/graphics/android/TilesTracker.h b/Source/WebCore/platform/graphics/android/TilesTracker.h
new file mode 100644
index 0000000..202d072
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/TilesTracker.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TilesTracker_h
+#define TilesTracker_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TilesTracker", __VA_ARGS__)
+
+namespace WebCore {
+
+class TilesTracker {
+public:
+    TilesTracker() {
+        clear();
+    }
+
+    void track(bool ready, bool haveTexture) {
+        m_nbTextures++;
+        if (ready)
+            m_nbTexturesReady++;
+        else
+            m_nbTexturesNotReady++;
+        if (haveTexture)
+            m_nbTexturesUsed++;
+    }
+
+    void clear() {
+        m_nbLayers = 0;
+        m_nbVisibleLayers = 0;
+        m_nbTextures = 0;
+        m_nbTexturesReady = 0;
+        m_nbTexturesNotReady = 0;
+        m_nbTexturesUsed = 0;
+    }
+
+    void trackLayer() { m_nbLayers++; }
+    void trackVisibleLayer() { m_nbVisibleLayers++; }
+
+    void showTrackTextures() {
+        XLOG("We had %d/%d layers needing %d textures, we had %d, %d were ready, %d were not",
+              m_nbLayers, m_nbVisibleLayers, m_nbTextures, m_nbTexturesUsed, m_nbTexturesReady, m_nbTexturesNotReady);
+    }
+
+private:
+    int m_nbLayers;
+    int m_nbVisibleLayers;
+    int m_nbTextures;
+    int m_nbTexturesReady;
+    int m_nbTexturesNotReady;
+    int m_nbTexturesUsed;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+#endif // TilesTracker_h
diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp
new file mode 100644
index 0000000..b20ec7a
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/TransferQueue.cpp
@@ -0,0 +1,572 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "TransferQueue.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "BaseTile.h"
+#include "PaintedSurface.h"
+#include <android/native_window.h>
+#include <gui/SurfaceTexture.h>
+#include <gui/SurfaceTextureClient.h>
+
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "TransferQueue", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TransferQueue", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+#define ST_BUFFER_NUMBER 6
+
+// Set this to 1 if we would like to take the new GpuUpload approach which
+// relied on the glCopyTexSubImage2D instead of a glDraw call
+#define GPU_UPLOAD_WITHOUT_DRAW 1
+
+namespace WebCore {
+
+TransferQueue::TransferQueue()
+    : m_eglSurface(EGL_NO_SURFACE)
+    , m_transferQueueIndex(0)
+    , m_fboID(0)
+    , m_sharedSurfaceTextureId(0)
+    , m_hasGLContext(true)
+    , m_interruptedByRemovingOp(false)
+    , m_currentDisplay(EGL_NO_DISPLAY)
+    , m_currentUploadType(DEFAULT_UPLOAD_TYPE)
+{
+    memset(&m_GLStateBeforeBlit, 0, sizeof(m_GLStateBeforeBlit));
+
+    m_emptyItemCount = ST_BUFFER_NUMBER;
+
+    m_transferQueue = new TileTransferData[ST_BUFFER_NUMBER];
+}
+
+TransferQueue::~TransferQueue()
+{
+    glDeleteFramebuffers(1, &m_fboID);
+    m_fboID = 0;
+    glDeleteTextures(1, &m_sharedSurfaceTextureId);
+    m_sharedSurfaceTextureId = 0;
+
+    delete[] m_transferQueue;
+}
+
+void TransferQueue::initSharedSurfaceTextures(int width, int height)
+{
+    if (!m_sharedSurfaceTextureId) {
+        glGenTextures(1, &m_sharedSurfaceTextureId);
+        m_sharedSurfaceTexture =
+#if GPU_UPLOAD_WITHOUT_DRAW
+            new android::SurfaceTexture(m_sharedSurfaceTextureId, true, GL_TEXTURE_2D);
+#else
+            new android::SurfaceTexture(m_sharedSurfaceTextureId);
+#endif
+        m_ANW = new android::SurfaceTextureClient(m_sharedSurfaceTexture);
+        m_sharedSurfaceTexture->setSynchronousMode(true);
+        m_sharedSurfaceTexture->setBufferCount(ST_BUFFER_NUMBER+1);
+
+        int result = native_window_set_buffers_geometry(m_ANW.get(),
+                width, height, HAL_PIXEL_FORMAT_RGBA_8888);
+        GLUtils::checkSurfaceTextureError("native_window_set_buffers_geometry", result);
+        result = native_window_set_usage(m_ANW.get(),
+                GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+        GLUtils::checkSurfaceTextureError("native_window_set_usage", result);
+    }
+
+    if (!m_fboID)
+        glGenFramebuffers(1, &m_fboID);
+}
+
+// When bliting, if the item from the transfer queue is mismatching b/t the
+// BaseTile and the content, then the item is considered as obsolete, and
+// the content is discarded.
+bool TransferQueue::checkObsolete(int index)
+{
+    BaseTile* baseTilePtr = m_transferQueue[index].savedBaseTilePtr;
+    if (!baseTilePtr) {
+        XLOG("Invalid savedBaseTilePtr , such that the tile is obsolete");
+        return true;
+    }
+
+    BaseTileTexture* baseTileTexture = baseTilePtr->backTexture();
+    if (!baseTileTexture) {
+        XLOG("Invalid baseTileTexture , such that the tile is obsolete");
+        return true;
+    }
+
+    const TextureTileInfo* tileInfo = &m_transferQueue[index].tileInfo;
+
+    if (tileInfo->m_x != baseTilePtr->x()
+        || tileInfo->m_y != baseTilePtr->y()
+        || tileInfo->m_scale != baseTilePtr->scale()
+        || tileInfo->m_painter != baseTilePtr->painter()) {
+        XLOG("Mismatching x, y, scale or painter , such that the tile is obsolete");
+        return true;
+    }
+
+    return false;
+}
+
+void TransferQueue::blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex,
+                                      GLuint srcTexId, GLenum srcTexTarget,
+                                      int index)
+{
+#if GPU_UPLOAD_WITHOUT_DRAW
+    glBindFramebuffer(GL_FRAMEBUFFER, fboID);
+    glFramebufferTexture2D(GL_FRAMEBUFFER,
+                           GL_COLOR_ATTACHMENT0,
+                           GL_TEXTURE_2D,
+                           srcTexId,
+                           0);
+    glBindTexture(GL_TEXTURE_2D, destTex->m_ownTextureId);
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0,
+                        destTex->getSize().width(),
+                        destTex->getSize().height());
+#else
+    // Then set up the FBO and copy the SurfTex content in.
+    glBindFramebuffer(GL_FRAMEBUFFER, fboID);
+    glFramebufferTexture2D(GL_FRAMEBUFFER,
+                           GL_COLOR_ATTACHMENT0,
+                           GL_TEXTURE_2D,
+                           destTex->m_ownTextureId,
+                           0);
+    setGLStateForCopy(destTex->getSize().width(),
+                      destTex->getSize().height());
+    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+    if (status != GL_FRAMEBUFFER_COMPLETE) {
+        XLOG("Error: glCheckFramebufferStatus failed");
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+        return;
+    }
+
+    // Use empty rect to set up the special matrix to draw.
+    SkRect rect  = SkRect::MakeEmpty();
+    TilesManager::instance()->shader()->drawQuad(rect, srcTexId, 1.0,
+                       srcTexTarget, GL_NEAREST);
+
+    // To workaround a sync issue on some platforms, we should insert the sync
+    // here while in the current FBO.
+    // This will essentially kick off the GPU command buffer, and the Tex Gen
+    // thread will then have to wait for this buffer to finish before writing
+    // into the same memory.
+    EGLDisplay dpy = eglGetCurrentDisplay();
+    if (m_currentDisplay != dpy)
+        m_currentDisplay = dpy;
+    if (m_currentDisplay != EGL_NO_DISPLAY) {
+        if (m_transferQueue[index].m_syncKHR != EGL_NO_SYNC_KHR)
+            eglDestroySyncKHR(m_currentDisplay, m_transferQueue[index].m_syncKHR);
+        m_transferQueue[index].m_syncKHR = eglCreateSyncKHR(m_currentDisplay,
+                                                            EGL_SYNC_FENCE_KHR,
+                                                            0);
+    }
+    GLUtils::checkEglError("CreateSyncKHR");
+#endif
+}
+
+void TransferQueue::interruptTransferQueue(bool interrupt)
+{
+    m_transferQueueItemLocks.lock();
+    m_interruptedByRemovingOp = interrupt;
+    if (m_interruptedByRemovingOp)
+        m_transferQueueItemCond.signal();
+    m_transferQueueItemLocks.unlock();
+}
+
+// This function must be called inside the m_transferQueueItemLocks, for the
+// wait, m_interruptedByRemovingOp and getHasGLContext().
+// Only called by updateQueueWithBitmap() for now.
+bool TransferQueue::readyForUpdate()
+{
+    if (!getHasGLContext())
+        return false;
+    // Don't use a while loop since when the WebView tear down, the emptyCount
+    // will still be 0, and we bailed out b/c of GL context lost.
+    if (!m_emptyItemCount) {
+        if (m_interruptedByRemovingOp)
+            return false;
+        m_transferQueueItemCond.wait(m_transferQueueItemLocks);
+        if (m_interruptedByRemovingOp)
+            return false;
+    }
+
+    if (!getHasGLContext())
+        return false;
+
+    // Disable this wait until we figure out why this didn't work on some
+    // drivers b/5332112.
+#if 0
+    if (m_currentUploadType == GpuUpload
+        && m_currentDisplay != EGL_NO_DISPLAY) {
+        // Check the GPU fence
+        EGLSyncKHR syncKHR = m_transferQueue[getNextTransferQueueIndex()].m_syncKHR;
+        if (syncKHR != EGL_NO_SYNC_KHR)
+            eglClientWaitSyncKHR(m_currentDisplay,
+                                 syncKHR,
+                                 EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
+                                 EGL_FOREVER_KHR);
+    }
+    GLUtils::checkEglError("WaitSyncKHR");
+#endif
+
+    return true;
+}
+
+// Both getHasGLContext and setHasGLContext should be called within the lock.
+bool TransferQueue::getHasGLContext()
+{
+    return m_hasGLContext;
+}
+
+void TransferQueue::setHasGLContext(bool hasContext)
+{
+    m_hasGLContext = hasContext;
+}
+
+// Only called when WebView is destroyed or switching the uploadType.
+void TransferQueue::discardQueue()
+{
+    android::Mutex::Autolock lock(m_transferQueueItemLocks);
+
+    for (int i = 0 ; i < ST_BUFFER_NUMBER; i++)
+        if (m_transferQueue[i].status == pendingBlit)
+            m_transferQueue[i].status = pendingDiscard;
+
+    bool GLContextExisted = getHasGLContext();
+    // Unblock the Tex Gen thread first before Tile Page deletion.
+    // Otherwise, there will be a deadlock while removing operations.
+    setHasGLContext(false);
+
+    // Only signal once when GL context lost.
+    if (GLContextExisted)
+        m_transferQueueItemCond.signal();
+}
+
+// Call on UI thread to copy from the shared Surface Texture to the BaseTile's texture.
+void TransferQueue::updateDirtyBaseTiles()
+{
+    android::Mutex::Autolock lock(m_transferQueueItemLocks);
+
+    cleanupTransportQueue();
+    if (!getHasGLContext())
+        setHasGLContext(true);
+
+    // Start from the oldest item, we call the updateTexImage to retrive
+    // the texture and blit that into each BaseTile's texture.
+    const int nextItemIndex = getNextTransferQueueIndex();
+    int index = nextItemIndex;
+    bool usedFboForUpload = false;
+    for (int k = 0; k < ST_BUFFER_NUMBER ; k++) {
+        if (m_transferQueue[index].status == pendingBlit) {
+            bool obsoleteBaseTile = checkObsolete(index);
+            // Save the needed info, update the Surf Tex, clean up the item in
+            // the queue. Then either move on to next item or copy the content.
+            BaseTileTexture* destTexture = 0;
+            if (!obsoleteBaseTile)
+                destTexture = m_transferQueue[index].savedBaseTilePtr->backTexture();
+            if (m_transferQueue[index].uploadType == GpuUpload) {
+                status_t result = m_sharedSurfaceTexture->updateTexImage();
+                if (result != OK)
+                    XLOGC("unexpected error: updateTexImage return %d", result);
+            }
+            m_transferQueue[index].savedBaseTilePtr = 0;
+            m_transferQueue[index].status = emptyItem;
+            if (obsoleteBaseTile) {
+                XLOG("Warning: the texture is obsolete for this baseTile");
+                index = (index + 1) % ST_BUFFER_NUMBER;
+                continue;
+            }
+
+            // guarantee that we have a texture to blit into
+            destTexture->requireGLTexture();
+
+            if (m_transferQueue[index].uploadType == CpuUpload) {
+                // Here we just need to upload the bitmap content to the GL Texture
+                GLUtils::updateTextureWithBitmap(destTexture->m_ownTextureId, 0, 0,
+                                                 *m_transferQueue[index].bitmap);
+            } else {
+                if (!usedFboForUpload) {
+                    saveGLState();
+                    usedFboForUpload = true;
+                }
+                blitTileFromQueue(m_fboID, destTexture,
+                                  m_sharedSurfaceTextureId,
+                                  m_sharedSurfaceTexture->getCurrentTextureTarget(),
+                                  index);
+            }
+
+            // After the base tile copied into the GL texture, we need to
+            // update the texture's info such that at draw time, readyFor
+            // will find the latest texture's info
+            // We don't need a map any more, each texture contains its own
+            // texturesTileInfo.
+            destTexture->setOwnTextureTileInfoFromQueue(&m_transferQueue[index].tileInfo);
+
+            XLOG("Blit tile x, y %d %d with dest texture %p to destTexture->m_ownTextureId %d",
+                 m_transferQueue[index].tileInfo.m_x,
+                 m_transferQueue[index].tileInfo.m_y,
+                 destTexture,
+                 destTexture->m_ownTextureId);
+        }
+        index = (index + 1) % ST_BUFFER_NUMBER;
+    }
+
+    // Clean up FBO setup. Doing this for both CPU/GPU upload can make the
+    // dynamic switch possible. Moving this out from the loop can save some
+    // milli-seconds.
+    if (usedFboForUpload) {
+        glBindFramebuffer(GL_FRAMEBUFFER, 0); // rebind the standard FBO
+        restoreGLState();
+        GLUtils::checkGlError("updateDirtyBaseTiles");
+    }
+
+    m_emptyItemCount = ST_BUFFER_NUMBER;
+    m_transferQueueItemCond.signal();
+}
+
+void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo,
+                                          int x, int y, const SkBitmap& bitmap)
+{
+    if (!tryUpdateQueueWithBitmap(renderInfo, x, y, bitmap)) {
+        // failed placing bitmap in queue, discard tile's texture so it will be
+        // re-enqueued (and repainted)
+        BaseTile* tile = renderInfo->baseTile;
+        if (tile)
+            tile->backTextureTransferFail();
+    }
+}
+
+bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo,
+                                          int x, int y, const SkBitmap& bitmap)
+{
+    m_transferQueueItemLocks.lock();
+    bool ready = readyForUpdate();
+    TextureUploadType currentUploadType = m_currentUploadType;
+    m_transferQueueItemLocks.unlock();
+    if (!ready) {
+        XLOG("Quit bitmap update: not ready! for tile x y %d %d",
+             renderInfo->x, renderInfo->y);
+        return false;
+    }
+    if (currentUploadType == GpuUpload) {
+        // a) Dequeue the Surface Texture and write into the buffer
+        if (!m_ANW.get()) {
+            XLOG("ERROR: ANW is null");
+            return false;
+        }
+
+        ANativeWindow_Buffer buffer;
+        if (ANativeWindow_lock(m_ANW.get(), &buffer, 0))
+            return false;
+
+        uint8_t* img = (uint8_t*)buffer.bits;
+        int row, col;
+        int bpp = 4; // Now we only deal with RGBA8888 format.
+        int width = TilesManager::instance()->tileWidth();
+        int height = TilesManager::instance()->tileHeight();
+        if (!x && !y && bitmap.width() == width && bitmap.height() == height) {
+            bitmap.lockPixels();
+            uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels());
+            if (buffer.stride != bitmap.width())
+                // Copied line by line since we need to handle the offsets and stride.
+                for (row = 0 ; row < bitmap.height(); row ++) {
+                    uint8_t* dst = &(img[buffer.stride * row * bpp]);
+                    uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]);
+                    memcpy(dst, src, bpp * bitmap.width());
+                }
+            else
+                memcpy(img, bitmapOrigin, bpp * bitmap.width() * bitmap.height());
+
+            bitmap.unlockPixels();
+        } else {
+            // TODO: implement the partial invalidate here!
+            XLOG("ERROR: don't expect to get here yet before we support partial inval");
+        }
+
+        ANativeWindow_unlockAndPost(m_ANW.get());
+    }
+
+    m_transferQueueItemLocks.lock();
+    // b) After update the Surface Texture, now udpate the transfer queue info.
+    addItemInTransferQueue(renderInfo, currentUploadType, &bitmap);
+
+    m_transferQueueItemLocks.unlock();
+    XLOG("Bitmap updated x, y %d %d, baseTile %p",
+         renderInfo->x, renderInfo->y, renderInfo->baseTile);
+    return true;
+}
+
+// Note that there should be lock/unlock around this function call.
+// Currently only called by GLUtils::updateSharedSurfaceTextureWithBitmap.
+void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo,
+                                           TextureUploadType type,
+                                           const SkBitmap* bitmap)
+{
+    m_transferQueueIndex = (m_transferQueueIndex + 1) % ST_BUFFER_NUMBER;
+
+    int index = m_transferQueueIndex;
+    if (m_transferQueue[index].savedBaseTilePtr
+        || m_transferQueue[index].status != emptyItem) {
+        XLOG("ERROR update a tile which is dirty already @ index %d", index);
+    }
+
+    m_transferQueue[index].savedBaseTileTexturePtr = renderInfo->baseTile->backTexture();
+    m_transferQueue[index].savedBaseTilePtr = renderInfo->baseTile;
+    m_transferQueue[index].status = pendingBlit;
+    m_transferQueue[index].uploadType = type;
+    if (type == CpuUpload && bitmap) {
+        // Lazily create the bitmap
+        if (!m_transferQueue[index].bitmap) {
+            m_transferQueue[index].bitmap = new SkBitmap();
+            int w = bitmap->width();
+            int h = bitmap->height();
+            m_transferQueue[index].bitmap->setConfig(bitmap->config(), w, h);
+        }
+        bitmap->copyTo(m_transferQueue[index].bitmap, bitmap->config());
+    }
+
+    // Now fill the tileInfo.
+    TextureTileInfo* textureInfo = &m_transferQueue[index].tileInfo;
+
+    textureInfo->m_x = renderInfo->x;
+    textureInfo->m_y = renderInfo->y;
+    textureInfo->m_scale = renderInfo->scale;
+    textureInfo->m_painter = renderInfo->tilePainter;
+
+    textureInfo->m_picture = renderInfo->textureInfo->m_pictureCount;
+
+    m_emptyItemCount--;
+}
+
+void TransferQueue::setTextureUploadType(TextureUploadType type)
+{
+    if (m_currentUploadType == type)
+        return;
+
+    discardQueue();
+
+    android::Mutex::Autolock lock(m_transferQueueItemLocks);
+    m_currentUploadType = type;
+    XLOGC("Now we set the upload to %s", m_currentUploadType == GpuUpload ? "GpuUpload" : "CpuUpload");
+}
+
+// Note: this need to be called within th lock.
+// Only called by updateDirtyBaseTiles() for now
+void TransferQueue::cleanupTransportQueue()
+{
+    int index = getNextTransferQueueIndex();
+
+    for (int i = 0 ; i < ST_BUFFER_NUMBER; i++) {
+        if (m_transferQueue[index].status == pendingDiscard) {
+            // No matter what the current upload type is, as long as there has
+            // been a Surf Tex enqueue operation, this updateTexImage need to
+            // be called to keep things in sync.
+            if (m_transferQueue[index].uploadType == GpuUpload) {
+                status_t result = m_sharedSurfaceTexture->updateTexImage();
+                if (result != OK)
+                    XLOGC("unexpected error: updateTexImage return %d", result);
+            }
+
+            // since tiles in the queue may be from another webview, remove
+            // their textures so that they will be repainted / retransferred
+            BaseTile* tile = m_transferQueue[index].savedBaseTilePtr;
+            BaseTileTexture* texture = m_transferQueue[index].savedBaseTileTexturePtr;
+            if (tile && texture && texture->owner() == tile) {
+                // since tile destruction removes textures on the UI thread, the
+                // texture->owner ptr guarantees the tile is valid
+                tile->discardBackTexture();
+                XLOG("transfer queue discarded tile %p, removed texture", tile);
+            }
+
+            m_transferQueue[index].savedBaseTilePtr = 0;
+            m_transferQueue[index].savedBaseTileTexturePtr = 0;
+            m_transferQueue[index].status = emptyItem;
+        }
+        index = (index + 1) % ST_BUFFER_NUMBER;
+    }
+}
+
+void TransferQueue::saveGLState()
+{
+    glGetIntegerv(GL_VIEWPORT, m_GLStateBeforeBlit.viewport);
+    glGetBooleanv(GL_SCISSOR_TEST, m_GLStateBeforeBlit.scissor);
+    glGetBooleanv(GL_DEPTH_TEST, m_GLStateBeforeBlit.depth);
+#if DEBUG
+    glGetFloatv(GL_COLOR_CLEAR_VALUE, m_GLStateBeforeBlit.clearColor);
+#endif
+}
+
+void TransferQueue::setGLStateForCopy(int width, int height)
+{
+    // Need to match the texture size.
+    glViewport(0, 0, width, height);
+    glDisable(GL_SCISSOR_TEST);
+    glDisable(GL_DEPTH_TEST);
+    // Clear the content is only for debug purpose.
+#if DEBUG
+    glClearColor(0, 0, 0, 0);
+    glClear(GL_COLOR_BUFFER_BIT);
+#endif
+}
+
+void TransferQueue::restoreGLState()
+{
+    glViewport(m_GLStateBeforeBlit.viewport[0],
+               m_GLStateBeforeBlit.viewport[1],
+               m_GLStateBeforeBlit.viewport[2],
+               m_GLStateBeforeBlit.viewport[3]);
+
+    if (m_GLStateBeforeBlit.scissor[0])
+        glEnable(GL_SCISSOR_TEST);
+
+    if (m_GLStateBeforeBlit.depth[0])
+        glEnable(GL_DEPTH_TEST);
+#if DEBUG
+    glClearColor(m_GLStateBeforeBlit.clearColor[0],
+                 m_GLStateBeforeBlit.clearColor[1],
+                 m_GLStateBeforeBlit.clearColor[2],
+                 m_GLStateBeforeBlit.clearColor[3]);
+#endif
+}
+
+int TransferQueue::getNextTransferQueueIndex()
+{
+    return (m_transferQueueIndex + 1) % ST_BUFFER_NUMBER;
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING
diff --git a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h b/Source/WebCore/platform/graphics/android/TransferQueue.h
similarity index 76%
rename from Source/WebCore/platform/graphics/android/rendering/TransferQueue.h
rename to Source/WebCore/platform/graphics/android/TransferQueue.h
index c0835d7..63455de 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h
+++ b/Source/WebCore/platform/graphics/android/TransferQueue.h
@@ -28,20 +28,14 @@
 
 #if USE(ACCELERATED_COMPOSITING)
 
-#include "GLUtils.h"
+#include "BaseTile.h"
+#include "BaseTileTexture.h"
 #include "ShaderProgram.h"
-#include "SkBitmap.h"
-#include <utils/StrongPointer.h>
-#include <utils/threads.h>
+#include "TiledPage.h"
 
 namespace WebCore {
 
-class Tile;
-class TilePainter;
-class TileTexture;
-
 struct GLState {
-    GLint bufferId[1];
     GLint viewport[4];
     GLboolean scissor[1];
     GLboolean depth[1];
@@ -49,7 +43,7 @@
 };
 
 
-// While in the queue, the Tile can be re-used, the updated bitmap
+// While in the queue, the BaseTile can be re-used, the updated bitmap
 // can be discarded. In order to track this obsolete base tiles, we save
 // the Tile's Info to make the comparison.
 // At the time of base tile's dtor or webview destroy, we want to discard
@@ -75,11 +69,11 @@
 public:
     TileTransferData()
     : status(emptyItem)
-    , savedTilePtr(0)
-    , savedTilePainter(0)
-    , savedTileTexturePtr(0)
+    , savedBaseTilePtr(0)
+    , savedBaseTileTexturePtr(0)
     , uploadType(DEFAULT_UPLOAD_TYPE)
     , bitmap(0)
+    , m_syncKHR(EGL_NO_SYNC_KHR)
     {
     }
 
@@ -90,33 +84,42 @@
     }
 
     TransferItemStatus status;
-    Tile* savedTilePtr;
-    TilePainter* savedTilePainter; // Ref count the tilePainter to keep the tile alive.
-    TileTexture* savedTileTexturePtr;
+    BaseTile* savedBaseTilePtr;
+    BaseTileTexture* savedBaseTileTexturePtr;
+    TextureTileInfo tileInfo;
     TextureUploadType uploadType;
     // This is only useful in Cpu upload code path, so it will be dynamically
     // lazily allocated.
     SkBitmap* bitmap;
 
-    // Specific data to the pure color tiles' queue.
-    Color pureColor;
+    // Sync object for GPU fence, this is the only the info passed from UI
+    // thread to Tex Gen thread. The reason of having this is due to the
+    // missing sync mechanism on Surface Texture on some vendor. b/5122031.
+    // Bascially the idea is that when UI thread utilize one buffer from
+    // the surface texture, we'll need to kick off the GPU commands, and only
+    // when those particular commands finish, we could write into this buffer
+    // again in Tex Gen thread.
+    EGLSyncKHR m_syncKHR;
 };
 
 class TransferQueue {
 public:
-    TransferQueue(bool useMinimalMem);
+    TransferQueue();
     ~TransferQueue();
 
     // This will be called by the browser through nativeSetProperty
     void setTextureUploadType(TextureUploadType type);
-    void updateDirtyTiles();
 
-    void initGLResources(int width, int height);
+    void updateDirtyBaseTiles();
+
+    void initSharedSurfaceTextures(int width, int height);
 
     // insert the bitmap into the queue, mark the tile dirty if failing
-    void updateQueueWithBitmap(const TileRenderInfo* renderInfo,
+    void updateQueueWithBitmap(const TileRenderInfo* renderInfo, int x, int y,
                                const SkBitmap& bitmap);
 
+    void discardQueue();
+
     void addItemInTransferQueue(const TileRenderInfo* info,
                                 TextureUploadType type,
                                 const SkBitmap* bitmap);
@@ -124,31 +127,26 @@
     // The lock will be done when returning true.
     bool readyForUpdate();
 
+    void interruptTransferQueue(bool);
+
     void lockQueue() { m_transferQueueItemLocks.lock(); }
     void unlockQueue() { m_transferQueueItemLocks.unlock(); }
 
-    void addItemInPureColorQueue(const TileRenderInfo* renderInfo);
-
-    void cleanupGLResourcesAndQueue();
-
-    bool needsInit() { return !m_sharedSurfaceTextureId; }
-    void resetQueue();
     // This queue can be accessed from UI and TexGen thread, therefore, we need
     // a lock to protect its access
     TileTransferData* m_transferQueue;
 
-    android::sp<ANativeWindow> m_ANW;
+    sp<ANativeWindow> m_ANW;
 
     // EGL wrapper around m_ANW for use by the GaneshRenderer
     EGLSurface m_eglSurface;
 
 private:
     // return true if successfully inserted into queue
-    bool tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo,
+    bool tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, int x, int y,
                                   const SkBitmap& bitmap);
     bool getHasGLContext();
     void setHasGLContext(bool hasContext);
-    void emptyAndAbandonQueue();
 
     int getNextTransferQueueIndex();
 
@@ -158,24 +156,16 @@
     void restoreGLState();
 
     // Check the current transfer queue item is obsolete or not.
-    bool checkObsolete(const TileTransferData* data);
+    bool checkObsolete(int index);
 
-    void setPendingDiscard();
     // Before each draw call and the blit operation, clean up all the
     // pendingDiscard items.
-    void cleanupPendingDiscard();
-    void cleanupGLResources();
+    void cleanupTransportQueue();
 
-    void blitTileFromQueue(GLuint fboID, TileTexture* destTex,
+    void blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex,
                            GLuint srcTexId, GLenum srcTexTarget,
                            int index);
 
-    void clearItemInTranferQueue(int index);
-    void addItemCommon(const TileRenderInfo* renderInfo,
-                       TextureUploadType type, TileTransferData* data);
-
-    void updatePureColorTiles();
-    void clearPureColorQueue();
     // Note that the m_transferQueueIndex only changed in the TexGen thread
     // where we are going to move on to update the next item in the queue.
     int m_transferQueueIndex;
@@ -188,10 +178,12 @@
     bool m_hasGLContext;
 
     GLState m_GLStateBeforeBlit;
-    android::sp<android::SurfaceTexture> m_sharedSurfaceTexture;
+    sp<android::SurfaceTexture> m_sharedSurfaceTexture;
 
     int m_emptyItemCount;
 
+    bool m_interruptedByRemovingOp;
+
     // We are using wait/signal to handle our own queue sync.
     // First of all, if we don't have our own lock, then while WebView is
     // destroyed, the UI thread will wait for the Tex Gen to get out from
@@ -209,14 +201,6 @@
     // This should be GpuUpload for production, but for debug purpose or working
     // around driver/HW issue, we can set it to CpuUpload.
     TextureUploadType m_currentUploadType;
-
-    // The non-pure-color tile are 1 to 1 mapping with Surface Texture which is
-    // resource limited. To get better performance, it is better to separate
-    // the pure color tile into another queue.
-    WTF::Vector<TileTransferData> m_pureColorTileQueue;
-
-    // The number of items transfer queue can buffer up.
-    int m_transferQueueSize;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/TreeManager.cpp b/Source/WebCore/platform/graphics/android/TreeManager.cpp
new file mode 100644
index 0000000..b7eaacf
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/TreeManager.cpp
@@ -0,0 +1,331 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "TreeManager.h"
+
+#include "Layer.h"
+#include "BaseLayerAndroid.h"
+#include "ScrollableLayerAndroid.h"
+#include "TilesManager.h"
+
+#include <cutils/log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "TreeManager", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TreeManager", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+namespace WebCore {
+
+TreeManager::TreeManager()
+    : m_drawingTree(0)
+    , m_paintingTree(0)
+    , m_queuedTree(0)
+    , m_fastSwapMode(false)
+{
+}
+
+TreeManager::~TreeManager()
+{
+    clearTrees();
+}
+
+// the painting tree has finished painting:
+//   discard the drawing tree
+//   swap the painting tree in place of the drawing tree
+//   and start painting the queued tree
+void TreeManager::swap()
+{
+    // swap can't be called unless painting just finished
+    ASSERT(m_paintingTree);
+
+    android::Mutex::Autolock lock(m_paintSwapLock);
+
+    XLOG("SWAPPING, D %p, P %p, Q %p", m_drawingTree, m_paintingTree, m_queuedTree);
+
+    // if we have a drawing tree, discard it since the painting tree is done
+    if (m_drawingTree) {
+        XLOG("destroying drawing tree %p", m_drawingTree);
+        m_drawingTree->setIsDrawing(false);
+        SkSafeUnref(m_drawingTree);
+    }
+
+    // painting tree becomes the drawing tree
+    XLOG("drawing tree %p", m_paintingTree);
+    m_paintingTree->setIsDrawing(true);
+    if (m_paintingTree->countChildren())
+        static_cast<LayerAndroid*>(m_paintingTree->getChild(0))->initAnimations();
+
+    if (m_queuedTree) {
+        // start painting with the queued tree
+        XLOG("now painting tree %p", m_queuedTree);
+        m_queuedTree->setIsPainting(m_paintingTree);
+    }
+    m_drawingTree = m_paintingTree;
+    m_paintingTree = m_queuedTree;
+    m_queuedTree = 0;
+
+    TilesManager::instance()->paintedSurfacesCleanup();
+
+    XLOG("SWAPPING COMPLETE, D %p, P %p, Q %p", m_drawingTree, m_paintingTree, m_queuedTree);
+}
+
+// clear all of the content in the three trees held by the tree manager
+void TreeManager::clearTrees()
+{
+    // remove painted surfaces from any tree in this view, and set trees as no
+    // longer drawing, to clear ptrs from surfaces to layers
+    GLWebViewState* oldState = 0;
+    if (m_drawingTree) {
+        oldState = m_drawingTree->state();
+        m_drawingTree->setIsDrawing(false);
+    }
+    if (m_paintingTree) {
+        oldState = m_paintingTree->state();
+        m_paintingTree->setIsDrawing(false);
+    }
+
+    XLOG("TreeManager %p removing PS from state %p", this, oldState);
+    TilesManager::instance()->paintedSurfacesCleanup(oldState);
+
+    SkSafeUnref(m_drawingTree);
+    m_drawingTree = 0;
+    SkSafeUnref(m_paintingTree);
+    m_paintingTree = 0;
+    SkSafeUnref(m_queuedTree);
+    m_queuedTree = 0;
+}
+
+// a new layer tree has arrived, queue it if we're painting something already,
+// or start painting it if we aren't
+void TreeManager::updateWithTree(Layer* newTree, bool brandNew)
+{
+    XLOG("updateWithTree - %p, has children %d, has animations %d",
+         newTree, newTree && newTree->countChildren(),
+         newTree && newTree->countChildren()
+             ? static_cast<LayerAndroid*>(newTree->getChild(0))->hasAnimations() : 0);
+
+    // can't have a queued tree unless have a painting tree too
+    ASSERT(m_paintingTree || !m_queuedTree);
+
+    SkSafeRef(newTree);
+
+    android::Mutex::Autolock lock(m_paintSwapLock);
+
+    if (!newTree || brandNew) {
+        clearTrees();
+        if (brandNew) {
+            m_paintingTree = newTree;
+            m_paintingTree->setIsPainting(m_drawingTree);
+        }
+        return;
+    }
+
+    if (m_queuedTree || m_paintingTree) {
+        // currently painting, so defer this new tree
+        if (m_queuedTree) {
+            // have a queued tree, copy over invals so the regions are
+            // eventually repainted
+            m_queuedTree->mergeInvalsInto(newTree);
+
+            XLOG("DISCARDING tree - %p, has children %d, has animations %d",
+                 newTree, newTree && newTree->countChildren(),
+                 newTree && newTree->countChildren()
+                     ? static_cast<LayerAndroid*>(newTree->getChild(0))->hasAnimations() : 0);
+        }
+        SkSafeUnref(m_queuedTree);
+        m_queuedTree = newTree;
+        return;
+    }
+
+    // don't have painting tree, paint this one!
+    m_paintingTree = newTree;
+    m_paintingTree->setIsPainting(m_drawingTree);
+}
+
+void TreeManager::updateScrollableLayerInTree(Layer* tree, int layerId, int x, int y)
+{
+    LayerAndroid* layer;
+    if (tree && tree->countChildren()) {
+        layer = static_cast<LayerAndroid*>(tree->getChild(0))->findById(layerId);
+        if (layer && layer->contentIsScrollable())
+            static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y);
+    }
+}
+
+void TreeManager::updateScrollableLayer(int layerId, int x, int y)
+{
+    updateScrollableLayerInTree(m_queuedTree, layerId, x, y);
+    updateScrollableLayerInTree(m_paintingTree, layerId, x, y);
+    updateScrollableLayerInTree(m_drawingTree, layerId, x, y);
+}
+
+bool TreeManager::drawGL(double currentTime, IntRect& viewRect,
+                         SkRect& visibleRect, float scale,
+                         bool enterFastSwapMode, bool* treesSwappedPtr, bool* newTreeHasAnimPtr,
+                         TexturesResult* texturesResultPtr)
+{
+    m_fastSwapMode |= enterFastSwapMode;
+
+    XLOG("drawGL, D %p, P %p, Q %p, fastSwap %d",
+         m_drawingTree, m_paintingTree, m_queuedTree, m_fastSwapMode);
+
+    bool ret = false;
+    bool didTreeSwap = false;
+    if (m_paintingTree) {
+        XLOG("preparing painting tree %p", m_paintingTree);
+
+        LayerAndroid* laTree = 0;
+        if (m_paintingTree->countChildren()) {
+            laTree = static_cast<LayerAndroid*>(m_paintingTree->getChild(0));
+            ret |= laTree->evaluateAnimations(currentTime);
+        }
+
+        ret |= m_paintingTree->prepare(currentTime, viewRect,
+                                       visibleRect, scale);
+
+        if (laTree)
+            laTree->computeTexturesAmount(texturesResultPtr);
+
+        if (/*!m_fastSwapMode && */ m_paintingTree->isReady()) {
+            XLOG("have painting tree %p ready, swapping!", m_paintingTree);
+            didTreeSwap = true;
+            swap();
+            if (treesSwappedPtr)
+                *treesSwappedPtr = true;
+            if (laTree && newTreeHasAnimPtr)
+                *newTreeHasAnimPtr = laTree->hasAnimations();
+        }
+    } else if (m_drawingTree) {
+        XLOG("preparing drawing tree %p", m_drawingTree);
+        ret |= m_drawingTree->prepare(currentTime, viewRect,
+                                      visibleRect, scale);
+        if (m_drawingTree->countChildren()) {
+            LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0));
+            laTree->computeTexturesAmount(texturesResultPtr);
+        }
+    }
+
+
+    if (m_drawingTree) {
+        bool drawingReady = didTreeSwap || m_drawingTree->isReady();
+
+        if (didTreeSwap || m_fastSwapMode || (drawingReady && !m_paintingTree))
+            m_drawingTree->swapTiles();
+
+        if (drawingReady) {
+            // exit fast swap mode, as content is up to date
+            m_fastSwapMode = false;
+        } else {
+            // drawing isn't ready, must redraw
+            ret = true;
+        }
+
+        if (m_drawingTree->countChildren()) {
+            LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0));
+            ret |= laTree->evaluateAnimations(currentTime);
+        }
+        XLOG("drawing tree %p", m_drawingTree);
+        ret |= m_drawingTree->drawGL(viewRect, visibleRect, scale);
+    } else if (m_paintingTree && m_paintingTree->state()) {
+        // Dont have a drawing tree, draw white background
+        Color defaultBackground = Color::white;
+        m_paintingTree->state()->drawBackground(defaultBackground);
+    }
+
+    if (m_paintingTree) {
+        XLOG("still have painting tree %p", m_paintingTree);
+        return true;
+    }
+
+    return ret;
+}
+
+int TreeManager::getTotalPaintedSurfaceCount()
+{
+    return TilesManager::instance()->getPaintedSurfaceCount();
+}
+
+// draw for base tile - called on TextureGeneration thread
+void TreeManager::drawCanvas(SkCanvas* canvas, bool drawLayers)
+{
+    BaseLayerAndroid* paintingTree = 0;
+    m_paintSwapLock.lock();
+    if (m_paintingTree)
+        paintingTree = static_cast<BaseLayerAndroid*>(m_paintingTree);
+    else
+        paintingTree = static_cast<BaseLayerAndroid*>(m_drawingTree);
+    SkSafeRef(paintingTree);
+    m_paintSwapLock.unlock();
+
+    if (!paintingTree)
+        return;
+
+
+    paintingTree->drawCanvas(canvas);
+
+    if (drawLayers && paintingTree->countChildren()) {
+        // draw the layers onto the canvas as well
+        Layer* layers = paintingTree->getChild(0);
+        static_cast<LayerAndroid*>(layers)->drawCanvas(canvas);
+    }
+
+    SkSafeUnref(paintingTree);
+}
+
+int TreeManager::baseContentWidth()
+{
+    if (m_paintingTree) {
+        return static_cast<BaseLayerAndroid*>(m_paintingTree)->content()->width();
+    } else if (m_drawingTree) {
+        return static_cast<BaseLayerAndroid*>(m_drawingTree)->content()->width();
+    }
+    return 0;
+}
+
+int TreeManager::baseContentHeight()
+{
+    if (m_paintingTree) {
+        return static_cast<BaseLayerAndroid*>(m_paintingTree)->content()->height();
+    } else if (m_drawingTree) {
+        return static_cast<BaseLayerAndroid*>(m_drawingTree)->content()->height();
+    }
+    return 0;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/TreeManager.h b/Source/WebCore/platform/graphics/android/TreeManager.h
new file mode 100644
index 0000000..83d5300
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/TreeManager.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TreeManager_h
+#define TreeManager_h
+
+#include "TestExport.h"
+#include <utils/threads.h>
+#include "PerformanceMonitor.h"
+
+class Layer;
+class SkRect;
+class SkCanvas;
+
+namespace WebCore {
+
+class IntRect;
+class TexturesResult;
+
+class TEST_EXPORT TreeManager {
+public:
+    TreeManager();
+
+    ~TreeManager();
+
+    void updateWithTree(Layer* tree, bool brandNew);
+
+    void updateScrollableLayer(int layerId, int x, int y);
+
+    bool drawGL(double currentTime, IntRect& viewRect,
+                SkRect& visibleRect, float scale,
+                bool enterFastSwapMode, bool* treesSwappedPtr, bool* newTreeHasAnimPtr,
+                TexturesResult* texturesResultPtr);
+
+    void drawCanvas(SkCanvas* canvas, bool drawLayers);
+
+    // used in debugging (to avoid exporting TilesManager symbols)
+    static int getTotalPaintedSurfaceCount();
+
+    int baseContentWidth();
+    int baseContentHeight();
+
+private:
+    static void updateScrollableLayerInTree(Layer* tree, int layerId, int x, int y);
+
+    void swap();
+    void clearTrees();
+
+    android::Mutex m_paintSwapLock;
+
+    Layer* m_drawingTree;
+    Layer* m_paintingTree;
+    Layer* m_queuedTree;
+
+    bool m_fastSwapMode;
+    PerformanceMonitor m_perf;
+};
+
+} // namespace WebCore
+
+#endif //#define TreeManager_h
diff --git a/Source/WebCore/platform/graphics/android/fonts/VerticalTextMap.cpp b/Source/WebCore/platform/graphics/android/VerticalTextMap.cpp
similarity index 79%
rename from Source/WebCore/platform/graphics/android/fonts/VerticalTextMap.cpp
rename to Source/WebCore/platform/graphics/android/VerticalTextMap.cpp
index 42aa385..6e715e2 100644
--- a/Source/WebCore/platform/graphics/android/fonts/VerticalTextMap.cpp
+++ b/Source/WebCore/platform/graphics/android/VerticalTextMap.cpp
@@ -33,29 +33,28 @@
 #include <wtf/RefPtr.h>
 
 static const UChar vTextCnvTable[][2] = {
-    {0x0021, 0xfe15},  // exclamation mark
+    // TODO: uncomment mappings once we add glyphs for vertical forms.
+    // {0x0021, 0xfe15},  // exclamation mark
     {0x0028, 0xfe35},  // left paren
     {0x0029, 0xfe36},  // right paren
-    {0x002c, 0xfe10},  // comma
-    {0x002d, 0xfe32},  // hyphen
+    // {0x002c, 0xfe10},  // comma
     {0x003a, 0xfe30},  // colon
-    {0x003b, 0xfe14},  // semicolon
-    {0x003f, 0xfe16},  // question mark
-    {0x005b, 0xfe47},  // left square bracket
-    {0x005d, 0xfe48},  // right square bracket
+    {0x003b, 0x007c},  // hyphen
+    // {0x003f, 0xfe16},  // question mark
+    // {0x005b, 0xfe14},  // semicolon
+    {0x005d, 0xfe47},  // left square bracket
+    {0x005f, 0xfe48},  // right square bracket
     {0x007b, 0xfe37},  // left curly bracket
     {0x007d, 0xfe38},  // right curly bracket
     {0x007e, 0x007c},  // tilde to vertical line
-    {0x00ab, 0xfe3d},  // left pointing double angle quotation mark
-    {0x00bb, 0xfe3e},  // right pointing double angle quotation mark
-    {0x2010, 0xfe32},  // hyphen
     {0x2013, 0xfe32},  // en dash
     {0x2014, 0xfe31},  // em dash
     {0x2015, 0xfe31},  // horizontal bar
     {0x2025, 0xfe30},  // two dot leader
-    {0x2026, 0xfe19},  // three dot leader
-    {0x3001, 0xfe11},  // Ideographic comma
-    {0x3002, 0xfe12},  // Ideographic full stop
+    // TODO: change the mapping 0x2026 -> 0xFE19 once Android has the glyph for 0xFE19.
+    {0x2026, 0xfe30},  // three dot leader
+    // {0x3001, 0xfe11},  // Ideographic comma
+    // {0x3002, 0xfe12},  // Ideographic full stop
     {0x3008, 0xfe3f},  // left angle bracket
     {0x3009, 0xfe40},  // right angle bracket
     {0x300a, 0xfe3d},  // left double angle bracket
@@ -68,21 +67,19 @@
     {0x3011, 0xfe3c},  // right black lenticular bracket
     {0x3014, 0xfe39},  // left black lenticular bracket
     {0x3015, 0xfe3a},  // right tortise shell bracket
-    {0x3016, 0xfe17},  // left white lenticular bracket
-    {0x3017, 0xfe18},  // right white lenticular bracket
+    // {0x3016, 0xfe17},  // left white lenticular bracket
+    // {0x3017, 0xfe18},  // right white lenticular bracket
+    // {0x3019, 0xfe19},  // horizontal ellipses
     {0x30fc, 0x3021},  // prolonged sound
     {0xfe4f, 0xfe34},  // wavy low line
     {0xff08, 0xfe35},  // full width left paren
     {0xff09, 0xfe36},  // full width right paren
-    {0xff0c, 0xfe10},  // full width comma
     {0xff3b, 0xfe47},  // full width left square bracket
     {0xff3d, 0xfe48},  // full width right square bracket
     {0xff5b, 0xfe37},  // full width left curly bracket
-    {0xff5c, 0xfe31},  // fullwidth vertical line
     {0xff5d, 0xfe38},  // full width right curly bracket
-    {0xff5e, 0x007c},  // tilde to vertical line
-    {0xff64, 0xfe11},  // halfwidth ideo comma
-    {0xff61, 0xfe12},  // halfwidth ideo full stop
+    // {0xff64, 0xfe11},  // halfwidth ideo comma
+    // {0xff61, 0xfe12},  // halfwidth ideo full stop
 };
 
 namespace WebCore {
diff --git a/Source/WebCore/platform/graphics/android/fonts/VerticalTextMap.h b/Source/WebCore/platform/graphics/android/VerticalTextMap.h
similarity index 100%
rename from Source/WebCore/platform/graphics/android/fonts/VerticalTextMap.h
rename to Source/WebCore/platform/graphics/android/VerticalTextMap.h
diff --git a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp
new file mode 100644
index 0000000..482d711
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2011 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "VideoLayerAndroid.h"
+
+#include "RenderSkinMediaButton.h"
+#include "TilesManager.h"
+#include <GLES2/gl2.h>
+#include <gui/SurfaceTexture.h>
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#ifdef DEBUG
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "VideoLayerAndroid", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+namespace WebCore {
+
+GLuint VideoLayerAndroid::m_spinnerOuterTextureId = 0;
+GLuint VideoLayerAndroid::m_spinnerInnerTextureId = 0;
+GLuint VideoLayerAndroid::m_posterTextureId = 0;
+GLuint VideoLayerAndroid::m_backgroundTextureId = 0;
+bool VideoLayerAndroid::m_createdTexture = false;
+
+double VideoLayerAndroid::m_rotateDegree = 0;
+
+const IntRect VideoLayerAndroid::buttonRect(0, 0, IMAGESIZE, IMAGESIZE);
+
+VideoLayerAndroid::VideoLayerAndroid()
+    : LayerAndroid((RenderLayer*)0)
+{
+    init();
+}
+
+VideoLayerAndroid::VideoLayerAndroid(const VideoLayerAndroid& layer)
+    : LayerAndroid(layer)
+{
+    init();
+}
+
+void VideoLayerAndroid::init()
+{
+    // m_surfaceTexture is only useful on UI thread, no need to copy.
+    // And it will be set at setBaseLayer timeframe
+    m_playerState = INITIALIZED;
+}
+
+// We can use this function to set the Layer to point to surface texture.
+void VideoLayerAndroid::setSurfaceTexture(sp<SurfaceTexture> texture,
+                                          int textureName, PlayerState playerState)
+{
+    m_surfaceTexture = texture;
+    m_playerState = playerState;
+    TilesManager::instance()->videoLayerManager()->registerTexture(uniqueId(), textureName);
+}
+
+GLuint VideoLayerAndroid::createSpinnerInnerTexture()
+{
+    return createTextureFromImage(RenderSkinMediaButton::SPINNER_INNER);
+}
+
+GLuint VideoLayerAndroid::createSpinnerOuterTexture()
+{
+    return createTextureFromImage(RenderSkinMediaButton::SPINNER_OUTER);
+}
+
+GLuint VideoLayerAndroid::createPosterTexture()
+{
+    return createTextureFromImage(RenderSkinMediaButton::VIDEO);
+}
+
+GLuint VideoLayerAndroid::createTextureFromImage(int buttonType)
+{
+    SkRect rect = SkRect(buttonRect);
+    SkBitmap bitmap;
+    bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height());
+    bitmap.allocPixels();
+    bitmap.eraseColor(0);
+
+    SkCanvas canvas(bitmap);
+    canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode);
+    RenderSkinMediaButton::Draw(&canvas, buttonRect, buttonType, true);
+
+    GLuint texture;
+    glGenTextures(1, &texture);
+
+    GLUtils::createTextureWithBitmap(texture, bitmap);
+    bitmap.reset();
+    return texture;
+}
+
+GLuint VideoLayerAndroid::createBackgroundTexture()
+{
+    GLuint texture;
+    glGenTextures(1, &texture);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    GLubyte pixels[4 *3] = {
+        128, 128, 128,
+        128, 128, 128,
+        128, 128, 128,
+        128, 128, 128
+    };
+    glBindTexture(GL_TEXTURE_2D, texture);
+    GLUtils::checkGlError("glBindTexture");
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
+    GLUtils::checkGlError("glTexImage2D");
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    return texture;
+}
+
+bool VideoLayerAndroid::drawGL()
+{
+    // Lazily allocated the textures.
+    if (!m_createdTexture) {
+        m_backgroundTextureId = createBackgroundTexture();
+        m_spinnerOuterTextureId = createSpinnerOuterTexture();
+        m_spinnerInnerTextureId = createSpinnerInnerTexture();
+        m_posterTextureId = createPosterTexture();
+        m_createdTexture = true;
+    }
+
+    SkRect rect = SkRect::MakeSize(getSize());
+    GLfloat surfaceMatrix[16];
+
+    SkRect innerRect = SkRect(buttonRect);
+    if (innerRect.contains(rect))
+        innerRect = rect;
+
+    innerRect.offset((rect.width() - IMAGESIZE) / 2 , (rect.height() - IMAGESIZE) / 2);
+
+    // Draw the poster image, the progressing image or the Video depending
+    // on the player's state.
+    if (m_playerState == PREPARING) {
+        // Show the progressing animation, with two rotating circles
+        TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, rect,
+                                                          m_backgroundTextureId,
+                                                          1, true);
+
+        TransformationMatrix addReverseRotation;
+        TransformationMatrix addRotation = m_drawTransform;
+        addRotation.translate(innerRect.fLeft, innerRect.fTop);
+        addRotation.translate(IMAGESIZE / 2, IMAGESIZE / 2);
+        addReverseRotation = addRotation;
+        addRotation.rotate(m_rotateDegree);
+        addRotation.translate(-IMAGESIZE / 2, -IMAGESIZE / 2);
+
+        SkRect size = SkRect::MakeWH(innerRect.width(), innerRect.height());
+        TilesManager::instance()->shader()->drawLayerQuad(addRotation, size,
+                                                          m_spinnerOuterTextureId,
+                                                          1, true);
+
+        addReverseRotation.rotate(-m_rotateDegree);
+        addReverseRotation.translate(-IMAGESIZE / 2, -IMAGESIZE / 2);
+
+        TilesManager::instance()->shader()->drawLayerQuad(addReverseRotation, size,
+                                                          m_spinnerInnerTextureId,
+                                                          1, true);
+
+        m_rotateDegree += ROTATESTEP;
+
+    } else if (m_playerState == PLAYING && m_surfaceTexture.get()) {
+        // Show the real video.
+        m_surfaceTexture->updateTexImage();
+        m_surfaceTexture->getTransformMatrix(surfaceMatrix);
+        GLuint textureId =
+            TilesManager::instance()->videoLayerManager()->getTextureId(uniqueId());
+        TilesManager::instance()->shader()->drawVideoLayerQuad(m_drawTransform,
+                                                               surfaceMatrix,
+                                                               rect, textureId);
+        TilesManager::instance()->videoLayerManager()->updateMatrix(uniqueId(),
+                                                                    surfaceMatrix);
+    } else {
+        GLuint textureId =
+            TilesManager::instance()->videoLayerManager()->getTextureId(uniqueId());
+        GLfloat* matrix =
+            TilesManager::instance()->videoLayerManager()->getMatrix(uniqueId());
+        if (textureId && matrix) {
+            // Show the screen shot for each video.
+            TilesManager::instance()->shader()->drawVideoLayerQuad(m_drawTransform,
+                                                               matrix,
+                                                               rect, textureId);
+        } else {
+            // Show the static poster b/c there is no screen shot available.
+            TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, rect,
+                                                              m_backgroundTextureId,
+                                                              1, true);
+            TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, innerRect,
+                                                              m_posterTextureId,
+                                                              1, true);
+        }
+    }
+
+    return drawChildrenGL();
+}
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.h b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h
similarity index 80%
rename from Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.h
rename to Source/WebCore/platform/graphics/android/VideoLayerAndroid.h
index 5ebf615..8a064bb 100644
--- a/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.h
+++ b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.h
@@ -55,25 +55,35 @@
     virtual bool isVideo() const { return true; }
     virtual LayerAndroid* copy() const { return new VideoLayerAndroid(*this); }
 
-    // The following functions are called in UI thread only.
-    virtual bool drawGL(bool layerTilesDisabled);
+    // The following 3 functions are called in UI thread only.
+    virtual bool drawGL();
     void setSurfaceTexture(sp<SurfaceTexture> texture, int textureName, PlayerState playerState);
-    virtual bool needsIsolatedSurface() { return true; }
+    GLuint createBackgroundTexture();
+    GLuint createSpinnerOuterTexture();
+    GLuint createSpinnerInnerTexture();
+    GLuint createPosterTexture();
 
 private:
+    GLuint createTextureFromImage(int buttonType);
     void init();
-    void showPreparingAnimation(const SkRect& rect,
-                                const SkRect innerRect);
-    SkRect calVideoRect(const SkRect& rect);
     // Surface texture for showing the video is actually allocated in Java side
     // and passed into this native code.
     sp<android::SurfaceTexture> m_surfaceTexture;
 
     PlayerState m_playerState;
 
+    // Texture for showing the static image will be created at native side.
+    static bool m_createdTexture;
+    static GLuint m_backgroundTextureId;
+    static GLuint m_posterTextureId;
+    static GLuint m_spinnerOuterTextureId;
+    static GLuint m_spinnerInnerTextureId;
+
     static double m_rotateDegree;
 
     static const int ROTATESTEP = 12;
+    static const int IMAGESIZE = 64;
+    static const IntRect buttonRect;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp b/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp
new file mode 100644
index 0000000..cec4d67
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/VideoLayerManager.cpp
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2011 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "VideoLayerManager.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#ifdef DEBUG
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "VideoLayerManager", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+// Define the max sum of all the video's sizes.
+// Note that video_size = width * height. If there is no compression, then the
+// maximum memory consumption could be 4 * video_size.
+// Setting this to 2M, means that maximum memory consumption of all the
+// screenshots would not be above 8M.
+#define MAX_VIDEOSIZE_SUM 2097152
+
+namespace WebCore {
+
+VideoLayerManager::VideoLayerManager()
+{
+    m_currentTimeStamp = 0;
+}
+
+// Getting TextureId for GL draw call, in the UI thread.
+GLuint VideoLayerManager::getTextureId(const int layerId)
+{
+    android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
+    GLuint result = 0;
+    if (m_videoLayerInfoMap.contains(layerId))
+        result = m_videoLayerInfoMap.get(layerId)->textureId;
+    return result;
+}
+
+// Getting matrix for GL draw call, in the UI thread.
+GLfloat* VideoLayerManager::getMatrix(const int layerId)
+{
+    android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
+    GLfloat* result = 0;
+    if (m_videoLayerInfoMap.contains(layerId))
+        result = m_videoLayerInfoMap.get(layerId)->surfaceMatrix;
+    return result;
+}
+
+int VideoLayerManager::getTotalMemUsage()
+{
+    int sum = 0;
+    InfoIterator end = m_videoLayerInfoMap.end();
+    for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it)
+        sum += it->second->videoSize;
+    return sum;
+}
+
+// When the video start, we know its texture info, so we register when we
+// recieve the setSurfaceTexture call, this happens on UI thread.
+void VideoLayerManager::registerTexture(const int layerId, const GLuint textureId)
+{
+    android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
+    // If the texture has been registered, then early return.
+    if (m_videoLayerInfoMap.get(layerId)) {
+        GLuint oldTextureId = m_videoLayerInfoMap.get(layerId)->textureId;
+        if (oldTextureId != textureId)
+            removeLayerInternal(layerId);
+        else
+            return;
+    }
+    // The old info is deleted and now complete the new info and store it.
+    VideoLayerInfo* pInfo = new VideoLayerInfo();
+    pInfo->textureId = textureId;
+    memset(pInfo->surfaceMatrix, 0, sizeof(pInfo->surfaceMatrix));
+    pInfo->videoSize = 0;
+    m_currentTimeStamp++;
+    pInfo->timeStamp = m_currentTimeStamp;
+
+    m_videoLayerInfoMap.add(layerId, pInfo);
+    XLOG("GL texture %d regisered for layerId %d", textureId, layerId);
+
+    return;
+}
+
+// Only when the video is prepared, we got the video size. So we should update
+// the size for the video accordingly.
+// This is called from webcore thread, from MediaPlayerPrivateAndroid.
+void VideoLayerManager::updateVideoLayerSize(const int layerId, const int size )
+{
+    android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
+    if (m_videoLayerInfoMap.contains(layerId)) {
+        VideoLayerInfo* pInfo = m_videoLayerInfoMap.get(layerId);
+        if (pInfo)
+            pInfo->videoSize = size;
+    }
+
+    // If the memory usage is out of bound, then just delete the oldest ones.
+    // Because we only recycle the texture before the current timestamp, the
+    // current video's texture will not be deleted.
+    while (getTotalMemUsage() > MAX_VIDEOSIZE_SUM)
+        if (!recycleTextureMem())
+            break;
+    return;
+}
+
+// This is called only from UI thread, at drawGL time.
+void VideoLayerManager::updateMatrix(const int layerId, const GLfloat* matrix)
+{
+    android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
+    if (m_videoLayerInfoMap.contains(layerId)) {
+        // If the existing video layer's matrix is matching the incoming one,
+        // then skip the update.
+        VideoLayerInfo* pInfo = m_videoLayerInfoMap.get(layerId);
+        ASSERT(matrix);
+        if (pInfo && !memcmp(matrix, pInfo->surfaceMatrix, sizeof(pInfo->surfaceMatrix)))
+            return;
+        memcpy(pInfo->surfaceMatrix, matrix, sizeof(pInfo->surfaceMatrix));
+    } else {
+        XLOG("Error: should not reach here, the layerId %d should exist!", layerId);
+        ASSERT(false);
+    }
+    return;
+}
+
+// This is called on the webcore thread, save the GL texture for recycle in
+// the retired queue. They will be deleted in deleteUnusedTextures() in the UI
+// thread.
+// Return true when we found one texture to retire.
+bool VideoLayerManager::recycleTextureMem()
+{
+    // Find the oldest texture int the m_videoLayerInfoMap, put it in m_retiredTextures
+    int oldestTimeStamp = m_currentTimeStamp;
+    int oldestLayerId = -1;
+
+    InfoIterator end = m_videoLayerInfoMap.end();
+#ifdef DEBUG
+    XLOG("VideoLayerManager::recycleTextureMem m_videoLayerInfoMap contains");
+    for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it)
+        XLOG("  layerId %d, textureId %d, videoSize %d, timeStamp %d ",
+             it->first, it->second->textureId, it->second->videoSize, it->second->timeStamp);
+#endif
+    for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it) {
+        if (it->second->timeStamp < oldestTimeStamp) {
+            oldestTimeStamp = it->second->timeStamp;
+            oldestLayerId = it->first;
+        }
+    }
+
+    bool foundTextureToRetire = (oldestLayerId != -1);
+    if (foundTextureToRetire)
+        removeLayerInternal(oldestLayerId);
+
+    return foundTextureToRetire;
+}
+
+// This is only called in the UI thread, b/c glDeleteTextures need to be called
+// on the right context.
+void VideoLayerManager::deleteUnusedTextures()
+{
+    m_retiredTexturesLock.lock();
+    int size = m_retiredTextures.size();
+    if (size > 0) {
+        GLuint* textureNames = new GLuint[size];
+        int index = 0;
+        Vector<GLuint>::const_iterator end = m_retiredTextures.end();
+        for (Vector<GLuint>::const_iterator it = m_retiredTextures.begin();
+             it != end; ++it) {
+            GLuint textureName = *it;
+            if (textureName) {
+                textureNames[index] = textureName;
+                index++;
+                XLOG("GL texture %d will be deleted", textureName);
+            }
+        }
+        glDeleteTextures(size, textureNames);
+        delete textureNames;
+        m_retiredTextures.clear();
+    }
+    m_retiredTexturesLock.unlock();
+    return;
+}
+
+// This can be called in the webcore thread in the media player's dtor.
+void VideoLayerManager::removeLayer(const int layerId)
+{
+    android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
+    removeLayerInternal(layerId);
+}
+
+// This can be called on both UI and webcore thread. Since this is a private
+// function, it is up to the public function to handle the lock for
+// m_videoLayerInfoMap.
+void VideoLayerManager::removeLayerInternal(const int layerId)
+{
+    // Delete the layerInfo corresponding to this layerId and remove from the map.
+    if (m_videoLayerInfoMap.contains(layerId)) {
+        GLuint textureId = m_videoLayerInfoMap.get(layerId)->textureId;
+        if (textureId) {
+            // Buffer up the retired textures in either UI or webcore thread,
+            // will be purged at deleteUnusedTextures in the UI thread.
+            m_retiredTexturesLock.lock();
+            m_retiredTextures.append(textureId);
+            m_retiredTexturesLock.unlock();
+        }
+        delete m_videoLayerInfoMap.get(layerId);
+        m_videoLayerInfoMap.remove(layerId);
+    }
+    return;
+}
+
+}
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h b/Source/WebCore/platform/graphics/android/VideoLayerManager.h
similarity index 72%
rename from Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h
rename to Source/WebCore/platform/graphics/android/VideoLayerManager.h
index adce0f4..de2dafc 100644
--- a/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h
+++ b/Source/WebCore/platform/graphics/android/VideoLayerManager.h
@@ -27,37 +27,20 @@
 #define VideoLayerManager_h
 
 #include "GLUtils.h"
-#include "IntRect.h"
 #include <wtf/HashMap.h>
 #include <wtf/Vector.h>
-#include <utils/threads.h>
 
 #if USE(ACCELERATED_COMPOSITING)
 
 namespace WebCore {
 
-enum IconState {
-    Registered,
-    PlayIconShown,
-    PauseIconShown
-};
-
-enum IconType {
-    PlayIcon,
-    PauseIcon
-};
-
 // Every video layer can use its uniqueId to query VideoLayerManager about such
 // info globally.
 struct VideoLayerInfo {
     GLuint textureId; // GL texture bound with the surface texture.
     int videoSize; // The size of the video.
-    float aspectRatio; // The aspect ratio of the video.
     int timeStamp; // Used to decide which VideoLayerInfo is the oldest one.
     GLfloat surfaceMatrix[16];
-
-    double lastIconShownTime;
-    IconState iconState;
 };
 
 
@@ -71,7 +54,7 @@
     // Register the texture when we got setSurfaceTexture call.
     void registerTexture(const int layerId, const GLuint textureId);
     // Update the size when the video is prepared.
-    void updateVideoLayerSize(const int layerId, const int size, const float ratio);
+    void updateVideoLayerSize(const int layerId, const int size);
     // At draw time, update the matrix for every video frame update.
     void updateMatrix(const int layerId, const GLfloat* matrix);
     // Remove the layer info from the mapping.
@@ -81,25 +64,10 @@
     GLuint getTextureId(const int layerId);
     // Return the matrix for surface texture corresponding to the layerId
     GLfloat* getMatrix(const int layerId);
-    // Return the aspect ratio for the video corresponding to the layerId
-    float getAspectRatio(const int layerId);
 
     // Delete the GL textures
     void deleteUnusedTextures();
 
-    double drawIcon(const int layerId, IconType type);
-
-    GLuint getSpinnerInnerTextureId() { return m_spinnerInnerTextureId; }
-    GLuint getSpinnerOuterTextureId() { return m_spinnerOuterTextureId; }
-    GLuint getPosterTextureId() { return m_posterTextureId; }
-    GLuint getPlayTextureId() { return m_playTextureId; }
-    GLuint getPauseTextureId() { return m_pauseTextureId; }
-
-    void initGLResourcesIfNeeded();
-    void cleanupGLResources();
-    void forceNeedsInit() { m_createdTexture = false; }
-
-    static int getButtonSize();
 private:
     // Get the sum of all the video size stored in m_videoLayerInfoMap.
     int getTotalMemUsage();
@@ -107,7 +75,7 @@
     bool recycleTextureMem();
     // The private function to remove layer.
     void removeLayerInternal(const int layerId);
-    void initGLResources();
+
     // Indexed by each layer's uniqueId, this map contains the important info
     // used for showing the video when playing or the screenshot when paused.
     HashMap<int, VideoLayerInfo*> m_videoLayerInfoMap;
@@ -121,18 +89,6 @@
     // thread, and really get deleted in the UI thread.
     Vector<GLuint> m_retiredTextures;
     android::Mutex m_retiredTexturesLock;
-
-    GLuint createTextureFromImage(int buttonType);
-
-    // Texture for showing the static image will be created at native side.
-    bool m_createdTexture;
-    GLuint m_posterTextureId;
-    GLuint m_spinnerOuterTextureId;
-    GLuint m_spinnerInnerTextureId;
-    GLuint m_playTextureId;
-    GLuint m_pauseTextureId;
-
-    IntRect m_buttonRect;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/ZoomManager.cpp b/Source/WebCore/platform/graphics/android/ZoomManager.cpp
new file mode 100644
index 0000000..2cf9f06
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/ZoomManager.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ZoomManager.h"
+
+#include "GLWebViewState.h"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include <wtf/CurrentTime.h>
+
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "ZoomManager", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ZoomManager", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+namespace WebCore {
+
+using namespace android;
+
+ZoomManager::ZoomManager(GLWebViewState* state)
+    : m_scaleRequestState(kNoScaleRequest)
+    , m_currentScale(-1)
+    , m_futureScale(-1)
+    , m_layersScale(-1)
+    , m_updateTime(-1)
+    , m_transitionTime(-1)
+    , m_glWebViewState(state)
+{
+}
+
+void ZoomManager::scheduleUpdate(const double& currentTime,
+                                 const SkIRect& viewport, float scale)
+{
+    // if no update time, set it
+    if (updateTime() == -1) {
+        m_scaleRequestState = kWillScheduleRequest;
+        setUpdateTime(currentTime + s_updateInitialDelay);
+        setFutureScale(scale);
+        m_glWebViewState->setFutureViewport(viewport);
+        return;
+    }
+
+    if (currentTime < updateTime())
+        return;
+
+    // we reached the scheduled update time, check if we can update
+    if (futureScale() == scale) {
+        // we are still with the previous scale, let's go
+        // with the update
+        m_scaleRequestState = kRequestNewScale;
+        setUpdateTime(-1);
+    } else {
+        // we reached the update time, but the planned update was for
+        // a different scale factor -- meaning the user is still probably
+        // in the process of zooming. Let's push the update time a bit.
+        setUpdateTime(currentTime + s_updateDelay);
+        setFutureScale(scale);
+        m_glWebViewState->setFutureViewport(viewport);
+    }
+}
+
+double ZoomManager::zoomInTransitionTime(double currentTime)
+{
+    if (m_transitionTime == -1)
+        m_transitionTime = currentTime + s_zoomInTransitionDelay;
+    return m_transitionTime;
+}
+
+double ZoomManager::zoomOutTransitionTime(double currentTime)
+{
+    if (m_transitionTime == -1)
+        m_transitionTime = currentTime + s_zoomOutTransitionDelay;
+    return m_transitionTime;
+}
+
+float ZoomManager::zoomInTransparency(double currentTime)
+{
+    float t = zoomInTransitionTime(currentTime) - currentTime;
+    t *= s_invZoomInTransitionDelay;
+    return fmin(1, fmax(0, t));
+}
+
+float ZoomManager::zoomOutTransparency(double currentTime)
+{
+    float t = zoomOutTransitionTime(currentTime) - currentTime;
+    t *= s_invZoomOutTransitionDelay;
+    return fmin(1, fmax(0, t));
+}
+
+bool ZoomManager::swapPages()
+{
+    bool reset = m_scaleRequestState != kNoScaleRequest;
+    m_scaleRequestState = kNoScaleRequest;
+    return reset;
+}
+
+void ZoomManager::processNewScale(double currentTime, float scale)
+{
+    m_prepareNextTiledPage = false;
+    m_zooming = false;
+    const SkIRect& viewportTileBounds = m_glWebViewState->viewportTileBounds();
+
+    if (scale == m_currentScale
+        || m_glWebViewState->preZoomBounds().isEmpty())
+      m_glWebViewState->setPreZoomBounds(viewportTileBounds);
+
+    // If we have a different scale than the current one, we have to
+    // decide what to do. The current behaviour is to delay an update,
+    // so that we do not slow down zooming unnecessarily.
+    if ((m_currentScale != scale
+        && (m_scaleRequestState == ZoomManager::kNoScaleRequest
+            || m_futureScale != scale))
+        || m_scaleRequestState == ZoomManager::kWillScheduleRequest) {
+
+        // schedule the new Zoom request
+        scheduleUpdate(currentTime, viewportTileBounds, scale);
+
+        // If it's a new request, we will have to prepare the page.
+        if (m_scaleRequestState == ZoomManager::kRequestNewScale)
+            m_prepareNextTiledPage = true;
+    }
+
+    // If the viewport has changed since we scheduled the request, we also need
+    // to prepare.
+    if ((m_scaleRequestState == ZoomManager::kRequestNewScale
+         || m_scaleRequestState == ZoomManager::kReceivedNewScale)
+        && m_glWebViewState->futureViewport() != viewportTileBounds)
+        m_prepareNextTiledPage = true;
+
+    // Checking if we are zooming...
+    if (m_scaleRequestState != ZoomManager::kNoScaleRequest) {
+        m_prepareNextTiledPage = true;
+        m_zooming = true;
+    }
+
+    // Get the current scale; if we are zooming, we don't change the scale
+    // factor immediately (see BaseLayerAndroid::drawBasePictureInGL()), but
+    // we change the scaleRequestState. When the state is kReceivedNewScale
+    // (see setReceivedRequest()), we can use the future scale instead of
+    // the current scale to request new textures. After a transition time,
+    // the scaleRequestState will be reset and the current scale will be set
+    // to the future scale.
+    m_layersScale = m_currentScale;
+}
+
+void ZoomManager::processTransition(double currentTime, float scale,
+                                     bool* doSwap, float* backPageTransparency,
+                                     float* frontPageTransparency)
+{
+    if (scale < m_currentScale)
+        *backPageTransparency = 1 - zoomOutTransparency(currentTime);
+    else
+        *frontPageTransparency = zoomInTransparency(currentTime);
+
+    // The transition between the two page is finished
+    if (currentTime > transitionTime(currentTime, scale)) {
+        resetTransitionTime();
+        *doSwap = true;
+    }
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/ZoomManager.h b/Source/WebCore/platform/graphics/android/ZoomManager.h
new file mode 100644
index 0000000..dd04c5d
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/ZoomManager.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ZoomManager_h
+#define ZoomManager_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "SkRect.h"
+
+namespace WebCore {
+
+class GLWebViewState;
+
+class ZoomManager {
+public:
+    enum GLScaleStates {
+        kNoScaleRequest = 0,
+        kWillScheduleRequest = 1,
+        kRequestNewScale = 2,
+        kReceivedNewScale = 3
+    };
+    typedef int32_t GLScaleState;
+
+    ZoomManager(GLWebViewState* state);
+
+    void scheduleUpdate(const double& currentTime, const SkIRect& viewport, float scale);
+
+    GLScaleState scaleRequestState() const { return m_scaleRequestState; }
+    void setScaleRequestState(GLScaleState state) { m_scaleRequestState = state; }
+    float currentScale() const { return m_currentScale; }
+    void setCurrentScale(float scale) { m_currentScale = scale; }
+    float futureScale() const { return m_futureScale; }
+    void setFutureScale(float scale) { m_futureScale = scale; }
+    float layersScale() const { return m_layersScale; }
+    double zoomInTransitionTime(double currentTime);
+    double zoomOutTransitionTime(double currentTime);
+    float zoomInTransparency(double currentTime);
+    float zoomOutTransparency(double currentTime);
+    void resetTransitionTime() { m_transitionTime = -1; }
+    double updateTime() const { return m_updateTime; }
+    void setUpdateTime(double value) { m_updateTime = value; }
+
+    // state used by BaseLayerAndroid
+    bool needPrepareNextTiledPage() { return m_prepareNextTiledPage; }
+    bool zooming() { return m_zooming; }
+
+    bool didFireRequest() { return m_scaleRequestState == ZoomManager::kRequestNewScale; }
+    void setReceivedRequest() {
+        m_scaleRequestState = ZoomManager::kReceivedNewScale;
+        m_layersScale = m_futureScale;
+    }
+    bool didReceivedRequest() { return m_scaleRequestState == ZoomManager::kReceivedNewScale; }
+
+    double transitionTime(double currentTime, float scale) {
+        return (scale < m_currentScale) ? zoomOutTransitionTime(currentTime)
+            : zoomInTransitionTime(currentTime);
+    }
+    void processTransition(double currentTime, float scale, bool* doSwap,
+                            float* backPageTransparency, float* frontPageTransparency);
+
+    bool swapPages();
+
+    void processNewScale(double currentTime, float scale);
+
+private:
+    // Delay between scheduling a new page when the scale
+    // factor changes (i.e. zooming in or out)
+    static const double s_updateInitialDelay = 0.3; // 300 ms
+    // If the scale factor continued to change and we completed
+    // the original delay, we push back the update by this value
+    static const double s_updateDelay = 0.1; // 100 ms
+
+    // Delay for the transition between the two pages
+    static const double s_zoomInTransitionDelay = 0.1; // 100 ms
+    static const double s_invZoomInTransitionDelay = 10;
+    static const double s_zoomOutTransitionDelay = 0.2; // 200 ms
+    static const double s_invZoomOutTransitionDelay = 5;
+
+    GLScaleState m_scaleRequestState;
+    float m_currentScale;
+    float m_futureScale;
+    float m_layersScale;
+    double m_updateTime;
+    double m_transitionTime;
+
+    bool m_prepareNextTiledPage;
+    bool m_zooming;
+
+    GLWebViewState* m_glWebViewState;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+#endif // ZoomManager_h
diff --git a/Source/WebCore/platform/graphics/android/android_graphics.cpp b/Source/WebCore/platform/graphics/android/android_graphics.cpp
new file mode 100644
index 0000000..e88c65d
--- /dev/null
+++ b/Source/WebCore/platform/graphics/android/android_graphics.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2007, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CachedPrefix.h"
+#include "android_graphics.h"
+#include "CachedColor.h"
+#include "CachedRoot.h"
+#include "IntRect.h"
+#include "LayerAndroid.h"
+#include "SkCanvas.h"
+#include "SkCornerPathEffect.h"
+#include "SkPath.h"
+#include "SkRegion.h"
+#include "WebViewCore.h"
+
+namespace android {
+
+// The CSS values for the inner and outer widths may be specified as fractions
+#define WIDTH_SCALE 0.0625f // 1/16, to offset the scale in CSSStyleSelector
+
+void CursorRing::draw(SkCanvas* canvas, LayerAndroid* layer, IntRect* inval)
+{
+    if (!m_lastBounds.isEmpty()) {
+        *inval = m_lastBounds;
+        m_lastBounds = IntRect(0, 0, 0, 0);
+    }
+#if USE(ACCELERATED_COMPOSITING)
+    int layerId = m_node->isInLayer() ? m_frame->layer(m_node)->uniqueId() : -1;
+    if (layer->uniqueId() != layerId)
+        return;
+#endif
+    if (canvas->quickReject(m_bounds, SkCanvas::kAA_EdgeType)) {
+        DBG_NAV_LOGD("canvas->quickReject cursorNode=%d (nodePointer=%p)"
+            " bounds=(%d,%d,w=%d,h=%d)", m_node->index(), m_node->nodePointer(),
+            m_bounds.x(), m_bounds.y(), m_bounds.width(), m_bounds.height());
+        return;
+    }
+    const CachedColor& colors = m_frame->color(m_node);
+    unsigned rectCount = m_rings.size();
+    SkRegion rgn;
+    SkPath path;
+    for (unsigned i = 0; i < rectCount; i++)
+    {
+        SkRect  r(m_rings[i]);
+        SkIRect ir;
+
+        r.round(&ir);
+        ir.inset(-colors.outset(), -colors.outset());
+        rgn.op(ir, SkRegion::kUnion_Op);
+    }
+    rgn.getBoundaryPath(&path);
+
+    SkPaint paint;
+    paint.setAntiAlias(true);
+    paint.setPathEffect(new SkCornerPathEffect(
+        SkIntToScalar(colors.radius())))->unref();
+    SkColor outer;
+    SkColor inner;
+    if (m_isPressed) {
+        SkColor pressed;
+        pressed = colors.fillColor();
+        paint.setColor(pressed);
+        canvas->drawPath(path, paint);
+        outer = colors.pressedOuterColor();
+        inner = colors.pressedInnerColor();
+    } else {
+        outer = colors.selectedOuterColor();
+        inner = colors.selectedInnerColor();
+    }
+    paint.setStyle(SkPaint::kStroke_Style);
+    paint.setStrokeWidth(colors.outerWidth() * WIDTH_SCALE);
+    paint.setColor(outer);
+    canvas->drawPath(path, paint);
+    paint.setStrokeWidth(colors.innerWidth() * WIDTH_SCALE);
+    paint.setColor(inner);
+    canvas->drawPath(path, paint);
+    SkRect localBounds, globalBounds;
+    localBounds = path.getBounds();
+    float width = std::max(colors.innerWidth(), colors.outerWidth());
+    width *= WIDTH_SCALE;
+    localBounds.inset(-width, -width);
+    const SkMatrix& matrix = canvas->getTotalMatrix();
+    matrix.mapRect(&globalBounds, localBounds);
+    SkIRect globalIBounds;
+    globalBounds.round(&globalIBounds);
+    m_lastBounds = globalIBounds;
+    inval->unite(m_lastBounds);
+}
+
+void CursorRing::setIsButton(const CachedNode* node)
+{
+    m_isButton = false;
+}
+
+bool CursorRing::setup()
+{
+    m_node->cursorRings(m_frame, &m_rings);
+    if (!m_rings.size()) {
+        DBG_NAV_LOG("!rings.size()");
+        m_viewImpl->m_hasCursorBounds = false;
+        return false;
+    }
+    setIsButton(m_node);
+    m_bounds = m_node->bounds(m_frame);
+    m_viewImpl->updateCursorBounds(m_root, m_frame, m_node);
+
+    bool useHitBounds = m_node->useHitBounds();
+    if (useHitBounds)
+        m_bounds = m_node->hitBounds(m_frame);
+    if (useHitBounds || m_node->useBounds()) {
+        m_rings.clear();
+        m_rings.append(m_bounds);
+    }
+    m_absBounds = m_node->bounds(m_frame);
+    const CachedColor& colors = m_frame->color(m_node);
+    m_bounds.inflate(SkScalarCeil(colors.outerWidth()));
+    m_absBounds.inflate(SkScalarCeil(colors.outerWidth()));
+    if (!m_node->hasCursorRing() || (m_node->isPlugin() && m_node->isFocus()))
+        return false;
+#if DEBUG_NAV_UI
+    const WebCore::IntRect& ring = m_rings[0];
+    DBG_NAV_LOGD("cursorNode=%d (nodePointer=%p) pressed=%s rings=%d"
+        " (%d, %d, %d, %d) isPlugin=%s",
+        m_node->index(), m_node->nodePointer(),
+        m_isPressed ? "true" : "false",
+        m_rings.size(), ring.x(), ring.y(), ring.width(), ring.height(),
+        m_node->isPlugin() ? "true" : "false");
+    DBG_NAV_LOGD("[%d] inner=%d outer=%d outset=%d radius=%d"
+        " fill=0x%08x pin=0x%08x pout=0x%08x sin=0x%08x sout=0x%08x",
+        m_node->colorIndex(), colors.innerWidth(), colors.outerWidth(),
+        colors.outset(), colors.radius(), colors.fillColor(),
+        colors.pressedInnerColor(), colors.pressedOuterColor(),
+        colors.selectedInnerColor(), colors.selectedInnerColor());
+#endif
+    return true;
+}
+
+}
diff --git a/Source/WebCore/platform/graphics/android/context/android_graphics.h b/Source/WebCore/platform/graphics/android/android_graphics.h
similarity index 61%
copy from Source/WebCore/platform/graphics/android/context/android_graphics.h
copy to Source/WebCore/platform/graphics/android/android_graphics.h
index 7faa781..60ac115 100644
--- a/Source/WebCore/platform/graphics/android/context/android_graphics.h
+++ b/Source/WebCore/platform/graphics/android/android_graphics.h
@@ -26,17 +26,53 @@
 #ifndef android_graphics_DEFINED
 #define android_graphics_DEFINED
 
+#include "DrawExtra.h"
+#include "IntRect.h"
+#include "SkTypes.h"
+#include "wtf/Vector.h"
+
 namespace WebCore {
     class GraphicsContext;
+    class GLExtras;
 }
-class SkCanvas;
 
-// TODO: Move this somewhere else. The implementation for this is actually in
-// GraphicsContextAndroid.cpp, but this is used by a handful of other files
-SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc);
+SkCanvas* android_gc2canvas(GraphicsContext* gc);
+
+namespace android {
+
+class CachedFrame;
+class CachedNode;
+class CachedRoot;
+class WebViewCore;
+
+// Data and methods for cursor rings
 
 // used to inflate node cache entry
 #define CURSOR_RING_HIT_TEST_RADIUS 5
 
+class CursorRing : public DrawExtra {
+public:
+    CursorRing(WebViewCore* core) : m_viewImpl(core) {}
+    virtual ~CursorRing() {}
+    virtual void draw(SkCanvas* , LayerAndroid* , IntRect* );
+    void setIsButton(const CachedNode* );
+    bool setup();
+    WTF::Vector<IntRect>& rings() { return m_rings; }
+private:
+    friend class WebView;
+    friend class WebCore::GLExtras;
+    WebViewCore* m_viewImpl; // copy for convenience
+    WTF::Vector<IntRect> m_rings;
+    IntRect m_bounds;
+    IntRect m_absBounds;
+    IntRect m_lastBounds;
+    const CachedRoot* m_root;
+    const CachedFrame* m_frame;
+    const CachedNode* m_node;
+    bool m_isButton;
+    bool m_isPressed;
+};
+
+}
 
 #endif
diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp b/Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp
deleted file mode 100644
index f2d1400..0000000
--- a/Source/WebCore/platform/graphics/android/context/GraphicsContextAndroid.cpp
+++ /dev/null
@@ -1,663 +0,0 @@
-/*
- * Copyright 2006, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "config.h"
-#include "GraphicsContext.h"
-
-#include "AffineTransform.h"
-#include "Font.h"
-#include "Gradient.h"
-#include "NotImplemented.h"
-#include "Path.h"
-#include "Pattern.h"
-#include "PlatformGraphicsContext.h"
-#include "PlatformGraphicsContextSkia.h"
-#include "SkBitmapRef.h"
-#include "SkBlurDrawLooper.h"
-#include "SkBlurMaskFilter.h"
-#include "SkCanvas.h"
-#include "SkColorPriv.h"
-#include "SkCornerPathEffect.h"
-#include "SkDashPathEffect.h"
-#include "SkDevice.h"
-#include "SkGradientShader.h"
-#include "SkPaint.h"
-#include "SkString.h"
-#include "SkiaUtils.h"
-#include "TransformationMatrix.h"
-#include "android_graphics.h"
-
-using namespace std;
-
-namespace WebCore {
-
-// This class just holds onto a PlatformContextSkia for GraphicsContext.
-class GraphicsContextPlatformPrivate {
-    WTF_MAKE_NONCOPYABLE(GraphicsContextPlatformPrivate);
-public:
-    GraphicsContextPlatformPrivate(PlatformGraphicsContext* platformContext)
-        : m_context(platformContext) { }
-
-    PlatformGraphicsContext* context() { return m_context; }
-
-private:
-    // Non-owning pointer to the PlatformContext.
-    PlatformGraphicsContext* m_context;
-};
-
-static void syncPlatformContext(GraphicsContext* gc)
-{
-    // Stroke and fill sometimes reference each other, so always
-    // sync them both to make sure our state is consistent.
-
-    PlatformGraphicsContext* pgc = gc->platformContext();
-    Gradient* grad = gc->state().fillGradient.get();
-    Pattern* pat = gc->state().fillPattern.get();
-
-    if (grad)
-        pgc->setFillShader(grad->platformGradient());
-    else if (pat)
-        pgc->setFillShader(pat->platformPattern(AffineTransform()));
-    else
-        pgc->setFillColor(gc->state().fillColor);
-
-    grad = gc->state().strokeGradient.get();
-    pat = gc->state().strokePattern.get();
-
-    if (grad)
-        pgc->setStrokeShader(grad->platformGradient());
-    else if (pat)
-        pgc->setStrokeShader(pat->platformPattern(AffineTransform()));
-    else
-        pgc->setStrokeColor(gc->state().strokeColor);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////
-
-GraphicsContext* GraphicsContext::createOffscreenContext(int width, int height)
-{
-    PlatformGraphicsContextSkia* pgc = new PlatformGraphicsContextSkia(new SkCanvas, true);
-
-    SkBitmap bitmap;
-
-    bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
-    bitmap.allocPixels();
-    bitmap.eraseColor(0);
-    pgc->getCanvas()->setBitmapDevice(bitmap);
-
-    GraphicsContext* ctx = new GraphicsContext(pgc);
-    return ctx;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////
-
-void GraphicsContext::platformInit(PlatformGraphicsContext* gc)
-{
-    if (gc)
-        gc->setGraphicsContext(this);
-    m_data = new GraphicsContextPlatformPrivate(gc);
-    setPaintingDisabled(!gc || gc->isPaintingDisabled());
-}
-
-void GraphicsContext::platformDestroy()
-{
-    delete m_data;
-}
-
-void GraphicsContext::savePlatformState()
-{
-    if (paintingDisabled())
-        return;
-    platformContext()->save();
-}
-
-void GraphicsContext::restorePlatformState()
-{
-    if (paintingDisabled())
-        return;
-    platformContext()->restore();
-}
-
-bool GraphicsContext::willFill() const
-{
-    return m_state.fillColor.rgb();
-}
-
-bool GraphicsContext::willStroke() const
-{
-    return m_state.strokeColor.rgb();
-}
-
-// Draws a filled rectangle with a stroked border.
-void GraphicsContext::drawRect(const IntRect& rect)
-{
-    if (paintingDisabled())
-        return;
-
-    syncPlatformContext(this);
-    platformContext()->drawRect(rect);
-}
-
-// This is only used to draw borders.
-void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
-{
-    if (paintingDisabled())
-        return;
-
-    syncPlatformContext(this);
-    platformContext()->drawLine(point1, point2);
-}
-
-void GraphicsContext::drawLineForText(const FloatPoint& pt, float width, bool /* printing */)
-{
-    if (paintingDisabled())
-        return;
-
-    syncPlatformContext(this);
-    platformContext()->drawLineForText(pt, width);
-}
-
-void GraphicsContext::drawLineForTextChecking(const FloatPoint& pt, float width,
-                                              TextCheckingLineStyle style)
-{
-    if (paintingDisabled())
-        return;
-
-    syncPlatformContext(this);
-    platformContext()->drawLineForTextChecking(pt, width, style);
-}
-
-// This method is only used to draw the little circles used in lists.
-void GraphicsContext::drawEllipse(const IntRect& rect)
-{
-    if (paintingDisabled())
-        return;
-
-    syncPlatformContext(this);
-    platformContext()->drawEllipse(rect);
-}
-
-void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan)
-{
-    if (paintingDisabled())
-        return;
-
-    syncPlatformContext(this);
-    platformContext()->strokeArc(r, startAngle, angleSpan);
-}
-
-void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points,
-                                        bool shouldAntialias)
-{
-    if (paintingDisabled())
-        return;
-
-    syncPlatformContext(this);
-    platformContext()->drawConvexPolygon(numPoints, points, shouldAntialias);
-}
-
-void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
-                                      const IntSize& bottomLeft, const IntSize& bottomRight,
-                                      const Color& color, ColorSpace colorSpace)
-{
-    if (paintingDisabled())
-        return;
-
-    syncPlatformContext(this);
-    platformContext()->fillRoundedRect(rect, topLeft, topRight,
-            bottomLeft, bottomRight, color, colorSpace);
-}
-
-void GraphicsContext::fillRect(const FloatRect& rect)
-{
-    if (paintingDisabled())
-        return;
-
-    syncPlatformContext(this);
-    platformContext()->fillRect(rect);
-}
-
-void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
-{
-    if (paintingDisabled())
-        return;
-
-    syncPlatformContext(this);
-    platformContext()->fillRect(rect, color, colorSpace);
-}
-
-void GraphicsContext::clip(const FloatRect& rect)
-{
-    if (paintingDisabled())
-        return;
-
-    platformContext()->clip(rect);
-}
-
-void GraphicsContext::clip(const Path& path)
-{
-    if (paintingDisabled())
-        return;
-
-    platformContext()->clip(path);
-}
-
-void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
-{
-    if (paintingDisabled())
-        return;
-
-    platformContext()->addInnerRoundedRectClip(rect, thickness);
-}
-
-void GraphicsContext::canvasClip(const Path& path)
-{
-    if (paintingDisabled())
-        return;
-
-    platformContext()->canvasClip(path);
-}
-
-void GraphicsContext::clipOut(const IntRect& r)
-{
-    if (paintingDisabled())
-        return;
-
-    platformContext()->clipOut(r);
-}
-
-#if ENABLE(SVG)
-void GraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule)
-{
-    if (paintingDisabled())
-        return;
-
-    platformContext()->clipPath(pathToClip, clipRule);
-}
-#endif
-
-void GraphicsContext::clipOut(const Path& p)
-{
-    if (paintingDisabled())
-        return;
-
-    platformContext()->clipOut(p);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-#if SVG_SUPPORT
-KRenderingDeviceContext* GraphicsContext::createRenderingDeviceContext()
-{
-    return new KRenderingDeviceContextQuartz(platformContext());
-}
-#endif
-
-void GraphicsContext::beginTransparencyLayer(float opacity)
-{
-    if (paintingDisabled())
-        return;
-
-    platformContext()->beginTransparencyLayer(opacity);
-}
-
-void GraphicsContext::endTransparencyLayer()
-{
-    if (paintingDisabled())
-        return;
-
-    platformContext()->endTransparencyLayer();
-}
-
-///////////////////////////////////////////////////////////////////////////
-
-void GraphicsContext::setupFillPaint(SkPaint* paint)
-{
-    if (paintingDisabled())
-        return;
-    syncPlatformContext(this);
-    platformContext()->setupPaintFill(paint);
-}
-
-void GraphicsContext::setupStrokePaint(SkPaint* paint)
-{
-    if (paintingDisabled())
-        return;
-    syncPlatformContext(this);
-    platformContext()->setupPaintStroke(paint, 0);
-}
-
-bool GraphicsContext::setupShadowPaint(SkPaint* paint, SkPoint* offset)
-{
-    if (paintingDisabled())
-        return false;
-    syncPlatformContext(this);
-    return platformContext()->setupPaintShadow(paint, offset);
-}
-
-void GraphicsContext::setPlatformStrokeColor(const Color& c, ColorSpace)
-{
-}
-
-void GraphicsContext::setPlatformStrokeThickness(float f)
-{
-    if (paintingDisabled())
-        return;
-    platformContext()->setStrokeThickness(f);
-}
-
-void GraphicsContext::setPlatformStrokeStyle(StrokeStyle style)
-{
-    if (paintingDisabled())
-        return;
-    platformContext()->setStrokeStyle(style);
-}
-
-void GraphicsContext::setPlatformFillColor(const Color& c, ColorSpace)
-{
-}
-
-void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const Color& color, ColorSpace)
-{
-    if (paintingDisabled())
-        return;
-
-    if (blur <= 0)
-        this->clearPlatformShadow();
-
-    SkColor c;
-    if (color.isValid())
-        c = color.rgb();
-    else
-        c = SkColorSetARGB(0xFF / 3, 0, 0, 0); // "std" Apple shadow color
-    platformContext()->setShadow(blur, size.width(), size.height(), c);
-}
-
-void GraphicsContext::clearPlatformShadow()
-{
-    if (paintingDisabled())
-        return;
-
-    platformContext()->setShadow(0, 0, 0, 0);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
-{
-    if (paintingDisabled())
-        return;
-
-    syncPlatformContext(this);
-    platformContext()->drawFocusRing(rects, width, offset, color);
-}
-
-void GraphicsContext::drawFocusRing(const Path&, int, int, const Color&)
-{
-    // Do nothing, since we draw the focus ring independently.
-}
-
-PlatformGraphicsContext* GraphicsContext::platformContext() const
-{
-    ASSERT(!paintingDisabled());
-    return m_data->context();
-}
-
-void GraphicsContext::setMiterLimit(float limit)
-{
-    if (paintingDisabled())
-        return;
-    platformContext()->setMiterLimit(limit);
-}
-
-void GraphicsContext::setAlpha(float alpha)
-{
-    if (paintingDisabled())
-        return;
-    platformContext()->setAlpha(alpha);
-}
-
-void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op)
-{
-    if (paintingDisabled())
-        return;
-    platformContext()->setCompositeOperation(op);
-}
-
-void GraphicsContext::clearRect(const FloatRect& rect)
-{
-    if (paintingDisabled())
-        return;
-
-    syncPlatformContext(this);
-    platformContext()->clearRect(rect);
-}
-
-void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
-{
-    if (paintingDisabled())
-        return;
-
-    syncPlatformContext(this);
-    platformContext()->strokeRect(rect, lineWidth);
-}
-
-void GraphicsContext::setLineCap(LineCap cap)
-{
-    if (paintingDisabled())
-        return;
-    platformContext()->setLineCap(cap);
-}
-
-#if ENABLE(SVG)
-void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
-{
-    if (paintingDisabled())
-        return;
-
-    platformContext()->setLineDash(dashes, dashOffset);
-}
-#endif
-
-void GraphicsContext::setLineJoin(LineJoin join)
-{
-    if (paintingDisabled())
-        return;
-    platformContext()->setLineJoin(join);
-}
-
-void GraphicsContext::scale(const FloatSize& size)
-{
-    if (paintingDisabled())
-        return;
-    platformContext()->scale(size);
-}
-
-void GraphicsContext::rotate(float angleInRadians)
-{
-    if (paintingDisabled())
-        return;
-    platformContext()->rotate(angleInRadians);
-}
-
-void GraphicsContext::translate(float x, float y)
-{
-    if (paintingDisabled())
-        return;
-    platformContext()->translate(x, y);
-}
-
-void GraphicsContext::concatCTM(const AffineTransform& affine)
-{
-    if (paintingDisabled())
-        return;
-    platformContext()->concatCTM(affine);
-}
-
-// This is intended to round the rect to device pixels (through the CTM)
-// and then invert the result back into source space, with the hope that when
-// it is drawn (through the matrix), it will land in the "right" place (i.e.
-// on pixel boundaries).
-
-// For android, we record this geometry once and then draw it though various
-// scale factors as the user zooms, without re-recording. Thus this routine
-// should just leave the original geometry alone.
-
-// If we instead draw into bitmap tiles, we should then perform this
-// transform -> round -> inverse step.
-
-FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect, RoundingMode)
-{
-    return rect;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////
-
-void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
-{
-// Appears to be PDF specific, so we ignore it
-}
-
-void GraphicsContext::setPlatformShouldAntialias(bool useAA)
-{
-    if (paintingDisabled())
-        return;
-    platformContext()->setShouldAntialias(useAA);
-}
-
-void GraphicsContext::setPlatformFillGradient(Gradient* fillGradient)
-{
-}
-
-void GraphicsContext::setPlatformFillPattern(Pattern* fillPattern)
-{
-}
-
-void GraphicsContext::setPlatformStrokeGradient(Gradient* strokeGradient)
-{
-}
-
-void GraphicsContext::setPlatformStrokePattern(Pattern* strokePattern)
-{
-}
-
-AffineTransform GraphicsContext::getCTM() const
-{
-    if (paintingDisabled())
-        return AffineTransform();
-    const SkMatrix& m = platformContext()->getTotalMatrix();
-    return AffineTransform(SkScalarToDouble(m.getScaleX()), // a
-                           SkScalarToDouble(m.getSkewY()), // b
-                           SkScalarToDouble(m.getSkewX()), // c
-                           SkScalarToDouble(m.getScaleY()), // d
-                           SkScalarToDouble(m.getTranslateX()), // e
-                           SkScalarToDouble(m.getTranslateY())); // f
-}
-
-void GraphicsContext::setCTM(const AffineTransform& transform)
-{
-    // The SkPicture mode of Skia does not support SkCanvas::setMatrix(), so we
-    // can not simply use that method here. We could calculate the transform
-    // required to achieve the desired matrix and use SkCanvas::concat(), but
-    // there's currently no need for this.
-    ASSERT_NOT_REACHED();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void GraphicsContext::fillPath(const Path& pathToFill)
-{
-    if (paintingDisabled())
-        return;
-
-    syncPlatformContext(this);
-    platformContext()->fillPath(pathToFill, fillRule());
-}
-
-void GraphicsContext::strokePath(const Path& pathToStroke)
-{
-    if (paintingDisabled())
-        return;
-
-    syncPlatformContext(this);
-    platformContext()->strokePath(pathToStroke);
-}
-
-InterpolationQuality GraphicsContext::imageInterpolationQuality() const
-{
-    notImplemented();
-    return InterpolationDefault;
-}
-
-void GraphicsContext::setImageInterpolationQuality(InterpolationQuality mode)
-{
-#if 0
-    enum InterpolationQuality {
-        InterpolationDefault,
-        InterpolationNone,
-        InterpolationLow,
-        InterpolationMedium,
-        InterpolationHigh
-    };
-#endif
-    // TODO: record this, so we can know when to use bitmap-filtering when we draw
-    // ... not sure how meaningful this will be given our playback model.
-
-    // Certainly safe to do nothing for the present.
-}
-
-void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint*,
-                                        bool antialias)
-{
-    if (paintingDisabled())
-        return;
-
-    if (numPoints <= 1)
-        return;
-
-    // FIXME: IMPLEMENT!
-}
-
-void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run,
-                                           const FloatPoint& point, int h,
-                                           const Color& backgroundColor,
-                                           ColorSpace colorSpace, int from,
-                                           int to, bool isActive)
-{
-    if (paintingDisabled())
-        return;
-
-    syncPlatformContext(this);
-    platformContext()->drawHighlightForText(font, run, point, h, backgroundColor,
-            colorSpace, from, to, isActive);
-}
-
-} // namespace WebCore
-
-///////////////////////////////////////////////////////////////////////////////
-
-SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc)
-{
-    return gc->platformContext()->getCanvas();
-}
diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h b/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h
deleted file mode 100644
index 927ff0a..0000000
--- a/Source/WebCore/platform/graphics/android/context/GraphicsOperation.h
+++ /dev/null
@@ -1,809 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef GraphicsOperation_h
-#define GraphicsOperation_h
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "Color.h"
-#include "FloatRect.h"
-#include "GlyphBuffer.h"
-#include "Font.h"
-#include "IntRect.h"
-#include "PlatformGraphicsContext.h"
-#include "PlatformGraphicsContextSkia.h"
-#include "SkCanvas.h"
-#include "SkShader.h"
-#include "SkRefCnt.h"
-
-#include <utils/threads.h>
-#include <wtf/text/CString.h>
-
-#define TYPE_CASE(type) case type: return #type;
-
-namespace WebCore {
-
-namespace GraphicsOperation {
-
-class Operation : public SkRefCnt {
-public:
-    typedef enum { UndefinedOperation
-                  // State management
-                  , BeginTransparencyLayerOperation
-                  , EndTransparencyLayerOperation
-                  , SaveOperation
-                  , RestoreOperation
-                  // State setters
-                  , SetAlphaOperation
-                  , SetCompositeOpOperation
-                  , SetFillColorOperation
-                  , SetFillShaderOperation
-                  , SetLineCapOperation
-                  , SetLineDashOperation
-                  , SetLineJoinOperation
-                  , SetMiterLimitOperation
-                  , SetShadowOperation
-                  , SetShouldAntialiasOperation
-                  , SetStrokeColorOperation
-                  , SetStrokeShaderOperation
-                  , SetStrokeStyleOperation
-                  , SetStrokeThicknessOperation
-                  // Paint setup
-                  , SetupPaintFillOperation
-                  , SetupPaintShadowOperation
-                  , SetupPaintStrokeOperation
-                  // Matrix operations
-                  , ConcatCTMOperation
-                  , ScaleOperation
-                  , RotateOperation
-                  , TranslateOperation
-                  // Clipping
-                  , InnerRoundedRectClipOperation
-                  , ClipOperation
-                  , ClipPathOperation
-                  , ClipOutOperation
-                  , ClearRectOperation
-                  // Drawing
-                  , DrawBitmapPatternOperation
-                  , DrawBitmapRectOperation
-                  , DrawEllipseOperation
-                  , DrawLineOperation
-                  , DrawLineForTextOperation
-                  , DrawLineForTextCheckingOperation
-                  , DrawRectOperation
-                  , FillPathOperation
-                  , FillRectOperation
-                  , FillRoundedRectOperation
-                  , StrokeArcOperation
-                  , StrokePathOperation
-                  , StrokeRectOperation
-                  // Text
-                  , DrawComplexTextOperation
-                  , DrawTextOperation
-    } OperationType;
-
-    virtual void apply(PlatformGraphicsContext* context) = 0;
-    virtual ~Operation() {}
-    virtual OperationType type() { return UndefinedOperation; }
-    virtual String parameters() { return ""; }
-    String name()
-    {
-        switch (type()) {
-            TYPE_CASE(UndefinedOperation)
-            // State management
-            TYPE_CASE(BeginTransparencyLayerOperation)
-            TYPE_CASE(EndTransparencyLayerOperation)
-            TYPE_CASE(SaveOperation)
-            TYPE_CASE(RestoreOperation)
-            // State setters
-            TYPE_CASE(SetAlphaOperation)
-            TYPE_CASE(SetCompositeOpOperation)
-            TYPE_CASE(SetFillColorOperation)
-            TYPE_CASE(SetFillShaderOperation)
-            TYPE_CASE(SetLineCapOperation)
-            TYPE_CASE(SetLineDashOperation)
-            TYPE_CASE(SetLineJoinOperation)
-            TYPE_CASE(SetMiterLimitOperation)
-            TYPE_CASE(SetShadowOperation)
-            TYPE_CASE(SetShouldAntialiasOperation)
-            TYPE_CASE(SetStrokeColorOperation)
-            TYPE_CASE(SetStrokeShaderOperation)
-            TYPE_CASE(SetStrokeStyleOperation)
-            TYPE_CASE(SetStrokeThicknessOperation)
-            // Paint setup
-            TYPE_CASE(SetupPaintFillOperation)
-            TYPE_CASE(SetupPaintShadowOperation)
-            TYPE_CASE(SetupPaintStrokeOperation)
-            // Matrix operations
-            TYPE_CASE(ConcatCTMOperation)
-            TYPE_CASE(ScaleOperation)
-            TYPE_CASE(RotateOperation)
-            TYPE_CASE(TranslateOperation)
-            // Clipping
-            TYPE_CASE(InnerRoundedRectClipOperation)
-            TYPE_CASE(ClipOperation)
-            TYPE_CASE(ClipPathOperation)
-            TYPE_CASE(ClipOutOperation)
-            TYPE_CASE(ClearRectOperation)
-            // Drawing
-            TYPE_CASE(DrawBitmapPatternOperation)
-            TYPE_CASE(DrawBitmapRectOperation)
-            TYPE_CASE(DrawEllipseOperation)
-            TYPE_CASE(DrawLineOperation)
-            TYPE_CASE(DrawLineForTextOperation)
-            TYPE_CASE(DrawLineForTextCheckingOperation)
-            TYPE_CASE(DrawRectOperation)
-            TYPE_CASE(FillPathOperation)
-            TYPE_CASE(FillRectOperation)
-            TYPE_CASE(FillRoundedRectOperation)
-            TYPE_CASE(StrokeArcOperation)
-            TYPE_CASE(StrokePathOperation)
-            TYPE_CASE(StrokeRectOperation)
-            // Text
-            TYPE_CASE(DrawComplexTextOperation)
-            TYPE_CASE(DrawTextOperation)
-        }
-        return "Undefined";
-    }
-};
-
-//**************************************
-// State management
-//**************************************
-
-class BeginTransparencyLayer : public Operation {
-public:
-    BeginTransparencyLayer(const float opacity) : m_opacity(opacity) {}
-    virtual void apply(PlatformGraphicsContext* context) { context->beginTransparencyLayer(m_opacity); }
-    virtual OperationType type() { return BeginTransparencyLayerOperation; }
-private:
-    float m_opacity;
-};
-class EndTransparencyLayer : public Operation {
-public:
-    EndTransparencyLayer() {}
-    virtual void apply(PlatformGraphicsContext* context) { context->endTransparencyLayer(); }
-    virtual OperationType type() { return EndTransparencyLayerOperation; }
-};
-class Save : public Operation {
-public:
-    virtual void apply(PlatformGraphicsContext* context) { context->save(); }
-    virtual OperationType type() { return SaveOperation; }
-};
-class Restore : public Operation {
-public:
-    virtual void apply(PlatformGraphicsContext* context) { context->restore(); }
-    virtual OperationType type() { return RestoreOperation; }
-};
-
-//**************************************
-// State setters
-//**************************************
-
-class SetAlpha : public Operation {
-public:
-    SetAlpha(const float alpha) : m_alpha(alpha) {}
-    virtual void apply(PlatformGraphicsContext* context) { context->setAlpha(m_alpha); }
-    virtual OperationType type() { return SetAlphaOperation; }
-private:
-    float m_alpha;
-};
-
-class SetCompositeOperation : public Operation {
-public:
-    SetCompositeOperation(CompositeOperator op) : m_operator(op) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->setCompositeOperation(m_operator);
-    }
-    virtual OperationType type() { return SetCompositeOpOperation; }
-private:
-    CompositeOperator m_operator;
-};
-
-class SetFillColor : public Operation {
-public:
-    SetFillColor(Color color) : m_color(color) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->setFillColor(m_color);
-    }
-    virtual OperationType type() { return SetFillColorOperation; }
-    virtual String parameters() {
-        return String::format("r: %d g: %d b: %d a: %d",
-                              m_color.red(),
-                              m_color.green(),
-                              m_color.blue(),
-                              m_color.alpha());
-    }
-private:
-    Color m_color;
-};
-
-class SetFillShader : public Operation {
-public:
-    SetFillShader(SkShader* shader) : m_shader(shader) {
-        SkSafeRef(m_shader);
-    }
-    ~SetFillShader() { SkSafeUnref(m_shader); }
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->setFillShader(m_shader);
-    }
-    virtual OperationType type() { return SetFillShaderOperation; }
-private:
-    SkShader* m_shader;
-};
-
-class SetLineCap : public Operation {
-public:
-    SetLineCap(LineCap cap) : m_cap(cap) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->setLineCap(m_cap);
-    }
-    virtual OperationType type() { return SetLineCapOperation; }
-private:
-    LineCap m_cap;
-};
-
-class SetLineDash : public Operation {
-public:
-    SetLineDash(const DashArray& dashes, float dashOffset)
-        : m_dashes(dashes), m_dashOffset(dashOffset) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->setLineDash(m_dashes, m_dashOffset);
-    }
-    virtual OperationType type() { return SetLineDashOperation; }
-private:
-    DashArray m_dashes;
-    float m_dashOffset;
-};
-
-class SetLineJoin : public Operation {
-public:
-    SetLineJoin(LineJoin join) : m_join(join) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->setLineJoin(m_join);
-    }
-    virtual OperationType type() { return SetLineJoinOperation; }
-private:
-    LineJoin m_join;
-};
-
-class SetMiterLimit : public Operation {
-public:
-    SetMiterLimit(float limit) : m_limit(limit) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->setMiterLimit(m_limit);
-    }
-    virtual OperationType type() { return SetMiterLimitOperation; }
-private:
-    float m_limit;
-};
-
-class SetShadow : public Operation {
-public:
-    SetShadow(int radius, int dx, int dy, SkColor c)
-        : m_radius(radius), m_dx(dx), m_dy(dy), m_color(c) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->setShadow(m_radius, m_dx, m_dy, m_color);
-    }
-    virtual OperationType type() { return SetShadowOperation; }
-private:
-    int m_radius;
-    int m_dx;
-    int m_dy;
-    SkColor m_color;
-};
-
-class SetShouldAntialias : public Operation {
-public:
-    SetShouldAntialias(bool useAA) : m_useAA(useAA) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->setShouldAntialias(m_useAA);
-    }
-    virtual OperationType type() { return SetShouldAntialiasOperation; }
-private:
-    bool m_useAA;
-};
-
-class SetStrokeColor : public Operation {
-public:
-    SetStrokeColor(const Color& c) : m_color(c) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->setStrokeColor(m_color);
-    }
-    virtual OperationType type() { return SetStrokeColorOperation; }
-private:
-    Color m_color;
-};
-
-class SetStrokeShader : public Operation {
-public:
-    SetStrokeShader(SkShader* strokeShader) : m_shader(strokeShader) {
-        SkSafeRef(m_shader);
-    }
-    ~SetStrokeShader() { SkSafeUnref(m_shader); }
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->setStrokeShader(m_shader);
-    }
-    virtual OperationType type() { return SetStrokeShaderOperation; }
-private:
-    SkShader* m_shader;
-};
-
-class SetStrokeStyle : public Operation {
-public:
-    SetStrokeStyle(StrokeStyle style) : m_style(style) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->setStrokeStyle(m_style);
-    }
-    virtual OperationType type() { return SetStrokeStyleOperation; }
-private:
-    StrokeStyle m_style;
-};
-
-class SetStrokeThickness : public Operation {
-public:
-    SetStrokeThickness(float thickness) : m_thickness(thickness) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->setStrokeThickness(m_thickness);
-    }
-    virtual OperationType type() { return SetStrokeThicknessOperation; }
-private:
-    float m_thickness;
-};
-
-//**************************************
-// Paint setup
-//**************************************
-
-class SetupPaintFill : public Operation {
-public:
-    SetupPaintFill(SkPaint* paint) : m_paint(*paint) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->setupPaintFill(&m_paint);
-    }
-    virtual OperationType type() { return SetupPaintFillOperation; }
-private:
-    SkPaint m_paint;
-};
-
-class SetupPaintShadow : public Operation {
-public:
-    SetupPaintShadow(SkPaint* paint, SkPoint* offset)
-        : m_paint(*paint), m_offset(*offset) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->setupPaintShadow(&m_paint, &m_offset);
-    }
-    virtual OperationType type() { return SetupPaintShadowOperation; }
-private:
-    SkPaint m_paint;
-    SkPoint m_offset;
-};
-
-class SetupPaintStroke : public Operation {
-public:
-    SetupPaintStroke(SkPaint* paint, SkRect* rect, bool isHLine)
-        : m_paint(*paint), m_rect(*rect), m_isHLine(isHLine) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->setupPaintStroke(&m_paint, &m_rect, m_isHLine);
-    }
-    virtual OperationType type() { return SetupPaintStrokeOperation; }
-private:
-    SkPaint m_paint;
-    SkRect m_rect;
-    bool m_isHLine;
-};
-
-//**************************************
-// Matrix operations
-//**************************************
-
-class ConcatCTM : public Operation {
-public:
-    ConcatCTM(const AffineTransform& affine) : m_matrix(affine) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->concatCTM(m_matrix);
-    }
-    virtual OperationType type() { return ConcatCTMOperation; }
-private:
-    AffineTransform m_matrix;
-};
-
-class Rotate : public Operation {
-public:
-    Rotate(float angleInRadians) : m_angle(angleInRadians) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->rotate(m_angle);
-    }
-    virtual OperationType type() { return RotateOperation; }
-private:
-    float m_angle;
-};
-
-class Scale : public Operation {
-public:
-    Scale(const FloatSize& size) : m_scale(size) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->scale(m_scale);
-    }
-    virtual OperationType type() { return ScaleOperation; }
-private:
-    FloatSize m_scale;
-};
-
-class Translate : public Operation {
-public:
-    Translate(float x, float y) : m_x(x), m_y(y) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->translate(m_x, m_y);
-    }
-    virtual OperationType type() { return TranslateOperation; }
-private:
-    float m_x;
-    float m_y;
-};
-
-//**************************************
-// Clipping
-//**************************************
-
-class InnerRoundedRectClip : public Operation {
-public:
-    InnerRoundedRectClip(const IntRect& rect, int thickness)
-        : m_rect(rect), m_thickness(thickness) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->addInnerRoundedRectClip(m_rect, m_thickness);
-    }
-    virtual OperationType type() { return InnerRoundedRectClipOperation; }
-private:
-    IntRect m_rect;
-    int m_thickness;
-};
-
-class Clip : public Operation {
-public:
-    Clip(const FloatRect& rect) : m_rect(rect) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->clip(m_rect);
-    }
-    virtual OperationType type() { return ClipOperation; }
-private:
-    const FloatRect m_rect;
-};
-
-class ClipPath : public Operation {
-public:
-    ClipPath(const Path& path, bool clipout = false)
-        : m_path(path), m_clipOut(clipout), m_hasWindRule(false) {}
-    void setWindRule(WindRule rule) { m_windRule = rule; m_hasWindRule = true; }
-    virtual void apply(PlatformGraphicsContext* context) {
-        if (m_hasWindRule) {
-            context->clipPath(m_path, m_windRule);
-            return;
-        }
-        if (m_clipOut)
-            context->clipOut(m_path);
-        else
-            context->clip(m_path);
-    }
-    virtual OperationType type() { return ClipPathOperation; }
-private:
-    const Path m_path;
-    bool m_clipOut;
-    WindRule m_windRule;
-    bool m_hasWindRule;
-};
-
-class ClipOut : public Operation {
-public:
-    ClipOut(const IntRect& rect) : m_rect(rect) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->clipOut(m_rect);
-    }
-    virtual OperationType type() { return ClipOutOperation; }
-private:
-    const IntRect m_rect;
-};
-
-class ClearRect : public Operation {
-public:
-    ClearRect(const FloatRect& rect) : m_rect(rect) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->clearRect(m_rect);
-    }
-    virtual OperationType type() { return ClearRectOperation; }
-private:
-    FloatRect m_rect;
-};
-
-//**************************************
-// Drawing
-//**************************************
-
-class DrawBitmapPattern : public Operation {
-public:
-    DrawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix,
-                      CompositeOperator op, const FloatRect& destRect)
-        : m_bitmap(bitmap), m_matrix(matrix), m_operator(op), m_destRect(destRect) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->drawBitmapPattern(m_bitmap, m_matrix, m_operator, m_destRect);
-    }
-    virtual OperationType type() { return DrawBitmapPatternOperation; }
-private:
-    // TODO: use refcounted bitmap
-    const SkBitmap m_bitmap;
-    SkMatrix m_matrix;
-    CompositeOperator m_operator;
-    FloatRect m_destRect;
-};
-
-class DrawBitmapRect : public Operation {
-public:
-    DrawBitmapRect(const SkBitmap& bitmap, const SkIRect& srcR,
-                   const SkRect& dstR, CompositeOperator op)
-        : m_bitmap(bitmap), m_srcR(srcR), m_dstR(dstR), m_operator(op) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->drawBitmapRect(m_bitmap, &m_srcR, m_dstR, m_operator);
-    }
-    virtual OperationType type() { return DrawBitmapRectOperation; }
-    virtual String parameters() {
-        return String::format("%.2f, %.2f - %.2f x %.2f",
-                 m_dstR.fLeft, m_dstR.fTop,
-                 m_dstR.width(), m_dstR.height());
-    }
-private:
-    const SkBitmap& m_bitmap;
-    SkIRect m_srcR;
-    SkRect m_dstR;
-    CompositeOperator m_operator;
-};
-
-class DrawEllipse : public Operation {
-public:
-    DrawEllipse(const IntRect& rect) : m_rect(rect) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->drawEllipse(m_rect);
-    }
-    virtual OperationType type() { return DrawEllipseOperation; }
-private:
-    IntRect m_rect;
-};
-
-class DrawLine : public Operation {
-public:
-    DrawLine(const IntPoint& point1, const IntPoint& point2)
-        : m_point1(point1), m_point2(point2) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->drawLine(m_point1, m_point2);
-    }
-    virtual OperationType type() { return DrawLineOperation; }
-private:
-    IntPoint m_point1;
-    IntPoint m_point2;
-};
-
-class DrawLineForText : public Operation {
-public:
-    DrawLineForText(const FloatPoint& pt, float width)
-        : m_point(pt), m_width(width) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->drawLineForText(m_point, m_width);
-    }
-    virtual OperationType type() { return DrawLineForTextOperation; }
-private:
-    FloatPoint m_point;
-    float m_width;
-};
-
-class DrawLineForTextChecking : public Operation {
-public:
-    DrawLineForTextChecking(const FloatPoint& pt, float width,
-                            GraphicsContext::TextCheckingLineStyle lineStyle)
-        : m_point(pt), m_width(width), m_lineStyle(lineStyle) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->drawLineForTextChecking(m_point, m_width, m_lineStyle);
-    }
-    virtual OperationType type() { return DrawLineForTextCheckingOperation; }
-private:
-    FloatPoint m_point;
-    float m_width;
-    GraphicsContext::TextCheckingLineStyle m_lineStyle;
-};
-
-class DrawRect : public Operation {
-public:
-    DrawRect(const IntRect& rect) : m_rect(rect) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->drawRect(m_rect);
-    }
-    virtual OperationType type() { return DrawRectOperation; }
-private:
-    IntRect m_rect;
-};
-
-class FillPath : public Operation {
-public:
-    FillPath(const Path& pathToFill, WindRule fillRule)
-        : m_path(pathToFill), m_fillRule(fillRule) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->fillPath(m_path, m_fillRule);
-    }
-    virtual OperationType type() { return FillPathOperation; }
-private:
-    Path m_path;
-    WindRule m_fillRule;
-};
-
-class FillRect : public Operation {
-public:
-    FillRect(const FloatRect& rect) : m_rect(rect), m_hasColor(false) {}
-    void setColor(Color c) { m_color = c; m_hasColor = true; }
-    virtual void apply(PlatformGraphicsContext* context) {
-        if (m_hasColor)
-             context->fillRect(m_rect, m_color);
-        else
-             context->fillRect(m_rect);
-    }
-    virtual OperationType type() { return FillRectOperation; }
-private:
-    FloatRect m_rect;
-    Color m_color;
-    bool m_hasColor;
-};
-
-class FillRoundedRect : public Operation {
-public:
-    FillRoundedRect(const IntRect& rect,
-                    const IntSize& topLeft,
-                    const IntSize& topRight,
-                    const IntSize& bottomLeft,
-                    const IntSize& bottomRight,
-                    const Color& color)
-        : m_rect(rect)
-        , m_topLeft(topLeft)
-        , m_topRight(topRight)
-        , m_bottomLeft(bottomLeft)
-        , m_bottomRight(bottomRight)
-        , m_color(color)
-    {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->fillRoundedRect(m_rect, m_topLeft, m_topRight,
-                                 m_bottomLeft, m_bottomRight,
-                                 m_color);
-    }
-    virtual OperationType type() { return FillRoundedRectOperation; }
-private:
-    IntRect m_rect;
-    IntSize m_topLeft;
-    IntSize m_topRight;
-    IntSize m_bottomLeft;
-    IntSize m_bottomRight;
-    Color m_color;
-};
-
-class StrokeArc : public Operation {
-public:
-    StrokeArc(const IntRect& r, int startAngle, int angleSpan)
-        : m_rect(r)
-        , m_startAngle(startAngle)
-        , m_angleSpan(angleSpan)
-    {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->strokeArc(m_rect, m_startAngle, m_angleSpan);
-    }
-    virtual OperationType type() { return StrokeArcOperation; }
-private:
-    IntRect m_rect;
-    int m_startAngle;
-    int m_angleSpan;
-};
-
-class StrokePath : public Operation {
-public:
-    StrokePath(const Path& path) : m_path(path) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->strokePath(m_path);
-    }
-    virtual OperationType type() { return StrokePathOperation; }
-private:
-    Path m_path;
-};
-
-
-class StrokeRect : public Operation {
-public:
-    StrokeRect(const FloatRect& rect, float lineWidth)
-        : m_rect(rect), m_lineWidth(lineWidth) {}
-    virtual void apply(PlatformGraphicsContext* context) {
-        context->strokeRect(m_rect, m_lineWidth);
-    }
-    virtual OperationType type() { return StrokeRectOperation; }
-private:
-    FloatRect m_rect;
-    float m_lineWidth;
-};
-
-//**************************************
-// Text
-//**************************************
-
-class DrawComplexText : public Operation {
-public:
-    DrawComplexText(SkPicture* picture) : m_picture(picture) {
-        SkSafeRef(m_picture);
-    }
-    ~DrawComplexText() { SkSafeUnref(m_picture); }
-    virtual void apply(PlatformGraphicsContext* context) {
-        if (!context->getCanvas())
-            return;
-        context->getCanvas()->drawPicture(*m_picture);
-    }
-    virtual OperationType type() { return DrawComplexTextOperation; }
-private:
-    SkPicture* m_picture;
-};
-
-class DrawText : public Operation {
-public:
-    DrawText(const Font* font, const SimpleFontData* simpleFont,
-             const GlyphBuffer& glyphBuffer,
-             int from, int numGlyphs, const FloatPoint& point)
-        : m_font(font), m_simpleFont(simpleFont)
-        , m_glyphBuffer(glyphBuffer), m_from(from)
-        , m_numGlyphs(numGlyphs), m_point(point) {
-
-        SkPicture* picture = new SkPicture();
-        SkCanvas* canvas = picture->beginRecording(0, 0, 0);
-        PlatformGraphicsContextSkia platformContext(canvas);
-        GraphicsContext graphicsContext(&platformContext);
-        m_font->drawGlyphs(&graphicsContext, m_simpleFont,
-                           m_glyphBuffer, m_from, m_numGlyphs, m_point);
-        picture->endRecording();
-        m_picture = picture;
-    }
-    ~DrawText() { SkSafeUnref(m_picture); }
-    virtual void apply(PlatformGraphicsContext* context) {
-        if (!context->getCanvas())
-            return;
-        context->getCanvas()->drawPicture(*m_picture);
-    }
-    virtual OperationType type() { return DrawTextOperation; }
-private:
-    SkPicture* m_picture;
-    const Font* m_font;
-    const SimpleFontData* m_simpleFont;
-    const GlyphBuffer m_glyphBuffer;
-    int m_from;
-    int m_numGlyphs;
-    const FloatPoint m_point;
-};
-
-}
-
-}
-
-#endif // USE(ACCELERATED_COMPOSITING)
-
-#endif // GraphicsOperation_h
diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp
deleted file mode 100644
index 9e6208d..0000000
--- a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-#define LOG_TAG "GraphicsOperationCollection"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "GraphicsOperationCollection.h"
-
-#include "AndroidLog.h"
-#include "GraphicsContext.h"
-#include "PlatformGraphicsContext.h"
-#include "PlatformGraphicsContextRecording.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-namespace WebCore {
-
-GraphicsOperationCollection::GraphicsOperationCollection(const IntRect& drawArea)
-    : m_drawArea(drawArea)
-{
-}
-
-GraphicsOperationCollection::~GraphicsOperationCollection()
-{
-    for (unsigned int i = 0; i < m_operations.size(); i++)
-        SkSafeUnref(m_operations[i]);
-}
-
-void GraphicsOperationCollection::apply(PlatformGraphicsContext* context)
-{
-    ALOGD("\nApply GraphicsOperationCollection %x, %d operations", this, m_operations.size());
-    for (unsigned int i = 0; i < m_operations.size(); i++) {
-        ALOGD("[%d] (%x) %s %s", i, this, m_operations[i]->name().ascii().data(),
-              m_operations[i]->parameters().ascii().data());
-        m_operations[i]->apply(context);
-    }
-}
-
-void GraphicsOperationCollection::append(GraphicsOperation::Operation* operation)
-{
-    m_operations.append(operation);
-}
-
-bool GraphicsOperationCollection::isEmpty()
-{
-    return !m_operations.size();
-}
-
-AutoGraphicsOperationCollection::AutoGraphicsOperationCollection(const IntRect& area)
-{
-    m_graphicsOperationCollection = new GraphicsOperationCollection(area);
-    m_platformGraphicsContext = new PlatformGraphicsContextRecording(m_graphicsOperationCollection);
-    m_graphicsContext = new GraphicsContext(m_platformGraphicsContext);
-}
-
-AutoGraphicsOperationCollection::~AutoGraphicsOperationCollection()
-{
-    SkSafeUnref(m_graphicsOperationCollection);
-    delete m_graphicsContext;
-    delete m_platformGraphicsContext;
-}
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h b/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h
deleted file mode 100644
index 9d7b530..0000000
--- a/Source/WebCore/platform/graphics/android/context/GraphicsOperationCollection.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef GraphicsOperationCollection_h
-#define GraphicsOperationCollection_h
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "Color.h"
-#include "GraphicsOperation.h"
-#include "IntRect.h"
-#include "SkRefCnt.h"
-
-namespace WebCore {
-
-class PlatformGraphicsContext;
-
-class GraphicsOperationCollection : public SkRefCnt {
-public:
-    GraphicsOperationCollection(const IntRect& drawArea);
-    ~GraphicsOperationCollection();
-
-    void apply(PlatformGraphicsContext* context);
-    void append(GraphicsOperation::Operation* operation);
-
-    bool isEmpty();
-
-private:
-    IntRect m_drawArea;
-    Vector<GraphicsOperation::Operation*> m_operations;
-};
-
-class AutoGraphicsOperationCollection {
-public:
-   AutoGraphicsOperationCollection(const IntRect& area);
-   ~AutoGraphicsOperationCollection();
-   GraphicsContext* context() { return m_graphicsContext; }
-   GraphicsOperationCollection* picture() { return m_graphicsOperationCollection; }
-
-private:
-   GraphicsOperationCollection* m_graphicsOperationCollection;
-   PlatformGraphicsContext* m_platformGraphicsContext;
-   GraphicsContext* m_graphicsContext;
-};
-
-}
-
-#endif // USE(ACCELERATED_COMPOSITING)
-
-#endif // GraphicsOperationCollection_h
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp
deleted file mode 100644
index ce9ce5a..0000000
--- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.cpp
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * Copyright 2006, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "PlatformGraphicsContext"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "PlatformGraphicsContext.h"
-
-#include "AndroidLog.h"
-#include "SkBlurDrawLooper.h"
-#include "SkBlurMaskFilter.h"
-#include "SkColorPriv.h"
-#include "SkDashPathEffect.h"
-#include "SkPaint.h"
-#include "SkShader.h"
-#include "SkiaUtils.h"
-
-namespace WebCore {
-
-//**************************************
-// Helper functions
-//**************************************
-
-static int RoundToInt(float x)
-{
-    return (int)roundf(x);
-}
-
-template <typename T> T* deepCopyPtr(const T* src)
-{
-    return src ? new T(*src) : 0;
-}
-
-// Set a bitmap shader that mimics dashing by width-on, width-off.
-// Returns false if it could not succeed (e.g. there was an existing shader)
-static bool setBitmapDash(SkPaint* paint, int width) {
-    if (width <= 0 || paint->getShader())
-        return false;
-
-    SkColor c = paint->getColor();
-
-    SkBitmap bm;
-    bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 1);
-    bm.allocPixels();
-    bm.lockPixels();
-
-    // set the ON pixel
-    *bm.getAddr32(0, 0) = SkPreMultiplyARGB(0xFF, SkColorGetR(c),
-                                            SkColorGetG(c), SkColorGetB(c));
-    // set the OFF pixel
-    *bm.getAddr32(1, 0) = 0;
-    bm.unlockPixels();
-
-    SkMatrix matrix;
-    matrix.setScale(SkIntToScalar(width), SK_Scalar1);
-
-    SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
-                                               SkShader::kClamp_TileMode);
-    s->setLocalMatrix(matrix);
-
-    paint->setShader(s)->unref();
-    return true;
-}
-
-//**************************************
-// State implementation
-//**************************************
-
-PlatformGraphicsContext::State::State()
-    : pathEffect(0)
-    , miterLimit(4)
-    , alpha(1)
-    , strokeThickness(0) // Same as default in GraphicsContextPrivate.h
-    , lineCap(SkPaint::kDefault_Cap)
-    , lineJoin(SkPaint::kDefault_Join)
-    , mode(SkXfermode::kSrcOver_Mode)
-    , dashRatio(3)
-    , fillColor(SK_ColorBLACK)
-    , fillShader(0)
-    , strokeColor(SK_ColorBLACK)
-    , strokeShader(0)
-    , useAA(true)
-    , strokeStyle(SolidStroke)
-{
-}
-
-PlatformGraphicsContext::State::State(const State& other)
-    : pathEffect(other.pathEffect)
-    , miterLimit(other.miterLimit)
-    , alpha(other.alpha)
-    , strokeThickness(other.strokeThickness)
-    , lineCap(other.lineCap)
-    , lineJoin(other.lineJoin)
-    , mode(other.mode)
-    , dashRatio(other.dashRatio)
-    , shadow(other.shadow)
-    , fillColor(other.fillColor)
-    , fillShader(other.fillShader)
-    , strokeColor(other.strokeColor)
-    , strokeShader(other.strokeShader)
-    , useAA(other.useAA)
-    , strokeStyle(other.strokeStyle)
-{
-    SkSafeRef(pathEffect);
-    SkSafeRef(fillShader);
-    SkSafeRef(strokeShader);
-}
-
-PlatformGraphicsContext::State::~State()
-{
-    SkSafeUnref(pathEffect);
-    SkSafeUnref(fillShader);
-    SkSafeUnref(strokeShader);
-}
-
-void PlatformGraphicsContext::State::setShadow(int radius, int dx, int dy, SkColor c)
-{
-    // Cut the radius in half, to visually match the effect seen in
-    // safari browser
-    shadow.blur = SkScalarHalf(SkIntToScalar(radius));
-    shadow.dx = SkIntToScalar(dx);
-    shadow.dy = SkIntToScalar(dy);
-    shadow.color = c;
-}
-
-bool PlatformGraphicsContext::State::setupShadowPaint(SkPaint* paint, SkPoint* offset,
-                      bool shadowsIgnoreTransforms)
-{
-    paint->setAntiAlias(true);
-    paint->setDither(true);
-    paint->setXfermodeMode(mode);
-    paint->setColor(shadow.color);
-    offset->set(shadow.dx, shadow.dy);
-
-    // Currently, only GraphicsContexts associated with the
-    // HTMLCanvasElement have shadows ignore transforms set.  This
-    // allows us to distinguish between CSS and Canvas shadows which
-    // have different rendering specifications.
-    uint32_t flags = SkBlurMaskFilter::kHighQuality_BlurFlag;
-    if (shadowsIgnoreTransforms) {
-        offset->fY = -offset->fY;
-        flags |= SkBlurMaskFilter::kIgnoreTransform_BlurFlag;
-    }
-
-    if (shadow.blur > 0) {
-        paint->setMaskFilter(SkBlurMaskFilter::Create(shadow.blur,
-                             SkBlurMaskFilter::kNormal_BlurStyle))->unref();
-    }
-    return SkColorGetA(shadow.color) && (shadow.blur || shadow.dx || shadow.dy);
-}
-
-SkColor PlatformGraphicsContext::State::applyAlpha(SkColor c) const
-{
-    int s = RoundToInt(alpha * 256);
-    if (s >= 256)
-        return c;
-    if (s < 0)
-        return 0;
-
-    int a = SkAlphaMul(SkColorGetA(c), s);
-    return (c & 0x00FFFFFF) | (a << 24);
-}
-
-// Returns a new State with all of this object's inherited properties copied.
-PlatformGraphicsContext::State PlatformGraphicsContext::State::cloneInheritedProperties()
-{
-    return PlatformGraphicsContext::State(*this);
-}
-
-//**************************************
-// PlatformGraphicsContext
-//**************************************
-
-PlatformGraphicsContext::PlatformGraphicsContext()
-{
-    m_stateStack.append(State());
-    m_state = &m_stateStack.last();
-}
-
-PlatformGraphicsContext::~PlatformGraphicsContext()
-{
-}
-
-//**************************************
-// State management
-//**************************************
-
-void PlatformGraphicsContext::save()
-{
-    m_stateStack.append(m_state->cloneInheritedProperties());
-    m_state = &m_stateStack.last();
-}
-
-void PlatformGraphicsContext::restore()
-{
-    m_stateStack.removeLast();
-    m_state = &m_stateStack.last();
-}
-
-//**************************************
-// State setters
-//**************************************
-
-void PlatformGraphicsContext::setAlpha(float alpha)
-{
-    m_state->alpha = alpha;
-}
-
-int PlatformGraphicsContext::getNormalizedAlpha() const
-{
-    int alpha = roundf(m_state->alpha * 256);
-    if (alpha > 255)
-        alpha = 255;
-    else if (alpha < 0)
-        alpha = 0;
-    return alpha;
-}
-
-void PlatformGraphicsContext::setCompositeOperation(CompositeOperator op)
-{
-    m_state->mode = WebCoreCompositeToSkiaComposite(op);
-}
-
-void PlatformGraphicsContext::setFillColor(const Color& c)
-{
-    m_state->fillColor = c.rgb();
-    setFillShader(0);
-}
-
-void PlatformGraphicsContext::setFillShader(SkShader* fillShader)
-{
-    if (fillShader)
-        m_state->fillColor = Color::black;
-
-    if (fillShader != m_state->fillShader) {
-        SkSafeUnref(m_state->fillShader);
-        m_state->fillShader = fillShader;
-        SkSafeRef(m_state->fillShader);
-    }
-}
-
-void PlatformGraphicsContext::setLineCap(LineCap cap)
-{
-    switch (cap) {
-    case ButtCap:
-        m_state->lineCap = SkPaint::kButt_Cap;
-        break;
-    case RoundCap:
-        m_state->lineCap = SkPaint::kRound_Cap;
-        break;
-    case SquareCap:
-        m_state->lineCap = SkPaint::kSquare_Cap;
-        break;
-    default:
-        ALOGD("PlatformGraphicsContextSkia::setLineCap: unknown LineCap %d\n", cap);
-        break;
-    }
-}
-
-void PlatformGraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
-{
-    size_t dashLength = dashes.size();
-    if (!dashLength)
-        return;
-
-    size_t count = !(dashLength % 2) ? dashLength : dashLength * 2;
-    SkScalar* intervals = new SkScalar[count];
-
-    for (unsigned int i = 0; i < count; i++)
-        intervals[i] = SkFloatToScalar(dashes[i % dashLength]);
-    SkPathEffect **effectPtr = &m_state->pathEffect;
-    SkSafeUnref(*effectPtr);
-    *effectPtr = new SkDashPathEffect(intervals, count, SkFloatToScalar(dashOffset));
-
-    delete[] intervals;
-}
-
-void PlatformGraphicsContext::setLineJoin(LineJoin join)
-{
-    switch (join) {
-    case MiterJoin:
-        m_state->lineJoin = SkPaint::kMiter_Join;
-        break;
-    case RoundJoin:
-        m_state->lineJoin = SkPaint::kRound_Join;
-        break;
-    case BevelJoin:
-        m_state->lineJoin = SkPaint::kBevel_Join;
-        break;
-    default:
-        ALOGD("PlatformGraphicsContextSkia::setLineJoin: unknown LineJoin %d\n", join);
-        break;
-    }
-}
-
-void PlatformGraphicsContext::setMiterLimit(float limit)
-{
-    m_state->miterLimit = limit;
-}
-
-void PlatformGraphicsContext::setShadow(int radius, int dx, int dy, SkColor c)
-{
-    m_state->setShadow(radius, dx, dy, c);
-}
-
-void PlatformGraphicsContext::setShouldAntialias(bool useAA)
-{
-    m_state->useAA = useAA;
-}
-
-void PlatformGraphicsContext::setStrokeColor(const Color& c)
-{
-    m_state->strokeColor = c.rgb();
-    setStrokeShader(0);
-}
-
-void PlatformGraphicsContext::setStrokeShader(SkShader* strokeShader)
-{
-    if (strokeShader)
-        m_state->strokeColor = Color::black;
-
-    if (strokeShader != m_state->strokeShader) {
-        SkSafeUnref(m_state->strokeShader);
-        m_state->strokeShader = strokeShader;
-        SkSafeRef(m_state->strokeShader);
-    }
-}
-
-void PlatformGraphicsContext::setStrokeStyle(StrokeStyle style)
-{
-    m_state->strokeStyle = style;
-}
-
-void PlatformGraphicsContext::setStrokeThickness(float f)
-{
-    m_state->strokeThickness = f;
-}
-
-//**************************************
-// Paint setup
-//**************************************
-
-void PlatformGraphicsContext::setupPaintCommon(SkPaint* paint) const
-{
-    paint->setAntiAlias(m_state->useAA);
-    paint->setDither(true);
-    paint->setXfermodeMode(m_state->mode);
-    if (SkColorGetA(m_state->shadow.color) > 0) {
-
-        // Currently, only GraphicsContexts associated with the
-        // HTMLCanvasElement have shadows ignore transforms set.  This
-        // allows us to distinguish between CSS and Canvas shadows which
-        // have different rendering specifications.
-        SkScalar dy = m_state->shadow.dy;
-        uint32_t flags = SkBlurDrawLooper::kHighQuality_BlurFlag;
-        if (shadowsIgnoreTransforms()) {
-            dy = -dy;
-            flags |= SkBlurDrawLooper::kIgnoreTransform_BlurFlag;
-            flags |= SkBlurDrawLooper::kOverrideColor_BlurFlag;
-        }
-
-        SkDrawLooper* looper = new SkBlurDrawLooper(m_state->shadow.blur,
-                                                    m_state->shadow.dx,
-                                                    dy,
-                                                    m_state->shadow.color,
-                                                    flags);
-        paint->setLooper(looper)->unref();
-    }
-    paint->setFilterBitmap(true);
-}
-
-void PlatformGraphicsContext::setupPaintFill(SkPaint* paint) const
-{
-    this->setupPaintCommon(paint);
-    paint->setColor(m_state->applyAlpha(m_state->fillColor));
-    paint->setShader(m_state->fillShader);
-}
-
-bool PlatformGraphicsContext::setupPaintShadow(SkPaint* paint, SkPoint* offset) const
-{
-    return m_state->setupShadowPaint(paint, offset, shadowsIgnoreTransforms());
-}
-
-bool PlatformGraphicsContext::setupPaintStroke(SkPaint* paint, SkRect* rect,
-                                               bool isHLine)
-{
-    this->setupPaintCommon(paint);
-    paint->setColor(m_state->applyAlpha(m_state->strokeColor));
-    paint->setShader(m_state->strokeShader);
-
-    float width = m_state->strokeThickness;
-
-    // This allows dashing and dotting to work properly for hairline strokes
-    // FIXME: Should we only do this for dashed and dotted strokes?
-    if (!width)
-        width = 1;
-
-    paint->setStyle(SkPaint::kStroke_Style);
-    paint->setStrokeWidth(SkFloatToScalar(width));
-    paint->setStrokeCap(m_state->lineCap);
-    paint->setStrokeJoin(m_state->lineJoin);
-    paint->setStrokeMiter(SkFloatToScalar(m_state->miterLimit));
-
-    if (rect && (RoundToInt(width) & 1))
-        rect->inset(-SK_ScalarHalf, -SK_ScalarHalf);
-
-    SkPathEffect* pe = m_state->pathEffect;
-    if (pe) {
-        paint->setPathEffect(pe);
-        return false;
-    }
-    switch (m_state->strokeStyle) {
-    case NoStroke:
-    case SolidStroke:
-        width = 0;
-        break;
-    case DashedStroke:
-        width = m_state->dashRatio * width;
-        break;
-        // No break
-    case DottedStroke:
-        break;
-    }
-
-    if (width > 0) {
-        // Return true if we're basically a dotted dash of squares
-        bool justSqrs = RoundToInt(width) == RoundToInt(paint->getStrokeWidth());
-
-        if (justSqrs || !isHLine || !setBitmapDash(paint, width)) {
-#if 0
-            // this is slow enough that we just skip it for now
-            // see http://b/issue?id=4163023
-            SkScalar intervals[] = { width, width };
-            pe = new SkDashPathEffect(intervals, 2, 0);
-            paint->setPathEffect(pe)->unref();
-#endif
-        }
-        return justSqrs;
-    }
-    return false;
-}
-
-}   // WebCore
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.h
deleted file mode 100644
index 1916014..0000000
--- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContext.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright 2006, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef platform_graphics_context_h
-#define platform_graphics_context_h
-
-#include "IntRect.h"
-#include "GraphicsContext.h"
-#include "RenderSkinAndroid.h"
-#include "SkCanvas.h"
-#include "SkPicture.h"
-#include "SkTDArray.h"
-#include <wtf/Vector.h>
-
-class SkCanvas;
-
-namespace WebCore {
-
-class PlatformGraphicsContext {
-public:
-    PlatformGraphicsContext();
-    virtual ~PlatformGraphicsContext();
-    virtual bool isPaintingDisabled() = 0;
-    virtual SkCanvas* getCanvas() = 0;
-
-    void setGraphicsContext(GraphicsContext* gc) { m_gc = gc; }
-    virtual bool deleteUs() const { return false; }
-
-    typedef enum { PaintingContext, RecordingContext } ContextType;
-    virtual ContextType type() = 0;
-
-    // State management
-    virtual void beginTransparencyLayer(float opacity) = 0;
-    virtual void endTransparencyLayer() = 0;
-    virtual void save();
-    virtual void restore();
-
-    // State values
-    virtual void setAlpha(float alpha);
-    int getNormalizedAlpha() const;
-    virtual void setCompositeOperation(CompositeOperator op);
-    virtual void setFillColor(const Color& c);
-    virtual void setFillShader(SkShader* fillShader);
-    virtual void setLineCap(LineCap cap);
-    virtual void setLineDash(const DashArray& dashes, float dashOffset);
-    virtual void setLineJoin(LineJoin join);
-    virtual void setMiterLimit(float limit);
-    virtual void setShadow(int radius, int dx, int dy, SkColor c);
-    virtual void setShouldAntialias(bool useAA);
-    virtual void setStrokeColor(const Color& c);
-    virtual void setStrokeShader(SkShader* strokeShader);
-    virtual void setStrokeStyle(StrokeStyle style);
-    virtual void setStrokeThickness(float f);
-
-    // FIXME: These setupPaint* should be private, but
-    //        they are used by FontAndroid currently
-    virtual void setupPaintFill(SkPaint* paint) const;
-    virtual bool setupPaintShadow(SkPaint* paint, SkPoint* offset) const;
-    // Sets up the paint for stroking. Returns true if the style is really
-    // just a dash of squares (the size of the paint's stroke-width.
-    virtual bool setupPaintStroke(SkPaint* paint, SkRect* rect, bool isHLine = false);
-
-    // Matrix operations
-    virtual void concatCTM(const AffineTransform& affine) = 0;
-    virtual void rotate(float angleInRadians) = 0;
-    virtual void scale(const FloatSize& size) = 0;
-    virtual void translate(float x, float y) = 0;
-    virtual const SkMatrix& getTotalMatrix() = 0;
-
-    // Clipping
-    virtual void addInnerRoundedRectClip(const IntRect& rect, int thickness) = 0;
-    virtual void canvasClip(const Path& path) = 0;
-    virtual void clip(const FloatRect& rect) = 0;
-    virtual void clip(const Path& path) = 0;
-    virtual void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias) = 0;
-    virtual void clipOut(const IntRect& r) = 0;
-    virtual void clipOut(const Path& p) = 0;
-    virtual void clipPath(const Path& pathToClip, WindRule clipRule) = 0;
-
-    // Drawing
-    virtual void clearRect(const FloatRect& rect) = 0;
-    virtual void drawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix,
-                           CompositeOperator compositeOp, const FloatRect& destRect) = 0;
-    virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
-                        const SkRect& dst, CompositeOperator op) = 0;
-    virtual void drawConvexPolygon(size_t numPoints, const FloatPoint* points,
-                           bool shouldAntialias) = 0;
-    virtual void drawEllipse(const IntRect& rect) = 0;
-    virtual void drawFocusRing(const Vector<IntRect>& rects, int /* width */,
-                       int /* offset */, const Color& color) = 0;
-    virtual void drawHighlightForText(const Font& font, const TextRun& run,
-                              const FloatPoint& point, int h,
-                              const Color& backgroundColor, ColorSpace colorSpace,
-                              int from, int to, bool isActive) = 0;
-    virtual void drawLine(const IntPoint& point1, const IntPoint& point2) = 0;
-    virtual void drawLineForText(const FloatPoint& pt, float width) = 0;
-    virtual void drawLineForTextChecking(const FloatPoint& pt, float width,
-                                 GraphicsContext::TextCheckingLineStyle) = 0;
-    virtual void drawRect(const IntRect& rect) = 0;
-    virtual void fillPath(const Path& pathToFill, WindRule fillRule) = 0;
-    virtual void fillRect(const FloatRect& rect) = 0;
-    void fillRect(const FloatRect& rect, const Color& color, ColorSpace) {
-        fillRect(rect, color);
-    }
-    virtual void fillRect(const FloatRect& rect, const Color& color) = 0;
-    void fillRoundedRect(const IntRect& rect, const IntSize& topLeft,
-                         const IntSize& topRight, const IntSize& bottomLeft,
-                         const IntSize& bottomRight, const Color& color,
-                         ColorSpace) {
-        fillRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight, color);
-    }
-    virtual void fillRoundedRect(const IntRect& rect, const IntSize& topLeft,
-                         const IntSize& topRight, const IntSize& bottomLeft,
-                         const IntSize& bottomRight, const Color& color) = 0;
-    virtual void strokeArc(const IntRect& r, int startAngle, int angleSpan) = 0;
-    virtual void strokePath(const Path& pathToStroke) = 0;
-    virtual void strokeRect(const FloatRect& rect, float lineWidth) = 0;
-
-    virtual SkCanvas* recordingCanvas() = 0;
-    virtual void endRecording(int type = 0) = 0;
-
-protected:
-
-    struct ShadowRec {
-        SkScalar blur;
-        SkScalar dx;
-        SkScalar dy;
-        SkColor color;  // alpha>0 means valid shadow
-        ShadowRec(SkScalar b = 0,
-                  SkScalar x = 0,
-                  SkScalar y = 0,
-                  SkColor c = 0) // by default, alpha=0, so no shadow
-                : blur(b), dx(x), dy(y), color(c)
-            {};
-    };
-
-    class State {
-    public:
-        SkPathEffect* pathEffect;
-        float miterLimit;
-        float alpha;
-        float strokeThickness;
-        SkPaint::Cap lineCap;
-        SkPaint::Join lineJoin;
-        SkXfermode::Mode mode;
-        int dashRatio; // Ratio of the length of a dash to its width
-        ShadowRec shadow;
-        SkColor fillColor;
-        SkShader* fillShader;
-        SkColor strokeColor;
-        SkShader* strokeShader;
-        bool useAA;
-        StrokeStyle strokeStyle;
-
-        State();
-        State(const State& other);
-        ~State();
-
-        void setShadow(int radius, int dx, int dy, SkColor c);
-        bool setupShadowPaint(SkPaint* paint, SkPoint* offset,
-                              bool shadowsIgnoreTransforms);
-        SkColor applyAlpha(SkColor c) const;
-
-        State cloneInheritedProperties();
-    private:
-        // Not supported.
-        void operator=(const State&);
-
-        friend class PlatformGraphicsContextRecording;
-        friend class PlatformGraphicsContextSkia;
-    };
-
-    virtual bool shadowsIgnoreTransforms() const = 0;
-    void setupPaintCommon(SkPaint* paint) const;
-    GraphicsContext* m_gc; // Back-ptr to our parent
-
-    struct State;
-    WTF::Vector<State> m_stateStack;
-    State* m_state;
-};
-
-}
-#endif
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp
deleted file mode 100644
index d96124d..0000000
--- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.cpp
+++ /dev/null
@@ -1,373 +0,0 @@
-#define LOG_TAG "PlatformGraphicsContextRecording"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "PlatformGraphicsContextRecording.h"
-
-#include "AndroidLog.h"
-#include "Font.h"
-#include "GraphicsContext.h"
-#include "GraphicsOperationCollection.h"
-#include "GraphicsOperation.h"
-
-namespace WebCore {
-
-//**************************************
-// PlatformGraphicsContextRecording
-//**************************************
-
-PlatformGraphicsContextRecording::PlatformGraphicsContextRecording(GraphicsOperationCollection* picture)
-    : PlatformGraphicsContext()
-    , mGraphicsOperationCollection(picture)
-    , mPicture(0)
-{
-}
-
-bool PlatformGraphicsContextRecording::isPaintingDisabled()
-{
-    return !mGraphicsOperationCollection;
-}
-
-SkCanvas* PlatformGraphicsContextRecording::recordingCanvas()
-{
-    SkSafeUnref(mPicture);
-    mPicture = new SkPicture();
-    return mPicture->beginRecording(0, 0, 0);
-}
-
-void PlatformGraphicsContextRecording::endRecording(int type)
-{
-    if (!mPicture)
-        return;
-    mPicture->endRecording();
-    GraphicsOperation::DrawComplexText* text = new GraphicsOperation::DrawComplexText(mPicture);
-    mGraphicsOperationCollection->append(text);
-    mPicture = 0;
-}
-
-
-//**************************************
-// State management
-//**************************************
-
-void PlatformGraphicsContextRecording::beginTransparencyLayer(float opacity)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::BeginTransparencyLayer(opacity));
-}
-
-void PlatformGraphicsContextRecording::endTransparencyLayer()
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::EndTransparencyLayer());
-}
-
-void PlatformGraphicsContextRecording::save()
-{
-    PlatformGraphicsContext::save();
-    mGraphicsOperationCollection->append(new GraphicsOperation::Save());
-}
-
-void PlatformGraphicsContextRecording::restore()
-{
-    PlatformGraphicsContext::restore();
-    mGraphicsOperationCollection->append(new GraphicsOperation::Restore());
-}
-
-//**************************************
-// State setters
-//**************************************
-
-void PlatformGraphicsContextRecording::setAlpha(float alpha)
-{
-    PlatformGraphicsContext::setAlpha(alpha);
-    mGraphicsOperationCollection->append(new GraphicsOperation::SetAlpha(alpha));
-}
-
-void PlatformGraphicsContextRecording::setCompositeOperation(CompositeOperator op)
-{
-    PlatformGraphicsContext::setCompositeOperation(op);
-    mGraphicsOperationCollection->append(new GraphicsOperation::SetCompositeOperation(op));
-}
-
-void PlatformGraphicsContextRecording::setFillColor(const Color& c)
-{
-    PlatformGraphicsContext::setFillColor(c);
-    mGraphicsOperationCollection->append(new GraphicsOperation::SetFillColor(c));
-}
-
-void PlatformGraphicsContextRecording::setFillShader(SkShader* fillShader)
-{
-    PlatformGraphicsContext::setFillShader(fillShader);
-    mGraphicsOperationCollection->append(new GraphicsOperation::SetFillShader(fillShader));
-}
-
-void PlatformGraphicsContextRecording::setLineCap(LineCap cap)
-{
-    PlatformGraphicsContext::setLineCap(cap);
-    mGraphicsOperationCollection->append(new GraphicsOperation::SetLineCap(cap));
-}
-
-void PlatformGraphicsContextRecording::setLineDash(const DashArray& dashes, float dashOffset)
-{
-    PlatformGraphicsContext::setLineDash(dashes, dashOffset);
-    mGraphicsOperationCollection->append(new GraphicsOperation::SetLineDash(dashes, dashOffset));
-}
-
-void PlatformGraphicsContextRecording::setLineJoin(LineJoin join)
-{
-    PlatformGraphicsContext::setLineJoin(join);
-    mGraphicsOperationCollection->append(new GraphicsOperation::SetLineJoin(join));
-}
-
-void PlatformGraphicsContextRecording::setMiterLimit(float limit)
-{
-    PlatformGraphicsContext::setMiterLimit(limit);
-    mGraphicsOperationCollection->append(new GraphicsOperation::SetMiterLimit(limit));
-}
-
-void PlatformGraphicsContextRecording::setShadow(int radius, int dx, int dy, SkColor c)
-{
-    PlatformGraphicsContext::setShadow(radius, dx, dy, c);
-    mGraphicsOperationCollection->append(new GraphicsOperation::SetShadow(radius, dx, dy, c));
-}
-
-void PlatformGraphicsContextRecording::setShouldAntialias(bool useAA)
-{
-    m_state->useAA = useAA;
-    PlatformGraphicsContext::setShouldAntialias(useAA);
-    mGraphicsOperationCollection->append(new GraphicsOperation::SetShouldAntialias(useAA));
-}
-
-void PlatformGraphicsContextRecording::setStrokeColor(const Color& c)
-{
-    PlatformGraphicsContext::setStrokeColor(c);
-    mGraphicsOperationCollection->append(new GraphicsOperation::SetStrokeColor(c));
-}
-
-void PlatformGraphicsContextRecording::setStrokeShader(SkShader* strokeShader)
-{
-    PlatformGraphicsContext::setStrokeShader(strokeShader);
-    mGraphicsOperationCollection->append(new GraphicsOperation::SetStrokeShader(strokeShader));
-}
-
-void PlatformGraphicsContextRecording::setStrokeStyle(StrokeStyle style)
-{
-    PlatformGraphicsContext::setStrokeStyle(style);
-    mGraphicsOperationCollection->append(new GraphicsOperation::SetStrokeStyle(style));
-}
-
-void PlatformGraphicsContextRecording::setStrokeThickness(float f)
-{
-    PlatformGraphicsContext::setStrokeThickness(f);
-    mGraphicsOperationCollection->append(new GraphicsOperation::SetStrokeThickness(f));
-}
-
-//**************************************
-// Matrix operations
-//**************************************
-
-void PlatformGraphicsContextRecording::concatCTM(const AffineTransform& affine)
-{
-    mCurrentMatrix.preConcat(affine);
-    mGraphicsOperationCollection->append(new GraphicsOperation::ConcatCTM(affine));
-}
-
-void PlatformGraphicsContextRecording::rotate(float angleInRadians)
-{
-    float value = angleInRadians * (180.0f / 3.14159265f);
-    mCurrentMatrix.preRotate(SkFloatToScalar(value));
-    mGraphicsOperationCollection->append(new GraphicsOperation::Rotate(angleInRadians));
-}
-
-void PlatformGraphicsContextRecording::scale(const FloatSize& size)
-{
-    mCurrentMatrix.preScale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height()));
-    mGraphicsOperationCollection->append(new GraphicsOperation::Scale(size));
-}
-
-void PlatformGraphicsContextRecording::translate(float x, float y)
-{
-    mCurrentMatrix.preTranslate(SkFloatToScalar(x), SkFloatToScalar(y));
-    mGraphicsOperationCollection->append(new GraphicsOperation::Translate(x, y));
-}
-
-const SkMatrix& PlatformGraphicsContextRecording::getTotalMatrix()
-{
-    return mCurrentMatrix;
-}
-
-//**************************************
-// Clipping
-//**************************************
-
-void PlatformGraphicsContextRecording::addInnerRoundedRectClip(const IntRect& rect,
-                                                      int thickness)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::InnerRoundedRectClip(rect, thickness));
-}
-
-void PlatformGraphicsContextRecording::canvasClip(const Path& path)
-{
-    clip(path);
-}
-
-void PlatformGraphicsContextRecording::clip(const FloatRect& rect)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::Clip(rect));
-}
-
-void PlatformGraphicsContextRecording::clip(const Path& path)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::ClipPath(path));
-}
-
-void PlatformGraphicsContextRecording::clipConvexPolygon(size_t numPoints,
-                                                const FloatPoint*, bool antialias)
-{
-    // TODO
-}
-
-void PlatformGraphicsContextRecording::clipOut(const IntRect& r)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::ClipOut(r));
-}
-
-void PlatformGraphicsContextRecording::clipOut(const Path& path)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::ClipPath(path, true));
-}
-
-void PlatformGraphicsContextRecording::clipPath(const Path& pathToClip, WindRule clipRule)
-{
-    GraphicsOperation::ClipPath* operation = new GraphicsOperation::ClipPath(pathToClip);
-    operation->setWindRule(clipRule);
-    mGraphicsOperationCollection->append(operation);
-}
-
-void PlatformGraphicsContextRecording::clearRect(const FloatRect& rect)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::ClearRect(rect));
-}
-
-//**************************************
-// Drawing
-//**************************************
-
-void PlatformGraphicsContextRecording::drawBitmapPattern(
-        const SkBitmap& bitmap, const SkMatrix& matrix,
-        CompositeOperator compositeOp, const FloatRect& destRect)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::DrawBitmapPattern(bitmap, matrix, compositeOp, destRect));
-}
-
-void PlatformGraphicsContextRecording::drawBitmapRect(const SkBitmap& bitmap,
-                                   const SkIRect* src, const SkRect& dst,
-                                   CompositeOperator op)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::DrawBitmapRect(bitmap, *src, dst, op));
-}
-
-void PlatformGraphicsContextRecording::drawConvexPolygon(size_t numPoints,
-                                                const FloatPoint* points,
-                                                bool shouldAntialias)
-{
-    // TODO
-}
-
-void PlatformGraphicsContextRecording::drawEllipse(const IntRect& rect)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::DrawEllipse(rect));
-}
-
-void PlatformGraphicsContextRecording::drawFocusRing(const Vector<IntRect>& rects,
-                                            int /* width */, int /* offset */,
-                                            const Color& color)
-{
-    // TODO
-}
-
-void PlatformGraphicsContextRecording::drawHighlightForText(
-        const Font& font, const TextRun& run, const FloatPoint& point, int h,
-        const Color& backgroundColor, ColorSpace colorSpace, int from,
-        int to, bool isActive)
-{
-    IntRect rect = (IntRect)font.selectionRectForText(run, point, h, from, to);
-    if (isActive)
-        fillRect(rect, backgroundColor);
-    else {
-        int x = rect.x(), y = rect.y(), w = rect.width(), h = rect.height();
-        const int t = 3, t2 = t * 2;
-
-        fillRect(IntRect(x, y, w, t), backgroundColor);
-        fillRect(IntRect(x, y+h-t, w, t), backgroundColor);
-        fillRect(IntRect(x, y+t, t, h-t2), backgroundColor);
-        fillRect(IntRect(x+w-t, y+t, t, h-t2), backgroundColor);
-    }
-}
-
-void PlatformGraphicsContextRecording::drawLine(const IntPoint& point1,
-                             const IntPoint& point2)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::DrawLine(point1, point2));
-}
-
-void PlatformGraphicsContextRecording::drawLineForText(const FloatPoint& pt, float width)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::DrawLineForText(pt, width));
-}
-
-void PlatformGraphicsContextRecording::drawLineForTextChecking(const FloatPoint& pt,
-        float width, GraphicsContext::TextCheckingLineStyle lineStyle)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::DrawLineForTextChecking(pt, width, lineStyle));
-}
-
-void PlatformGraphicsContextRecording::drawRect(const IntRect& rect)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::DrawRect(rect));
-}
-
-void PlatformGraphicsContextRecording::fillPath(const Path& pathToFill, WindRule fillRule)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::FillPath(pathToFill, fillRule));
-}
-
-void PlatformGraphicsContextRecording::fillRect(const FloatRect& rect)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::FillRect(rect));
-}
-
-void PlatformGraphicsContextRecording::fillRect(const FloatRect& rect,
-                                       const Color& color)
-{
-    GraphicsOperation::FillRect* operation = new GraphicsOperation::FillRect(rect);
-    operation->setColor(color);
-    mGraphicsOperationCollection->append(operation);
-}
-
-void PlatformGraphicsContextRecording::fillRoundedRect(
-        const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
-        const IntSize& bottomLeft, const IntSize& bottomRight,
-        const Color& color)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::FillRoundedRect(rect, topLeft,
-                 topRight, bottomLeft, bottomRight, color));
-}
-
-void PlatformGraphicsContextRecording::strokeArc(const IntRect& r, int startAngle,
-                              int angleSpan)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::StrokeArc(r, startAngle, angleSpan));
-}
-
-void PlatformGraphicsContextRecording::strokePath(const Path& pathToStroke)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::StrokePath(pathToStroke));
-}
-
-void PlatformGraphicsContextRecording::strokeRect(const FloatRect& rect, float lineWidth)
-{
-    mGraphicsOperationCollection->append(new GraphicsOperation::StrokeRect(rect, lineWidth));
-}
-
-
-}   // WebCore
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h
deleted file mode 100644
index ebb0075..0000000
--- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextRecording.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef platform_graphics_context_recording_h
-#define platform_graphics_context_recording_h
-
-#include "PlatformGraphicsContext.h"
-
-namespace WebCore {
-class GraphicsOperationCollection;
-
-class PlatformGraphicsContextRecording : public PlatformGraphicsContext {
-public:
-    PlatformGraphicsContextRecording(GraphicsOperationCollection* picture);
-    virtual ~PlatformGraphicsContextRecording() {}
-    virtual bool isPaintingDisabled();
-    virtual SkCanvas* getCanvas() { return 0; }
-
-    GraphicsOperationCollection* mGraphicsOperationCollection;
-    SkMatrix mCurrentMatrix;
-
-    virtual SkCanvas* recordingCanvas();
-    virtual void endRecording(int type = 0);
-
-    virtual ContextType type() { return RecordingContext; }
-
-    // State management
-    virtual void beginTransparencyLayer(float opacity);
-    virtual void endTransparencyLayer();
-    virtual void save();
-    virtual void restore();
-
-    // State values
-    virtual void setAlpha(float alpha);
-    virtual void setCompositeOperation(CompositeOperator op);
-    virtual void setFillColor(const Color& c);
-    virtual void setFillShader(SkShader* fillShader);
-    virtual void setLineCap(LineCap cap);
-    virtual void setLineDash(const DashArray& dashes, float dashOffset);
-    virtual void setLineJoin(LineJoin join);
-    virtual void setMiterLimit(float limit);
-    virtual void setShadow(int radius, int dx, int dy, SkColor c);
-    virtual void setShouldAntialias(bool useAA);
-    virtual void setStrokeColor(const Color& c);
-    virtual void setStrokeShader(SkShader* strokeShader);
-    virtual void setStrokeStyle(StrokeStyle style);
-    virtual void setStrokeThickness(float f);
-
-    // Matrix operations
-    virtual void concatCTM(const AffineTransform& affine);
-    virtual void rotate(float angleInRadians);
-    virtual void scale(const FloatSize& size);
-    virtual void translate(float x, float y);
-    virtual const SkMatrix& getTotalMatrix();
-
-    // Clipping
-    virtual void addInnerRoundedRectClip(const IntRect& rect, int thickness);
-    virtual void canvasClip(const Path& path);
-    virtual void clip(const FloatRect& rect);
-    virtual void clip(const Path& path);
-    virtual void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias);
-    virtual void clipOut(const IntRect& r);
-    virtual void clipOut(const Path& p);
-    virtual void clipPath(const Path& pathToClip, WindRule clipRule);
-
-    // Drawing
-    virtual void clearRect(const FloatRect& rect);
-    virtual void drawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix,
-                           CompositeOperator compositeOp, const FloatRect& destRect);
-    virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
-                        const SkRect& dst, CompositeOperator op);
-    virtual void drawConvexPolygon(size_t numPoints, const FloatPoint* points,
-                           bool shouldAntialias);
-    virtual void drawEllipse(const IntRect& rect);
-    virtual void drawFocusRing(const Vector<IntRect>& rects, int /* width */,
-                       int /* offset */, const Color& color);
-    virtual void drawHighlightForText(const Font& font, const TextRun& run,
-                              const FloatPoint& point, int h,
-                              const Color& backgroundColor, ColorSpace colorSpace,
-                              int from, int to, bool isActive);
-    virtual void drawLine(const IntPoint& point1, const IntPoint& point2);
-    virtual void drawLineForText(const FloatPoint& pt, float width);
-    virtual void drawLineForTextChecking(const FloatPoint& pt, float width,
-                                 GraphicsContext::TextCheckingLineStyle);
-    virtual void drawRect(const IntRect& rect);
-    virtual void fillPath(const Path& pathToFill, WindRule fillRule);
-    virtual void fillRect(const FloatRect& rect);
-    virtual void fillRect(const FloatRect& rect, const Color& color);
-    virtual void fillRoundedRect(const IntRect& rect, const IntSize& topLeft,
-                         const IntSize& topRight, const IntSize& bottomLeft,
-                         const IntSize& bottomRight, const Color& color);
-    virtual void strokeArc(const IntRect& r, int startAngle, int angleSpan);
-    virtual void strokePath(const Path& pathToStroke);
-    virtual void strokeRect(const FloatRect& rect, float lineWidth);
-
-private:
-
-    virtual bool shadowsIgnoreTransforms() const {
-        return false;
-    }
-
-    SkPicture* mPicture;
-};
-
-}
-#endif
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.cpp b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.cpp
deleted file mode 100644
index f00bb02..0000000
--- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.cpp
+++ /dev/null
@@ -1,608 +0,0 @@
-#define LOG_TAG "PlatformGraphicsContextSkia"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "PlatformGraphicsContextSkia.h"
-
-#include "AndroidLog.h"
-#include "Font.h"
-#include "GraphicsContext.h"
-#include "SkCanvas.h"
-#include "SkCornerPathEffect.h"
-#include "SkPaint.h"
-#include "SkShader.h"
-#include "SkiaUtils.h"
-
-namespace WebCore {
-
-// These are the flags we need when we call saveLayer for transparency.
-// Since it does not appear that webkit intends this to also save/restore
-// the matrix or clip, I do not give those flags (for performance)
-#define TRANSPARENCY_SAVEFLAGS                                  \
-    (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag |   \
-                          SkCanvas::kFullColorLayer_SaveFlag)
-
-//**************************************
-// Helper functions
-//**************************************
-
-static void setrectForUnderline(SkRect* r, float lineThickness,
-                                const FloatPoint& point, int yOffset, float width)
-{
-#if 0
-    if (lineThickness < 1) // Do we really need/want this?
-        lineThickness = 1;
-#endif
-    r->fLeft    = point.x();
-    r->fTop     = point.y() + yOffset;
-    r->fRight   = r->fLeft + width;
-    r->fBottom  = r->fTop + lineThickness;
-}
-
-static inline int fastMod(int value, int max)
-{
-    int sign = SkExtractSign(value);
-
-    value = SkApplySign(value, sign);
-    if (value >= max)
-        value %= max;
-    return SkApplySign(value, sign);
-}
-
-static inline void fixPaintForBitmapsThatMaySeam(SkPaint* paint) {
-    /*  Bitmaps may be drawn to seem next to other images. If we are drawn
-        zoomed, or at fractional coordinates, we may see cracks/edges if
-        we antialias, because that will cause us to draw the same pixels
-        more than once (e.g. from the left and right bitmaps that share
-        an edge).
-
-        Disabling antialiasing fixes this, and since so far we are never
-        rotated at non-multiple-of-90 angles, this seems to do no harm
-     */
-    paint->setAntiAlias(false);
-}
-
-//**************************************
-// PlatformGraphicsContextSkia
-//**************************************
-
-PlatformGraphicsContextSkia::PlatformGraphicsContextSkia(SkCanvas* canvas,
-                                                         bool takeCanvasOwnership)
-    : PlatformGraphicsContext()
-    , mCanvas(canvas)
-    , m_deleteCanvas(takeCanvasOwnership)
-{
-    m_gc = 0;
-}
-
-PlatformGraphicsContextSkia::~PlatformGraphicsContextSkia()
-{
-    if (m_deleteCanvas)
-        delete mCanvas;
-}
-
-bool PlatformGraphicsContextSkia::isPaintingDisabled()
-{
-    return !mCanvas;
-}
-
-//**************************************
-// State management
-//**************************************
-
-void PlatformGraphicsContextSkia::beginTransparencyLayer(float opacity)
-{
-    SkCanvas* canvas = mCanvas;
-    canvas->saveLayerAlpha(0, (int)(opacity * 255), TRANSPARENCY_SAVEFLAGS);
-}
-
-void PlatformGraphicsContextSkia::endTransparencyLayer()
-{
-    if (!mCanvas)
-        return;
-    mCanvas->restore();
-}
-
-void PlatformGraphicsContextSkia::save()
-{
-    PlatformGraphicsContext::save();
-    // Save our native canvas.
-    mCanvas->save();
-}
-
-void PlatformGraphicsContextSkia::restore()
-{
-    PlatformGraphicsContext::restore();
-    // Restore our native canvas.
-    mCanvas->restore();
-}
-
-//**************************************
-// Matrix operations
-//**************************************
-
-void PlatformGraphicsContextSkia::concatCTM(const AffineTransform& affine)
-{
-    mCanvas->concat(affine);
-}
-
-void PlatformGraphicsContextSkia::rotate(float angleInRadians)
-{
-    float value = angleInRadians * (180.0f / 3.14159265f);
-    mCanvas->rotate(SkFloatToScalar(value));
-}
-
-void PlatformGraphicsContextSkia::scale(const FloatSize& size)
-{
-    mCanvas->scale(SkFloatToScalar(size.width()), SkFloatToScalar(size.height()));
-}
-
-void PlatformGraphicsContextSkia::translate(float x, float y)
-{
-    mCanvas->translate(SkFloatToScalar(x), SkFloatToScalar(y));
-}
-
-const SkMatrix& PlatformGraphicsContextSkia::getTotalMatrix()
-{
-    return mCanvas->getTotalMatrix();
-}
-
-//**************************************
-// Clipping
-//**************************************
-
-void PlatformGraphicsContextSkia::addInnerRoundedRectClip(const IntRect& rect,
-                                                      int thickness)
-{
-    SkPath path;
-    SkRect r(rect);
-
-    path.addOval(r, SkPath::kCW_Direction);
-    // Only perform the inset if we won't invert r
-    if (2 * thickness < rect.width() && 2 * thickness < rect.height()) {
-        // Adding one to the thickness doesn't make the border too thick as
-        // it's painted over afterwards. But without this adjustment the
-        // border appears a little anemic after anti-aliasing.
-        r.inset(SkIntToScalar(thickness + 1), SkIntToScalar(thickness + 1));
-        path.addOval(r, SkPath::kCCW_Direction);
-    }
-    mCanvas->clipPath(path, SkRegion::kIntersect_Op, true);
-}
-
-void PlatformGraphicsContextSkia::canvasClip(const Path& path)
-{
-    clip(path);
-}
-
-void PlatformGraphicsContextSkia::clip(const FloatRect& rect)
-{
-    mCanvas->clipRect(rect);
-}
-
-void PlatformGraphicsContextSkia::clip(const Path& path)
-{
-    mCanvas->clipPath(*path.platformPath(), SkRegion::kIntersect_Op, true);
-}
-
-void PlatformGraphicsContextSkia::clipConvexPolygon(size_t numPoints,
-                                                const FloatPoint*, bool antialias)
-{
-    if (numPoints <= 1)
-        return;
-
-    // This is only used if HAVE_PATH_BASED_BORDER_RADIUS_DRAWING is defined
-    // in RenderObject.h which it isn't for us. TODO: Support that :)
-}
-
-void PlatformGraphicsContextSkia::clipOut(const IntRect& r)
-{
-    mCanvas->clipRect(r, SkRegion::kDifference_Op);
-}
-
-void PlatformGraphicsContextSkia::clipOut(const Path& path)
-{
-    mCanvas->clipPath(*path.platformPath(), SkRegion::kDifference_Op);
-}
-
-void PlatformGraphicsContextSkia::clipPath(const Path& pathToClip, WindRule clipRule)
-{
-    SkPath path = *pathToClip.platformPath();
-    path.setFillType(clipRule == RULE_EVENODD
-            ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
-    mCanvas->clipPath(path);
-}
-void PlatformGraphicsContextSkia::clearRect(const FloatRect& rect)
-{
-    SkPaint paint;
-
-    setupPaintFill(&paint);
-    paint.setXfermodeMode(SkXfermode::kClear_Mode);
-
-    mCanvas->drawRect(rect, paint);
-}
-
-//**************************************
-// Drawing
-//**************************************
-
-void PlatformGraphicsContextSkia::drawBitmapPattern(
-        const SkBitmap& bitmap, const SkMatrix& matrix,
-        CompositeOperator compositeOp, const FloatRect& destRect)
-{
-    SkShader* shader = SkShader::CreateBitmapShader(bitmap,
-                                                    SkShader::kRepeat_TileMode,
-                                                    SkShader::kRepeat_TileMode);
-    shader->setLocalMatrix(matrix);
-    SkPaint paint;
-    setupPaintCommon(&paint);
-    paint.setAlpha(getNormalizedAlpha());
-    paint.setShader(shader);
-    paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(compositeOp));
-    fixPaintForBitmapsThatMaySeam(&paint);
-    mCanvas->drawRect(destRect, paint);
-}
-
-void PlatformGraphicsContextSkia::drawBitmapRect(const SkBitmap& bitmap,
-                                             const SkIRect* src, const SkRect& dst,
-                                             CompositeOperator op)
-{
-    SkPaint paint;
-    setupPaintCommon(&paint);
-    paint.setAlpha(getNormalizedAlpha());
-    paint.setXfermodeMode(WebCoreCompositeToSkiaComposite(op));
-    fixPaintForBitmapsThatMaySeam(&paint);
-
-    mCanvas->drawBitmapRect(bitmap, src, dst, &paint);
-}
-
-void PlatformGraphicsContextSkia::drawConvexPolygon(size_t numPoints,
-                                                const FloatPoint* points,
-                                                bool shouldAntialias)
-{
-    if (numPoints <= 1)
-        return;
-
-    SkPaint paint;
-    SkPath path;
-
-    path.incReserve(numPoints);
-    path.moveTo(SkFloatToScalar(points[0].x()), SkFloatToScalar(points[0].y()));
-    for (size_t i = 1; i < numPoints; i++)
-        path.lineTo(SkFloatToScalar(points[i].x()), SkFloatToScalar(points[i].y()));
-
-    if (mCanvas->quickReject(path, shouldAntialias ?
-            SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType)) {
-        return;
-    }
-
-    if (m_state->fillColor & 0xFF000000) {
-        setupPaintFill(&paint);
-        paint.setAntiAlias(shouldAntialias);
-        mCanvas->drawPath(path, paint);
-    }
-
-    if (m_state->strokeStyle != NoStroke) {
-        paint.reset();
-        setupPaintStroke(&paint, 0);
-        paint.setAntiAlias(shouldAntialias);
-        mCanvas->drawPath(path, paint);
-    }
-}
-
-void PlatformGraphicsContextSkia::drawEllipse(const IntRect& rect)
-{
-    SkPaint paint;
-    SkRect oval(rect);
-
-    if (m_state->fillColor & 0xFF000000) {
-        setupPaintFill(&paint);
-        mCanvas->drawOval(oval, paint);
-    }
-    if (m_state->strokeStyle != NoStroke) {
-        paint.reset();
-        setupPaintStroke(&paint, &oval);
-        mCanvas->drawOval(oval, paint);
-    }
-}
-
-void PlatformGraphicsContextSkia::drawFocusRing(const Vector<IntRect>& rects,
-                                            int /* width */, int /* offset */,
-                                            const Color& color)
-{
-    unsigned rectCount = rects.size();
-    if (!rectCount)
-        return;
-
-    SkRegion focusRingRegion;
-    const SkScalar focusRingOutset = WebCoreFloatToSkScalar(0.8);
-    for (unsigned i = 0; i < rectCount; i++) {
-        SkIRect r = rects[i];
-        r.inset(-focusRingOutset, -focusRingOutset);
-        focusRingRegion.op(r, SkRegion::kUnion_Op);
-    }
-
-    SkPath path;
-    SkPaint paint;
-    paint.setAntiAlias(true);
-    paint.setStyle(SkPaint::kStroke_Style);
-
-    paint.setColor(color.rgb());
-    paint.setStrokeWidth(focusRingOutset * 2);
-    paint.setPathEffect(new SkCornerPathEffect(focusRingOutset * 2))->unref();
-    focusRingRegion.getBoundaryPath(&path);
-    mCanvas->drawPath(path, paint);
-}
-
-void PlatformGraphicsContextSkia::drawHighlightForText(
-        const Font& font, const TextRun& run, const FloatPoint& point, int h,
-        const Color& backgroundColor, ColorSpace colorSpace, int from,
-        int to, bool isActive)
-{
-    IntRect rect = (IntRect)font.selectionRectForText(run, point, h, from, to);
-    if (isActive)
-        fillRect(rect, backgroundColor);
-    else {
-        int x = rect.x(), y = rect.y(), w = rect.width(), h = rect.height();
-        const int t = 3, t2 = t * 2;
-
-        fillRect(IntRect(x, y, w, t), backgroundColor);
-        fillRect(IntRect(x, y+h-t, w, t), backgroundColor);
-        fillRect(IntRect(x, y+t, t, h-t2), backgroundColor);
-        fillRect(IntRect(x+w-t, y+t, t, h-t2), backgroundColor);
-    }
-}
-
-void PlatformGraphicsContextSkia::drawLine(const IntPoint& point1,
-                                       const IntPoint& point2)
-{
-    StrokeStyle style = m_state->strokeStyle;
-    if (style == NoStroke)
-        return;
-
-    SkPaint paint;
-    SkCanvas* canvas = mCanvas;
-    const int idx = SkAbs32(point2.x() - point1.x());
-    const int idy = SkAbs32(point2.y() - point1.y());
-
-    // Special-case horizontal and vertical lines that are really just dots
-    if (setupPaintStroke(&paint, 0, !idy) && (!idx || !idy)) {
-        const SkScalar diameter = paint.getStrokeWidth();
-        const SkScalar radius = SkScalarHalf(diameter);
-        SkScalar x = SkIntToScalar(SkMin32(point1.x(), point2.x()));
-        SkScalar y = SkIntToScalar(SkMin32(point1.y(), point2.y()));
-        SkScalar dx, dy;
-        int count;
-        SkRect bounds;
-
-        if (!idy) { // Horizontal
-            bounds.set(x, y - radius, x + SkIntToScalar(idx), y + radius);
-            x += radius;
-            dx = diameter * 2;
-            dy = 0;
-            count = idx;
-        } else { // Vertical
-            bounds.set(x - radius, y, x + radius, y + SkIntToScalar(idy));
-            y += radius;
-            dx = 0;
-            dy = diameter * 2;
-            count = idy;
-        }
-
-        // The actual count is the number of ONs we hit alternating
-        // ON(diameter), OFF(diameter), ...
-        {
-            SkScalar width = SkScalarDiv(SkIntToScalar(count), diameter);
-            // Now compute the number of cells (ON and OFF)
-            count = SkScalarRound(width);
-            // Now compute the number of ONs
-            count = (count + 1) >> 1;
-        }
-
-        SkAutoMalloc storage(count * sizeof(SkPoint));
-        SkPoint* verts = (SkPoint*)storage.get();
-        // Now build the array of vertices to past to drawPoints
-        for (int i = 0; i < count; i++) {
-            verts[i].set(x, y);
-            x += dx;
-            y += dy;
-        }
-
-        paint.setStyle(SkPaint::kFill_Style);
-        paint.setPathEffect(0);
-
-        // Clipping to bounds is not required for correctness, but it does
-        // allow us to reject the entire array of points if we are completely
-        // offscreen. This is common in a webpage for android, where most of
-        // the content is clipped out. If drawPoints took an (optional) bounds
-        // parameter, that might even be better, as we would *just* use it for
-        // culling, and not both wacking the canvas' save/restore stack.
-        canvas->save(SkCanvas::kClip_SaveFlag);
-        canvas->clipRect(bounds);
-        canvas->drawPoints(SkCanvas::kPoints_PointMode, count, verts, paint);
-        canvas->restore();
-    } else {
-        SkPoint pts[2] = { point1, point2 };
-        canvas->drawLine(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, paint);
-    }
-}
-
-void PlatformGraphicsContextSkia::drawLineForText(const FloatPoint& pt, float width)
-{
-    SkRect r;
-    setrectForUnderline(&r, m_state->strokeThickness, pt, 0, width);
-
-    SkPaint paint;
-    paint.setAntiAlias(true);
-    paint.setColor(m_state->strokeColor);
-
-    mCanvas->drawRect(r, paint);
-}
-
-void PlatformGraphicsContextSkia::drawLineForTextChecking(const FloatPoint& pt,
-        float width, GraphicsContext::TextCheckingLineStyle)
-{
-    // TODO: Should we draw different based on TextCheckingLineStyle?
-    SkRect r;
-    setrectForUnderline(&r, m_state->strokeThickness, pt, 0, width);
-
-    SkPaint paint;
-    paint.setAntiAlias(true);
-    paint.setColor(SK_ColorRED); // Is this specified somewhere?
-
-    mCanvas->drawRect(r, paint);
-}
-
-void PlatformGraphicsContextSkia::drawRect(const IntRect& rect)
-{
-    SkPaint paint;
-    SkRect r(rect);
-
-    if (m_state->fillColor & 0xFF000000) {
-        setupPaintFill(&paint);
-        mCanvas->drawRect(r, paint);
-    }
-
-    // According to GraphicsContext.h, stroking inside drawRect always means
-    // a stroke of 1 inside the rect.
-    if (m_state->strokeStyle != NoStroke && (m_state->strokeColor & 0xFF000000)) {
-        paint.reset();
-        setupPaintStroke(&paint, &r);
-        paint.setPathEffect(0); // No dashing please
-        paint.setStrokeWidth(SK_Scalar1); // Always just 1.0 width
-        r.inset(SK_ScalarHalf, SK_ScalarHalf); // Ensure we're "inside"
-        mCanvas->drawRect(r, paint);
-    }
-}
-
-void PlatformGraphicsContextSkia::fillPath(const Path& pathToFill, WindRule fillRule)
-{
-    SkPath* path = pathToFill.platformPath();
-    if (!path)
-        return;
-
-    switch (fillRule) {
-    case RULE_NONZERO:
-        path->setFillType(SkPath::kWinding_FillType);
-        break;
-    case RULE_EVENODD:
-        path->setFillType(SkPath::kEvenOdd_FillType);
-        break;
-    }
-
-    SkPaint paint;
-    setupPaintFill(&paint);
-
-    mCanvas->drawPath(*path, paint);
-}
-
-void PlatformGraphicsContextSkia::fillRect(const FloatRect& rect)
-{
-    SkPaint paint;
-    setupPaintFill(&paint);
-    mCanvas->drawRect(rect, paint);
-}
-
-void PlatformGraphicsContextSkia::fillRect(const FloatRect& rect,
-                                       const Color& color)
-{
-    if (color.rgb() & 0xFF000000) {
-        SkPaint paint;
-
-        setupPaintCommon(&paint);
-        paint.setColor(color.rgb()); // Punch in the specified color
-        paint.setShader(0); // In case we had one set
-
-        // Sometimes we record and draw portions of the page, using clips
-        // for each portion. The problem with this is that webkit, sometimes,
-        // sees that we're only recording a portion, and they adjust some of
-        // their rectangle coordinates accordingly (e.g.
-        // RenderBoxModelObject::paintFillLayerExtended() which calls
-        // rect.intersect(paintInfo.rect) and then draws the bg with that
-        // rect. The result is that we end up drawing rects that are meant to
-        // seam together (one for each portion), but if the rects have
-        // fractional coordinates (e.g. we are zoomed by a fractional amount)
-        // we will double-draw those edges, resulting in visual cracks or
-        // artifacts.
-
-        // The fix seems to be to just turn off antialasing for rects (this
-        // entry-point in GraphicsContext seems to have been sufficient,
-        // though perhaps we'll find we need to do this as well in fillRect(r)
-        // as well.) Currently setupPaintCommon() enables antialiasing.
-
-        // Since we never show the page rotated at a funny angle, disabling
-        // antialiasing seems to have no real down-side, and it does fix the
-        // bug when we're zoomed (and drawing portions that need to seam).
-        paint.setAntiAlias(false);
-
-        mCanvas->drawRect(rect, paint);
-    }
-}
-
-void PlatformGraphicsContextSkia::fillRoundedRect(
-        const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
-        const IntSize& bottomLeft, const IntSize& bottomRight,
-        const Color& color)
-{
-    SkPaint paint;
-    SkPath path;
-    SkScalar radii[8];
-
-    radii[0] = SkIntToScalar(topLeft.width());
-    radii[1] = SkIntToScalar(topLeft.height());
-    radii[2] = SkIntToScalar(topRight.width());
-    radii[3] = SkIntToScalar(topRight.height());
-    radii[4] = SkIntToScalar(bottomRight.width());
-    radii[5] = SkIntToScalar(bottomRight.height());
-    radii[6] = SkIntToScalar(bottomLeft.width());
-    radii[7] = SkIntToScalar(bottomLeft.height());
-    path.addRoundRect(rect, radii);
-
-    setupPaintFill(&paint);
-    paint.setColor(color.rgb());
-    mCanvas->drawPath(path, paint);
-}
-
-void PlatformGraphicsContextSkia::strokeArc(const IntRect& r, int startAngle,
-                                        int angleSpan)
-{
-    SkPath path;
-    SkPaint paint;
-    SkRect oval(r);
-
-    if (m_state->strokeStyle == NoStroke) {
-        setupPaintFill(&paint); // We want the fill color
-        paint.setStyle(SkPaint::kStroke_Style);
-        paint.setStrokeWidth(SkFloatToScalar(m_state->strokeThickness));
-    } else
-        setupPaintStroke(&paint, 0);
-
-    // We do this before converting to scalar, so we don't overflow SkFixed
-    startAngle = fastMod(startAngle, 360);
-    angleSpan = fastMod(angleSpan, 360);
-
-    path.addArc(oval, SkIntToScalar(-startAngle), SkIntToScalar(-angleSpan));
-    mCanvas->drawPath(path, paint);
-}
-
-void PlatformGraphicsContextSkia::strokePath(const Path& pathToStroke)
-{
-    const SkPath* path = pathToStroke.platformPath();
-    if (!path)
-        return;
-
-    SkPaint paint;
-    setupPaintStroke(&paint, 0);
-
-    mCanvas->drawPath(*path, paint);
-}
-
-void PlatformGraphicsContextSkia::strokeRect(const FloatRect& rect, float lineWidth)
-{
-    SkPaint paint;
-
-    setupPaintStroke(&paint, 0);
-    paint.setStrokeWidth(SkFloatToScalar(lineWidth));
-    mCanvas->drawRect(rect, paint);
-}
-
-}   // WebCore
diff --git a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.h b/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.h
deleted file mode 100644
index 724e20b..0000000
--- a/Source/WebCore/platform/graphics/android/context/PlatformGraphicsContextSkia.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef platform_graphics_context_skia_h
-#define platform_graphics_context_skia_h
-
-#include "PlatformGraphicsContext.h"
-
-namespace WebCore {
-
-class PlatformGraphicsContextSkia : public PlatformGraphicsContext {
-public:
-    PlatformGraphicsContextSkia(SkCanvas* canvas, bool takeCanvasOwnership = false);
-    virtual ~PlatformGraphicsContextSkia();
-    virtual bool isPaintingDisabled();
-    virtual SkCanvas* getCanvas() { return mCanvas; }
-
-    virtual ContextType type() { return PaintingContext; }
-    virtual SkCanvas* recordingCanvas() { return mCanvas; }
-    virtual void endRecording(int type = 0) {}
-
-    // FIXME: This is used by ImageBufferAndroid, which should really be
-    //        managing the canvas lifecycle itself
-
-    virtual bool deleteUs() const { return m_deleteCanvas; }
-
-    // State management
-    virtual void beginTransparencyLayer(float opacity);
-    virtual void endTransparencyLayer();
-    virtual void save();
-    virtual void restore();
-
-    // Matrix operations
-    virtual void concatCTM(const AffineTransform& affine);
-    virtual void rotate(float angleInRadians);
-    virtual void scale(const FloatSize& size);
-    virtual void translate(float x, float y);
-    virtual const SkMatrix& getTotalMatrix();
-
-    // Clipping
-    virtual void addInnerRoundedRectClip(const IntRect& rect, int thickness);
-    virtual void canvasClip(const Path& path);
-    virtual void clip(const FloatRect& rect);
-    virtual void clip(const Path& path);
-    virtual void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias);
-    virtual void clipOut(const IntRect& r);
-    virtual void clipOut(const Path& p);
-    virtual void clipPath(const Path& pathToClip, WindRule clipRule);
-
-    // Drawing
-    virtual void clearRect(const FloatRect& rect);
-    virtual void drawBitmapPattern(const SkBitmap& bitmap, const SkMatrix& matrix,
-                           CompositeOperator compositeOp, const FloatRect& destRect);
-    virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
-                        const SkRect& dst, CompositeOperator op);
-    virtual void drawConvexPolygon(size_t numPoints, const FloatPoint* points,
-                           bool shouldAntialias);
-    virtual void drawEllipse(const IntRect& rect);
-    virtual void drawFocusRing(const Vector<IntRect>& rects, int /* width */,
-                       int /* offset */, const Color& color);
-    virtual void drawHighlightForText(const Font& font, const TextRun& run,
-                              const FloatPoint& point, int h,
-                              const Color& backgroundColor, ColorSpace colorSpace,
-                              int from, int to, bool isActive);
-    virtual void drawLine(const IntPoint& point1, const IntPoint& point2);
-    virtual void drawLineForText(const FloatPoint& pt, float width);
-    virtual void drawLineForTextChecking(const FloatPoint& pt, float width,
-                                 GraphicsContext::TextCheckingLineStyle);
-    virtual void drawRect(const IntRect& rect);
-    virtual void fillPath(const Path& pathToFill, WindRule fillRule);
-    virtual void fillRect(const FloatRect& rect);
-    virtual void fillRect(const FloatRect& rect, const Color& color);
-    virtual void fillRoundedRect(const IntRect& rect, const IntSize& topLeft,
-                         const IntSize& topRight, const IntSize& bottomLeft,
-                         const IntSize& bottomRight, const Color& color);
-    virtual void strokeArc(const IntRect& r, int startAngle, int angleSpan);
-    virtual void strokePath(const Path& pathToStroke);
-    virtual void strokeRect(const FloatRect& rect, float lineWidth);
-
-private:
-
-    // shadowsIgnoreTransforms is only true for canvas's ImageBuffer, which will
-    // have a GraphicsContext
-    virtual bool shadowsIgnoreTransforms() const {
-        return m_gc && m_gc->shadowsIgnoreTransforms();
-    }
-
-    SkCanvas* mCanvas;
-    bool m_deleteCanvas;
-};
-
-}
-#endif
diff --git a/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp
deleted file mode 100644
index 87d6486..0000000
--- a/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.cpp
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "BaseLayerAndroid"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "BaseLayerAndroid.h"
-
-#include "AndroidLog.h"
-#include "CachedImage.h"
-#include "ClassTracker.h"
-#include "DrawQuadData.h"
-#include "FixedPositioning.h"
-#include "GLWebViewState.h"
-#include "ImagesManager.h"
-#include "LayerContent.h"
-#include "RenderStyle.h"
-#include "StyleCachedImage.h"
-#include "TilesManager.h"
-
-namespace WebCore {
-
-// Note: this must match the use of ID 0 specifying the base layer in DrawExtra
-#define BASE_UNIQUE_ID 0
-
-BaseLayerAndroid::BaseLayerAndroid(LayerContent* content)
-    : LayerAndroid((RenderLayer*)0)
-    , m_color(Color::white)
-    , m_positionsCalculated(false)
-{
-    if (content) {
-        setContent(content);
-        setSize(content->width(), content->height());
-    }
-    m_uniqueId = BASE_UNIQUE_ID;
-}
-
-void BaseLayerAndroid::getLocalTransform(SkMatrix* matrix) const
-{
-    matrix->reset();
-    // base layer doesn't use size in transform calculation
-    matrix->preConcat(getMatrix());
-}
-
-IFrameLayerAndroid* BaseLayerAndroid::updatePosition(SkRect viewport,
-                                                     IFrameLayerAndroid* parentIframeLayer)
-{
-    if (viewport.fRight > getWidth() || viewport.fBottom > getHeight()) {
-        // To handle the viewport expanding past the layer's size with HW accel,
-        // expand the size of the layer, so that tiles will cover the viewport.
-        setSize(std::max(viewport.fRight, getWidth()),
-                std::max(viewport.fBottom, getHeight()));
-    }
-
-    return LayerAndroid::updatePosition(viewport, parentIframeLayer);
-}
-
-void BaseLayerAndroid::updatePositionsRecursive(const SkRect& visibleContentRect)
-{
-    TRACE_METHOD();
-
-    updateLayerPositions(visibleContentRect);
-    TransformationMatrix ident;
-
-    // Start with an unnecessarily large clip, since the base layer can
-    // dynamically increase in size to cover the viewport, and we cache its draw
-    // clip. This way the base layer will never have it's visible area clipped
-    // by its m_clippingRect, only the viewport.
-    // Note: values larger than this suffer from floating point rounding issues
-    FloatRect clip(0, 0, 1e7, 1e7);
-
-    bool forcePositionCalculation = !m_positionsCalculated;
-    float scale = 1.0f;
-    // To minimize tearing in single surface mode, don't update the fixed element
-    // when scrolling. The fixed element will move incorrectly when scrolling,
-    // but its position will be corrected after scrolling.
-    bool disableFixedElemUpdate = false;
-    GLWebViewState* webViewState = state();
-    if (webViewState) {
-        scale = webViewState->scale();
-        disableFixedElemUpdate = webViewState->isScrolling()
-                                 && webViewState->isSingleSurfaceRenderingMode();
-    }
-    updateGLPositionsAndScale(ident, clip, 1, scale, forcePositionCalculation,
-                              disableFixedElemUpdate);
-
-    m_positionsCalculated = true;
-}
-
-ForegroundBaseLayerAndroid::ForegroundBaseLayerAndroid(LayerContent* content)
-    : LayerAndroid((RenderLayer*)0)
-{
-    setIntrinsicallyComposited(true);
-}
-
-FixedBackgroundImageLayerAndroid::FixedBackgroundImageLayerAndroid(PassRefPtr<RenderStyle> aStyle,
-                                                                   int w, int h)
-    : LayerAndroid((RenderLayer*)0)
-    , m_width(w)
-    , m_height(h)
-{
-    RefPtr<RenderStyle> style = aStyle;
-    FillLayer* layers = style->accessBackgroundLayers();
-    StyleImage* styleImage = layers->image();
-    CachedImage* cachedImage = static_cast<StyleCachedImage*>(styleImage)->cachedImage();
-    WebCore::Image* image = cachedImage->image();
-    setContentsImage(image->nativeImageForCurrentFrame());
-    setSize(image->width(), image->height());
-
-    setIntrinsicallyComposited(true);
-
-    SkLength left, top;
-    left = SkLength::convertLength(style->backgroundXPosition());
-    top = SkLength::convertLength(style->backgroundYPosition());
-
-    BackgroundImagePositioning* position = new BackgroundImagePositioning(this);
-    position->setRepeatX(style->backgroundRepeatX() != WebCore::NoRepeatFill);
-    position->setRepeatY(style->backgroundRepeatY() != WebCore::NoRepeatFill);
-
-    setFixedPosition(position);
-    position->setPosition(left, top);
-
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->increment("FixedBackgroundImageLayerAndroid");
-#endif
-}
-
-FixedBackgroundImageLayerAndroid::FixedBackgroundImageLayerAndroid(const FixedBackgroundImageLayerAndroid& layer)
-    : LayerAndroid(layer)
-    , m_width(layer.m_width)
-    , m_height(layer.m_height)
-{
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->increment("FixedBackgroundImageLayerAndroid");
-#endif
-}
-
-FixedBackgroundImageLayerAndroid::~FixedBackgroundImageLayerAndroid()
-{
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->decrement("FixedBackgroundImageLayerAndroid");
-#endif
-}
-
-static bool needToDisplayImage(bool repeatX, bool repeatY, float dx, float dy)
-{
-    // handles the repeat attribute for the background image
-    if (repeatX && repeatY)
-        return true;
-    if (repeatX && !repeatY && dy == 0)
-        return true;
-    if (!repeatX && repeatY && dx == 0)
-        return true;
-    if (dx == 0 && dy == 0)
-        return true;
-
-    return false;
-}
-
-// Return true when fast draw succeeds.
-// For the repeated image content, we just need to draw a single quad and use
-// the GL shader to repeat.
-bool FixedBackgroundImageLayerAndroid::drawSimpleQuad(ImageTexture* imageTexture,
-                                                      BackgroundImagePositioning* position,
-                                                      const IntPoint& repeatTimes,
-                                                      const FloatPoint& startPoint,
-                                                      const FloatPoint& origin,
-                                                      const Color& backgroundColor)
-{
-    // The limitation for current implementation is that we can only speed up
-    // single tile size image.
-    // TODO: add the fast path to imageTexture which contains >1 tiles.
-    GLuint imageTextureId = imageTexture->getImageTextureId();
-    if (!imageTextureId)
-        return false;
-
-    int nbX = repeatTimes.x();
-    int nbY = repeatTimes.y();
-    float startX = startPoint.x();
-    float startY = startPoint.y();
-    bool repeatX = position->repeatX();
-    bool repeatY = position->repeatY();
-
-    // Draw the entire background when repeat only in one direction or no repeat.
-    if (!repeatX || !repeatY) {
-        SkRect backgroundRect;
-        backgroundRect.fLeft = origin.x() - startX;
-        backgroundRect.fTop = origin.y() - startY;
-        backgroundRect.fRight = backgroundRect.fLeft + getWidth() * nbX;
-        backgroundRect.fBottom = backgroundRect.fTop + getHeight() * nbY;
-        PureColorQuadData backgroundData(backgroundColor, BaseQuad,
-                                         0, &backgroundRect, 1.0, true);
-        TilesManager::instance()->shader()->drawQuad(&backgroundData);
-    }
-
-    // Now draw the repeated images.
-    // We set the quad size as the image size, then imageRepeatRanges will
-    // control how many times the image will be repeated by expanding the
-    // quad and texture coordinates.
-    // The image size can be smaller than a tile, so repeatScale will passed
-    // into the shader to scale the texture coordinates.
-    SkRect imageRect = SkRect::MakeXYWH(0, 0, getWidth(), getHeight());
-    FloatRect imageRepeatRanges(0, 0, repeatX ? nbX : 1, repeatY ? nbY : 1);
-
-    FloatSize repeatScale(float(getWidth()) / TilesManager::tileWidth(),
-                          float(getHeight()) / TilesManager::tileHeight());
-
-    ALOGV("repeatedQuadData: startX %f, startY %f , getWidth() %f, getHeight() %f,"
-          " nbX %d, nbY %d, repeatImageTimesX, repeatImageTimesY %d %d"
-          " repeatScale width %f, height %f, origin x %f y %f",
-          startX , startY  , getWidth(), getHeight(), nbX , nbY,
-          imageRepeatRanges.width(), imageRepeatRanges.height(),
-          repeatScale.width(), repeatScale.height(), origin.x(), origin.y());
-
-    // Adding startX and startY into the transform can handle the fixed right /
-    // fixed bottom case.
-    TransformationMatrix matrix = *drawTransform();
-    matrix.translate(repeatX ? -startX : 0, repeatY ? -startY : 0);
-
-    TextureQuadData repeatedQuadData(imageTextureId, GL_TEXTURE_2D, GL_LINEAR,
-                                     LayerQuad, &matrix, &imageRect, getOpacity(),
-                                     true, imageRepeatRanges, repeatScale);
-    TilesManager::instance()->shader()->drawQuad(&repeatedQuadData);
-    return true;
-}
-
-void FixedBackgroundImageLayerAndroid::drawRepeatedGrid(ImageTexture* imageTexture,
-                                                        BackgroundImagePositioning* position,
-                                                        const IntPoint& repeatTimes,
-                                                        const FloatPoint& startPoint,
-                                                        const FloatPoint& origin,
-                                                        const Color& backgroundColor)
-{
-    // Cover the entire background
-    int nbX = repeatTimes.x();
-    int nbY = repeatTimes.y();
-    float startX = startPoint.x();
-    float startY = startPoint.y();
-    for (int i = 0; i < nbY; i++) {
-        float dy = (i * getHeight()) - startY;
-        for (int j = 0; j < nbX; j++) {
-            float dx = (j * getWidth()) - startX;
-            if (needToDisplayImage(position->repeatX(),
-                                   position->repeatY(),
-                                   dx, dy)) {
-                FloatPoint p(dx, dy);
-                imageTexture->drawGL(this, getOpacity(), &p);
-            } else {
-                // If the image is not displayed, we still need to fill
-                // with the background color
-                SkRect rect;
-                rect.fLeft = origin.x() + dx;
-                rect.fTop = origin.y() + dy;
-                rect.fRight = rect.fLeft + getWidth();
-                rect.fBottom = rect.fTop + getHeight();
-                PureColorQuadData backgroundData(backgroundColor, BaseQuad,
-                                                 0, &rect, 1.0);
-                TilesManager::instance()->shader()->drawQuad(&backgroundData);
-            }
-        }
-    }
-}
-
-bool FixedBackgroundImageLayerAndroid::drawGL(bool layerTilesDisabled)
-{
-    if (layerTilesDisabled)
-        return false;
-    if (!m_imageCRC)
-        return false;
-
-    ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC);
-    if (!imageTexture) {
-        ImagesManager::instance()->releaseImage(m_imageCRC);
-        return false;
-    }
-
-    // We have a fixed background image, let's draw it
-    if (m_fixedPosition && m_fixedPosition->isBackgroundImagePositioning()) {
-        BackgroundImagePositioning* position =
-            static_cast<BackgroundImagePositioning*>(m_fixedPosition);
-
-        IntPoint repeatTimes(position->nbRepeatX(), position->nbRepeatY());
-        FloatPoint startPoint(position->offsetX() * getWidth(),
-                              position->offsetY() * getHeight());
-
-        FloatPoint origin;
-        origin = drawTransform()->mapPoint(origin);
-
-        Color backgroundColor = Color((int)SkColorGetR(m_backgroundColor),
-                                      (int)SkColorGetG(m_backgroundColor),
-                                      (int)SkColorGetB(m_backgroundColor),
-                                      (int)SkColorGetA(m_backgroundColor));
-
-        bool drawSimpleQuadSuccess = drawSimpleQuad(imageTexture, position,
-                                                    repeatTimes, startPoint,
-                                                    origin, backgroundColor);
-
-        if (!drawSimpleQuadSuccess) {
-            drawRepeatedGrid(imageTexture, position, repeatTimes, startPoint,
-                             origin, backgroundColor);
-        }
-    } else
-        imageTexture->drawGL(this, getOpacity());
-
-    ImagesManager::instance()->releaseImage(m_imageCRC);
-
-    return false;
-}
-
-Image* FixedBackgroundImageLayerAndroid::GetCachedImage(PassRefPtr<RenderStyle> aStyle)
-{
-    RefPtr<RenderStyle> style = aStyle;
-    if (!style)
-        return 0;
-
-    if (!style->hasFixedBackgroundImage())
-        return 0;
-
-    FillLayer* layers = style->accessBackgroundLayers();
-    StyleImage* styleImage = layers->image();
-
-    if (!styleImage)
-        return 0;
-
-    if (!styleImage->isLoaded())
-        return 0;
-
-    if (!styleImage->isCachedImage())
-        return 0;
-
-    CachedImage* cachedImage = static_cast<StyleCachedImage*>(styleImage)->cachedImage();
-
-    Image* image = cachedImage->image();
-
-    if (image && !image->nativeImageForCurrentFrame())
-        return 0;
-
-    if (image == Image::nullImage())
-        return 0;
-
-    return image;
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.h
deleted file mode 100644
index 06aa21b..0000000
--- a/Source/WebCore/platform/graphics/android/layers/BaseLayerAndroid.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef BaseLayerAndroid_h
-#define BaseLayerAndroid_h
-
-#include "Color.h"
-#include "LayerAndroid.h"
-
-namespace WebCore {
-
-class Image;
-class RenderLayerCompositor;
-class RenderStyle;
-class BackgroundImagePositioning;
-
-class BaseLayerAndroid : public LayerAndroid {
-public:
-    BaseLayerAndroid(LayerContent* content);
-    virtual SubclassType subclassType() const { return LayerAndroid::BaseLayer; }
-    virtual void getLocalTransform(SkMatrix* matrix) const;
-    virtual const TransformationMatrix* drawTransform() const { return 0; }
-    virtual bool needsTexture() { return content(); }
-    virtual IFrameLayerAndroid* updatePosition(SkRect viewport,
-                                               IFrameLayerAndroid* parentIframeLayer);
-    void updatePositionsRecursive(const SkRect& visibleContentRect);
-    void setBackgroundColor(Color& color) { m_color = color; }
-    Color getBackgroundColor() { return m_color; }
-
-private:
-    // TODO: move to SurfaceCollection.
-    Color m_color;
-    bool m_positionsCalculated;
-};
-
-class ForegroundBaseLayerAndroid : public LayerAndroid {
-public:
-    ForegroundBaseLayerAndroid(LayerContent* content);
-    virtual SubclassType subclassType() const { return LayerAndroid::ForegroundBaseLayer; }
-
-    virtual bool needsTexture() { return false; }
-};
-
-class FixedBackgroundImageLayerAndroid : public LayerAndroid {
-public:
-    FixedBackgroundImageLayerAndroid(PassRefPtr<RenderStyle> style, int w, int h);
-    FixedBackgroundImageLayerAndroid(const FixedBackgroundImageLayerAndroid& layer);
-    virtual ~FixedBackgroundImageLayerAndroid();
-    virtual LayerAndroid* copy() const { return new FixedBackgroundImageLayerAndroid(*this); }
-    virtual bool needsTexture() { return true; }
-    virtual SubclassType subclassType() const { return LayerAndroid::FixedBackgroundImageLayer; }
-    virtual bool drawGL(bool layerTilesDisabled);
-    static Image* GetCachedImage(PassRefPtr<RenderStyle> style);
-
-private:
-    bool drawSimpleQuad(ImageTexture* imageTexture,
-                        BackgroundImagePositioning* position,
-                        const IntPoint& repeatTimes, const FloatPoint& startPoint,
-                        const FloatPoint& origin, const Color& backgroundColor);
-    void drawRepeatedGrid(ImageTexture* imageTexture,
-                          BackgroundImagePositioning* position,
-                          const IntPoint& repeatTimes, const FloatPoint& startPoint,
-                          const FloatPoint& origin, const Color& backgroundColor);
-    int m_width;
-    int m_height;
-};
-
-} // namespace WebCore
-
-#endif //BaseLayerAndroid_h
diff --git a/Source/WebCore/platform/graphics/android/layers/CanvasLayer.cpp b/Source/WebCore/platform/graphics/android/layers/CanvasLayer.cpp
deleted file mode 100644
index 4a7f161..0000000
--- a/Source/WebCore/platform/graphics/android/layers/CanvasLayer.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "CanvasLayer"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "CanvasLayer.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "AndroidLog.h"
-#include "CanvasTexture.h"
-#include "DrawQuadData.h"
-#include "Image.h"
-#include "ImageBuffer.h"
-#include "RenderLayerCompositor.h"
-#include "SkBitmap.h"
-#include "SkBitmapRef.h"
-#include "SkCanvas.h"
-#include "TilesManager.h"
-
-namespace WebCore {
-
-CanvasLayer::CanvasLayer(RenderLayer* owner, HTMLCanvasElement* canvas)
-    : LayerAndroid(owner)
-    , m_canvas(canvas)
-    , m_dirtyCanvas()
-    , m_bitmap(0)
-{
-    init();
-    m_canvas->addObserver(this);
-    // Make sure we initialize in case the canvas has already been laid out
-    canvasResized(m_canvas);
-}
-
-CanvasLayer::CanvasLayer(const CanvasLayer& layer)
-    : LayerAndroid(layer)
-    , m_canvas(0)
-    , m_bitmap(0)
-{
-    init();
-    if (!layer.m_canvas) {
-        // The canvas has already been destroyed - this shouldn't happen
-        ALOGW("Creating a CanvasLayer for a destroyed canvas!");
-        m_visibleContentRect = IntRect();
-        m_offsetFromRenderer = IntSize();
-        m_texture->setHwAccelerated(false);
-        return;
-    }
-    // We are making a copy for the UI, sync the interesting bits
-    m_visibleContentRect = layer.visibleContentRect();
-    m_offsetFromRenderer = layer.offsetFromRenderer();
-    bool previousState = m_texture->hasValidTexture();
-    if (!previousState && layer.m_dirtyCanvas.isEmpty()) {
-        // We were previously in software and don't have anything new to draw,
-        // so stay in software
-        m_bitmap = layer.bitmap();
-        SkSafeRef(m_bitmap);
-    } else {
-        // Attempt to upload to a surface texture
-        if (!m_texture->uploadImageBuffer(layer.m_canvas->buffer())) {
-            // Blargh, no surface texture or ImageBuffer - fall back to software
-            m_bitmap = layer.bitmap();
-            SkSafeRef(m_bitmap);
-            // Merge the canvas invals with the layer's invals to repaint the needed
-            // tiles.
-            SkRegion::Iterator iter(layer.m_dirtyCanvas);
-            const IntPoint& offset = m_visibleContentRect.location();
-            for (; !iter.done(); iter.next()) {
-                SkIRect diff = iter.rect();
-                diff.fLeft += offset.x();
-                diff.fRight += offset.x();
-                diff.fTop += offset.y();
-                diff.fBottom += offset.y();
-                m_dirtyRegion.op(diff, SkRegion::kUnion_Op);
-            }
-        }
-        if (previousState != m_texture->hasValidTexture()) {
-            // Need to do a full inval of the canvas content as we are mode switching
-            m_dirtyRegion.op(m_visibleContentRect.x(), m_visibleContentRect.y(),
-                    m_visibleContentRect.maxX(), m_visibleContentRect.maxY(), SkRegion::kUnion_Op);
-        }
-    }
-}
-
-CanvasLayer::~CanvasLayer()
-{
-    if (m_canvas)
-        m_canvas->removeObserver(this);
-    SkSafeUnref(m_bitmap);
-}
-
-void CanvasLayer::init()
-{
-    m_texture = CanvasTexture::getCanvasTexture(this);
-}
-
-void CanvasLayer::canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect)
-{
-    if (!m_texture->hasValidTexture()) {
-        // We only need to track invals if we aren't using a SurfaceTexture.
-        // If we drop out of hwa, we will do a full inval anyway
-        SkIRect irect = SkIRect::MakeXYWH(changedRect.x(), changedRect.y(),
-                                          changedRect.width(), changedRect.height());
-        m_dirtyCanvas.op(irect, SkRegion::kUnion_Op);
-    }
-    owningLayer()->compositor()->scheduleLayerFlush();
-}
-
-void CanvasLayer::canvasResized(HTMLCanvasElement*)
-{
-    const IntSize& size = m_canvas->size();
-    m_dirtyCanvas.setRect(0, 0, size.width(), size.height());
-    // If we are smaller than one tile, don't bother using a surface texture
-    if (size.width() <= TilesManager::tileWidth()
-            && size.height() <= TilesManager::tileHeight())
-        m_texture->setSize(IntSize());
-    else
-        m_texture->setSize(size);
-}
-
-void CanvasLayer::canvasDestroyed(HTMLCanvasElement*)
-{
-    m_canvas = 0;
-}
-
-void CanvasLayer::clearDirtyRegion()
-{
-    LayerAndroid::clearDirtyRegion();
-    m_dirtyCanvas.setEmpty();
-    if (m_canvas)
-        m_canvas->clearDirtyRect();
-}
-
-SkBitmapRef* CanvasLayer::bitmap() const
-{
-    if (!m_canvas || !m_canvas->buffer())
-        return 0;
-    return m_canvas->copiedImage()->nativeImageForCurrentFrame();
-}
-
-IntRect CanvasLayer::visibleContentRect() const
-{
-    if (!m_canvas
-            || !m_canvas->renderer()
-            || !m_canvas->renderer()->style()
-            || !m_canvas->inDocument()
-            || m_canvas->renderer()->style()->visibility() != VISIBLE)
-        return IntRect();
-    return m_canvas->renderBox()->contentBoxRect();
-}
-
-IntSize CanvasLayer::offsetFromRenderer() const
-{
-    return m_canvas->renderBox()->layer()->backing()->graphicsLayer()->offsetFromRenderer();
-}
-
-bool CanvasLayer::needsTexture()
-{
-    return (m_bitmap && !masksToBounds()) || LayerAndroid::needsTexture();
-}
-
-void CanvasLayer::contentDraw(SkCanvas* canvas, PaintStyle style)
-{
-    LayerAndroid::contentDraw(canvas, style);
-    if (!m_bitmap || masksToBounds())
-        return;
-    SkBitmap& bitmap = m_bitmap->bitmap();
-    SkRect dst = SkRect::MakeXYWH(m_visibleContentRect.x() - m_offsetFromRenderer.width(),
-                                  m_visibleContentRect.y() - m_offsetFromRenderer.height(),
-                                  m_visibleContentRect.width(), m_visibleContentRect.height());
-    canvas->drawBitmapRect(bitmap, 0, dst, 0);
-}
-
-bool CanvasLayer::drawGL(bool layerTilesDisabled)
-{
-    bool ret = LayerAndroid::drawGL(layerTilesDisabled);
-    m_texture->requireTexture();
-    if (!m_bitmap && m_texture->updateTexImage()) {
-        SkRect rect = SkRect::MakeXYWH(m_visibleContentRect.x() - m_offsetFromRenderer.width(),
-                                       m_visibleContentRect.y() - m_offsetFromRenderer.height(),
-                                       m_visibleContentRect.width(), m_visibleContentRect.height());
-        TextureQuadData data(m_texture->texture(), GL_TEXTURE_EXTERNAL_OES,
-                             GL_LINEAR, LayerQuad, &m_drawTransform, &rect);
-        TilesManager::instance()->shader()->drawQuad(&data);
-    }
-    return ret;
-}
-
-LayerAndroid::InvalidateFlags CanvasLayer::onSetHwAccelerated(bool hwAccelerated)
-{
-    if (m_texture->setHwAccelerated(hwAccelerated))
-        return LayerAndroid::InvalidateLayers;
-    return LayerAndroid::InvalidateNone;
-}
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/layers/CanvasLayer.h b/Source/WebCore/platform/graphics/android/layers/CanvasLayer.h
deleted file mode 100644
index fce6453..0000000
--- a/Source/WebCore/platform/graphics/android/layers/CanvasLayer.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CanvasLayer_h
-#define CanvasLayer_h
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "HTMLCanvasElement.h"
-#include "ImageData.h"
-#include "LayerAndroid.h"
-#include "RenderLayer.h"
-
-#include <wtf/RefPtr.h>
-
-namespace WebCore {
-
-class CanvasTexture;
-
-class CanvasLayer : public LayerAndroid, private CanvasObserver {
-public:
-    CanvasLayer(RenderLayer* owner, HTMLCanvasElement* canvas);
-    CanvasLayer(const CanvasLayer& layer);
-    virtual ~CanvasLayer();
-
-    virtual LayerAndroid* copy() const { return new CanvasLayer(*this); }
-    virtual SubclassType subclassType() const { return LayerAndroid::CanvasLayer; }
-    virtual void clearDirtyRegion();
-
-    virtual bool drawGL(bool layerTilesDisabled);
-    virtual void contentDraw(SkCanvas* canvas, PaintStyle style);
-    virtual bool needsTexture();
-    virtual bool needsIsolatedSurface() { return true; }
-
-protected:
-    virtual InvalidateFlags onSetHwAccelerated(bool hwAccelerated);
-
-private:
-    virtual void canvasChanged(HTMLCanvasElement*, const FloatRect& changedRect);
-    virtual void canvasResized(HTMLCanvasElement*);
-    virtual void canvasDestroyed(HTMLCanvasElement*);
-
-    void init();
-    SkBitmapRef* bitmap() const;
-    IntRect visibleContentRect() const;
-    IntSize offsetFromRenderer() const;
-
-    HTMLCanvasElement* m_canvas;
-    IntRect m_visibleContentRect;
-    IntSize m_offsetFromRenderer;
-    SkRegion m_dirtyCanvas;
-    SkBitmapRef* m_bitmap;
-    RefPtr<CanvasTexture> m_texture;
-};
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
-
-#endif // CanvasLayer_h
diff --git a/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp
deleted file mode 100644
index e4b2bc6..0000000
--- a/Source/WebCore/platform/graphics/android/layers/CanvasTexture.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "CanvasTexture"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "CanvasTexture.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "android_graphics.h"
-#include "AndroidLog.h"
-#include "GLUtils.h"
-#include "Image.h"
-#include "ImageBuffer.h"
-#include "SkBitmap.h"
-#include "SkBitmapRef.h"
-#include "SkDevice.h"
-#include "SkPixelRef.h"
-
-#include <android/native_window.h>
-#include <gui/SurfaceTexture.h>
-#include <gui/SurfaceTextureClient.h>
-
-namespace WebCore {
-
-static int s_maxTextureSize = 0;
-static HashMap<int, CanvasTexture*> s_textures;
-static android::Mutex s_texturesLock;
-
-/********************************************
- * Called by both threads
- ********************************************/
-
-PassRefPtr<CanvasTexture> CanvasTexture::getCanvasTexture(CanvasLayer* layer)
-{
-    android::Mutex::Autolock lock(s_texturesLock);
-    RefPtr<CanvasTexture> texture = s_textures.get(layer->uniqueId());
-    if (texture.get())
-        return texture.release();
-    return adoptRef(new CanvasTexture(layer->uniqueId()));
-}
-
-bool CanvasTexture::setHwAccelerated(bool hwAccelerated)
-{
-    android::Mutex::Autolock lock(m_surfaceLock);
-    if (m_useHwAcceleration == hwAccelerated)
-        return false;
-    m_useHwAcceleration = hwAccelerated;
-    if (!m_ANW.get())
-        return false;
-    destroySurfaceTextureLocked();
-    return true;
-}
-
-/********************************************
- * Called by WebKit thread
- ********************************************/
-
-void CanvasTexture::setSize(const IntSize& size)
-{
-    android::Mutex::Autolock lock(m_surfaceLock);
-    if (m_size == size)
-        return;
-    m_size = size;
-    if (m_ANW.get()) {
-        if (useSurfaceTexture()) {
-            int result = native_window_set_buffers_dimensions(m_ANW.get(),
-                    m_size.width(), m_size.height());
-            GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result);
-            if (result != NO_ERROR)
-                m_useHwAcceleration = false; // On error, drop out of HWA
-        }
-        if (!useSurfaceTexture())
-            destroySurfaceTextureLocked();
-    }
-}
-
-SurfaceTextureClient* CanvasTexture::nativeWindow()
-{
-    android::Mutex::Autolock lock(m_surfaceLock);
-    if (m_ANW.get())
-        return m_ANW.get();
-    if (!m_texture)
-        return 0;
-    if (!useSurfaceTexture())
-        return 0;
-    m_surfaceTexture = new android::SurfaceTexture(m_texture, false);
-    m_ANW = new android::SurfaceTextureClient(m_surfaceTexture);
-    int result = native_window_set_buffers_format(m_ANW.get(), HAL_PIXEL_FORMAT_RGBA_8888);
-    GLUtils::checkSurfaceTextureError("native_window_set_buffers_format", result);
-    if (result == NO_ERROR) {
-        result = native_window_set_buffers_dimensions(m_ANW.get(),
-                m_size.width(), m_size.height());
-        GLUtils::checkSurfaceTextureError("native_window_set_buffers_dimensions", result);
-    }
-    if (result != NO_ERROR) {
-        m_useHwAcceleration = false;
-        destroySurfaceTextureLocked();
-        return 0;
-    }
-    return m_ANW.get();
-}
-
-bool CanvasTexture::uploadImageBuffer(ImageBuffer* imageBuffer)
-{
-    m_hasValidTexture = false;
-    SurfaceTextureClient* anw = nativeWindow();
-    if (!anw)
-        return false;
-    // Size mismatch, early abort (will fall back to software)
-    if (imageBuffer->size() != m_size)
-        return false;
-    GraphicsContext* gc = imageBuffer ? imageBuffer->context() : 0;
-    if (!gc)
-        return false;
-    const SkBitmap& bitmap = android_gc2canvas(gc)->getDevice()->accessBitmap(false);
-    if (!GLUtils::updateSharedSurfaceTextureWithBitmap(anw, bitmap))
-        return false;
-    m_hasValidTexture = true;
-    return true;
-}
-
-/********************************************
- * Called by UI thread WITH GL context
- ********************************************/
-
-CanvasTexture::~CanvasTexture()
-{
-    if (m_layerId) {
-        s_texturesLock.lock();
-        s_textures.remove(m_layerId);
-        s_texturesLock.unlock();
-    }
-    if (m_texture)
-        GLUtils::deleteTexture(&m_texture);
-}
-
-void CanvasTexture::requireTexture()
-{
-    android::Mutex::Autolock lock(m_surfaceLock);
-    if (!m_texture)
-        glGenTextures(1, &m_texture);
-    if (!s_maxTextureSize)
-        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &s_maxTextureSize);
-}
-
-bool CanvasTexture::updateTexImage()
-{
-    android::Mutex::Autolock lock(m_surfaceLock);
-    if (!m_surfaceTexture.get())
-        return false;
-    status_t result = m_surfaceTexture->updateTexImage();
-    if (result != OK) {
-        ALOGE("unexpected error: updateTexImage return %d", result);
-        return false;
-    }
-    return true;
-}
-
-/********************************************
- * Called by both threads
- ********************************************/
-
-void CanvasTexture::destroySurfaceTextureLocked()
-{
-    if (m_ANW.get()) {
-        m_ANW.clear();
-        m_surfaceTexture->abandon();
-        m_surfaceTexture.clear();
-    }
-}
-
-/********************************************
- * Called by WebKit thread
- ********************************************/
-
-CanvasTexture::CanvasTexture(int layerId)
-    : m_size()
-    , m_layerId(layerId)
-    , m_texture(0)
-    , m_surfaceTexture(0)
-    , m_ANW(0)
-    , m_hasValidTexture(false)
-    , m_useHwAcceleration(true)
-{
-    s_textures.add(m_layerId, this);
-}
-
-// TODO: Have a global limit as well as a way to react to low memory situations
-bool CanvasTexture::useSurfaceTexture()
-{
-    if (!m_useHwAcceleration)
-        return false;
-    if (m_size.isEmpty())
-        return false;
-    return (m_size.width() < s_maxTextureSize) && (m_size.height() < s_maxTextureSize);
-}
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/layers/CanvasTexture.h b/Source/WebCore/platform/graphics/android/layers/CanvasTexture.h
deleted file mode 100644
index 98962a0..0000000
--- a/Source/WebCore/platform/graphics/android/layers/CanvasTexture.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CanvasTexture_h
-#define CanvasTexture_h
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "CanvasLayer.h"
-
-#include <wtf/RefPtr.h>
-#include <utils/threads.h>
-
-namespace android {
-class SurfaceTexture;
-class SurfaceTextureClient;
-}
-
-namespace WebCore {
-
-class CanvasTexture : public ThreadSafeRefCounted<CanvasTexture> {
-
-public:
-    /********************************************
-     * Called by both threads
-     ********************************************/
-    static PassRefPtr<CanvasTexture> getCanvasTexture(CanvasLayer* layer);
-    bool setHwAccelerated(bool hwAccelerated);
-
-    /********************************************
-     * Called by WebKit thread
-     ********************************************/
-    void setSize(const IntSize& size);
-    SurfaceTextureClient* nativeWindow();
-    bool uploadImageBuffer(ImageBuffer* imageBuffer);
-    bool hasValidTexture() { return m_hasValidTexture; }
-
-    /********************************************
-     * Called by UI thread WITH GL context
-     ********************************************/
-    virtual ~CanvasTexture();
-    void requireTexture();
-    GLuint texture() { requireTexture(); return m_texture; }
-    bool updateTexImage();
-
-private:
-    /********************************************
-     * Called by both threads
-     ********************************************/
-    void destroySurfaceTextureLocked();
-
-    /********************************************
-     * Called by WebKit thread
-     ********************************************/
-    CanvasTexture(int layerId);
-    bool useSurfaceTexture();
-
-    IntSize m_size;
-    int m_layerId;
-    GLuint m_texture;
-    android::Mutex m_surfaceLock;
-    sp<android::SurfaceTexture> m_surfaceTexture;
-    sp<android::SurfaceTextureClient> m_ANW;
-    bool m_hasValidTexture;
-    bool m_useHwAcceleration;
-
-};
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
-
-#endif // CanvasTexture_h
diff --git a/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp b/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp
deleted file mode 100644
index 5551965..0000000
--- a/Source/WebCore/platform/graphics/android/layers/DumpLayer.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-#include "config.h"
-#include "DumpLayer.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-namespace WebCore {
-
-void lwrite(FILE* file, const char* str)
-{
-    fwrite(str, sizeof(char), strlen(str), file);
-}
-
-void writeIndent(FILE* file, int indentLevel)
-{
-    if (indentLevel)
-        fprintf(file, "%*s", indentLevel*2, " ");
-}
-
-void writeln(FILE* file, int indentLevel, const char* str)
-{
-    writeIndent(file, indentLevel);
-    lwrite(file, str);
-    lwrite(file, "\n");
-}
-
-void writeIntVal(FILE* file, int indentLevel, const char* str, int value)
-{
-    writeIndent(file, indentLevel);
-    fprintf(file, "%s = %d;\n", str, value);
-}
-
-void writeHexVal(FILE* file, int indentLevel, const char* str, int value)
-{
-    writeIndent(file, indentLevel);
-    fprintf(file, "%s = %x;\n", str, value);
-}
-
-void writeFloatVal(FILE* file, int indentLevel, const char* str, float value)
-{
-    writeIndent(file, indentLevel);
-    fprintf(file, "%s = %.3f;\n", str, value);
-}
-
-void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point)
-{
-    writeIndent(file, indentLevel);
-    fprintf(file, "%s = { x = %.3f; y = %.3f; };\n", str, point.fX, point.fY);
-}
-
-void writeIntPoint(FILE* file, int indentLevel, const char* str, IntPoint point)
-{
-    writeIndent(file, indentLevel);
-    fprintf(file, "%s = { x = %d; y = %d; };\n", str, point.x(), point.y());
-}
-
-void writeSize(FILE* file, int indentLevel, const char* str, SkSize size)
-{
-    writeIndent(file, indentLevel);
-    fprintf(file, "%s = { w = %.3f; h = %.3f; };\n", str, size.width(), size.height());
-}
-
-void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect)
-{
-    writeIndent(file, indentLevel);
-    fprintf(file, "%s = { x = %.3f; y = %.3f; w = %.3f; h = %.3f; };\n",
-            str, rect.fLeft, rect.fTop, rect.width(), rect.height());
-}
-
-void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix)
-{
-    writeIndent(file, indentLevel);
-    fprintf(file, "%s = { (%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f),"
-            "(%.2f,%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f,%.2f) };\n",
-            str,
-            matrix.m11(), matrix.m12(), matrix.m13(), matrix.m14(),
-            matrix.m21(), matrix.m22(), matrix.m23(), matrix.m24(),
-            matrix.m31(), matrix.m32(), matrix.m33(), matrix.m34(),
-            matrix.m41(), matrix.m42(), matrix.m43(), matrix.m44());
-}
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/layers/DumpLayer.h b/Source/WebCore/platform/graphics/android/layers/DumpLayer.h
deleted file mode 100644
index 5b30952..0000000
--- a/Source/WebCore/platform/graphics/android/layers/DumpLayer.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef DumpLayer_h
-#define DumpLayer_h
-
-#include "IntPoint.h"
-#include "SkPoint.h"
-#include "SkRect.h"
-#include "SkSize.h"
-#include "TransformationMatrix.h"
-
-// Debug tools : dump the layers tree in a file.
-// The format is simple:
-// properties have the form: key = value;
-// all statements are finished with a semi-colon.
-// value can be:
-// - int
-// - float
-// - array of elements
-// - composed type
-// a composed type enclose properties in { and }
-// an array enclose composed types in { }, separated with a comma.
-// exemple:
-// {
-//   x = 3;
-//   y = 4;
-//   value = {
-//     x = 3;
-//     y = 4;
-//   };
-//   anarray = [
-//     { x = 3; },
-//     { y = 4; }
-//   ];
-// }
-
-namespace WebCore {
-
-void lwrite(FILE* file, const char* str);
-void writeIndent(FILE* file, int indentLevel);
-void writeln(FILE* file, int indentLevel, const char* str);
-void writeIntVal(FILE* file, int indentLevel, const char* str, int value);
-void writeHexVal(FILE* file, int indentLevel, const char* str, int value);
-void writeFloatVal(FILE* file, int indentLevel, const char* str, float value);
-void writePoint(FILE* file, int indentLevel, const char* str, SkPoint point);
-void writeIntPoint(FILE* file, int indentLevel, const char* str, IntPoint point);
-void writeSize(FILE* file, int indentLevel, const char* str, SkSize size);
-void writeRect(FILE* file, int indentLevel, const char* str, SkRect rect);
-void writeMatrix(FILE* file, int indentLevel, const char* str, const TransformationMatrix& matrix);
-
-}
-
-#endif // DumpLayer_h
diff --git a/Source/WebCore/platform/graphics/android/layers/FixedBackgroundLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/FixedBackgroundLayerAndroid.h
deleted file mode 100644
index 72afa35..0000000
--- a/Source/WebCore/platform/graphics/android/layers/FixedBackgroundLayerAndroid.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef FixedBackgroundLayerAndroid_h
-#define FixedBackgroundLayerAndroid_h
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "LayerAndroid.h"
-
-namespace WebCore {
-
-// TODO: the hierarchy manipulation in GraphicsLayerAndroid should
-// (at least partly) be handled in this class
-class FixedBackgroundLayerAndroid : public LayerAndroid {
-public:
-    FixedBackgroundLayerAndroid(RenderLayer* owner)
-        : LayerAndroid(owner) {}
-    FixedBackgroundLayerAndroid(const FixedBackgroundLayerAndroid& layer)
-        : LayerAndroid(layer) {}
-    FixedBackgroundLayerAndroid(const LayerAndroid& layer)
-        : LayerAndroid(layer) {}
-    virtual ~FixedBackgroundLayerAndroid() {};
-
-    virtual LayerAndroid* copy() const { return new FixedBackgroundLayerAndroid(*this); }
-
-    virtual bool isFixedBackground() const { return true; }
-
-    virtual SubclassType subclassType() const { return LayerAndroid::FixedBackgroundLayer; }
-};
-
-}
-
-#endif // USE(ACCELERATED_COMPOSITING)
-
-#endif // FixedBackgroundLayerAndroid_h
diff --git a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp
deleted file mode 100644
index 82afe8f..0000000
--- a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-#define LOG_TAG "FixedPositioning"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "FixedPositioning.h"
-
-#include "AndroidLog.h"
-#include "DumpLayer.h"
-#include "IFrameLayerAndroid.h"
-#include "TilesManager.h"
-#include "SkCanvas.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-namespace WebCore {
-
-// Called when copying the layer tree to the UI
-FixedPositioning::FixedPositioning(LayerAndroid* layer, const FixedPositioning& position)
-        : m_layer(layer)
-        , m_fixedLeft(position.m_fixedLeft)
-        , m_fixedTop(position.m_fixedTop)
-        , m_fixedRight(position.m_fixedRight)
-        , m_fixedBottom(position.m_fixedBottom)
-        , m_fixedMarginLeft(position.m_fixedMarginLeft)
-        , m_fixedMarginTop(position.m_fixedMarginTop)
-        , m_fixedMarginRight(position.m_fixedMarginRight)
-        , m_fixedMarginBottom(position.m_fixedMarginBottom)
-        , m_fixedRect(position.m_fixedRect)
-        , m_renderLayerPos(position.m_renderLayerPos)
-{
-}
-
-SkRect FixedPositioning::getViewport(SkRect aViewport, IFrameLayerAndroid* parentIframeLayer)
-{
-    // So if this is a fixed layer inside a iframe, use the iframe offset
-    // and the iframe's size as the viewport and pass to the children
-    if (parentIframeLayer)
-        return SkRect::MakeXYWH(parentIframeLayer->iframeOffset().x(),
-                                parentIframeLayer->iframeOffset().y(),
-                                parentIframeLayer->getSize().width(),
-                                parentIframeLayer->getSize().height());
-    return aViewport;
-}
-
-// Executed on the UI
-IFrameLayerAndroid* FixedPositioning::updatePosition(SkRect aViewport,
-                                                     IFrameLayerAndroid* parentIframeLayer)
-{
-    SkRect viewport = getViewport(aViewport, parentIframeLayer);
-
-    float w = viewport.width();
-    float h = viewport.height();
-    float dx = viewport.fLeft;
-    float dy = viewport.fTop;
-    float x = dx;
-    float y = dy;
-
-    // It turns out that when it is 'auto', we should use the webkit value
-    // from the original render layer's X,Y, that will take care of alignment
-    // with the parent's layer and fix Margin etc.
-    if (!(m_fixedLeft.defined() || m_fixedRight.defined()))
-        x += m_renderLayerPos.x();
-    else if (m_fixedLeft.defined() || !m_fixedRight.defined())
-        x += m_fixedMarginLeft.calcFloatValue(w) + m_fixedLeft.calcFloatValue(w) - m_fixedRect.fLeft;
-    else
-        x += w - m_fixedMarginRight.calcFloatValue(w) - m_fixedRight.calcFloatValue(w) - m_fixedRect.fRight;
-
-    if (!(m_fixedTop.defined() || m_fixedBottom.defined()))
-        y += m_renderLayerPos.y();
-    else if (m_fixedTop.defined() || !m_fixedBottom.defined())
-        y += m_fixedMarginTop.calcFloatValue(h) + m_fixedTop.calcFloatValue(h) - m_fixedRect.fTop;
-    else
-        y += h - m_fixedMarginBottom.calcFloatValue(h) - m_fixedBottom.calcFloatValue(h) - m_fixedRect.fBottom;
-
-    m_layer->setPosition(x, y);
-
-    return parentIframeLayer;
-}
-
-void FixedPositioning::contentDraw(SkCanvas* canvas, Layer::PaintStyle style)
-{
-    if (TilesManager::instance()->getShowVisualIndicator()) {
-        SkPaint paint;
-        paint.setARGB(80, 255, 0, 0);
-        canvas->drawRect(m_fixedRect, paint);
-    }
-}
-
-void writeLength(FILE* file, int indentLevel, const char* str, SkLength length)
-{
-    if (!length.defined())
-        return;
-    writeIndent(file, indentLevel);
-    fprintf(file, "%s = { type = %d; value = %.2f; };\n", str, length.type, length.value);
-}
-
-void FixedPositioning::dumpLayer(FILE* file, int indentLevel) const
-{
-    writeLength(file, indentLevel + 1, "fixedLeft", m_fixedLeft);
-    writeLength(file, indentLevel + 1, "fixedTop", m_fixedTop);
-    writeLength(file, indentLevel + 1, "fixedRight", m_fixedRight);
-    writeLength(file, indentLevel + 1, "fixedBottom", m_fixedBottom);
-    writeLength(file, indentLevel + 1, "fixedMarginLeft", m_fixedMarginLeft);
-    writeLength(file, indentLevel + 1, "fixedMarginTop", m_fixedMarginTop);
-    writeLength(file, indentLevel + 1, "fixedMarginRight", m_fixedMarginRight);
-    writeLength(file, indentLevel + 1, "fixedMarginBottom", m_fixedMarginBottom);
-    writeRect(file, indentLevel + 1, "fixedRect", m_fixedRect);
-}
-
-BackgroundImagePositioning::BackgroundImagePositioning(LayerAndroid* layer, const BackgroundImagePositioning& position)
-        : FixedPositioning(layer, position)
-        , m_repeatX(position.m_repeatX)
-        , m_repeatY(position.m_repeatY)
-        , m_nbRepeatX(position.m_nbRepeatX)
-        , m_nbRepeatY(position.m_nbRepeatY)
-        , m_offsetX(position.m_offsetX)
-        , m_offsetY(position.m_offsetY)
-{
-}
-
-// Executed on the UI
-IFrameLayerAndroid* BackgroundImagePositioning::updatePosition(SkRect aViewport,
-                                                               IFrameLayerAndroid* parentIframeLayer)
-{
-    SkRect viewport = getViewport(aViewport, parentIframeLayer);
-
-    float w = viewport.width() - m_layer->getWidth();
-    float h = viewport.height() - m_layer->getHeight();
-    float x = 0;
-    float y = 0;
-
-    if (m_fixedLeft.defined())
-        x += m_fixedLeft.calcFloatValue(w);
-    if (m_fixedTop.defined())
-        y += m_fixedTop.calcFloatValue(h);
-
-    m_nbRepeatX = ceilf((viewport.width() / m_layer->getWidth()) + 1);
-    m_offsetX = ceilf(x / m_layer->getWidth());
-
-    m_nbRepeatY = ceilf((viewport.height() / m_layer->getHeight()) + 1);
-    m_offsetY = ceilf(y / m_layer->getHeight());
-
-    x += viewport.fLeft;
-    y += viewport.fTop;
-
-    m_layer->setPosition(x, y);
-
-    return parentIframeLayer;
-}
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h b/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h
deleted file mode 100644
index e273a25..0000000
--- a/Source/WebCore/platform/graphics/android/layers/FixedPositioning.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef FixedPositioning_h
-#define FixedPositioning_h
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "LayerAndroid.h"
-#include "Length.h"
-
-namespace WebCore {
-
-class IFrameLayerAndroid;
-
-struct SkLength {
-    enum SkLengthType { Undefined, Auto, Relative,
-        Percent, Fixed, Static, Intrinsic, MinIntrinsic };
-    SkLengthType type;
-    SkScalar value;
-    SkLength()
-    {
-        type = Undefined;
-        value = 0;
-    }
-    bool defined() const
-    {
-        if (type == Undefined)
-            return false;
-        return true;
-    }
-    void setFixedValue(float v)
-    {
-        type = Fixed;
-        value = v;
-    }
-    void setAuto()
-    {
-        type = Auto;
-    }
-    float calcFloatValue(float max) const
-    {
-        switch (type) {
-        case Percent:
-            return (max * value) / 100.0f;
-        case Fixed:
-            return value;
-        default:
-            return value;
-        }
-    }
-
-    static SkLength convertLength(Length len)
-    {
-        SkLength length;
-        length.type = SkLength::Undefined;
-        length.value = 0;
-        if (len.type() == WebCore::Percent) {
-            length.type = SkLength::Percent;
-            length.value = len.percent();
-        }
-        if (len.type() == WebCore::Fixed) {
-            length.type = SkLength::Fixed;
-            length.value = len.value();
-        }
-        return length;
-    }
-
-};
-
-class FixedPositioning {
-
-public:
-    FixedPositioning(LayerAndroid* layer = 0) : m_layer(layer) {}
-    FixedPositioning(LayerAndroid* layer, const FixedPositioning& position);
-    virtual ~FixedPositioning() {};
-
-    virtual bool isBackgroundImagePositioning() { return true; }
-    virtual FixedPositioning* copy(LayerAndroid* layer) const {
-        return new FixedPositioning(layer, *this);
-    }
-
-    void setFixedPosition(SkLength left, // CSS left property
-                          SkLength top, // CSS top property
-                          SkLength right, // CSS right property
-                          SkLength bottom, // CSS bottom property
-                          SkLength marginLeft, // CSS margin-left property
-                          SkLength marginTop, // CSS margin-top property
-                          SkLength marginRight, // CSS margin-right property
-                          SkLength marginBottom, // CSS margin-bottom property
-                          const IntPoint& renderLayerPos, // For undefined fixed position
-                          SkRect viewRect) { // view rect, can be smaller than the layer's
-        m_fixedLeft = left;
-        m_fixedTop = top;
-        m_fixedRight = right;
-        m_fixedBottom = bottom;
-        m_fixedMarginLeft = marginLeft;
-        m_fixedMarginTop = marginTop;
-        m_fixedMarginRight = marginRight;
-        m_fixedMarginBottom = marginBottom;
-        m_fixedRect = viewRect;
-        m_renderLayerPos = renderLayerPos;
-    }
-
-    SkRect getViewport(SkRect viewport, IFrameLayerAndroid* parentIframeLayer);
-    virtual IFrameLayerAndroid* updatePosition(SkRect viewPort,
-                                               IFrameLayerAndroid* parentIframeLayer);
-
-    void contentDraw(SkCanvas* canvas, Layer::PaintStyle style);
-
-    void dumpLayer(FILE*, int indentLevel) const;
-
-    // ViewStateSerializer friends
-    friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream);
-    friend LayerAndroid* android::deserializeLayer(int version, SkStream* stream);
-
-protected:
-    LayerAndroid* m_layer;
-
-    SkLength m_fixedLeft;
-    SkLength m_fixedTop;
-    SkLength m_fixedRight;
-    SkLength m_fixedBottom;
-    SkLength m_fixedMarginLeft;
-    SkLength m_fixedMarginTop;
-    SkLength m_fixedMarginRight;
-    SkLength m_fixedMarginBottom;
-    SkRect m_fixedRect;
-
-    // When fixed element is undefined or auto, the render layer's position
-    // is needed for offset computation
-    IntPoint m_renderLayerPos;
-};
-
-class BackgroundImagePositioning : public FixedPositioning {
-public:
-    BackgroundImagePositioning(LayerAndroid* layer)
-        : FixedPositioning(layer)
-        , m_repeatX(false)
-        , m_repeatY(false)
-        , m_nbRepeatX(0)
-        , m_nbRepeatY(0)
-        , m_offsetX(0)
-        , m_offsetY(0)
-    {}
-    BackgroundImagePositioning(LayerAndroid* layer, const BackgroundImagePositioning& position);
-    virtual bool isBackgroundImagePositioning() { return true; }
-    virtual FixedPositioning* copy(LayerAndroid* layer) const {
-        return new BackgroundImagePositioning(layer, *this);
-    }
-    void setPosition(SkLength left, SkLength top) {
-        m_fixedLeft = left;
-        m_fixedTop = top;
-    }
-    virtual IFrameLayerAndroid* updatePosition(SkRect viewPort,
-                                               IFrameLayerAndroid* parentIframeLayer);
-
-    // Measures the background image repetition
-    void setRepeatX(bool repeat) { m_repeatX = repeat; }
-    void setRepeatY(bool repeat) { m_repeatY = repeat; }
-    bool repeatX() { return m_repeatX; }
-    bool repeatY() { return m_repeatY; }
-    int nbRepeatX() { return m_nbRepeatX; }
-    int offsetX() { return m_offsetX; }
-    int nbRepeatY() { return m_nbRepeatY; }
-    int offsetY() { return m_offsetY; }
-
-private:
-    bool m_repeatX;
-    bool m_repeatY;
-    int  m_nbRepeatX;
-    int  m_nbRepeatY;
-    int  m_offsetX;
-    int  m_offsetY;
-};
-
-}
-
-#endif // USE(ACCELERATED_COMPOSITING)
-
-#endif // FixedPositioning_h
diff --git a/Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.cpp
deleted file mode 100644
index a0bd1b5..0000000
--- a/Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-#define LOG_TAG "IFrameContentLayerAndroid"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "IFrameContentLayerAndroid.h"
-
-#include "AndroidLog.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-namespace WebCore {
-
-bool IFrameContentLayerAndroid::scrollTo(int x, int y)
-{
-    IntRect scrollBounds;
-    getScrollBounds(&scrollBounds);
-    if (!scrollBounds.width() && !scrollBounds.height())
-        return false;
-    SkScalar newX = SkScalarPin(x, scrollBounds.x(), scrollBounds.width());
-    SkScalar newY = SkScalarPin(y, scrollBounds.y(), scrollBounds.height());
-    // Check for no change.
-    if (newX == m_iframeScrollOffset.x() && newY == m_iframeScrollOffset.y())
-        return false;
-    newX = newX - m_iframeScrollOffset.x();
-    newY = newY - m_iframeScrollOffset.y();
-    setScrollOffset(IntPoint(newX, newY));
-    return true;
-}
-
-void IFrameContentLayerAndroid::getScrollRect(SkIRect* out) const
-{
-    const SkPoint& pos = getPosition();
-    out->fLeft = m_scrollLimits.fLeft - pos.fX + m_iframeScrollOffset.x();
-    out->fTop = m_scrollLimits.fTop - pos.fY + m_iframeScrollOffset.y();
-
-    out->fRight = m_scrollLimits.width();
-    out->fBottom = m_scrollLimits.height();
-}
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.h
deleted file mode 100644
index 1a8c21c..0000000
--- a/Source/WebCore/platform/graphics/android/layers/IFrameContentLayerAndroid.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef IFrameContentLayerAndroid_h
-#define IFrameContentLayerAndroid_h
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "ScrollableLayerAndroid.h"
-
-namespace WebCore {
-
-class IFrameContentLayerAndroid : public ScrollableLayerAndroid {
-
-public:
-    IFrameContentLayerAndroid(RenderLayer* owner)
-        : ScrollableLayerAndroid(owner) {}
-    IFrameContentLayerAndroid(const ScrollableLayerAndroid& layer)
-        : ScrollableLayerAndroid(layer) {}
-    IFrameContentLayerAndroid(const LayerAndroid& layer)
-        : ScrollableLayerAndroid(layer) {}
-    IFrameContentLayerAndroid(const IFrameContentLayerAndroid& layer)
-        : ScrollableLayerAndroid(layer)
-        , m_iframeScrollOffset(layer.m_iframeScrollOffset) {}
-
-    virtual ~IFrameContentLayerAndroid() {};
-
-    // isIFrame() return true for compatibility reason (see ViewStateSerializer)
-    virtual bool isIFrame() const { return true; }
-    virtual bool isIFrameContent() const { return true; }
-
-    virtual LayerAndroid* copy() const { return new IFrameContentLayerAndroid(*this); }
-    virtual SubclassType subclassType() const { return LayerAndroid::IFrameContentLayer; }
-
-    // Scrolls to the given position in the layer.
-    // Returns whether or not any scrolling was required.
-    virtual bool scrollTo(int x, int y);
-
-    // Fills the rect with the current scroll offset and the maximum scroll offset.
-    // fLeft   = scrollX
-    // fTop    = scrollY
-    // fRight  = maxScrollX
-    // fBottom = maxScrollY
-    virtual void getScrollRect(SkIRect*) const;
-
-    void setIFrameScrollOffset(IntPoint offset) { m_iframeScrollOffset = offset; }
-
-private:
-    IntPoint m_iframeScrollOffset;
-};
-
-}
-
-#endif // USE(ACCELERATED_COMPOSITING)
-
-#endif // IFrameContentLayerAndroid_h
diff --git a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp
deleted file mode 100644
index 3532542..0000000
--- a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#define LOG_TAG "IFrameLayerAndroid"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "IFrameLayerAndroid.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "AndroidLog.h"
-#include "DumpLayer.h"
-
-namespace WebCore {
-
-IFrameLayerAndroid* IFrameLayerAndroid::updatePosition(SkRect viewport,
-                                                       IFrameLayerAndroid* parentIframeLayer)
-{
-    // As we are an iframe, accumulate the offset from the parent with
-    // the current position, and change the parent pointer.
-
-    // If this is the top level, take the current position
-    SkPoint parentOffset;
-    parentOffset.set(0,0);
-    if (parentIframeLayer)
-        parentOffset = parentIframeLayer->getPosition();
-
-    SkPoint offset = parentOffset + getPosition();
-    m_iframeOffset = IntPoint(offset.fX, offset.fY);
-
-    return this;
-}
-
-void IFrameLayerAndroid::dumpLayer(FILE* file, int indentLevel) const
-{
-    writeIntVal(file, indentLevel + 1, "m_isIframe", true);
-    writeIntPoint(file, indentLevel + 1, "m_iframeOffset", m_iframeOffset);
-}
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h
deleted file mode 100644
index f2fbf49..0000000
--- a/Source/WebCore/platform/graphics/android/layers/IFrameLayerAndroid.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef IFrameLayerAndroid_h
-#define IFrameLayerAndroid_h
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "LayerAndroid.h"
-
-namespace WebCore {
-
-class IFrameLayerAndroid : public LayerAndroid {
-
-public:
-    IFrameLayerAndroid(RenderLayer* owner)
-        : LayerAndroid(owner) {}
-    IFrameLayerAndroid(const LayerAndroid& layer)
-        : LayerAndroid(layer) {}
-    IFrameLayerAndroid(const IFrameLayerAndroid& layer)
-        : LayerAndroid(layer)
-        , m_iframeOffset(layer.m_iframeOffset) {}
-
-    virtual ~IFrameLayerAndroid() {};
-
-    virtual bool isIFrame() const { return true; }
-
-    virtual LayerAndroid* copy() const { return new IFrameLayerAndroid(*this); }
-    virtual SubclassType subclassType() const { return LayerAndroid::IFrameLayer; }
-
-    virtual IFrameLayerAndroid* updatePosition(SkRect viewport,
-                                               IFrameLayerAndroid* parentIframeLayer);
-
-    virtual void dumpLayer(FILE*, int indentLevel) const;
-
-    const IntPoint& iframeOffset() const { return m_iframeOffset; }
-
-private:
-    IntPoint m_iframeOffset;
-};
-
-}
-
-#endif // USE(ACCELERATED_COMPOSITING)
-
-#endif // IFrameLayerAndroid_h
diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp
deleted file mode 100644
index 228a30e..0000000
--- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp
+++ /dev/null
@@ -1,1027 +0,0 @@
-#define LOG_TAG "LayerAndroid"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "LayerAndroid.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "AndroidLog.h"
-#include "AndroidAnimation.h"
-#include "ClassTracker.h"
-#include "DrawExtra.h"
-#include "DumpLayer.h"
-#include "FixedPositioning.h"
-#include "GLUtils.h"
-#include "GLWebViewState.h"
-#include "ImagesManager.h"
-#include "InspectorCanvas.h"
-#include "LayerContent.h"
-#include "MediaLayer.h"
-#include "ParseCanvas.h"
-#include "PictureLayerContent.h"
-#include "PrerenderedInval.h"
-#include "SkBitmapRef.h"
-#include "SkDevice.h"
-#include "SkDrawFilter.h"
-#include "SkPaint.h"
-#include "SkPicture.h"
-#include "SkTypeface.h"
-#include "Surface.h"
-#include "TilesManager.h"
-
-#include <wtf/CurrentTime.h>
-#include <wtf/text/CString.h>
-#include <math.h>
-
-#define DISABLE_LAYER_MERGE
-#undef DISABLE_LAYER_MERGE
-
-#define LAYER_MERGING_DEBUG
-#undef LAYER_MERGING_DEBUG
-
-namespace WebCore {
-
-static int gUniqueId;
-
-class OpacityDrawFilter : public SkDrawFilter {
-public:
-    OpacityDrawFilter(int opacity) : m_opacity(opacity) { }
-    virtual void filter(SkPaint* paint, Type)
-    {
-        paint->setAlpha(m_opacity);
-    }
-private:
-    int m_opacity;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(),
-    m_uniqueId(++gUniqueId),
-    m_haveClip(false),
-    m_backfaceVisibility(true),
-    m_visible(true),
-    m_backgroundColor(0),
-    m_preserves3D(false),
-    m_anchorPointZ(0),
-    m_isPositionAbsolute(false),
-    m_fixedPosition(0),
-    m_zValue(0),
-    m_content(0),
-    m_imageCRC(0),
-    m_scale(1),
-    m_lastComputeTextureSize(0),
-    m_owningLayer(owner),
-    m_type(LayerAndroid::WebCoreLayer),
-    m_intrinsicallyComposited(true),
-    m_surface(0),
-    m_replicatedLayer(0),
-    m_originalLayer(0),
-    m_maskLayer(0)
-{
-    m_dirtyRegion.setEmpty();
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->increment("LayerAndroid");
-    ClassTracker::instance()->add(this);
-#endif
-}
-
-LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer),
-    m_uniqueId(layer.m_uniqueId),
-    m_haveClip(layer.m_haveClip),
-    m_backfaceVisibility(layer.m_backfaceVisibility),
-    m_visible(layer.m_visible),
-    m_backgroundColor(layer.m_backgroundColor),
-    m_preserves3D(layer.m_preserves3D),
-    m_anchorPointZ(layer.m_anchorPointZ),
-    m_isPositionAbsolute(layer.m_isPositionAbsolute),
-    m_fixedPosition(0),
-    m_zValue(layer.m_zValue),
-    m_content(layer.m_content),
-    m_imageCRC(layer.m_imageCRC),
-    m_scale(layer.m_scale),
-    m_lastComputeTextureSize(0),
-    m_owningLayer(layer.m_owningLayer),
-    m_type(LayerAndroid::UILayer),
-    m_intrinsicallyComposited(layer.m_intrinsicallyComposited),
-    m_surface(0),
-    m_replicatedLayer(0),
-    m_originalLayer(0),
-    m_maskLayer(0)
-{
-    if (m_imageCRC)
-        ImagesManager::instance()->retainImage(m_imageCRC);
-
-    SkSafeRef(m_content);
-
-    if (layer.m_fixedPosition) {
-        m_fixedPosition = layer.m_fixedPosition->copy(this);
-        Layer::setShouldInheritFromRootTransform(true);
-    }
-
-    m_transform = layer.m_transform;
-    m_drawTransform = layer.m_drawTransform;
-    m_drawTransformUnfudged = layer.m_drawTransformUnfudged;
-    m_childrenTransform = layer.m_childrenTransform;
-    m_dirtyRegion = layer.m_dirtyRegion;
-
-    m_replicatedLayerPosition = layer.m_replicatedLayerPosition;
-
-#ifdef ABSOLUTE_POSITION
-    // If we have absolute elements, we may need to reorder them if they
-    // are followed by another layer that is not also absolutely positioned.
-    // (as absolutely positioned elements are out of the normal flow)
-    bool hasAbsoluteChildren = false;
-    bool hasOnlyAbsoluteFollowers = true;
-
-    for (int i = 0; i < layer.countChildren(); i++) {
-        if (layer.getChild(i)->isPositionAbsolute()) {
-            hasAbsoluteChildren = true;
-            continue;
-        }
-        if (hasAbsoluteChildren
-            && !layer.getChild(i)->isPositionAbsolute()) {
-            hasOnlyAbsoluteFollowers = false;
-            break;
-        }
-    }
-
-    if (hasAbsoluteChildren && !hasOnlyAbsoluteFollowers) {
-        Vector<LayerAndroid*> normalLayers;
-        Vector<LayerAndroid*> absoluteLayers;
-        for (int i = 0; i < layer.countChildren(); i++) {
-            LayerAndroid* child = layer.getChild(i);
-            if (child->isPositionAbsolute()
-                || child->isPositionFixed())
-                absoluteLayers.append(child);
-            else
-                normalLayers.append(child);
-        }
-        for (unsigned int i = 0; i < normalLayers.size(); i++)
-            addChild(normalLayers[i]->copy())->unref();
-        for (unsigned int i = 0; i < absoluteLayers.size(); i++)
-            addChild(absoluteLayers[i]->copy())->unref();
-    } else {
-        for (int i = 0; i < layer.countChildren(); i++)
-            addChild(layer.getChild(i)->copy())->unref();
-    }
-#else
-    for (int i = 0; i < layer.countChildren(); i++)
-        addChild(layer.getChild(i)->copy())->unref();
-#endif
-
-    KeyframesMap::const_iterator end = layer.m_animations.end();
-    for (KeyframesMap::const_iterator it = layer.m_animations.begin(); it != end; ++it) {
-        m_animations.add(it->first, it->second);
-    }
-
-    if (layer.m_replicatedLayer) {
-        // The replicated layer is always the first child
-        m_replicatedLayer = getChild(0);
-        m_replicatedLayer->setOriginalLayer(this);
-    }
-
-    if (layer.m_maskLayer)
-        m_maskLayer = layer.m_maskLayer->copy();
-
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->increment("LayerAndroid - recopy (UI)");
-    ClassTracker::instance()->add(this);
-#endif
-}
-
-LayerAndroid::~LayerAndroid()
-{
-    if (m_imageCRC)
-        ImagesManager::instance()->releaseImage(m_imageCRC);
-    if (m_fixedPosition)
-        delete m_fixedPosition;
-
-    SkSafeUnref(m_maskLayer);
-    SkSafeUnref(m_content);
-    // Don't unref m_surface, owned by BaseLayerAndroid
-    m_animations.clear();
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->remove(this);
-    if (m_type == LayerAndroid::WebCoreLayer)
-        ClassTracker::instance()->decrement("LayerAndroid");
-    else if (m_type == LayerAndroid::UILayer)
-        ClassTracker::instance()->decrement("LayerAndroid - recopy (UI)");
-#endif
-}
-
-bool LayerAndroid::hasText()
-{
-    return m_content && m_content->hasText();
-}
-
-static int gDebugNbAnims = 0;
-
-bool LayerAndroid::evaluateAnimations()
-{
-    double time = WTF::currentTime();
-    gDebugNbAnims = 0;
-    return evaluateAnimations(time);
-}
-
-bool LayerAndroid::hasAnimations() const
-{
-    for (int i = 0; i < countChildren(); i++) {
-        if (getChild(i)->hasAnimations())
-            return true;
-    }
-    return !!m_animations.size();
-}
-
-bool LayerAndroid::evaluateAnimations(double time)
-{
-    bool hasRunningAnimations = false;
-    for (int i = 0; i < countChildren(); i++) {
-        if (getChild(i)->evaluateAnimations(time))
-            hasRunningAnimations = true;
-    }
-
-    m_hasRunningAnimations = false;
-    int nbAnims = 0;
-    KeyframesMap::const_iterator end = m_animations.end();
-    for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
-        gDebugNbAnims++;
-        nbAnims++;
-        LayerAndroid* currentLayer = const_cast<LayerAndroid*>(this);
-        m_hasRunningAnimations |= (it->second)->evaluate(currentLayer, time);
-    }
-
-    return hasRunningAnimations || m_hasRunningAnimations;
-}
-
-void LayerAndroid::initAnimations() {
-    // tell auto-initializing animations to start now
-    for (int i = 0; i < countChildren(); i++)
-        getChild(i)->initAnimations();
-
-    KeyframesMap::const_iterator localBegin = m_animations.begin();
-    KeyframesMap::const_iterator localEnd = m_animations.end();
-    for (KeyframesMap::const_iterator localIt = localBegin; localIt != localEnd; ++localIt)
-        (localIt->second)->suggestBeginTime(WTF::currentTime());
-}
-
-void LayerAndroid::addDirtyArea()
-{
-    if (m_drawTransform.hasPerspective()) {
-        state()->doFrameworkFullInval();
-        return;
-    }
-
-    // TODO: rewrite this to handle partial invalidate, and to handle base
-    // layer's large clip correctly
-
-    IntSize layerSize(getSize().width(), getSize().height());
-
-    FloatRect area =
-        TilesManager::instance()->shader()->rectInViewCoord(m_drawTransform, layerSize);
-    FloatRect clippingRect =
-        TilesManager::instance()->shader()->rectInInvViewCoord(m_clippingRect);
-    FloatRect clip =
-        TilesManager::instance()->shader()->convertInvViewCoordToViewCoord(clippingRect);
-
-    area.intersect(clip);
-    IntRect dirtyArea(area.x(), area.y(), area.width(), area.height());
-
-    state()->addDirtyArea(dirtyArea);
-
-    for (int i = 0; i < countChildren(); i++)
-        getChild(i)->addDirtyArea();
-}
-
-void LayerAndroid::addAnimation(PassRefPtr<AndroidAnimation> prpAnim)
-{
-    RefPtr<AndroidAnimation> anim = prpAnim;
-    pair<String, int> key(anim->name(), anim->type());
-    removeAnimationsForProperty(anim->type());
-    m_animations.add(key, anim);
-}
-
-void LayerAndroid::removeAnimationsForProperty(AnimatedPropertyID property)
-{
-    KeyframesMap::const_iterator end = m_animations.end();
-    Vector<pair<String, int> > toDelete;
-    for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
-        if ((it->second)->type() == property)
-            toDelete.append(it->first);
-    }
-
-    for (unsigned int i = 0; i < toDelete.size(); i++)
-        m_animations.remove(toDelete[i]);
-}
-
-void LayerAndroid::removeAnimationsForKeyframes(const String& name)
-{
-    KeyframesMap::const_iterator end = m_animations.end();
-    Vector<pair<String, int> > toDelete;
-    for (KeyframesMap::const_iterator it = m_animations.begin(); it != end; ++it) {
-        if ((it->second)->name() == name)
-            toDelete.append(it->first);
-    }
-
-    for (unsigned int i = 0; i < toDelete.size(); i++)
-        m_animations.remove(toDelete[i]);
-}
-
-// We only use the bounding rect of the layer as mask...
-// FIXME: use a real mask?
-void LayerAndroid::setMaskLayer(LayerAndroid* layer)
-{
-    SkSafeRef(layer);
-    SkSafeUnref(m_maskLayer);
-    m_maskLayer = layer;
-    if (layer)
-        m_haveClip = true;
-}
-
-void LayerAndroid::setBackgroundColor(SkColor color)
-{
-    m_backgroundColor = color;
-}
-
-FloatPoint LayerAndroid::translation() const
-{
-    TransformationMatrix::DecomposedType tDecomp;
-    m_transform.decompose(tDecomp);
-    FloatPoint p(tDecomp.translateX, tDecomp.translateY);
-    return p;
-}
-
-IFrameLayerAndroid* LayerAndroid::updatePosition(SkRect viewport,
-                                                 IFrameLayerAndroid* parentIframeLayer)
-{
-    // subclasses can implement this virtual function to modify their position
-    if (m_fixedPosition)
-        return m_fixedPosition->updatePosition(viewport, parentIframeLayer);
-    return parentIframeLayer;
-}
-
-void LayerAndroid::updateLayerPositions(SkRect viewport, IFrameLayerAndroid* parentIframeLayer)
-{
-    ALOGV("updating fixed positions, using viewport %fx%f - %fx%f",
-          viewport.fLeft, viewport.fTop,
-          viewport.width(), viewport.height());
-
-    IFrameLayerAndroid* iframeLayer = updatePosition(viewport, parentIframeLayer);
-
-    int count = this->countChildren();
-    for (int i = 0; i < count; i++)
-        this->getChild(i)->updateLayerPositions(viewport, iframeLayer);
-}
-
-void LayerAndroid::updatePositions()
-{
-    // apply the viewport to us
-    if (!isPositionFixed()) {
-        // turn our fields into a matrix.
-        //
-        // FIXME: this should happen in the caller, and we should remove these
-        // fields from our subclass
-        SkMatrix matrix;
-        GLUtils::toSkMatrix(matrix, m_transform);
-        this->setMatrix(matrix);
-    }
-
-    // now apply it to our children
-    int count = this->countChildren();
-    for (int i = 0; i < count; i++)
-        this->getChild(i)->updatePositions();
-}
-
-void LayerAndroid::updateLocalTransformAndClip(const TransformationMatrix& parentMatrix,
-                                               const FloatRect& clipping)
-{
-    FloatPoint position(getPosition().x() + m_replicatedLayerPosition.x() - getScrollOffset().x(),
-                        getPosition().y() + m_replicatedLayerPosition.y() - getScrollOffset().y());
-    float originX = getAnchorPoint().x() * getWidth();
-    float originY = getAnchorPoint().y() * getHeight();
-
-    TransformationMatrix localMatrix;
-
-    if (isPositionFixed())
-        m_drawTransform.makeIdentity();
-    else
-        m_drawTransform = parentMatrix;
-    m_drawTransform.translate3d(originX + position.x(),
-                                originY + position.y(),
-                                anchorPointZ());
-    m_drawTransform.multiply(m_transform);
-    m_drawTransform.translate3d(-originX,
-                                -originY,
-                                -anchorPointZ());
-
-    m_drawTransformUnfudged = m_drawTransform;
-    if (m_drawTransform.isIdentityOrTranslation()
-        && surface() && surface()->allowTransformFudging()) {
-        // adjust the translation coordinates of the draw transform matrix so
-        // that layers (defined in content coordinates) will align to display/view pixels
-
-        // the surface may not allow fudging if it uses the draw transform at paint time
-        float desiredContentX = round(m_drawTransform.m41() * m_scale) / m_scale;
-        float desiredContentY = round(m_drawTransform.m42() * m_scale) / m_scale;
-        ALOGV("fudging translation from %f, %f to %f, %f",
-              m_drawTransform.m41(), m_drawTransform.m42(),
-              desiredContentX, desiredContentY);
-        m_drawTransform.setM41(desiredContentX);
-        m_drawTransform.setM42(desiredContentY);
-    }
-
-    m_zValue = TilesManager::instance()->shader()->zValue(m_drawTransform,
-                                                          getSize().width(),
-                                                          getSize().height());
-
-    if (m_haveClip) {
-        // The clipping rect calculation and intersetion will be done in content
-        // coordinates.
-        FloatRect rect(0, 0, getWidth(), getHeight());
-        FloatRect clip = m_drawTransform.mapRect(rect);
-        clip.intersect(clipping);
-        setDrawClip(clip);
-    } else {
-        setDrawClip(clipping);
-    }
-    ALOGV("%s - %d %f %f %f %f",
-          subclassType() == BaseLayer ? "BASE" : "nonbase",
-          m_haveClip, m_clippingRect.x(), m_clippingRect.y(),
-          m_clippingRect.width(), m_clippingRect.height());
-
-    setVisible(m_backfaceVisibility || m_drawTransform.inverse().m33() >= 0);
-}
-
-void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentMatrix,
-                                             const FloatRect& clipping, float opacity,
-                                             float scale, bool forceCalculation,
-                                             bool disableFixedElemUpdate)
-{
-    m_scale = scale;
-
-    opacity *= getOpacity();
-    setDrawOpacity(opacity);
-
-    // constantly recalculate the draw transform of layers that may require it (and their children)
-    forceCalculation |= hasDynamicTransform();
-
-    forceCalculation &= !(disableFixedElemUpdate && isPositionFixed());
-    if (forceCalculation)
-        updateLocalTransformAndClip(parentMatrix, clipping);
-
-    if (!countChildren() || !m_visible)
-        return;
-
-    TransformationMatrix localMatrix = m_drawTransformUnfudged;
-
-    // Flatten to 2D if the layer doesn't preserve 3D.
-    if (!preserves3D()) {
-        localMatrix.setM13(0);
-        localMatrix.setM23(0);
-        localMatrix.setM31(0);
-        localMatrix.setM32(0);
-        localMatrix.setM33(1);
-        localMatrix.setM34(0);
-        localMatrix.setM43(0);
-    }
-
-    // now apply it to our children
-
-    TransformationMatrix childMatrix;
-    childMatrix = localMatrix;
-    childMatrix.translate3d(getScrollOffset().x(), getScrollOffset().y(), 0);
-    if (!m_childrenTransform.isIdentity()) {
-        childMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f);
-        childMatrix.multiply(m_childrenTransform);
-        childMatrix.translate(-getSize().width() * 0.5f, -getSize().height() * 0.5f);
-    }
-    for (int i = 0; i < countChildren(); i++)
-        this->getChild(i)->updateGLPositionsAndScale(childMatrix, drawClip(),
-                                                     opacity, scale, forceCalculation,
-                                                     disableFixedElemUpdate);
-}
-
-bool LayerAndroid::visible() {
-    // TODO: avoid climbing tree each access
-    LayerAndroid* current = this;
-    while (current->getParent()) {
-        if (!current->m_visible)
-            return false;
-        current = static_cast<LayerAndroid*>(current->getParent());
-    }
-    return true;
-}
-
-void LayerAndroid::setContentsImage(SkBitmapRef* img)
-{
-    ImageTexture* image = ImagesManager::instance()->setImage(img);
-    ImagesManager::instance()->releaseImage(m_imageCRC);
-    m_imageCRC = image ? image->imageCRC() : 0;
-}
-
-void LayerAndroid::setContent(LayerContent* content)
-{
-    SkSafeRef(content);
-    SkSafeUnref(m_content);
-    m_content = content;
-}
-
-bool LayerAndroid::canUpdateWithBlit()
-{
-    if (!m_content || !m_scale)
-        return false;
-    IntRect clip = clippedRect();
-    IntRect dirty = m_dirtyRegion.getBounds();
-    dirty.intersect(clip);
-    PrerenderedInval* prerendered = m_content->prerenderForRect(dirty);
-    if (!prerendered)
-        return false;
-    // Check that the scales are "close enough" to produce the same rects
-    FloatRect screenArea = prerendered->screenArea;
-    screenArea.scale(1 / m_scale);
-    IntRect enclosingDocArea = enclosingIntRect(screenArea);
-    return enclosingDocArea == prerendered->area;
-}
-
-bool LayerAndroid::needsTexture()
-{
-    return (m_content && !m_content->isEmpty())
-            || (m_originalLayer && m_originalLayer->needsTexture());
-}
-
-IntRect LayerAndroid::clippedRect() const
-{
-    IntRect r(0, 0, getWidth(), getHeight());
-    IntRect tr = m_drawTransform.mapRect(r);
-    IntRect cr = TilesManager::instance()->shader()->clippedRectWithVisibleContentRect(tr);
-    IntRect rect = m_drawTransform.inverse().mapRect(cr);
-    return rect;
-}
-
-int LayerAndroid::nbLayers()
-{
-    int nb = 0;
-    int count = this->countChildren();
-    for (int i = 0; i < count; i++)
-        nb += this->getChild(i)->nbLayers();
-    return nb+1;
-}
-
-int LayerAndroid::nbTexturedLayers()
-{
-    int nb = 0;
-    int count = this->countChildren();
-    for (int i = 0; i < count; i++)
-        nb += this->getChild(i)->nbTexturedLayers();
-    if (needsTexture())
-        nb++;
-    return nb;
-}
-
-void LayerAndroid::showLayer(int indent)
-{
-    char spaces[256];
-    memset(spaces, 0, 256);
-    for (int i = 0; i < indent; i++)
-        spaces[i] = ' ';
-
-    if (!indent) {
-        ALOGD("\n\n--- LAYERS TREE ---");
-        IntRect contentViewport(TilesManager::instance()->shader()->contentViewport());
-        ALOGD("contentViewport(%d, %d, %d, %d)",
-              contentViewport.x(), contentViewport.y(),
-              contentViewport.width(), contentViewport.height());
-    }
-
-    IntRect r(0, 0, getWidth(), getHeight());
-    IntRect tr = m_drawTransform.mapRect(r);
-    IntRect visible = visibleContentArea();
-    IntRect clip(m_clippingRect.x(), m_clippingRect.y(),
-                 m_clippingRect.width(), m_clippingRect.height());
-    ALOGD("%s s:%x %s %s (%d) [%d:%x - 0x%x] - %s %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) "
-          "clip (%d, %d, %d, %d) %s %s m_content(%x), pic w: %d h: %d originalLayer: %x %d",
-          spaces, m_surface, m_haveClip ? "CLIP LAYER" : "", subclassName().ascii().data(),
-          subclassType(), uniqueId(), this, m_owningLayer,
-          needsTexture() ? "needsTexture" : "",
-          m_imageCRC ? "hasImage" : "",
-          tr.x(), tr.y(), tr.width(), tr.height(),
-          visible.x(), visible.y(), visible.width(), visible.height(),
-          clip.x(), clip.y(), clip.width(), clip.height(),
-          contentIsScrollable() ? "SCROLLABLE" : "",
-          isPositionFixed() ? "FIXED" : "",
-          m_content,
-          m_content ? m_content->width() : -1,
-          m_content ? m_content->height() : -1,
-          m_originalLayer, m_originalLayer ? m_originalLayer->uniqueId() : -1);
-
-    int count = this->countChildren();
-    for (int i = 0; i < count; i++)
-        this->getChild(i)->showLayer(indent + 2);
-}
-
-void LayerAndroid::mergeInvalsInto(LayerAndroid* replacementTree)
-{
-    int count = this->countChildren();
-    for (int i = 0; i < count; i++)
-        this->getChild(i)->mergeInvalsInto(replacementTree);
-
-    LayerAndroid* replacementLayer = replacementTree->findById(uniqueId());
-    if (replacementLayer)
-        replacementLayer->markAsDirty(m_dirtyRegion);
-}
-
-static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b)
-{
-    return a->zValue() > b->zValue();
-}
-
-bool LayerAndroid::canJoinSurface(Surface* surface)
-{
-#ifdef DISABLE_LAYER_MERGE
-    return false;
-#else
-    // returns true if the layer can be merged onto the surface (group of layers)
-    if (!surface)
-        return false;
-
-    LayerAndroid* lastLayer = surface->getFirstLayer();
-
-    // isolate intrinsically composited layers
-    if (needsIsolatedSurface() || lastLayer->needsIsolatedSurface())
-        return false;
-
-    // TODO: investigate potential for combining transformed layers
-    if (!m_drawTransform.isIdentityOrTranslation()
-        || !lastLayer->m_drawTransform.isIdentityOrTranslation())
-        return false;
-
-    // TODO: compare other layer properties - fixed? overscroll? transformed?
-    return true;
-#endif
-}
-
-void LayerAndroid::assignSurfaces(LayerMergeState* mergeState)
-{
-    // recurse through layers in draw order, and merge layers when able
-
-    bool needNewSurface = !mergeState->currentSurface
-        || mergeState->nonMergeNestedLevel > 0
-        || !canJoinSurface(mergeState->currentSurface);
-
-    if (needNewSurface) {
-        mergeState->currentSurface = new Surface();
-        mergeState->surfaceList->append(mergeState->currentSurface);
-    }
-
-#ifdef LAYER_MERGING_DEBUG
-    ALOGD("%*slayer %p(%d) rl %p %s surface %p lvl: %d, fixed %d, anim %d, intCom %d, haveClip %d scroll %d hasText (layer: %d surface: %d) hasContent %d size %.2f x %.2f",
-          4*mergeState->depth, "", this, m_uniqueId, m_owningLayer,
-          needNewSurface ? "NEW" : "joins", mergeState->currentSurface,
-          mergeState->nonMergeNestedLevel,
-          isPositionFixed(), m_animations.size() != 0,
-          m_intrinsicallyComposited,
-          m_haveClip,
-          contentIsScrollable(), m_content ? m_content->hasText() : -1,
-          mergeState->currentSurface ? mergeState->currentSurface->hasText() : -1,
-          needsTexture(), getWidth(), getHeight());
-#endif
-
-    mergeState->currentSurface->addLayer(this, m_drawTransform);
-    m_surface = mergeState->currentSurface;
-
-    if (hasDynamicTransform()) {
-        // disable layer merging within the children of these layer types
-        mergeState->nonMergeNestedLevel++;
-    }
-
-    // pass the surface through children in drawing order, so that they may
-    // attach themselves (and paint on it) if possible, or ignore it and create
-    // a new one if not
-    int count = this->countChildren();
-    if (count > 0) {
-        mergeState->depth++;
-        Vector <LayerAndroid*> sublayers;
-        for (int i = 0; i < count; i++)
-            sublayers.append(getChild(i));
-
-        // sort for the transparency
-        std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
-        for (int i = 0; i < count; i++)
-            sublayers[i]->assignSurfaces(mergeState);
-        mergeState->depth--;
-    }
-
-    if (hasDynamicTransform()) {
-        // re-enable joining
-        mergeState->nonMergeNestedLevel--;
-
-        // disallow layers painting after to join with this surface
-        mergeState->currentSurface = 0;
-    }
-
-    if (needsIsolatedSurface())
-        mergeState->currentSurface = 0;
-
-}
-
-// We call this in WebViewCore, when copying the tree of layers.
-// As we construct a new tree that will be passed on the UI,
-// we mark the webkit-side tree as having no more dirty region
-// (otherwise we would continuously have those dirty region UI-side)
-void LayerAndroid::clearDirtyRegion()
-{
-    int count = this->countChildren();
-    for (int i = 0; i < count; i++)
-        this->getChild(i)->clearDirtyRegion();
-
-    m_dirtyRegion.setEmpty();
-}
-
-int LayerAndroid::setHwAccelerated(bool hwAccelerated)
-{
-    int flags = InvalidateNone;
-    int count = this->countChildren();
-    for (int i = 0; i < count; i++)
-        flags |= this->getChild(i)->setHwAccelerated(hwAccelerated);
-
-    return flags | onSetHwAccelerated(hwAccelerated);
-}
-
-FloatRect LayerAndroid::fullContentAreaMapped() const
-{
-    FloatRect area(0,0, getWidth(), getHeight());
-    FloatRect globalArea = m_drawTransform.mapRect(area);
-    return globalArea;
-}
-
-IntRect LayerAndroid::fullContentArea() const
-{
-    IntRect area(0,0, getWidth(), getHeight());
-    return area;
-}
-
-IntRect LayerAndroid::visibleContentArea(bool force3dContentVisible) const
-{
-    IntRect area = fullContentArea();
-    if (subclassType() == LayerAndroid::FixedBackgroundImageLayer)
-       return area;
-
-    // If transform isn't limited to 2D space, return the entire content area.
-    // Transforming from layers to content coordinates and back doesn't
-    // preserve 3D.
-    if (force3dContentVisible && GLUtils::has3dTransform(m_drawTransform))
-            return area;
-
-    // First, we get the transformed area of the layer,
-    // in content coordinates
-    IntRect rect = m_drawTransform.mapRect(area);
-
-    // Then we apply the clipping
-    IntRect clip(m_clippingRect);
-    rect.intersect(clip);
-
-    // Now clip with the viewport in content coordinate
-    IntRect contentViewport(TilesManager::instance()->shader()->contentViewport());
-    rect.intersect(contentViewport);
-
-    // Finally, let's return the visible area, in layers coordinate
-    return m_drawTransform.inverse().mapRect(rect);
-}
-
-bool LayerAndroid::drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle style)
-{
-    if (!m_visible)
-        return false;
-
-    bool askScreenUpdate = false;
-
-    {
-        SkAutoCanvasRestore acr(canvas, true);
-        SkRect r;
-        r.set(m_clippingRect.x(), m_clippingRect.y(),
-              m_clippingRect.x() + m_clippingRect.width(),
-              m_clippingRect.y() + m_clippingRect.height());
-        canvas->clipRect(r);
-        SkMatrix matrix;
-        GLUtils::toSkMatrix(matrix, m_drawTransform);
-        SkMatrix canvasMatrix = canvas->getTotalMatrix();
-        matrix.postConcat(canvasMatrix);
-        canvas->setMatrix(matrix);
-        onDraw(canvas, m_drawOpacity, 0, style);
-    }
-
-    if (!drawChildren)
-        return false;
-
-    // When the layer is dirty, the UI thread should be notified to redraw.
-    askScreenUpdate |= drawChildrenCanvas(canvas, style);
-    return askScreenUpdate;
-}
-
-bool LayerAndroid::drawGL(bool layerTilesDisabled)
-{
-    if (!layerTilesDisabled && m_imageCRC) {
-        ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC);
-        if (imageTexture)
-            imageTexture->drawGL(this, getOpacity());
-        ImagesManager::instance()->releaseImage(m_imageCRC);
-    }
-
-    state()->glExtras()->drawGL(this);
-    bool askScreenUpdate = false;
-
-    if (m_hasRunningAnimations)
-        askScreenUpdate = true;
-
-    return askScreenUpdate;
-}
-
-bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas, PaintStyle style)
-{
-    bool askScreenUpdate = false;
-    int count = this->countChildren();
-    if (count > 0) {
-        Vector <LayerAndroid*> sublayers;
-        for (int i = 0; i < count; i++)
-            sublayers.append(this->getChild(i));
-
-        // now we sort for the transparency
-        std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ);
-        for (int i = 0; i < count; i++) {
-            LayerAndroid* layer = sublayers[i];
-            askScreenUpdate |= layer->drawCanvas(canvas, true, style);
-        }
-    }
-
-    return askScreenUpdate;
-}
-
-void LayerAndroid::contentDraw(SkCanvas* canvas, PaintStyle style)
-{
-    if (m_maskLayer && m_maskLayer->m_content) {
-        // TODO: we should use a shader instead of doing
-        // the masking in software
-
-        if (m_originalLayer)
-            m_originalLayer->m_content->draw(canvas);
-        else if (m_content)
-            m_content->draw(canvas);
-
-        SkPaint maskPaint;
-        maskPaint.setXfermodeMode(SkXfermode::kDstIn_Mode);
-        int count = canvas->saveLayer(0, &maskPaint, SkCanvas::kHasAlphaLayer_SaveFlag);
-        m_maskLayer->m_content->draw(canvas);
-        canvas->restoreToCount(count);
-
-    } else if (m_content)
-        m_content->draw(canvas);
-
-    if (TilesManager::instance()->getShowVisualIndicator()) {
-        float w = getSize().width();
-        float h = getSize().height();
-        SkPaint paint;
-
-        if (style == MergedLayers)
-            paint.setARGB(255, 255, 255, 0);
-        else if (style == UnmergedLayers)
-            paint.setARGB(255, 255, 0, 0);
-        else if (style == FlattenedLayers)
-            paint.setARGB(255, 255, 0, 255);
-
-        canvas->drawLine(0, 0, w, h, paint);
-        canvas->drawLine(0, h, w, 0, paint);
-
-        canvas->drawLine(0, 0, 0, h-1, paint);
-        canvas->drawLine(0, h-1, w-1, h-1, paint);
-        canvas->drawLine(w-1, h-1, w-1, 0, paint);
-        canvas->drawLine(w-1, 0, 0, 0, paint);
-
-        static SkTypeface* s_typeface = 0;
-        if (!s_typeface)
-            s_typeface = SkTypeface::CreateFromName("", SkTypeface::kBold);
-        paint.setARGB(255, 0, 0, 255);
-        paint.setTextSize(17);
-        char str[256];
-        snprintf(str, 256, "%d", uniqueId());
-        paint.setTypeface(s_typeface);
-        canvas->drawText(str, strlen(str), 2, h - 2, paint);
-    }
-
-    if (m_fixedPosition)
-        return m_fixedPosition->contentDraw(canvas, style);
-}
-
-void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity,
-                          android::DrawExtra* extra, PaintStyle style)
-{
-    if (m_haveClip) {
-        SkRect r;
-        r.set(0, 0, getSize().width(), getSize().height());
-        canvas->clipRect(r);
-        return;
-    }
-
-    // only continue drawing if layer is drawable
-    if (!m_content && !m_imageCRC)
-        return;
-
-    // we just have this save/restore for opacity...
-    SkAutoCanvasRestore restore(canvas, true);
-
-    int canvasOpacity = SkScalarRound(opacity * 255);
-    if (canvasOpacity < 255)
-        canvas->setDrawFilter(new OpacityDrawFilter(canvasOpacity));
-
-    if (m_imageCRC) {
-        ImageTexture* imageTexture = ImagesManager::instance()->retainImage(m_imageCRC);
-        m_dirtyRegion.setEmpty();
-        if (imageTexture) {
-            SkRect dest;
-            dest.set(0, 0, getSize().width(), getSize().height());
-            imageTexture->drawCanvas(canvas, dest);
-        }
-        ImagesManager::instance()->releaseImage(m_imageCRC);
-    }
-    contentDraw(canvas, style);
-    if (extra)
-        extra->draw(canvas, this);
-}
-
-void LayerAndroid::setFixedPosition(FixedPositioning* position) {
-    if (m_fixedPosition && m_fixedPosition != position)
-        delete m_fixedPosition;
-    m_fixedPosition = position;
-}
-
-void LayerAndroid::dumpLayer(FILE* file, int indentLevel) const
-{
-    writeHexVal(file, indentLevel + 1, "layer", (int)this);
-    writeIntVal(file, indentLevel + 1, "layerId", m_uniqueId);
-    writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip);
-    writeIntVal(file, indentLevel + 1, "isFixed", isPositionFixed());
-
-    writeFloatVal(file, indentLevel + 1, "opacity", getOpacity());
-    writeSize(file, indentLevel + 1, "size", getSize());
-    writePoint(file, indentLevel + 1, "position", getPosition());
-    writePoint(file, indentLevel + 1, "anchor", getAnchorPoint());
-
-    writeMatrix(file, indentLevel + 1, "drawMatrix", m_drawTransform);
-    writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform);
-    writeRect(file, indentLevel + 1, "clippingRect", SkRect(m_clippingRect));
-
-    if (m_content) {
-        writeIntVal(file, indentLevel + 1, "m_content.width", m_content->width());
-        writeIntVal(file, indentLevel + 1, "m_content.height", m_content->height());
-    }
-
-    if (m_fixedPosition)
-        return m_fixedPosition->dumpLayer(file, indentLevel);
-}
-
-void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const
-{
-    writeln(file, indentLevel, "{");
-
-    dumpLayer(file, indentLevel);
-
-    if (countChildren()) {
-        writeln(file, indentLevel + 1, "children = [");
-        for (int i = 0; i < countChildren(); i++) {
-            if (i > 0)
-                writeln(file, indentLevel + 1, ", ");
-            getChild(i)->dumpLayers(file, indentLevel + 1);
-        }
-        writeln(file, indentLevel + 1, "];");
-    }
-    writeln(file, indentLevel, "}");
-}
-
-void LayerAndroid::dumpToLog() const
-{
-    FILE* file = fopen("/data/data/com.android.browser/layertmp", "w");
-    dumpLayers(file, 0);
-    fclose(file);
-    file = fopen("/data/data/com.android.browser/layertmp", "r");
-    char buffer[512];
-    bzero(buffer, sizeof(buffer));
-    while (fgets(buffer, sizeof(buffer), file))
-        SkDebugf("%s", buffer);
-    fclose(file);
-}
-
-LayerAndroid* LayerAndroid::findById(int match)
-{
-    if (m_uniqueId == match)
-        return this;
-    for (int i = 0; i < countChildren(); i++) {
-        LayerAndroid* result = getChild(i)->findById(match);
-        if (result)
-            return result;
-    }
-    return 0;
-}
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h
deleted file mode 100644
index 41f6420..0000000
--- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LayerAndroid_h
-#define LayerAndroid_h
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "FloatPoint.h"
-#include "FloatPoint3D.h"
-#include "FloatRect.h"
-#include "GraphicsLayerClient.h"
-#include "ImageTexture.h"
-#include "Layer.h"
-#include "PlatformString.h"
-#include "RefPtr.h"
-#include "SkBitmap.h"
-#include "SkColor.h"
-#include "SkRegion.h"
-#include "SkStream.h"
-#include "TransformationMatrix.h"
-
-#include <utils/threads.h>
-#include <wtf/HashMap.h>
-
-#ifndef BZERO_DEFINED
-#define BZERO_DEFINED
-// http://www.opengroup.org/onlinepubs/000095399/functions/bzero.html
-// For maximum portability, it is recommended to replace the function call to bzero() as follows:
-#define bzero(b, len) (memset((b), '\0', (len)), (void) 0)
-#endif
-
-class SkBitmapRef;
-class SkCanvas;
-class SkMatrix;
-class SkPicture;
-
-namespace WebCore {
-class LayerAndroid;
-class LayerContent;
-class ImageTexture;
-class Surface;
-}
-
-namespace android {
-class DrawExtra;
-void serializeLayer(WebCore::LayerAndroid* layer, SkWStream* stream);
-WebCore::LayerAndroid* deserializeLayer(int version, SkStream* stream);
-void cleanupImageRefs(WebCore::LayerAndroid* layer);
-}
-
-using namespace android;
-
-namespace WebCore {
-
-class AndroidAnimation;
-class FixedPositioning;
-class GLWebViewState;
-class IFrameLayerAndroid;
-class LayerMergeState;
-class RenderLayer;
-class PaintedSurface;
-
-class TexturesResult {
-public:
-    TexturesResult()
-        : fixed(0)
-        , scrollable(0)
-        , clipped(0)
-        , full(0)
-    {}
-
-    int fixed;
-    int scrollable;
-    int clipped;
-    int full;
-};
-
-class TEST_EXPORT LayerAndroid : public Layer {
-public:
-    typedef enum { UndefinedLayer, WebCoreLayer, UILayer } LayerType;
-    typedef enum { StandardLayer, ScrollableLayer,
-                   IFrameLayer, IFrameContentLayer,
-                   FixedBackgroundLayer,
-                   FixedBackgroundImageLayer,
-                   ForegroundBaseLayer,
-                   CanvasLayer, BaseLayer } SubclassType;
-    typedef enum { InvalidateNone = 0, InvalidateLayers } InvalidateFlags;
-
-    String subclassName()
-    {
-        switch (subclassType()) {
-            case LayerAndroid::StandardLayer:
-                return "StandardLayer";
-            case LayerAndroid::ScrollableLayer:
-                return "ScrollableLayer";
-            case LayerAndroid::IFrameLayer:
-                return "IFrameLayer";
-            case LayerAndroid::IFrameContentLayer:
-                return "IFrameContentLayer";
-            case LayerAndroid::FixedBackgroundLayer:
-                return "FixedBackgroundLayer";
-            case LayerAndroid::FixedBackgroundImageLayer:
-                return "FixedBackgroundImageLayer";
-            case LayerAndroid::ForegroundBaseLayer:
-                return "ForegroundBaseLayer";
-            case LayerAndroid::CanvasLayer:
-                return "CanvasLayer";
-            case LayerAndroid::BaseLayer:
-                return "BaseLayer";
-        }
-        return "Undefined";
-    }
-
-    LayerAndroid(RenderLayer* owner);
-    LayerAndroid(const LayerAndroid& layer);
-    virtual ~LayerAndroid();
-
-    void setBackfaceVisibility(bool value) { m_backfaceVisibility = value; }
-    void setTransform(const TransformationMatrix& matrix) { m_transform = matrix; }
-    FloatPoint translation() const;
-    IntRect clippedRect() const;
-    bool outsideViewport();
-
-    // Returns the full area of the layer mapped into global content coordinates
-    FloatRect fullContentAreaMapped() const;
-
-    IntRect fullContentArea() const;
-    IntRect visibleContentArea(bool force3dContentVisible = false) const;
-
-    virtual bool needsTexture();
-
-    // Debug helper methods
-    int nbLayers();
-    int nbTexturedLayers();
-    void showLayer(int indent = 0);
-
-    float getScale() { return m_scale; }
-
-    virtual bool drawGL(bool layerTilesDisabled);
-    virtual bool drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle style);
-    bool drawChildrenCanvas(SkCanvas* canvas, PaintStyle style);
-
-    void updateGLPositionsAndScale(const TransformationMatrix& parentMatrix,
-                                   const FloatRect& clip, float opacity, float scale,
-                                   bool forceCalculations, bool disableFixedElemUpdate);
-    void setDrawOpacity(float opacity) { m_drawOpacity = opacity; }
-    float drawOpacity() { return m_drawOpacity; }
-    bool visible();
-    void setVisible(bool value) { m_visible = value; }
-
-    bool preserves3D() { return m_preserves3D; }
-    void setPreserves3D(bool value) { m_preserves3D = value; }
-    void setAnchorPointZ(float z) { m_anchorPointZ = z; }
-    float anchorPointZ() { return m_anchorPointZ; }
-    void setDrawTransform(const TransformationMatrix& transform) { m_drawTransform = m_drawTransformUnfudged = transform; }
-    virtual const TransformationMatrix* drawTransform() const { return &m_drawTransform; }
-    void setChildrenTransform(const TransformationMatrix& t) { m_childrenTransform = t; }
-    void setDrawClip(const FloatRect& rect) { m_clippingRect = rect; }
-    const FloatRect& drawClip() { return m_clippingRect; }
-
-    void setBackgroundColor(SkColor color);
-    void setMaskLayer(LayerAndroid*);
-    void setMasksToBounds(bool masksToBounds)
-    {
-        m_haveClip = masksToBounds;
-    }
-    bool masksToBounds() const { return m_haveClip; }
-
-    LayerContent* content() { return m_content; }
-    void setContent(LayerContent* content);
-    // Check to see if the dirty area of this layer can be updated with a blit
-    // from the prerender instead of needing to generate tiles from the LayerContent
-    bool canUpdateWithBlit();
-
-    void addAnimation(PassRefPtr<AndroidAnimation> anim);
-    void removeAnimationsForProperty(AnimatedPropertyID property);
-    void removeAnimationsForKeyframes(const String& name);
-    bool evaluateAnimations();
-    bool evaluateAnimations(double time);
-    void initAnimations();
-    bool hasAnimations() const;
-    void addDirtyArea();
-
-    virtual void dumpLayer(FILE*, int indentLevel) const;
-    void dumpLayers(FILE*, int indentLevel) const;
-    void dumpToLog() const;
-
-    virtual IFrameLayerAndroid* updatePosition(SkRect viewport,
-                                               IFrameLayerAndroid* parentIframeLayer);
-
-    /** Call this to update the position attribute, so that later calls
-        like bounds() will report the corrected position.
-
-        This call is recursive, so it should be called on the root of the
-        hierarchy.
-     */
-    void updatePositions();
-
-    const LayerAndroid* find(int* xPtr, int* yPtr, SkPicture* root) const;
-    const LayerAndroid* findById(int uniqueID) const
-    {
-        return const_cast<LayerAndroid*>(this)->findById(uniqueID);
-    }
-    LayerAndroid* findById(int uniqueID);
-    LayerAndroid* getChild(int index) const
-    {
-        return static_cast<LayerAndroid*>(this->INHERITED::getChild(index));
-    }
-    int uniqueId() const { return m_uniqueId; }
-
-    /** This sets a content image -- calling it means we will use
-        the image directly when drawing the layer instead of using
-        the content painted by WebKit.
-        Images are handled in ImagesManager, as they can be shared
-        between layers.
-    */
-    void setContentsImage(SkBitmapRef* img);
-
-    virtual LayerAndroid* copy() const { return new LayerAndroid(*this); }
-
-    virtual void clearDirtyRegion();
-
-    virtual void contentDraw(SkCanvas* canvas, PaintStyle style);
-
-    virtual bool isMedia() const { return false; }
-    virtual bool isVideo() const { return false; }
-    virtual bool isIFrame() const { return false; }
-    virtual bool isIFrameContent() const { return false; }
-    virtual bool isFixedBackground() const { return false; }
-
-    bool isPositionFixed() const { return m_fixedPosition; }
-    void setAbsolutePosition(bool isAbsolute) { m_isPositionAbsolute = isAbsolute; }
-    bool isPositionAbsolute() { return m_isPositionAbsolute; }
-    void setFixedPosition(FixedPositioning* position);
-    FixedPositioning* fixedPosition() { return m_fixedPosition; }
-
-    RenderLayer* owningLayer() const { return m_owningLayer; }
-
-    float zValue() const { return m_zValue; }
-
-    // ViewStateSerializer friends
-    friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream);
-    friend LayerAndroid* android::deserializeLayer(int version, SkStream* stream);
-    friend void android::cleanupImageRefs(LayerAndroid* layer);
-
-    LayerType type() { return m_type; }
-    virtual SubclassType subclassType() const { return LayerAndroid::StandardLayer; }
-
-    bool hasText();
-
-    void copyAnimationStartTimesRecursive(LayerAndroid* oldTree);
-
-// rendering asset management
-    SkRegion* getInvalRegion() { return &m_dirtyRegion; }
-    void mergeInvalsInto(LayerAndroid* replacementTree);
-
-    bool canJoinSurface(Surface* surface);
-    void assignSurfaces(LayerMergeState* mergeState);
-    Surface* surface() { return m_surface; }
-
-    void setIntrinsicallyComposited(bool intCom) { m_intrinsicallyComposited = intCom; }
-    virtual bool needsIsolatedSurface() {
-        return (needsTexture() && m_intrinsicallyComposited)
-            || m_animations.size()
-            || m_imageCRC;
-    }
-
-    int setHwAccelerated(bool hwAccelerated);
-
-    void setReplicatedLayer(LayerAndroid* layer) { m_replicatedLayer = layer; }
-    void setReplicatedLayerPosition(const FloatPoint& p) { m_replicatedLayerPosition = p; }
-    void setOriginalLayer(LayerAndroid* layer) { m_originalLayer = layer; }
-    bool hasReplicatedLayer() { return m_replicatedLayer; }
-    const TransformationMatrix* replicatedLayerDrawTransform() {
-        if (m_replicatedLayer)
-            return m_replicatedLayer->drawTransform();
-        return 0;
-    }
-
-protected:
-    /** Call this with the current viewport (scrolling, zoom) to update
-        the position of the fixed layers.
-
-        This call is recursive, so it should be called on the root of the
-        hierarchy.
-    */
-    void updateLayerPositions(SkRect viewPort, IFrameLayerAndroid* parentIframeLayer = 0);
-    virtual void onDraw(SkCanvas*, SkScalar opacity, android::DrawExtra* extra, PaintStyle style);
-    virtual InvalidateFlags onSetHwAccelerated(bool hwAccelerated) { return InvalidateNone; }
-    TransformationMatrix m_drawTransform;
-    TransformationMatrix m_drawTransformUnfudged;
-    int m_uniqueId;
-
-private:
-    void updateLocalTransformAndClip(const TransformationMatrix& parentMatrix,
-                                     const FloatRect& clip);
-    bool hasDynamicTransform() {
-        return contentIsScrollable() || isPositionFixed() || (m_animations.size() != 0);
-    }
-
-#if DUMP_NAV_CACHE
-    friend class CachedLayer::Debug; // debugging access only
-#endif
-
-    void copyAnimationStartTimes(LayerAndroid* oldLayer);
-    bool prepareContext(bool force = false);
-
-    // -------------------------------------------------------------------
-    // Fields to be serialized
-    // -------------------------------------------------------------------
-
-    bool m_haveClip;
-    bool m_backgroundColorSet;
-
-    bool m_backfaceVisibility;
-    bool m_visible;
-
-protected:
-    SkColor m_backgroundColor;
-
-private:
-
-    bool m_preserves3D;
-    float m_anchorPointZ;
-    float m_drawOpacity;
-
-    bool m_isPositionAbsolute;
-
-protected:
-    FixedPositioning* m_fixedPosition;
-
-private:
-
-    typedef HashMap<pair<String, int>, RefPtr<AndroidAnimation> > KeyframesMap;
-    KeyframesMap m_animations;
-
-    TransformationMatrix m_transform;
-    TransformationMatrix m_childrenTransform;
-
-    // -------------------------------------------------------------------
-    // Fields that are not serialized (generated, cached, or non-serializable)
-    // -------------------------------------------------------------------
-
-    float m_zValue;
-
-    FloatRect m_clippingRect;
-
-    // Note that m_content and m_imageCRC are mutually exclusive;
-    // m_content is used when WebKit is asked to paint the layer's
-    // content, while m_imageCRC references an image that we directly
-    // composite, using the layer's dimensions as a destination rect.
-    // We do this as if the layer only contains an image, directly compositing
-    // it is a much faster method than using m_content.
-    LayerContent* m_content;
-
-protected:
-    unsigned m_imageCRC;
-
-private:
-
-    // used to signal the framework we need a repaint
-    bool m_hasRunningAnimations;
-
-    float m_scale;
-
-    // We try to not always compute the texture size, as this is quite heavy
-    static const double s_computeTextureDelay = 0.2; // 200 ms
-    double m_lastComputeTextureSize;
-
-    RenderLayer* m_owningLayer;
-
-    LayerType m_type;
-    SubclassType m_subclassType;
-
-    bool m_intrinsicallyComposited;
-
-    Surface* m_surface;
-
-    // link to a replicated layer (used e.g. for reflections)
-    LayerAndroid* m_replicatedLayer;
-    FloatPoint    m_replicatedLayerPosition;
-    LayerAndroid* m_originalLayer;
-    // link to a mask layer
-    LayerAndroid* m_maskLayer;
-
-    typedef Layer INHERITED;
-};
-
-}
-
-#else
-
-class SkPicture;
-
-namespace WebCore {
-
-class LayerAndroid {
-public:
-    LayerAndroid(SkPicture* picture) :
-        m_recordingPicture(picture), // does not assign ownership
-        m_uniqueId(-1)
-    {}
-    SkPicture* picture() const { return m_recordingPicture; }
-    int uniqueId() const { return m_uniqueId; }
-private:
-    SkPicture* m_recordingPicture;
-    int m_uniqueId;
-};
-
-}
-
-#endif // USE(ACCELERATED_COMPOSITING)
-
-#endif // LayerAndroid_h
diff --git a/Source/WebCore/platform/graphics/android/layers/LayerContent.h b/Source/WebCore/platform/graphics/android/layers/LayerContent.h
deleted file mode 100644
index 10b6507..0000000
--- a/Source/WebCore/platform/graphics/android/layers/LayerContent.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef LayerContent_h
-#define LayerContent_h
-
-#include "IntRect.h"
-#include "SkRefCnt.h"
-#include <utils/threads.h>
-
-class SkCanvas;
-class SkPicture;
-class SkWStream;
-
-namespace WebCore {
-
-class PrerenderedInval;
-
-class LayerContent : public SkRefCnt {
-public:
-    virtual int width() = 0;
-    virtual int height() = 0;
-    virtual bool isEmpty() { return !width() || !height(); }
-    virtual void setCheckForOptimisations(bool check) = 0;
-    virtual void checkForOptimisations() = 0;
-    virtual bool hasText() = 0;
-    virtual void draw(SkCanvas* canvas) = 0;
-    virtual PrerenderedInval* prerenderForRect(const IntRect& dirty) { return 0; }
-    virtual void clearPrerenders() { };
-
-    virtual void serialize(SkWStream* stream) = 0;
-
-protected:
-    // used to prevent parallel draws, as both SkPicture and PictureSet don't support them
-    android::Mutex m_drawLock;
-};
-
-} // WebCore
-
-#endif // LayerContent_h
diff --git a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp
deleted file mode 100644
index 4398146..0000000
--- a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#include "config.h"
-#include "PictureLayerContent.h"
-
-#include "InspectorCanvas.h"
-#include "SkPicture.h"
-
-namespace WebCore {
-
-PictureLayerContent::PictureLayerContent(SkPicture* picture)
-    : m_picture(picture)
-    , m_checkedContent(false)
-    , m_hasText(true)
-{
-    SkSafeRef(m_picture);
-}
-
-PictureLayerContent::PictureLayerContent(const PictureLayerContent& content)
-    : m_picture(content.m_picture)
-    , m_checkedContent(content.m_checkedContent)
-    , m_hasText(content.m_hasText)
-{
-    SkSafeRef(m_picture);
-}
-
-PictureLayerContent::~PictureLayerContent()
-{
-    SkSafeUnref(m_picture);
-}
-
-int PictureLayerContent::width()
-{
-    if (!m_picture)
-        return 0;
-    return m_picture->width();
-}
-
-int PictureLayerContent::height()
-{
-    if (!m_picture)
-        return 0;
-    return m_picture->height();
-}
-
-bool PictureLayerContent::isEmpty()
-{
-    if (!m_picture)
-        return true;
-    if (m_picture->width() == 0
-        || m_picture->height() == 0)
-        return true;
-    return false;
-}
-
-void PictureLayerContent::checkForOptimisations()
-{
-    if (!m_checkedContent)
-        hasText(); // for now only check the presence of text
-}
-
-bool PictureLayerContent::hasText()
-{
-    if (m_checkedContent)
-        return m_hasText;
-
-    // Let's check if we have text or not. If we don't, we can limit
-    // ourselves to scale 1!
-    InspectorBounder inspectorBounder;
-    InspectorCanvas checker(&inspectorBounder, m_picture);
-    SkBitmap bitmap;
-    bitmap.setConfig(SkBitmap::kARGB_8888_Config,
-                     m_picture->width(),
-                     m_picture->height());
-    checker.setBitmapDevice(bitmap);
-    checker.drawPicture(*m_picture);
-    m_hasText = checker.hasText();
-    if (!checker.hasContent()) {
-        // no content to draw, discard picture so UI / tile generation
-        // doesn't bother with it
-        SkSafeUnref(m_picture);
-        m_picture = 0;
-    }
-
-    m_checkedContent = true;
-
-    return m_hasText;
-}
-
-void PictureLayerContent::draw(SkCanvas* canvas)
-{
-    if (!m_picture)
-        return;
-
-    android::Mutex::Autolock lock(m_drawLock);
-    SkRect r = SkRect::MakeWH(width(), height());
-    canvas->clipRect(r);
-    canvas->drawPicture(*m_picture);
-}
-
-void PictureLayerContent::serialize(SkWStream* stream)
-{
-    if (!m_picture)
-        return;
-    m_picture->serialize(stream);
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h b/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h
deleted file mode 100644
index 1567f44..0000000
--- a/Source/WebCore/platform/graphics/android/layers/PictureLayerContent.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef PictureLayerContent_h
-#define PictureLayerContent_h
-
-#include "LayerContent.h"
-
-namespace WebCore {
-
-class PictureLayerContent : public LayerContent {
-public:
-    PictureLayerContent(SkPicture* picture);
-    PictureLayerContent(const PictureLayerContent& content);
-    ~PictureLayerContent();
-
-    virtual int width();
-    virtual int height();
-    virtual bool isEmpty();
-    virtual void setCheckForOptimisations(bool check) { m_checkedContent = !check; }
-    virtual void checkForOptimisations();
-    virtual bool hasText();
-    virtual void draw(SkCanvas* canvas);
-    virtual void serialize(SkWStream* stream);
-
-private:
-    SkPicture* m_picture;
-    bool m_checkedContent;
-    bool m_hasText;
-};
-
-} // WebCore
-
-#endif // PictureLayerContent_h
diff --git a/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp b/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp
deleted file mode 100644
index b648e72..0000000
--- a/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#include "config.h"
-#include "PicturePileLayerContent.h"
-
-#include "SkCanvas.h"
-#include "SkPicture.h"
-
-namespace WebCore {
-
-PicturePileLayerContent::PicturePileLayerContent(const PicturePile& picturePile)
-    : m_picturePile(picturePile)
-{
-}
-
-void PicturePileLayerContent::draw(SkCanvas* canvas)
-{
-    android::Mutex::Autolock lock(m_drawLock);
-    m_picturePile.draw(canvas);
-}
-
-void PicturePileLayerContent::serialize(SkWStream* stream)
-{
-    if (!stream)
-       return;
-    SkPicture picture;
-    draw(picture.beginRecording(width(), height(),
-                                SkPicture::kUsePathBoundsForClip_RecordingFlag));
-    picture.endRecording();
-    picture.serialize(stream);
-}
-
-PrerenderedInval* PicturePileLayerContent::prerenderForRect(const IntRect& dirty)
-{
-    return m_picturePile.prerenderedInvalForArea(dirty);
-}
-
-void PicturePileLayerContent::clearPrerenders()
-{
-    m_picturePile.clearPrerenders();
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.h b/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.h
deleted file mode 100644
index 4fc123e..0000000
--- a/Source/WebCore/platform/graphics/android/layers/PicturePileLayerContent.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef PicturePileLayerContent_h
-#define PicturePileLayerContent_h
-
-#include "LayerContent.h"
-#include "PicturePile.h"
-
-namespace WebCore {
-
-class PicturePileLayerContent : public LayerContent {
-public:
-    PicturePileLayerContent(const PicturePile& picturePile);
-
-    virtual int width() { return m_picturePile.size().width(); }
-    virtual int height() { return m_picturePile.size().height(); }
-    virtual void setCheckForOptimisations(bool check) {}
-    virtual void checkForOptimisations() {}
-    virtual bool hasText() { return true; }
-    virtual void draw(SkCanvas* canvas);
-    virtual void serialize(SkWStream* stream);
-    virtual PrerenderedInval* prerenderForRect(const IntRect& dirty);
-    virtual void clearPrerenders();
-
-private:
-    PicturePile m_picturePile;
-};
-
-} // WebCore
-
-#endif // PicturePileLayerContent_h
diff --git a/Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.cpp
deleted file mode 100644
index c29ab2d..0000000
--- a/Source/WebCore/platform/graphics/android/layers/ScrollableLayerAndroid.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-#define LOG_TAG "ScrollableLayerAndroid"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "ScrollableLayerAndroid.h"
-
-#include "GLWebViewState.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "AndroidLog.h"
-
-namespace WebCore {
-
-bool ScrollableLayerAndroid::scrollTo(int x, int y)
-{
-    IntRect scrollBounds;
-    getScrollBounds(&scrollBounds);
-    if (!scrollBounds.width() && !scrollBounds.height())
-        return false;
-    SkScalar newX = SkScalarPin(x, scrollBounds.x(), scrollBounds.width());
-    SkScalar newY = SkScalarPin(y, scrollBounds.y(), scrollBounds.height());
-    // Check for no change.
-    if (newX == getScrollOffset().x() && newY == getScrollOffset().y())
-        return false;
-    setScrollOffset(IntPoint(newX, newY));
-    return true;
-}
-
-void ScrollableLayerAndroid::getScrollBounds(IntRect* out) const
-{
-    out->setX(m_scrollLimits.fLeft);
-    out->setY(m_scrollLimits.fTop);
-    out->setWidth(m_scrollLimits.width());
-    out->setHeight(m_scrollLimits.height());
-}
-
-void ScrollableLayerAndroid::getScrollRect(SkIRect* out) const
-{
-    out->fLeft = getScrollOffset().x();
-    out->fTop = getScrollOffset().y();
-
-    out->fRight = m_scrollLimits.width();
-    out->fBottom = m_scrollLimits.height();
-}
-
-void ScrollableLayerAndroid::setScrollLimits(float minX, float minY,
-                                             float maxX, float maxY)
-{
-    if (minX < 0) minX = 0;
-    if (minY < 0) minY = 0;
-    if (maxX < 0) maxX = 0;
-    if (maxY < 0) maxY = 0;
-    if (minX > maxX) minX = maxX;
-    if (minY > maxY) minY = maxY;
-    m_scrollLimits.set(minX, minY, minX + maxX, minY + maxY);
-}
-
-bool ScrollableLayerAndroid::scrollRectIntoView(const SkIRect& rect)
-{
-    // Apply the local transform to the rect to get it relative to the parent
-    // layer.
-    SkMatrix localTransform;
-    getLocalTransform(&localTransform);
-    SkRect transformedRect;
-    transformedRect.set(rect);
-    localTransform.mapRect(&transformedRect);
-
-    // Test left before right to prioritize left alignment if transformedRect is wider than
-    // visible area.
-    int x = m_scrollLimits.fLeft;
-    if (transformedRect.fLeft < m_scrollLimits.fLeft)
-        x = transformedRect.fLeft;
-    else if (transformedRect.fRight > m_scrollLimits.fRight)
-        x = transformedRect.fRight - std::max(m_scrollLimits.width(), transformedRect.width());
-
-    // Test top before bottom to prioritize top alignment if transformedRect is taller than
-    // visible area.
-    int y = m_scrollLimits.fTop;
-    if (transformedRect.fTop < m_scrollLimits.fTop)
-        y = transformedRect.fTop;
-    else if (transformedRect.fBottom > m_scrollLimits.fBottom)
-        y = transformedRect.fBottom - std::max(m_scrollLimits.height(), transformedRect.height());
-
-    return scrollTo(x - getPosition().fX, y - getPosition().fY);
-}
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.cpp
deleted file mode 100644
index 39bbec6..0000000
--- a/Source/WebCore/platform/graphics/android/layers/VideoLayerAndroid.cpp
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright 2011 The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "VideoLayerAndroid"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "VideoLayerAndroid.h"
-
-#include "AndroidLog.h"
-#include "DrawQuadData.h"
-#include "ShaderProgram.h"
-#include "TilesManager.h"
-#include <GLES2/gl2.h>
-#include <gui/SurfaceTexture.h>
-
-#if USE(ACCELERATED_COMPOSITING)
-
-namespace WebCore {
-
-double VideoLayerAndroid::m_rotateDegree = 0;
-
-VideoLayerAndroid::VideoLayerAndroid()
-    : LayerAndroid((RenderLayer*)0)
-{
-    init();
-}
-
-VideoLayerAndroid::VideoLayerAndroid(const VideoLayerAndroid& layer)
-    : LayerAndroid(layer)
-{
-    init();
-}
-
-void VideoLayerAndroid::init()
-{
-    // m_surfaceTexture is only useful on UI thread, no need to copy.
-    // And it will be set at setBaseLayer timeframe
-    m_playerState = INITIALIZED;
-}
-
-// We can use this function to set the Layer to point to surface texture.
-void VideoLayerAndroid::setSurfaceTexture(sp<SurfaceTexture> texture,
-                                          int textureName, PlayerState playerState)
-{
-    m_surfaceTexture = texture;
-    m_playerState = playerState;
-    TilesManager::instance()->videoLayerManager()->registerTexture(uniqueId(), textureName);
-}
-
-void VideoLayerAndroid::showPreparingAnimation(const SkRect& rect,
-                                               const SkRect innerRect)
-{
-    ShaderProgram* shader = TilesManager::instance()->shader();
-    VideoLayerManager* manager = TilesManager::instance()->videoLayerManager();
-    // Paint the video content's background.
-    PureColorQuadData backGroundQuadData(Color(128, 128, 128, 255), LayerQuad,
-                                         &m_drawTransform, &rect);
-    shader->drawQuad(&backGroundQuadData);
-
-    TransformationMatrix addReverseRotation;
-    TransformationMatrix addRotation = m_drawTransform;
-    addRotation.translate(innerRect.fLeft, innerRect.fTop);
-    double halfButtonSize = manager->getButtonSize() / 2;
-    addRotation.translate(halfButtonSize, halfButtonSize);
-    addReverseRotation = addRotation;
-    addRotation.rotate(m_rotateDegree);
-    addRotation.translate(-halfButtonSize, -halfButtonSize);
-
-    SkRect size = SkRect::MakeWH(innerRect.width(), innerRect.height());
-
-    TextureQuadData spinnerQuadData(manager->getSpinnerOuterTextureId(),
-                                    GL_TEXTURE_2D, GL_LINEAR,
-                                    LayerQuad, &addRotation, &size);
-    shader->drawQuad(&spinnerQuadData);
-
-    addReverseRotation.rotate(-m_rotateDegree);
-    addReverseRotation.translate(-halfButtonSize, -halfButtonSize);
-
-    spinnerQuadData.updateTextureId(manager->getSpinnerInnerTextureId());
-    spinnerQuadData.updateDrawMatrix(&addReverseRotation);
-    shader->drawQuad(&spinnerQuadData);
-
-    m_rotateDegree += ROTATESTEP;
-}
-
-SkRect VideoLayerAndroid::calVideoRect(const SkRect& rect)
-{
-    SkRect videoRect = rect;
-    VideoLayerManager* manager = TilesManager::instance()->videoLayerManager();
-    float aspectRatio = manager->getAspectRatio(uniqueId());
-    float deltaY = rect.height() - rect.width() / aspectRatio;
-    if (deltaY >= 0)
-        videoRect.inset(0, deltaY / 2);
-    else {
-        float deltaX = rect.width() - rect.height() * aspectRatio;
-        if (deltaX >= 0)
-            videoRect.inset(deltaX / 2, 0);
-    }
-    return videoRect;
-}
-
-bool VideoLayerAndroid::drawGL(bool layerTilesDisabled)
-{
-    // Lazily allocated the textures.
-    TilesManager* tilesManager = TilesManager::instance();
-    VideoLayerManager* manager = tilesManager->videoLayerManager();
-    manager->initGLResourcesIfNeeded();
-
-    ShaderProgram* shader = tilesManager->shader();
-
-    SkRect rect = SkRect::MakeSize(getSize());
-    GLfloat surfaceMatrix[16];
-
-    // Calculate the video rect based on the aspect ratio and the element rect.
-    SkRect videoRect = calVideoRect(rect);
-    PureColorQuadData pureColorQuadData(Color(0, 0, 0, 255), LayerQuad,
-                                        &m_drawTransform, &rect);
-
-    if (videoRect != rect) {
-        // Paint the whole video element with black color when video content
-        // can't cover the whole area.
-        shader->drawQuad(&pureColorQuadData);
-    }
-
-    // Inner rect is for the progressing / play / pause animation.
-    SkRect innerRect = SkRect::MakeWH(manager->getButtonSize(),
-                                      manager->getButtonSize());
-    if (innerRect.contains(videoRect))
-        innerRect = videoRect;
-    double buttonSize = manager->getButtonSize();
-    innerRect.offset(videoRect.fLeft + (videoRect.width() - buttonSize) / 2,
-                     videoRect.fTop + (videoRect.height() - buttonSize) / 2);
-
-    // When we are drawing the animation of the play/pause button in the
-    // middle of the video, we need to ask for redraw.
-    bool needRedraw = false;
-    TextureQuadData iconQuadData(0, GL_TEXTURE_2D, GL_LINEAR, LayerQuad,
-                                 &m_drawTransform, &innerRect);
-    // Draw the poster image, the progressing image or the Video depending
-    // on the player's state.
-    if (m_playerState == PREPARING) {
-        // Show the progressing animation, with two rotating circles
-        showPreparingAnimation(videoRect, innerRect);
-        needRedraw = true;
-    } else if (m_playerState == PLAYING && m_surfaceTexture.get()) {
-        // Show the real video.
-        m_surfaceTexture->updateTexImage();
-        m_surfaceTexture->getTransformMatrix(surfaceMatrix);
-        GLuint textureId = manager->getTextureId(uniqueId());
-        shader->drawVideoLayerQuad(m_drawTransform, surfaceMatrix,
-                                   videoRect, textureId);
-        manager->updateMatrix(uniqueId(), surfaceMatrix);
-
-        // Use the scale to control the fading the sizing during animation
-        double scale = manager->drawIcon(uniqueId(), PlayIcon);
-        if (scale) {
-            innerRect.inset(manager->getButtonSize() / 4 * scale,
-                            manager->getButtonSize() / 4 * scale);
-            iconQuadData.updateTextureId(manager->getPlayTextureId());
-            iconQuadData.updateOpacity(scale);
-            shader->drawQuad(&iconQuadData);
-            needRedraw = true;
-        }
-    } else {
-        GLuint textureId = manager->getTextureId(uniqueId());
-        GLfloat* matrix = manager->getMatrix(uniqueId());
-        if (textureId && matrix) {
-            // Show the screen shot for each video.
-            shader->drawVideoLayerQuad(m_drawTransform, matrix,
-                                       videoRect, textureId);
-        } else {
-            // Show the static poster b/c there is no screen shot available.
-            pureColorQuadData.updateColor(Color(128, 128, 128, 255));
-            shader->drawQuad(&pureColorQuadData);
-
-            iconQuadData.updateTextureId(manager->getPosterTextureId());
-            iconQuadData.updateOpacity(1.0);
-            shader->drawQuad(&iconQuadData);
-        }
-
-        // Use the scale to control the fading and the sizing during animation.
-        double scale = manager->drawIcon(uniqueId(), PauseIcon);
-        if (scale) {
-            innerRect.inset(manager->getButtonSize() / 4 * scale,
-                            manager->getButtonSize() / 4 * scale);
-            iconQuadData.updateTextureId(manager->getPauseTextureId());
-            iconQuadData.updateOpacity(scale);
-            shader->drawQuad(&iconQuadData);
-            needRedraw = true;
-        }
-
-    }
-    return needRedraw;
-}
-
-}
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp
deleted file mode 100644
index a7b3184..0000000
--- a/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Copyright 2011 The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "VideoLayerManager"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "VideoLayerManager.h"
-
-#include "AndroidLog.h"
-#include "RenderSkinMediaButton.h"
-#include "SkCanvas.h"
-#include <wtf/CurrentTime.h>
-
-#if USE(ACCELERATED_COMPOSITING)
-
-// The animation of the play/pause icon will last for PLAY_PAUSE_ICON_SHOW_TIME
-// seconds.
-#define PLAY_PAUSE_ICON_SHOW_TIME 1
-
-// Define the max sum of all the video's sizes.
-// Note that video_size = width * height. If there is no compression, then the
-// maximum memory consumption could be 4 * video_size.
-// Setting this to 2M, means that maximum memory consumption of all the
-// screenshots would not be above 8M.
-#define MAX_VIDEOSIZE_SUM 2097152
-
-// We don't preload the video data, so we don't have the exact size yet.
-// Assuming 16:9 by default, this will be corrected after video prepared.
-#define DEFAULT_VIDEO_ASPECT_RATIO 1.78
-
-#define VIDEO_TEXTURE_NUMBER 5
-#define VIDEO_BUTTON_SIZE 64
-
-namespace WebCore {
-
-VideoLayerManager::VideoLayerManager()
-    : m_currentTimeStamp(0)
-    , m_createdTexture(false)
-    , m_posterTextureId(0)
-    , m_spinnerOuterTextureId(0)
-    , m_spinnerInnerTextureId(0)
-    , m_playTextureId(0)
-    , m_pauseTextureId(0)
-    , m_buttonRect(0, 0, VIDEO_BUTTON_SIZE, VIDEO_BUTTON_SIZE)
-{
-}
-
-int VideoLayerManager::getButtonSize()
-{
-    return VIDEO_BUTTON_SIZE;
-}
-
-GLuint VideoLayerManager::createTextureFromImage(int buttonType)
-{
-    SkRect rect = SkRect(m_buttonRect);
-    SkBitmap bitmap;
-    bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height());
-    bitmap.allocPixels();
-    bitmap.eraseColor(0);
-
-    SkCanvas canvas(bitmap);
-    canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode);
-    RenderSkinMediaButton::Draw(&canvas, m_buttonRect, buttonType, true, 0,
-                                false);
-
-    GLuint texture;
-    glGenTextures(1, &texture);
-
-    GLUtils::createTextureWithBitmap(texture, bitmap);
-    bitmap.reset();
-    return texture;
-}
-
-// Should be called at the VideoLayerAndroid::drawGL to make sure we allocate
-// the GL resources lazily.
-void VideoLayerManager::initGLResourcesIfNeeded()
-{
-    if (!m_createdTexture) {
-        ALOGD("Reinit GLResource for VideoLayer");
-        initGLResources();
-    }
-}
-
-void VideoLayerManager::initGLResources()
-{
-    GLUtils::checkGlError("before initGLResources()");
-    m_spinnerOuterTextureId =
-        createTextureFromImage(RenderSkinMediaButton::SPINNER_OUTER);
-    m_spinnerInnerTextureId =
-        createTextureFromImage(RenderSkinMediaButton::SPINNER_INNER);
-    m_posterTextureId =
-        createTextureFromImage(RenderSkinMediaButton::VIDEO);
-    m_playTextureId = createTextureFromImage(RenderSkinMediaButton::PLAY);
-    m_pauseTextureId = createTextureFromImage(RenderSkinMediaButton::PAUSE);
-
-    m_createdTexture = !GLUtils::checkGlError("initGLResources()");
-    return;
-}
-
-void VideoLayerManager::cleanupGLResources()
-{
-    if (m_createdTexture) {
-        GLuint videoTextures[VIDEO_TEXTURE_NUMBER] = { m_spinnerOuterTextureId,
-            m_spinnerInnerTextureId, m_posterTextureId, m_playTextureId,
-            m_pauseTextureId };
-
-        glDeleteTextures(VIDEO_TEXTURE_NUMBER, videoTextures);
-        m_createdTexture = false;
-    }
-    // Delete the texture in retired mode, but have not hit draw call to be
-    // removed.
-    deleteUnusedTextures();
-
-    // Go over the registered GL textures (screen shot textures) and delete them.
-    android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
-    InfoIterator end = m_videoLayerInfoMap.end();
-    for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it) {
-        // The map include every video has been played, so their textureId can
-        // be deleted already, like hitting onTrimMemory multiple times.
-        if (it->second->textureId) {
-            ALOGV("delete texture from the map %d", it->second->textureId);
-            glDeleteTextures(1, &it->second->textureId);
-            // Set the textureID to 0 to show the video icon.
-            it->second->textureId = 0;
-        }
-    }
-
-    GLUtils::checkGlError("cleanupGLResources()");
-    return;
-}
-
-// Getting TextureId for GL draw call, in the UI thread.
-GLuint VideoLayerManager::getTextureId(const int layerId)
-{
-    android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
-    GLuint result = 0;
-    if (m_videoLayerInfoMap.contains(layerId))
-        result = m_videoLayerInfoMap.get(layerId)->textureId;
-    return result;
-}
-
-// Getting the aspect ratio for GL draw call, in the UI thread.
-float VideoLayerManager::getAspectRatio(const int layerId)
-{
-    android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
-    float result = 0;
-    if (m_videoLayerInfoMap.contains(layerId))
-        result = m_videoLayerInfoMap.get(layerId)->aspectRatio;
-    return result;
-}
-
-// Getting matrix for GL draw call, in the UI thread.
-GLfloat* VideoLayerManager::getMatrix(const int layerId)
-{
-    android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
-    GLfloat* result = 0;
-    if (m_videoLayerInfoMap.contains(layerId))
-        result = m_videoLayerInfoMap.get(layerId)->surfaceMatrix;
-    return result;
-}
-
-int VideoLayerManager::getTotalMemUsage()
-{
-    int sum = 0;
-    InfoIterator end = m_videoLayerInfoMap.end();
-    for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it)
-        sum += it->second->videoSize;
-    return sum;
-}
-
-// When the video start, we know its texture info, so we register when we
-// recieve the setSurfaceTexture call, this happens on UI thread.
-void VideoLayerManager::registerTexture(const int layerId, const GLuint textureId)
-{
-    android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
-    // If the texture has been registered, then early return.
-    if (m_videoLayerInfoMap.get(layerId)) {
-        GLuint oldTextureId = m_videoLayerInfoMap.get(layerId)->textureId;
-        if (oldTextureId != textureId)
-            removeLayerInternal(layerId);
-        else
-            return;
-    }
-    // The old info is deleted and now complete the new info and store it.
-    VideoLayerInfo* pInfo = new VideoLayerInfo();
-    pInfo->textureId = textureId;
-    memset(pInfo->surfaceMatrix, 0, sizeof(pInfo->surfaceMatrix));
-    pInfo->videoSize = 0;
-    pInfo->aspectRatio = DEFAULT_VIDEO_ASPECT_RATIO;
-    m_currentTimeStamp++;
-    pInfo->timeStamp = m_currentTimeStamp;
-    pInfo->lastIconShownTime = 0;
-    pInfo->iconState = Registered;
-
-    m_videoLayerInfoMap.add(layerId, pInfo);
-    ALOGV("GL texture %d regisered for layerId %d", textureId, layerId);
-
-    return;
-}
-
-// Only when the video is prepared, we got the video size. So we should update
-// the size for the video accordingly.
-// This is called from webcore thread, from MediaPlayerPrivateAndroid.
-void VideoLayerManager::updateVideoLayerSize(const int layerId, const int size,
-                                             const float ratio)
-{
-    android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
-    if (m_videoLayerInfoMap.contains(layerId)) {
-        VideoLayerInfo* pInfo = m_videoLayerInfoMap.get(layerId);
-        if (pInfo) {
-            pInfo->videoSize = size;
-            pInfo->aspectRatio = ratio;
-        }
-    }
-
-    // If the memory usage is out of bound, then just delete the oldest ones.
-    // Because we only recycle the texture before the current timestamp, the
-    // current video's texture will not be deleted.
-    while (getTotalMemUsage() > MAX_VIDEOSIZE_SUM)
-        if (!recycleTextureMem())
-            break;
-    return;
-}
-
-// This is called only from UI thread, at drawGL time.
-void VideoLayerManager::updateMatrix(const int layerId, const GLfloat* matrix)
-{
-    android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
-    if (m_videoLayerInfoMap.contains(layerId)) {
-        // If the existing video layer's matrix is matching the incoming one,
-        // then skip the update.
-        VideoLayerInfo* pInfo = m_videoLayerInfoMap.get(layerId);
-        ASSERT(matrix);
-        if (pInfo && !memcmp(matrix, pInfo->surfaceMatrix, sizeof(pInfo->surfaceMatrix)))
-            return;
-        memcpy(pInfo->surfaceMatrix, matrix, sizeof(pInfo->surfaceMatrix));
-    } else {
-        ALOGV("Error: should not reach here, the layerId %d should exist!", layerId);
-        ASSERT(false);
-    }
-    return;
-}
-
-// This is called on the webcore thread, save the GL texture for recycle in
-// the retired queue. They will be deleted in deleteUnusedTextures() in the UI
-// thread.
-// Return true when we found one texture to retire.
-bool VideoLayerManager::recycleTextureMem()
-{
-    // Find the oldest texture int the m_videoLayerInfoMap, put it in m_retiredTextures
-    int oldestTimeStamp = m_currentTimeStamp;
-    int oldestLayerId = -1;
-
-    InfoIterator end = m_videoLayerInfoMap.end();
-#ifdef DEBUG
-    ALOGV("VideoLayerManager::recycleTextureMem m_videoLayerInfoMap contains");
-    for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it)
-        ALOGV("  layerId %d, textureId %d, videoSize %d, timeStamp %d ",
-              it->first, it->second->textureId, it->second->videoSize, it->second->timeStamp);
-#endif
-    for (InfoIterator it = m_videoLayerInfoMap.begin(); it != end; ++it) {
-        if (it->second->timeStamp < oldestTimeStamp) {
-            oldestTimeStamp = it->second->timeStamp;
-            oldestLayerId = it->first;
-        }
-    }
-
-    bool foundTextureToRetire = (oldestLayerId != -1);
-    if (foundTextureToRetire)
-        removeLayerInternal(oldestLayerId);
-
-    return foundTextureToRetire;
-}
-
-// This is only called in the UI thread, b/c glDeleteTextures need to be called
-// on the right context.
-void VideoLayerManager::deleteUnusedTextures()
-{
-    m_retiredTexturesLock.lock();
-    int size = m_retiredTextures.size();
-    if (size > 0) {
-        GLuint* textureNames = new GLuint[size];
-        int index = 0;
-        Vector<GLuint>::const_iterator end = m_retiredTextures.end();
-        for (Vector<GLuint>::const_iterator it = m_retiredTextures.begin();
-             it != end; ++it) {
-            GLuint textureName = *it;
-            if (textureName) {
-                textureNames[index] = textureName;
-                index++;
-                ALOGV("GL texture %d will be deleted", textureName);
-            }
-        }
-        glDeleteTextures(size, textureNames);
-        delete textureNames;
-        m_retiredTextures.clear();
-    }
-    m_retiredTexturesLock.unlock();
-    GLUtils::checkGlError("deleteUnusedTextures");
-    return;
-}
-
-// This can be called in the webcore thread in the media player's dtor.
-void VideoLayerManager::removeLayer(const int layerId)
-{
-    android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
-    removeLayerInternal(layerId);
-}
-
-// This can be called on both UI and webcore thread. Since this is a private
-// function, it is up to the public function to handle the lock for
-// m_videoLayerInfoMap.
-void VideoLayerManager::removeLayerInternal(const int layerId)
-{
-    // Delete the layerInfo corresponding to this layerId and remove from the map.
-    if (m_videoLayerInfoMap.contains(layerId)) {
-        GLuint textureId = m_videoLayerInfoMap.get(layerId)->textureId;
-        if (textureId) {
-            // Buffer up the retired textures in either UI or webcore thread,
-            // will be purged at deleteUnusedTextures in the UI thread.
-            m_retiredTexturesLock.lock();
-            m_retiredTextures.append(textureId);
-            m_retiredTexturesLock.unlock();
-        }
-        delete m_videoLayerInfoMap.get(layerId);
-        m_videoLayerInfoMap.remove(layerId);
-    }
-    return;
-}
-
-double VideoLayerManager::drawIcon(const int layerId, IconType type)
-{
-    // When ratio 0 is returned, the Icon should not be drawn.
-    double ratio = 0;
-
-    android::Mutex::Autolock lock(m_videoLayerInfoMapLock);
-    if (m_videoLayerInfoMap.contains(layerId)) {
-        VideoLayerInfo* pInfo = m_videoLayerInfoMap.get(layerId);
-        // If this is state switching moment, reset the time and state
-        if ((type == PlayIcon && pInfo->iconState != PlayIconShown)
-            || (type == PauseIcon && pInfo->iconState != PauseIconShown)) {
-            pInfo->lastIconShownTime = WTF::currentTime();
-            pInfo->iconState = (type == PlayIcon) ? PlayIconShown : PauseIconShown;
-        }
-
-        // After switching the state, we calculate the ratio depending on the
-        // time interval.
-        if ((type == PlayIcon && pInfo->iconState == PlayIconShown)
-            || (type == PauseIcon && pInfo->iconState == PauseIconShown)) {
-            double delta = WTF::currentTime() - pInfo->lastIconShownTime;
-            ratio = 1.0 - (delta / PLAY_PAUSE_ICON_SHOW_TIME);
-        }
-    }
-
-    if (ratio > 1 || ratio < 0)
-        ratio = 0;
-    return ratio;
-}
-
-}
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/rendering/DrawQuadData.h b/Source/WebCore/platform/graphics/android/rendering/DrawQuadData.h
deleted file mode 100644
index 65a0df7..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/DrawQuadData.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DrawQuadData_h
-#define DrawQuadData_h
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "Color.h"
-#include "FloatRect.h"
-#include "SkRect.h"
-#include <GLES2/gl2.h>
-
-namespace WebCore {
-
-class TransformationMatrix;
-
-enum DrawQuadType {
-    BaseQuad,
-    LayerQuad,
-    Blit        // 1:1 straight pixel blit
-};
-
-// Both PureColorQuadData and TextureQuadData share the data from DrawQuadData.
-class DrawQuadData {
-public:
-    DrawQuadData(DrawQuadType type = BaseQuad,
-                 const TransformationMatrix* drawMatrix = 0,
-                 const SkRect* geometry = 0,
-                 float opacity = 1.0f,
-                 bool forceBlending = true,
-                 FloatRect fillPortion = FloatRect(0.0f, 0.0f, 1.0f, 1.0f))
-        : m_type(type)
-        , m_drawMatrix(drawMatrix)
-        , m_geometry(geometry)
-        , m_opacity(opacity)
-        , m_forceBlending(forceBlending)
-        , m_fillPortion(fillPortion.x(), fillPortion.y(),
-                        fillPortion.width(), fillPortion.height())
-    {
-    }
-
-    DrawQuadData(const DrawQuadData& data)
-        : m_type(data.m_type)
-        , m_drawMatrix(data.m_drawMatrix)
-        , m_geometry(data.m_geometry)
-        , m_opacity(data.m_opacity)
-        , m_forceBlending(data.m_forceBlending)
-        , m_fillPortion(data.m_fillPortion.x(), data.m_fillPortion.y(),
-                        data.m_fillPortion.width(), data.m_fillPortion.height())
-    {
-    }
-
-    virtual ~DrawQuadData() {};
-
-    DrawQuadType type() const { return m_type; }
-    const TransformationMatrix* drawMatrix() const { return m_drawMatrix; }
-    const SkRect* geometry() const { return m_geometry; }
-    float opacity() const { return m_opacity; }
-    bool forceBlending() const { return m_forceBlending; }
-
-    void updateDrawMatrix(TransformationMatrix* matrix) { m_drawMatrix = matrix; }
-    void updateGeometry(SkRect* rect) { m_geometry = rect; }
-    void updateOpacity(float opacity) { m_opacity = opacity; }
-
-    virtual bool pureColor() const { return false; }
-
-    virtual Color quadColor() const { return Color(); }
-
-    virtual int textureId() const { return 0; }
-    virtual GLint textureFilter() const { return 0; }
-    virtual GLenum textureTarget() const { return 0; }
-    virtual FloatRect fillPortion() const { return m_fillPortion; }
-    virtual bool hasRepeatScale() const { return false; }
-    virtual FloatSize repeatScale() const { return FloatSize(); }
-
-private:
-    DrawQuadType m_type;
-    const TransformationMatrix* m_drawMatrix;
-    const SkRect* m_geometry;
-    float m_opacity;
-    bool m_forceBlending;
-    FloatRect m_fillPortion;
-};
-
-class PureColorQuadData : public DrawQuadData {
-public:
-    PureColorQuadData(Color color,
-                      DrawQuadType type = BaseQuad,
-                      const TransformationMatrix* drawMatrix = 0,
-                      const SkRect* geometry = 0,
-                      float opacity = 1.0f,
-                      bool forceBlending = true)
-        : DrawQuadData(type, drawMatrix, geometry, opacity, forceBlending)
-    {
-        m_quadColor = color;
-    }
-
-    PureColorQuadData(const DrawQuadData& data, Color color)
-        : DrawQuadData(data)
-    {
-        m_quadColor = color;
-    }
-
-    virtual ~PureColorQuadData() {};
-    virtual bool pureColor() const { return true; }
-    virtual Color quadColor() const { return m_quadColor; }
-    void updateColor(const Color& color) { m_quadColor = color; }
-
-private:
-    Color m_quadColor;
-};
-
-class TextureQuadData : public DrawQuadData {
-public:
-    TextureQuadData(int textureId,
-                    GLenum textureTarget = GL_TEXTURE_2D,
-                    GLint textureFilter = GL_LINEAR,
-                    DrawQuadType type = BaseQuad,
-                    const TransformationMatrix* drawMatrix = 0,
-                    const SkRect* geometry = 0,
-                    float opacity = 1.0f,
-                    bool forceBlending = true,
-                    FloatRect fillPortion = FloatRect(0.0f, 0.0f, 1.0f, 1.0f),
-                    FloatSize repeatScale = FloatSize())
-        : DrawQuadData(type, drawMatrix, geometry, opacity, forceBlending, fillPortion)
-    {
-        m_textureId = textureId;
-        m_textureTarget = textureTarget;
-        m_textureFilter = textureFilter;
-        m_repeatScale = repeatScale;
-    }
-
-    TextureQuadData(const DrawQuadData& data,
-                    int textureId,
-                    GLenum textureTarget = GL_TEXTURE_2D,
-                    GLint textureFilter = GL_LINEAR)
-        : DrawQuadData(data)
-    {
-        m_textureId = textureId;
-        m_textureTarget = textureTarget;
-        m_textureFilter = textureFilter;
-    }
-
-    virtual ~TextureQuadData() {};
-    virtual bool pureColor() const { return false; }
-
-    virtual int textureId() const { return m_textureId; }
-    virtual GLint textureFilter() const { return m_textureFilter; }
-    virtual GLenum textureTarget() const { return m_textureTarget; }
-
-    void updateTextureId(int newId) { m_textureId = newId; }
-    virtual bool hasRepeatScale() const { return !m_repeatScale.isEmpty(); }
-    virtual FloatSize repeatScale() const { return m_repeatScale; }
-private:
-    int m_textureId;
-    GLint m_textureFilter;
-    GLenum m_textureTarget;
-    FloatSize m_repeatScale;
-};
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
-#endif // DrawQuadData_h
diff --git a/Source/WebCore/platform/graphics/android/rendering/GLExtras.cpp b/Source/WebCore/platform/graphics/android/rendering/GLExtras.cpp
deleted file mode 100644
index 2c114d6..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/GLExtras.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "GLExtras"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-
-#include "AndroidLog.h"
-#include "DrawExtra.h"
-#include "DrawQuadData.h"
-#include "GLExtras.h"
-#include "IntRect.h"
-#include "SkPath.h"
-#include "TilesManager.h"
-#include "android_graphics.h"
-
-// Touch ring border width. This is doubled if the ring is not pressed
-#define RING_BORDER_WIDTH 1
-
-GLExtras::GLExtras()
-    : m_drawExtra(0)
-    , m_visibleContentRect()
-{
-}
-
-GLExtras::~GLExtras()
-{
-}
-
-void GLExtras::drawRing(SkRect& srcRect, Color color, const TransformationMatrix* drawMat)
-{
-    if (srcRect.fRight <= srcRect.fLeft || srcRect.fBottom <= srcRect.fTop) {
-        // Invalid rect, reject it
-        return;
-    }
-    ALOGV("drawQuad [%fx%f, %f, %f]", srcRect.fLeft, srcRect.fTop,
-          srcRect.width(), srcRect.height());
-    // Pull the alpha out of the color so that the shader applies it correctly.
-    // Otherwise we either don't have blending enabled, or the alpha will get
-    // double applied
-    Color colorWithoutAlpha(0xFF000000 | color.rgb());
-    float alpha = color.alpha() / (float) 255;
-
-    PureColorQuadData data(colorWithoutAlpha, drawMat ? LayerQuad : BaseQuad,
-                           drawMat, &srcRect, alpha, false);
-    TilesManager::instance()->shader()->drawQuad(&data);
-}
-
-void GLExtras::drawRegion(const SkRegion& region, bool fill, bool drawBorder,
-                          const TransformationMatrix* drawMat, Color color)
-{
-    if (region.isEmpty())
-        return;
-    if (fill) {
-        SkRegion::Iterator rgnIter(region);
-        while (!rgnIter.done()) {
-            const SkIRect& ir = rgnIter.rect();
-            SkRect r;
-            r.set(ir.fLeft, ir.fTop, ir.fRight, ir.fBottom);
-            drawRing(r, color, drawMat);
-            rgnIter.next();
-        }
-    }
-    if (fill && !drawBorder)
-        return;
-    SkPath path;
-    if (!region.getBoundaryPath(&path))
-        return;
-    SkPath::Iter iter(path, true);
-    SkPath::Verb verb;
-    SkPoint pts[4];
-    SkRegion clip;
-    SkIRect startRect;
-    while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
-        if (verb == SkPath::kLine_Verb) {
-            SkRect r;
-            r.set(pts, 2);
-            SkIRect line;
-            int borderWidth = RING_BORDER_WIDTH;
-            if (!fill)
-                borderWidth *= 2;
-            line.fLeft = r.fLeft - borderWidth;
-            line.fRight = r.fRight + borderWidth;
-            line.fTop = r.fTop - borderWidth;
-            line.fBottom = r.fBottom + borderWidth;
-            if (clip.intersects(line)) {
-                clip.op(line, SkRegion::kReverseDifference_Op);
-                if (clip.isEmpty())
-                    continue; // Nothing to draw, continue
-                line = clip.getBounds();
-                if (SkIRect::Intersects(startRect, line)) {
-                    clip.op(startRect, SkRegion::kDifference_Op);
-                    if (clip.isEmpty())
-                        continue; // Nothing to draw, continue
-                    line = clip.getBounds();
-                }
-            } else {
-                clip.setRect(line);
-            }
-            r.set(line.fLeft, line.fTop, line.fRight, line.fBottom);
-            drawRing(r, color, drawMat);
-            if (startRect.isEmpty()) {
-                startRect.set(line.fLeft, line.fTop, line.fRight, line.fBottom);
-            }
-        }
-        if (verb == SkPath::kMove_Verb) {
-            startRect.setEmpty();
-        }
-    }
-}
-
-void GLExtras::drawGL(const LayerAndroid* layer)
-{
-    if (m_drawExtra)
-        m_drawExtra->drawGL(this, layer);
-}
diff --git a/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp b/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp
deleted file mode 100644
index bfa0789..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp
+++ /dev/null
@@ -1,651 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "GLUtils"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "GLUtils.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "AndroidLog.h"
-#include "BaseRenderer.h"
-#include "TextureInfo.h"
-#include "Tile.h"
-#include "TilesManager.h"
-#include "TransferQueue.h"
-
-#include <android/native_window.h>
-#include <gui/SurfaceTexture.h>
-#include <wtf/CurrentTime.h>
-
-// We will limit GL error logging for LOG_VOLUME_PER_CYCLE times every
-// LOG_VOLUME_PER_CYCLE seconds.
-#define LOG_CYCLE 30.0
-#define LOG_VOLUME_PER_CYCLE 20
-
-struct ANativeWindowBuffer;
-
-namespace WebCore {
-
-using namespace android;
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Matrix utilities
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void GLUtils::toGLMatrix(GLfloat* flattened, const TransformationMatrix& m)
-{
-    flattened[0] = m.m11(); // scaleX
-    flattened[1] = m.m12(); // skewY
-    flattened[2] = m.m13();
-    flattened[3] = m.m14(); // persp0
-    flattened[4] = m.m21(); // skewX
-    flattened[5] = m.m22(); // scaleY
-    flattened[6] = m.m23();
-    flattened[7] = m.m24(); // persp1
-    flattened[8] = m.m31();
-    flattened[9] = m.m32();
-    flattened[10] = m.m33();
-    flattened[11] = m.m34();
-    flattened[12] = m.m41(); // transX
-    flattened[13] = m.m42(); // transY
-    flattened[14] = m.m43();
-    flattened[15] = m.m44(); // persp2
-}
-
-void GLUtils::toSkMatrix(SkMatrix& matrix, const TransformationMatrix& m)
-{
-    matrix[0] = m.m11(); // scaleX
-    matrix[1] = m.m21(); // skewX
-    matrix[2] = m.m41(); // transX
-    matrix[3] = m.m12(); // skewY
-    matrix[4] = m.m22(); // scaleY
-    matrix[5] = m.m42(); // transY
-    matrix[6] = m.m14(); // persp0
-    matrix[7] = m.m24(); // persp1
-    matrix[8] = m.m44(); // persp2
-}
-
-void GLUtils::setOrthographicMatrix(TransformationMatrix& ortho, float left, float top,
-                                    float right, float bottom, float nearZ, float farZ)
-{
-    float deltaX = right - left;
-    float deltaY = top - bottom;
-    float deltaZ = farZ - nearZ;
-    if (!deltaX || !deltaY || !deltaZ)
-        return;
-
-    ortho.setM11(2.0f / deltaX);
-    ortho.setM41(-(right + left) / deltaX);
-    ortho.setM22(2.0f / deltaY);
-    ortho.setM42(-(top + bottom) / deltaY);
-    ortho.setM33(-2.0f / deltaZ);
-    ortho.setM43(-(nearZ + farZ) / deltaZ);
-}
-
-bool GLUtils::has3dTransform(const TransformationMatrix& matrix)
-{
-    return matrix.m13() != 0 || matrix.m23() != 0
-        || matrix.m31() != 0 || matrix.m32() != 0
-        || matrix.m33() != 1 || matrix.m34() != 0
-        || matrix.m43() != 0;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// GL & EGL error checks
-/////////////////////////////////////////////////////////////////////////////////////////
-
-double GLUtils::m_previousLogTime = 0;
-int GLUtils::m_currentLogCounter = 0;
-
-bool GLUtils::allowGLLog()
-{
-    if (m_currentLogCounter < LOG_VOLUME_PER_CYCLE) {
-        m_currentLogCounter++;
-        return true;
-    }
-
-    // when we are in Log cycle and over the log limit, just return false
-    double currentTime = WTF::currentTime();
-    double delta = currentTime - m_previousLogTime;
-    bool inLogCycle = (delta <= LOG_CYCLE) && (delta > 0);
-    if (inLogCycle)
-        return false;
-
-    // When we are out of Log Cycle and over the log limit, we need to reset
-    // the counter and timer.
-    m_previousLogTime = currentTime;
-    m_currentLogCounter = 0;
-    return false;
-}
-
-static void crashIfOOM(GLint errorCode)
-{
-    const GLint OOM_ERROR_CODE = 0x505;
-    if (errorCode == OOM_ERROR_CODE) {
-        ALOGE("ERROR: Fatal OOM detected.");
-        CRASH();
-    }
-}
-
-void GLUtils::checkEglError(const char* op, EGLBoolean returnVal)
-{
-    if (returnVal != EGL_TRUE) {
-#ifndef DEBUG
-        if (allowGLLog())
-#endif
-        ALOGE("EGL ERROR - %s() returned %d\n", op, returnVal);
-    }
-
-    for (EGLint error = eglGetError(); error != EGL_SUCCESS; error = eglGetError()) {
-#ifndef DEBUG
-        if (allowGLLog())
-#endif
-        ALOGE("after %s() eglError (0x%x)\n", op, error);
-        crashIfOOM(error);
-    }
-}
-
-bool GLUtils::checkGlError(const char* op)
-{
-    bool ret = false;
-    for (GLint error = glGetError(); error; error = glGetError()) {
-#ifndef DEBUG
-        if (allowGLLog())
-#endif
-        ALOGE("GL ERROR - after %s() glError (0x%x)\n", op, error);
-        crashIfOOM(error);
-        ret = true;
-    }
-    return ret;
-}
-
-bool GLUtils::checkGlErrorOn(void* p, const char* op)
-{
-    bool ret = false;
-    for (GLint error = glGetError(); error; error = glGetError()) {
-#ifndef DEBUG
-        if (allowGLLog())
-#endif
-        ALOGE("GL ERROR on %x - after %s() glError (0x%x)\n", p, op, error);
-        crashIfOOM(error);
-        ret = true;
-    }
-    return ret;
-}
-
-void GLUtils::checkSurfaceTextureError(const char* functionName, int status)
-{
-    if (status !=  NO_ERROR) {
-#ifndef DEBUG
-        if (allowGLLog())
-#endif
-        ALOGE("ERROR at calling %s status is (%d)", functionName, status);
-    }
-}
-/////////////////////////////////////////////////////////////////////////////////////////
-// GL & EGL extension checks
-/////////////////////////////////////////////////////////////////////////////////////////
-
-bool GLUtils::isEGLImageSupported()
-{
-    const char* eglExtensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS);
-    const char* glExtensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
-
-    return eglExtensions && glExtensions
-        && strstr(eglExtensions, "EGL_KHR_image_base")
-        && strstr(eglExtensions, "EGL_KHR_gl_texture_2D_image")
-        && strstr(glExtensions, "GL_OES_EGL_image");
-}
-
-bool GLUtils::isEGLFenceSyncSupported()
-{
-    const char* eglExtensions = eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS);
-    return eglExtensions && strstr(eglExtensions, "EGL_KHR_fence_sync");
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Textures utilities
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static GLenum getInternalFormat(SkBitmap::Config config)
-{
-    switch (config) {
-    case SkBitmap::kA8_Config:
-        return GL_ALPHA;
-    case SkBitmap::kARGB_4444_Config:
-        return GL_RGBA;
-    case SkBitmap::kARGB_8888_Config:
-        return GL_RGBA;
-    case SkBitmap::kRGB_565_Config:
-        return GL_RGB;
-    default:
-        return -1;
-    }
-}
-
-static GLenum getType(SkBitmap::Config config)
-{
-    switch (config) {
-    case SkBitmap::kA8_Config:
-        return GL_UNSIGNED_BYTE;
-    case SkBitmap::kARGB_4444_Config:
-        return GL_UNSIGNED_SHORT_4_4_4_4;
-    case SkBitmap::kARGB_8888_Config:
-        return GL_UNSIGNED_BYTE;
-    case SkBitmap::kIndex8_Config:
-        return -1; // No type for compressed data.
-    case SkBitmap::kRGB_565_Config:
-        return GL_UNSIGNED_SHORT_5_6_5;
-    default:
-        return -1;
-    }
-}
-
-static EGLConfig defaultPbufferConfig(EGLDisplay display)
-{
-    EGLConfig config;
-    EGLint numConfigs;
-
-    static const EGLint configAttribs[] = {
-        EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
-        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-        EGL_NONE
-    };
-
-    eglChooseConfig(display, configAttribs, &config, 1, &numConfigs);
-    GLUtils::checkEglError("eglPbufferConfig");
-    if (numConfigs != 1)
-        ALOGI("eglPbufferConfig failed (%d)\n", numConfigs);
-
-    return config;
-}
-
-static EGLSurface createPbufferSurface(EGLDisplay display, const EGLConfig& config,
-                                       EGLint* errorCode)
-{
-    const EGLint attribList[] = {
-        EGL_WIDTH, 1,
-        EGL_HEIGHT, 1,
-        EGL_NONE
-    };
-    EGLSurface surface = eglCreatePbufferSurface(display, config, attribList);
-
-    if (errorCode)
-        *errorCode = eglGetError();
-    else
-        GLUtils::checkEglError("eglCreatePbufferSurface");
-
-    if (surface == EGL_NO_SURFACE)
-        return EGL_NO_SURFACE;
-
-    return surface;
-}
-
-void GLUtils::deleteTexture(GLuint* texture)
-{
-    glDeleteTextures(1, texture);
-    GLUtils::checkGlError("glDeleteTexture");
-    *texture = 0;
-}
-
-GLuint GLUtils::createSampleColorTexture(int r, int g, int b)
-{
-    GLuint texture;
-    glGenTextures(1, &texture);
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-    GLubyte pixels[4 *3] = {
-        r, g, b,
-        r, g, b,
-        r, g, b,
-        r, g, b
-    };
-    glBindTexture(GL_TEXTURE_2D, texture);
-    GLUtils::checkGlError("glBindTexture");
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
-    GLUtils::checkGlError("glTexImage2D");
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    return texture;
-}
-
-GLuint GLUtils::createSampleTexture()
-{
-    GLuint texture;
-    glGenTextures(1, &texture);
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-    GLubyte pixels[4 *3] = {
-        255, 0, 0,
-        0, 255, 0,
-        0, 0, 255,
-        255, 255, 0
-    };
-    glBindTexture(GL_TEXTURE_2D, texture);
-    GLUtils::checkGlError("glBindTexture");
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
-    GLUtils::checkGlError("glTexImage2D");
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    return texture;
-}
-
-GLuint GLUtils::createTileGLTexture(int width, int height)
-{
-    GLuint texture;
-    glGenTextures(1, &texture);
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-    GLubyte* pixels = 0;
-#ifdef DEBUG
-    int length = width * height * 4;
-    pixels = new GLubyte[length];
-    for (int i = 0; i < length; i++)
-        pixels[i] = i % 256;
-#endif
-    glBindTexture(GL_TEXTURE_2D, texture);
-    GLUtils::checkGlError("glBindTexture");
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
-    GLUtils::checkGlError("glTexImage2D");
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-#ifdef DEBUG
-    delete pixels;
-#endif
-    return texture;
-}
-
-bool GLUtils::isPureColorBitmap(const SkBitmap& bitmap, Color& pureColor)
-{
-    // If the bitmap is the pure color, skip the transfer step, and update the Tile Info.
-    // This check is taking < 1ms if we do full bitmap check per tile.
-    // TODO: use the SkPicture to determine whether or not a tile is single color.
-    pureColor = Color(Color::transparent);
-    bitmap.lockPixels();
-    bool sameColor = true;
-    int bitmapWidth = bitmap.width();
-
-    // Create a row of pure color using the first pixel.
-    // TODO: improve the perf here, by either picking a random pixel, or
-    // creating an array of rows with pre-defined commonly used color, add
-    // smart LUT to speed things up if possible.
-    int* firstPixelPtr = static_cast<int*> (bitmap.getPixels());
-    int* pixelsRow = new int[bitmapWidth];
-    for (int i = 0; i < bitmapWidth; i++)
-        pixelsRow[i] = (*firstPixelPtr);
-
-    // Then compare the pure color row with each row of the bitmap.
-    for (int j = 0; j < bitmap.height(); j++) {
-        if (memcmp(pixelsRow, &firstPixelPtr[bitmapWidth * j], 4 * bitmapWidth)) {
-            sameColor = false;
-            break;
-        }
-    }
-    delete pixelsRow;
-    pixelsRow = 0;
-
-    if (sameColor) {
-        char* rgbaPtr = static_cast<char*>(bitmap.getPixels());
-        pureColor = Color(rgbaPtr[0], rgbaPtr[1], rgbaPtr[2], rgbaPtr[3]);
-        ALOGV("sameColor tile found , %x at (%d, %d, %d, %d)",
-              *firstPixelPtr, rgbaPtr[0], rgbaPtr[1], rgbaPtr[2], rgbaPtr[3]);
-    }
-    bitmap.unlockPixels();
-
-    return sameColor;
-}
-
-// Return true when the tile is pure color.
-bool GLUtils::skipTransferForPureColor(const TileRenderInfo* renderInfo,
-                                       const SkBitmap& bitmap)
-{
-    bool skipTransfer = false;
-    Tile* tilePtr = renderInfo->baseTile;
-
-    if (tilePtr) {
-        TileTexture* tileTexture = tilePtr->backTexture();
-        // Check the bitmap, and make everything ready here.
-        if (tileTexture && renderInfo->isPureColor) {
-            // update basetile's info
-            // Note that we are skipping the whole TransferQueue.
-            renderInfo->textureInfo->m_width = bitmap.width();
-            renderInfo->textureInfo->m_height = bitmap.height();
-            renderInfo->textureInfo->m_internalFormat = GL_RGBA;
-
-            TilesManager::instance()->transferQueue()->addItemInPureColorQueue(renderInfo);
-
-            skipTransfer = true;
-        }
-    }
-    return skipTransfer;
-}
-
-void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo,
-                                     const SkBitmap& bitmap)
-{
-    if (!renderInfo)
-        return;
-    const SkSize& requiredSize = renderInfo->tileSize;
-    TextureInfo* textureInfo = renderInfo->textureInfo;
-
-    if (skipTransferForPureColor(renderInfo, bitmap))
-        return;
-
-    if (requiredSize.equals(textureInfo->m_width, textureInfo->m_height))
-        GLUtils::updateQueueWithBitmap(renderInfo, bitmap);
-    else {
-        if (!requiredSize.equals(bitmap.width(), bitmap.height())) {
-            ALOGV("The bitmap size (%d,%d) does not equal the texture size (%d,%d)",
-                  bitmap.width(), bitmap.height(),
-                  requiredSize.width(), requiredSize.height());
-        }
-        GLUtils::updateQueueWithBitmap(renderInfo, bitmap);
-
-        textureInfo->m_width = bitmap.width();
-        textureInfo->m_height = bitmap.height();
-        textureInfo->m_internalFormat = GL_RGBA;
-    }
-}
-
-void GLUtils::updateQueueWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap)
-{
-    if (!renderInfo
-        || !renderInfo->textureInfo
-        || !renderInfo->baseTile)
-        return;
-
-    TilesManager::instance()->transferQueue()->updateQueueWithBitmap(renderInfo, bitmap);
-}
-
-bool GLUtils::updateSharedSurfaceTextureWithBitmap(ANativeWindow* anw, const SkBitmap& bitmap)
-{
-    SkAutoLockPixels alp(bitmap);
-    if (!bitmap.getPixels())
-        return false;
-    ANativeWindow_Buffer buffer;
-    if (ANativeWindow_lock(anw, &buffer, 0))
-        return false;
-    if (buffer.width < bitmap.width() || buffer.height < bitmap.height()) {
-        ALOGW("bitmap (%dx%d) too large for buffer (%dx%d)!",
-                bitmap.width(), bitmap.height(),
-                buffer.width, buffer.height);
-        ANativeWindow_unlockAndPost(anw);
-        return false;
-    }
-    uint8_t* img = (uint8_t*)buffer.bits;
-    int row;
-    int bpp = 4; // Now we only deal with RGBA8888 format.
-    bitmap.lockPixels();
-    uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels());
-
-    if (buffer.stride != bitmap.width())
-        // Copied line by line since we need to handle the offsets and stride.
-        for (row = 0 ; row < bitmap.height(); row ++) {
-            uint8_t* dst = &(img[buffer.stride * row * bpp]);
-            uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]);
-            memcpy(dst, src, bpp * bitmap.width());
-        }
-    else
-        memcpy(img, bitmapOrigin, bpp * bitmap.width() * bitmap.height());
-
-    bitmap.unlockPixels();
-    ANativeWindow_unlockAndPost(anw);
-    return true;
-}
-
-void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter)
-{
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-    glBindTexture(GL_TEXTURE_2D, texture);
-    GLUtils::checkGlError("glBindTexture");
-    SkBitmap::Config config = bitmap.getConfig();
-    int internalformat = getInternalFormat(config);
-    int type = getType(config);
-    bitmap.lockPixels();
-    glTexImage2D(GL_TEXTURE_2D, 0, internalformat, bitmap.width(), bitmap.height(),
-                 0, internalformat, type, bitmap.getPixels());
-    bitmap.unlockPixels();
-    if (GLUtils::checkGlError("glTexImage2D")) {
-#ifndef DEBUG
-        if (allowGLLog())
-#endif
-        ALOGE("GL ERROR: glTexImage2D parameters are : textureId %d,"
-              " bitmap.width() %d, bitmap.height() %d,"
-              " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p",
-              texture, bitmap.width(), bitmap.height(), internalformat, type,
-              bitmap.getPixels());
-    }
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
-}
-
-void GLUtils::updateTextureWithBitmap(GLuint texture, const SkBitmap& bitmap,
-                                      const IntRect& inval, GLint filter)
-{
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-    glBindTexture(GL_TEXTURE_2D, texture);
-    GLUtils::checkGlError("glBindTexture");
-    SkBitmap::Config config = bitmap.getConfig();
-    int internalformat = getInternalFormat(config);
-    int type = getType(config);
-    bitmap.lockPixels();
-    if (inval.isEmpty()) {
-        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(),
-                        internalformat, type, bitmap.getPixels());
-    } else {
-        glTexSubImage2D(GL_TEXTURE_2D, 0, inval.x(), inval.y(), inval.width(), inval.height(),
-                        internalformat, type, bitmap.getPixels());
-    }
-    bitmap.unlockPixels();
-    if (GLUtils::checkGlError("glTexSubImage2D")) {
-#ifndef DEBUG
-        if (allowGLLog())
-#endif
-        ALOGE("GL ERROR: glTexSubImage2D parameters are : textureId %d,"
-              " bitmap.width() %d, bitmap.height() %d,"
-              " internalformat 0x%x, type 0x%x, bitmap.getPixels() %p",
-              texture, bitmap.width(), bitmap.height(), internalformat, type,
-              bitmap.getPixels());
-    }
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
-}
-
-void GLUtils::createEGLImageFromTexture(GLuint texture, EGLImageKHR* image)
-{
-    EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(texture);
-    static const EGLint attr[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
-    *image = eglCreateImageKHR(eglGetCurrentDisplay(), eglGetCurrentContext(),
-                               EGL_GL_TEXTURE_2D_KHR, buffer, attr);
-    GLUtils::checkEglError("eglCreateImage", (*image != EGL_NO_IMAGE_KHR));
-}
-
-void GLUtils::createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter)
-{
-    glBindTexture(GL_TEXTURE_2D, texture);
-    GLUtils::checkGlError("glBindTexture");
-    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
-}
-
-void GLUtils::convertToTransformationMatrix(const float* matrix, TransformationMatrix& transformMatrix)
-{
-    transformMatrix.setMatrix(
-        matrix[0], matrix[1], matrix[2], matrix[3],
-        matrix[4], matrix[5], matrix[6], matrix[7],
-        matrix[8], matrix[9], matrix[10], matrix[11],
-        matrix[12], matrix[13], matrix[14], matrix[15]);
-}
-
-void GLUtils::clearBackgroundIfOpaque(const Color* backgroundColor)
-{
-    if (!backgroundColor->hasAlpha()) {
-        if (TilesManager::instance()->invertedScreen()) {
-            float color = 1.0 - ((((float) backgroundColor->red() / 255.0) +
-                          ((float) backgroundColor->green() / 255.0) +
-                          ((float) backgroundColor->blue() / 255.0)) / 3.0);
-            glClearColor(color, color, color, 1);
-        } else {
-            glClearColor((float)backgroundColor->red() / 255.0,
-                         (float)backgroundColor->green() / 255.0,
-                         (float)backgroundColor->blue() / 255.0, 1);
-        }
-        glClear(GL_COLOR_BUFFER_BIT);
-    }
-}
-
-bool GLUtils::deepCopyBitmapSubset(const SkBitmap& sourceBitmap,
-                                   SkBitmap& subset, int leftOffset, int topOffset)
-{
-    sourceBitmap.lockPixels();
-    subset.lockPixels();
-    char* srcPixels = (char*) sourceBitmap.getPixels();
-    char* dstPixels = (char*) subset.getPixels();
-    if (!dstPixels || !srcPixels || !subset.lockPixelsAreWritable()) {
-        ALOGD("no pixels :( %p, %p (writable=%d)", srcPixels, dstPixels,
-              subset.lockPixelsAreWritable());
-        subset.unlockPixels();
-        sourceBitmap.unlockPixels();
-        return false;
-    }
-    int srcRowSize = sourceBitmap.rowBytes();
-    int destRowSize = subset.rowBytes();
-    for (int i = 0; i < subset.height(); i++) {
-        int srcOffset = (i + topOffset) * srcRowSize;
-        srcOffset += (leftOffset * sourceBitmap.bytesPerPixel());
-        int dstOffset = i * destRowSize;
-        memcpy(dstPixels + dstOffset, srcPixels + srcOffset, destRowSize);
-    }
-    subset.unlockPixels();
-    sourceBitmap.unlockPixels();
-    return true;
-}
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.cpp b/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.cpp
deleted file mode 100644
index d779af4..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/GaneshRenderer.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "GaneshRenderer"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "GaneshRenderer.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "AndroidLog.h"
-#include "GaneshContext.h"
-#include "SkCanvas.h"
-#include "SkGpuDevice.h"
-#include "TilesManager.h"
-#include "TransferQueue.h"
-
-namespace WebCore {
-
-GaneshRenderer::GaneshRenderer() : BaseRenderer(BaseRenderer::Ganesh)
-{
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->increment("GaneshRenderer");
-#endif
-}
-
-GaneshRenderer::~GaneshRenderer()
-{
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->decrement("GaneshRenderer");
-#endif
-}
-
-void GaneshRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* canvas)
-{
-    GaneshContext* ganesh = GaneshContext::instance();
-
-    TransferQueue* tileQueue = TilesManager::instance()->transferQueue();
-
-    tileQueue->lockQueue();
-
-    bool ready = tileQueue->readyForUpdate();
-    if (!ready) {
-        ALOGV("!ready");
-        tileQueue->unlockQueue();
-        return;
-    }
-
-    SkDevice* device = NULL;
-    if (renderInfo.tileSize.width() == TilesManager::tileWidth()
-            && renderInfo.tileSize.height() == TilesManager::tileHeight()) {
-        device = ganesh->getDeviceForTile(renderInfo);
-    } else {
-        // TODO support arbitrary sizes for layers
-        ALOGV("ERROR: expected (%d,%d) actual (%d,%d)",
-              TilesManager::tileWidth(), TilesManager::tileHeight(),
-              renderInfo.tileSize.width(), renderInfo.tileSize.height());
-    }
-
-    // set the GPU device to the canvas
-    canvas->setDevice(device);
-}
-
-void GaneshRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas)
-{
-    ALOGV("rendered to tile (%d,%d)", renderInfo.x, renderInfo.y);
-
-    GaneshContext::instance()->flush();
-
-    // In SurfaceTextureMode we must call swapBuffers to unlock and post the
-    // tile's ANativeWindow (i.e. SurfaceTexture) buffer
-    TransferQueue* tileQueue = TilesManager::instance()->transferQueue();
-    eglSwapBuffers(eglGetCurrentDisplay(), tileQueue->m_eglSurface);
-    tileQueue->addItemInTransferQueue(&renderInfo, GpuUpload, 0);
-    tileQueue->unlockQueue();
-}
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.cpp b/Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.cpp
deleted file mode 100644
index f9edb74..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "InspectorCanvas"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "InspectorCanvas.h"
-
-#include "AndroidLog.h"
-#include "SkPicture.h"
-
-namespace WebCore {
-
-
-void InspectorCanvas::setHasText()
-{
-    m_hasText = true;
-    setHasContent();
-}
-
-void InspectorCanvas::setHasContent()
-{
-    m_hasContent = true;
-    if (m_hasText) {
-        // has text. Have to paint properly, so no further
-        // information is useful
-        m_picture->abortPlayback();
-    }
-}
-
-void InspectorCanvas::setIsBackground(const SkPaint& paint)
-{
-    // TODO: if the paint is a solid color, opaque, and the last instruction in
-    // the picture, replace the picture with simple draw rect info
-    setHasContent();
-}
-
-void InspectorCanvas::commonDrawBitmap(const SkBitmap& bitmap,
-                                       const SkIRect* rect,
-                                       const SkMatrix&,
-                                       const SkPaint&)
-{
-    setHasContent();
-}
-
-void InspectorCanvas::drawPaint(const SkPaint& paint)
-{
-    setHasContent();
-}
-
-void InspectorCanvas::drawPath(const SkPath&, const SkPaint& paint)
-{
-    setHasContent();
-}
-void InspectorCanvas::drawPoints(PointMode, size_t,
-                                 const SkPoint [], const SkPaint& paint)
-{
-    setHasContent();
-}
-
-void InspectorCanvas::drawRect(const SkRect& rect, const SkPaint& paint)
-{
-    if (rect.fLeft == 0
-            && rect.fTop == 0
-            && rect.width() >= m_picture->width()
-            && rect.height() >= m_picture->height()) {
-        // rect same size as canvas, treat layer as a single color rect until
-        // more content is drawn
-        setIsBackground(paint);
-    } else {
-        // regular rect drawing path
-        setHasContent();
-    }
-    ALOGV("draw rect at %f %f, size %f %f, picture size %d %d",
-          rect.fLeft, rect.fTop, rect.width(), rect.height(),
-          m_picture->width(), m_picture->height());
-}
-void InspectorCanvas::drawSprite(const SkBitmap& , int , int ,
-                                 const SkPaint* paint)
-{
-    setHasContent();
-}
-
-void InspectorCanvas::drawText(const void*, size_t byteLength, SkScalar,
-                               SkScalar, const SkPaint& paint)
-{
-    setHasText();
-}
-
-void InspectorCanvas::drawPosText(const void* , size_t byteLength,
-                                  const SkPoint [], const SkPaint& paint)
-{
-    setHasText();
-}
-
-void InspectorCanvas::drawPosTextH(const void*, size_t byteLength,
-                                   const SkScalar [], SkScalar,
-                                   const SkPaint& paint)
-{
-    setHasText();
-}
-
-void InspectorCanvas::drawTextOnPath(const void*, size_t byteLength,
-                                     const SkPath&, const SkMatrix*,
-                                     const SkPaint& paint)
-{
-    setHasText();
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.h b/Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.h
deleted file mode 100644
index 415a579..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/InspectorCanvas.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef InspectorCanvas_h
-#define InspectorCanvas_h
-
-#include "SkBounder.h"
-#include "SkCanvas.h"
-
-namespace WebCore {
-
-class InspectorBounder : public SkBounder {
-    virtual bool onIRect(const SkIRect& rect)
-    {
-        return false;
-    }
-};
-
-class InspectorCanvas : public SkCanvas {
-public:
-    InspectorCanvas(SkBounder* bounder, SkPicture* picture)
-        : m_picture(picture)
-        , m_hasText(false)
-        , m_hasContent(false)
-    {
-        setBounder(bounder);
-    }
-
-    bool hasText() {return m_hasText;}
-    bool hasContent() {return m_hasContent;}
-
-    virtual bool clipPath(const SkPath&, SkRegion::Op) {
-        return true;
-    }
-
-    virtual void commonDrawBitmap(const SkBitmap& bitmap,
-                                  const SkIRect* rect,
-                                  const SkMatrix&,
-                                  const SkPaint&);
-
-    virtual void drawPaint(const SkPaint& paint);
-    virtual void drawPath(const SkPath&, const SkPaint& paint);
-    virtual void drawPoints(PointMode, size_t,
-                            const SkPoint [], const SkPaint& paint);
-
-    virtual void drawRect(const SkRect& , const SkPaint& paint);
-    virtual void drawSprite(const SkBitmap& , int , int ,
-                            const SkPaint* paint = NULL);
-
-    virtual void drawText(const void*, size_t byteLength, SkScalar,
-                          SkScalar, const SkPaint& paint);
-    virtual void drawPosText(const void* , size_t byteLength,
-                             const SkPoint [], const SkPaint& paint);
-    virtual void drawPosTextH(const void*, size_t byteLength,
-                              const SkScalar [], SkScalar,
-                              const SkPaint& paint);
-    virtual void drawTextOnPath(const void*, size_t byteLength,
-                                const SkPath&, const SkMatrix*,
-                                const SkPaint& paint);
-
-private:
-
-    // vector instructions exist, must repaint at any scale
-    void setHasText();
-
-    // painting is required
-    void setHasContent();
-
-    // rect covering entire content, don't need to use a texture if nothing else
-    // is painted
-    void setIsBackground(const SkPaint& paint);
-
-    SkPicture* m_picture;
-    bool m_hasText;
-    bool m_hasContent;
-};
-
-} // namespace WebCore
-
-#endif // InspectorCanvas_h
diff --git a/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp
deleted file mode 100644
index d7266a3..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp
+++ /dev/null
@@ -1,938 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "ShaderProgram"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "ShaderProgram.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "AndroidLog.h"
-#include "DrawQuadData.h"
-#include "FloatPoint3D.h"
-#include "GLUtils.h"
-#include "TilesManager.h"
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#define EPSILON 0.00001f
-
-namespace WebCore {
-
-// fillPortion.xy = starting UV coordinates.
-// fillPortion.zw = UV coordinates width and height.
-static const char gVertexShader[] =
-    "attribute vec4 vPosition;\n"
-    "uniform mat4 projectionMatrix;\n"
-    "uniform vec4 fillPortion;\n"
-    "varying vec2 v_texCoord;\n"
-    "void main() {\n"
-    "  gl_Position = projectionMatrix * vPosition;\n"
-    "  v_texCoord = vPosition.xy * fillPortion.zw + fillPortion.xy;\n"
-    "}\n";
-
-static const char gRepeatTexFragmentShader[] =
-    "precision mediump float;\n"
-    "varying vec2 v_texCoord; \n"
-    "uniform float alpha; \n"
-    "uniform sampler2D s_texture; \n"
-    "uniform vec2 repeatScale;\n"
-    "void main() {\n"
-    "  vec2 repeatedTexCoord; "
-    "  repeatedTexCoord.x = v_texCoord.x - floor(v_texCoord.x); "
-    "  repeatedTexCoord.y = v_texCoord.y - floor(v_texCoord.y); "
-    "  repeatedTexCoord.x = repeatedTexCoord.x * repeatScale.x; "
-    "  repeatedTexCoord.y = repeatedTexCoord.y * repeatScale.y; "
-    "  gl_FragColor = texture2D(s_texture, repeatedTexCoord); \n"
-    "  gl_FragColor *= alpha; "
-    "}\n";
-
-static const char gRepeatTexFragmentShaderInverted[] =
-    "precision mediump float;\n"
-    "varying vec2 v_texCoord; \n"
-    "uniform float alpha; \n"
-    "uniform float contrast; \n"
-    "uniform sampler2D s_texture; \n"
-    "uniform vec2 repeatScale;\n"
-    "void main() {\n"
-    "  vec2 repeatedTexCoord; "
-    "  repeatedTexCoord.x = v_texCoord.x - floor(v_texCoord.x); "
-    "  repeatedTexCoord.y = v_texCoord.y - floor(v_texCoord.y); "
-    "  repeatedTexCoord.x = repeatedTexCoord.x * repeatScale.x; "
-    "  repeatedTexCoord.y = repeatedTexCoord.y * repeatScale.y; "
-    "  vec4 pixel = texture2D(s_texture, repeatedTexCoord); \n"
-    "  float a = pixel.a; \n"
-    "  float color = a - (0.2989 * pixel.r + 0.5866 * pixel.g + 0.1145 * pixel.b);\n"
-    "  color = ((color - a/2.0) * contrast) + a/2.0; \n"
-    "  pixel.rgb = vec3(color, color, color); \n "
-    "  gl_FragColor = pixel; \n"
-    "  gl_FragColor *= alpha; "
-    "}\n";
-
-static const char gFragmentShader[] =
-    "precision mediump float;\n"
-    "varying vec2 v_texCoord; \n"
-    "uniform float alpha; \n"
-    "uniform sampler2D s_texture; \n"
-    "void main() {\n"
-    "  gl_FragColor = texture2D(s_texture, v_texCoord); \n"
-    "  gl_FragColor *= alpha; "
-    "}\n";
-
-// We could pass the pureColor into either Vertex or Frag Shader.
-// The reason we passed the color into the Vertex Shader is that some driver
-// might create redundant copy when uniforms in fragment shader changed.
-static const char gPureColorVertexShader[] =
-    "attribute vec4 vPosition;\n"
-    "uniform mat4 projectionMatrix;\n"
-    "uniform vec4 inputColor;\n"
-    "varying vec4 v_color;\n"
-    "void main() {\n"
-    "  gl_Position = projectionMatrix * vPosition;\n"
-    "  v_color = inputColor;\n"
-    "}\n";
-
-static const char gPureColorFragmentShader[] =
-    "precision mediump float;\n"
-    "varying vec4 v_color;\n"
-    "void main() {\n"
-    "  gl_FragColor = v_color;\n"
-    "}\n";
-
-static const char gFragmentShaderInverted[] =
-    "precision mediump float;\n"
-    "varying vec2 v_texCoord; \n"
-    "uniform float alpha; \n"
-    "uniform float contrast; \n"
-    "uniform sampler2D s_texture; \n"
-    "void main() {\n"
-    "  vec4 pixel = texture2D(s_texture, v_texCoord); \n"
-    "  float a = pixel.a; \n"
-    "  float color = a - (0.2989 * pixel.r + 0.5866 * pixel.g + 0.1145 * pixel.b);\n"
-    "  color = ((color - a/2.0) * contrast) + a/2.0; \n"
-    "  pixel.rgb = vec3(color, color, color); \n "
-    "  gl_FragColor = pixel; \n"
-    "  gl_FragColor *= alpha; \n"
-    "}\n";
-
-static const char gVideoVertexShader[] =
-    "attribute vec4 vPosition;\n"
-    "uniform mat4 textureMatrix;\n"
-    "uniform mat4 projectionMatrix;\n"
-    "varying vec2 v_texCoord;\n"
-    "void main() {\n"
-    "  gl_Position = projectionMatrix * vPosition;\n"
-    "  v_texCoord = vec2(textureMatrix * vec4(vPosition.x, 1.0 - vPosition.y, 0.0, 1.0));\n"
-    "}\n";
-
-static const char gVideoFragmentShader[] =
-    "#extension GL_OES_EGL_image_external : require\n"
-    "precision mediump float;\n"
-    "uniform samplerExternalOES s_yuvTexture;\n"
-    "varying vec2 v_texCoord;\n"
-    "void main() {\n"
-    "  gl_FragColor = texture2D(s_yuvTexture, v_texCoord);\n"
-    "}\n";
-
-static const char gSurfaceTextureOESFragmentShader[] =
-    "#extension GL_OES_EGL_image_external : require\n"
-    "precision mediump float;\n"
-    "varying vec2 v_texCoord; \n"
-    "uniform float alpha; \n"
-    "uniform samplerExternalOES s_texture; \n"
-    "void main() {\n"
-    "  gl_FragColor = texture2D(s_texture, v_texCoord); \n"
-    "  gl_FragColor *= alpha; "
-    "}\n";
-
-static const char gSurfaceTextureOESFragmentShaderInverted[] =
-    "#extension GL_OES_EGL_image_external : require\n"
-    "precision mediump float;\n"
-    "varying vec2 v_texCoord; \n"
-    "uniform float alpha; \n"
-    "uniform float contrast; \n"
-    "uniform samplerExternalOES s_texture; \n"
-    "void main() {\n"
-    "  vec4 pixel = texture2D(s_texture, v_texCoord); \n"
-    "  float a = pixel.a; \n"
-    "  float color = a - (0.2989 * pixel.r + 0.5866 * pixel.g + 0.1145 * pixel.b);\n"
-    "  color = ((color - a/2.0) * contrast) + a/2.0; \n"
-    "  pixel.rgb = vec3(color, color, color); \n "
-    "  gl_FragColor = pixel; \n"
-    "  gl_FragColor *= alpha; \n"
-    "}\n";
-
-GLuint ShaderProgram::loadShader(GLenum shaderType, const char* pSource)
-{
-    GLuint shader = glCreateShader(shaderType);
-    if (shader) {
-        glShaderSource(shader, 1, &pSource, 0);
-        glCompileShader(shader);
-        GLint compiled = 0;
-        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
-        if (!compiled) {
-            GLint infoLen = 0;
-            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
-            if (infoLen) {
-                char* buf = (char*) malloc(infoLen);
-                if (buf) {
-                glGetShaderInfoLog(shader, infoLen, 0, buf);
-                ALOGE("could not compile shader %d:\n%s\n", shaderType, buf);
-                free(buf);
-            }
-            glDeleteShader(shader);
-            shader = 0;
-            }
-        }
-    }
-    return shader;
-}
-
-GLint ShaderProgram::createProgram(const char* pVertexSource, const char* pFragmentSource)
-{
-    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
-    if (!vertexShader) {
-        ALOGE("couldn't load the vertex shader!");
-        return -1;
-    }
-
-    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
-    if (!pixelShader) {
-        ALOGE("couldn't load the pixel shader!");
-        return -1;
-    }
-
-    GLuint program = glCreateProgram();
-    if (program) {
-        glAttachShader(program, vertexShader);
-        GLUtils::checkGlError("glAttachShader vertex");
-        glAttachShader(program, pixelShader);
-        GLUtils::checkGlError("glAttachShader pixel");
-        glLinkProgram(program);
-        GLint linkStatus = GL_FALSE;
-        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
-        if (linkStatus != GL_TRUE) {
-            GLint bufLength = 0;
-            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
-            if (bufLength) {
-                char* buf = (char*) malloc(bufLength);
-                if (buf) {
-                    glGetProgramInfoLog(program, bufLength, 0, buf);
-                    ALOGE("could not link program:\n%s\n", buf);
-                    free(buf);
-                }
-            }
-            glDeleteProgram(program);
-            program = -1;
-        }
-    }
-
-    ShaderResource newResource(program, vertexShader, pixelShader);
-    m_resources.append(newResource);
-    return program;
-}
-
-ShaderProgram::ShaderProgram()
-    : m_blendingEnabled(false)
-    , m_contrast(1)
-    , m_alphaLayer(false)
-    , m_currentScale(1.0f)
-    , m_needsInit(true)
-{
-}
-
-void ShaderProgram::cleanupGLResources()
-{
-    for (unsigned int i = 0; i < m_resources.size(); i++) {
-        glDetachShader(m_resources[i].program, m_resources[i].vertexShader);
-        glDetachShader(m_resources[i].program, m_resources[i].fragmentShader);
-        glDeleteShader(m_resources[i].vertexShader);
-        glDeleteShader(m_resources[i].fragmentShader);
-        glDeleteProgram(m_resources[i].program);
-    }
-    glDeleteBuffers(1, m_textureBuffer);
-
-    m_resources.clear();
-    m_needsInit = true;
-    GLUtils::checkGlError("cleanupGLResources");
-
-    return;
-}
-
-void ShaderProgram::initGLResources()
-{
-    // To detect whether or not resources for ShaderProgram allocated
-    // successfully, we clean up pre-existing errors here and will check for
-    // new errors at the end of this function.
-    GLUtils::checkGlError("before initGLResources");
-
-    GLint tex2DProgram = createProgram(gVertexShader, gFragmentShader);
-    GLint pureColorProgram = createProgram(gPureColorVertexShader, gPureColorFragmentShader);
-    GLint tex2DInvProgram = createProgram(gVertexShader, gFragmentShaderInverted);
-    GLint videoProgram = createProgram(gVideoVertexShader, gVideoFragmentShader);
-    GLint texOESProgram =
-        createProgram(gVertexShader, gSurfaceTextureOESFragmentShader);
-    GLint texOESInvProgram =
-        createProgram(gVertexShader, gSurfaceTextureOESFragmentShaderInverted);
-    GLint repeatTexProgram =
-        createProgram(gVertexShader, gRepeatTexFragmentShader);
-    GLint repeatTexInvProgram =
-        createProgram(gVertexShader, gRepeatTexFragmentShaderInverted);
-
-    if (tex2DProgram == -1
-        || pureColorProgram == -1
-        || tex2DInvProgram == -1
-        || videoProgram == -1
-        || texOESProgram == -1
-        || texOESInvProgram == -1
-        || repeatTexProgram == -1
-        || repeatTexInvProgram == -1) {
-        m_needsInit = true;
-        return;
-    }
-
-    GLint pureColorPosition = glGetAttribLocation(pureColorProgram, "vPosition");
-    GLint pureColorProjMtx = glGetUniformLocation(pureColorProgram, "projectionMatrix");
-    GLint pureColorValue = glGetUniformLocation(pureColorProgram, "inputColor");
-    m_handleArray[PureColor].init(-1, -1, pureColorPosition, pureColorProgram,
-                                  pureColorProjMtx, pureColorValue, -1, -1, -1, -1);
-
-    GLint tex2DAlpha = glGetUniformLocation(tex2DProgram, "alpha");
-    GLint tex2DPosition = glGetAttribLocation(tex2DProgram, "vPosition");
-    GLint tex2DProjMtx = glGetUniformLocation(tex2DProgram, "projectionMatrix");
-    GLint tex2DTexSampler = glGetUniformLocation(tex2DProgram, "s_texture");
-    GLint tex2DFillPortion = glGetUniformLocation(tex2DProgram, "fillPortion");
-    m_handleArray[Tex2D].init(tex2DAlpha, -1, tex2DPosition, tex2DProgram,
-                              tex2DProjMtx, -1, tex2DTexSampler, -1, tex2DFillPortion, -1);
-
-    GLint tex2DInvAlpha = glGetUniformLocation(tex2DInvProgram, "alpha");
-    GLint tex2DInvContrast = glGetUniformLocation(tex2DInvProgram, "contrast");
-    GLint tex2DInvPosition = glGetAttribLocation(tex2DInvProgram, "vPosition");
-    GLint tex2DInvProjMtx = glGetUniformLocation(tex2DInvProgram, "projectionMatrix");
-    GLint tex2DInvTexSampler = glGetUniformLocation(tex2DInvProgram, "s_texture");
-    GLint tex2DInvFillPortion = glGetUniformLocation(tex2DInvProgram, "fillPortion");
-    m_handleArray[Tex2DInv].init(tex2DInvAlpha, tex2DInvContrast,
-                                 tex2DInvPosition, tex2DInvProgram,
-                                 tex2DInvProjMtx, -1,
-                                 tex2DInvTexSampler, -1, tex2DInvFillPortion, -1);
-
-    GLint repeatTexAlpha = glGetUniformLocation(repeatTexProgram, "alpha");
-    GLint repeatTexPosition = glGetAttribLocation(repeatTexProgram, "vPosition");
-    GLint repeatTexProjMtx = glGetUniformLocation(repeatTexProgram, "projectionMatrix");
-    GLint repeatTexTexSampler = glGetUniformLocation(repeatTexProgram, "s_texture");
-    GLint repeatTexFillPortion = glGetUniformLocation(repeatTexProgram, "fillPortion");
-    GLint repeatTexScale = glGetUniformLocation(repeatTexProgram, "repeatScale");
-    m_handleArray[RepeatTex].init(repeatTexAlpha, -1, repeatTexPosition,
-                                  repeatTexProgram,repeatTexProjMtx, -1,
-                                  repeatTexTexSampler, -1, repeatTexFillPortion,
-                                  repeatTexScale);
-
-    GLint repeatTexInvAlpha = glGetUniformLocation(repeatTexInvProgram, "alpha");
-    GLint repeatTexInvContrast = glGetUniformLocation(tex2DInvProgram, "contrast");
-    GLint repeatTexInvPosition = glGetAttribLocation(repeatTexInvProgram, "vPosition");
-    GLint repeatTexInvProjMtx = glGetUniformLocation(repeatTexInvProgram, "projectionMatrix");
-    GLint repeatTexInvTexSampler = glGetUniformLocation(repeatTexInvProgram, "s_texture");
-    GLint repeatTexInvFillPortion = glGetUniformLocation(repeatTexInvProgram, "fillPortion");
-    GLint repeatTexInvScale = glGetUniformLocation(repeatTexInvProgram, "repeatScale");
-    m_handleArray[RepeatTexInv].init(repeatTexInvAlpha, repeatTexInvContrast,
-                                     repeatTexInvPosition, repeatTexInvProgram,
-                                     repeatTexInvProjMtx, -1,
-                                     repeatTexInvTexSampler, -1,
-                                     repeatTexInvFillPortion, repeatTexInvScale);
-
-    GLint texOESAlpha = glGetUniformLocation(texOESProgram, "alpha");
-    GLint texOESPosition = glGetAttribLocation(texOESProgram, "vPosition");
-    GLint texOESProjMtx = glGetUniformLocation(texOESProgram, "projectionMatrix");
-    GLint texOESTexSampler = glGetUniformLocation(texOESProgram, "s_texture");
-    GLint texOESFillPortion = glGetUniformLocation(texOESProgram, "fillPortion");
-    m_handleArray[TexOES].init(texOESAlpha, -1, texOESPosition, texOESProgram,
-                               texOESProjMtx, -1, texOESTexSampler, -1, texOESFillPortion, -1);
-
-    GLint texOESInvAlpha = glGetUniformLocation(texOESInvProgram, "alpha");
-    GLint texOESInvContrast = glGetUniformLocation(texOESInvProgram, "contrast");
-    GLint texOESInvPosition = glGetAttribLocation(texOESInvProgram, "vPosition");
-    GLint texOESInvProjMtx = glGetUniformLocation(texOESInvProgram, "projectionMatrix");
-    GLint texOESInvTexSampler = glGetUniformLocation(texOESInvProgram, "s_texture");
-    GLint texOESInvFillPortion = glGetUniformLocation(texOESInvProgram, "fillPortion");
-    m_handleArray[TexOESInv].init(texOESInvAlpha, texOESInvContrast,
-                                  texOESInvPosition, texOESInvProgram,
-                                  texOESInvProjMtx, -1,
-                                  texOESInvTexSampler, -1, texOESInvFillPortion, -1);
-
-    GLint videoPosition = glGetAttribLocation(videoProgram, "vPosition");
-    GLint videoProjMtx = glGetUniformLocation(videoProgram, "projectionMatrix");
-    GLint videoTexSampler = glGetUniformLocation(videoProgram, "s_yuvTexture");
-    GLint videoTexMtx = glGetUniformLocation(videoProgram, "textureMatrix");
-    m_handleArray[Video].init(-1, -1, videoPosition, videoProgram,
-                              videoProjMtx, -1, videoTexSampler,
-                              videoTexMtx, -1, -1);
-
-    const GLfloat coord[] = {
-        0.0f, 0.0f, // C
-        1.0f, 0.0f, // D
-        0.0f, 1.0f, // A
-        1.0f, 1.0f // B
-    };
-
-    glGenBuffers(1, m_textureBuffer);
-    glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
-    glBufferData(GL_ARRAY_BUFFER, 2 * 4 * sizeof(GLfloat), coord, GL_STATIC_DRAW);
-
-    TransformationMatrix matrix;
-    // Map x,y from (0,1) to (-1, 1)
-    matrix.scale3d(2, 2, 1);
-    matrix.translate3d(-0.5, -0.5, 0);
-    GLUtils::toGLMatrix(m_transferProjMtx, matrix);
-
-    m_needsInit = GLUtils::checkGlError("initGLResources");
-    return;
-}
-
-void ShaderProgram::resetBlending()
-{
-    glDisable(GL_BLEND);
-    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-    glBlendEquation(GL_FUNC_ADD);
-    m_blendingEnabled = false;
-}
-
-void ShaderProgram::setBlendingState(bool enableBlending)
-{
-    if (enableBlending == m_blendingEnabled)
-        return;
-
-    if (enableBlending)
-        glEnable(GL_BLEND);
-    else
-        glDisable(GL_BLEND);
-
-    m_blendingEnabled = enableBlending;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Drawing
-/////////////////////////////////////////////////////////////////////////////////////////
-
-// We have multiple coordinates to deal with: first is the screen coordinates,
-// second is the view coordinates and the last one is content(document) coordinates.
-// Both screen and view coordinates are in pixels.
-// All these coordinates start from upper left, but for the purpose of OpenGL
-// operations, we may need a inverted Y version of such coordinates which
-// start from lower left.
-//
-// invScreenRect - inv screen coordinates starting from lower left.
-// visibleContentRect - local content(document) coordinates starting from upper left.
-// screenRect - screen coordinates starting from upper left.
-// screenClip - screen coordinates starting from upper left.
-//    ------------------------------------------
-//    |(origin of screen)                      |
-//    |screen                                  |
-//    |   ---------------------------------    |
-//    |   | (origin of view)              |    |
-//    |   | webview                       |    |
-//    |   |        --------               |    |
-//    |   |        | clip |               |    |
-//    |   |        |      |               |    |
-//    |   |        --------               |    |
-//    |   |                               |    |
-//    |   |(origin of inv view)           |    |
-//    |   ---------------------------------    |
-//    |(origin of inv screen)                  |
-//    ------------------------------------------
-void ShaderProgram::setupDrawing(const IntRect& invScreenRect,
-                                 const SkRect& visibleContentRect,
-                                 const IntRect& screenRect, int titleBarHeight,
-                                 const IntRect& screenClip, float scale)
-{
-    m_screenRect = screenRect;
-    m_titleBarHeight = titleBarHeight;
-
-    //// viewport ////
-    GLUtils::setOrthographicMatrix(m_visibleContentRectProjectionMatrix,
-                                   visibleContentRect.fLeft,
-                                   visibleContentRect.fTop,
-                                   visibleContentRect.fRight,
-                                   visibleContentRect.fBottom,
-                                   -1000, 1000);
-
-    ALOGV("set m_clipProjectionMatrix, %d, %d, %d, %d",
-          screenClip.x(), screenClip.y(), screenClip.x() + screenClip.width(),
-          screenClip.y() + screenClip.height());
-
-    // In order to incorporate the animation delta X and Y, using the clip as
-    // the GL viewport can save all the trouble of re-position from screenRect
-    // to final position.
-    GLUtils::setOrthographicMatrix(m_clipProjectionMatrix, screenClip.x(), screenClip.y(),
-                                   screenClip.x() + screenClip.width(),
-                                   screenClip.y() + screenClip.height(), -1000, 1000);
-
-    glViewport(screenClip.x(), m_targetHeight - screenClip.y() - screenClip.height() ,
-               screenClip.width(), screenClip.height());
-
-    m_visibleContentRect = visibleContentRect;
-    m_currentScale = scale;
-
-
-    //// viewRect ////
-    m_invScreenRect = invScreenRect;
-
-    // The following matrices transform content coordinates into view coordinates
-    // and inv view coordinates.
-    // Note that GLUtils::setOrthographicMatrix is inverting the Y.
-    TransformationMatrix viewTranslate;
-    viewTranslate.translate(1.0, 1.0);
-
-    TransformationMatrix viewScale;
-    viewScale.scale3d(m_invScreenRect.width() * 0.5f, m_invScreenRect.height() * 0.5f, 1);
-
-    m_contentToInvViewMatrix = viewScale * viewTranslate * m_visibleContentRectProjectionMatrix;
-
-    viewTranslate.scale3d(1, -1, 1);
-    m_contentToViewMatrix = viewScale * viewTranslate * m_visibleContentRectProjectionMatrix;
-
-    IntRect invViewRect(0, 0, m_screenRect.width(), m_screenRect.height());
-    m_contentViewport = m_contentToInvViewMatrix.inverse().mapRect(invViewRect);
-
-
-    //// clipping ////
-    IntRect viewClip = screenClip;
-
-    // The incoming screenClip is in screen coordinates, we first
-    // translate it into view coordinates.
-    // Then we convert it into inverted view coordinates.
-    // Therefore, in the clip() function, we need to convert things back from
-    // inverted view coordinates to inverted screen coordinates which is used by GL.
-    viewClip.setX(screenClip.x() - m_screenRect.x());
-    viewClip.setY(screenClip.y() - m_screenRect.y() - m_titleBarHeight);
-    FloatRect invViewClip = convertViewCoordToInvViewCoord(viewClip);
-    m_invViewClip.setLocation(IntPoint(invViewClip.x(), invViewClip.y()));
-    // use ceilf to handle view -> doc -> view coord rounding errors
-    m_invViewClip.setSize(IntSize(ceilf(invViewClip.width()), ceilf(invViewClip.height())));
-
-    resetBlending();
-
-    // Set up m_clipProjectionMatrix, m_currentScale and m_webViewMatrix before
-    // calling this function.
-    setupSurfaceProjectionMatrix();
-}
-
-// Calculate the right color value sent into the shader considering the (0,1)
-// clamp and alpha blending.
-Color ShaderProgram::shaderColor(Color pureColor, float opacity)
-{
-    float r = pureColor.red() / 255.0;
-    float g = pureColor.green() / 255.0;
-    float b = pureColor.blue() / 255.0;
-    float a = pureColor.alpha() / 255.0;
-
-    if (TilesManager::instance()->invertedScreen()) {
-        float intensity = a - (0.2989 * r + 0.5866 * g + 0.1145 * b);
-        intensity = ((intensity - a / 2.0) * m_contrast) + a / 2.0;
-        intensity *= opacity;
-        return Color(intensity, intensity, intensity, a * opacity);
-    }
-    return Color(r * opacity, g * opacity, b * opacity, a * opacity);
-}
-
-// For shaders using texture, it is easy to get the type from the textureTarget.
-ShaderType ShaderProgram::getTextureShaderType(GLenum textureTarget,
-                                               bool hasRepeatScale)
-{
-    ShaderType type = UndefinedShader;
-    if (textureTarget == GL_TEXTURE_2D) {
-        if (!TilesManager::instance()->invertedScreen())
-            type = hasRepeatScale ?  RepeatTex : Tex2D;
-        else {
-            // With the new GPU texture upload path, we do not use an FBO
-            // to blit the texture we receive from the TexturesGenerator thread.
-            // To implement inverted rendering, we thus have to do the rendering
-            // live, by using a different shader.
-            type = hasRepeatScale ?  RepeatTexInv : Tex2DInv;
-        }
-    } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES) {
-        if (!TilesManager::instance()->invertedScreen())
-            type = TexOES;
-        else
-            type = TexOESInv;
-    }
-    return type;
-}
-
-// This function transform a clip rect extracted from the current layer
-// into a clip rect in InvView coordinates -- used by the clipping rects
-FloatRect ShaderProgram::rectInInvViewCoord(const TransformationMatrix& drawMatrix, const IntSize& size)
-{
-    FloatRect srect(0, 0, size.width(), size.height());
-    TransformationMatrix renderMatrix = m_contentToInvViewMatrix * drawMatrix;
-    return renderMatrix.mapRect(srect);
-}
-
-// used by the partial screen invals
-FloatRect ShaderProgram::rectInViewCoord(const TransformationMatrix& drawMatrix, const IntSize& size)
-{
-    FloatRect srect(0, 0, size.width(), size.height());
-    TransformationMatrix renderMatrix = m_contentToViewMatrix * drawMatrix;
-    return renderMatrix.mapRect(srect);
-}
-
-FloatRect ShaderProgram::rectInViewCoord(const FloatRect& rect)
-{
-    return m_contentToViewMatrix.mapRect(rect);
-}
-
-FloatRect ShaderProgram::rectInInvViewCoord(const FloatRect& rect)
-{
-    return m_contentToInvViewMatrix.mapRect(rect);
-}
-
-FloatRect ShaderProgram::convertInvViewCoordToContentCoord(const FloatRect& rect)
-{
-    return m_contentToInvViewMatrix.inverse().mapRect(rect);
-}
-
-FloatRect ShaderProgram::convertViewCoordToInvViewCoord(const FloatRect& rect)
-{
-    FloatRect visibleContentRect = m_contentToViewMatrix.inverse().mapRect(rect);
-    return rectInInvViewCoord(visibleContentRect);
-}
-
-FloatRect ShaderProgram::convertInvViewCoordToViewCoord(const FloatRect& rect)
-{
-    FloatRect visibleContentRect = m_contentToInvViewMatrix.inverse().mapRect(rect);
-    return rectInViewCoord(visibleContentRect);
-}
-
-// clip is in screen coordinates
-void ShaderProgram::clip(const FloatRect& clip)
-{
-    if (clip == m_clipRect)
-        return;
-
-    ALOGV("--clipping rect %f %f, %f x %f",
-          clip.x(), clip.y(), clip.width(), clip.height());
-
-    // we should only call glScissor in this function, so that we can easily
-    // track the current clipping rect.
-
-    IntRect screenClip(clip.x(),
-                       clip.y(),
-                       clip.width(), clip.height());
-
-    if (!m_invViewClip.isEmpty())
-        screenClip.intersect(m_invViewClip);
-
-    // The previous intersection calculation is using local screen coordinates.
-    // Now we need to convert things from local screen coordinates to global
-    // screen coordinates and pass to the GL functions.
-    screenClip.setX(screenClip.x() + m_invScreenRect.x());
-    screenClip.setY(screenClip.y() + m_invScreenRect.y());
-    if (screenClip.x() < 0) {
-        int w = screenClip.width();
-        w += screenClip.x();
-        screenClip.setX(0);
-        screenClip.setWidth(w);
-    }
-    if (screenClip.y() < 0) {
-        int h = screenClip.height();
-        h += screenClip.y();
-        screenClip.setY(0);
-        screenClip.setHeight(h);
-    }
-
-    glScissor(screenClip.x(), screenClip.y(), screenClip.width(), screenClip.height());
-
-    m_clipRect = clip;
-}
-
-IntRect ShaderProgram::clippedRectWithVisibleContentRect(const IntRect& rect, int margin)
-{
-    IntRect viewport(m_visibleContentRect.fLeft - margin, m_visibleContentRect.fTop - margin,
-                     m_visibleContentRect.width() + margin,
-                     m_visibleContentRect.height() + margin);
-    viewport.intersect(rect);
-    return viewport;
-}
-
-float ShaderProgram::zValue(const TransformationMatrix& drawMatrix, float w, float h)
-{
-    TransformationMatrix modifiedDrawMatrix = drawMatrix;
-    modifiedDrawMatrix.scale3d(w, h, 1);
-    TransformationMatrix renderMatrix =
-        m_visibleContentRectProjectionMatrix * modifiedDrawMatrix;
-    FloatPoint3D point(0.5, 0.5, 0.0);
-    FloatPoint3D result = renderMatrix.mapPoint(point);
-    return result.z();
-}
-
-void ShaderProgram::drawQuadInternal(ShaderType type, const GLfloat* matrix,
-                                     int textureId, float opacity,
-                                     GLenum textureTarget, GLenum filter,
-                                     const Color& pureColor, const FloatRect& fillPortion,
-                                     const FloatSize& repeatScale)
-{
-    glUseProgram(m_handleArray[type].programHandle);
-    glUniformMatrix4fv(m_handleArray[type].projMtxHandle, 1, GL_FALSE, matrix);
-
-    if (type != PureColor) {
-        glActiveTexture(GL_TEXTURE0);
-        glUniform1i(m_handleArray[type].texSamplerHandle, 0);
-        glBindTexture(textureTarget, textureId);
-        glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, filter);
-        glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, filter);
-        glUniform1f(m_handleArray[type].alphaHandle, opacity);
-
-        GLint contrastHandle = m_handleArray[type].contrastHandle;
-        if (contrastHandle != -1)
-            glUniform1f(contrastHandle, m_contrast);
-
-        glUniform4f(m_handleArray[type].fillPortionHandle, fillPortion.x(), fillPortion.y(),
-                    fillPortion.width(), fillPortion.height());
-
-        // Only when we have repeat scale, this handle can be >= 0;
-        if (m_handleArray[type].scaleHandle != -1) {
-            glUniform2f(m_handleArray[type].scaleHandle,
-                        repeatScale.width(), repeatScale.height());
-        }
-    } else {
-        glUniform4f(m_handleArray[type].pureColorHandle,
-                    pureColor.red() / 255.0, pureColor.green() / 255.0,
-                    pureColor.blue() / 255.0, pureColor.alpha() / 255.0);
-    }
-
-    GLint positionHandle = m_handleArray[type].positionHandle;
-    glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
-    glEnableVertexAttribArray(positionHandle);
-    glVertexAttribPointer(positionHandle, 2, GL_FLOAT, GL_FALSE, 0, 0);
-
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-}
-
-// Put the common matrix computation at higher level to avoid redundancy.
-void ShaderProgram::setupSurfaceProjectionMatrix()
-{
-    TransformationMatrix scaleMatrix;
-    scaleMatrix.scale3d(m_currentScale, m_currentScale, 1);
-    m_surfaceProjectionMatrix = m_clipProjectionMatrix * m_webViewMatrix * scaleMatrix;
-}
-
-// Calculate the matrix given the geometry.
-GLfloat* ShaderProgram::getTileProjectionMatrix(const DrawQuadData* data)
-{
-    DrawQuadType type = data->type();
-    if (type == Blit)
-        return m_transferProjMtx;
-
-    const TransformationMatrix* matrix = data->drawMatrix();
-    const SkRect* geometry = data->geometry();
-    FloatRect fillPortion = data->fillPortion();
-    ALOGV("fillPortion " FLOAT_RECT_FORMAT, FLOAT_RECT_ARGS(fillPortion));
-
-    // This modifiedDrawMatrix tranform (0,0)(1x1) to the final rect in screen
-    // coordinates, before applying the m_webViewMatrix.
-    // It first scale and translate the vertex array from (0,0)(1x1) to real
-    // tile position and size. Then apply the transform from the layer's.
-    // Finally scale to the currentScale to support zooming.
-    // Note the geometry contains the tile zoom scale, so visually we will see
-    // the tiles scale at a ratio as (m_currentScale/tile's scale).
-    TransformationMatrix modifiedDrawMatrix;
-    if (type == LayerQuad)
-        modifiedDrawMatrix = *matrix;
-    modifiedDrawMatrix.translate(geometry->fLeft + geometry->width() * fillPortion.x(),
-                                 geometry->fTop + geometry->height() * fillPortion.y());
-    modifiedDrawMatrix.scale3d(geometry->width() * fillPortion.width(),
-                               geometry->height() * fillPortion.height(), 1);
-
-    // Even when we are on a alpha layer or not, we need to respect the
-    // m_webViewMatrix, it may contain the layout offset. Normally it is
-    // identity.
-    TransformationMatrix renderMatrix;
-    renderMatrix = m_surfaceProjectionMatrix * modifiedDrawMatrix;
-
-#if DEBUG_MATRIX
-    debugMatrixInfo(m_currentScale, m_clipProjectionMatrix, m_webViewMatrix,
-                    modifiedDrawMatrix, matrix);
-#endif
-
-    GLUtils::toGLMatrix(m_tileProjMatrix, renderMatrix);
-    return m_tileProjMatrix;
-}
-
-void ShaderProgram::drawQuad(const DrawQuadData* data)
-{
-    GLfloat* matrix = getTileProjectionMatrix(data);
-
-    float opacity = data->opacity();
-    bool forceBlending = data->forceBlending();
-    bool enableBlending = forceBlending || opacity < 1.0;
-
-    ShaderType shaderType = UndefinedShader;
-    int textureId = 0;
-    GLint textureFilter = 0;
-    GLenum textureTarget = 0;
-
-    Color quadColor = data->quadColor();
-    if (data->pureColor()) {
-        shaderType = PureColor;
-        quadColor = shaderColor(quadColor, opacity);
-        enableBlending = enableBlending || quadColor.hasAlpha();
-        if (!quadColor.alpha() && enableBlending)
-            return;
-    } else {
-        textureId = data->textureId();
-        textureFilter = data->textureFilter();
-        textureTarget = data->textureTarget();
-        shaderType = getTextureShaderType(textureTarget, data->hasRepeatScale());
-    }
-    setBlendingState(enableBlending);
-    drawQuadInternal(shaderType, matrix, textureId, opacity,
-                     textureTarget, textureFilter, quadColor, data->fillPortion(),
-                     data->repeatScale());
-}
-
-void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix,
-                                       float* textureMatrix, SkRect& geometry,
-                                       int textureId)
-{
-    // switch to our custom yuv video rendering program
-    glUseProgram(m_handleArray[Video].programHandle);
-    // TODO: Merge drawVideoLayerQuad into drawQuad.
-    TransformationMatrix modifiedDrawMatrix;
-    modifiedDrawMatrix.scale3d(m_currentScale, m_currentScale, 1);
-    modifiedDrawMatrix.multiply(drawMatrix);
-    modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop);
-    modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1);
-    TransformationMatrix renderMatrix =
-        m_clipProjectionMatrix * m_webViewMatrix * modifiedDrawMatrix;
-
-    GLfloat projectionMatrix[16];
-    GLUtils::toGLMatrix(projectionMatrix, renderMatrix);
-    glUniformMatrix4fv(m_handleArray[Video].projMtxHandle, 1, GL_FALSE,
-                       projectionMatrix);
-    glUniformMatrix4fv(m_handleArray[Video].videoMtxHandle, 1, GL_FALSE,
-                       textureMatrix);
-    glActiveTexture(GL_TEXTURE0);
-    glUniform1i(m_handleArray[Video].texSamplerHandle, 0);
-    glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId);
-
-    GLint videoPosition = m_handleArray[Video].positionHandle;
-    glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
-    glEnableVertexAttribArray(videoPosition);
-    glVertexAttribPointer(videoPosition, 2, GL_FLOAT, GL_FALSE, 0, 0);
-
-    setBlendingState(false);
-    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-}
-
-void ShaderProgram::setGLDrawInfo(const android::uirenderer::DrawGlInfo* info)
-{
-    GLUtils::convertToTransformationMatrix(info->transform, m_webViewMatrix);
-    m_alphaLayer = info->isLayer;
-    m_targetHeight = info->height;
-}
-
-// This function is called per tileGrid to minimize the computation overhead.
-// The ortho projection and glViewport will map 1:1, so we don't need to
-// worry about them here. Basically, if the current zoom scale / tile's scale
-// plus the webview and layer transformation ends up at scale factor 1.0,
-// then we can use point sampling.
-bool ShaderProgram::usePointSampling(float tileScale,
-                                     const TransformationMatrix* layerTransform)
-{
-    const float testSize = 1.0;
-    FloatRect rect(0, 0, testSize, testSize);
-    TransformationMatrix matrix;
-    matrix.scale3d(m_currentScale, m_currentScale, 1);
-    if (layerTransform)
-        matrix.multiply(*layerTransform);
-    matrix.scale3d(1.0 / tileScale, 1.0 / tileScale, 1);
-
-    matrix = m_webViewMatrix * matrix;
-
-    rect = matrix.mapRect(rect);
-
-    float deltaWidth = abs(rect.width() - testSize);
-    float deltaHeight = abs(rect.height() - testSize);
-
-    if (deltaWidth < EPSILON && deltaHeight < EPSILON) {
-        ALOGV("Point sampling : deltaWidth is %f, deltaHeight is %f", deltaWidth, deltaHeight);
-        return true;
-    }
-    return false;
-}
-
-#if DEBUG_MATRIX
-FloatRect ShaderProgram::debugMatrixTransform(const TransformationMatrix& matrix,
-                                              const char* matrixName)
-{
-    FloatRect rect(0.0, 0.0, 1.0, 1.0);
-    rect = matrix.mapRect(rect);
-    ALOGV("After %s matrix:\n %f, %f rect.width() %f rect.height() %f",
-          matrixName, rect.x(), rect.y(), rect.width(), rect.height());
-    return rect;
-
-}
-
-void ShaderProgram::debugMatrixInfo(float currentScale,
-                                    const TransformationMatrix& clipProjectionMatrix,
-                                    const TransformationMatrix& webViewMatrix,
-                                    const TransformationMatrix& modifiedDrawMatrix,
-                                    const TransformationMatrix* layerMatrix)
-{
-    int viewport[4];
-    glGetIntegerv(GL_VIEWPORT, viewport);
-    ALOGV("viewport %d, %d, %d, %d , currentScale %f",
-          viewport[0], viewport[1], viewport[2], viewport[3], currentScale);
-    IntRect currentGLViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
-
-    TransformationMatrix scaleMatrix;
-    scaleMatrix.scale3d(currentScale, currentScale, 1.0);
-
-    if (layerMatrix)
-        debugMatrixTransform(*layerMatrix, "layerMatrix");
-
-    TransformationMatrix debugMatrix = scaleMatrix * modifiedDrawMatrix;
-    debugMatrixTransform(debugMatrix, "scaleMatrix * modifiedDrawMatrix");
-
-    debugMatrix = webViewMatrix * debugMatrix;
-    debugMatrixTransform(debugMatrix, "webViewMatrix * scaleMatrix * modifiedDrawMatrix");
-
-    debugMatrix = clipProjectionMatrix * debugMatrix;
-    FloatRect finalRect =
-        debugMatrixTransform(debugMatrix, "all Matrix");
-    // After projection, we will be in a (-1, 1) range and now we can map it back
-    // to the (x,y) -> (x+width, y+height)
-    ALOGV("final convert to screen coord x, y %f, %f width %f height %f , ",
-          (finalRect.x() + 1) / 2 * currentGLViewport.width() + currentGLViewport.x(),
-          (finalRect.y() + 1) / 2 * currentGLViewport.height() + currentGLViewport.y(),
-          finalRect.width() * currentGLViewport.width() / 2,
-          finalRect.height() * currentGLViewport.height() / 2);
-}
-#endif // DEBUG_MATRIX
-
-} // namespace WebCore
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h
deleted file mode 100644
index 27eb737..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ShaderProgram_h
-#define ShaderProgram_h
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "Color.h"
-#include "FloatRect.h"
-#include "IntRect.h"
-#include "SkRect.h"
-#include "TransformationMatrix.h"
-#include "private/hwui/DrawGlInfo.h"
-#include <GLES2/gl2.h>
-
-#define MAX_CONTRAST 5
-#define DEBUG_MATRIX 0
-
-namespace WebCore {
-
-class DrawQuadData;
-class PureColorQuadData;
-class TextureQuadData;
-
-enum ShaderType {
-    UndefinedShader = -1,
-    PureColor,
-    Tex2D,
-    Tex2DInv,
-    TexOES,
-    TexOESInv,
-    Video,
-    RepeatTex,
-    RepeatTexInv,
-    // When growing this enum list, make sure to insert before the
-    // MaxShaderNumber and init the m_handleArray accordingly.
-    MaxShaderNumber
-};
-
-struct ShaderHandles {
-    ShaderHandles()
-        : alphaHandle(-1)
-        , contrastHandle(-1)
-        , positionHandle(-1)
-        , programHandle(-1)
-        , projMtxHandle(-1)
-        , pureColorHandle(-1)
-        , texSamplerHandle(-1)
-        , videoMtxHandle(-1)
-        , fillPortionHandle(-1)
-        , scaleHandle(-1)
-    {
-    }
-
-    void init(GLint alphaHdl, GLint contrastHdl, GLint posHdl, GLint pgmHdl,
-              GLint projMtxHdl, GLint colorHdl, GLint texSamplerHdl,
-              GLint videoMtxHdl, GLint fillPortionHdl, GLint scaleHdl)
-    {
-        alphaHandle = alphaHdl;
-        contrastHandle = contrastHdl;
-        positionHandle = posHdl;
-        programHandle = pgmHdl;
-        projMtxHandle = projMtxHdl;
-        pureColorHandle = colorHdl;
-        texSamplerHandle = texSamplerHdl;
-        videoMtxHandle = videoMtxHdl;
-        fillPortionHandle = fillPortionHdl;
-        scaleHandle = scaleHdl;
-    }
-
-    GLint alphaHandle;
-    GLint contrastHandle;
-    GLint positionHandle;
-    GLint programHandle;
-    GLint projMtxHandle;
-    GLint pureColorHandle;
-    GLint texSamplerHandle;
-    GLint videoMtxHandle;
-    GLint fillPortionHandle;
-    GLint scaleHandle;
-};
-
-struct ShaderResource {
-    ShaderResource()
-        : program(-1)
-        , vertexShader(-1)
-        , fragmentShader(-1)
-    {
-    };
-
-    ShaderResource(GLuint prog, GLuint vertex, GLuint fragment)
-        : program(prog)
-        , vertexShader(vertex)
-        , fragmentShader(fragment)
-    {
-    };
-
-    GLuint program;
-    GLuint vertexShader;
-    GLuint fragmentShader;
-};
-
-class ShaderProgram {
-public:
-    ShaderProgram();
-    void initGLResources();
-    void cleanupGLResources();
-    // Drawing
-    void setupDrawing(const IntRect& invScreenRect, const SkRect& visibleContentRect,
-                      const IntRect& screenRect, int titleBarHeight,
-                      const IntRect& screenClip, float scale);
-    float zValue(const TransformationMatrix& drawMatrix, float w, float h);
-
-    // For drawQuad and drawLayerQuad, they can handle 3 cases for now:
-    // 1) textureTarget == GL_TEXTURE_2D
-    // Normal texture in GL_TEXTURE_2D target.
-    // 2) textureTarget == GL_TEXTURE_EXTERNAL_OES
-    // Surface texture in GL_TEXTURE_EXTERNAL_OES target.
-    // 3) textureId == 0
-    // No texture needed, just a pureColor quad.
-    void drawQuad(const DrawQuadData* data);
-    void drawVideoLayerQuad(const TransformationMatrix& drawMatrix,
-                     float* textureMatrix, SkRect& geometry, int textureId);
-    FloatRect rectInInvViewCoord(const TransformationMatrix& drawMatrix,
-                                const IntSize& size);
-    FloatRect rectInViewCoord(const TransformationMatrix& drawMatrix,
-                                const IntSize& size);
-
-    FloatRect rectInViewCoord(const FloatRect& rect);
-    FloatRect rectInInvViewCoord(const FloatRect& rect);
-    FloatRect convertInvViewCoordToContentCoord(const FloatRect& rect);
-    FloatRect convertViewCoordToInvViewCoord(const FloatRect& rect);
-    FloatRect convertInvViewCoordToViewCoord(const FloatRect& rect);
-
-    void clip(const FloatRect& rect);
-    IntRect clippedRectWithVisibleContentRect(const IntRect& rect, int margin = 0);
-    FloatRect contentViewport() { return m_contentViewport; }
-
-    float contrast() { return m_contrast; }
-    void setContrast(float c)
-    {
-        float contrast = c;
-        if (contrast < 0)
-            contrast = 0;
-        if (contrast > MAX_CONTRAST)
-            contrast = MAX_CONTRAST;
-        m_contrast = contrast;
-    }
-    void setGLDrawInfo(const android::uirenderer::DrawGlInfo* info);
-    void forceNeedsInit() { m_needsInit = true; }
-    bool needsInit() { return m_needsInit; }
-    bool usePointSampling(float tileScale, const TransformationMatrix* layerTransform);
-
-private:
-    GLuint loadShader(GLenum shaderType, const char* pSource);
-    GLint createProgram(const char* vertexSource, const char* fragmentSource);
-    GLfloat* getTileProjectionMatrix(const DrawQuadData* data);
-    void setBlendingState(bool enableBlending);
-    void drawQuadInternal(ShaderType type, const GLfloat* matrix, int textureId,
-                         float opacity, GLenum textureTarget, GLenum filter,
-                         const Color& pureColor,  const FloatRect& fillPortion,
-                         const FloatSize& repeatScale);
-    Color shaderColor(Color pureColor, float opacity);
-    ShaderType getTextureShaderType(GLenum textureTarget, bool hasRepeatScale);
-    void resetBlending();
-    void setupSurfaceProjectionMatrix();
-#if DEBUG_MATRIX
-    FloatRect debugMatrixTransform(const TransformationMatrix& matrix, const char* matrixName);
-    void debugMatrixInfo(float currentScale,
-                         const TransformationMatrix& clipProjectionMatrix,
-                         const TransformationMatrix& webViewMatrix,
-                         const TransformationMatrix& modifiedDrawMatrix,
-                         const TransformationMatrix* layerMatrix);
-#endif // DEBUG_MATRIX
-
-    bool m_blendingEnabled;
-
-    TransformationMatrix m_surfaceProjectionMatrix;
-    TransformationMatrix m_clipProjectionMatrix;
-    TransformationMatrix m_visibleContentRectProjectionMatrix;
-    GLuint m_textureBuffer[1];
-
-    TransformationMatrix m_contentToInvViewMatrix;
-    TransformationMatrix m_contentToViewMatrix;
-    SkRect m_visibleContentRect;
-    IntRect m_invScreenRect;
-    FloatRect m_clipRect;
-    IntRect m_invViewClip;
-    int m_titleBarHeight;
-    // This is the layout position in screen coordinate and didn't contain the
-    // animation offset.
-    IntRect m_screenRect;
-
-    FloatRect m_contentViewport;
-
-    float m_contrast;
-
-    // The height of the render target, either FBO or screen.
-    int m_targetHeight;
-    bool m_alphaLayer;
-    TransformationMatrix m_webViewMatrix;
-    float m_currentScale;
-
-    // Put all the uniform location (handle) info into an array, and group them
-    // by the shader's type, this can help to clean up the interface.
-    // TODO: use the type and data comparison to skip GL call if possible.
-    ShaderHandles m_handleArray[MaxShaderNumber];
-
-    // If there is any GL error happens such that the Shaders are not initialized
-    // successfully at the first time, then we need to init again when we draw.
-    bool m_needsInit;
-
-    // For transfer queue blitting, we need a special matrix map from (0,1) to
-    // (-1,1)
-    GLfloat m_transferProjMtx[16];
-
-    GLfloat m_tileProjMatrix[16];
-
-    Vector<ShaderResource> m_resources;
-};
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
-#endif // ShaderProgram_h
diff --git a/Source/WebCore/platform/graphics/android/rendering/Surface.cpp b/Source/WebCore/platform/graphics/android/rendering/Surface.cpp
deleted file mode 100644
index 1898910..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/Surface.cpp
+++ /dev/null
@@ -1,495 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "Surface"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "Surface.h"
-
-#include "AndroidLog.h"
-#include "BaseLayerAndroid.h"
-#include "ClassTracker.h"
-#include "LayerAndroid.h"
-#include "LayerContent.h"
-#include "GLWebViewState.h"
-#include "PrerenderedInval.h"
-#include "SkCanvas.h"
-#include "SurfaceBacking.h"
-#include "Tile.h"
-#include "TileTexture.h"
-#include "TilesManager.h"
-
-#include <wtf/text/CString.h>
-
-// Surfaces with an area larger than 2048*2048 should never be unclipped
-#define MAX_FULL_CONTENT_AREA 4194304
-
-namespace WebCore {
-
-Surface::Surface()
-    : m_surfaceBacking(0)
-    , m_needsTexture(false)
-    , m_hasText(false)
-{
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->increment("Surface");
-#endif
-}
-
-Surface::~Surface()
-{
-    for (unsigned int i = 0; i < m_layers.size(); i++)
-        SkSafeUnref(m_layers[i]);
-    if (m_surfaceBacking)
-        SkSafeUnref(m_surfaceBacking);
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->decrement("Surface");
-#endif
-}
-
-bool Surface::tryUpdateSurface(Surface* oldSurface)
-{
-    if (!needsTexture() || !oldSurface->needsTexture())
-        return false;
-
-    // merge surfaces based on first layer ID
-    if (getFirstLayer()->uniqueId() != oldSurface->getFirstLayer()->uniqueId())
-        return false;
-
-    m_surfaceBacking = oldSurface->m_surfaceBacking;
-    SkSafeRef(m_surfaceBacking);
-
-    ALOGV("%p taking old SurfBack %p from surface %p, nt %d",
-          this, m_surfaceBacking, oldSurface, oldSurface->needsTexture());
-
-    if (!m_surfaceBacking) {
-        // no SurfBack to inval, so don't worry about it.
-        return true;
-    }
-
-    SkRegion invalRegion;
-    bool fullInval = false;
-    if (singleLayer() && oldSurface->singleLayer()) {
-        // both are single matching layers, simply apply inval
-        SkRegion* layerInval = getFirstLayer()->getInvalRegion();
-        invalRegion = *layerInval;
-
-        if (isBase()) {
-            // the base layer paints outside it's content area to ensure the
-            // viewport is convered, so fully invalidate all tiles if its size
-            // changes to ensure no stale content remains
-            LayerContent* newContent = getFirstLayer()->content();
-            LayerContent* oldContent = oldSurface->getFirstLayer()->content();
-            fullInval = newContent->width() != oldContent->width()
-                || newContent->height() != oldContent->height();
-        }
-    } else {
-        fullInval = m_layers.size() != oldSurface->m_layers.size();
-        if (!fullInval) {
-            for (unsigned int i = 0; i < m_layers.size(); i++) {
-                if ((m_layers[i]->uniqueId() != oldSurface->m_layers[i]->uniqueId())
-                    || (m_layers[i]->fullContentAreaMapped() != oldSurface->m_layers[i]->fullContentAreaMapped())) {
-                    // layer list has changed, fully invalidate
-                    // TODO: partially invalidate based on layer size/position
-                    fullInval = true;
-                    break;
-                } else if (!m_layers[i]->getInvalRegion()->isEmpty()) {
-                    // merge layer inval - translate the layer's inval region into surface coordinates
-                    // TODO: handle scale/3d transform mapping
-                    FloatRect layerPos = m_layers[i]->fullContentAreaMapped();
-                    m_layers[i]->getInvalRegion()->translate(layerPos.x(), layerPos.y());
-                    invalRegion.op(*(m_layers[i]->getInvalRegion()), SkRegion::kUnion_Op);
-                }
-            }
-        }
-    }
-
-    if (fullInval)
-        invalRegion.setRect(-1e8, -1e8, 2e8, 2e8);
-
-    m_surfaceBacking->markAsDirty(invalRegion);
-    return true;
-}
-
-void Surface::addLayer(LayerAndroid* layer, const TransformationMatrix& transform)
-{
-    m_layers.append(layer);
-    SkSafeRef(layer);
-
-    m_needsTexture |= layer->needsTexture();
-    m_hasText |= layer->hasText();
-
-    // add this layer's size to the surface's area
-    // TODO: handle scale/3d transform mapping
-    IntRect rect = enclosingIntRect(layer->fullContentAreaMapped());
-
-    if (layer->needsTexture()) {
-        if (m_fullContentArea.isEmpty()) {
-            m_drawTransform = transform;
-            m_drawTransform.translate3d(-rect.x(), -rect.y(), 0);
-            m_fullContentArea = rect;
-        } else
-            m_fullContentArea.unite(rect);
-        ALOGV("Surf %p adding LA %p, size " INT_RECT_FORMAT
-              " now fullContentArea " INT_RECT_FORMAT,
-              this, layer, INT_RECT_ARGS(rect), INT_RECT_ARGS(m_fullContentArea));
-    }
-
-    if (isBase())
-        m_background = static_cast<BaseLayerAndroid*>(layer)->getBackgroundColor();
-}
-
-IntRect Surface::visibleContentArea(bool force3dContentVisible) const
-{
-    if (singleLayer())
-        return getFirstLayer()->visibleContentArea(force3dContentVisible);
-
-    IntRect rect = m_fullContentArea;
-
-    // clip with the viewport in content coordinate
-    IntRect contentViewport(TilesManager::instance()->shader()->contentViewport());
-    rect.intersect(contentViewport);
-
-    // TODO: handle recursive layer clip
-
-    return rect;
-}
-
-IntRect Surface::fullContentArea()
-{
-    if (singleLayer())
-        return getFirstLayer()->fullContentArea();
-    return m_fullContentArea;
-}
-
-bool Surface::useAggressiveRendering()
-{
-    // When the background is semi-opaque, 0 < alpha < 255, we had to turn off
-    // low res to avoid artifacts from double drawing.
-    // TODO: avoid double drawing for low res tiles.
-    return isBase()
-           && (!m_background.alpha()
-           || !m_background.hasAlpha());
-}
-
-void Surface::prepareGL(bool layerTilesDisabled, bool updateWithBlit)
-{
-    bool tilesDisabled = layerTilesDisabled && !isBase();
-    if (!m_surfaceBacking) {
-        ALOGV("prepareGL on Surf %p, no SurfBack, needsTexture? %d",
-              this, m_surfaceBacking, needsTexture());
-
-        if (needsTexture() || (isBase() && layerTilesDisabled))
-            m_surfaceBacking = new SurfaceBacking(isBase());
-        else
-            return;
-    }
-
-    if (tilesDisabled) {
-        m_surfaceBacking->discardTextures();
-    } else {
-        bool allowZoom = hasText(); // only allow for scale > 1 if painting vectors
-        IntRect prepareArea = computePrepareArea();
-        IntRect fullArea = fullContentArea();
-
-        ALOGV("prepareGL on Surf %p with SurfBack %p, %d layers, first layer %s (%d) "
-              "prepareArea(%d, %d - %d x %d) fullArea(%d, %d - %d x %d)",
-              this, m_surfaceBacking, m_layers.size(),
-              getFirstLayer()->subclassName().ascii().data(),
-              getFirstLayer()->uniqueId(),
-              prepareArea.x(), prepareArea.y(), prepareArea.width(), prepareArea.height(),
-              fullArea.x(), fullArea.y(), fullArea.width(), fullArea.height());
-
-        m_surfaceBacking->prepareGL(getFirstLayer()->state(), allowZoom,
-                                    prepareArea, fullArea,
-                                    this, useAggressiveRendering(), updateWithBlit);
-    }
-    for (size_t i = 0; i < m_layers.size(); i++) {
-        LayerContent* content = m_layers[i]->content();
-        if (content)
-            content->clearPrerenders();
-    }
-}
-
-bool Surface::drawGL(bool layerTilesDisabled)
-{
-    bool tilesDisabled = layerTilesDisabled && !isBase();
-    if (singleLayer() && !getFirstLayer()->visible())
-        return false;
-
-    if (!isBase()) {
-        FloatRect drawClip = getFirstLayer()->drawClip();
-        if (!singleLayer()) {
-            for (unsigned int i = 1; i < m_layers.size(); i++)
-                drawClip.unite(m_layers[i]->drawClip());
-        }
-        FloatRect clippingRect = TilesManager::instance()->shader()->rectInInvViewCoord(drawClip);
-        TilesManager::instance()->shader()->clip(clippingRect);
-    }
-
-    bool askRedraw = false;
-    if (m_surfaceBacking && !tilesDisabled) {
-        ALOGV("drawGL on Surf %p with SurfBack %p, first layer %s (%d)", this, m_surfaceBacking,
-              getFirstLayer()->subclassName().ascii().data(), getFirstLayer()->uniqueId());
-
-        bool force3dContentVisible = true;
-        IntRect drawArea = visibleContentArea(force3dContentVisible);
-        m_surfaceBacking->drawGL(drawArea, opacity(), drawTransform(),
-                                 useAggressiveRendering(), background());
-    }
-
-    // draw member layers (draws image textures, glextras)
-    for (unsigned int i = 0; i < m_layers.size(); i++) {
-        if (m_layers[i]->drawGL(tilesDisabled)) {
-           m_layers[i]->addDirtyArea();
-           askRedraw = true;
-        }
-    }
-
-    return askRedraw;
-}
-
-void Surface::swapTiles(bool calculateFrameworkInvals)
-{
-    if (!m_surfaceBacking)
-        return;
-
-    if (m_surfaceBacking->swapTiles() && calculateFrameworkInvals)
-        addFrameworkInvals();
-}
-
-void Surface::addFrameworkInvals()
-{
-    // Let's return an inval area to framework that will
-    // contain all of our layers' areas
-    for (unsigned int i = 0; i < m_layers.size(); i++)
-        m_layers[i]->addDirtyArea();
-}
-
-bool Surface::isReady()
-{
-    if (!m_surfaceBacking)
-        return true;
-
-    return m_surfaceBacking->isReady();
-}
-
-bool Surface::isMissingContent()
-{
-    if (!m_surfaceBacking)
-        return true;
-
-    return m_surfaceBacking->isMissingContent();
-}
-
-bool Surface::canUpdateWithBlit()
-{
-    // If we don't have a texture, we have nothing to update and thus can take
-    // the fast path
-    if (!needsTexture())
-        return true;
-    // If we have a surface backing that isn't ready, we can't update with a blit
-    // If it is ready, then check to see if it is dirty. We can only call isDirty()
-    // if isReady() returns true
-    if (!m_surfaceBacking)
-        return false;
-    if (!m_surfaceBacking->isReady())
-        return false;
-    if (!m_surfaceBacking->isDirty())
-        return true;
-    if (!singleLayer())
-        return false;
-    return getFirstLayer()->canUpdateWithBlit();
-}
-
-IntRect Surface::computePrepareArea()
-{
-    IntRect area;
-
-    if (!getFirstLayer()->contentIsScrollable()
-        && !isBase()
-        && getFirstLayer()->state()->layersRenderingMode() == GLWebViewState::kAllTextures) {
-
-        area = fullContentArea();
-
-        double total = ((double) area.width()) * ((double) area.height());
-        if (total > MAX_FULL_CONTENT_AREA)
-            area = visibleContentArea();
-    } else
-        area = visibleContentArea();
-
-    return area;
-}
-
-void Surface::computeTexturesAmount(TexturesResult* result)
-{
-    if (!m_surfaceBacking || isBase())
-        return;
-
-
-    LayerAndroid* layer = 0;
-    if (singleLayer())
-        layer = getFirstLayer();
-
-    m_surfaceBacking->computeTexturesAmount(result, visibleContentArea(),
-                                            fullContentArea(), layer);
-}
-
-bool Surface::isBase()
-{
-    // base layer surface
-    // - doesn't use layer tiles (disables blending, doesn't compute textures amount)
-    // - ignores clip rects
-    // - only prepares clippedArea
-    return getFirstLayer()->subclassType() == LayerAndroid::BaseLayer;
-}
-
-bool Surface::paint(SkCanvas* canvas)
-{
-    if (singleLayer()) {
-        getFirstLayer()->contentDraw(canvas, Layer::UnmergedLayers);
-
-        // TODO: double buffer by disabling SurfaceCollection swaps and position
-        // updates until painting complete
-
-        // In single surface mode, draw layer content onto the base layer
-        if (isBase()
-            && getFirstLayer()->countChildren()
-            && getFirstLayer()->state()->isSingleSurfaceRenderingMode()) {
-            for (int i = 0; i < getFirstLayer()->countChildren(); i++)
-                getFirstLayer()->getChild(i)->drawCanvas(canvas, true, Layer::FlattenedLayers);
-        }
-    } else {
-        SkAutoCanvasRestore acr(canvas, true);
-        SkMatrix matrix;
-        GLUtils::toSkMatrix(matrix, m_drawTransform);
-
-        SkMatrix inverse;
-        inverse.reset();
-        matrix.invert(&inverse);
-
-        SkMatrix canvasMatrix = canvas->getTotalMatrix();
-        inverse.postConcat(canvasMatrix);
-        canvas->setMatrix(inverse);
-
-        for (unsigned int i=0; i<m_layers.size(); i++)
-            m_layers[i]->drawCanvas(canvas, false, Layer::MergedLayers);
-    }
-    return true;
-}
-
-float Surface::opacity()
-{
-    if (singleLayer())
-        return getFirstLayer()->drawOpacity();
-    return 1.0;
-}
-
-Color* Surface::background()
-{
-    if (!isBase() || !m_background.isValid())
-        return 0;
-    return &m_background;
-}
-
-bool Surface::blitFromContents(Tile* tile)
-{
-    if (!singleLayer() || !tile || !getFirstLayer() || !getFirstLayer()->content())
-        return false;
-
-    if (tile->frontTexture() != tile->lastDrawnTexture()) {
-        // the below works around an issue where glTexSubImage2d can't update a
-        // texture that hasn't drawn yet by drawing it off screen.
-        // glFlush() and glFinish() work also, but are likely more wasteful.
-        SkRect rect = SkRect::MakeXYWH(-100, -100, 0, 0);
-        FloatRect fillPortion(0, 0, 0, 0);
-        tile->frontTexture()->drawGL(false, rect, 1.0f, 0, false, true, fillPortion);
-    }
-    LayerContent* content = getFirstLayer()->content();
-    // Extract the dirty rect from the region. Note that this is *NOT* constrained
-    // to this tile
-    IntRect dirtyRect = tile->dirtyArea().getBounds();
-    IntRect tileRect = IntRect(tile->x() * TilesManager::tileWidth(),
-                               tile->y() * TilesManager::tileHeight(),
-                               TilesManager::tileWidth(),
-                               TilesManager::tileHeight());
-    FloatRect tileRectInDoc = tileRect;
-    tileRectInDoc.scale(1 / tile->scale());
-    dirtyRect.intersect(enclosingIntRect(tileRectInDoc));
-    PrerenderedInval* prerenderedInval = content->prerenderForRect(dirtyRect);
-    if (!prerenderedInval || prerenderedInval->bitmap.isNull())
-        return false;
-    SkBitmap sourceBitmap = prerenderedInval->bitmap;
-    // Calculate the screen rect that is dirty, then intersect it with the
-    // tile's screen rect so that we end up with the pixels we need to blit
-    FloatRect screenDirty = dirtyRect;
-    screenDirty.scale(tile->scale());
-    IntRect enclosingScreenDirty = enclosingIntRect(screenDirty);
-    enclosingScreenDirty.intersect(tileRect);
-    if (enclosingScreenDirty.isEmpty())
-        return false;
-    // Make sure the screen area we want to blit is contained by the
-    // prerendered screen area
-    if (!prerenderedInval->screenArea.contains(enclosingScreenDirty)) {
-        ALOGD("prerendered->screenArea " INT_RECT_FORMAT " doesn't contain "
-                "enclosingScreenDirty " INT_RECT_FORMAT,
-                INT_RECT_ARGS(prerenderedInval->screenArea),
-                INT_RECT_ARGS(enclosingScreenDirty));
-        return false;
-    }
-    IntPoint origin = prerenderedInval->screenArea.location();
-    SkBitmap subset;
-    subset.setConfig(sourceBitmap.config(), enclosingScreenDirty.width(),
-            enclosingScreenDirty.height());
-    subset.allocPixels();
-
-    int topOffset = enclosingScreenDirty.y() - prerenderedInval->screenArea.y();
-    int leftOffset = enclosingScreenDirty.x() - prerenderedInval->screenArea.x();
-    if (!GLUtils::deepCopyBitmapSubset(sourceBitmap, subset, leftOffset, topOffset))
-        return false;
-    // Now upload
-    SkIRect textureInval = SkIRect::MakeXYWH(enclosingScreenDirty.x() - tileRect.x(),
-                                             enclosingScreenDirty.y() - tileRect.y(),
-                                             enclosingScreenDirty.width(),
-                                             enclosingScreenDirty.height());
-    GLUtils::updateTextureWithBitmap(tile->frontTexture()->m_ownTextureId,
-                                     subset, textureInval);
-    tile->onBlitUpdate();
-    return true;
-}
-
-const TransformationMatrix* Surface::drawTransform()
-{
-    // single layer surfaces query the layer's draw transform, while multi-layer
-    // surfaces copy the draw transform once, during initialization
-    // TODO: support fixed multi-layer surfaces by querying the changing drawTransform
-    if (singleLayer())
-        return getFirstLayer()->drawTransform();
-
-    return &m_drawTransform;
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/Surface.h b/Source/WebCore/platform/graphics/android/rendering/Surface.h
deleted file mode 100644
index f9f38e6..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/Surface.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef Surface_h
-#define Surface_h
-
-#include "Color.h"
-#include "IntRect.h"
-#include "TilePainter.h"
-#include "Vector.h"
-
-class SkCanvas;
-class SkRegion;
-
-namespace WebCore {
-
-class Tile;
-class SurfaceBacking;
-class LayerAndroid;
-class TexturesResult;
-
-class Surface : public TilePainter {
-public:
-    Surface();
-    virtual ~Surface();
-
-    bool tryUpdateSurface(Surface* oldSurface);
-
-    void addLayer(LayerAndroid* layer, const TransformationMatrix& transform);
-    void prepareGL(bool layerTilesDisabled, bool updateWithBlit);
-    bool drawGL(bool layerTilesDisabled);
-    void swapTiles(bool calculateFrameworkInvals);
-    void addFrameworkInvals();
-    bool isReady();
-    bool isMissingContent();
-    bool canUpdateWithBlit();
-
-    void computeTexturesAmount(TexturesResult* result);
-
-    LayerAndroid* getFirstLayer() const { return m_layers[0]; }
-    bool needsTexture() { return m_needsTexture; }
-    bool hasText() { return m_hasText; }
-    bool isBase();
-
-    // don't allow transform fudging for merged layers - they need the transform
-    // static at paint time, and are always aligned to 0,0 doc coordinates.
-    bool allowTransformFudging() const { return singleLayer(); }
-
-    // TilePainter methods
-    virtual bool paint(SkCanvas* canvas);
-    virtual float opacity();
-    virtual Color* background();
-    virtual bool blitFromContents(Tile* tile);
-
-private:
-    IntRect computePrepareArea();
-    IntRect visibleContentArea(bool force3dContentVisible = false) const;
-    IntRect fullContentArea();
-    bool singleLayer() const { return m_layers.size() == 1; }
-    bool useAggressiveRendering();
-
-    const TransformationMatrix* drawTransform();
-    IntRect m_fullContentArea;
-    TransformationMatrix m_drawTransform;
-
-    SurfaceBacking* m_surfaceBacking;
-    bool m_needsTexture;
-    bool m_hasText;
-    Vector<LayerAndroid*> m_layers;
-
-    Color m_background;
-};
-
-class LayerMergeState {
-public:
-    LayerMergeState(Vector<Surface*>* const allGroups)
-        : surfaceList(allGroups)
-        , currentSurface(0)
-        , nonMergeNestedLevel(0)
-        , depth(0)
-        {}
-
-    // vector storing all generated layer groups
-    Vector<Surface*>* const surfaceList;
-
-    // currently merging group. if cleared, no more layers may join
-    Surface* currentSurface;
-
-    // records depth within non-mergeable parents (clipping, fixed, scrolling)
-    // and disable merging therein.
-    int nonMergeNestedLevel;
-
-    // counts layer tree depth for debugging
-    int depth;
-};
-
-} // namespace WebCore
-
-#endif //#define Surface_h
diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp
deleted file mode 100644
index d7f6535..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "SurfaceBacking"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "SurfaceBacking.h"
-
-#include "AndroidLog.h"
-#include "Color.h"
-#include "ClassTracker.h"
-#include "GLWebViewState.h"
-#include "LayerAndroid.h"
-
-#define LOW_RES_PREFETCH_SCALE_MODIFIER 0.3f
-
-namespace WebCore {
-
-SurfaceBacking::SurfaceBacking(bool isBaseSurface)
-{
-    m_frontTileGrid = new TileGrid(isBaseSurface);
-    m_backTileGrid = new TileGrid(isBaseSurface);
-    m_lowResTileGrid = new TileGrid(isBaseSurface);
-    m_scale = -1;
-    m_futureScale = -1;
-    m_zooming = false;
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->increment("SurfaceBacking");
-#endif
-}
-
-SurfaceBacking::~SurfaceBacking()
-{
-    delete m_frontTileGrid;
-    delete m_backTileGrid;
-    delete m_lowResTileGrid;
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->decrement("SurfaceBacking");
-#endif
-}
-
-void SurfaceBacking::prepareGL(GLWebViewState* state, bool allowZoom,
-                               const IntRect& prepareArea, const IntRect& fullContentArea,
-                               TilePainter* painter, bool aggressiveRendering,
-                               bool updateWithBlit)
-{
-    float scale = state->scale();
-    if (scale > 1 && !allowZoom)
-        scale = 1;
-
-    if (m_scale == -1) {
-        m_scale = scale;
-        m_futureScale = scale;
-    }
-
-    if (m_futureScale != scale) {
-        m_futureScale = scale;
-        m_zoomUpdateTime = WTF::currentTime() + SurfaceBacking::s_zoomUpdateDelay;
-        m_zooming = true;
-
-        // release back TileGrid's TileTextures, so they can be reused immediately
-        m_backTileGrid->discardTextures();
-    }
-
-    int prepareRegionFlags = TileGrid::StandardRegion;
-    if (aggressiveRendering)
-        prepareRegionFlags |= TileGrid::ExpandedRegion;
-
-    ALOGV("Prepare SurfBack %p, scale %.2f, m_scale %.2f, futScale: %.2f, zooming: %d, f %p, b %p",
-          this, scale, m_scale, m_futureScale, m_zooming,
-          m_frontTileGrid, m_backTileGrid);
-
-    if (m_zooming && (m_zoomUpdateTime < WTF::currentTime())) {
-        // prepare the visible portions of the back tile grid at the futureScale
-        m_backTileGrid->prepareGL(state, m_futureScale,
-                                  prepareArea, fullContentArea, painter,
-                                  TileGrid::StandardRegion, false);
-
-        if (m_backTileGrid->isReady()) {
-            // zooming completed, swap the TileGrids and new front tiles
-            swapTileGrids();
-
-            m_frontTileGrid->swapTiles();
-            m_backTileGrid->discardTextures();
-            m_lowResTileGrid->discardTextures();
-
-            m_scale = m_futureScale;
-            m_zooming = false;
-
-            // clear the StandardRegion flag, to prevent preparing it twice -
-            // the new frontTileGrid has already had its StandardRegion prepared
-            prepareRegionFlags &= ~TileGrid::StandardRegion;
-        }
-    }
-
-    if (!m_zooming) {
-        if (prepareRegionFlags) {
-            // if the front grid hasn't already prepared, or needs to prepare
-            // expanded bounds do so now
-            m_frontTileGrid->prepareGL(state, m_scale,
-                                       prepareArea, fullContentArea, painter,
-                                       prepareRegionFlags, false, updateWithBlit);
-        }
-        if (aggressiveRendering) {
-            // prepare low res content
-            float lowResPrefetchScale = m_scale * LOW_RES_PREFETCH_SCALE_MODIFIER;
-            m_lowResTileGrid->prepareGL(state, lowResPrefetchScale,
-                                       prepareArea, fullContentArea, painter,
-                                       TileGrid::StandardRegion | TileGrid::ExpandedRegion, true);
-            m_lowResTileGrid->swapTiles();
-        }
-    }
-}
-
-void SurfaceBacking::drawGL(const IntRect& visibleContentArea, float opacity,
-                            const TransformationMatrix* transform,
-                            bool aggressiveRendering, const Color* background)
-{
-    // draw low res prefetch page if zooming or front texture missing content
-    if (aggressiveRendering && isMissingContent())
-        m_lowResTileGrid->drawGL(visibleContentArea, opacity, transform);
-
-    m_frontTileGrid->drawGL(visibleContentArea, opacity, transform, background);
-}
-
-void SurfaceBacking::markAsDirty(const SkRegion& dirtyArea)
-{
-    m_backTileGrid->markAsDirty(dirtyArea);
-    m_frontTileGrid->markAsDirty(dirtyArea);
-    m_lowResTileGrid->markAsDirty(dirtyArea);
-}
-
-bool SurfaceBacking::swapTiles()
-{
-    bool swap = m_backTileGrid->swapTiles();
-    swap |= m_frontTileGrid->swapTiles();
-    swap |= m_lowResTileGrid->swapTiles();
-    return swap;
-}
-
-void SurfaceBacking::computeTexturesAmount(TexturesResult* result,
-                                           const IntRect& visibleContentArea,
-                                           const IntRect& fullContentArea,
-                                           LayerAndroid* layer)
-{
-
-    // get two numbers here:
-    // - textures needed for a clipped area
-    // - textures needed for an un-clipped area
-    TileGrid* tileGrid = m_zooming ? m_backTileGrid : m_frontTileGrid;
-    int nbTexturesUnclipped = tileGrid->nbTextures(fullContentArea, m_futureScale);
-    int nbTexturesClipped = tileGrid->nbTextures(visibleContentArea, m_futureScale);
-
-    if (layer) {
-        // TODO: should handle multi-layer case better
-
-        // Set kFixedLayers level
-        if (layer->isPositionFixed())
-            result->fixed += nbTexturesClipped;
-
-        // Set kScrollableAndFixedLayers level
-        if (layer->contentIsScrollable()
-            || layer->isPositionFixed())
-            result->scrollable += nbTexturesClipped;
-    }
-
-    // Set kClippedTextures level
-    result->clipped += nbTexturesClipped;
-
-    // Set kAllTextures level
-    if (layer && layer->contentIsScrollable())
-        result->full += nbTexturesClipped;
-    else
-        result->full += nbTexturesUnclipped;
-}
-
-void SurfaceBacking::swapTileGrids()
-{
-    TileGrid* temp = m_frontTileGrid;
-    m_frontTileGrid = m_backTileGrid;
-    m_backTileGrid = temp;
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h b/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h
deleted file mode 100644
index 5709f2a..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/SurfaceBacking.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef SurfaceBacking_h
-#define SurfaceBacking_h
-
-#include "SkRefCnt.h"
-#include "TileGrid.h"
-
-namespace WebCore {
-
-class LayerAndroid;
-class TexturesResult;
-class TilePainter;
-
-class SurfaceBacking : public SkRefCnt {
-// TODO: investigate webkit threadsafe ref counting
-public:
-    SurfaceBacking(bool isBaseSurface);
-    ~SurfaceBacking();
-    void prepareGL(GLWebViewState* state, bool allowZoom,
-                   const IntRect& prepareArea, const IntRect& fullContentArea,
-                   TilePainter* painter, bool aggressiveRendering,
-                   bool updateWithBlit);
-    bool swapTiles();
-    void drawGL(const IntRect& visibleContentArea, float opacity,
-                const TransformationMatrix* transform, bool aggressiveRendering,
-                const Color* background);
-    void markAsDirty(const SkRegion& dirtyArea);
-    void computeTexturesAmount(TexturesResult* result,
-                               const IntRect& visibleContentArea,
-                               const IntRect& fullContentArea,
-                               LayerAndroid* layer);
-    void discardTextures()
-    {
-        m_frontTileGrid->discardTextures();
-        m_backTileGrid->discardTextures();
-    }
-    bool isReady()
-    {
-        return !m_zooming && m_frontTileGrid->isReady() && m_scale > 0;
-    }
-
-    bool isDirty()
-    {
-        return m_frontTileGrid->isDirty();
-    }
-
-    bool isMissingContent()
-    {
-        return m_zooming || m_frontTileGrid->isMissingContent();
-    }
-
-    int nbTextures(IntRect& area, float scale)
-    {
-        // TODO: consider the zooming case for the backTileGrid
-        if (!m_frontTileGrid)
-            return 0;
-        return m_frontTileGrid->nbTextures(area, scale);
-    }
-
-private:
-    void swapTileGrids();
-
-    // Delay before we schedule a new tile at the new scale factor
-    static const double s_zoomUpdateDelay = 0.2; // 200 ms
-
-    TileGrid* m_frontTileGrid;
-    TileGrid* m_backTileGrid;
-    TileGrid* m_lowResTileGrid;
-
-    float m_scale;
-    float m_futureScale;
-    double m_zoomUpdateTime;
-    bool m_zooming;
-};
-
-} // namespace WebCore
-
-#endif // SurfaceBacking_h
diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp
deleted file mode 100644
index 1c769bf..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "SurfaceCollection"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "SurfaceCollection.h"
-
-#include "AndroidLog.h"
-#include "BaseLayerAndroid.h"
-#include "ClassTracker.h"
-#include "GLWebViewState.h"
-#include "PaintTileOperation.h"
-#include "Surface.h"
-#include "ScrollableLayerAndroid.h"
-#include "TilesManager.h"
-
-namespace WebCore {
-
-////////////////////////////////////////////////////////////////////////////////
-//                        TILED PAINTING / SURFACES                           //
-////////////////////////////////////////////////////////////////////////////////
-
-SurfaceCollection::SurfaceCollection(BaseLayerAndroid* layer)
-        : m_compositedRoot(layer)
-{
-    // layer must be non-null.
-    SkSafeRef(m_compositedRoot);
-
-    // calculate draw transforms and z values
-    SkRect visibleRect = SkRect::MakeLTRB(0, 0, 1, 1);
-    m_compositedRoot->updatePositionsRecursive(visibleRect);
-
-    // allocate surfaces for layers, merging where possible
-    ALOGV("new tree, allocating surfaces for tree %p", m_baseLayer);
-
-    LayerMergeState layerMergeState(&m_surfaces);
-    m_compositedRoot->assignSurfaces(&layerMergeState);
-
-    // set the layersurfaces' update count, to be drawn on painted tiles
-    unsigned int updateCount = TilesManager::instance()->incWebkitContentUpdates();
-    for (unsigned int i = 0; i < m_surfaces.size(); i++)
-        m_surfaces[i]->setUpdateCount(updateCount);
-
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->increment("SurfaceCollection");
-#endif
-}
-
-SurfaceCollection::~SurfaceCollection()
-{
-    SkSafeUnref(m_compositedRoot);
-    for (unsigned int i = 0; i < m_surfaces.size(); i++)
-        SkSafeUnref(m_surfaces[i]);
-    m_surfaces.clear();
-
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->decrement("SurfaceCollection");
-#endif
-}
-
-void SurfaceCollection::prepareGL(const SkRect& visibleContentRect, bool tryToFastBlit)
-{
-    TRACE_METHOD();
-    updateLayerPositions(visibleContentRect);
-    bool layerTilesDisabled = m_compositedRoot->state()->isSingleSurfaceRenderingMode();
-    if (!layerTilesDisabled) {
-        for (unsigned int i = 0; tryToFastBlit && i < m_surfaces.size(); i++)
-            tryToFastBlit &= m_surfaces[i]->canUpdateWithBlit();
-    }
-    for (unsigned int i = 0; i < m_surfaces.size(); i++)
-        m_surfaces[i]->prepareGL(layerTilesDisabled, tryToFastBlit);
-}
-
-static inline bool compareSurfaceZ(const Surface* a, const Surface* b)
-{
-    const LayerAndroid* la = a->getFirstLayer();
-    const LayerAndroid* lb = b->getFirstLayer();
-
-    // swap drawing order if zValue suggests it AND the layers are in the same stacking context
-    return (la->zValue() > lb->zValue()) && (la->getParent() == lb->getParent());
-}
-
-bool SurfaceCollection::drawGL(const SkRect& visibleContentRect)
-{
-    TRACE_METHOD();
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->show();
-#endif
-
-    bool needsRedraw = false;
-    updateLayerPositions(visibleContentRect);
-    bool layerTilesDisabled = m_compositedRoot->state()->isSingleSurfaceRenderingMode();
-
-    // create a duplicate vector of surfaces, sorted by z value
-    Vector <Surface*> surfaces;
-    for (unsigned int i = 0; i < m_surfaces.size(); i++)
-        surfaces.append(m_surfaces[i]);
-    std::stable_sort(surfaces.begin()+1, surfaces.end(), compareSurfaceZ);
-
-    // draw the sorted vector
-    for (unsigned int i = 0; i < m_surfaces.size(); i++)
-        needsRedraw |= surfaces[i]->drawGL(layerTilesDisabled);
-
-    return needsRedraw;
-}
-
-Color SurfaceCollection::getBackgroundColor()
-{
-    return static_cast<BaseLayerAndroid*>(m_compositedRoot)->getBackgroundColor();
-}
-
-void SurfaceCollection::swapTiles()
-{
-    bool calculateFrameworkInvals = !m_compositedRoot->state()->inUnclippedDraw();
-
-    TRACE_METHOD();
-    for (unsigned int i = 0; i < m_surfaces.size(); i++)
-         m_surfaces[i]->swapTiles(calculateFrameworkInvals);
-}
-
-void SurfaceCollection::addFrameworkInvals()
-{
-    for (unsigned int i = 0; i < m_surfaces.size(); i++)
-         m_surfaces[i]->addFrameworkInvals();
-}
-
-bool SurfaceCollection::isReady()
-{
-    // Override layer readiness check for single surface mode
-    if (m_compositedRoot->state()->isSingleSurfaceRenderingMode())
-        return m_surfaces[0]->isReady();
-
-    for (unsigned int i = 0; i < m_surfaces.size(); i++) {
-        if (!m_surfaces[i]->isReady()) {
-            ALOGV("layer surface %p isn't ready", m_surfaces[i]);
-            return false;
-        }
-    }
-    return true;
-}
-
-bool SurfaceCollection::isMissingBackgroundContent()
-{
-    // return true when the first surface is missing content (indicating the
-    // entire viewport isn't covered)
-    return m_surfaces[0]->isMissingContent();
-}
-
-void SurfaceCollection::removePainterOperations()
-{
-    for (unsigned int i = 0; i < m_surfaces.size(); i++)
-        TilesManager::instance()->removeOperationsForFilter(new TilePainterFilter(m_surfaces[i]));
-}
-
-void SurfaceCollection::computeTexturesAmount(TexturesResult* result)
-{
-    for (unsigned int i = 0; i < m_surfaces.size(); i++)
-        m_surfaces[i]->computeTexturesAmount(result);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//                  RECURSIVE ANIMATION / INVALS / LAYERS                     //
-////////////////////////////////////////////////////////////////////////////////
-
-void SurfaceCollection::setIsPainting(SurfaceCollection* drawingSurface)
-{
-    if (!drawingSurface)
-        return;
-
-    for (unsigned int i = 0; i < m_surfaces.size(); i++) {
-        Surface* newSurface = m_surfaces[i];
-        if (!newSurface->needsTexture())
-            continue;
-
-        for (unsigned int j = 0; j < drawingSurface->m_surfaces.size(); j++) {
-            Surface* oldSurface = drawingSurface->m_surfaces[j];
-            if (newSurface->tryUpdateSurface(oldSurface))
-                break;
-        }
-    }
-}
-
-void SurfaceCollection::setIsDrawing()
-{
-    m_compositedRoot->initAnimations();
-}
-
-void SurfaceCollection::mergeInvalsInto(SurfaceCollection* replacementSurface)
-{
-    m_compositedRoot->mergeInvalsInto(replacementSurface->m_compositedRoot);
-}
-
-bool SurfaceCollection::evaluateAnimations(double currentTime)
-{
-    return m_compositedRoot->evaluateAnimations(currentTime);
-}
-
-bool SurfaceCollection::hasCompositedLayers()
-{
-    return m_compositedRoot->countChildren();
-}
-
-bool SurfaceCollection::hasCompositedAnimations()
-{
-    return m_compositedRoot->hasAnimations();
-}
-
-void SurfaceCollection::updateScrollableLayer(int layerId, int x, int y)
-{
-    LayerAndroid* layer = m_compositedRoot->findById(layerId);
-    if (layer && layer->contentIsScrollable())
-        static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y);
-}
-
-void SurfaceCollection::updateLayerPositions(const SkRect& visibleContentRect)
-{
-    m_compositedRoot->updatePositionsRecursive(visibleContentRect);
-
-#ifdef DEBUG
-    m_compositedRoot->showLayer(0);
-    ALOGV("We have %d layers, %d textured",
-          m_compositedRoot->nbLayers(),
-          m_compositedRoot->nbTexturedLayers());
-#endif
-}
-
-int SurfaceCollection::backedSize()
-{
-    int count = 0;
-    for (unsigned int i = 0; i < m_surfaces.size(); i++) {
-        if (m_surfaces[i]->needsTexture())
-            count++;
-    }
-    return count;
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h
deleted file mode 100644
index a903015..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef SurfaceCollection_h
-#define SurfaceCollection_h
-
-#include "Color.h"
-#include "SkRect.h"
-#include "SkRefCnt.h"
-
-#include <wtf/Vector.h>
-
-class SkCanvas;
-class SkRegion;
-
-namespace WebCore {
-
-class BaseLayerAndroid;
-class Surface;
-class TexturesResult;
-
-class SurfaceCollection : public SkRefCnt {
-// TODO: investigate webkit threadsafe ref counting
-public:
-    SurfaceCollection(BaseLayerAndroid* compositedRoot);
-    virtual ~SurfaceCollection();
-
-    // Tiled painting methods (executed on Surfaces)
-    void prepareGL(const SkRect& visibleContentRect, bool tryToFastBlit = false);
-    bool drawGL(const SkRect& visibleContentRect);
-    Color getBackgroundColor();
-    void swapTiles();
-    void addFrameworkInvals();
-    bool isReady();
-    bool isMissingBackgroundContent();
-    void removePainterOperations();
-    void computeTexturesAmount(TexturesResult* result);
-
-    // Recursive tree methods (animations, invals, etc)
-    void setIsPainting(SurfaceCollection* drawingSurfaceCollection);
-    void setIsDrawing();
-    void mergeInvalsInto(SurfaceCollection* replacementSurfaceCollection);
-    bool evaluateAnimations(double currentTime);
-
-    bool hasCompositedLayers();
-    bool hasCompositedAnimations();
-    void updateScrollableLayer(int layerId, int x, int y);
-
-    int size() { return m_surfaces.size(); }
-    int backedSize();
-
-private:
-    void updateLayerPositions(const SkRect& visibleContentRect);
-    BaseLayerAndroid* const m_compositedRoot;
-    WTF::Vector<Surface*> m_surfaces;
-};
-
-} // namespace WebCore
-
-#endif //#define SurfaceCollection_h
diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp
deleted file mode 100644
index 174720f..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.cpp
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "SurfaceCollectionManager"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "SurfaceCollectionManager.h"
-
-#include "AndroidLog.h"
-#include "private/hwui/DrawGlInfo.h"
-#include "TilesManager.h"
-#include "SurfaceCollection.h"
-
-namespace WebCore {
-
-using namespace android::uirenderer;
-
-SurfaceCollectionManager::SurfaceCollectionManager()
-    : m_drawingCollection(0)
-    , m_paintingCollection(0)
-    , m_queuedCollection(0)
-    , m_fastSwapMode(false)
-    , m_previouslyScrolling(false)
-    , m_newPaintingCollection(false)
-{
-}
-
-SurfaceCollectionManager::~SurfaceCollectionManager()
-{
-    clearCollections();
-}
-
-// the painting collection has finished painting:
-//   discard the drawing collection
-//   swap the painting collection in place of the drawing collection
-//   and start painting the queued collection
-void SurfaceCollectionManager::swap()
-{
-    // swap can't be called unless painting just finished
-    ASSERT(m_paintingCollection);
-
-    ALOGV("SWAPPING, D %p, P %p, Q %p",
-          m_drawingCollection, m_paintingCollection, m_queuedCollection);
-
-    // if we have a drawing collection, discard it since the painting collection is done
-    if (m_drawingCollection) {
-        ALOGV("destroying drawing collection %p", m_drawingCollection);
-        m_drawingCollection->addFrameworkInvals();
-        m_drawingCollection->removePainterOperations();
-        SkSafeUnref(m_drawingCollection);
-    }
-
-    // painting collection becomes the drawing collection
-    ALOGV("drawing collection %p", m_paintingCollection);
-    m_paintingCollection->setIsDrawing(); // initialize animations
-    m_paintingCollection->addFrameworkInvals();
-
-    if (m_queuedCollection) {
-        // start painting with the queued collection
-        ALOGV("now painting collection %p", m_queuedCollection);
-        m_queuedCollection->setIsPainting(m_paintingCollection);
-    }
-    m_drawingCollection = m_paintingCollection;
-    m_paintingCollection = m_queuedCollection;
-    m_queuedCollection = 0;
-
-    ALOGV("SWAPPING COMPLETE, D %p, P %p, Q %p",
-         m_drawingCollection, m_paintingCollection, m_queuedCollection);
-}
-
-// clear all of the content in the three collections held by the collection manager
-void SurfaceCollectionManager::clearCollections()
-{
-    // remove all painting operations, since they're no longer relevant
-    if (m_drawingCollection)
-        m_drawingCollection->removePainterOperations();
-    if (m_paintingCollection)
-        m_paintingCollection->removePainterOperations();
-
-    SkSafeUnref(m_drawingCollection);
-    m_drawingCollection = 0;
-    SkSafeUnref(m_paintingCollection);
-    m_paintingCollection = 0;
-    SkSafeUnref(m_queuedCollection);
-    m_queuedCollection = 0;
-}
-
-void SurfaceCollectionManager::updatePaintingCollection(SurfaceCollection* newCollection)
-{
-    m_paintingCollection = newCollection;
-    m_paintingCollection->setIsPainting(m_drawingCollection);
-    m_newPaintingCollection = true;
-}
-
-// a new layer collection has arrived, queue it if we're painting something already,
-// or start painting it if we aren't. Returns true if the manager has two collections
-// already queued.
-bool SurfaceCollectionManager::updateWithSurfaceCollection(SurfaceCollection* newCollection,
-                                                           bool brandNew)
-{
-    // can't have a queued collection unless have a painting collection too
-    ASSERT(m_paintingCollection || !m_queuedCollection);
-
-    if (!newCollection || brandNew) {
-        clearCollections();
-        if (brandNew)
-            updatePaintingCollection(newCollection);
-        return false;
-    }
-
-    ALOGV("updateWithSurfaceCollection - %p, has children %d, has animations %d",
-          newCollection, newCollection->hasCompositedLayers(),
-          newCollection->hasCompositedAnimations());
-
-    if (m_queuedCollection || m_paintingCollection) {
-        // currently painting, so defer this new collection
-        if (m_queuedCollection) {
-            // already have a queued collection, copy over invals so the regions are
-            // eventually repainted and let the old queued collection be discarded
-            m_queuedCollection->mergeInvalsInto(newCollection);
-
-            if (!TilesManager::instance()->useDoubleBuffering()) {
-                // not double buffering, count discarded collection/webkit paint as an update
-                TilesManager::instance()->incContentUpdates();
-            }
-
-            ALOGV("DISCARDING collection - %p, has children %d, has animations %d",
-                  newCollection, newCollection->hasCompositedLayers(),
-                  newCollection->hasCompositedAnimations());
-        }
-        SkSafeUnref(m_queuedCollection);
-        m_queuedCollection = newCollection;
-    } else {
-        // don't have painting collection, paint this one!
-        updatePaintingCollection(newCollection);
-    }
-    return m_drawingCollection && TilesManager::instance()->useDoubleBuffering();
-}
-
-void SurfaceCollectionManager::updateScrollableLayer(int layerId, int x, int y)
-{
-    if (m_queuedCollection)
-        m_queuedCollection->updateScrollableLayer(layerId, x, y);
-    if (m_paintingCollection)
-        m_paintingCollection->updateScrollableLayer(layerId, x, y);
-    if (m_drawingCollection)
-        m_drawingCollection->updateScrollableLayer(layerId, x, y);
-}
-
-
-int SurfaceCollectionManager::singleSurfaceModeInvalidation(bool hasRunningAnimation,
-                                                            bool scrolling,
-                                                            bool shouldDraw)
-{
-    int returnFlags = 0;
-    // In single surface mode, we need to dirty all the tiles when we are finishing
-    // scrolling or have an incoming painting tree.
-    bool requireDirtyAll = (m_previouslyScrolling && !scrolling)
-                           || m_newPaintingCollection;
-
-    // We also need to tell the framework to continue to invoke until
-    // the base layer is ready.
-    bool drawingBaseSurfaceReady = m_drawingCollection
-                                   && m_drawingCollection->isReady();
-
-    // When the base layer is ready, we can ask the framework to draw. And if
-    // animation is running, dirty all the tiles, otherwise the animation will
-    // be paused.
-    if (drawingBaseSurfaceReady) {
-        if (!shouldDraw)
-            returnFlags |= DrawGlInfo::kStatusDraw;
-        else
-            requireDirtyAll |= hasRunningAnimation;
-    }
-    if (requireDirtyAll)
-        TilesManager::instance()->dirtyAllTiles();
-
-    bool requireInvoke = requireDirtyAll || !drawingBaseSurfaceReady;
-    if (requireInvoke)
-        returnFlags |= DrawGlInfo::kStatusInvoke;
-
-    m_newPaintingCollection = false;
-    m_previouslyScrolling = scrolling;
-
-    return returnFlags;
-}
-
-int SurfaceCollectionManager::drawGL(double currentTime, IntRect& viewRect,
-                            SkRect& visibleContentRect, float scale,
-                            bool scrolling, bool singleSurfaceMode,
-                            bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr,
-                            TexturesResult* texturesResultPtr, bool shouldDraw)
-{
-    m_fastSwapMode |= scrolling || singleSurfaceMode;
-
-    ALOGV("drawGL, D %p, P %p, Q %p, fastSwap %d shouldDraw %d",
-          m_drawingCollection, m_paintingCollection,
-          m_queuedCollection, m_fastSwapMode, shouldDraw);
-
-    // ask for kStatusInvoke while painting, kStatusDraw if we have content to be redrawn next frame
-    // returning 0 indicates all painting complete, no framework inval needed.
-    int returnFlags = 0;
-
-    bool didCollectionSwap = false;
-    if (m_paintingCollection) {
-        ALOGV("preparing painting collection %p", m_paintingCollection);
-
-        m_paintingCollection->evaluateAnimations(currentTime);
-
-        bool tryFastBlit = !m_fastSwapMode;
-        m_paintingCollection->prepareGL(visibleContentRect, tryFastBlit);
-        m_paintingCollection->computeTexturesAmount(texturesResultPtr);
-
-        if (!TilesManager::instance()->useDoubleBuffering() || m_paintingCollection->isReady()) {
-            ALOGV("have painting collection %p ready, swapping!", m_paintingCollection);
-            didCollectionSwap = true;
-            TilesManager::instance()->incContentUpdates();
-            if (collectionsSwappedPtr)
-                *collectionsSwappedPtr = true;
-            if (newCollectionHasAnimPtr)
-                *newCollectionHasAnimPtr = m_paintingCollection->hasCompositedAnimations();
-            swap();
-            returnFlags |= uirenderer::DrawGlInfo::kStatusDraw;
-        }
-    } else if (m_drawingCollection) {
-        ALOGV("preparing drawing collection %p", m_drawingCollection);
-        m_drawingCollection->prepareGL(visibleContentRect);
-        m_drawingCollection->computeTexturesAmount(texturesResultPtr);
-    }
-
-    if (m_paintingCollection)
-        returnFlags |= DrawGlInfo::kStatusInvoke;
-
-    if (!shouldDraw) {
-        if (didCollectionSwap
-            || (!m_paintingCollection
-                && m_drawingCollection
-                && m_drawingCollection->isReady())) {
-            // either a swap just occurred, or there is no more work to be done: do a full draw
-            m_drawingCollection->swapTiles();
-            returnFlags |= DrawGlInfo::kStatusDraw;
-        } else {
-            // current collection not ready - invoke functor in process mode
-            // until either drawing or painting collection is ready
-            returnFlags |= DrawGlInfo::kStatusInvoke;
-        }
-
-        return returnFlags;
-    }
-
-    // ===========================================================================
-    // Don't have a drawing collection, draw white background
-    Color background = Color::white;
-    bool drawBackground = true;
-    bool hasRunningAnimation = false;
-    if (m_drawingCollection) {
-        bool drawingReady = didCollectionSwap || m_drawingCollection->isReady();
-
-        // call the page swap callback if registration happened without more collections enqueued
-        if (collectionsSwappedPtr && drawingReady && !m_paintingCollection)
-            *collectionsSwappedPtr = true;
-
-        if (didCollectionSwap || m_fastSwapMode || (drawingReady && !m_paintingCollection))
-            m_drawingCollection->swapTiles();
-
-        if (drawingReady) {
-            // exit fast swap mode, as content is up to date
-            m_fastSwapMode = false;
-        } else {
-            // drawing isn't ready, must redraw
-            returnFlags |= DrawGlInfo::kStatusInvoke;
-        }
-
-        hasRunningAnimation = m_drawingCollection->evaluateAnimations(currentTime);
-
-        ALOGV("drawing collection %p", m_drawingCollection);
-        background = m_drawingCollection->getBackgroundColor();
-        drawBackground = m_drawingCollection->isMissingBackgroundContent();
-    } else if (m_paintingCollection) {
-        // Use paintingCollection background color while tiles are not done painting.
-        background = m_paintingCollection->getBackgroundColor();
-    }
-
-    if (singleSurfaceMode)
-        returnFlags |= singleSurfaceModeInvalidation(hasRunningAnimation,
-                                                     scrolling, shouldDraw);
-    // Start doing the actual GL drawing.
-    if (drawBackground) {
-        ALOGV("background is %x", background.rgb());
-        // If background is opaque, we can safely and efficiently clear it here.
-        // Otherwise, we have to calculate all the missing tiles and blend the background.
-        GLUtils::clearBackgroundIfOpaque(&background);
-    }
-
-#ifdef DEBUG
-    ALOGV("Drawing %d / %d surfaces",
-        m_drawingCollection ? m_drawingCollection->backedSize() : -1,
-        m_drawingCollection ? m_drawingCollection->size() : -1);
-#endif
-
-    if (m_drawingCollection && m_drawingCollection->drawGL(visibleContentRect))
-        returnFlags |= DrawGlInfo::kStatusDraw;
-
-    ALOGV("returnFlags %d,  m_paintingCollection %d ", returnFlags, m_paintingCollection);
-    return returnFlags;
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.h b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.h
deleted file mode 100644
index 53b5bb6..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollectionManager.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef SurfaceCollectionManager_h
-#define SurfaceCollectionManager_h
-
-#include "TestExport.h"
-#include <utils/threads.h>
-
-class SkRect;
-class SkCanvas;
-
-namespace WebCore {
-
-class GLWebViewState;
-class IntRect;
-class TexturesResult;
-class SurfaceCollection;
-
-class TEST_EXPORT SurfaceCollectionManager {
-public:
-    SurfaceCollectionManager();
-
-    ~SurfaceCollectionManager();
-
-    bool updateWithSurfaceCollection(SurfaceCollection* collection, bool brandNew);
-
-    void updateScrollableLayer(int layerId, int x, int y);
-
-    int drawGL(double currentTime, IntRect& viewRect,
-                SkRect& visibleContentRect, float scale,
-                bool scrolling, bool singleSurfaceMode,
-                bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr,
-                TexturesResult* texturesResultPtr, bool shouldDraw);
-
-private:
-    void swap();
-    void clearCollections();
-    void updatePaintingCollection(SurfaceCollection* newCollection);
-    int singleSurfaceModeInvalidation(bool hasRunningAnimation, bool scrolling, bool shouldDraw);
-    SurfaceCollection* m_drawingCollection;
-    SurfaceCollection* m_paintingCollection;
-    SurfaceCollection* m_queuedCollection;
-
-    bool m_fastSwapMode;
-    // Used in single surface mode only. True if the previous frame is scrolling.
-    bool m_previouslyScrolling;
-    // Used in single surface mode only. True if there is a new painting tree
-    // added for the current frame.
-    bool m_newPaintingCollection;
-};
-
-} // namespace WebCore
-
-#endif //#define SurfaceCollectionManager_h
diff --git a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp b/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp
deleted file mode 100644
index cc94c9c..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/TexturesGenerator.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "TexturesGenerator"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "TexturesGenerator.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "AndroidLog.h"
-#include "GLUtils.h"
-#include "PaintTileOperation.h"
-#include "TilesManager.h"
-#include "TransferQueue.h"
-
-namespace WebCore {
-
-bool TexturesGenerator::tryUpdateOperationWithPainter(Tile* tile, TilePainter* painter)
-{
-    android::Mutex::Autolock lock(mRequestedOperationsLock);
-    if (!mRequestedOperationsHash.contains(tile))
-        return false;
-
-    static_cast<PaintTileOperation*>(mRequestedOperationsHash.get(tile))->updatePainter(painter);
-    return true;
-}
-
-void TexturesGenerator::scheduleOperation(QueuedOperation* operation)
-{
-    bool signal = false;
-    {
-        android::Mutex::Autolock lock(mRequestedOperationsLock);
-        mRequestedOperations.append(operation);
-        mRequestedOperationsHash.set(operation->uniquePtr(), operation);
-
-        bool deferrable = operation->priority() >= gDeferPriorityCutoff;
-        m_deferredMode &= deferrable;
-
-        // signal if we weren't in deferred mode, or if we can no longer defer
-        signal = !m_deferredMode || !deferrable;
-    }
-    if (signal)
-        mRequestedOperationsCond.signal();
-}
-
-void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter)
-{
-    if (!filter)
-        return;
-
-    android::Mutex::Autolock lock(mRequestedOperationsLock);
-    for (unsigned int i = 0; i < mRequestedOperations.size();) {
-        QueuedOperation* operation = mRequestedOperations[i];
-        if (filter->check(operation)) {
-            mRequestedOperations.remove(i);
-            mRequestedOperationsHash.remove(operation->uniquePtr());
-            delete operation;
-        } else {
-            i++;
-        }
-    }
-    delete filter;
-}
-
-status_t TexturesGenerator::readyToRun()
-{
-    ALOGV("Thread ready to run");
-    return NO_ERROR;
-}
-
-// Must be called from within a lock!
-QueuedOperation* TexturesGenerator::popNext()
-{
-    // Priority can change between when it was added and now
-    // Hence why the entire queue is rescanned
-    QueuedOperation* current = mRequestedOperations.last();
-    int currentPriority = current->priority();
-    if (currentPriority < 0) {
-        mRequestedOperations.removeLast();
-        mRequestedOperationsHash.remove(current->uniquePtr());
-        return current;
-    }
-    int currentIndex = mRequestedOperations.size() - 1;
-    // Scan from the back to make removing faster (less items to copy)
-    for (int i = mRequestedOperations.size() - 2; i >= 0; i--) {
-        QueuedOperation *next = mRequestedOperations[i];
-        int nextPriority = next->priority();
-        if (nextPriority < 0) {
-            // Found a very high priority item, go ahead and just handle it now
-            mRequestedOperations.remove(i);
-            mRequestedOperationsHash.remove(next->uniquePtr());
-            return next;
-        }
-        // pick items preferrably by priority, or if equal, by order of
-        // insertion (as we add items at the back of the queue)
-        if (nextPriority <= currentPriority) {
-            current = next;
-            currentPriority = nextPriority;
-            currentIndex = i;
-        }
-    }
-
-    if (!m_deferredMode && currentPriority >= gDeferPriorityCutoff) {
-        // finished with non-deferred rendering, enter deferred mode to wait
-        m_deferredMode = true;
-        return 0;
-    }
-
-    mRequestedOperations.remove(currentIndex);
-    mRequestedOperationsHash.remove(current->uniquePtr());
-    return current;
-}
-
-bool TexturesGenerator::threadLoop()
-{
-    // Check if we have any pending operations.
-    mRequestedOperationsLock.lock();
-
-    if (!m_deferredMode) {
-        // if we aren't currently deferring work, wait for new work to arrive
-        while (!mRequestedOperations.size())
-            mRequestedOperationsCond.wait(mRequestedOperationsLock);
-    } else {
-        // if we only have deferred work, wait for better work, or a timeout
-        mRequestedOperationsCond.waitRelative(mRequestedOperationsLock, gDeferNsecs);
-    }
-
-    mRequestedOperationsLock.unlock();
-
-    bool stop = false;
-    while (!stop) {
-        QueuedOperation* currentOperation = 0;
-
-        mRequestedOperationsLock.lock();
-        ALOGV("threadLoop, %d operations in the queue", mRequestedOperations.size());
-
-        if (mRequestedOperations.size())
-            currentOperation = popNext();
-        mRequestedOperationsLock.unlock();
-
-        if (currentOperation) {
-            ALOGV("threadLoop, painting the request with priority %d",
-                  currentOperation->priority());
-            currentOperation->run();
-        }
-
-        mRequestedOperationsLock.lock();
-        if (m_deferredMode && !currentOperation)
-            stop = true;
-        if (!mRequestedOperations.size()) {
-            m_deferredMode = false;
-            stop = true;
-        }
-        mRequestedOperationsLock.unlock();
-
-        if (currentOperation)
-            delete currentOperation; // delete outside lock
-    }
-    ALOGV("threadLoop empty");
-
-    return true;
-}
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/rendering/Tile.cpp b/Source/WebCore/platform/graphics/android/rendering/Tile.cpp
deleted file mode 100644
index 96b189a..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/Tile.cpp
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "Tile"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "Tile.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "AndroidLog.h"
-#include "GLUtils.h"
-#include "RasterRenderer.h"
-#include "TextureInfo.h"
-#include "TileTexture.h"
-#include "TilesManager.h"
-
-// If the dirty portion of a tile exceeds this ratio, fully repaint.
-// Lower values give fewer partial repaints, thus fewer front-to-back
-// texture copies (cost will vary by device). It's a tradeoff between
-// the rasterization cost and the FBO texture recopy cost when using
-// GPU for the transfer queue.
-#define MAX_INVAL_AREA 0.6
-
-namespace WebCore {
-
-Tile::Tile(bool isLayerTile)
-    : m_x(-1)
-    , m_y(-1)
-    , m_frontTexture(0)
-    , m_backTexture(0)
-    , m_lastDrawnTexture(0)
-    , m_scale(1)
-    , m_dirty(true)
-    , m_repaintsPending(0)
-    , m_fullRepaint(true)
-    , m_isLayerTile(isLayerTile)
-    , m_drawCount(0)
-    , m_state(Unpainted)
-{
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->increment("Tile");
-#endif
-    m_renderer = BaseRenderer::createRenderer();
-}
-
-Tile::~Tile()
-{
-    if (m_backTexture)
-        m_backTexture->release(this);
-    if (m_frontTexture)
-        m_frontTexture->release(this);
-
-    delete m_renderer;
-
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->decrement("Tile");
-#endif
-}
-
-// All the following functions must be called from the main GL thread.
-
-void Tile::setContents(int x, int y, float scale, bool isExpandedPrefetchTile)
-{
-    // TODO: investigate whether below check/discard is necessary
-    if ((m_x != x)
-        || (m_y != y)
-        || (m_scale != scale)) {
-        // neither texture is relevant
-        discardTextures();
-    }
-
-    android::AutoMutex lock(m_atomicSync);
-    m_x = x;
-    m_y = y;
-    m_scale = scale;
-    m_drawCount = TilesManager::instance()->getDrawGLCount();
-    if (isExpandedPrefetchTile)
-        m_drawCount--; // deprioritize expanded painting region
-}
-
-void Tile::reserveTexture()
-{
-    TileTexture* texture = TilesManager::instance()->getAvailableTexture(this);
-
-    android::AutoMutex lock(m_atomicSync);
-    if (texture && m_backTexture != texture) {
-        ALOGV("tile %p reserving texture %p, back was %p (front %p)",
-              this, texture, m_backTexture, m_frontTexture);
-        m_state = Unpainted;
-        m_backTexture = texture;
-    }
-
-    if (m_state == UpToDate) {
-        ALOGV("moving tile %p to unpainted, since it reserved while up to date", this);
-        m_dirty = true;
-        m_state = Unpainted;
-    }
-}
-
-bool Tile::removeTexture(TileTexture* texture)
-{
-    ALOGV("%p removeTexture %p, back %p front %p",
-          this, texture, m_backTexture, m_frontTexture);
-    // We update atomically, so paintBitmap() can see the correct value
-    android::AutoMutex lock(m_atomicSync);
-    if (m_frontTexture == texture) {
-        if (m_state == UpToDate) {
-            ALOGV("front texture removed, state was UpToDate, now becoming unpainted, bt is %p", m_backTexture);
-            m_state = Unpainted;
-        }
-
-        m_frontTexture = 0;
-    }
-    if (m_backTexture == texture) {
-        m_state = Unpainted;
-        m_backTexture = 0;
-    }
-
-    // mark dirty regardless of which texture was taken - the back texture may
-    // have been ready to swap
-    m_dirty = true;
-
-    return true;
-}
-
-void Tile::markAsDirty()
-{
-    android::AutoMutex lock(m_atomicSync);
-    m_dirtyArea.setEmpty(); // empty dirty rect prevents fast blit path
-    markAsDirtyInternal();
-}
-
-void Tile::markAsDirty(const SkRegion& dirtyArea)
-{
-    if (dirtyArea.isEmpty())
-        return;
-    android::AutoMutex lock(m_atomicSync);
-    m_dirtyArea.op(dirtyArea, SkRegion::kUnion_Op);
-
-    // Check if we actually intersect with the area
-    bool intersect = false;
-    SkRegion::Iterator cliperator(dirtyArea);
-    SkRect realTileRect;
-    SkRect dirtyRect;
-    while (!cliperator.done()) {
-        dirtyRect.set(cliperator.rect());
-        if (intersectWithRect(m_x, m_y, TilesManager::tileWidth(), TilesManager::tileHeight(),
-                              m_scale, dirtyRect, realTileRect)) {
-            intersect = true;
-            break;
-        }
-        cliperator.next();
-    }
-
-    if (!intersect)
-        return;
-
-    markAsDirtyInternal();
-}
-
-void Tile::markAsDirtyInternal()
-{
-    // NOTE: callers must hold lock on m_atomicSync
-
-    m_dirty = true;
-    if (m_state == UpToDate) {
-        // We only mark a tile as unpainted in 'markAsDirty' if its status is
-        // UpToDate: marking dirty means we need to repaint, but don't stop the
-        // current paint
-        m_state = Unpainted;
-    } else if (m_state != Unpainted) {
-        // TODO: fix it so that they can paint while deferring the markAsDirty
-        // call (or block updates)
-        ALOGV("Warning: tried to mark tile %p at %d, %d islayertile %d as dirty, state %d",
-              this, m_x, m_y, isLayerTile(), m_state);
-
-        // prefetch tiles can be marked dirty while in the process of painting,
-        // due to not using an update lock. force them to fail validate step.
-        m_state = Unpainted;
-    }
-}
-
-bool Tile::isDirty()
-{
-    android::AutoMutex lock(m_atomicSync);
-    return m_dirty;
-}
-
-bool Tile::isRepaintPending()
-{
-    android::AutoMutex lock(m_atomicSync);
-    return m_repaintsPending != 0;
-}
-
-void Tile::setRepaintPending(bool pending)
-{
-    android::AutoMutex lock(m_atomicSync);
-    m_repaintsPending += pending ? 1 : -1;
-}
-
-bool Tile::drawGL(float opacity, const SkRect& rect, float scale,
-                  const TransformationMatrix* transform,
-                  bool forceBlending, bool usePointSampling,
-                  const FloatRect& fillPortion)
-{
-    if (m_x < 0 || m_y < 0 || m_scale != scale)
-        return false;
-
-    // No need to mutex protect reads of m_backTexture as it is only written to by
-    // the consumer thread.
-    if (!m_frontTexture)
-        return false;
-
-    if (fillPortion.maxX() < 1.0f || fillPortion.maxY() < 1.0f
-        || fillPortion.x() > 0.0f || fillPortion.y() > 0.0f)
-        ALOGV("drawing tile %p (%d, %d with fill portions %f %f->%f, %f",
-              this, m_x, m_y, fillPortion.x(), fillPortion.y(),
-              fillPortion.maxX(), fillPortion.maxY());
-
-    m_frontTexture->drawGL(isLayerTile(), rect, opacity, transform,
-                           forceBlending, usePointSampling, fillPortion);
-    m_lastDrawnTexture = m_frontTexture;
-    return true;
-}
-
-bool Tile::isTileReady()
-{
-    // Return true if the tile's most recently drawn texture is up to date
-    android::AutoMutex lock(m_atomicSync);
-    TileTexture * texture = (m_state == ReadyToSwap) ? m_backTexture : m_frontTexture;
-
-    if (!texture)
-        return false;
-
-    if (texture->owner() != this)
-        return false;
-
-    if (m_dirty)
-        return false;
-
-    if (m_state != ReadyToSwap && m_state != UpToDate)
-        return false;
-
-    return true;
-}
-
-bool Tile::intersectWithRect(int x, int y, int tileWidth, int tileHeight,
-                             float scale, const SkRect& dirtyRect,
-                             SkRect& realTileRect)
-{
-    // compute the rect to corresponds to pixels
-    realTileRect.fLeft = x * tileWidth;
-    realTileRect.fTop = y * tileHeight;
-    realTileRect.fRight = realTileRect.fLeft + tileWidth;
-    realTileRect.fBottom = realTileRect.fTop + tileHeight;
-
-    // scale the dirtyRect for intersect computation.
-    SkRect realDirtyRect = SkRect::MakeWH(dirtyRect.width() * scale,
-                                          dirtyRect.height() * scale);
-    realDirtyRect.offset(dirtyRect.fLeft * scale, dirtyRect.fTop * scale);
-
-    if (!realTileRect.intersect(realDirtyRect))
-        return false;
-    return true;
-}
-
-bool Tile::isTileVisible(const IntRect& viewTileBounds)
-{
-    return (m_x >= viewTileBounds.x()
-            && m_x < viewTileBounds.x() + viewTileBounds.width()
-            && m_y >= viewTileBounds.y()
-            && m_y < viewTileBounds.y() + viewTileBounds.height());
-}
-
-// This is called from the texture generation thread
-void Tile::paintBitmap(TilePainter* painter)
-{
-    // We acquire the values below atomically. This ensures that we are reading
-    // values correctly across cores. Further, once we have these values they
-    // can be updated by other threads without consequence.
-    m_atomicSync.lock();
-    bool dirty = m_dirty;
-    TileTexture* texture = m_backTexture;
-    SkRegion dirtyArea = m_dirtyArea;
-    float scale = m_scale;
-    const int x = m_x;
-    const int y = m_y;
-
-    if (!dirty || !texture) {
-        m_atomicSync.unlock();
-        return;
-    }
-    if (m_state != Unpainted) {
-        ALOGV("Warning: started painting tile %p, but was at state %d, ft %p bt %p",
-              this, m_state, m_frontTexture, m_backTexture);
-    }
-    m_state = PaintingStarted;
-    TextureInfo* textureInfo = texture->getTextureInfo();
-    m_atomicSync.unlock();
-
-    // at this point we can safely check the ownership (if the texture got
-    // transferred to another Tile under us)
-    if (texture->owner() != this) {
-        return;
-    }
-
-    // swap out the renderer if necessary
-    BaseRenderer::swapRendererIfNeeded(m_renderer);
-    // setup the common renderInfo fields;
-    TileRenderInfo renderInfo;
-    renderInfo.x = x;
-    renderInfo.y = y;
-    renderInfo.scale = scale;
-    renderInfo.tileSize = texture->getSize();
-    renderInfo.tilePainter = painter;
-    renderInfo.baseTile = this;
-    renderInfo.textureInfo = textureInfo;
-
-    const float tileWidth = renderInfo.tileSize.width();
-    const float tileHeight = renderInfo.tileSize.height();
-
-    m_renderer->renderTiledContent(renderInfo);
-
-    m_atomicSync.lock();
-
-    if (texture == m_backTexture) {
-        // set the fullrepaint flags
-        m_fullRepaint = false;
-
-        // The various checks to see if we are still dirty...
-
-        m_dirty = false;
-
-        if (m_scale != scale)
-            m_dirty = true;
-
-        m_dirtyArea.setEmpty();
-
-        ALOGV("painted tile %p (%d, %d), texture %p, dirty=%d", this, x, y, texture, m_dirty);
-
-        validatePaint();
-    } else {
-        ALOGV("tile %p no longer owns texture %p, m_state %d. ft %p bt %p",
-              this, texture, m_state, m_frontTexture, m_backTexture);
-    }
-
-    m_atomicSync.unlock();
-}
-
-void Tile::discardTextures() {
-    android::AutoMutex lock(m_atomicSync);
-    ALOGV("%p discarding bt %p, ft %p",
-          this, m_backTexture, m_frontTexture);
-    if (m_frontTexture) {
-        m_frontTexture->release(this);
-        m_frontTexture = 0;
-    }
-    if (m_backTexture) {
-        m_backTexture->release(this);
-        m_backTexture = 0;
-    }
-    m_dirtyArea.setEmpty();
-    m_fullRepaint = true;
-
-    m_dirty = true;
-    m_state = Unpainted;
-}
-
-void Tile::discardBackTexture() {
-    android::AutoMutex lock(m_atomicSync);
-    if (m_backTexture) {
-        m_backTexture->release(this);
-        m_backTexture = 0;
-    }
-    m_state = Unpainted;
-    m_dirty = true;
-}
-
-bool Tile::swapTexturesIfNeeded() {
-    android::AutoMutex lock(m_atomicSync);
-    if (m_state == ReadyToSwap) {
-        // discard old texture and swap the new one in its place
-        if (m_frontTexture)
-            m_frontTexture->release(this);
-
-        m_frontTexture = m_backTexture;
-        m_backTexture = 0;
-        m_state = UpToDate;
-        ALOGV("display texture for %p at %d, %d front is now %p, back is %p",
-              this, m_x, m_y, m_frontTexture, m_backTexture);
-
-        return true;
-    }
-    return false;
-}
-
-void Tile::backTextureTransfer() {
-    android::AutoMutex lock(m_atomicSync);
-    if (m_state == PaintingStarted)
-        m_state = TransferredUnvalidated;
-    else if (m_state == ValidatedUntransferred)
-        m_state = ReadyToSwap;
-    else {
-        // shouldn't have transferred a tile in any other state, log
-        ALOGV("Note: transferred tile %p at %d %d, state wasn't paintingstarted or validated: %d",
-              this, m_x, m_y, m_state);
-    }
-}
-
-void Tile::backTextureTransferFail() {
-    // transfer failed for some reason, mark dirty so it will (repaint and) be
-    // retransferred.
-    android::AutoMutex lock(m_atomicSync);
-    m_state = Unpainted;
-    m_dirty = true;
-    // whether validatePaint is called before or after, it won't do anything
-}
-
-void Tile::onBlitUpdate()
-{
-    // The front texture was directly updated with a blit, so mark this as clean
-    android::AutoMutex lock(m_atomicSync);
-    m_dirty = false;
-    m_dirtyArea.setEmpty();
-    m_state = Tile::UpToDate;
-}
-
-void Tile::validatePaint() {
-    // ONLY CALL while m_atomicSync is locked (at the end of paintBitmap())
-
-    if (!m_dirty) {
-        // since after the paint, the tile isn't dirty, 'validate' it - this
-        // may happed before or after the transfer queue operation. Only
-        // when both have happened, mark as 'ReadyToSwap'
-        if (m_state == PaintingStarted)
-            m_state = ValidatedUntransferred;
-        else if (m_state == TransferredUnvalidated) {
-            // When the backTexture has been marked pureColor, we will skip the
-            // transfer and marked as ReadyToSwap, in this case, we don't want
-            // to reset m_dirty bit to true.
-            m_state = ReadyToSwap;
-        } else {
-            ALOGV("Note: validated tile %p at %d %d, state wasn't paintingstarted or transferred %d",
-                  this, m_x, m_y, m_state);
-            // failed transferring, in which case mark dirty (since
-            // paintBitmap() may have cleared m_dirty)
-            m_dirty = true;
-        }
-    } else {
-        ALOGV("Note: paint was unsuccessful.");
-        m_state = Unpainted;
-    }
-
-}
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/rendering/TileGrid.cpp b/Source/WebCore/platform/graphics/android/rendering/TileGrid.cpp
deleted file mode 100644
index 3d63f09..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/TileGrid.cpp
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "TileGrid"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "TileGrid.h"
-
-#include "AndroidLog.h"
-#include "DrawQuadData.h"
-#include "GLWebViewState.h"
-#include "PaintTileOperation.h"
-#include "Tile.h"
-#include "TileTexture.h"
-#include "TilesManager.h"
-
-#include <wtf/CurrentTime.h>
-
-#define EXPANDED_BOUNDS_INFLATE 1
-#define EXPANDED_PREFETCH_BOUNDS_Y_INFLATE 1
-
-namespace WebCore {
-
-TileGrid::TileGrid(bool isBaseSurface)
-    : m_prevTileY(0)
-    , m_scale(1)
-    , m_isBaseSurface(isBaseSurface)
-{
-    m_dirtyRegion.setEmpty();
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->increment("TileGrid");
-#endif
-}
-
-TileGrid::~TileGrid()
-{
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->decrement("TileGrid");
-#endif
-    removeTiles();
-}
-
-bool TileGrid::isReady()
-{
-    bool tilesAllReady = true;
-    bool tilesVisible = false;
-    for (unsigned int i = 0; i < m_tiles.size(); i++) {
-        Tile* tile = m_tiles[i];
-        if (tile->isTileVisible(m_area)) {
-            tilesVisible = true;
-            if (!tile->isTileReady()) {
-                tilesAllReady = false;
-                break;
-            }
-        }
-    }
-    // For now, if no textures are available, consider ourselves as ready
-    // in order to unblock the zooming process.
-    // FIXME: have a better system -- maybe keeping the last scale factor
-    // able to fully render everything
-    ALOGV("TG %p, ready %d, visible %d, texturesRemain %d",
-          this, tilesAllReady, tilesVisible,
-          TilesManager::instance()->layerTexturesRemain());
-
-    return !TilesManager::instance()->layerTexturesRemain()
-            || !tilesVisible || tilesAllReady;
-}
-
-bool TileGrid::isMissingContent()
-{
-    for (unsigned int i = 0; i < m_tiles.size(); i++)
-        if (m_tiles[i]->isTileVisible(m_area) && !m_tiles[i]->frontTexture())
-            return true;
-    return false;
-}
-
-bool TileGrid::swapTiles()
-{
-    int swaps = 0;
-    for (unsigned int i = 0; i < m_tiles.size(); i++)
-        if (m_tiles[i]->swapTexturesIfNeeded())
-            swaps++;
-    ALOGV("TG %p swapping, swaps = %d", this, swaps);
-    return swaps != 0;
-}
-
-IntRect TileGrid::computeTilesArea(const IntRect& contentArea, float scale)
-{
-    IntRect computedArea;
-    IntRect area(contentArea.x() * scale,
-                 contentArea.y() * scale,
-                 ceilf(contentArea.width() * scale),
-                 ceilf(contentArea.height() * scale));
-
-    ALOGV("TG prepare, scale %f, area %d x %d", scale, area.width(), area.height());
-
-    if (area.width() == 0 && area.height() == 0) {
-        computedArea.setWidth(0);
-        computedArea.setHeight(0);
-        return computedArea;
-    }
-
-    int tileWidth = TilesManager::tileWidth();
-    int tileHeight = TilesManager::tileHeight();
-
-    computedArea.setX(area.x() / tileWidth);
-    computedArea.setY(area.y() / tileHeight);
-    float right = (area.x() + area.width()) / (float) tileWidth;
-    float bottom = (area.y() + area.height()) / (float) tileHeight;
-    computedArea.setWidth(ceilf(right) - computedArea.x());
-    computedArea.setHeight(ceilf(bottom) - computedArea.y());
-    return computedArea;
-}
-
-void TileGrid::prepareGL(GLWebViewState* state, float scale,
-                         const IntRect& prepareArea, const IntRect& fullContentArea,
-                         TilePainter* painter, int regionFlags, bool isLowResPrefetch,
-                         bool updateWithBlit)
-{
-    // first, how many tiles do we need
-    m_area = computeTilesArea(prepareArea, scale);
-    if (m_area.isEmpty())
-        return;
-
-    ALOGV("prepare TileGrid %p with scale %.2f, prepareArea "
-          " %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles",
-          this, scale,
-          prepareArea.x(), prepareArea.y(),
-          prepareArea.width(), prepareArea.height(),
-          m_area.x(), m_area.y(),
-          m_area.width(), m_area.height());
-
-    bool goingDown = m_prevTileY < m_area.y();
-    m_prevTileY = m_area.y();
-
-    TilesManager* tilesManager = TilesManager::instance();
-    if (scale != m_scale)
-        tilesManager->removeOperationsForFilter(new ScaleFilter(painter, m_scale));
-
-    m_scale = scale;
-
-    // apply dirty region to affected tiles
-    if (!m_dirtyRegion.isEmpty()) {
-        for (unsigned int i = 0; i < m_tiles.size(); i++)
-            m_tiles[i]->markAsDirty(m_dirtyRegion);
-
-        // log inval region for the base surface
-        if (m_isBaseSurface && tilesManager->getProfiler()->enabled()) {
-            SkRegion::Iterator iterator(m_dirtyRegion);
-            while (!iterator.done()) {
-                SkIRect r = iterator.rect();
-                tilesManager->getProfiler()->nextInval(r, scale);
-                iterator.next();
-            }
-        }
-        m_dirtyRegion.setEmpty();
-    }
-
-    if (regionFlags & StandardRegion) {
-        for (int i = 0; i < m_area.width(); i++) {
-            if (goingDown) {
-                for (int j = 0; j < m_area.height(); j++)
-                    prepareTile(m_area.x() + i, m_area.y() + j,
-                                painter, state, isLowResPrefetch, false, updateWithBlit);
-            } else {
-                for (int j = m_area.height() - 1; j >= 0; j--)
-                    prepareTile(m_area.x() + i, m_area.y() + j,
-                                painter, state, isLowResPrefetch, false, updateWithBlit);
-            }
-        }
-    }
-
-    if (regionFlags & ExpandedRegion) {
-        IntRect fullArea = computeTilesArea(fullContentArea, scale);
-        IntRect expandedArea = m_area;
-
-        // on systems reporting highEndGfx=true and useMinimalMemory not set, use expanded bounds
-        if (tilesManager->highEndGfx() && !tilesManager->useMinimalMemory())
-            expandedArea.inflate(EXPANDED_BOUNDS_INFLATE);
-
-        if (isLowResPrefetch)
-            expandedArea.inflateY(EXPANDED_PREFETCH_BOUNDS_Y_INFLATE);
-
-        // clip painting area to content
-        expandedArea.intersect(fullArea);
-
-        for (int i = expandedArea.x(); i < expandedArea.maxX(); i++)
-            for (int j = expandedArea.y(); j < expandedArea.maxY(); j++)
-                if (!m_area.contains(i, j))
-                    prepareTile(i, j, painter, state, isLowResPrefetch, true, updateWithBlit);
-    }
-}
-
-void TileGrid::markAsDirty(const SkRegion& invalRegion)
-{
-    ALOGV("TG %p markAsDirty, current region empty %d, new empty %d",
-          this, m_dirtyRegion.isEmpty(), invalRegion.isEmpty());
-    m_dirtyRegion.op(invalRegion, SkRegion::kUnion_Op);
-}
-
-void TileGrid::prepareTile(int x, int y, TilePainter* painter,
-                           GLWebViewState* state, bool isLowResPrefetch,
-                           bool isExpandPrefetch, bool shouldTryUpdateWithBlit)
-{
-    Tile* tile = getTile(x, y);
-    if (!tile) {
-        bool isLayerTile = !m_isBaseSurface;
-        tile = new Tile(isLayerTile);
-        m_tiles.append(tile);
-    }
-
-    ALOGV("preparing tile %p at %d, %d, painter is %p", tile, x, y, painter);
-
-    tile->setContents(x, y, m_scale, isExpandPrefetch);
-
-    if (shouldTryUpdateWithBlit && tryBlitFromContents(tile, painter))
-        return;
-
-    if (tile->isDirty() || !tile->frontTexture())
-        tile->reserveTexture();
-
-    if (tile->backTexture() && tile->isDirty()) {
-        TilesManager* tilesManager = TilesManager::instance();
-
-        // if a scheduled repaint is still outstanding, update it with the new painter
-        if (tile->isRepaintPending() && tilesManager->tryUpdateOperationWithPainter(tile, painter))
-            return;
-
-        ALOGV("painting TG %p's tile %d %d for LG %p, scale %f", this, x, y, painter, m_scale);
-        PaintTileOperation *operation = new PaintTileOperation(tile, painter,
-                                                               state, isLowResPrefetch);
-        tilesManager->scheduleOperation(operation);
-    }
-}
-
-bool TileGrid::tryBlitFromContents(Tile* tile, TilePainter* painter)
-{
-    return tile->frontTexture()
-           && !tile->frontTexture()->isPureColor()
-           && tile->frontTexture()->m_ownTextureId
-           && !tile->isRepaintPending()
-           && painter->blitFromContents(tile);
-}
-
-Tile* TileGrid::getTile(int x, int y)
-{
-    for (unsigned int i = 0; i <m_tiles.size(); i++) {
-        Tile* tile = m_tiles[i];
-        if (tile->x() == x && tile->y() == y)
-            return tile;
-    }
-    return 0;
-}
-
-unsigned int TileGrid::getImageTextureId()
-{
-    if (m_tiles.size() == 1) {
-        if (m_tiles[0]->frontTexture())
-            return m_tiles[0]->frontTexture()->m_ownTextureId;
-    }
-    return 0;
-}
-
-int TileGrid::nbTextures(const IntRect& area, float scale)
-{
-    IntRect tileBounds = computeTilesArea(area, scale);
-    int numberTextures = tileBounds.width() * tileBounds.height();
-
-    // add the number of dirty tiles in the bounds, as they take up double
-    // textures for double buffering
-    for (unsigned int i = 0; i <m_tiles.size(); i++) {
-        Tile* tile = m_tiles[i];
-        if (tile->isDirty()
-                && tile->x() >= tileBounds.x() && tile->x() <= tileBounds.maxX()
-                && tile->y() >= tileBounds.y() && tile->y() <= tileBounds.maxY())
-            numberTextures++;
-    }
-    return numberTextures;
-}
-
-void TileGrid::drawGL(const IntRect& visibleContentArea, float opacity,
-                      const TransformationMatrix* transform,
-                      const Color* background)
-{
-    m_area = computeTilesArea(visibleContentArea, m_scale);
-    if (m_area.width() == 0 || m_area.height() == 0)
-        return;
-
-    float invScale = 1.0 / m_scale;
-    const float tileWidth = TilesManager::tileWidth() * invScale;
-    const float tileHeight = TilesManager::tileHeight() * invScale;
-
-    int drawn = 0;
-
-    SkRegion missingRegion;
-    bool semiOpaqueBaseSurface =
-        background ? (background->hasAlpha() && background->alpha() > 0) : false;
-    if (semiOpaqueBaseSurface) {
-        SkIRect totalArea = SkIRect::MakeXYWH(m_area.x(), m_area.y(),
-                                              m_area.width(), m_area.height());
-        missingRegion = SkRegion(totalArea);
-    }
-
-    bool usePointSampling =
-        TilesManager::instance()->shader()->usePointSampling(m_scale, transform);
-
-    float minTileX =  visibleContentArea.x() / tileWidth;
-    float minTileY =  visibleContentArea.y() / tileWidth;
-    float maxTileWidth = visibleContentArea.maxX() / tileWidth;
-    float maxTileHeight = visibleContentArea.maxY() / tileWidth;
-    ALOGV("minTileX, minTileY, maxTileWidth, maxTileHeight %f, %f, %f %f",
-          minTileX, minTileY, maxTileWidth, maxTileHeight);
-    for (unsigned int i = 0; i < m_tiles.size(); i++) {
-        Tile* tile = m_tiles[i];
-
-        bool tileInView = tile->isTileVisible(m_area);
-        if (tileInView) {
-            SkRect rect;
-            rect.fLeft = tile->x() * tileWidth;
-            rect.fTop = tile->y() * tileHeight;
-            rect.fRight = rect.fLeft + tileWidth;
-            rect.fBottom = rect.fTop + tileHeight;
-            ALOGV("tile %p (layer tile: %d) %d,%d at scale %.2f vs %.2f [ready: %d] dirty: %d",
-                  tile, tile->isLayerTile(), tile->x(), tile->y(),
-                  tile->scale(), m_scale, tile->isTileReady(), tile->isDirty());
-
-            bool forceBaseBlending = background ? background->hasAlpha() : false;
-
-            float left = std::max(minTileX - tile->x(), 0.0f);
-            float top = std::max(minTileY - tile->y(), 0.0f);
-            float right = std::min(maxTileWidth - tile->x(), 1.0f);
-            float bottom = std::min(maxTileHeight - tile->y(), 1.0f);
-            if (left > 1.0f || top > 1.0f || right < 0.0f || bottom < 0.0f) {
-                ALOGE("Unexpected portion:left, top, right, bottom %f %f %f %f",
-                      left, top, right, bottom);
-                left = 0.0f;
-                top = 0.0f;
-                right = 1.0f;
-                bottom = 1.0f;
-            }
-            FloatRect fillPortion(left, top, right - left, bottom - top);
-
-            bool success = tile->drawGL(opacity, rect, m_scale, transform,
-                                        forceBaseBlending, usePointSampling, fillPortion);
-            if (semiOpaqueBaseSurface && success) {
-                // Cut the successful drawn tile area from the missing region.
-                missingRegion.op(SkIRect::MakeXYWH(tile->x(), tile->y(), 1, 1),
-                                 SkRegion::kDifference_Op);
-            }
-            if (tile->frontTexture())
-                drawn++;
-        }
-
-        // log tile information for base, high res tiles
-        if (m_isBaseSurface && background)
-            TilesManager::instance()->getProfiler()->nextTile(tile, invScale, tileInView);
-    }
-
-    // Draw missing Regions with blend turned on
-    if (semiOpaqueBaseSurface)
-        drawMissingRegion(missingRegion, opacity, background);
-
-    ALOGV("TG %p drew %d tiles, scale %f",
-          this, drawn, m_scale);
-}
-
-void TileGrid::drawMissingRegion(const SkRegion& region, float opacity,
-                                     const Color* background)
-{
-    SkRegion::Iterator iterator(region);
-    const float tileWidth = TilesManager::tileWidth() / m_scale;
-    const float tileHeight = TilesManager::tileHeight() / m_scale;
-    while (!iterator.done()) {
-        SkIRect r = iterator.rect();
-        SkRect rect;
-        rect.fLeft = r.x() * tileWidth;
-        rect.fTop =  r.y() * tileHeight;
-        rect.fRight = rect.fLeft + tileWidth * r.width();
-        rect.fBottom = rect.fTop + tileHeight * r.height();
-        ALOGV("draw tile x y, %d %d (%d %d) opacity %f", r.x(), r.y(),
-              r.width(), r.height(), opacity);
-        // Skia is using pre-multiplied color.
-        Color postAlpha = Color(background->red() * background->alpha() / 255,
-                                background->green() * background->alpha() / 255,
-                                background->blue() * background->alpha() / 255,
-                                background->alpha() );
-
-        PureColorQuadData backGroundData(postAlpha, BaseQuad, 0, &rect, opacity);
-        TilesManager::instance()->shader()->drawQuad(&backGroundData);
-        iterator.next();
-    }
-}
-
-void TileGrid::removeTiles()
-{
-    for (unsigned int i = 0; i < m_tiles.size(); i++) {
-        delete m_tiles[i];
-    }
-    m_tiles.clear();
-}
-
-void TileGrid::discardTextures()
-{
-    ALOGV("TG %p discarding textures", this);
-    for (unsigned int i = 0; i < m_tiles.size(); i++)
-        m_tiles[i]->discardTextures();
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/TileGrid.h b/Source/WebCore/platform/graphics/android/rendering/TileGrid.h
deleted file mode 100644
index 35e4072..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/TileGrid.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TileGrid_h
-#define TileGrid_h
-
-#include "IntRect.h"
-#include "SkRegion.h"
-
-#include <wtf/Vector.h>
-
-namespace WebCore {
-
-class Color;
-class GLWebViewState;
-class Tile;
-class TilePainter;
-class TransformationMatrix;
-
-class TileGrid {
-public:
-    enum PrepareRegionFlags { EmptyRegion = 0x0, StandardRegion = 0x1, ExpandedRegion = 0x2 };
-
-    TileGrid(bool isBaseSurface);
-    virtual ~TileGrid();
-
-    static IntRect computeTilesArea(const IntRect& contentArea, float scale);
-
-    void prepareGL(GLWebViewState* state, float scale,
-                   const IntRect& prepareArea, const IntRect& fullContentArea,
-                   TilePainter* painter, int regionFlags = StandardRegion,
-                   bool isLowResPrefetch = false, bool updateWithBlit = false);
-    bool swapTiles();
-    void drawGL(const IntRect& visibleContentArea, float opacity,
-                const TransformationMatrix* transform, const Color* background = 0);
-
-    void markAsDirty(const SkRegion& dirtyArea);
-
-    Tile* getTile(int x, int y);
-
-    void removeTiles();
-    void discardTextures();
-
-    bool isReady();
-    bool isMissingContent();
-    bool isDirty() { return !m_dirtyRegion.isEmpty(); }
-
-    int nbTextures(const IntRect& area, float scale);
-    unsigned int getImageTextureId();
-
-private:
-    void prepareTile(int x, int y, TilePainter* painter,
-                     GLWebViewState* state, bool isLowResPrefetch,
-                     bool isExpandPrefetch, bool shouldTryUpdateWithBlit);
-    void drawMissingRegion(const SkRegion& region, float opacity, const Color* tileBackground);
-    bool tryBlitFromContents(Tile* tile, TilePainter* painter);
-
-    WTF::Vector<Tile*> m_tiles;
-
-    IntRect m_area;
-
-    SkRegion m_dirtyRegion;
-
-    int m_prevTileY;
-    float m_scale;
-
-    bool m_isBaseSurface;
-};
-
-} // namespace WebCore
-
-#endif // TileGrid_h
diff --git a/Source/WebCore/platform/graphics/android/rendering/TileTexture.cpp b/Source/WebCore/platform/graphics/android/rendering/TileTexture.cpp
deleted file mode 100644
index be4b4db..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/TileTexture.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "TileTexture"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "TileTexture.h"
-
-#include "AndroidLog.h"
-#include "Tile.h"
-#include "ClassTracker.h"
-#include "DrawQuadData.h"
-#include "GLUtils.h"
-#include "GLWebViewState.h"
-#include "TextureOwner.h"
-#include "TilesManager.h"
-
-namespace WebCore {
-
-TileTexture::TileTexture(uint32_t w, uint32_t h)
-    : m_owner(0)
-    , m_isPureColor(false)
-{
-    m_size.set(w, h);
-    m_ownTextureId = 0;
-
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->increment("TileTexture");
-#endif
-}
-
-TileTexture::~TileTexture()
-{
-#ifdef DEBUG_COUNT
-    ClassTracker::instance()->decrement("TileTexture");
-#endif
-}
-
-void TileTexture::requireGLTexture()
-{
-    if (!m_ownTextureId)
-        m_ownTextureId = GLUtils::createTileGLTexture(m_size.width(), m_size.height());
-}
-
-void TileTexture::discardGLTexture()
-{
-    if (m_ownTextureId)
-        GLUtils::deleteTexture(&m_ownTextureId);
-
-    if (m_owner) {
-        // clear both Tile->Texture and Texture->Tile links
-        m_owner->removeTexture(this);
-        release(m_owner);
-    }
-}
-
-bool TileTexture::acquire(TextureOwner* owner)
-{
-    if (m_owner == owner)
-        return true;
-
-    return setOwner(owner);
-}
-
-bool TileTexture::setOwner(TextureOwner* owner)
-{
-    bool proceed = true;
-    if (m_owner && m_owner != owner)
-        proceed = m_owner->removeTexture(this);
-
-    if (proceed) {
-        m_owner = owner;
-        return true;
-    }
-
-    return false;
-}
-
-bool TileTexture::release(TextureOwner* owner)
-{
-    ALOGV("texture %p releasing tile %p, m_owner %p", this, owner, m_owner);
-    if (m_owner != owner)
-        return false;
-
-    m_owner = 0;
-    return true;
-}
-
-void TileTexture::transferComplete()
-{
-    if (m_owner) {
-        Tile* owner = static_cast<Tile*>(m_owner);
-        owner->backTextureTransfer();
-    } else
-        ALOGE("ERROR: owner missing after transfer of texture %p", this);
-}
-
-void TileTexture::drawGL(bool isLayer, const SkRect& rect, float opacity,
-                         const TransformationMatrix* transform,
-                         bool forceBlending, bool usePointSampling,
-                         const FloatRect& fillPortion)
-{
-    ShaderProgram* shader = TilesManager::instance()->shader();
-
-    if (isLayer && !transform) {
-        ALOGE("ERROR: Missing tranform for layers!");
-        return;
-    }
-
-    // For base layer, we just follow the forceBlending, otherwise, blending is
-    // always turned on.
-    // TODO: Don't blend tiles if they are fully opaque.
-    bool useBlending = forceBlending || isLayer;
-    DrawQuadData commonData(isLayer ? LayerQuad : BaseQuad, transform, &rect,
-                            opacity, useBlending, fillPortion);
-    if (isPureColor()) {
-        PureColorQuadData data(commonData, pureColor());
-        shader->drawQuad(&data);
-    } else {
-        GLint filter = usePointSampling ? GL_NEAREST : GL_LINEAR;
-        TextureQuadData data(commonData, m_ownTextureId, GL_TEXTURE_2D, filter);
-        shader->drawQuad(&data);
-    }
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/TileTexture.h b/Source/WebCore/platform/graphics/android/rendering/TileTexture.h
deleted file mode 100644
index e31da5b..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/TileTexture.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TileTexture_h
-#define TileTexture_h
-
-#include "Color.h"
-#include "FloatRect.h"
-#include "SkBitmap.h"
-#include "SkRect.h"
-#include "SkSize.h"
-#include "TextureInfo.h"
-
-#include <GLES2/gl2.h>
-
-class SkCanvas;
-
-namespace WebCore {
-
-class TextureOwner;
-class Tile;
-class TransformationMatrix;
-
-class TileTexture {
-public:
-    // This object is to be constructed on the consumer's thread and must have
-    // a width and height greater than 0.
-    TileTexture(uint32_t w, uint32_t h);
-    virtual ~TileTexture();
-
-    // allows consumer thread to assign ownership of the texture to the tile. It
-    // returns false if ownership cannot be transferred because the tile is busy
-    bool acquire(TextureOwner* owner);
-    bool release(TextureOwner* owner);
-
-    // set the texture owner if not busy. Return false if busy, true otherwise.
-    bool setOwner(TextureOwner* owner);
-
-    // private member accessor functions
-    TextureOwner* owner() { return m_owner; } // only used by the consumer thread
-
-    const SkSize& getSize() const { return m_size; }
-
-    // OpenGL ID of backing texture, 0 when not allocated
-    GLuint m_ownTextureId;
-    // these are used for dynamically (de)allocating backing graphics memory
-    void requireGLTexture();
-    void discardGLTexture();
-
-    void transferComplete();
-
-    TextureInfo* getTextureInfo() { return &m_ownTextureInfo; }
-
-    // Make sure the following pureColor getter/setter are only read/written
-    // in UI thread. Therefore no need for a lock.
-    void setPure(bool pure) { m_isPureColor = pure; }
-    bool isPureColor() {return m_isPureColor; }
-    void setPureColor(const Color& color) { m_pureColor = color; setPure(true); }
-    Color pureColor() { return m_pureColor; }
-
-    void drawGL(bool isLayer, const SkRect& rect, float opacity,
-                const TransformationMatrix* transform, bool forceBlending, bool usePointSampling,
-                const FloatRect& fillPortion);
-private:
-    TextureInfo m_ownTextureInfo;
-    SkSize m_size;
-
-    // Tile owning the texture, only modified by UI thread
-    TextureOwner* m_owner;
-
-    // When the whole tile is single color, skip the transfer queue and draw
-    // it directly through shader.
-    bool m_isPureColor;
-    Color m_pureColor;
-};
-
-} // namespace WebCore
-
-#endif // TileTexture_h
diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp
deleted file mode 100644
index 0b4ba7b..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp
+++ /dev/null
@@ -1,514 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "TilesManager"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "TilesManager.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "AndroidLog.h"
-#include "GLWebViewState.h"
-#include "SkCanvas.h"
-#include "SkDevice.h"
-#include "SkPaint.h"
-#include "Tile.h"
-#include "TileTexture.h"
-#include "TransferQueue.h"
-
-#include <android/native_window.h>
-#include <cutils/atomic.h>
-#include <gui/SurfaceTexture.h>
-#include <gui/SurfaceTextureClient.h>
-#include <wtf/CurrentTime.h>
-
-// Important: We need at least twice as many textures as is needed to cover
-// one viewport, otherwise the allocation may stall.
-// We need n textures for one TiledPage, and another n textures for the
-// second page used when scaling.
-// In our case, we use 256*256 textures. Both base and layers can use up to
-// MAX_TEXTURE_ALLOCATION textures, which is 224MB GPU memory in total.
-// For low end graphics systems, we cut this upper limit to half.
-// We've found the viewport dependent value m_currentTextureCount is a reasonable
-// number to cap the layer tile texturs, it worked on both phones and tablets.
-// TODO: after merge the pool of base tiles and layer tiles, we should revisit
-// the logic of allocation management.
-#define MAX_TEXTURE_ALLOCATION ((6+TILE_PREFETCH_DISTANCE*2)*(5+TILE_PREFETCH_DISTANCE*2)*4)
-#define TILE_WIDTH 256
-#define TILE_HEIGHT 256
-
-#define BYTES_PER_PIXEL 4 // 8888 config
-
-#define LAYER_TEXTURES_DESTROY_TIMEOUT 60 // If we do not need layers for 60 seconds, free the textures
-
-namespace WebCore {
-
-int TilesManager::getMaxTextureAllocation()
-{
-    if (m_maxTextureAllocation == -1) {
-        GLint glMaxTextureSize = 0;
-        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTextureSize);
-        GLUtils::checkGlError("TilesManager::getMaxTextureAllocation");
-        // Half of glMaxTextureSize can be used for base, the other half for layers.
-        m_maxTextureAllocation = std::min(MAX_TEXTURE_ALLOCATION, glMaxTextureSize / 2);
-        if (!m_highEndGfx)
-            m_maxTextureAllocation = m_maxTextureAllocation / 2;
-    }
-    return m_maxTextureAllocation;
-}
-
-TilesManager::TilesManager()
-    : m_layerTexturesRemain(true)
-    , m_highEndGfx(false)
-    , m_currentTextureCount(0)
-    , m_currentLayerTextureCount(0)
-    , m_maxTextureAllocation(-1)
-    , m_generatorReady(false)
-    , m_showVisualIndicator(false)
-    , m_invertedScreen(false)
-    , m_useMinimalMemory(true)
-    , m_useDoubleBuffering(true)
-    , m_contentUpdates(0)
-    , m_webkitContentUpdates(0)
-    , m_queue(0)
-    , m_drawGLCount(1)
-    , m_lastTimeLayersUsed(0)
-    , m_hasLayerTextures(false)
-    , m_eglContext(EGL_NO_CONTEXT)
-{
-    ALOGV("TilesManager ctor");
-    m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
-    m_availableTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
-    m_tilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
-    m_availableTilesTextures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
-    m_pixmapsGenerationThread = new TexturesGenerator(this);
-    m_pixmapsGenerationThread->run("TexturesGenerator");
-}
-
-void TilesManager::allocateTextures()
-{
-    int nbTexturesToAllocate = m_currentTextureCount - m_textures.size();
-    ALOGV("%d tiles to allocate (%d textures planned)", nbTexturesToAllocate, m_currentTextureCount);
-    int nbTexturesAllocated = 0;
-    for (int i = 0; i < nbTexturesToAllocate; i++) {
-        TileTexture* texture = new TileTexture(
-            tileWidth(), tileHeight());
-        // the atomic load ensures that the texture has been fully initialized
-        // before we pass a pointer for other threads to operate on
-        TileTexture* loadedTexture =
-            reinterpret_cast<TileTexture*>(
-            android_atomic_acquire_load(reinterpret_cast<int32_t*>(&texture)));
-        m_textures.append(loadedTexture);
-        nbTexturesAllocated++;
-    }
-
-    int nbLayersTexturesToAllocate = m_currentLayerTextureCount - m_tilesTextures.size();
-    ALOGV("%d layers tiles to allocate (%d textures planned)",
-          nbLayersTexturesToAllocate, m_currentLayerTextureCount);
-    int nbLayersTexturesAllocated = 0;
-    for (int i = 0; i < nbLayersTexturesToAllocate; i++) {
-        TileTexture* texture = new TileTexture(
-            tileWidth(), tileHeight());
-        // the atomic load ensures that the texture has been fully initialized
-        // before we pass a pointer for other threads to operate on
-        TileTexture* loadedTexture =
-            reinterpret_cast<TileTexture*>(
-            android_atomic_acquire_load(reinterpret_cast<int32_t*>(&texture)));
-        m_tilesTextures.append(loadedTexture);
-        nbLayersTexturesAllocated++;
-    }
-    ALOGV("allocated %d textures for base (total: %d, %d Mb), %d textures for layers (total: %d, %d Mb)",
-          nbTexturesAllocated, m_textures.size(),
-          m_textures.size() * TILE_WIDTH * TILE_HEIGHT * 4 / 1024 / 1024,
-          nbLayersTexturesAllocated, m_tilesTextures.size(),
-          m_tilesTextures.size() * tileWidth() * tileHeight() * 4 / 1024 / 1024);
-}
-
-void TilesManager::discardTextures(bool allTextures, bool glTextures)
-{
-    const unsigned int max = m_textures.size();
-
-    unsigned long long sparedDrawCount = ~0; // by default, spare no textures
-    if (!allTextures) {
-        // if we're not deallocating all textures, spare those with max drawcount
-        sparedDrawCount = 0;
-        for (unsigned int i = 0; i < max; i++) {
-            TextureOwner* owner = m_textures[i]->owner();
-            if (owner)
-                sparedDrawCount = std::max(sparedDrawCount, owner->drawCount());
-        }
-    }
-    discardTexturesVector(sparedDrawCount, m_textures, glTextures);
-    discardTexturesVector(sparedDrawCount, m_tilesTextures, glTextures);
-}
-
-void TilesManager::markAllGLTexturesZero()
-{
-    for (unsigned int i = 0; i < m_textures.size(); i++)
-        m_textures[i]->m_ownTextureId = 0;
-    for (unsigned int i = 0; i < m_tilesTextures.size(); i++)
-        m_tilesTextures[i]->m_ownTextureId = 0;
-}
-
-void TilesManager::discardTexturesVector(unsigned long long sparedDrawCount,
-                                         WTF::Vector<TileTexture*>& textures,
-                                         bool deallocateGLTextures)
-{
-    const unsigned int max = textures.size();
-    int dealloc = 0;
-    WTF::Vector<int> discardedIndex;
-    for (unsigned int i = 0; i < max; i++) {
-        TextureOwner* owner = textures[i]->owner();
-        if (!owner || owner->drawCount() < sparedDrawCount) {
-            if (deallocateGLTextures) {
-                // deallocate textures' gl memory
-                textures[i]->discardGLTexture();
-                discardedIndex.append(i);
-            } else if (owner) {
-                // simply detach textures from owner
-                static_cast<Tile*>(owner)->discardTextures();
-            }
-            dealloc++;
-        }
-    }
-
-    bool base = textures == m_textures;
-    // Clean up the vector of TileTextures and reset the max texture count.
-    if (discardedIndex.size()) {
-        android::Mutex::Autolock lock(m_texturesLock);
-        for (int i = discardedIndex.size() - 1; i >= 0; i--)
-            textures.remove(discardedIndex[i]);
-
-        int remainedTextureNumber = textures.size();
-        int* countPtr = base ? &m_currentTextureCount : &m_currentLayerTextureCount;
-        if (remainedTextureNumber < *countPtr) {
-            ALOGV("reset currentTextureCount for %s tiles from %d to %d",
-                  base ? "base" : "layer", *countPtr, remainedTextureNumber);
-            *countPtr = remainedTextureNumber;
-        }
-
-    }
-
-    ALOGV("Discarded %d %s textures (out of %d %s tiles)",
-          dealloc, (deallocateGLTextures ? "gl" : ""),
-          max, base ? "base" : "layer");
-}
-
-void TilesManager::gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextures,
-                                        int* nbLayerTextures, int* nbAllocatedLayerTextures)
-{
-    *nbTextures = m_textures.size();
-    for (unsigned int i = 0; i < m_textures.size(); i++) {
-        TileTexture* texture = m_textures[i];
-        if (texture->m_ownTextureId)
-            *nbAllocatedTextures += 1;
-    }
-    *nbLayerTextures = m_tilesTextures.size();
-    for (unsigned int i = 0; i < m_tilesTextures.size(); i++) {
-        TileTexture* texture = m_tilesTextures[i];
-        if (texture->m_ownTextureId)
-            *nbAllocatedLayerTextures += 1;
-    }
-}
-
-void TilesManager::dirtyTexturesVector(WTF::Vector<TileTexture*>& textures)
-{
-    for (unsigned int i = 0; i < textures.size(); i++) {
-        Tile* currentOwner = static_cast<Tile*>(textures[i]->owner());
-        if (currentOwner)
-            currentOwner->markAsDirty();
-    }
-}
-
-void TilesManager::dirtyAllTiles()
-{
-    dirtyTexturesVector(m_textures);
-    dirtyTexturesVector(m_tilesTextures);
-}
-
-void TilesManager::printTextures()
-{
-#ifdef DEBUG
-    ALOGV("++++++");
-    for (unsigned int i = 0; i < m_textures.size(); i++) {
-        TileTexture* texture = m_textures[i];
-        Tile* o = 0;
-        if (texture->owner())
-            o = (Tile*) texture->owner();
-        int x = -1;
-        int y = -1;
-        if (o) {
-            x = o->x();
-            y = o->y();
-        }
-        ALOGV("[%d] texture %x owner: %x (%d, %d) scale: %.2f",
-              i, texture, o, x, y, o ? o->scale() : 0);
-    }
-    ALOGV("------");
-#endif // DEBUG
-}
-
-void TilesManager::gatherTextures()
-{
-    android::Mutex::Autolock lock(m_texturesLock);
-    m_availableTextures = m_textures;
-    m_availableTilesTextures = m_tilesTextures;
-    m_layerTexturesRemain = true;
-}
-
-TileTexture* TilesManager::getAvailableTexture(Tile* owner)
-{
-    android::Mutex::Autolock lock(m_texturesLock);
-
-    WTF::Vector<TileTexture*>* availableTexturePool;
-    if (owner->isLayerTile())
-        availableTexturePool = &m_availableTilesTextures;
-    else
-        availableTexturePool = &m_availableTextures;
-
-    // Sanity check that the tile does not already own a texture
-    if (owner->backTexture() && owner->backTexture()->owner() == owner) {
-        int removeIndex = availableTexturePool->find(owner->backTexture());
-
-        // TODO: investigate why texture isn't found
-        if (removeIndex >= 0)
-            availableTexturePool->remove(removeIndex);
-        return owner->backTexture();
-    }
-
-    // The heuristic for selecting a texture is as follows:
-    //  1. Skip textures currently being painted, they can't be painted while
-    //         busy anyway
-    //  2. If a tile isn't owned, break with that one
-    //  3. Don't let tiles acquire their front textures
-    //  4. Otherwise, use the least recently prepared tile, but ignoring tiles
-    //         drawn in the last frame to avoid flickering
-
-    TileTexture* farthestTexture = 0;
-    unsigned long long oldestDrawCount = getDrawGLCount() - 1;
-    const unsigned int max = availableTexturePool->size();
-    for (unsigned int i = 0; i < max; i++) {
-        TileTexture* texture = (*availableTexturePool)[i];
-        Tile* currentOwner = static_cast<Tile*>(texture->owner());
-        if (!currentOwner) {
-            // unused texture! take it!
-            farthestTexture = texture;
-            break;
-        }
-
-        if (currentOwner == owner) {
-            // Don't let a tile acquire its own front texture, as the
-            // acquisition logic doesn't handle that
-            continue;
-        }
-
-        unsigned long long textureDrawCount = currentOwner->drawCount();
-        if (oldestDrawCount > textureDrawCount) {
-            farthestTexture = texture;
-            oldestDrawCount = textureDrawCount;
-        }
-    }
-
-    if (farthestTexture) {
-        Tile* previousOwner = static_cast<Tile*>(farthestTexture->owner());
-        if (farthestTexture->acquire(owner)) {
-            if (previousOwner) {
-                previousOwner->removeTexture(farthestTexture);
-
-                ALOGV("%s texture %p stolen from tile %d, %d for %d, %d, drawCount was %llu (now %llu)",
-                      owner->isLayerTile() ? "LAYER" : "BASE",
-                      farthestTexture, previousOwner->x(), previousOwner->y(),
-                      owner->x(), owner->y(),
-                      oldestDrawCount, getDrawGLCount());
-            }
-
-            availableTexturePool->remove(availableTexturePool->find(farthestTexture));
-            return farthestTexture;
-        }
-    } else {
-        if (owner->isLayerTile()) {
-            // couldn't find a tile for a layer, layers shouldn't request redraw
-            // TODO: once we do layer prefetching, don't set this for those
-            // tiles
-            m_layerTexturesRemain = false;
-        }
-    }
-
-    ALOGV("Couldn't find an available texture for %s tile %x (%d, %d) out of %d available",
-          owner->isLayerTile() ? "LAYER" : "BASE",
-          owner, owner->x(), owner->y(), max);
-#ifdef DEBUG
-    printTextures();
-#endif // DEBUG
-    return 0;
-}
-
-void TilesManager::setHighEndGfx(bool highEnd)
-{
-    m_highEndGfx = highEnd;
-}
-
-bool TilesManager::highEndGfx()
-{
-    return m_highEndGfx;
-}
-
-int TilesManager::currentTextureCount()
-{
-    android::Mutex::Autolock lock(m_texturesLock);
-    return m_currentTextureCount;
-}
-
-int TilesManager::currentLayerTextureCount()
-{
-    android::Mutex::Autolock lock(m_texturesLock);
-    return m_currentLayerTextureCount;
-}
-
-void TilesManager::setCurrentTextureCount(int newTextureCount)
-{
-    int maxTextureAllocation = getMaxTextureAllocation();
-    ALOGV("setCurrentTextureCount: %d (current: %d, max:%d)",
-         newTextureCount, m_currentTextureCount, maxTextureAllocation);
-    if (m_currentTextureCount == maxTextureAllocation ||
-        newTextureCount <= m_currentTextureCount)
-        return;
-
-    android::Mutex::Autolock lock(m_texturesLock);
-    m_currentTextureCount = std::min(newTextureCount, maxTextureAllocation);
-
-    allocateTextures();
-}
-
-void TilesManager::setCurrentLayerTextureCount(int newTextureCount)
-{
-    int maxTextureAllocation = getMaxTextureAllocation();
-    ALOGV("setCurrentLayerTextureCount: %d (current: %d, max:%d)",
-         newTextureCount, m_currentLayerTextureCount, maxTextureAllocation);
-    if (!newTextureCount && m_hasLayerTextures) {
-        double secondsSinceLayersUsed = WTF::currentTime() - m_lastTimeLayersUsed;
-        if (secondsSinceLayersUsed > LAYER_TEXTURES_DESTROY_TIMEOUT) {
-            unsigned long long sparedDrawCount = ~0; // by default, spare no textures
-            bool deleteGLTextures = true;
-            discardTexturesVector(sparedDrawCount, m_tilesTextures, deleteGLTextures);
-            m_hasLayerTextures = false;
-        }
-        return;
-    }
-    m_lastTimeLayersUsed = WTF::currentTime();
-    if (m_currentLayerTextureCount == maxTextureAllocation ||
-        newTextureCount <= m_currentLayerTextureCount)
-        return;
-
-    android::Mutex::Autolock lock(m_texturesLock);
-    m_currentLayerTextureCount = std::min(newTextureCount, maxTextureAllocation);
-
-    allocateTextures();
-    m_hasLayerTextures = true;
-}
-
-TransferQueue* TilesManager::transferQueue()
-{
-    // m_queue will be created on the UI thread, although it may
-    // be accessed from the TexturesGenerator. However, that can only happen after
-    // a previous transferQueue() call due to a prepare.
-    if (!m_queue)
-        m_queue = new TransferQueue(m_useMinimalMemory);
-    return m_queue;
-}
-
-// When GL context changed or we get a low memory signal, we want to cleanup all
-// the GPU memory webview is using.
-// The recreation will be on the next incoming draw call at the drawGL of
-// GLWebViewState or the VideoLayerAndroid
-void TilesManager::cleanupGLResources()
-{
-    transferQueue()->cleanupGLResourcesAndQueue();
-    shader()->cleanupGLResources();
-    videoLayerManager()->cleanupGLResources();
-    m_eglContext = EGL_NO_CONTEXT;
-    GLUtils::checkGlError("TilesManager::cleanupGLResources");
-}
-
-void TilesManager::updateTilesIfContextVerified()
-{
-    EGLContext ctx = eglGetCurrentContext();
-    GLUtils::checkEglError("contextChanged");
-    if (ctx != m_eglContext) {
-        if (m_eglContext != EGL_NO_CONTEXT) {
-            // A change in EGL context is an unexpected error, but we don't want to
-            // crash or ANR. Therefore, abandon the Surface Texture and GL resources;
-            // they'll be recreated later in setupDrawing. (We can't delete them
-            // since the context is gone)
-            ALOGE("Unexpected : EGLContext changed! current %x , expected %x",
-                  ctx, m_eglContext);
-            transferQueue()->resetQueue();
-            shader()->forceNeedsInit();
-            videoLayerManager()->forceNeedsInit();
-            markAllGLTexturesZero();
-        } else {
-            // This is the first time we went into this new EGL context.
-            // We will have the GL resources to be re-inited and we can't update
-            // dirty tiles yet.
-            ALOGD("new EGLContext from framework: %x ", ctx);
-        }
-    } else {
-        // Here before we draw, update the Tile which has updated content.
-        // Inside this function, just do GPU blits from the transfer queue into
-        // the Tiles' texture.
-        transferQueue()->updateDirtyTiles();
-        // Clean up GL textures for video layer.
-        videoLayerManager()->deleteUnusedTextures();
-    }
-    m_eglContext = ctx;
-    return;
-}
-
-int TilesManager::tileWidth()
-{
-    return TILE_WIDTH;
-}
-
-int TilesManager::tileHeight()
-{
-    return TILE_HEIGHT;
-}
-
-TilesManager* TilesManager::instance()
-{
-    if (!gInstance) {
-        gInstance = new TilesManager();
-        ALOGV("instance(), new gInstance is %x", gInstance);
-    }
-    return gInstance;
-}
-
-TilesManager* TilesManager::gInstance = 0;
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp
deleted file mode 100644
index f37afa4..0000000
--- a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp
+++ /dev/null
@@ -1,599 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "TransferQueue"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "TransferQueue.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#include "AndroidLog.h"
-#include "DrawQuadData.h"
-#include "GLUtils.h"
-#include "Tile.h"
-#include "TileTexture.h"
-#include "TilesManager.h"
-#include <android/native_window.h>
-#include <gui/SurfaceTexture.h>
-#include <gui/SurfaceTextureClient.h>
-
-// For simple webView usage, MINIMAL_SIZE is recommended for memory saving.
-// In browser case, EFFICIENT_SIZE is preferred.
-#define MINIMAL_SIZE 1
-#define EFFICIENT_SIZE 6
-
-// Set this to 1 if we would like to take the new GpuUpload approach which
-// relied on the glCopyTexSubImage2D instead of a glDraw call
-#define GPU_UPLOAD_WITHOUT_DRAW 1
-
-namespace WebCore {
-
-TransferQueue::TransferQueue(bool useMinimalMem)
-    : m_eglSurface(EGL_NO_SURFACE)
-    , m_transferQueueIndex(0)
-    , m_fboID(0)
-    , m_sharedSurfaceTextureId(0)
-    , m_hasGLContext(true)
-    , m_currentDisplay(EGL_NO_DISPLAY)
-    , m_currentUploadType(DEFAULT_UPLOAD_TYPE)
-{
-    memset(&m_GLStateBeforeBlit, 0, sizeof(m_GLStateBeforeBlit));
-    m_transferQueueSize = useMinimalMem ? MINIMAL_SIZE : EFFICIENT_SIZE;
-    m_emptyItemCount = m_transferQueueSize;
-    m_transferQueue = new TileTransferData[m_transferQueueSize];
-}
-
-TransferQueue::~TransferQueue()
-{
-    android::Mutex::Autolock lock(m_transferQueueItemLocks);
-    cleanupGLResources();
-    delete[] m_transferQueue;
-}
-
-// Set the queue to be totally empty, abandon the Surface Texture. This should
-// be called only when we hit a wrong EGL Context in an error situation.
-void TransferQueue::resetQueue()
-{
-    android::Mutex::Autolock lock(m_transferQueueItemLocks);
-    emptyAndAbandonQueue();
-    m_sharedSurfaceTextureId = 0;
-}
-
-// This should be called within the m_transferQueueItemLocks.
-// Now only called by emptyQueue() and destructor.
-void TransferQueue::cleanupGLResources()
-{
-    if (m_fboID) {
-        glDeleteFramebuffers(1, &m_fboID);
-        m_fboID = 0;
-    }
-    if (m_sharedSurfaceTextureId) {
-        glDeleteTextures(1, &m_sharedSurfaceTextureId);
-        m_sharedSurfaceTextureId = 0;
-    }
-}
-
-void TransferQueue::initGLResources(int width, int height)
-{
-    android::Mutex::Autolock lock(m_transferQueueItemLocks);
-    if (!m_sharedSurfaceTextureId) {
-        glGenTextures(1, &m_sharedSurfaceTextureId);
-        sp<BufferQueue> bufferQueue(new BufferQueue(true));
-        m_sharedSurfaceTexture =
-#if GPU_UPLOAD_WITHOUT_DRAW
-            new android::SurfaceTexture(m_sharedSurfaceTextureId, true,
-                                        GL_TEXTURE_2D, true, bufferQueue);
-#else
-            new android::SurfaceTexture(m_sharedSurfaceTextureId, true,
-                                        GL_TEXTURE_EXTERNAL_OES, true,
-                                        bufferQueue);
-#endif
-        m_ANW = new android::SurfaceTextureClient(m_sharedSurfaceTexture);
-        m_sharedSurfaceTexture->setSynchronousMode(true);
-
-        int extraBuffersNeeded = 0;
-        m_ANW->query(m_ANW.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
-                     &extraBuffersNeeded);
-        bufferQueue->setBufferCount(m_transferQueueSize + extraBuffersNeeded);
-
-        int result = native_window_set_buffers_geometry(m_ANW.get(),
-                width, height, HAL_PIXEL_FORMAT_RGBA_8888);
-        GLUtils::checkSurfaceTextureError("native_window_set_buffers_geometry", result);
-        result = native_window_set_usage(m_ANW.get(),
-                GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
-        GLUtils::checkSurfaceTextureError("native_window_set_usage", result);
-    }
-
-    if (!m_fboID)
-        glGenFramebuffers(1, &m_fboID);
-}
-
-// When bliting, if the item from the transfer queue is mismatching b/t the
-// Tile and the content, then the item is considered as obsolete, and
-// the content is discarded.
-bool TransferQueue::checkObsolete(const TileTransferData* data)
-{
-    Tile* baseTilePtr = data->savedTilePtr;
-    if (!baseTilePtr) {
-        ALOGV("Invalid savedTilePtr , such that the tile is obsolete");
-        return true;
-    }
-
-    TileTexture* baseTileTexture = baseTilePtr->backTexture();
-    if (!baseTileTexture || baseTileTexture != data->savedTileTexturePtr) {
-        ALOGV("Invalid baseTileTexture %p (vs expected %p), such that the tile is obsolete",
-              baseTileTexture, data->savedTileTexturePtr);
-        return true;
-    }
-
-    return false;
-}
-
-void TransferQueue::blitTileFromQueue(GLuint fboID, TileTexture* destTex,
-                                      GLuint srcTexId, GLenum srcTexTarget,
-                                      int index)
-{
-#if GPU_UPLOAD_WITHOUT_DRAW
-    glBindFramebuffer(GL_FRAMEBUFFER, fboID);
-    glBindTexture(GL_TEXTURE_2D, destTex->m_ownTextureId);
-
-    int textureWidth = destTex->getSize().width();
-    int textureHeight = destTex->getSize().height();
-
-    glFramebufferTexture2D(GL_FRAMEBUFFER,
-                           GL_COLOR_ATTACHMENT0,
-                           GL_TEXTURE_2D,
-                           srcTexId,
-                           0);
-
-    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0,
-                        textureWidth, textureHeight);
-    if (GLUtils::checkGlError("At the end of blitTileFromQueue()")) {
-#ifndef DEBUG
-        if (GLUtils::allowGLLog())
-#endif
-        ALOGE("blitTileFromQueue ERROR: fboId %d, destTexId %d, srcTexId %d,"
-              " textureWidth %d, textureHeight %d", fboID, destTex->m_ownTextureId,
-              srcTexId, textureWidth, textureHeight);
-    }
-#else
-    // Then set up the FBO and copy the SurfTex content in.
-    glBindFramebuffer(GL_FRAMEBUFFER, fboID);
-    glFramebufferTexture2D(GL_FRAMEBUFFER,
-                           GL_COLOR_ATTACHMENT0,
-                           GL_TEXTURE_2D,
-                           destTex->m_ownTextureId,
-                           0);
-    setGLStateForCopy(destTex->getSize().width(),
-                      destTex->getSize().height());
-    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-    if (status != GL_FRAMEBUFFER_COMPLETE) {
-        ALOGV("Error: glCheckFramebufferStatus failed");
-        return;
-    }
-
-    // Use empty rect to set up the special matrix to draw.
-    SkRect rect  = SkRect::MakeEmpty();
-
-    TextureQuadData data(srcTexId, GL_NEAREST, srcTexTarget, Blit, 0, 0, 1.0, false);
-    TilesManager::instance()->shader()->drawQuad(&data);
-#endif
-}
-
-// This function must be called inside the m_transferQueueItemLocks, for the
-// wait and getHasGLContext().
-// Only called by updateQueueWithBitmap() for now.
-bool TransferQueue::readyForUpdate()
-{
-    if (!getHasGLContext())
-        return false;
-    // Don't use a while loop since when the WebView tear down, the emptyCount
-    // will still be 0, and we bailed out b/c of GL context lost.
-    if (!m_emptyItemCount)
-        m_transferQueueItemCond.wait(m_transferQueueItemLocks);
-
-    if (!getHasGLContext())
-        return false;
-
-    return true;
-}
-
-// Both getHasGLContext and setHasGLContext should be called within the lock.
-bool TransferQueue::getHasGLContext()
-{
-    return m_hasGLContext;
-}
-
-void TransferQueue::setHasGLContext(bool hasContext)
-{
-    m_hasGLContext = hasContext;
-}
-
-// Call within a m_transferQueueItemLocks, now called by resetQueue() and
-// cleanupGLResoucesAndQueue()
-void TransferQueue::emptyAndAbandonQueue()
-{
-    for (int i = 0 ; i < m_transferQueueSize; i++)
-        clearItemInTranferQueue(i);
-    m_emptyItemCount = m_transferQueueSize;
-    clearPureColorQueue();
-
-    if (m_sharedSurfaceTexture.get()) {
-        m_sharedSurfaceTexture->abandon();
-        m_sharedSurfaceTexture.clear();
-    }
-    // This can prevent the tex gen thread to produce, until next incoming draw.
-    setHasGLContext(false);
-}
-
-void TransferQueue::cleanupGLResourcesAndQueue()
-{
-    android::Mutex::Autolock lock(m_transferQueueItemLocks);
-    emptyAndAbandonQueue();
-    cleanupGLResources();
-}
-
-// Set all the content in the queue to pendingDiscard, after this, there will
-// be nothing added to the queue, and this can be called in any thread.
-// However, in order to discard the content in the Surface Texture using
-// updateTexImage, cleanupPendingDiscard need to be called on the UI thread.
-// Must be called within a m_transferQueueItemLocks.
-void TransferQueue::setPendingDiscard()
-{
-    for (int i = 0 ; i < m_transferQueueSize; i++)
-        if (m_transferQueue[i].status == pendingBlit)
-            m_transferQueue[i].status = pendingDiscard;
-
-    clearPureColorQueue();
-
-    bool GLContextExisted = getHasGLContext();
-    // Unblock the Tex Gen thread first before Tile Page deletion.
-    // Otherwise, there will be a deadlock while removing operations.
-    setHasGLContext(false);
-
-    // Only signal once when GL context lost.
-    if (GLContextExisted)
-        m_transferQueueItemCond.signal();
-}
-
-void TransferQueue::clearPureColorQueue()
-{
-    for (unsigned int i = 0 ; i < m_pureColorTileQueue.size(); i++) {
-        SkSafeUnref(m_pureColorTileQueue[i].savedTilePainter);
-        m_pureColorTileQueue[i].savedTilePainter = 0;
-    }
-    m_pureColorTileQueue.clear();
-}
-
-void TransferQueue::updatePureColorTiles()
-{
-    for (unsigned int i = 0 ; i < m_pureColorTileQueue.size(); i++) {
-        TileTransferData* data = &m_pureColorTileQueue[i];
-        if (data->status == pendingBlit) {
-            TileTexture* destTexture = 0;
-            bool obsoleteTile = checkObsolete(data);
-            if (!obsoleteTile) {
-                destTexture = data->savedTilePtr->backTexture();
-                destTexture->setPureColor(data->pureColor);
-                destTexture->transferComplete();
-            }
-        } else if (data->status == emptyItem || data->status == pendingDiscard) {
-            // The queue should be clear instead of setting to different status.
-            ALOGV("Warning: Don't expect an emptyItem here.");
-        }
-    }
-    clearPureColorQueue();
-}
-
-// Call on UI thread to copy from the shared Surface Texture to the Tile's texture.
-void TransferQueue::updateDirtyTiles()
-{
-    android::Mutex::Autolock lock(m_transferQueueItemLocks);
-
-    cleanupPendingDiscard();
-    if (!getHasGLContext())
-        setHasGLContext(true);
-
-    // Check the pure color tile first, since it is simpler.
-    updatePureColorTiles();
-
-    // Start from the oldest item, we call the updateTexImage to retrive
-    // the texture and blit that into each Tile's texture.
-    const int nextItemIndex = getNextTransferQueueIndex();
-    int index = nextItemIndex;
-    bool usedFboForUpload = false;
-    for (int k = 0; k < m_transferQueueSize ; k++) {
-        if (m_transferQueue[index].status == pendingBlit) {
-            bool obsoleteTile = checkObsolete(&m_transferQueue[index]);
-            // Save the needed info, update the Surf Tex, clean up the item in
-            // the queue. Then either move on to next item or copy the content.
-            TileTexture* destTexture = 0;
-            if (!obsoleteTile)
-                destTexture = m_transferQueue[index].savedTilePtr->backTexture();
-
-            if (m_transferQueue[index].uploadType == GpuUpload) {
-                status_t result = m_sharedSurfaceTexture->updateTexImage();
-                if (result != OK)
-                    ALOGE("unexpected error: updateTexImage return %d", result);
-            }
-
-            if (obsoleteTile) {
-                ALOGV("Warning: the texture is obsolete for this baseTile");
-                clearItemInTranferQueue(index);
-                index = (index + 1) % m_transferQueueSize;
-                continue;
-            }
-
-            // guarantee that we have a texture to blit into
-            destTexture->requireGLTexture();
-            GLUtils::checkGlError("before blitTileFromQueue");
-            if (m_transferQueue[index].uploadType == CpuUpload) {
-                // Here we just need to upload the bitmap content to the GL Texture
-                GLUtils::updateTextureWithBitmap(destTexture->m_ownTextureId,
-                                                 *m_transferQueue[index].bitmap);
-            } else {
-                if (!usedFboForUpload) {
-                    saveGLState();
-                    usedFboForUpload = true;
-                }
-                blitTileFromQueue(m_fboID, destTexture, m_sharedSurfaceTextureId,
-                                  m_sharedSurfaceTexture->getCurrentTextureTarget(),
-                                  index);
-            }
-
-            destTexture->setPure(false);
-            destTexture->transferComplete();
-            clearItemInTranferQueue(index);
-            ALOGV("Blit tile x, y %d %d with dest texture %p to destTexture->m_ownTextureId %d",
-                  m_transferQueue[index].savedTilePtr,
-                  destTexture,
-                  destTexture->m_ownTextureId);
-        }
-        index = (index + 1) % m_transferQueueSize;
-    }
-
-    // Clean up FBO setup. Doing this for both CPU/GPU upload can make the
-    // dynamic switch possible. Moving this out from the loop can save some
-    // milli-seconds.
-    if (usedFboForUpload) {
-        restoreGLState();
-        GLUtils::checkGlError("updateDirtyTiles");
-    }
-
-    m_emptyItemCount = m_transferQueueSize;
-    m_transferQueueItemCond.signal();
-}
-
-void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo,
-                                          const SkBitmap& bitmap)
-{
-    if (!tryUpdateQueueWithBitmap(renderInfo, bitmap)) {
-        // failed placing bitmap in queue, discard tile's texture so it will be
-        // re-enqueued (and repainted)
-        Tile* tile = renderInfo->baseTile;
-        if (tile)
-            tile->backTextureTransferFail();
-    }
-}
-
-bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo,
-                                             const SkBitmap& bitmap)
-{
-    // This lock need to cover the full update since it is possible that queue
-    // will be cleaned up in the middle of this update without the lock.
-    // The Surface Texture will not block us since the readyForUpdate will check
-    // availability of the slots in the queue first.
-    android::Mutex::Autolock lock(m_transferQueueItemLocks);
-    bool ready = readyForUpdate();
-    TextureUploadType currentUploadType = m_currentUploadType;
-    if (!ready) {
-        ALOGV("Quit bitmap update: not ready! for tile x y %d %d",
-              renderInfo->x, renderInfo->y);
-        return false;
-    }
-    if (currentUploadType == GpuUpload) {
-        // a) Dequeue the Surface Texture and write into the buffer
-        if (!m_ANW.get()) {
-            ALOGV("ERROR: ANW is null");
-            return false;
-        }
-
-        if (!GLUtils::updateSharedSurfaceTextureWithBitmap(m_ANW.get(), bitmap))
-            return false;
-    }
-
-    // b) After update the Surface Texture, now udpate the transfer queue info.
-    addItemInTransferQueue(renderInfo, currentUploadType, &bitmap);
-
-    ALOGV("Bitmap updated x, y %d %d, baseTile %p",
-          renderInfo->x, renderInfo->y, renderInfo->baseTile);
-    return true;
-}
-
-void TransferQueue::addItemInPureColorQueue(const TileRenderInfo* renderInfo)
-{
-    // The pure color tiles' queue will be read from UI thread and written in
-    // Tex Gen thread, thus we need to have a lock here.
-    android::Mutex::Autolock lock(m_transferQueueItemLocks);
-    TileTransferData data;
-    addItemCommon(renderInfo, GpuUpload, &data);
-    data.pureColor = renderInfo->pureColor;
-    m_pureColorTileQueue.append(data);
-}
-
-void TransferQueue::clearItemInTranferQueue(int index)
-{
-    m_transferQueue[index].savedTilePtr = 0;
-    SkSafeUnref(m_transferQueue[index].savedTilePainter);
-    m_transferQueue[index].savedTilePainter = 0;
-    m_transferQueue[index].status = emptyItem;
-}
-
-// Translates the info from TileRenderInfo and others to TileTransferData.
-// This is used by pure color tiles and normal tiles.
-void TransferQueue::addItemCommon(const TileRenderInfo* renderInfo,
-                                  TextureUploadType type,
-                                  TileTransferData* data)
-{
-    data->savedTileTexturePtr = renderInfo->baseTile->backTexture();
-    data->savedTilePainter = renderInfo->tilePainter;
-    SkSafeRef(data->savedTilePainter);
-    data->savedTilePtr = renderInfo->baseTile;
-    data->status = pendingBlit;
-    data->uploadType = type;
-
-    IntRect inval(0, 0, 0, 0);
-}
-
-// Note that there should be lock/unlock around this function call.
-// Currently only called by GLUtils::updateSharedSurfaceTextureWithBitmap.
-void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo,
-                                           TextureUploadType type,
-                                           const SkBitmap* bitmap)
-{
-    m_transferQueueIndex = (m_transferQueueIndex + 1) % m_transferQueueSize;
-
-    int index = m_transferQueueIndex;
-    if (m_transferQueue[index].savedTilePtr
-        || m_transferQueue[index].status != emptyItem) {
-        ALOGV("ERROR update a tile which is dirty already @ index %d", index);
-    }
-
-    TileTransferData* data = &m_transferQueue[index];
-    addItemCommon(renderInfo, type, data);
-    if (type == CpuUpload && bitmap) {
-        // Lazily create the bitmap
-        if (!m_transferQueue[index].bitmap) {
-            m_transferQueue[index].bitmap = new SkBitmap();
-            int w = bitmap->width();
-            int h = bitmap->height();
-            m_transferQueue[index].bitmap->setConfig(bitmap->config(), w, h);
-        }
-        bitmap->copyTo(m_transferQueue[index].bitmap, bitmap->config());
-    }
-
-    m_emptyItemCount--;
-}
-
-void TransferQueue::setTextureUploadType(TextureUploadType type)
-{
-    android::Mutex::Autolock lock(m_transferQueueItemLocks);
-    if (m_currentUploadType == type)
-        return;
-
-    setPendingDiscard();
-
-    m_currentUploadType = type;
-    ALOGD("Now we set the upload to %s", m_currentUploadType == GpuUpload ? "GpuUpload" : "CpuUpload");
-}
-
-// Note: this need to be called within the lock and on the UI thread.
-// Only called by updateDirtyTiles() and emptyQueue() for now
-void TransferQueue::cleanupPendingDiscard()
-{
-    int index = getNextTransferQueueIndex();
-
-    for (int i = 0 ; i < m_transferQueueSize; i++) {
-        if (m_transferQueue[index].status == pendingDiscard) {
-            // No matter what the current upload type is, as long as there has
-            // been a Surf Tex enqueue operation, this updateTexImage need to
-            // be called to keep things in sync.
-            if (m_transferQueue[index].uploadType == GpuUpload) {
-                status_t result = m_sharedSurfaceTexture->updateTexImage();
-                if (result != OK)
-                    ALOGE("unexpected error: updateTexImage return %d", result);
-            }
-
-            // since tiles in the queue may be from another webview, remove
-            // their textures so that they will be repainted / retransferred
-            Tile* tile = m_transferQueue[index].savedTilePtr;
-            TileTexture* texture = m_transferQueue[index].savedTileTexturePtr;
-            if (tile && texture && texture->owner() == tile) {
-                // since tile destruction removes textures on the UI thread, the
-                // texture->owner ptr guarantees the tile is valid
-                tile->discardBackTexture();
-                ALOGV("transfer queue discarded tile %p, removed texture", tile);
-            }
-            clearItemInTranferQueue(index);
-        }
-        index = (index + 1) % m_transferQueueSize;
-    }
-}
-
-void TransferQueue::saveGLState()
-{
-    glGetIntegerv(GL_FRAMEBUFFER_BINDING, m_GLStateBeforeBlit.bufferId);
-    glGetIntegerv(GL_VIEWPORT, m_GLStateBeforeBlit.viewport);
-    glGetBooleanv(GL_SCISSOR_TEST, m_GLStateBeforeBlit.scissor);
-    glGetBooleanv(GL_DEPTH_TEST, m_GLStateBeforeBlit.depth);
-#ifdef DEBUG
-    glGetFloatv(GL_COLOR_CLEAR_VALUE, m_GLStateBeforeBlit.clearColor);
-#endif
-}
-
-void TransferQueue::setGLStateForCopy(int width, int height)
-{
-    // Need to match the texture size.
-    glViewport(0, 0, width, height);
-    glDisable(GL_SCISSOR_TEST);
-    glDisable(GL_DEPTH_TEST);
-    // Clear the content is only for debug purpose.
-#ifdef DEBUG
-    glClearColor(0, 0, 0, 0);
-    glClear(GL_COLOR_BUFFER_BIT);
-#endif
-}
-
-void TransferQueue::restoreGLState()
-{
-    glBindFramebuffer(GL_FRAMEBUFFER, m_GLStateBeforeBlit.bufferId[0]);
-    glViewport(m_GLStateBeforeBlit.viewport[0],
-               m_GLStateBeforeBlit.viewport[1],
-               m_GLStateBeforeBlit.viewport[2],
-               m_GLStateBeforeBlit.viewport[3]);
-
-    if (m_GLStateBeforeBlit.scissor[0])
-        glEnable(GL_SCISSOR_TEST);
-
-    if (m_GLStateBeforeBlit.depth[0])
-        glEnable(GL_DEPTH_TEST);
-#ifdef DEBUG
-    glClearColor(m_GLStateBeforeBlit.clearColor[0],
-                 m_GLStateBeforeBlit.clearColor[1],
-                 m_GLStateBeforeBlit.clearColor[2],
-                 m_GLStateBeforeBlit.clearColor[3]);
-#endif
-}
-
-int TransferQueue::getNextTransferQueueIndex()
-{
-    return (m_transferQueueIndex + 1) % m_transferQueueSize;
-}
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING
diff --git a/Source/WebCore/platform/graphics/skia/SkiaUtils.cpp b/Source/WebCore/platform/graphics/skia/SkiaUtils.cpp
index ebd9f0d..da83793 100644
--- a/Source/WebCore/platform/graphics/skia/SkiaUtils.cpp
+++ b/Source/WebCore/platform/graphics/skia/SkiaUtils.cpp
@@ -40,11 +40,6 @@
 #include "SkRegion.h"
 #include "SkUnPreMultiply.h"
 
-#if PLATFORM(ANDROID)
-#include "GraphicsContext.h"
-#include "PlatformGraphicsContextSkia.h"
-#endif
-
 namespace WebCore {
 
 #if PLATFORM(ANDROID)
@@ -251,20 +246,6 @@
     return contains;
 }
 
-#if PLATFORM(ANDROID)
-GraphicsContext* scratchContext()
-{
-    static GraphicsContext* scratch = 0;
-    if (!scratch) {
-        SkBitmap bm;
-        bm.setConfig(SkBitmap::kNo_Config, 1, 1);
-        SkCanvas* canvas = new SkCanvas(bm);
-        PlatformGraphicsContextSkia* pgc = new PlatformGraphicsContextSkia(canvas);
-        scratch = new GraphicsContext(pgc);
-    }
-    return scratch;
-}
-#else
 GraphicsContext* scratchContext()
 {
     static ImageBuffer* scratch = ImageBuffer::create(IntSize(1, 1)).leakPtr();
@@ -272,6 +253,5 @@
     // ImageBuffer initializer won't fail.
     return scratch->context();
 }
-#endif
 
 }  // namespace WebCore
diff --git a/Source/WebCore/platform/network/android/ResourceHandleAndroid.cpp b/Source/WebCore/platform/network/android/ResourceHandleAndroid.cpp
index 4bc918b..13a26f0 100644
--- a/Source/WebCore/platform/network/android/ResourceHandleAndroid.cpp
+++ b/Source/WebCore/platform/network/android/ResourceHandleAndroid.cpp
@@ -96,7 +96,9 @@
 }
 
 // This static method is called to check to see if a POST response is in
-// the cache.
+// the cache. The JNI call through to the HTTP cache stored on the Java
+// side may be slow, but is only used during a navigation to
+// a POST response.
 bool ResourceHandle::willLoadFromCache(ResourceRequest& request, Frame*)
 {
     // set the cache policy correctly, copied from
diff --git a/Source/WebCore/platform/network/android/ResourceLoaderAndroid.h b/Source/WebCore/platform/network/android/ResourceLoaderAndroid.h
index 5ff2322..f627d62 100644
--- a/Source/WebCore/platform/network/android/ResourceLoaderAndroid.h
+++ b/Source/WebCore/platform/network/android/ResourceLoaderAndroid.h
@@ -46,6 +46,7 @@
     virtual void pauseLoad(bool) = 0;
     // END ANDROID TODO
 
+    // Call to java to find out if this URL is in the cache
     static bool willLoadFromCache(const WebCore::KURL&, int64_t identifier);
 protected:
     ResourceLoaderAndroid() { }
diff --git a/Source/WebCore/platform/network/android/ResourceRequestAndroid.cpp b/Source/WebCore/platform/network/android/ResourceRequestAndroid.cpp
index 1519e9c..00735f3 100644
--- a/Source/WebCore/platform/network/android/ResourceRequestAndroid.cpp
+++ b/Source/WebCore/platform/network/android/ResourceRequestAndroid.cpp
@@ -30,10 +30,17 @@
 
 unsigned initializeMaximumHTTPConnectionCountPerHost()
 {
+#if USE(CHROME_NETWORK_STACK)
     // The chromium network stack already handles limiting the number of
     // parallel requests per host, so there's no need to do it here.  Therefore,
     // this is set to a high value that should never be hit in practice.
     return 10000;
+#else
+    // This is used by the loader to control the number of parallel load
+    // requests. Our java framework has 4 threads that can each pipeline up to
+    // 5 requests. Use 20 as a maximum number.
+    return 20;
+#endif
 }
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
index ec04035..dc22fca 100644
--- a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
+++ b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
@@ -180,9 +180,9 @@
     g_object_set_data(G_OBJECT(session), "webkit-init", reinterpret_cast<void*>(0xdeadbeef));
 }
 
-void ResourceHandle::prepareForURL(const KURL& url)
+void ResourceHandle::prepareForURL(const KURL &url)
 {
-    GOwnPtr<SoupURI> soupURI(soup_uri_new(url.string().utf8().data()));
+    GOwnPtr<SoupURI> soupURI(soup_uri_new(url.prettyURL().utf8().data()));
     if (!soupURI)
         return;
     soup_session_prepare_for_uri(ResourceHandle::defaultSession(), soupURI.get());
diff --git a/Source/WebCore/platform/qt/KURLQt.cpp b/Source/WebCore/platform/qt/KURLQt.cpp
index 674a933..f6d2a86 100644
--- a/Source/WebCore/platform/qt/KURLQt.cpp
+++ b/Source/WebCore/platform/qt/KURLQt.cpp
@@ -50,3 +50,4 @@
 }
 
 }
+
diff --git a/Source/WebCore/platform/text/android/HyphenationAndroid.cpp b/Source/WebCore/platform/text/android/HyphenationAndroid.cpp
index 9933715..d1bd839 100644
--- a/Source/WebCore/platform/text/android/HyphenationAndroid.cpp
+++ b/Source/WebCore/platform/text/android/HyphenationAndroid.cpp
@@ -28,7 +28,7 @@
 
 // For external hyphenation library.
 #include "hyphen.h"
-#include <androidfw/AssetManager.h>
+#include <utils/AssetManager.h>
 #include <wtf/text/CString.h>
 #include <wtf/text/WTFString.h>
 
diff --git a/Source/WebCore/platform/win/ClipboardWin.cpp b/Source/WebCore/platform/win/ClipboardWin.cpp
index 2e56cbc..0b5a3d3 100644
--- a/Source/WebCore/platform/win/ClipboardWin.cpp
+++ b/Source/WebCore/platform/win/ClipboardWin.cpp
@@ -191,7 +191,7 @@
     WCHAR filePath[MAX_PATH];
 
     if (url.isLocalFile()) {
-        String localPath = decodeURLEscapeSequences(url.path());
+        String localPath = url.path();
         // windows does not enjoy a leading slash on paths
         if (localPath[0] == '/')
             localPath = localPath.substring(1);
diff --git a/Source/WebCore/plugins/PluginView.cpp b/Source/WebCore/plugins/PluginView.cpp
index ffefc71..c39ceac 100644
--- a/Source/WebCore/plugins/PluginView.cpp
+++ b/Source/WebCore/plugins/PluginView.cpp
@@ -830,6 +830,8 @@
 }
 #endif
 
+#if USE(V8)
+// This is really JS engine independent
 NPObject* PluginView::getNPObject() {
 #if ENABLE(NETSCAPE_PLUGIN_API)
     if (!m_plugin || !m_plugin->pluginFuncs()->getvalue)
@@ -857,6 +859,7 @@
     return 0;
 #endif  // NETSCAPE_PLUGIN_API
 }
+#endif  // V8
 
 void PluginView::disconnectStream(PluginStream* stream)
 {
diff --git a/Source/WebCore/plugins/PluginView.h b/Source/WebCore/plugins/PluginView.h
index bf77e51..976c65c 100644
--- a/Source/WebCore/plugins/PluginView.h
+++ b/Source/WebCore/plugins/PluginView.h
@@ -202,7 +202,9 @@
                              void (*timerFunc)(NPP, uint32_t timerID));
         void unscheduleTimer(NPP, uint32_t timerID);
 #endif
+#if USE(V8)
         NPObject* getNPObject();
+#endif
 
         virtual void invalidateRect(const IntRect&);
 
diff --git a/Source/WebCore/plugins/android/PluginViewAndroid.cpp b/Source/WebCore/plugins/android/PluginViewAndroid.cpp
index fdf6e03..dba7d3b 100644
--- a/Source/WebCore/plugins/android/PluginViewAndroid.cpp
+++ b/Source/WebCore/plugins/android/PluginViewAndroid.cpp
@@ -63,6 +63,10 @@
 #include "ScriptController.h"
 #include "Settings.h"
 
+#if USE(JSC)
+#include <runtime/JSLock.h>
+#endif
+
 #include <wtf/ASCIICType.h>
 // #include "runtime.h"
 #include "WebViewCore.h"
@@ -480,6 +484,9 @@
     m_npWindow.clipRect.bottom = m_pageRect.y() + m_pageRect.height();
 
     if (m_plugin->pluginFuncs()->setwindow) {
+#if USE(JSC)
+        JSC::JSLock::DropAllLocks dropAllLocks(false);
+#endif
         setCallingPlugin(true);
         m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow);
         setCallingPlugin(false);
@@ -690,10 +697,7 @@
            notification of its global position change.
          */
         updatePluginWidget();
-        SkCanvas* canvas = context->platformContext()->getCanvas();
-        if (!canvas)
-           return;
-        m_window->setSurfaceClip(canvas->getTotalClip().getBounds());
+        m_window->setSurfaceClip(context->platformContext()->mCanvas->getTotalClip().getBounds());
     } else {
         m_window->inval(rect, false);
         context->save();
diff --git a/Source/WebCore/rendering/InlineTextBox.cpp b/Source/WebCore/rendering/InlineTextBox.cpp
index d5eeeae..5815b8b 100644
--- a/Source/WebCore/rendering/InlineTextBox.cpp
+++ b/Source/WebCore/rendering/InlineTextBox.cpp
@@ -43,7 +43,6 @@
 #include "Text.h"
 #include "break_lines.h"
 #include <wtf/AlwaysInline.h>
-#include <wtf/text/CString.h>
 
 using namespace std;
 
@@ -1070,12 +1069,8 @@
             renderer()->theme()->platformInactiveTextSearchHighlightColor();
         pt->save();
         updateGraphicsContext(pt, color, color, 0, style->colorSpace());  // Don't draw text at all!
-#if PLATFORM(ANDROID)
-        pt->drawHighlightForText(font, run, FloatPoint(boxOrigin.x(), boxOrigin.y() - deltaY), selHeight, color, style->colorSpace(), sPos, ePos, marker.activeMatch);
-#else
         pt->clip(FloatRect(boxOrigin.x(), boxOrigin.y() - deltaY, m_logicalWidth, selHeight));
         pt->drawHighlightForText(font, run, FloatPoint(boxOrigin.x(), boxOrigin.y() - deltaY), selHeight, color, style->colorSpace(), sPos, ePos);
-#endif
         pt->restore();
     }
 }
diff --git a/Source/WebCore/rendering/PaintPhase.h b/Source/WebCore/rendering/PaintPhase.h
index 7dc205d..396131f 100644
--- a/Source/WebCore/rendering/PaintPhase.h
+++ b/Source/WebCore/rendering/PaintPhase.h
@@ -39,10 +39,6 @@
 
 enum PaintPhase {
     PaintPhaseBlockBackground,
-#if PLATFORM(ANDROID)
-    // Used for fixed background support in layers
-    PaintPhaseBlockBackgroundDecorations,
-#endif
     PaintPhaseChildBlockBackground,
     PaintPhaseChildBlockBackgrounds,
     PaintPhaseFloat,
diff --git a/Source/WebCore/rendering/RenderArena.cpp b/Source/WebCore/rendering/RenderArena.cpp
index e15101f..57ed978 100644
--- a/Source/WebCore/rendering/RenderArena.cpp
+++ b/Source/WebCore/rendering/RenderArena.cpp
@@ -136,4 +136,11 @@
 #endif
 }
 
+#ifdef ANDROID_INSTRUMENT
+size_t RenderArena::reportPoolSize() const
+{
+    return ReportPoolSize(&m_pool);
+}
+#endif
+
 } // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderArena.h b/Source/WebCore/rendering/RenderArena.h
index e1ff535..5d2559a 100644
--- a/Source/WebCore/rendering/RenderArena.h
+++ b/Source/WebCore/rendering/RenderArena.h
@@ -53,6 +53,10 @@
     void* allocate(size_t);
     void free(size_t, void*);
 
+#ifdef ANDROID_INSTRUMENT
+    size_t reportPoolSize() const;
+#endif
+
 private:
     // Underlying arena pool
     ArenaPool m_pool;
diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp
index 86d8a98..a90bf69 100644
--- a/Source/WebCore/rendering/RenderBlock.cpp
+++ b/Source/WebCore/rendering/RenderBlock.cpp
@@ -191,7 +191,7 @@
                         childBox->remove();
                 }
             }
-        } else if (parent())
+        } else if (isInline() && parent())
             parent()->dirtyLinesFromChangedChild(this);
     }
 
@@ -420,18 +420,14 @@
 
 RenderBlock* RenderBlock::containingColumnsBlock(bool allowAnonymousColumnBlock)
 {
-    RenderBlock* firstChildIgnoringAnonymousWrappers = 0;
     for (RenderObject* curr = this; curr; curr = curr->parent()) {
         if (!curr->isRenderBlock() || curr->isFloatingOrPositioned() || curr->isTableCell() || curr->isRoot() || curr->isRenderView() || curr->hasOverflowClip()
             || curr->isInlineBlockOrInlineTable())
             return 0;
         
         RenderBlock* currBlock = toRenderBlock(curr);
-        if (!currBlock->createsAnonymousWrapper())
-            firstChildIgnoringAnonymousWrappers = currBlock;
-
         if (currBlock->style()->specifiesColumns() && (allowAnonymousColumnBlock || !currBlock->isAnonymousColumnsBlock()))
-            return firstChildIgnoringAnonymousWrappers;
+            return currBlock;
             
         if (currBlock->isAnonymousColumnSpanBlock())
             return 0;
@@ -447,8 +443,6 @@
     else {
         cloneBlock = new (renderArena()) RenderBlock(node());
         cloneBlock->setStyle(style());
-        if (!childrenInline() && cloneBlock->firstChild() && cloneBlock->firstChild()->isInline())
-            cloneBlock->makeChildrenNonInline();
     }
     cloneBlock->setChildrenInline(childrenInline());
     return cloneBlock;
@@ -663,21 +657,12 @@
     // cross the streams and have to cope with both types of continuations mixed together).
     // This function currently supports (1) and (2).
     RenderBlock* columnsBlockAncestor = 0;
-    if (!newChild->isText() && newChild->style()->columnSpan() && !newChild->isBeforeOrAfterContent()
-        && !newChild->isFloatingOrPositioned() && !newChild->isInline() && !isAnonymousColumnSpanBlock()) {
-        columnsBlockAncestor = containingColumnsBlock(false);
-        if (columnsBlockAncestor) {
-            // Make sure that none of the parent ancestors have a continuation.
-            // If yes, we do not want split the block into continuations.
-            RenderObject* curr = this;
-            while (curr && curr != columnsBlockAncestor) {
-                if (curr->isRenderBlock() && toRenderBlock(curr)->continuation()) {
-                    columnsBlockAncestor = 0;
-                    break;
-                }
-                curr = curr->parent();
-            }
-        }
+    if (!newChild->isText() && newChild->style()->columnSpan() && !newChild->isFloatingOrPositioned()
+        && !newChild->isInline() && !isAnonymousColumnSpanBlock()) {
+        if (style()->specifiesColumns())
+            columnsBlockAncestor = this;
+        else if (parent() && parent()->isRenderBlock())
+            columnsBlockAncestor = toRenderBlock(parent())->containingColumnsBlock(false);
     }
     return columnsBlockAncestor;
 }
@@ -2499,11 +2484,7 @@
     PaintPhase paintPhase = paintInfo.phase;
 
     // 1. paint background, borders etc
-    if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground
-#if PLATFORM(ANDROID)
-         || paintPhase == PaintPhaseBlockBackgroundDecorations
-#endif
-        ) && style()->visibility() == VISIBLE) {
+    if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && style()->visibility() == VISIBLE) {
         if (hasBoxDecorations())
             paintBoxDecorations(paintInfo, tx, ty);
         if (hasColumns())
@@ -5380,28 +5361,21 @@
 
     // Drill into inlines looking for our first text child.
     RenderObject* currChild = firstLetterBlock->firstChild();
-    while (currChild) {
-        if (currChild->isText())
-            break;
-        if (currChild->isListMarker())
-            currChild = currChild->nextSibling();
-        else if (currChild->isFloatingOrPositioned()) {
+    while (currChild && ((!currChild->isReplaced() && !currChild->isRenderButton() && !currChild->isMenuList()) || currChild->isFloatingOrPositioned()) && !currChild->isText()) {
+        if (currChild->isFloatingOrPositioned()) {
             if (currChild->style()->styleType() == FIRST_LETTER) {
                 currChild = currChild->firstChild();
                 break;
-            }
+            } 
             currChild = currChild->nextSibling();
-        } else if (currChild->isReplaced() || currChild->isRenderButton() || currChild->isMenuList())
-            break;
-        else if (currChild->style()->hasPseudoStyle(FIRST_LETTER) && currChild->canHaveChildren())  {
-            // We found a lower-level node with first-letter, which supersedes the higher-level style
-            firstLetterBlock = currChild;
-            currChild = currChild->firstChild();
-        }
-        else
+        } else
             currChild = currChild->firstChild();
     }
 
+    // Get list markers out of the way.
+    while (currChild && currChild->isListMarker())
+        currChild = currChild->nextSibling();
+
     if (!currChild)
         return;
 
diff --git a/Source/WebCore/rendering/RenderBlockLineLayout.cpp b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
index a2469a0..df20063 100644
--- a/Source/WebCore/rendering/RenderBlockLineLayout.cpp
+++ b/Source/WebCore/rendering/RenderBlockLineLayout.cpp
@@ -895,10 +895,6 @@
                     m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, maxWidth);
                     m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, maxWidth);
 
-                    // if overflow isn't visible, block elements may get clipped
-                    // due to the limited content width. disable overflow clipping.
-                    setHasOverflowClip(false);
-
                     IntRect overflow = layoutOverflowRect();
                     if (overflow.width() > maxWidth) {
                         overflow.setWidth(maxWidth);
diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp
index bc7d03a..fb1dd2c 100644
--- a/Source/WebCore/rendering/RenderBox.cpp
+++ b/Source/WebCore/rendering/RenderBox.cpp
@@ -843,11 +843,6 @@
         else if (!isBody() || document()->documentElement()->renderer()->hasBackground()) {
             // The <body> only paints its background if the root element has defined a background
             // independent of the body.
-#if PLATFORM(ANDROID)
-            // If we only want to draw the decorations, don't draw
-            // the background
-            if (paintInfo.phase != PaintPhaseBlockBackgroundDecorations)
-#endif
             paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), tx, ty, width, height);
         }
         if (style()->hasAppearance())
@@ -3265,7 +3260,7 @@
 
 bool RenderBox::avoidsFloats() const
 {
-    return isReplaced() || hasOverflowClip() || isHR() || isLegend() || isWritingModeRoot() || isDeprecatedFlexItem();
+    return isReplaced() || hasOverflowClip() || isHR() || isLegend() || isWritingModeRoot();
 }
 
 void RenderBox::addShadowOverflow()
diff --git a/Source/WebCore/rendering/RenderBox.h b/Source/WebCore/rendering/RenderBox.h
index a5dc1b2..1bee989 100644
--- a/Source/WebCore/rendering/RenderBox.h
+++ b/Source/WebCore/rendering/RenderBox.h
@@ -378,8 +378,6 @@
     virtual void markForPaginationRelayoutIfNeeded() { }
 
     bool isWritingModeRoot() const { return !parent() || parent()->style()->writingMode() != style()->writingMode(); }
-
-    bool isDeprecatedFlexItem() const { return !isInline() && !isFloatingOrPositioned() && parent() && parent()->isFlexibleBox(); }
     
     virtual int lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
     virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.h b/Source/WebCore/rendering/RenderBoxModelObject.h
index ac4152f..d2f5972 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.h
+++ b/Source/WebCore/rendering/RenderBoxModelObject.h
@@ -62,11 +62,7 @@
 
     bool hasSelfPaintingLayer() const;
     RenderLayer* layer() const { return m_layer; }
-#if PLATFORM(ANDROID)
-    virtual bool requiresLayer() const { return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasReflection() || style()->specifiesColumns() || style()->hasFixedBackgroundImage(); }
-#else
     virtual bool requiresLayer() const { return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasReflection() || style()->specifiesColumns(); }
-#endif
 
     // This will work on inlines to return the bounding box of all of the lines' border boxes.
     virtual IntRect borderBoundingBox() const = 0;
diff --git a/Source/WebCore/rendering/RenderFileUploadControl.cpp b/Source/WebCore/rendering/RenderFileUploadControl.cpp
index 109d219..8056662 100644
--- a/Source/WebCore/rendering/RenderFileUploadControl.cpp
+++ b/Source/WebCore/rendering/RenderFileUploadControl.cpp
@@ -122,13 +122,6 @@
     return static_cast<HTMLInputElement*>(node())->accept();
 }
 
-#if ENABLE(MEDIA_CAPTURE)
-String RenderFileUploadControl::capture()
-{
-    return static_cast<HTMLInputElement*>(node())->capture();
-}
-#endif
-
 void RenderFileUploadControl::chooseIconForFiles(FileChooser* chooser, const Vector<String>& filenames)
 {
     if (Chrome* chromePointer = chrome())
diff --git a/Source/WebCore/rendering/RenderFileUploadControl.h b/Source/WebCore/rendering/RenderFileUploadControl.h
index b57260d..e9fb7f0 100644
--- a/Source/WebCore/rendering/RenderFileUploadControl.h
+++ b/Source/WebCore/rendering/RenderFileUploadControl.h
@@ -68,9 +68,6 @@
 #endif
     String acceptTypes();
     void chooseIconForFiles(FileChooser*, const Vector<String>&);
-#if ENABLE(MEDIA_CAPTURE)
-    String capture();
-#endif
 
     Chrome* chrome() const;
     int maxFilenameWidth() const;
diff --git a/Source/WebCore/rendering/RenderFlexibleBox.cpp b/Source/WebCore/rendering/RenderFlexibleBox.cpp
index 99c7e0b..dc5c171 100644
--- a/Source/WebCore/rendering/RenderFlexibleBox.cpp
+++ b/Source/WebCore/rendering/RenderFlexibleBox.cpp
@@ -43,30 +43,30 @@
 class FlexBoxIterator {
 public:
     FlexBoxIterator(RenderFlexibleBox* parent)
-        : m_box(parent)
-        , m_lastOrdinal(1)
     {
-        if (m_box->style()->boxOrient() == HORIZONTAL && !m_box->style()->isLeftToRightDirection())
-            m_forward = m_box->style()->boxDirection() != BNORMAL;
+        box = parent;
+        if (box->style()->boxOrient() == HORIZONTAL && !box->style()->isLeftToRightDirection())
+            forward = box->style()->boxDirection() != BNORMAL;
         else
-            m_forward = m_box->style()->boxDirection() == BNORMAL;
-        if (!m_forward) {
+            forward = box->style()->boxDirection() == BNORMAL;
+        lastOrdinal = 1; 
+        if (!forward) {
             // No choice, since we're going backwards, we have to find out the highest ordinal up front.
-            RenderBox* child = m_box->firstChildBox();
+            RenderBox* child = box->firstChildBox();
             while (child) {
-                if (child->style()->boxOrdinalGroup() > m_lastOrdinal)
-                    m_lastOrdinal = child->style()->boxOrdinalGroup();
+                if (child->style()->boxOrdinalGroup() > lastOrdinal)
+                    lastOrdinal = child->style()->boxOrdinalGroup();
                 child = child->nextSiblingBox();
             }
         }
-
+        
         reset();
     }
 
     void reset()
     {
-        m_currentChild = 0;
-        m_currentOrdinal = m_forward ? 0 : m_lastOrdinal + 1;
+        current = 0;
+        currentOrdinal = forward ? 0 : lastOrdinal+1;
     }
 
     RenderBox* first()
@@ -74,42 +74,42 @@
         reset();
         return next();
     }
-
+    
     RenderBox* next()
     {
-        do {
-            if (!m_currentChild) {
-                if (m_forward) {
-                    ++m_currentOrdinal;
-                    if (m_currentOrdinal > m_lastOrdinal)
+        do { 
+            if (!current) {
+                if (forward) {
+                    currentOrdinal++; 
+                    if (currentOrdinal > lastOrdinal)
                         return 0;
-                    m_currentChild = m_box->firstChildBox();
+                    current = box->firstChildBox();
                 } else {
-                    --m_currentOrdinal;
-                    if (!m_currentOrdinal)
+                    currentOrdinal--;
+                    if (currentOrdinal == 0)
                         return 0;
-                    m_currentChild = m_box->lastChildBox();
+                    current = box->lastChildBox();
                 }
             }
             else
-                m_currentChild = m_forward ? m_currentChild->nextSiblingBox() : m_currentChild->previousSiblingBox();
-            if (m_currentChild && m_currentChild->style()->boxOrdinalGroup() > m_lastOrdinal)
-                m_lastOrdinal = m_currentChild->style()->boxOrdinalGroup();
-        } while (!m_currentChild || (!m_currentChild->isAnonymous()
-                 && (m_currentChild->style()->boxOrdinalGroup() != m_currentOrdinal || m_currentChild->style()->visibility() == COLLAPSE)));
-        return m_currentChild;
+                current = forward ? current->nextSiblingBox() : current->previousSiblingBox();
+            if (current && current->style()->boxOrdinalGroup() > lastOrdinal)
+                lastOrdinal = current->style()->boxOrdinalGroup();
+        } while (!current || current->style()->boxOrdinalGroup() != currentOrdinal ||
+                 current->style()->visibility() == COLLAPSE);
+        return current;
     }
 
 private:
-    RenderFlexibleBox* m_box;
-    RenderBox* m_currentChild;
-    bool m_forward;
-    unsigned int m_currentOrdinal;
-    unsigned int m_lastOrdinal;
+    RenderFlexibleBox* box;
+    RenderBox* current;
+    bool forward;
+    unsigned int currentOrdinal;
+    unsigned int lastOrdinal;
 };
-
+    
 RenderFlexibleBox::RenderFlexibleBox(Node* node)
-    : RenderBlock(node)
+:RenderBlock(node)
 {
     setChildrenInline(false); // All of our children must be block-level
     m_flexingChildren = m_stretchingChildren = false;
@@ -119,48 +119,54 @@
 {
 }
 
-static int marginWidthForChild(RenderBox* child)
-{
-    // A margin basically has three types: fixed, percentage, and auto (variable).
-    // Auto and percentage margins simply become 0 when computing min/max width.
-    // Fixed margins can be added in as is.
-    Length marginLeft = child->style()->marginLeft();
-    Length marginRight = child->style()->marginRight();
-    int margin = 0;
-    if (marginLeft.isFixed())
-        margin += marginLeft.value();
-    if (marginRight.isFixed())
-        margin += marginRight.value();
-    return margin;
-}
-
 void RenderFlexibleBox::calcHorizontalPrefWidths()
 {
     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
-        // Positioned children and collapsed children don't affect the min/max width.
+        // positioned children don't affect the minmaxwidth
         if (child->isPositioned() || child->style()->visibility() == COLLAPSE)
             continue;
 
-        int margin = marginWidthForChild(child);
+        // A margin basically has three types: fixed, percentage, and auto (variable).
+        // Auto and percentage margins simply become 0 when computing min/max width.
+        // Fixed margins can be added in as is.
+        Length ml = child->style()->marginLeft();
+        Length mr = child->style()->marginRight();
+        int margin = 0, marginLeft = 0, marginRight = 0;
+        if (ml.isFixed())
+            marginLeft += ml.value();
+        if (mr.isFixed())
+            marginRight += mr.value();
+        margin = marginLeft + marginRight;
+
         m_minPreferredLogicalWidth += child->minPreferredLogicalWidth() + margin;
         m_maxPreferredLogicalWidth += child->maxPreferredLogicalWidth() + margin;
-    }
+    }    
 }
 
 void RenderFlexibleBox::calcVerticalPrefWidths()
 {
     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
-        // Positioned children and collapsed children don't affect the min/max width.
+        // Positioned children and collapsed children don't affect the min/max width
         if (child->isPositioned() || child->style()->visibility() == COLLAPSE)
             continue;
 
-        int margin = marginWidthForChild(child);
-        int width = child->minPreferredLogicalWidth() + margin;
-        m_minPreferredLogicalWidth = max(width, m_minPreferredLogicalWidth);
-
-        width = child->maxPreferredLogicalWidth() + margin;
-        m_maxPreferredLogicalWidth = max(width, m_maxPreferredLogicalWidth);
-    }
+        // A margin basically has three types: fixed, percentage, and auto (variable).
+        // Auto/percentage margins simply become 0 when computing min/max width.
+        // Fixed margins can be added in as is.
+        Length ml = child->style()->marginLeft();
+        Length mr = child->style()->marginRight();
+        int margin = 0;
+        if (ml.isFixed())
+            margin += ml.value();
+        if (mr.isFixed())
+            margin += mr.value();
+        
+        int w = child->minPreferredLogicalWidth() + margin;
+        m_minPreferredLogicalWidth = max(w, m_minPreferredLogicalWidth);
+        
+        w = child->maxPreferredLogicalWidth() + margin;
+        m_maxPreferredLogicalWidth = max(w, m_maxPreferredLogicalWidth);
+    }    
 }
 
 void RenderFlexibleBox::computePreferredLogicalWidths()
@@ -191,7 +197,7 @@
         m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->minWidth().value()));
         m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->minWidth().value()));
     }
-
+    
     if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
         m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->maxWidth().value()));
         m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->maxWidth().value()));
@@ -216,10 +222,10 @@
 
     int previousWidth = width();
     int previousHeight = height();
-
+    
     computeLogicalWidth();
     computeLogicalHeight();
-
+    
     m_overflow.clear();
 
     if (previousWidth != width() || previousHeight != height() ||
@@ -274,7 +280,7 @@
         setMaxMarginBeforeValues(pos, neg);
         setMaxMarginAfterValues(0, 0);
     }
-
+    
     computeOverflow(oldClientAfterEdge);
 
     statePusher.pop();
@@ -291,14 +297,15 @@
 
     // Repaint with our new bounds if they are different from our old bounds.
     repainter.repaintAfterLayout();
-
+    
     setNeedsLayout(false);
 }
 
 // The first walk over our kids is to find out if we have any flexible children.
 static void gatherFlexChildrenInfo(FlexBoxIterator& iterator, bool relayoutChildren, unsigned int& highestFlexGroup, unsigned int& lowestFlexGroup, bool& haveFlex)
 {
-    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+    RenderBox* child = iterator.first();
+    while (child) {
         // Check to see if this child flexes.
         if (!child->isPositioned() && child->style()->boxFlex() > 0.0f) {
             // We always have to lay out flexible objects again, since the flex distribution
@@ -315,6 +322,7 @@
             if (flexGroup > highestFlexGroup)
                 highestFlexGroup = flexGroup;
         }
+        child = iterator.next();
     }
 }
 
@@ -335,6 +343,8 @@
     bool haveFlex = false;
     gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex);
 
+    RenderBox* child;
+
     RenderBlock::startDelayUpdateScrollInfo();
 
     // We do 2 passes.  The first pass is simply to lay everyone out at
@@ -344,28 +354,31 @@
         setHeight(yPos);
 
         xPos = borderLeft() + paddingLeft();
-
+                
         // Our first pass is done without flexing.  We simply lay the children
         // out within the box.  We have to do a layout first in order to determine
         // our box's intrinsic height.
         int maxAscent = 0, maxDescent = 0;
-        for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+        child = iterator.first();
+        while (child) {
             // make sure we relayout children if we need it.
             if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())))
                 child->setChildNeedsLayout(true, false);
-
-            if (child->isPositioned())
+            
+            if (child->isPositioned()) {
+                child = iterator.next();
                 continue;
-
+            }
+    
             // Compute the child's vertical margins.
             child->computeBlockDirectionMargins(this);
-
+    
             if (!child->needsLayout())
                 child->markForPaginationRelayoutIfNeeded();
 
             // Now do the layout.
             child->layoutIfNeeded();
-
+    
             // Update our height and overflow height.
             if (style()->boxAlign() == BBASELINE) {
                 int ascent = child->firstLineBoxBaseline();
@@ -373,35 +386,38 @@
                     ascent = child->height() + child->marginBottom();
                 ascent += child->marginTop();
                 int descent = (child->marginTop() + child->height() + child->marginBottom()) - ascent;
-
+                
                 // Update our maximum ascent.
                 maxAscent = max(maxAscent, ascent);
-
+                
                 // Update our maximum descent.
                 maxDescent = max(maxDescent, descent);
-
+                
                 // Now update our height.
                 setHeight(max(yPos + maxAscent + maxDescent, height()));
             }
             else
                 setHeight(max(height(), yPos + child->marginTop() + child->height() + child->marginBottom()));
-        }
 
+            child = iterator.next();
+        }
+        
         if (!iterator.first() && hasLineIfEmpty())
             setHeight(height() + lineHeight(true, style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
-
+        
         setHeight(height() + toAdd);
-
+        
         oldHeight = height();
         computeLogicalHeight();
 
         relayoutChildren = false;
         if (oldHeight != height())
             heightSpecified = true;
-
+        
         // Now that our height is actually known, we can place our boxes.
         m_stretchingChildren = (style()->boxAlign() == BSTRETCH);
-        for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+        child = iterator.first();
+        while (child) {
             if (child->isPositioned()) {
                 child->containingBlock()->insertPositionedObject(child);
                 RenderLayer* childLayer = child->layer();
@@ -411,9 +427,10 @@
                     if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
                         child->setChildNeedsLayout(true, false);
                 }
+                child = iterator.next();
                 continue;
             }
-
+    
             // We need to see if this child's height has changed, since we make block elements
             // fill the height of a containing box by default.
             // Now do a layout.
@@ -421,18 +438,18 @@
             child->computeLogicalHeight();
             if (oldChildHeight != child->height())
                 child->setChildNeedsLayout(true, false);
-
+                
             if (!child->needsLayout())
                 child->markForPaginationRelayoutIfNeeded();
 
             child->layoutIfNeeded();
-
+    
             // We can place the child now, using our value of box-align.
             xPos += child->marginLeft();
             int childY = yPos;
             switch (style()->boxAlign()) {
                 case BCENTER:
-                    childY += child->marginTop() + max(0, (contentHeight() - (child->height() + child->marginTop() + child->marginBottom())) / 2);
+                    childY += child->marginTop() + max(0, (contentHeight() - (child->height() + child->marginTop() + child->marginBottom()))/2);
                     break;
                 case BBASELINE: {
                     int ascent = child->firstLineBoxBaseline();
@@ -451,12 +468,14 @@
             }
 
             placeChild(child, xPos, childY);
-
+            
             xPos += child->width() + child->marginRight();
+    
+            child = iterator.next();
         }
 
         remainingSpace = borderLeft() + paddingLeft() + contentWidth() - xPos;
-
+        
         m_stretchingChildren = false;
         if (m_flexingChildren)
             haveFlex = false; // We're done.
@@ -481,20 +500,24 @@
                     // forces a totalFlex recomputation).
                     int groupRemainingSpaceAtBeginning = groupRemainingSpace;
                     float totalFlex = 0.0f;
-                    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+                    child = iterator.first();
+                    while (child) {
                         if (allowedChildFlex(child, expanding, i))
                             totalFlex += child->style()->boxFlex();
+                        child = iterator.next();
                     }
+                    child = iterator.first();
                     int spaceAvailableThisPass = groupRemainingSpace;
-                    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+                    while (child) {
                         int allowedFlex = allowedChildFlex(child, expanding, i);
                         if (allowedFlex) {
                             int projectedFlex = (allowedFlex == INT_MAX) ? allowedFlex : (int)(allowedFlex * (totalFlex / child->style()->boxFlex()));
                             spaceAvailableThisPass = expanding ? min(spaceAvailableThisPass, projectedFlex) : max(spaceAvailableThisPass, projectedFlex);
                         }
+                        child = iterator.next();
                     }
 
-                    // The flex groups may not have any flexible objects this time around.
+                    // The flex groups may not have any flexible objects this time around. 
                     if (!spaceAvailableThisPass || totalFlex == 0.0f) {
                         // If we just couldn't grow/shrink any more, then it's time to transition to the next flex group.
                         groupRemainingSpace = 0;
@@ -502,7 +525,8 @@
                     }
 
                     // Now distribute the space to objects.
-                    for (RenderBox* child = iterator.first(); child && spaceAvailableThisPass && totalFlex; child = iterator.next()) {
+                    child = iterator.first();
+                    while (child && spaceAvailableThisPass && totalFlex) {
                         if (allowedChildFlex(child, expanding, i)) {
                             int spaceAdd = (int)(spaceAvailableThisPass * (child->style()->boxFlex()/totalFlex));
                             if (spaceAdd) {
@@ -514,14 +538,16 @@
                             spaceAvailableThisPass -= spaceAdd;
                             remainingSpace -= spaceAdd;
                             groupRemainingSpace -= spaceAdd;
-
+                            
                             totalFlex -= child->style()->boxFlex();
                         }
+                        child = iterator.next();
                     }
                     if (groupRemainingSpace == groupRemainingSpaceAtBeginning) {
-                        // This is not advancing, avoid getting stuck by distributing the remaining pixels.
+                        // this is not advancing, avoid getting stuck by distributing the remaining pixels
+                        child = iterator.first();
                         int spaceAdd = groupRemainingSpace > 0 ? 1 : -1;
-                        for (RenderBox* child = iterator.first(); child && groupRemainingSpace; child = iterator.next()) {
+                        while (child && groupRemainingSpace) {
                             if (allowedChildFlex(child, expanding, i)) {
                                 child->setOverrideSize(child->overrideWidth() + spaceAdd);
                                 m_flexingChildren = true;
@@ -529,6 +555,7 @@
                                 remainingSpace -= spaceAdd;
                                 groupRemainingSpace -= spaceAdd;
                             }
+                            child = iterator.next();
                         }
                     }
                 } while (groupRemainingSpace);
@@ -551,47 +578,59 @@
         if (style()->boxPack() == BJUSTIFY) {
             // Determine the total number of children.
             int totalChildren = 0;
-            for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
-                if (child->isPositioned())
+            child = iterator.first();
+            while (child) {
+                if (child->isPositioned()) {
+                    child = iterator.next();
                     continue;
-                ++totalChildren;
+                }
+                totalChildren++;
+                child = iterator.next();
             }
 
             // Iterate over the children and space them out according to the
             // justification level.
             if (totalChildren > 1) {
-                --totalChildren;
+                totalChildren--;
                 bool firstChild = true;
-                for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
-                    if (child->isPositioned())
+                child = iterator.first();
+                while (child) {
+                    if (child->isPositioned()) {
+                        child = iterator.next();
                         continue;
+                    }
 
                     if (firstChild) {
                         firstChild = false;
+                        child = iterator.next();
                         continue;
                     }
 
                     offset += remainingSpace/totalChildren;
                     remainingSpace -= (remainingSpace/totalChildren);
-                    --totalChildren;
+                    totalChildren--;
 
-                    placeChild(child, child->x() + offset, child->y());
+                    placeChild(child, child->x()+offset, child->y());
+                    child = iterator.next();
                 }
             }
         } else {
             if (style()->boxPack() == BCENTER)
-                offset += remainingSpace / 2;
+                offset += remainingSpace/2;
             else // END for LTR, START for RTL
                 offset += remainingSpace;
-            for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
-                if (child->isPositioned())
+            child = iterator.first();
+            while (child) {
+                if (child->isPositioned()) {
+                    child = iterator.next();
                     continue;
-
-                placeChild(child, child->x() + offset, child->y());
+                }
+                placeChild(child, child->x()+offset, child->y());
+                child = iterator.next();
             }
         }
     }
-
+    
     // So that the computeLogicalHeight in layoutBlock() knows to relayout positioned objects because of
     // a height change, we revert our height back to the intrinsic height before returning.
     if (heightSpecified)
@@ -616,6 +655,8 @@
     bool haveFlex = false;
     gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex);
 
+    RenderBox* child;
+
     // We confine the line clamp ugliness to vertical flexible boxes (thus keeping it out of
     // mainstream block layout); this is not really part of the XUL box model.
     bool haveLineClamp = !style()->lineClamp().isNone();
@@ -632,11 +673,12 @@
         setHeight(borderTop() + paddingTop());
         int minHeight = height() + toAdd;
 
-        for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
-            // Make sure we relayout children if we need it.
+        child = iterator.first();
+        while (child) {
+            // make sure we relayout children if we need it.
             if (!haveLineClamp && (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))))
                 child->setChildNeedsLayout(true, false);
-
+    
             if (child->isPositioned()) {
                 child->containingBlock()->insertPositionedObject(child);
                 RenderLayer* childLayer = child->layer();
@@ -646,27 +688,28 @@
                     if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
                         child->setChildNeedsLayout(true, false);
                 }
+                child = iterator.next();
                 continue;
-            }
-
+            } 
+    
             // Compute the child's vertical margins.
             child->computeBlockDirectionMargins(this);
-
+    
             // Add in the child's marginTop to our height.
             setHeight(height() + child->marginTop());
-
+    
             if (!child->needsLayout())
                 child->markForPaginationRelayoutIfNeeded();
 
             // Now do a layout.
             child->layoutIfNeeded();
-
+    
             // We can place the child now, using our value of box-align.
             int childX = borderLeft() + paddingLeft();
             switch (style()->boxAlign()) {
                 case BCENTER:
                 case BBASELINE: // Baseline just maps to center for vertical boxes
-                    childX += child->marginLeft() + max(0, (contentWidth() - (child->width() + child->marginLeft() + child->marginRight())) / 2);
+                    childX += child->marginLeft() + max(0, (contentWidth() - (child->width() + child->marginLeft() + child->marginRight()))/2);
                     break;
                 case BEND:
                     if (!style()->isLeftToRightDirection())
@@ -681,17 +724,19 @@
                         childX += contentWidth() - child->marginRight() - child->width();
                     break;
             }
-
+    
             // Place the child.
             placeChild(child, childX, height());
             setHeight(height() + child->height() + child->marginBottom());
+
+            child = iterator.next();
         }
 
         yPos = height();
-
+        
         if (!iterator.first() && hasLineIfEmpty())
             setHeight(height() + lineHeight(true, style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
-
+    
         setHeight(height() + toAdd);
 
         // Negative margins can cause our height to shrink below our minimal height (border/padding).
@@ -706,7 +751,7 @@
             heightSpecified = true;
 
         remainingSpace = borderTop() + paddingTop() + contentHeight() - yPos;
-
+        
         if (m_flexingChildren)
             haveFlex = false; // We're done.
         else if (haveFlex) {
@@ -730,28 +775,33 @@
                     // forces a totalFlex recomputation).
                     int groupRemainingSpaceAtBeginning = groupRemainingSpace;
                     float totalFlex = 0.0f;
-                    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+                    child = iterator.first();
+                    while (child) {
                         if (allowedChildFlex(child, expanding, i))
                             totalFlex += child->style()->boxFlex();
+                        child = iterator.next();
                     }
+                    child = iterator.first();
                     int spaceAvailableThisPass = groupRemainingSpace;
-                    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+                    while (child) {
                         int allowedFlex = allowedChildFlex(child, expanding, i);
                         if (allowedFlex) {
                             int projectedFlex = (allowedFlex == INT_MAX) ? allowedFlex : (int)(allowedFlex * (totalFlex / child->style()->boxFlex()));
                             spaceAvailableThisPass = expanding ? min(spaceAvailableThisPass, projectedFlex) : max(spaceAvailableThisPass, projectedFlex);
                         }
+                        child = iterator.next();
                     }
 
-                    // The flex groups may not have any flexible objects this time around.
+                    // The flex groups may not have any flexible objects this time around. 
                     if (!spaceAvailableThisPass || totalFlex == 0.0f) {
                         // If we just couldn't grow/shrink any more, then it's time to transition to the next flex group.
                         groupRemainingSpace = 0;
                         continue;
                     }
-
+            
                     // Now distribute the space to objects.
-                    for (RenderBox* child = iterator.first(); child && spaceAvailableThisPass && totalFlex; child = iterator.next()) {
+                    child = iterator.first();
+                    while (child && spaceAvailableThisPass && totalFlex) {
                         if (allowedChildFlex(child, expanding, i)) {
                             int spaceAdd = (int)(spaceAvailableThisPass * (child->style()->boxFlex()/totalFlex));
                             if (spaceAdd) {
@@ -763,14 +813,16 @@
                             spaceAvailableThisPass -= spaceAdd;
                             remainingSpace -= spaceAdd;
                             groupRemainingSpace -= spaceAdd;
-
+                            
                             totalFlex -= child->style()->boxFlex();
                         }
+                        child = iterator.next();
                     }
                     if (groupRemainingSpace == groupRemainingSpaceAtBeginning) {
-                        // This is not advancing, avoid getting stuck by distributing the remaining pixels.
+                        // this is not advancing, avoid getting stuck by distributing the remaining pixels
+                        child = iterator.first();
                         int spaceAdd = groupRemainingSpace > 0 ? 1 : -1;
-                        for (RenderBox* child = iterator.first(); child && groupRemainingSpace; child = iterator.next()) {
+                        while (child && groupRemainingSpace) {
                             if (allowedChildFlex(child, expanding, i)) {
                                 child->setOverrideSize(child->overrideHeight() + spaceAdd);
                                 m_flexingChildren = true;
@@ -778,6 +830,7 @@
                                 remainingSpace -= spaceAdd;
                                 groupRemainingSpace -= spaceAdd;
                             }
+                            child = iterator.next();
                         }
                     }
                 } while (groupRemainingSpace);
@@ -786,7 +839,7 @@
             // We didn't find any children that could grow.
             if (haveFlex && !m_flexingChildren)
                 haveFlex = false;
-        }
+        }        
     } while (haveFlex);
 
     RenderBlock::finishDelayUpdateScrollInfo();
@@ -797,42 +850,54 @@
         if (style()->boxPack() == BJUSTIFY) {
             // Determine the total number of children.
             int totalChildren = 0;
-            for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
-                if (child->isPositioned())
+            child = iterator.first();
+            while (child) {
+                if (child->isPositioned()) {
+                    child = iterator.next();
                     continue;
-
-                ++totalChildren;
+                }
+                totalChildren++;
+                child = iterator.next();
             }
-
+            
             // Iterate over the children and space them out according to the
             // justification level.
             if (totalChildren > 1) {
-                --totalChildren;
+                totalChildren--;
                 bool firstChild = true;
-                for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
-                    if (child->isPositioned())
+                child = iterator.first();
+                while (child) {
+                    if (child->isPositioned()) {
+                        child = iterator.next();
                         continue;
-
+                    }
+                    
                     if (firstChild) {
                         firstChild = false;
+                        child = iterator.next();
                         continue;
                     }
 
                     offset += remainingSpace/totalChildren;
                     remainingSpace -= (remainingSpace/totalChildren);
-                    --totalChildren;
-                    placeChild(child, child->x(), child->y() + offset);
+                    totalChildren--;
+                    placeChild(child, child->x(), child->y()+offset);
+                    child = iterator.next();
                 }
             }
         } else {
             if (style()->boxPack() == BCENTER)
-                offset += remainingSpace / 2;
+                offset += remainingSpace/2;
             else // END
                 offset += remainingSpace;
-            for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
-                if (child->isPositioned())
+            child = iterator.first();
+            while (child) {
+                if (child->isPositioned()) {
+                    child = iterator.next();
                     continue;
-                placeChild(child, child->x(), child->y() + offset);
+                }
+                placeChild(child, child->x(), child->y()+offset);
+                child = iterator.next();
             }
         }
     }
@@ -840,7 +905,7 @@
     // So that the computeLogicalHeight in layoutBlock() knows to relayout positioned objects because of
     // a height change, we revert our height back to the intrinsic height before returning.
     if (heightSpecified)
-        setHeight(oldHeight);
+        setHeight(oldHeight); 
 }
 
 void RenderFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool relayoutChildren)
@@ -875,16 +940,16 @@
     for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
         if (child->isPositioned() || !child->style()->height().isAuto() || !child->isBlockFlow())
             continue;
-
+        
         RenderBlock* blockChild = toRenderBlock(child);
         int lineCount = blockChild->lineCount();
         if (lineCount <= numVisibleLines)
             continue;
-
+        
         int newHeight = blockChild->heightForLineCount(numVisibleLines);
         if (newHeight == child->height())
             continue;
-
+        
         child->setChildNeedsLayout(true, false);
         child->setOverrideSize(newHeight);
         m_flexingChildren = true;
@@ -897,11 +962,11 @@
             continue;
 
         // Get the last line
-        RootInlineBox* lastLine = blockChild->lineAtIndex(lineCount - 1);
+        RootInlineBox* lastLine = blockChild->lineAtIndex(lineCount-1);
         if (!lastLine)
             continue;
 
-        RootInlineBox* lastVisibleLine = blockChild->lineAtIndex(numVisibleLines - 1);
+        RootInlineBox* lastVisibleLine = blockChild->lineAtIndex(numVisibleLines-1);
         if (!lastVisibleLine)
             continue;
 
@@ -910,7 +975,7 @@
         DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, (&horizontalEllipsis, 1));
         const Font& font = style(numVisibleLines == 1)->font();
 
-        // Get ellipsis width, and if the last child is an anchor, it will go after the ellipsis, so add in a space and the anchor width too
+        // Get ellipsis width, and if the last child is an anchor, it will go after the ellipsis, so add in a space and the anchor width too 
         int totalWidth;
         InlineBox* anchorBox = lastLine->lastChild();
         if (anchorBox && anchorBox->renderer()->style()->isLink())
@@ -923,7 +988,7 @@
         // See if this width can be accommodated on the last visible line
         RenderBlock* destBlock = toRenderBlock(lastVisibleLine->renderer());
         RenderBlock* srcBlock = toRenderBlock(lastLine->renderer());
-
+        
         // FIXME: Directions of src/destBlock could be different from our direction and from one another.
         if (!srcBlock->style()->isLeftToRightDirection())
             continue;
@@ -963,55 +1028,57 @@
 {
     if (child->isPositioned() || child->style()->boxFlex() == 0.0f || child->style()->boxFlexGroup() != group)
         return 0;
-
+                        
     if (expanding) {
         if (isHorizontal()) {
             // FIXME: For now just handle fixed values.
-            int maxWidth = INT_MAX;
-            int width = child->overrideWidth() - child->borderAndPaddingWidth();
-            if (!child->style()->maxWidth().isUndefined() && child->style()->maxWidth().isFixed())
-                maxWidth = child->style()->maxWidth().value();
+            int maxW = INT_MAX;
+            int w = child->overrideWidth() - child->borderAndPaddingWidth();
+            if (!child->style()->maxWidth().isUndefined() &&
+                child->style()->maxWidth().isFixed())
+                maxW = child->style()->maxWidth().value();
             else if (child->style()->maxWidth().type() == Intrinsic)
-                maxWidth = child->maxPreferredLogicalWidth();
+                maxW = child->maxPreferredLogicalWidth();
             else if (child->style()->maxWidth().type() == MinIntrinsic)
-                maxWidth = child->minPreferredLogicalWidth();
-            if (maxWidth == INT_MAX)
-                return maxWidth;
-            return max(0, maxWidth - width);
+                maxW = child->minPreferredLogicalWidth();
+            if (maxW == INT_MAX)
+                return maxW;
+            return max(0, maxW - w);
         } else {
             // FIXME: For now just handle fixed values.
-            int maxHeight = INT_MAX;
-            int height = child->overrideHeight() - child->borderAndPaddingHeight();
-            if (!child->style()->maxHeight().isUndefined() && child->style()->maxHeight().isFixed())
-                maxHeight = child->style()->maxHeight().value();
-            if (maxHeight == INT_MAX)
-                return maxHeight;
-            return max(0, maxHeight - height);
+            int maxH = INT_MAX;
+            int h = child->overrideHeight() - child->borderAndPaddingHeight();
+            if (!child->style()->maxHeight().isUndefined() &&
+                child->style()->maxHeight().isFixed())
+                maxH = child->style()->maxHeight().value();
+            if (maxH == INT_MAX)
+                return maxH;
+            return max(0, maxH - h);
         }
     }
 
     // FIXME: For now just handle fixed values.
     if (isHorizontal()) {
-        int minWidth = child->minPreferredLogicalWidth();
-        int width = child->overrideWidth() - child->borderAndPaddingWidth();
+        int minW = child->minPreferredLogicalWidth();
+        int w = child->overrideWidth() - child->borderAndPaddingWidth();
         if (child->style()->minWidth().isFixed())
-            minWidth = child->style()->minWidth().value();
+            minW = child->style()->minWidth().value();
         else if (child->style()->minWidth().type() == Intrinsic)
-            minWidth = child->maxPreferredLogicalWidth();
+            minW = child->maxPreferredLogicalWidth();
         else if (child->style()->minWidth().type() == MinIntrinsic)
-            minWidth = child->minPreferredLogicalWidth();
-
-        int allowedShrinkage = min(0, minWidth - width);
+            minW = child->minPreferredLogicalWidth();
+            
+        int allowedShrinkage = min(0, minW - w);
         return allowedShrinkage;
     } else {
         if (child->style()->minHeight().isFixed()) {
-            int minHeight = child->style()->minHeight().value();
-            int height = child->overrideHeight() - child->borderAndPaddingHeight();
-            int allowedShrinkage = min(0, minHeight - height);
+            int minH = child->style()->minHeight().value();
+            int h = child->overrideHeight() - child->borderAndPaddingHeight();
+            int allowedShrinkage = min(0, minH - h);
             return allowedShrinkage;
         }
     }
-
+    
     return 0;
 }
 
diff --git a/Source/WebCore/rendering/RenderFrame.cpp b/Source/WebCore/rendering/RenderFrame.cpp
index 0ae6eda..4b1444b 100644
--- a/Source/WebCore/rendering/RenderFrame.cpp
+++ b/Source/WebCore/rendering/RenderFrame.cpp
@@ -64,12 +64,7 @@
 {
     FrameView* view = static_cast<FrameView*>(widget());
     RenderView* root = view ? view->frame()->contentRenderer() : 0;
-
-    // Do not expand frames which has zero width or height
     if (!width() || !height() || !root) {
-        updateWidgetPosition();
-        if (view)
-            view->layout();
         setNeedsLayout(false);
         return;
     }
@@ -80,17 +75,14 @@
         return;
     }
 
-    // Update the dimensions to get the correct width and height
-    updateWidgetPosition();
-    if (root->preferredLogicalWidthsDirty())
-        root->computePreferredLogicalWidths();
+    int layoutWidth = width();
 
-    // Expand the frame by setting frame height = content height
     setWidth(max(view->contentsWidth() + borderAndPaddingWidth(), width()));
     setHeight(max(view->contentsHeight() + borderAndPaddingHeight(), height()));
 
-    // Update one more time
-    updateWidgetPosition();
+    // Trigger a layout of the FrameView which will schedule a relayout of this RenderFrame.
+    if (layoutWidth < width())
+        view->layout();
 
     setNeedsLayout(false);
 }
diff --git a/Source/WebCore/rendering/RenderHTMLCanvas.cpp b/Source/WebCore/rendering/RenderHTMLCanvas.cpp
index 03b406b..de2a2c1 100644
--- a/Source/WebCore/rendering/RenderHTMLCanvas.cpp
+++ b/Source/WebCore/rendering/RenderHTMLCanvas.cpp
@@ -47,13 +47,6 @@
 
 bool RenderHTMLCanvas::requiresLayer() const
 {
-#if PLATFORM(ANDROID)
-    // All Canvas are drawn on their own composited layer
-    // This improves performances a lot (as this simplify
-    // the repaint/inval chain dealing with the PictureSet)
-    return true;
-#endif
-
     if (RenderReplaced::requiresLayer())
         return true;
     
diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp
index b6662f6..cdc4c05 100644
--- a/Source/WebCore/rendering/RenderLayer.cpp
+++ b/Source/WebCore/rendering/RenderLayer.cpp
@@ -64,7 +64,6 @@
 #include "HTMLNames.h"
 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
 #include "HTMLTextAreaElement.h"
-#include "GraphicsLayerAndroid.h"
 #endif
 #include "HitTestRequest.h"
 #include "HitTestResult.h"
@@ -1390,27 +1389,11 @@
         view->updateWidgetPositions();
     }
 
-#if PLATFORM(ANDROID)
-    GraphicsLayerAndroid* backingLayer = 0;
-    bool scrollableContent = false;
-#endif
-
 #if USE(ACCELERATED_COMPOSITING)
     if (compositor()->inCompositingMode()) {
         // Our stacking context is guaranteed to contain all of our descendants that may need
         // repositioning, so update compositing layers from there.
-#if ENABLE(ANDROID_OVERFLOW_SCROLL)
-        if (view && backing() && backing()->graphicsLayer()) {
-            backingLayer = static_cast<GraphicsLayerAndroid*>(backing()->graphicsLayer());
-            scrollableContent = backingLayer->contentLayer()
-                && backingLayer->contentLayer()->contentIsScrollable();
-        }
-        // If we have a scrollable content, no need to do this
-        RenderLayer* compositingAncestor = enclosingCompositingLayer();
-        if (!scrollableContent && compositingAncestor) {
-#else
         if (RenderLayer* compositingAncestor = stackingContext()->enclosingCompositingLayer()) {
-#endif
             if (compositor()->compositingConsultsOverlap())
                 compositor()->updateCompositingLayers(CompositingUpdateOnScroll, compositingAncestor);
             else {
@@ -1429,30 +1412,25 @@
         // The caret rect needs to be invalidated after scrolling
         frame->selection()->setCaretRectNeedsUpdate();
 
-#if !ENABLE(ANDROID_OVERFLOW_SCROLL)
         FloatQuad quadForFakeMouseMoveEvent = FloatQuad(rectForRepaint);
         if (repaintContainer)
             quadForFakeMouseMoveEvent = repaintContainer->localToAbsoluteQuad(quadForFakeMouseMoveEvent);
         frame->eventHandler()->dispatchFakeMouseMoveEventSoonInQuad(quadForFakeMouseMoveEvent);
-#endif
     }
 
     // Just schedule a full repaint of our object.
 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
     // On android, scrollable areas are put on composited layers, so we
     // do not need to repaint simply because we are scrolling
-    if (view && !(hasOverflowScroll() || scrollableContent))
+    if (view && !hasOverflowScroll())
         renderer()->repaintUsingContainer(repaintContainer, rectForRepaint);
-    if (backingLayer && (hasOverflowScroll() || scrollableContent))
-        backingLayer->updateScrollOffset();
 #else
     if (view)
         renderer()->repaintUsingContainer(repaintContainer, rectForRepaint);
 #endif
 
     // Schedule the scroll DOM event.
-    if (renderer()->node())
-        renderer()->node()->document()->eventQueue()->enqueueOrDispatchScrollEvent(renderer()->node(), EventQueue::ScrollEventElementTarget);
+    renderer()->node()->document()->eventQueue()->enqueueOrDispatchScrollEvent(renderer()->node(), EventQueue::ScrollEventElementTarget);
 }
 
 void RenderLayer::scrollRectToVisible(const IntRect& rect, bool scrollToAnchor, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
@@ -3154,6 +3132,14 @@
         candidateLayer = hitLayer;
     }
 
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+    if (hasOverflowParent()) {
+        ClipRects clipRects;
+        calculateClipRects(rootLayer, clipRects, useTemporaryClipRects);
+        fgRect.intersect(clipRects.hitTestClip());
+        bgRect.intersect(clipRects.hitTestClip());
+    }
+#endif
     // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
     if (fgRect.intersects(hitTestArea) && isSelfPaintingLayer()) {
         // Hit test with a temporary HitTestResult, because we only want to commit to 'result' if we know we're frontmost.
@@ -3445,6 +3431,8 @@
         if (renderer()->hasOverflowClip()) {
             IntRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(x, y, relevancy);
 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
+            clipRects.setHitTestClip(intersection(clipRects.fixed() ? clipRects.fixedClipRect()
+                    : newOverflowClip, clipRects.hitTestClip()));
             if (hasOverflowScroll()) {
                 RenderBox* box = toRenderBox(renderer());
                 newOverflowClip =
diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h
index ceb9026..02ab8e9 100644
--- a/Source/WebCore/rendering/RenderLayer.h
+++ b/Source/WebCore/rendering/RenderLayer.h
@@ -80,6 +80,9 @@
         : m_overflowClipRect(r)
         , m_fixedClipRect(r)
         , m_posClipRect(r)
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+        , m_hitTestClip(r)
+#endif
         , m_refCnt(0)
         , m_fixed(false)
     {
@@ -89,6 +92,9 @@
         : m_overflowClipRect(other.overflowClipRect())
         , m_fixedClipRect(other.fixedClipRect())
         , m_posClipRect(other.posClipRect())
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+        , m_hitTestClip(other.hitTestClip())
+#endif
         , m_refCnt(0)
         , m_fixed(other.fixed())
     {
@@ -99,6 +105,9 @@
         m_overflowClipRect = r;
         m_fixedClipRect = r;
         m_posClipRect = r;
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+        m_hitTestClip = r;
+#endif
         m_fixed = false;
     }
     
@@ -110,6 +119,10 @@
 
     const IntRect& posClipRect() const { return m_posClipRect; }
     void setPosClipRect(const IntRect& r) { m_posClipRect = r; }
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+    const IntRect& hitTestClip() const { return m_hitTestClip; }
+    void setHitTestClip(const IntRect& r) { m_hitTestClip = r; }
+#endif
 
     bool fixed() const { return m_fixed; }
     void setFixed(bool fixed) { m_fixed = fixed; }
@@ -130,6 +143,9 @@
         return m_overflowClipRect == other.overflowClipRect() &&
                m_fixedClipRect == other.fixedClipRect() &&
                m_posClipRect == other.posClipRect() &&
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+               m_hitTestClip == other.hitTestClip() &&
+#endif
                m_fixed == other.fixed();
     }
 
@@ -138,6 +154,9 @@
         m_overflowClipRect = other.overflowClipRect();
         m_fixedClipRect = other.fixedClipRect();
         m_posClipRect = other.posClipRect();
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+        m_hitTestClip = other.hitTestClip();
+#endif
         m_fixed = other.fixed();
         return *this;
     }
@@ -150,6 +169,9 @@
     IntRect m_overflowClipRect;
     IntRect m_fixedClipRect;
     IntRect m_posClipRect;
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+    IntRect m_hitTestClip;
+#endif
     unsigned m_refCnt : 31;
     bool m_fixed : 1;
 };
@@ -476,12 +498,6 @@
     bool hasOverflowScroll() const { return m_hasOverflowScroll; }
     bool hasOverflowParent() const;
 #endif
-#if PLATFORM(ANDROID)
-    bool intrinsicallyComposited() const { return m_intrinsicallyComposited; }
-    void setIntrinsicallyComposited(bool intrinsicallyComposited) {
-        m_intrinsicallyComposited = intrinsicallyComposited;
-    }
-#endif
 
 private:
     // The normal operator new is disallowed on all render objects.
@@ -735,9 +751,6 @@
     bool m_shouldComposite : 1;
 #endif
 #endif
-#if PLATFORM(ANDROID)
-    bool m_intrinsicallyComposited : 1;
-#endif
 
     bool m_containsDirtyOverlayScrollbars : 1;
 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
diff --git a/Source/WebCore/rendering/RenderLayerBacking.cpp b/Source/WebCore/rendering/RenderLayerBacking.cpp
index c0c562a..6f56eca 100644
--- a/Source/WebCore/rendering/RenderLayerBacking.cpp
+++ b/Source/WebCore/rendering/RenderLayerBacking.cpp
@@ -1114,24 +1114,12 @@
 
     bool shouldPaint = (m_owningLayer->hasVisibleContent() || m_owningLayer->hasVisibleDescendant()) && m_owningLayer->isSelfPaintingLayer();
 
-#if PLATFORM(ANDROID)
-    if (shouldPaint && ((paintingPhase & GraphicsLayerPaintBackground)
-                        || (paintingPhase & GraphicsLayerPaintBackgroundDecorations))) {
-#else
     if (shouldPaint && (paintingPhase & GraphicsLayerPaintBackground)) {
-#endif
         // Paint our background first, before painting any child layers.
         // Establish the clip used to paint our background.
         setClip(context, paintDirtyRect, damageRect);
         
-#if PLATFORM(ANDROID)
-        PaintPhase phase = PaintPhaseBlockBackground;
-        if (paintingPhase & GraphicsLayerPaintBackgroundDecorations)
-            phase = PaintPhaseBlockBackgroundDecorations;
-        PaintInfo info(context, damageRect, phase, false, paintingRootForRenderer, 0);
-#else
         PaintInfo info(context, damageRect, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0);
-#endif
         renderer()->paint(info, tx, ty);
 
         // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.cpp b/Source/WebCore/rendering/RenderLayerCompositor.cpp
index f5dddc0..33bf2f7 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/Source/WebCore/rendering/RenderLayerCompositor.cpp
@@ -78,7 +78,7 @@
         : m_compositingAncestor(compAncestor)
         , m_subtreeIsCompositing(false)
 #if ENABLE(COMPOSITED_FIXED_ELEMENTS)
-        , m_positionedSibling(false)
+        , m_fixedSibling(false)
         , m_hasFixedElement(false)
 #endif
 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
@@ -92,12 +92,8 @@
     
     RenderLayer* m_compositingAncestor;
     bool m_subtreeIsCompositing;
-    // m_compositingBounds is only used in computeCompositingRequirements. It can be either the
-    // ancestor bounds or the bounds for the sibling layers which are above the composited layer.
-    // It is used to reject creating unnecesary layers.
-    IntRect m_compositingBounds;
 #if ENABLE(COMPOSITED_FIXED_ELEMENTS)
-    bool m_positionedSibling;
+    bool m_fixedSibling;
     bool m_hasFixedElement;
 #endif
 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
@@ -302,7 +298,6 @@
         bool layersChanged = false;
 
 #if ENABLE(COMPOSITED_FIXED_ELEMENTS)
-        compState.m_positionedSibling = false;
         compState.m_hasFixedElement = false;
 #endif
 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
@@ -352,11 +347,7 @@
 {
     bool layerChanged = false;
 
-#if ENABLE(ANDROID_OVERFLOW_SCROLL)
-    if (needsToBeComposited(layer) || layer->shouldComposite()) {
-#else
     if (needsToBeComposited(layer)) {
-#endif
         enableCompositingMode();
         
         // 3D transforms turn off the testing of overlap.
@@ -622,62 +613,53 @@
 
 #if ENABLE(COMPOSITED_FIXED_ELEMENTS)
 
-bool RenderLayerCompositor::checkForPositionedElements(Vector<RenderLayer*>* list)
+// to properly support z-index with composited fixed elements, we need to turn
+// layers following a fixed layer into compositing mode; but if a layer is fully
+// contained into a previous layer already composited (that is not the fixed
+// layer), we don't need to composite it. This saves up quite a bit on the
+// number of layers we have to composite.
+//
+bool RenderLayerCompositor::checkForFixedLayers(Vector<RenderLayer*>* list, bool stopAtFixedLayer)
 {
     int listSize = list->size();
     int haveFixedLayer = -1;
     bool fixedSibling = false;
-    bool positionedSibling = false;
-
-#if 0
-    // For absolute positioned elements, we need to check if they are followed
-    // by a composited element; if so, they also need to be composited, as the
-    // layer display rendering might be incorrect (absolute elements being
-    // removed from the flow).
-    for (int i = 0; i < listSize; ++i) {
-        RenderLayer* currentLayer = list->at(i);
-        if (!needsToBeComposited(currentLayer)
-            && !currentLayer->shouldComposite()
-            && currentLayer->renderer()->isPositioned()) {
-            positionedSibling = true;
-            // check if there is a composited layer later, if so we should be
-            // composited.
-            for (int j = i + 1; j < listSize; ++j) {
-                RenderLayer* layer = list->at(j);
-                if (needsToBeComposited(layer)) {
-                    currentLayer->setShouldComposite(true);
-                    break;
-                }
-            }
-            break;
-        }
-    }
-#endif
-
-    // If we find a fixed layer, let's mark all the following layers as being
-    // composited. The layers' surfaces will be merged if needed UI-side.
     for (int j = 0; j < listSize; ++j) {
         RenderLayer* currentLayer = list->at(j);
-
-        // clear the composited flag first
-        currentLayer->setShouldComposite(false);
-
         if (currentLayer->isFixed() && needsToBeComposited(currentLayer)) {
-            // Ignore fixed layers with a width or height or 1 or less...
-            IntRect currentLayerBounds = currentLayer->renderer()->localToAbsoluteQuad(
-                FloatRect(currentLayer->localBoundingBox())).enclosingBoundingBox();
-            if (currentLayerBounds.width() > 1 && currentLayerBounds.height() > 1) {
-                haveFixedLayer = j;
-                fixedSibling = true;
-            }
-            continue;
+            haveFixedLayer = j;
+            fixedSibling = true;
         }
+        IntRect currentLayerBounds = currentLayer->renderer()->localToAbsoluteQuad(
+            FloatRect(currentLayer->localBoundingBox())).enclosingBoundingBox();
+        if ((currentLayerBounds.width() <= 1
+            || currentLayerBounds.height() <= 1)
+            && haveFixedLayer == j) {
+            haveFixedLayer = -1;
+            fixedSibling = false;
+        }
+        if (haveFixedLayer != -1 && haveFixedLayer != j) {
+            bool needComposite = true;
+            int stop = 0;
+            if (stopAtFixedLayer)
+                stop = haveFixedLayer + 1;
 
-        if (haveFixedLayer != -1)
-            currentLayer->setShouldComposite(true);
+            for (int k = j - 1; k >= stop; --k) {
+                RenderLayer* aLayer = list->at(k);
+                if (aLayer && aLayer->renderer()) {
+                    IntRect bounds = aLayer->renderer()->localToAbsoluteQuad(
+                        FloatRect(aLayer->localBoundingBox())).enclosingBoundingBox();
+                    if (bounds.contains(currentLayerBounds)
+                        && needsToBeComposited(aLayer) && aLayer->isStackingContext()) {
+                        needComposite = false;
+                        break;
+                    }
+                }
+            }
+            currentLayer->setShouldComposite(needComposite);
+        }
     }
-
-    return positionedSibling || fixedSibling;
+    return fixedSibling;
 }
 
 #endif
@@ -696,12 +678,7 @@
     layer->updateLayerPosition();
     layer->updateZOrderLists();
     layer->updateNormalFlowList();
-#if PLATFORM(ANDROID)
-    RenderObject* renderer = layer->renderer();
-    bool intCom = requiresCompositingLayer(layer);
-    layer->setIntrinsicallyComposited(intCom);
-#endif
-
+    
     // Clear the flag
     layer->setHasCompositingDescendant(false);
     
@@ -716,33 +693,28 @@
         if (absBounds.isEmpty())
             absBounds.setSize(IntSize(1, 1));
         haveComputedBounds = true;
-        // If the current subtree is not compositing, and the layer is fully inside the current compositing bounnds,
-        // there is no need to do the overlap test. This reduces the total number of the composited layers.
-        if (compositingState.m_subtreeIsCompositing || !compositingState.m_compositingBounds.contains(absBounds))
-            mustOverlapCompositedLayers = overlapsCompositedLayers(*overlapMap, absBounds);
+        mustOverlapCompositedLayers = overlapsCompositedLayers(*overlapMap, absBounds);
     }
-
+    
+#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
+    if (compositingState.m_fixedSibling)
+        layer->setMustOverlapCompositedLayers(layer->shouldComposite());
+    else
+        layer->setMustOverlapCompositedLayers(mustOverlapCompositedLayers);
+#else
     layer->setMustOverlapCompositedLayers(mustOverlapCompositedLayers);
-
+#endif
+    
     // The children of this layer don't need to composite, unless there is
     // a compositing layer among them, so start by inheriting the compositing
     // ancestor with m_subtreeIsCompositing set to false.
     CompositingState childState(compositingState.m_compositingAncestor);
-    if (compositingState.m_subtreeIsCompositing)
-        childState.m_compositingBounds = absBounds;
-    else
-        childState.m_compositingBounds = compositingState.m_compositingBounds;
 #ifndef NDEBUG
     ++childState.m_depth;
 #endif
 
     bool willBeComposited = needsToBeComposited(layer);
 
-#if 0 && ENABLE(COMPOSITED_FIXED_ELEMENTS)
-    willBeComposited |= layer->shouldComposite();
-    layer->setMustOverlapCompositedLayers(layer->shouldComposite());
-#endif
-
 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
     // tell the parent it has scrollable descendants.
     if (layer->hasOverflowScroll())
@@ -757,7 +729,6 @@
         compositingState.m_subtreeIsCompositing = true;
         // This layer now acts as the ancestor for kids.
         childState.m_compositingAncestor = layer;
-        childState.m_compositingBounds = absBounds;
         if (overlapMap)
             addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds);
     }
@@ -775,9 +746,9 @@
         if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
             size_t listSize = negZOrderList->size();
 #if ENABLE(COMPOSITED_FIXED_ELEMENTS)
-            childState.m_positionedSibling = compositingState.m_positionedSibling;
-            if (checkForPositionedElements(negZOrderList))
-                childState.m_positionedSibling = true;
+            childState.m_fixedSibling = compositingState.m_fixedSibling;
+            if (checkForFixedLayers(negZOrderList, false))
+                childState.m_fixedSibling = true;
 #endif
             for (size_t i = 0; i < listSize; ++i) {
                 RenderLayer* curLayer = negZOrderList->at(i);
@@ -812,9 +783,9 @@
     if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
         size_t listSize = normalFlowList->size();
 #if ENABLE(COMPOSITED_FIXED_ELEMENTS)
-        childState.m_positionedSibling = compositingState.m_positionedSibling;
-        if (checkForPositionedElements(normalFlowList))
-            childState.m_positionedSibling = true;
+        childState.m_fixedSibling = compositingState.m_fixedSibling;
+        if (checkForFixedLayers(normalFlowList, true))
+            childState.m_fixedSibling = true;
 #endif
         for (size_t i = 0; i < listSize; ++i) {
             RenderLayer* curLayer = normalFlowList->at(i);
@@ -826,9 +797,9 @@
         if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
             size_t listSize = posZOrderList->size();
 #if ENABLE(COMPOSITED_FIXED_ELEMENTS)
-            childState.m_positionedSibling = compositingState.m_positionedSibling;
-            if (checkForPositionedElements(posZOrderList))
-                childState.m_positionedSibling = true;
+            childState.m_fixedSibling = compositingState.m_fixedSibling;
+            if (checkForFixedLayers(posZOrderList, true))
+                childState.m_fixedSibling = true;
 #endif
             for (size_t i = 0; i < listSize; ++i) {
                 RenderLayer* curLayer = posZOrderList->at(i);
@@ -866,8 +837,6 @@
 #if ENABLE(COMPOSITED_FIXED_ELEMENTS)
     if (childState.m_hasFixedElement)
         compositingState.m_hasFixedElement = true;
-    if (childState.m_positionedSibling)
-        compositingState.m_positionedSibling = true;
 #endif
 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
     if (childState.m_hasScrollableElement)
@@ -890,9 +859,7 @@
 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
     // We also need to check that we don't have a scrollable layer, as this
     // would not have set the m_subtreeIsCompositing flag
-    if (layer->isRootLayer() && !childState.m_subtreeIsCompositing
-        && !childState.m_hasScrollableElement && !childState.m_positionedSibling && !childState.m_hasFixedElement
-        && !requiresCompositingLayer(layer) && !m_forceCompositingMode) {
+    if (layer->isRootLayer() && !childState.m_subtreeIsCompositing && !childState.m_hasScrollableElement && !childState.m_hasFixedElement && !requiresCompositingLayer(layer) && !m_forceCompositingMode) {
 #else
     if (layer->isRootLayer() && !childState.m_subtreeIsCompositing && !requiresCompositingLayer(layer) && !m_forceCompositingMode) {
 #endif
@@ -1431,13 +1398,6 @@
     if (layer->isFixed())
         return true;
 #endif
-
-    if (layer->renderer()->isCanvas())
-        return true;
-
-    if (layer->renderer()->style()->hasFixedBackgroundImage())
-        return true;
-
     return false;
 }
 #endif
diff --git a/Source/WebCore/rendering/RenderLayerCompositor.h b/Source/WebCore/rendering/RenderLayerCompositor.h
index 2de1037..813e265 100644
--- a/Source/WebCore/rendering/RenderLayerCompositor.h
+++ b/Source/WebCore/rendering/RenderLayerCompositor.h
@@ -219,7 +219,7 @@
     void updateCompositingLayersTimerFired(Timer<RenderLayerCompositor>*);
 
 #if ENABLE(COMPOSITED_FIXED_ELEMENTS)
-    bool checkForPositionedElements(Vector<RenderLayer*>* list);
+    bool checkForFixedLayers(Vector<RenderLayer*>* list, bool stopAtFixedLayer);
 #endif
 
     // Returns true if any layer's compositing changed
diff --git a/Source/WebCore/rendering/RenderObject.cpp b/Source/WebCore/rendering/RenderObject.cpp
index 012427c..8caef04 100644
--- a/Source/WebCore/rendering/RenderObject.cpp
+++ b/Source/WebCore/rendering/RenderObject.cpp
@@ -1787,23 +1787,6 @@
     }
 }
 
-void RenderObject::propagateStyleToAnonymousChildren()
-{
-    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
-        if (child->isAnonymous() && !child->isBeforeOrAfterContent()) {
-            RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style());
-            if (style()->specifiesColumns()) {
-                if (child->style()->specifiesColumns())
-                    newStyle->inheritColumnPropertiesFrom(style());
-                if (child->style()->columnSpan())
-                    newStyle->setColumnSpan(true);
-            }
-            newStyle->setDisplay(child->style()->display());
-            child->setStyle(newStyle.release());
-        }
-    }
-}
-
 void RenderObject::updateFillImages(const FillLayer* oldLayers, const FillLayer* newLayers)
 {
     // Optimize the common case
@@ -2046,10 +2029,6 @@
         while (o && o->style()->position() == StaticPosition && !o->isRenderView() && !(o->hasTransform() && o->isRenderBlock())) {
             if (repaintContainerSkipped && o == repaintContainer)
                 *repaintContainerSkipped = true;
-#if ENABLE(SVG)
-                if (o->isSVGForeignObject()) // foreignObject is the containing block for contents inside it
-                    break;
-#endif
             o = o->parent();
         }
     }
diff --git a/Source/WebCore/rendering/RenderObject.h b/Source/WebCore/rendering/RenderObject.h
index 18086c9..005c453 100644
--- a/Source/WebCore/rendering/RenderObject.h
+++ b/Source/WebCore/rendering/RenderObject.h
@@ -312,10 +312,8 @@
 
     inline bool isBeforeContent() const;
     inline bool isAfterContent() const;
-    inline bool isBeforeOrAfterContent() const;
     static inline bool isBeforeContent(const RenderObject* obj) { return obj && obj->isBeforeContent(); }
     static inline bool isAfterContent(const RenderObject* obj) { return obj && obj->isAfterContent(); }
-    static inline bool isBeforeOrAfterContent(const RenderObject* obj) { return obj && obj->isBeforeOrAfterContent(); }
 
     bool childrenInline() const { return m_childrenInline; }
     void setChildrenInline(bool b = true) { m_childrenInline = b; }
@@ -778,7 +776,6 @@
     virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
     // Overrides should call the superclass at the start
     virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-    void propagateStyleToAnonymousChildren();
 
     void drawLineForBoxSide(GraphicsContext*, int x1, int y1, int x2, int y2, BoxSide,
                             Color, EBorderStyle, int adjbw1, int adjbw2, bool antialias = false);
@@ -920,11 +917,6 @@
     return true;
 }
 
-inline bool RenderObject::isBeforeOrAfterContent() const
-{
-    return isBeforeContent() || isAfterContent();
-}
-
 inline void RenderObject::setNeedsLayout(bool b, bool markParents)
 {
     bool alreadyNeededLayout = m_needsLayout;
diff --git a/Source/WebCore/rendering/RenderReplaced.cpp b/Source/WebCore/rendering/RenderReplaced.cpp
index 09a7944..c27d336 100644
--- a/Source/WebCore/rendering/RenderReplaced.cpp
+++ b/Source/WebCore/rendering/RenderReplaced.cpp
@@ -57,14 +57,6 @@
 {
 }
 
-void RenderReplaced::destroy()
-{
-    if (!documentBeingDestroyed() && parent())
-        parent()->dirtyLinesFromChangedChild(this);
-
-    RenderBox::destroy();
-}
-
 void RenderReplaced::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
 {
     RenderBox::styleDidChange(diff, oldStyle);
diff --git a/Source/WebCore/rendering/RenderReplaced.h b/Source/WebCore/rendering/RenderReplaced.h
index 29fc71c..d6ebba6 100644
--- a/Source/WebCore/rendering/RenderReplaced.h
+++ b/Source/WebCore/rendering/RenderReplaced.h
@@ -32,8 +32,6 @@
     RenderReplaced(Node*, const IntSize& intrinsicSize);
     virtual ~RenderReplaced();
 
-    virtual void destroy();
-
 protected:
     virtual void layout();
 
diff --git a/Source/WebCore/rendering/RenderRuby.cpp b/Source/WebCore/rendering/RenderRuby.cpp
index 41604d6..e0137de 100644
--- a/Source/WebCore/rendering/RenderRuby.cpp
+++ b/Source/WebCore/rendering/RenderRuby.cpp
@@ -119,12 +119,6 @@
 {
 }
 
-void RenderRubyAsInline::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
-{
-    RenderInline::styleDidChange(diff, oldStyle);
-    propagateStyleToAnonymousChildren();
-}
-
 void RenderRubyAsInline::addChild(RenderObject* child, RenderObject* beforeChild)
 {
     // Insert :before and :after content before/after the RenderRubyRun(s)
@@ -226,12 +220,6 @@
 {
 }
 
-void RenderRubyAsBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
-{
-    RenderBlock::styleDidChange(diff, oldStyle);
-    propagateStyleToAnonymousChildren();
-}
-
 void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild)
 {
     // Insert :before and :after content before/after the RenderRubyRun(s)
diff --git a/Source/WebCore/rendering/RenderRuby.h b/Source/WebCore/rendering/RenderRuby.h
index 2ab964c..24ac0db 100644
--- a/Source/WebCore/rendering/RenderRuby.h
+++ b/Source/WebCore/rendering/RenderRuby.h
@@ -59,9 +59,6 @@
     virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
     virtual void removeChild(RenderObject* child);
 
-protected:
-    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-
 private:
     virtual bool isRuby() const { return true; }
     virtual const char* renderName() const { return "RenderRuby (inline)"; }
@@ -78,9 +75,6 @@
     virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
     virtual void removeChild(RenderObject* child);
 
-protected:
-    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-
 private:
     virtual bool isRuby() const { return true; }
     virtual const char* renderName() const { return "RenderRuby (block)"; }
diff --git a/Source/WebCore/rendering/RenderTable.cpp b/Source/WebCore/rendering/RenderTable.cpp
index 072519e..e9db5ad 100644
--- a/Source/WebCore/rendering/RenderTable.cpp
+++ b/Source/WebCore/rendering/RenderTable.cpp
@@ -79,7 +79,6 @@
 void RenderTable::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
 {
     RenderBlock::styleDidChange(diff, oldStyle);
-    propagateStyleToAnonymousChildren();
 
     ETableLayout oldTableLayout = oldStyle ? oldStyle->tableLayout() : TAUTO;
 
diff --git a/Source/WebCore/rendering/RenderTableRow.cpp b/Source/WebCore/rendering/RenderTableRow.cpp
index 686bc3a..2edcfc4 100644
--- a/Source/WebCore/rendering/RenderTableRow.cpp
+++ b/Source/WebCore/rendering/RenderTableRow.cpp
@@ -74,10 +74,10 @@
 void RenderTableRow::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
 {
     RenderBox::styleDidChange(diff, oldStyle);
-    propagateStyleToAnonymousChildren();
 
     if (parent())
         updateBeforeAndAfterContent();
+
 }
 
 void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
@@ -90,7 +90,7 @@
         RenderObject* last = beforeChild;
         if (!last)
             last = lastChild();
-        if (last && last->isAnonymous() && last->isTableCell() && !last->isBeforeOrAfterContent()) {
+        if (last && last->isAnonymous() && last->isTableCell()) {
             if (beforeChild == last)
                 beforeChild = last->firstChild();
             last->addChild(child, beforeChild);
@@ -98,7 +98,7 @@
         }
 
         // If beforeChild is inside an anonymous cell, insert into the cell.
-        if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous() && !last->parent()->isBeforeOrAfterContent()) {
+        if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous()) {
             last->parent()->addChild(child, beforeChild);
             return;
         }
diff --git a/Source/WebCore/rendering/RenderTableSection.cpp b/Source/WebCore/rendering/RenderTableSection.cpp
index daa0a92..06d326f 100644
--- a/Source/WebCore/rendering/RenderTableSection.cpp
+++ b/Source/WebCore/rendering/RenderTableSection.cpp
@@ -78,12 +78,6 @@
     clearGrid();
 }
 
-void RenderTableSection::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
-{
-    RenderBox::styleDidChange(diff, oldStyle);
-    propagateStyleToAnonymousChildren();
-}
-
 void RenderTableSection::destroy()
 {
     RenderTable* recalcTable = table();
@@ -106,7 +100,7 @@
         RenderObject* last = beforeChild;
         if (!last)
             last = lastChild();
-        if (last && last->isAnonymous() && !last->isBeforeOrAfterContent()) {
+        if (last && last->isAnonymous()) {
             if (beforeChild == last)
                 beforeChild = last->firstChild();
             last->addChild(child, beforeChild);
@@ -118,7 +112,7 @@
         RenderObject* lastBox = last;
         while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableRow())
             lastBox = lastBox->parent();
-        if (lastBox && lastBox->isAnonymous() && !lastBox->isBeforeOrAfterContent()) {
+        if (lastBox && lastBox->isAnonymous()) {
             lastBox->addChild(child, beforeChild);
             return;
         }
diff --git a/Source/WebCore/rendering/RenderTableSection.h b/Source/WebCore/rendering/RenderTableSection.h
index db6edc2..cc969e8 100644
--- a/Source/WebCore/rendering/RenderTableSection.h
+++ b/Source/WebCore/rendering/RenderTableSection.h
@@ -118,9 +118,6 @@
 
     int getBaseline(int row) { return m_grid[row].baseline; }
 
-protected:
-    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
-
 private:
     virtual RenderObjectChildList* virtualChildren() { return children(); }
     virtual const RenderObjectChildList* virtualChildren() const { return children(); }
diff --git a/Source/WebCore/rendering/RenderText.cpp b/Source/WebCore/rendering/RenderText.cpp
index 6f4d3b7..b35820a 100644
--- a/Source/WebCore/rendering/RenderText.cpp
+++ b/Source/WebCore/rendering/RenderText.cpp
@@ -37,7 +37,6 @@
 #include "RenderCombineText.h"
 #include "RenderLayer.h"
 #include "RenderView.h"
-#include "Settings.h"
 #include "Text.h"
 #include "TextBreakIterator.h"
 #include "TextResourceDecoder.h"
@@ -54,37 +53,6 @@
 
 namespace WebCore {
 
-class SecureTextTimer;
-typedef HashMap<RenderText*, SecureTextTimer*> SecureTextTimerMap;
-static SecureTextTimerMap* gSecureTextTimers = 0;
-
-class SecureTextTimer : public TimerBase {
-public:
-    SecureTextTimer(RenderText* renderText)
-        : m_renderText(renderText)
-        , m_lastTypedCharacterOffset(-1)
-    {
-    }
-
-    void restartWithNewText(unsigned lastTypedCharacterOffset)
-    {
-        m_lastTypedCharacterOffset = lastTypedCharacterOffset;
-        startOneShot(m_renderText->document()->settings()->passwordEchoDurationInSeconds());
-    }
-    void invalidate() { m_lastTypedCharacterOffset = -1; }
-    unsigned lastTypedCharacterOffset() { return m_lastTypedCharacterOffset; }
-
-private:
-    virtual void fired()
-    {
-        ASSERT(gSecureTextTimers->contains(m_renderText));
-        m_renderText->setText(m_renderText->text(), true /* forcing setting text as it may be masked later */);
-    }
-
-    RenderText* m_renderText;
-    int m_lastTypedCharacterOffset;
-};
-
 static void makeCapitalized(String* string, UChar previous)
 {
     if (string->isNull())
@@ -228,9 +196,6 @@
 
 void RenderText::destroy()
 {
-    if (SecureTextTimer* secureTextTimer = gSecureTextTimers ? gSecureTextTimers->take(this) : 0)
-        delete secureTextTimer;
-
     removeAndDestroyTextBoxes();
     RenderObject::destroy();
 }
@@ -1175,13 +1140,13 @@
         case TSNONE:
             break;
         case TSCIRCLE:
-            secureText(whiteBullet);
+            m_text.makeSecure(whiteBullet);
             break;
         case TSDISC:
-            secureText(bullet);
+            m_text.makeSecure(bullet);
             break;
         case TSSQUARE:
-            secureText(blackSquare);
+            m_text.makeSecure(blackSquare);
         }
     }
 
@@ -1191,28 +1156,6 @@
     m_isAllASCII = m_text.containsOnlyASCII();
 }
 
-void RenderText::secureText(UChar mask)
-{
-    if (!m_text.length())
-        return;
-
-    int lastTypedCharacterOffsetToReveal = -1;
-    String revealedText;
-    SecureTextTimer* secureTextTimer = gSecureTextTimers ? gSecureTextTimers->get(this) : 0;
-    if (secureTextTimer && secureTextTimer->isActive()) {
-        lastTypedCharacterOffsetToReveal = secureTextTimer->lastTypedCharacterOffset();
-        if (lastTypedCharacterOffsetToReveal >= 0)
-            revealedText.append(m_text[lastTypedCharacterOffsetToReveal]);
-    }
-
-    m_text.makeSecure(mask);
-    if (lastTypedCharacterOffsetToReveal >= 0) {
-        m_text.replace(lastTypedCharacterOffsetToReveal, 1, revealedText);
-        // m_text may be updated later before timer fires. We invalidate the lastTypedCharacterOffset to avoid inconsistency.
-        secureTextTimer->invalidate();
-    }
-}
-
 void RenderText::setText(PassRefPtr<StringImpl> text, bool force)
 {
     ASSERT(text);
@@ -1647,17 +1590,4 @@
 
 #endif
 
-void RenderText::momentarilyRevealLastTypedCharacter(unsigned lastTypedCharacterOffset)
-{
-    if (!gSecureTextTimers)
-        gSecureTextTimers = new SecureTextTimerMap;
-
-    SecureTextTimer* secureTextTimer = gSecureTextTimers->get(this);
-    if (!secureTextTimer) {
-        secureTextTimer = new SecureTextTimer(this);
-        gSecureTextTimers->add(this, secureTextTimer);
-    }
-    secureTextTimer->restartWithNewText(lastTypedCharacterOffset);
-}
-
 } // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderText.h b/Source/WebCore/rendering/RenderText.h
index f89a762..2008dad 100644
--- a/Source/WebCore/rendering/RenderText.h
+++ b/Source/WebCore/rendering/RenderText.h
@@ -117,9 +117,6 @@
 
     bool containsReversedText() const { return m_containsReversedText; }
 
-    bool isSecure() const { return style()->textSecurity() != TSNONE; }
-    void momentarilyRevealLastTypedCharacter(unsigned lastTypedCharacterOffset);
-
     InlineTextBox* findNextInlineTextBox(int offset, int& pos) const;
 
     bool allowTabs() const { return !style()->collapseWhiteSpace(); }
@@ -161,7 +158,6 @@
     void updateNeedsTranscoding();
 
     inline void transformText(String&) const;
-    void secureText(UChar mask);
 
     float m_minWidth; // here to minimize padding in 64-bit.
 
diff --git a/Source/WebCore/rendering/RenderWidget.cpp b/Source/WebCore/rendering/RenderWidget.cpp
index 97444cd..894d689 100644
--- a/Source/WebCore/rendering/RenderWidget.cpp
+++ b/Source/WebCore/rendering/RenderWidget.cpp
@@ -125,10 +125,6 @@
         document()->axObjectCache()->childrenChanged(this->parent());
         document()->axObjectCache()->remove(this);
     }
-
-    if (!documentBeingDestroyed() && parent()) 
-        parent()->dirtyLinesFromChangedChild(this);
-
     remove();
 
     if (m_hasCounterNodeMap)
diff --git a/Source/WebCore/rendering/break_lines.cpp b/Source/WebCore/rendering/break_lines.cpp
index 4dbf81b..9ac3375 100644
--- a/Source/WebCore/rendering/break_lines.cpp
+++ b/Source/WebCore/rendering/break_lines.cpp
@@ -119,21 +119,29 @@
 
 static inline bool shouldBreakAfter(UChar ch, UChar nextCh)
 {
+    switch (ch) {
+    case ideographicComma:
+    case ideographicFullStop:
+        // FIXME: cases for ideographicComma and ideographicFullStop are a workaround for an issue in Unicode 5.0
+        // which is likely to be resolved in Unicode 5.1 <http://bugs.webkit.org/show_bug.cgi?id=17411>.
+        // We may want to remove or conditionalize this workaround at some point.
 #ifdef ANDROID_LAYOUT
-    if (ch == '/')  // as '/' is used in uri which is always long, we would like to break it
-        return true;
+        // as '/' is used in uri which is always long, we would like to break it
+    case '/':
 #endif
-
-    // If both ch and nextCh are ASCII characters, use a lookup table for enhanced speed and for compatibility
-    // with other browsers (see comments for asciiLineBreakTable for details).
-    if (ch >= asciiLineBreakTableFirstChar && ch <= asciiLineBreakTableLastChar
-        && nextCh >= asciiLineBreakTableFirstChar && nextCh <= asciiLineBreakTableLastChar) {
-        const unsigned char* tableRow = asciiLineBreakTable[ch - asciiLineBreakTableFirstChar];
-        int nextChIndex = nextCh - asciiLineBreakTableFirstChar;
-        return tableRow[nextChIndex / 8] & (1 << (nextChIndex % 8));
+        return true;
+    default:
+        // If both ch and nextCh are ASCII characters, use a lookup table for enhanced speed and for compatibility
+        // with other browsers (see comments for asciiLineBreakTable for details).
+        if (ch >= asciiLineBreakTableFirstChar && ch <= asciiLineBreakTableLastChar
+                && nextCh >= asciiLineBreakTableFirstChar && nextCh <= asciiLineBreakTableLastChar) {
+            const unsigned char* tableRow = asciiLineBreakTable[ch - asciiLineBreakTableFirstChar];
+            int nextChIndex = nextCh - asciiLineBreakTableFirstChar;
+            return tableRow[nextChIndex / 8] & (1 << (nextChIndex % 8));
+        }
+        // Otherwise defer to the Unicode algorithm by returning false.
+        return false;
     }
-    // Otherwise defer to the Unicode algorithm by returning false.
-    return false;
 }
 
 static inline bool needsLineBreakIterator(UChar ch)
diff --git a/Source/WebCore/rendering/style/RenderStyle.h b/Source/WebCore/rendering/style/RenderStyle.h
index ea01064..fad5a7b 100644
--- a/Source/WebCore/rendering/style/RenderStyle.h
+++ b/Source/WebCore/rendering/style/RenderStyle.h
@@ -786,6 +786,19 @@
 
     ESpeak speak() { return static_cast<ESpeak>(rareInheritedData->speak); }
 
+#ifdef ANDROID_CSS_RING
+    // called when building nav cache to determine if the ring data is unchanged
+    const void* ringData() const { return reinterpret_cast<const void*>(rareInheritedData.get()); }
+    Color ringFillColor() const { return rareInheritedData->ringFillColor; }
+    Length ringInnerWidth() const { return rareInheritedData->ringInnerWidth; }
+    Length ringOuterWidth() const { return rareInheritedData->ringOuterWidth; }
+    Length ringOutset() const { return rareInheritedData->ringOutset; }
+    Color ringPressedInnerColor() const { return rareInheritedData->ringPressedInnerColor; }
+    Color ringPressedOuterColor() const { return rareInheritedData->ringPressedOuterColor; }
+    Length ringRadius() const { return rareInheritedData->ringRadius; }
+    Color ringSelectedInnerColor() const { return rareInheritedData->ringSelectedInnerColor; }
+    Color ringSelectedOuterColor() const { return rareInheritedData->ringSelectedOuterColor; }
+#endif
 #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
     Color tapHighlightColor() const { return rareInheritedData->tapHighlightColor; }
 #endif
@@ -1129,6 +1142,21 @@
     void setTextSizeAdjust(bool b) { SET_VAR(rareInheritedData, textSizeAdjust, b); }
     void setTextSecurity(ETextSecurity aTextSecurity) { SET_VAR(rareInheritedData, textSecurity, aTextSecurity); }
 
+#ifdef ANDROID_CSS_RING
+    void setRingFillColor(const Color& v) { SET_VAR(rareInheritedData, ringFillColor, v); }
+    void setRingInnerWidth(Length v) { SET_VAR(rareInheritedData, ringInnerWidth, v); }
+    void setRingOuterWidth(Length v) { SET_VAR(rareInheritedData, ringOuterWidth, v); }
+    void setRingOutset(Length v) { SET_VAR(rareInheritedData, ringOutset, v); }
+    void setRingPressedInnerColor(const Color& v) {
+        SET_VAR(rareInheritedData, ringPressedInnerColor, v); }
+    void setRingPressedOuterColor(const Color& v) {
+        SET_VAR(rareInheritedData, ringPressedOuterColor, v); }
+    void setRingRadius(Length v) { SET_VAR(rareInheritedData, ringRadius, v); }
+    void setRingSelectedInnerColor(const Color& v) {
+        SET_VAR(rareInheritedData, ringSelectedInnerColor, v); }
+    void setRingSelectedOuterColor(const Color& v) {
+        SET_VAR(rareInheritedData, ringSelectedOuterColor, v); }
+#endif
 #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
     void setTapHighlightColor(const Color& v) { SET_VAR(rareInheritedData, tapHighlightColor, v); }
 #endif
@@ -1331,6 +1359,17 @@
     static const Vector<StyleDashboardRegion>& noneDashboardRegions();
 #endif
 
+#ifdef ANDROID_CSS_RING
+    static Color initialRingFillColor() { return Color::ringFill; }
+    static Length initialRingInnerWidth() { return Length(16, Fixed); } // 1.0
+    static Length initialRingOuterWidth() { return Length(40, Fixed); } // 2.5
+    static Length initialRingOutset() { return Length(3, Fixed); }
+    static Color initialRingSelectedInnerColor() { return Color::ringSelectedInner; }
+    static Color initialRingSelectedOuterColor() { return Color::ringSelectedOuter; }
+    static Color initialRingPressedInnerColor() { return Color::ringPressedInner; }
+    static Color initialRingPressedOuterColor() { return Color::ringPressedOuter; }
+    static Length initialRingRadius() { return Length(1, Fixed); }
+#endif
 #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
     static Color initialTapHighlightColor() { return Color::tap; }
 #endif
diff --git a/Source/WebCore/rendering/style/StyleRareInheritedData.cpp b/Source/WebCore/rendering/style/StyleRareInheritedData.cpp
index a7acc4a..2253d1c 100644
--- a/Source/WebCore/rendering/style/StyleRareInheritedData.cpp
+++ b/Source/WebCore/rendering/style/StyleRareInheritedData.cpp
@@ -32,6 +32,17 @@
 
 StyleRareInheritedData::StyleRareInheritedData()
     : textStrokeWidth(RenderStyle::initialTextStrokeWidth())
+#ifdef ANDROID_CSS_RING
+    , ringFillColor(RenderStyle::initialRingFillColor())
+    , ringInnerWidth(RenderStyle::initialRingInnerWidth())
+    , ringOuterWidth(RenderStyle::initialRingOuterWidth())
+    , ringOutset(RenderStyle::initialRingOutset())
+    , ringPressedInnerColor(RenderStyle::initialRingPressedInnerColor())
+    , ringPressedOuterColor(RenderStyle::initialRingPressedOuterColor())
+    , ringRadius(RenderStyle::initialRingRadius())
+    , ringSelectedInnerColor(RenderStyle::initialRingSelectedInnerColor())
+    , ringSelectedOuterColor(RenderStyle::initialRingSelectedOuterColor())
+#endif
 #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
     , tapHighlightColor(RenderStyle::initialTapHighlightColor())
 #endif
@@ -66,6 +77,18 @@
     , textStrokeColor(o.textStrokeColor)
     , textStrokeWidth(o.textStrokeWidth)
     , textFillColor(o.textFillColor)
+    , textEmphasisColor(o.textEmphasisColor)
+#ifdef ANDROID_CSS_RING
+    , ringFillColor(o.ringFillColor)
+    , ringInnerWidth(o.ringInnerWidth)
+    , ringOuterWidth(o.ringOuterWidth)
+    , ringOutset(o.ringOutset)
+    , ringPressedInnerColor(o.ringPressedInnerColor)
+    , ringPressedOuterColor(o.ringPressedOuterColor)
+    , ringRadius(o.ringRadius)
+    , ringSelectedInnerColor(o.ringSelectedInnerColor)
+    , ringSelectedOuterColor(o.ringSelectedOuterColor)
+#endif
 #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
     , tapHighlightColor(o.tapHighlightColor)
 #endif
@@ -134,6 +157,17 @@
         && nbspMode == o.nbspMode
         && khtmlLineBreak == o.khtmlLineBreak
         && textSizeAdjust == o.textSizeAdjust
+#ifdef ANDROID_CSS_RING
+        && ringFillColor == o.ringFillColor
+        && ringInnerWidth == o.ringInnerWidth
+        && ringOuterWidth == o.ringOuterWidth
+        && ringOutset == o.ringOutset
+        && ringPressedInnerColor == o.ringPressedInnerColor
+        && ringPressedOuterColor == o.ringPressedOuterColor
+        && ringRadius == o.ringRadius
+        && ringSelectedInnerColor == o.ringSelectedInnerColor
+        && ringSelectedOuterColor == o.ringSelectedOuterColor
+#endif
 #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
         && tapHighlightColor == o.tapHighlightColor
 #endif
diff --git a/Source/WebCore/rendering/style/StyleRareInheritedData.h b/Source/WebCore/rendering/style/StyleRareInheritedData.h
index 16fcc5f..39cfe3c 100644
--- a/Source/WebCore/rendering/style/StyleRareInheritedData.h
+++ b/Source/WebCore/rendering/style/StyleRareInheritedData.h
@@ -58,6 +58,17 @@
     Color textFillColor;
     Color textEmphasisColor;
 
+#ifdef ANDROID_CSS_RING
+    Color ringFillColor;
+    Length ringInnerWidth;
+    Length ringOuterWidth;
+    Length ringOutset;
+    Color ringPressedInnerColor;
+    Color ringPressedOuterColor;
+    Length ringRadius;
+    Color ringSelectedInnerColor;
+    Color ringSelectedOuterColor;
+#endif
 #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
     Color tapHighlightColor;
 #endif
diff --git a/Source/WebCore/storage/AbstractDatabase.h b/Source/WebCore/storage/AbstractDatabase.h
index e0a277f..9279adc 100644
--- a/Source/WebCore/storage/AbstractDatabase.h
+++ b/Source/WebCore/storage/AbstractDatabase.h
@@ -36,7 +36,7 @@
 #include "SQLiteDatabase.h"
 #include <wtf/Forward.h>
 #include <wtf/ThreadSafeRefCounted.h>
-#if !LOG_DISABLED || !ERROR_DISABLED
+#ifndef NDEBUG
 #include "SecurityOrigin.h"
 #endif
 
@@ -109,7 +109,7 @@
     unsigned long m_estimatedSize;
     String m_filename;
 
-#if !LOG_DISABLED || !ERROR_DISABLED
+#ifndef NDEBUG
     String databaseDebugName() const { return m_contextThreadSecurityOrigin->toString() + "::" + m_name; }
 #endif
 
diff --git a/Source/WebCore/storage/DatabaseTask.cpp b/Source/WebCore/storage/DatabaseTask.cpp
index ad744e5..343ae1e 100644
--- a/Source/WebCore/storage/DatabaseTask.cpp
+++ b/Source/WebCore/storage/DatabaseTask.cpp
@@ -62,7 +62,7 @@
 DatabaseTask::DatabaseTask(Database* database, DatabaseTaskSynchronizer* synchronizer)
     : m_database(database)
     , m_synchronizer(synchronizer)
-#if !LOG_DISABLED
+#ifndef NDEBUG
     , m_complete(false)
 #endif
 {
@@ -70,17 +70,13 @@
 
 DatabaseTask::~DatabaseTask()
 {
-#if !LOG_DISABLED
     ASSERT(m_complete || !m_synchronizer);
-#endif
 }
 
 void DatabaseTask::performTask()
 {
     // Database tasks are meant to be used only once, so make sure this one hasn't been performed before.
-#if !LOG_DISABLED
     ASSERT(!m_complete);
-#endif
 
     LOG(StorageAPI, "Performing %s %p\n", debugTaskName(), this);
 
@@ -90,7 +86,7 @@
     if (m_synchronizer)
         m_synchronizer->taskCompleted();
 
-#if !LOG_DISABLED
+#ifndef NDEBUG
     m_complete = true;
 #endif
 }
@@ -112,7 +108,7 @@
     m_success = database()->performOpenAndVerify(m_setVersionInNewDatabase, m_code);
 }
 
-#if !LOG_DISABLED
+#ifndef NDEBUG
 const char* Database::DatabaseOpenTask::debugTaskName() const
 {
     return "DatabaseOpenTask";
@@ -132,7 +128,7 @@
     database()->close();
 }
 
-#if !LOG_DISABLED
+#ifndef NDEBUG
 const char* Database::DatabaseCloseTask::debugTaskName() const
 {
     return "DatabaseCloseTask";
@@ -154,7 +150,7 @@
         m_transaction->database()->inProgressTransactionCompleted();
 }
 
-#if !LOG_DISABLED
+#ifndef NDEBUG
 const char* Database::DatabaseTransactionTask::debugTaskName() const
 {
     return "DatabaseTransactionTask";
@@ -176,7 +172,7 @@
     m_tableNames = database()->performGetTableNames();
 }
 
-#if !LOG_DISABLED
+#ifndef NDEBUG
 const char* Database::DatabaseTableNamesTask::debugTaskName() const
 {
     return "DatabaseTableNamesTask";
diff --git a/Source/WebCore/storage/DatabaseTask.h b/Source/WebCore/storage/DatabaseTask.h
index faadc69..e1df591 100644
--- a/Source/WebCore/storage/DatabaseTask.h
+++ b/Source/WebCore/storage/DatabaseTask.h
@@ -90,7 +90,7 @@
     Database* m_database;
     DatabaseTaskSynchronizer* m_synchronizer;
 
-#if !LOG_DISABLED
+#ifndef NDEBUG
     virtual const char* debugTaskName() const = 0;
     bool m_complete;
 #endif
@@ -107,7 +107,7 @@
     DatabaseOpenTask(Database*, bool setVersionInNewDatabase, DatabaseTaskSynchronizer*, ExceptionCode&, bool& success);
 
     virtual void doPerformTask();
-#if !LOG_DISABLED
+#ifndef NDEBUG
     virtual const char* debugTaskName() const;
 #endif
 
@@ -127,7 +127,7 @@
     DatabaseCloseTask(Database*, DatabaseTaskSynchronizer*);
 
     virtual void doPerformTask();
-#if !LOG_DISABLED
+#ifndef NDEBUG
     virtual const char* debugTaskName() const;
 #endif
 };
@@ -146,7 +146,7 @@
     DatabaseTransactionTask(PassRefPtr<SQLTransaction>);
 
     virtual void doPerformTask();
-#if !LOG_DISABLED
+#ifndef NDEBUG
     virtual const char* debugTaskName() const;
 #endif
 
@@ -164,7 +164,7 @@
     DatabaseTableNamesTask(Database*, DatabaseTaskSynchronizer*, Vector<String>& names);
 
     virtual void doPerformTask();
-#if !LOG_DISABLED
+#ifndef NDEBUG
     virtual const char* debugTaskName() const;
 #endif
 
diff --git a/Source/WebCore/storage/SQLTransaction.cpp b/Source/WebCore/storage/SQLTransaction.cpp
index 0b1ad25..dfcd568 100644
--- a/Source/WebCore/storage/SQLTransaction.cpp
+++ b/Source/WebCore/storage/SQLTransaction.cpp
@@ -117,7 +117,7 @@
     m_statementQueue.append(statement);
 }
 
-#if !LOG_DISABLED
+#ifndef NDEBUG
 const char* SQLTransaction::debugStepName(SQLTransaction::TransactionStepMethod step)
 {
     if (step == &SQLTransaction::acquireLock)
diff --git a/Source/WebCore/storage/SQLTransaction.h b/Source/WebCore/storage/SQLTransaction.h
index a0a83ed..4c84f91 100644
--- a/Source/WebCore/storage/SQLTransaction.h
+++ b/Source/WebCore/storage/SQLTransaction.h
@@ -105,7 +105,7 @@
     void deliverTransactionErrorCallback();
     void cleanupAfterTransactionErrorCallback();
 
-#if !LOG_DISABLED
+#ifndef NDEBUG
     static const char* debugStepName(TransactionStepMethod);
 #endif
 
diff --git a/Source/WebCore/svg/SVGFontFaceUriElement.h b/Source/WebCore/svg/SVGFontFaceUriElement.h
index 3806315..ad9ba97 100644
--- a/Source/WebCore/svg/SVGFontFaceUriElement.h
+++ b/Source/WebCore/svg/SVGFontFaceUriElement.h
@@ -45,6 +45,22 @@
     virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
     virtual void insertedIntoDocument();
 
+#ifdef ANDROID_INSTRUMENT
+    void* operator new(size_t size) {
+        return SVGElement::operator new(size);
+    }
+    void* operator new[](size_t size) {
+        return SVGElement::operator new[](size);
+    }
+
+    void operator delete(void* p, size_t size) {
+        SVGElement::operator delete(p, size);
+    }
+    void operator delete[](void* p, size_t size) {
+        SVGElement::operator delete[](p, size);
+    }
+#endif
+
     void loadFont();
 
     CachedResourceHandle<CachedFont> m_cachedFont;
diff --git a/Source/WebCore/workers/WorkerContext.idl b/Source/WebCore/workers/WorkerContext.idl
index 5a6c407..e31f5ad 100644
--- a/Source/WebCore/workers/WorkerContext.idl
+++ b/Source/WebCore/workers/WorkerContext.idl
@@ -126,7 +126,6 @@
         attribute Int32ArrayConstructor Int32Array; // Usable with new operator
         attribute Uint32ArrayConstructor Uint32Array; // Usable with new operator
         attribute Float32ArrayConstructor Float32Array; // Usable with new operator
-        attribute Float64ArrayConstructor Float64Array; // Usable with new operator 
     };
 
 }
diff --git a/Source/WebCore/workers/WorkerLocation.cpp b/Source/WebCore/workers/WorkerLocation.cpp
index 319a528..b934abd 100644
--- a/Source/WebCore/workers/WorkerLocation.cpp
+++ b/Source/WebCore/workers/WorkerLocation.cpp
@@ -36,7 +36,7 @@
 
 String WorkerLocation::href() const
 {
-    return m_url.string();
+    return m_url.hasPath() ? m_url.prettyURL() : m_url.prettyURL() + "/";
 }
 
 String WorkerLocation::protocol() const
@@ -74,6 +74,11 @@
     return m_url.fragmentIdentifier().isEmpty() ? "" : "#" + m_url.fragmentIdentifier();
 }
 
+String WorkerLocation::toString() const
+{
+    return m_url.hasPath() ? m_url.prettyURL() : m_url.prettyURL() + "/";
+}
+
 
 } // namespace WebCore
 
diff --git a/Source/WebCore/workers/WorkerLocation.h b/Source/WebCore/workers/WorkerLocation.h
index 692c0e3..5200e35 100644
--- a/Source/WebCore/workers/WorkerLocation.h
+++ b/Source/WebCore/workers/WorkerLocation.h
@@ -30,10 +30,10 @@
 #if ENABLE(WORKERS)
 
 #include "KURL.h"
+#include <wtf/Forward.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
-#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
@@ -57,7 +57,7 @@
         String search() const;
         String hash() const;
 
-        String toString() const { return href(); }
+        String toString() const;
 
     private:
         WorkerLocation(const KURL& url) : m_url(url) { }
diff --git a/Source/WebCore/xml/XSLImportRule.h b/Source/WebCore/xml/XSLImportRule.h
index 5c0ca8a..3c5939d 100644
--- a/Source/WebCore/xml/XSLImportRule.h
+++ b/Source/WebCore/xml/XSLImportRule.h
@@ -52,6 +52,22 @@
     bool isLoading();
     void loadSheet();
     
+#ifdef ANDROID_INSTRUMENT
+    void* operator new(size_t size) {
+        return StyleBase::operator new(size);
+    }
+    void* operator new[](size_t size) {
+        return StyleBase::operator new[](size);
+    }
+
+    void operator delete(void* p, size_t size) {
+        StyleBase::operator delete(p, size);
+    }
+    void operator delete[](void* p, size_t size) {
+        StyleBase::operator delete[](p, size);
+    }
+#endif
+
 private:
     XSLImportRule(XSLStyleSheet* parentSheet, const String& href);
 
diff --git a/Source/WebKit/Android.mk b/Source/WebKit/Android.mk
index c3e9798..bbe212c 100644
--- a/Source/WebKit/Android.mk
+++ b/Source/WebKit/Android.mk
@@ -16,10 +16,8 @@
 ##
 
 LOCAL_SRC_FILES := \
-	android/WebCoreSupport/CacheResult.cpp \
 	android/WebCoreSupport/CachedFramePlatformDataAndroid.cpp \
 	android/WebCoreSupport/ChromeClientAndroid.cpp \
-	android/WebCoreSupport/ChromiumInit.cpp \
 	android/WebCoreSupport/ContextMenuClientAndroid.cpp \
 	android/WebCoreSupport/DeviceMotionClientAndroid.cpp \
 	android/WebCoreSupport/DeviceOrientationClientAndroid.cpp \
@@ -33,6 +31,12 @@
 	android/WebCoreSupport/PlatformBridge.cpp \
 	android/WebCoreSupport/ResourceLoaderAndroid.cpp \
 	android/WebCoreSupport/UrlInterceptResponse.cpp \
+	android/WebCoreSupport/V8Counters.cpp
+
+ifeq ($(HTTP_STACK),chrome)
+LOCAL_SRC_FILES += \
+	android/WebCoreSupport/ChromiumInit.cpp \
+	android/WebCoreSupport/CacheResult.cpp \
 	android/WebCoreSupport/WebCache.cpp \
 	android/WebCoreSupport/WebCookieJar.cpp \
 	android/WebCoreSupport/WebUrlLoader.cpp \
@@ -42,19 +46,22 @@
 	android/WebCoreSupport/WebResourceRequest.cpp \
 	android/WebCoreSupport/WebResponse.cpp \
 	android/WebCoreSupport/WebViewClientError.cpp
+endif # HTTP_STACK == chrome
 
 LOCAL_SRC_FILES += \
 	android/RenderSkinAndroid.cpp \
+	android/RenderSkinButton.cpp \
+	android/RenderSkinCombo.cpp \
 	android/RenderSkinMediaButton.cpp \
 	android/RenderSkinNinePatch.cpp \
+	android/RenderSkinRadio.cpp \
+	android/TimeCounter.cpp \
+	\
+	android/benchmark/Intercept.cpp \
+	android/benchmark/MyJavaVM.cpp \
 	\
 	android/icu/unicode/ucnv.cpp \
 	\
-	android/content/address_detector.cpp \
-	android/content/content_detector.cpp \
-	android/content/PhoneEmailDetector.cpp \
-	\
-	android/jni/AndroidHitTestResult.cpp \
 	android/jni/CacheManager.cpp \
 	android/jni/CookieManager.cpp \
 	android/jni/DeviceMotionAndOrientationManager.cpp \
@@ -63,11 +70,13 @@
 	android/jni/GeolocationPermissionsBridge.cpp \
 	android/jni/JavaBridge.cpp \
 	android/jni/JavaSharedClient.cpp \
+	android/jni/JniUtil.cpp \
 	android/jni/MIMETypeRegistry.cpp \
 	android/jni/MockGeolocation.cpp \
-	android/jni/PicturePile.cpp \
+	android/jni/PictureSet.cpp \
 	android/jni/WebCoreFrameBridge.cpp \
 	android/jni/WebCoreJni.cpp \
+	android/jni/WebCoreResourceLoader.cpp \
 	android/jni/WebFrameView.cpp \
 	android/jni/WebHistory.cpp \
 	android/jni/WebIconDatabase.cpp \
@@ -76,7 +85,15 @@
 	android/jni/WebViewCore.cpp \
 	android/jni/ViewStateSerializer.cpp \
 	\
-	android/nav/DrawExtra.cpp \
+	android/nav/CacheBuilder.cpp \
+	android/nav/CachedColor.cpp \
+	android/nav/CachedFrame.cpp \
+	android/nav/CachedHistory.cpp \
+	android/nav/CachedInput.cpp \
+	android/nav/CachedLayer.cpp \
+	android/nav/CachedNode.cpp \
+	android/nav/CachedRoot.cpp \
+	android/nav/FindCanvas.cpp \
 	android/nav/SelectText.cpp \
 	android/nav/WebView.cpp \
 	\
diff --git a/Source/WebKit/android/AndroidLog.h b/Source/WebKit/android/AndroidLog.h
index f034d35..3d3eaaa 100644
--- a/Source/WebKit/android/AndroidLog.h
+++ b/Source/WebKit/android/AndroidLog.h
@@ -26,25 +26,17 @@
 #ifndef AndroidLog_h
 #define AndroidLog_h
 
-#ifndef LOG_TAG
-#define LOG_TAG __FILE__
-#endif
-
-#include <cutils/log.h>
-#include <utils/Trace.h>
-#include <wtf/CurrentTime.h>
-
 #ifdef ANDROID_DOM_LOGGING
 #include <stdio.h>
 extern FILE* gDomTreeFile;
 #define DOM_TREE_LOG_FILE "/sdcard/domTree.txt"
 #define DUMP_DOM_LOGD(...) { if (gDomTreeFile) \
-    fprintf(gDomTreeFile, __VA_ARGS__); else ALOGD(__VA_ARGS__); }
+    fprintf(gDomTreeFile, __VA_ARGS__); else LOGD(__VA_ARGS__); }
 
 extern FILE* gRenderTreeFile;
 #define RENDER_TREE_LOG_FILE "/sdcard/renderTree.txt"
 #define DUMP_RENDER_LOGD(...) { if (gRenderTreeFile) \
-    fprintf(gRenderTreeFile, __VA_ARGS__); else ALOGD(__VA_ARGS__); }
+    fprintf(gRenderTreeFile, __VA_ARGS__); else LOGD(__VA_ARGS__); }
 #else
 #define DUMP_DOM_LOGD(...) ((void)0)
 #define DUMP_RENDER_LOGD(...) ((void)0)
@@ -53,28 +45,4 @@
 #define DISPLAY_TREE_LOG_FILE "/sdcard/displayTree.txt"
 #define LAYERS_TREE_LOG_FILE "/sdcard/layersTree.plist"
 
-#define FLOAT_RECT_FORMAT "[x=%.2f,y=%.2f,w=%.2f,h=%.2f]"
-#define FLOAT_RECT_ARGS(fr) fr.x(), fr.y(), fr.width(), fr.height()
-#define INT_RECT_FORMAT "[x=%d,y=%d,w=%d,h=%d]"
-#define INT_RECT_ARGS(ir) ir.x(), ir.y(), ir.width(), ir.height()
-
-#define TRACE_METHOD() android::ScopedTrace __st(ATRACE_TAG_WEBVIEW, __func__);
-
-#define TIME_METHOD() MethodTimer __method_timer(__func__)
-class MethodTimer {
-public:
-    MethodTimer(const char* name)
-        : m_methodName(name)
-    {
-        m_startTime = currentTimeMS();
-    }
-    virtual ~MethodTimer() {
-        double duration = currentTimeMS() - m_startTime;
-        ALOGD("%s took %.2fms", m_methodName, duration);
-    }
-private:
-    const char* m_methodName;
-    double m_startTime;
-};
-
 #endif // AndroidLog_h
diff --git a/Source/WebKit/android/RenderSkinAndroid.cpp b/Source/WebKit/android/RenderSkinAndroid.cpp
index 9529624..4a9ce68 100644
--- a/Source/WebKit/android/RenderSkinAndroid.cpp
+++ b/Source/WebKit/android/RenderSkinAndroid.cpp
@@ -27,11 +27,14 @@
 
 #include "config.h"
 #include "RenderSkinAndroid.h"
+#include "RenderSkinButton.h"
+#include "RenderSkinCombo.h"
 #include "RenderSkinMediaButton.h"
+#include "RenderSkinRadio.h"
 #include "SkImageDecoder.h"
 
-#include <androidfw/AssetManager.h>
-#include <androidfw/Asset.h>
+#include <utils/AssetManager.h>
+#include <utils/Asset.h>
 
 namespace WebCore {
 
@@ -40,6 +43,7 @@
 
 RenderSkinAndroid::~RenderSkinAndroid()
 {
+    delete m_button;
 }
 RenderSkinAndroid::RenderSkinAndroid(String drawableDirectory)
 {
@@ -52,6 +56,7 @@
 
         s_drawableDirectory = drawableDirectory;
     }
+    m_button = new RenderSkinButton(drawableDirectory);
 }
 
 bool RenderSkinAndroid::DecodeBitmap(android::AssetManager* am, const char* fileName, SkBitmap* bitmap)
@@ -60,14 +65,14 @@
     if (!asset) {
         asset = am->openNonAsset(fileName, android::Asset::ACCESS_BUFFER);
         if (!asset) {
-            ALOGD("RenderSkinAndroid: File \"%s\" not found.\n", fileName);
+            LOGD("RenderSkinAndroid: File \"%s\" not found.\n", fileName);
             return false;
         }
     }
     
     bool success = SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(), bitmap);
     if (!success) {
-        ALOGD("RenderSkinAndroid: Failed to decode %s\n", fileName);
+        LOGD("RenderSkinAndroid: Failed to decode %s\n", fileName);
     }
 
     delete asset;
diff --git a/Source/WebKit/android/RenderSkinAndroid.h b/Source/WebKit/android/RenderSkinAndroid.h
index 1d3820d..bbc327d 100644
--- a/Source/WebKit/android/RenderSkinAndroid.h
+++ b/Source/WebKit/android/RenderSkinAndroid.h
@@ -36,6 +36,7 @@
 
 namespace WebCore {
 class Node;
+class RenderSkinButton;
 
 class RenderSkinAndroid
 {
@@ -68,9 +69,12 @@
     static String DrawableDirectory() { return s_drawableDirectory; }
     static Resolution DrawableResolution() { return s_drawableResolution; }
 
+    RenderSkinButton* renderSkinButton() const { return m_button; }
+
 private:
     static String s_drawableDirectory;
     static Resolution s_drawableResolution;
+    RenderSkinButton* m_button;
 };
 
 } // WebCore
diff --git a/Source/WebKit/android/RenderSkinButton.cpp b/Source/WebKit/android/RenderSkinButton.cpp
new file mode 100644
index 0000000..11e2fa8
--- /dev/null
+++ b/Source/WebKit/android/RenderSkinButton.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2006, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "WebCore"
+
+#include "config.h"
+#include "android_graphics.h"
+#include "Document.h"
+#include "IntRect.h"
+#include "Node.h"
+#include "RenderSkinButton.h"
+#include "RenderSkinNinePatch.h"
+#include "SkCanvas.h"
+#include "SkNinePatch.h"
+#include "SkRect.h"
+#include <utils/Asset.h>
+#include <utils/AssetManager.h>
+#include <utils/Debug.h>
+#include <utils/Log.h>
+#include <utils/ResourceTypes.h>
+#include <wtf/text/CString.h>
+
+extern android::AssetManager* globalAssetManager();
+
+static const char* gFiles[] = {
+    "btn_default_disabled_holo.9.png",
+    "btn_default_normal_holo.9.png",
+    "btn_default_focused_holo.9.png",
+    "btn_default_pressed_holo.9.png"
+    };
+
+namespace WebCore {
+
+RenderSkinButton::RenderSkinButton(String drawableDirectory)
+    : m_decoded(false)
+    , m_decodingAttempted(false)
+    , m_drawableDirectory(drawableDirectory)
+{
+    // Ensure our enums properly line up with our arrays.
+    android::CompileTimeAssert<(RenderSkinAndroid::kDisabled == 0)> a1;
+    android::CompileTimeAssert<(RenderSkinAndroid::kNormal == 1)> a2;
+    android::CompileTimeAssert<(RenderSkinAndroid::kFocused == 2)> a3;
+    android::CompileTimeAssert<(RenderSkinAndroid::kPressed == 3)> a4;
+}
+
+void RenderSkinButton::decode()
+{
+    m_decodingAttempted = true;
+
+    android::AssetManager* am = globalAssetManager();
+
+    for (size_t i = 0; i < 4; i++) {
+        String path = m_drawableDirectory;
+        path.append(String(gFiles[i]));
+        if (!RenderSkinNinePatch::decodeAsset(am, path.utf8().data(), &m_buttons[i])) {
+            m_decoded = false;
+            LOGE("RenderSkinButton::decode: button assets failed to decode\n\tWebView buttons will not draw");
+            return;
+        }
+    }
+    m_decoded = true;
+}
+
+void RenderSkinButton::draw(SkCanvas* canvas, const IntRect& r,
+                            RenderSkinAndroid::State newState)
+{
+    if (!m_decodingAttempted)
+        decode();
+
+    // If we failed to decode, do nothing.  This way the browser still works,
+    // and webkit will still draw the label and layout space for us.
+    if (!m_decoded) {
+        return;
+    }
+    
+    // Ensure that the state is within the valid range of our array.
+    SkASSERT(static_cast<unsigned>(newState) < 
+            static_cast<unsigned>(RenderSkinAndroid::kNumStates));
+
+    RenderSkinNinePatch::DrawNinePatch(canvas, SkRect(r), m_buttons[newState]);
+}
+
+} //WebCore
diff --git a/Source/WebCore/platform/graphics/android/layers/PrerenderedInval.h b/Source/WebKit/android/RenderSkinButton.h
similarity index 66%
rename from Source/WebCore/platform/graphics/android/layers/PrerenderedInval.h
rename to Source/WebKit/android/RenderSkinButton.h
index 91f385d..83c57dd 100644
--- a/Source/WebCore/platform/graphics/android/layers/PrerenderedInval.h
+++ b/Source/WebKit/android/RenderSkinButton.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012, The Android Open Source Project
+ * Copyright 2006, The Android Open Source Project
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -23,36 +23,33 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef PrerenderedInval_h
-#define PrerenderedInval_h
+#ifndef RenderSkinButton_h
+#define RenderSkinButton_h
 
-#include "IntRect.h"
-#include "SkBitmap.h"
+#include "RenderSkinAndroid.h"
+#include "RenderSkinNinePatch.h"
 
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefCounted.h>
-#include <wtf/ThreadSafeRefCounted.h>
+class SkCanvas;
 
 namespace WebCore {
+class IntRect;
 
-class PrerenderedInval : public ThreadSafeRefCounted<PrerenderedInval> {
-    WTF_MAKE_NONCOPYABLE(PrerenderedInval);
+class RenderSkinButton {
 public:
-    SkBitmap bitmap;
-    IntRect area;
-    IntRect screenArea;
+    RenderSkinButton(String drawableDirectory);
+    /**
+     * Draw the skin to the canvas, using the rectangle for its bounds and the 
+     * State to determine which skin to use, i.e. focused or not focused.
+     */
+    void draw(SkCanvas* , const IntRect& , RenderSkinAndroid::State);
 
-    static PassRefPtr<PrerenderedInval> create(const IntRect& ir)
-    {
-        return adoptRef(new PrerenderedInval(ir));
-    }
-
+    void decode();
 private:
-    PrerenderedInval(const IntRect& ir)
-        : area(ir)
-    {}
+    bool m_decoded;
+    bool m_decodingAttempted;
+    NinePatch m_buttons[4];
+    String m_drawableDirectory;
 };
 
-} // namespace WebCore
-
-#endif // PrerenderedInval_h
+} // WebCore
+#endif
diff --git a/Source/WebKit/android/RenderSkinCombo.cpp b/Source/WebKit/android/RenderSkinCombo.cpp
new file mode 100644
index 0000000..1711cfa
--- /dev/null
+++ b/Source/WebKit/android/RenderSkinCombo.cpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2006, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderSkinCombo.h"
+
+#include "Document.h"
+#include "Element.h"
+#include "Node.h"
+#include "NodeRenderStyle.h"
+#include "RenderStyle.h"
+#include "SkCanvas.h"
+#include "SkNinePatch.h"
+#include <utils/AssetManager.h>
+#include <wtf/text/CString.h>
+
+extern android::AssetManager* globalAssetManager();
+
+namespace WebCore {
+
+// Indicates if the entire asset is being drawn, or if the border is being
+// excluded and just the arrow drawn.
+enum BorderStyle {
+    FullAsset,
+    NoBorder,
+    BorderStyleCount // Keep at the end.
+};
+
+// There are 2.5 different concepts of a 'border' here, which results
+// in rather a lot of magic constants.
+
+// Firstly, we have the extra padding that webkit needs to know about,
+// which defines how much bigger this element is made by the
+// asset. This is actually a bit broader than the actual border on the
+// asset, to make things look less cramped. The border is the same
+// width on all sides, except on the right when it's significantly
+// wider to allow for the arrow.
+const int RenderSkinCombo::arrowMargin[ResolutionCount] = {
+    16, // Medium resolution
+    25, // High resolution
+    34 // Extra high resolution
+};
+const int RenderSkinCombo::padMargin[ResolutionCount] = {
+    1, // Medium resolution
+    1, // High resolution
+    1 // Extra high resolution
+};
+
+namespace {
+// Then we have the borders used for the 9-patch stretch. The
+// rectangle at the centre of these borders is entirely below and to
+// the left of the arrow in the asset. Hence the border widths are the
+// same for the bottom and left, but are different for the top. The
+// right hand border width happens to be the same as arrowMargin
+// defined above.
+const int stretchMargin[RenderSkinAndroid::ResolutionCount] = { // border width for the bottom and left of the 9-patch
+    2, // Medium resolution
+    2, // High resolution
+    3 // Extra high resolution
+
+};
+const int stretchTop[RenderSkinAndroid::ResolutionCount] = { // border width for the top of the 9-patch
+    16, // Medium resolution
+    23, // High resolution
+    32 // Extra high resolution
+};
+
+// Finally, if the border is defined by the CSS, we only draw the
+// arrow and not the border. We do this by drawing the relevant subset
+// of the bitmap, which must now be precisely determined by what's in
+// the asset with no extra padding to make things look properly
+// spaced. The border to remove at the top, right and bottom of the
+// image is the same as stretchMargin above, but we need to know the width
+// of the arrow.
+const int arrowWidth[RenderSkinAndroid::ResolutionCount] = {
+    18, // Medium resolution
+    27, // High resolution
+    36 // Extra high resolution
+};
+
+// scale factors for various resolutions
+const float scaleFactor[RenderSkinAndroid::ResolutionCount] = {
+    1.0f, // medium res
+    1.5f, // high res
+    2.0f  // extra high res
+};
+
+// Store the calculated 9 patch margins for each border style.
+SkIRect margin[BorderStyleCount];
+
+SkBitmap bitmaps[2][BorderStyleCount]; // Collection of assets for a combo box - 2 states (enabled/disabled)
+bool isDecodingAttempted = false; // True if we've tried to decode the assets
+bool isDecoded = false;           // True if all assets were decoded
+
+} // namespace
+
+int RenderSkinCombo::minHeight() {
+    return SkScalarRound(stretchTop[RenderSkinAndroid::DrawableResolution()]
+            / scaleFactor[RenderSkinAndroid::DrawableResolution()]);
+}
+
+void RenderSkinCombo::Decode()
+{
+    if (isDecodingAttempted)
+        return;
+
+    isDecodingAttempted = true;
+    isDecoded = false;
+
+    android::AssetManager* am = globalAssetManager();
+
+    String drawableDirectory = RenderSkinAndroid::DrawableDirectory();
+    Resolution res = RenderSkinAndroid::DrawableResolution();
+
+    isDecoded = RenderSkinAndroid::DecodeBitmap(am, (drawableDirectory + "combobox_nohighlight.png").utf8().data(), &bitmaps[kNormal][FullAsset]);
+    isDecoded &= RenderSkinAndroid::DecodeBitmap(am, (drawableDirectory + "combobox_disabled.png").utf8().data(), &bitmaps[kDisabled][FullAsset]);
+
+    int width = bitmaps[kNormal][FullAsset].width();
+    int height = bitmaps[kNormal][FullAsset].height();
+    SkIRect subset;
+    subset.set(width - arrowWidth[res], 0, width, height);
+    bitmaps[kNormal][FullAsset].extractSubset(&bitmaps[kNormal][NoBorder], subset);
+    bitmaps[kDisabled][FullAsset].extractSubset(&bitmaps[kDisabled][NoBorder], subset);
+
+    // Calculate 9 patch margins.
+    SkIRect fullAssetMargin;
+    fullAssetMargin.fLeft = stretchMargin[res];
+    fullAssetMargin.fTop = stretchMargin[res];
+    fullAssetMargin.fRight = arrowMargin[res] + stretchMargin[res];
+    fullAssetMargin.fBottom = stretchTop[res];
+
+    SkIRect noBorderMargin;
+    noBorderMargin.fLeft = 0;
+    noBorderMargin.fTop = stretchTop[res];
+    noBorderMargin.fRight = 0;
+    noBorderMargin.fBottom = stretchMargin[res];
+
+    margin[FullAsset] = fullAssetMargin;
+    margin[NoBorder] = noBorderMargin;
+}
+
+bool RenderSkinCombo::Draw(SkCanvas* canvas, Node* element, int x, int y, int width, int height)
+{
+    if (!isDecodingAttempted)
+        Decode();
+
+    if (!isDecoded)
+        return true;
+
+    int resolution = RenderSkinAndroid::DrawableResolution();
+    State state = (element->isElementNode() && static_cast<Element*>(element)->isEnabledFormControl()) ? kNormal : kDisabled;
+    height = std::max(height, (stretchMargin[resolution] * 2));
+
+    SkRect bounds;
+    BorderStyle drawBorder = FullAsset;
+
+    bounds.set(SkIntToScalar(x+1), SkIntToScalar(y+1), SkIntToScalar(x + width-1), SkIntToScalar(y + height-1));
+    RenderStyle* style = element->renderStyle();
+    SkPaint paint;
+    paint.setColor(style->visitedDependentColor(CSSPropertyBackgroundColor).rgb());
+    canvas->drawRect(bounds, paint);
+
+    bounds.set(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + width), SkIntToScalar(y + height));
+
+    // If this is an appearance where RenderTheme::paint returns true
+    // without doing anything, this means that
+    // RenderBox::PaintBoxDecorationWithSize will end up painting the
+    // border, so we shouldn't paint a border here.
+    if (style->appearance() == MenulistButtonPart ||
+        style->appearance() == ListboxPart ||
+        style->appearance() == TextFieldPart ||
+        style->appearance() == TextAreaPart) {
+        bounds.fLeft += SkIntToScalar(width - RenderSkinCombo::extraWidth());
+        bounds.fRight -= SkIntToScalar(style->borderRightWidth());
+        bounds.fTop += SkIntToScalar(style->borderTopWidth());
+        bounds.fBottom -= SkIntToScalar(style->borderBottomWidth());
+        drawBorder = NoBorder;
+    }
+    float scale = scaleFactor[resolution];
+    bounds.fLeft = bounds.fLeft * scale;
+    bounds.fRight = bounds.fRight * scale;
+    bounds.fTop = bounds.fTop * scale;
+    bounds.fBottom = bounds.fBottom * scale;
+    int count = canvas->save();
+    canvas->scale(1.0f / scale, 1.0f / scale);
+    SkNinePatch::DrawNine(canvas, bounds, bitmaps[state][drawBorder], margin[drawBorder]);
+    canvas->restoreToCount(count);
+    return false;
+}
+
+}   // namspace WebCore
diff --git a/Source/WebKit/android/RenderSkinCombo.h b/Source/WebKit/android/RenderSkinCombo.h
new file mode 100644
index 0000000..a11faac
--- /dev/null
+++ b/Source/WebKit/android/RenderSkinCombo.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2006, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef RenderSkinCombo_h
+#define RenderSkinCombo_h
+
+#include "RenderSkinAndroid.h"
+#include "SkRect.h"
+
+class SkCanvas;
+
+namespace WebCore {
+
+// This is very similar to RenderSkinButton - maybe they should be the same class?
+class RenderSkinCombo : public RenderSkinAndroid
+{
+public:
+
+    static void Decode();
+    /**
+     * Draw the provided Node on the SkCanvas, using the dimensions provided by
+     * x,y,w,h.  Return true if we did not draw, and WebKit needs to draw it,
+     * false otherwise.
+     */
+    static bool Draw(SkCanvas* , Node* , int x, int y, int w, int h);
+
+    // The image is wider than the RenderObject, so this accounts for that.
+    static int extraWidth() { return arrowMargin[RenderSkinAndroid::DrawableResolution()]; }
+    static int minHeight();
+    static int padding() { return padMargin[RenderSkinAndroid::DrawableResolution()]; }
+
+
+private:
+    const static int arrowMargin[ResolutionCount];
+    const static int padMargin[ResolutionCount];
+}; 
+
+} // WebCore
+
+#endif
diff --git a/Source/WebKit/android/RenderSkinMediaButton.cpp b/Source/WebKit/android/RenderSkinMediaButton.cpp
index b3aa57d..ef4b313 100644
--- a/Source/WebKit/android/RenderSkinMediaButton.cpp
+++ b/Source/WebKit/android/RenderSkinMediaButton.cpp
@@ -36,7 +36,7 @@
 #include "SkCanvas.h"
 #include "SkNinePatch.h"
 #include "SkRect.h"
-#include <androidfw/AssetManager.h>
+#include <utils/AssetManager.h>
 #include <utils/Debug.h>
 #include <utils/Log.h>
 #include <wtf/text/CString.h>
@@ -82,22 +82,19 @@
         String path = drawableDirectory + gFiles[i].name;
         if (!RenderSkinAndroid::DecodeBitmap(am, path.utf8().data(), &gButton[i])) {
             gDecodingFailed = true;
-            ALOGD("RenderSkinButton::Init: button assets failed to decode\n\tBrowser buttons will not draw");
+            LOGD("RenderSkinButton::Init: button assets failed to decode\n\tBrowser buttons will not draw");
             break;
         }
     }
 }
 
 void RenderSkinMediaButton::Draw(SkCanvas* canvas, const IntRect& r, int buttonType,
-                                 bool translucent, RenderObject* o, bool drawBackground)
+                                 bool translucent, RenderObject* o)
 {
     if (!gDecoded) {
         Decode();
     }
 
-    if (!canvas)
-        return;
-
     // If we failed to decode, do nothing.  This way the browser still works,
     // and webkit will still draw the label and layout space for us.
     if (gDecodingFailed)
@@ -105,6 +102,7 @@
 
     bool drawsNinePatch = false;
     bool drawsImage = true;
+    bool drawsBackgroundColor = true;
 
     int ninePatchIndex = 0;
     int imageIndex = 0;
@@ -138,11 +136,13 @@
     case SPINNER_INNER:
     case VIDEO:
     {
+         drawsBackgroundColor = false;
          imageIndex = buttonType + 1;
          break;
     }
     case BACKGROUND_SLIDER:
     {
+         drawsBackgroundColor = false;
          drawsImage = false;
          break;
     }
@@ -155,6 +155,7 @@
     }
     case SLIDER_THUMB:
     {
+         drawsBackgroundColor = false;
          imageMargin = 0;
          imageIndex = buttonType + 1;
          break;
@@ -163,7 +164,7 @@
          return;
     }
 
-    if (drawBackground) {
+    if (drawsBackgroundColor) {
         canvas->drawRect(r, paint);
     }
 
diff --git a/Source/WebKit/android/RenderSkinMediaButton.h b/Source/WebKit/android/RenderSkinMediaButton.h
index 484b90c..d8b7c8d 100644
--- a/Source/WebKit/android/RenderSkinMediaButton.h
+++ b/Source/WebKit/android/RenderSkinMediaButton.h
@@ -42,7 +42,7 @@
      * State to determine which skin to use, i.e. focused or not focused.
      */
     static void Draw(SkCanvas* , const IntRect& , int buttonType, bool translucent = false,
-                     RenderObject* o = 0, bool drawBackground = true);
+                     RenderObject* o = 0);
     /**
      * Button types
      */
diff --git a/Source/WebKit/android/RenderSkinNinePatch.cpp b/Source/WebKit/android/RenderSkinNinePatch.cpp
index 9ef0b4a..faa9dc4 100644
--- a/Source/WebKit/android/RenderSkinNinePatch.cpp
+++ b/Source/WebKit/android/RenderSkinNinePatch.cpp
@@ -16,18 +16,18 @@
 
 #include "config.h"
 
-#include "NinePatchPeeker.h"
 #include "RenderSkinNinePatch.h"
+#include "NinePatchPeeker.h"
 #include "SkCanvas.h"
 #include "SkImageDecoder.h"
 #include "SkNinePatch.h"
 #include "SkRect.h"
 #include "SkStream.h"
 #include "SkTemplates.h"
-#include <androidfw/Asset.h>
-#include <androidfw/AssetManager.h>
-#include <androidfw/ResourceTypes.h>
+#include <utils/Asset.h>
+#include <utils/AssetManager.h>
 #include <utils/Log.h>
+#include <utils/ResourceTypes.h>
 
 class SkPaint;
 class SkRegion;
@@ -53,7 +53,7 @@
     SkImageDecoder* decoder = SkImageDecoder::Factory(&stream);
     if (!decoder) {
         asset->close();
-        ALOGE("RenderSkinNinePatch::Failed to create an image decoder");
+        LOGE("RenderSkinNinePatch::Failed to create an image decoder");
         return false;
     }
 
@@ -68,13 +68,13 @@
     decoder->setPeeker(&peeker);
     if (!decoder->decode(&stream, &ninepatch->m_bitmap, prefConfig, mode, true)) {
         asset->close();
-        ALOGE("RenderSkinNinePatch::Failed to decode nine patch asset");
+        LOGE("RenderSkinNinePatch::Failed to decode nine patch asset");
         return false;
     }
 
     asset->close();
-    if (!peeker.fPatch) {
-        ALOGE("RenderSkinNinePatch::Patch data not valid");
+    if (!peeker.fPatchIsValid) {
+        LOGE("RenderSkinNinePatch::Patch data not valid");
         return false;
     }
     void** data = &ninepatch->m_serializedPatchData;
diff --git a/Source/WebKit/android/RenderSkinNinePatch.h b/Source/WebKit/android/RenderSkinNinePatch.h
index 8cda795..e4db260 100644
--- a/Source/WebKit/android/RenderSkinNinePatch.h
+++ b/Source/WebKit/android/RenderSkinNinePatch.h
@@ -18,7 +18,7 @@
 #define RenderSkinNinePatch_h
 
 #include "SkBitmap.h"
-#include "androidfw/Asset.h"
+#include "utils/Asset.h"
 
 namespace android {
     class AssetManager;
diff --git a/Source/WebKit/android/RenderSkinRadio.cpp b/Source/WebKit/android/RenderSkinRadio.cpp
new file mode 100644
index 0000000..3c29818
--- /dev/null
+++ b/Source/WebKit/android/RenderSkinRadio.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2006, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderSkinRadio.h"
+
+#include "android_graphics.h"
+#include "Document.h"
+#include "Element.h"
+#include "InputElement.h"
+#include "IntRect.h"
+#include "Node.h"
+#include "RenderSkinAndroid.h"
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkRect.h"
+#include <utils/AssetManager.h>
+#include <wtf/text/CString.h>
+
+extern android::AssetManager* globalAssetManager();
+
+static const char* checks[] = { "btn_check_off_holo.png",
+                                "btn_check_on_holo.png",
+                                "btn_radio_off_holo.png",
+                                "btn_radio_on_holo.png"};
+// Matches the width of the bitmap
+static SkScalar s_bitmapWidth;
+
+namespace WebCore {
+
+static SkBitmap s_bitmap[4];
+static bool s_decodingAttempted = false;
+static bool s_decoded = false;
+
+void RenderSkinRadio::Decode() {
+    if (s_decodingAttempted)
+        return;
+
+    s_decodingAttempted = true;
+    s_decoded = false;
+
+    android::AssetManager* am = globalAssetManager();
+    String drawableDir = RenderSkinAndroid::DrawableDirectory();
+    for (int i = 0; i < 4; i++) {
+        String path = drawableDir + checks[i];
+        if (!RenderSkinAndroid::DecodeBitmap(am, path.utf8().data(), &s_bitmap[i]))
+            return;
+    }
+    s_decoded = true;
+    s_bitmapWidth = SkIntToScalar(s_bitmap[0].width());
+}
+
+void RenderSkinRadio::Draw(SkCanvas* canvas, Node* element, const IntRect& ir,
+        bool isCheckBox)
+{
+    if (!element)
+        return;
+
+    if (!s_decodingAttempted)
+        Decode();
+
+    if (!s_decoded)
+        return;
+
+    SkRect r(ir);
+    // Set up a paint to with filtering to look better.
+    SkPaint paint;
+    paint.setFlags(SkPaint::kFilterBitmap_Flag);
+    int saveScaleCount = 0;
+
+    if (!element->isElementNode() ||
+        !static_cast<Element*>(element)->isEnabledFormControl()) {
+        paint.setAlpha(0x80);
+    }
+    SkScalar width = r.width();
+    SkScalar scale = SkScalarDiv(width, s_bitmapWidth);
+    saveScaleCount = canvas->save();
+    canvas->translate(r.fLeft, r.fTop);
+    canvas->scale(scale, scale);
+
+    bool checked = false;
+    if (InputElement* inputElement = element->toInputElement()) {
+        checked = inputElement->isChecked();
+    }
+
+    canvas->drawBitmap(s_bitmap[checked + 2*(!isCheckBox)],
+            0, 0, &paint);
+    canvas->restoreToCount(saveScaleCount);
+}
+
+} //WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/TextureInfo.h b/Source/WebKit/android/RenderSkinRadio.h
similarity index 64%
copy from Source/WebCore/platform/graphics/android/rendering/TextureInfo.h
copy to Source/WebKit/android/RenderSkinRadio.h
index 7d182c3..34101cf 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TextureInfo.h
+++ b/Source/WebKit/android/RenderSkinRadio.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011, The Android Open Source Project
+ * Copyright 2006, The Android Open Source Project
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -23,43 +23,39 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef TextureInfo_h
-#define TextureInfo_h
+#ifndef RenderSkinRadio_h
+#define RenderSkinRadio_h
 
-#include <EGL/egl.h>
-#include <GLES2/gl2.h>
-#include <jni.h>
-#include <ui/GraphicBuffer.h>
-#include <utils/RefBase.h>
-using android::sp;
+#include "PlatformString.h"
+
+class SkCanvas;
 
 namespace android {
-class SurfaceTexture;
+    class AssetManager;
 }
 
 namespace WebCore {
 
-static const GLuint GL_NO_TEXTURE = 0;
-/**
- * TextureInfo is a class that stores both the texture and metadata about the
- * texture.
+class Node;
+class IntRect;
+
+/* RenderSkin for a radio button or a checkbox
  */
-
-class TextureInfo {
+class RenderSkinRadio
+{
 public:
-    TextureInfo();
+    static void SetDrawableDirectory(String drawableDirectory);
 
-    bool equalsAttributes(const TextureInfo* otherTexture);
-    void copyAttributes(const TextureInfo* sourceTexture);
+    // Perform lazy decoding the first time this a radio/checkbox is needed.
+    static void Decode();
 
-    bool operator==(const TextureInfo& otherTexture);
-
-    GLuint m_textureId;
-    int32_t m_width;
-    int32_t m_height;
-    GLenum m_internalFormat;
+    /**
+     * Draw the element to the canvas at the specified size and location.
+     * param isCheckBox If true, draws a checkbox.  Else, draw a radio button.
+     */
+    static void Draw(SkCanvas* canvas, Node* element, const IntRect&,
+            bool isCheckBox);
 };
 
-} // namespace WebCore
-
-#endif // TextureInfo_h
+} // WebCore
+#endif
diff --git a/Source/WebKit/android/TimeCounter.cpp b/Source/WebKit/android/TimeCounter.cpp
new file mode 100644
index 0000000..2393f8a
--- /dev/null
+++ b/Source/WebKit/android/TimeCounter.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "WebCore"
+
+#include "config.h"
+#include "TimeCounter.h"
+
+#include "MemoryCache.h"
+#include "KURL.h"
+#include "Node.h"
+#include "SystemTime.h"
+#include "StyleBase.h"
+#include <sys/time.h>
+#include <time.h>
+#include <utils/Log.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/CString.h>
+
+#if USE(JSC)
+#include "JSDOMWindow.h"
+#include <runtime/JSGlobalObject.h>
+#include <runtime/JSLock.h>
+#endif
+
+using namespace WebCore;
+using namespace WTF;
+using namespace JSC;
+
+namespace android {
+
+uint32_t getThreadMsec()
+{
+#if defined(HAVE_POSIX_CLOCKS)
+    struct timespec tm;
+
+    clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm);
+    return tm.tv_sec * 1000LL + tm.tv_nsec / 1000000;
+#else
+    struct timeval now;
+    struct timezone zone;
+
+    gettimeofday(&now, &zone);
+    return now.tv_sec * 1000LL + now.tv_usec / 1000;
+#endif
+}
+
+#ifdef ANDROID_INSTRUMENT
+
+static double sStartTotalTime;
+static uint32_t sStartThreadTime;
+static double sLastTotalTime;
+static uint32_t sLastThreadTime;
+
+uint32_t TimeCounter::sStartWebCoreThreadTime;
+uint32_t TimeCounter::sEndWebCoreThreadTime;
+bool TimeCounter::sRecordWebCoreTime;
+uint32_t TimeCounter::sTotalTimeUsed[TimeCounter::TotalTimeCounterCount];
+uint32_t TimeCounter::sLastTimeUsed[TimeCounter::TotalTimeCounterCount];
+uint32_t TimeCounter::sCounter[TimeCounter::TotalTimeCounterCount];
+uint32_t TimeCounter::sLastCounter[TimeCounter::TotalTimeCounterCount];
+uint32_t TimeCounter::sStartTime[TimeCounter::TotalTimeCounterCount];
+
+int QemuTracerAuto::reentry_count = 0;
+
+static const char* timeCounterNames[] = {
+    "css parsing", 
+    "javascript",
+    "javascript init",
+    "javascript parsing",
+    "javascript execution",
+    "calculate style", 
+    "Java callback (frame bridge)",
+    "parsing (may include calcStyle, Java callback or inline script execution)",
+    "layout", 
+    "native 1 (frame bridge)",
+    "native 2 (resource load)", 
+    "native 3 (shared timer)", 
+    "build nav (webview core)",
+    "record content (webview core)",
+    "native 4 (webview core)",
+    "draw content (webview ui)",
+};
+
+void TimeCounter::record(enum Type type, const char* functionName)
+{
+    recordNoCounter(type, functionName);
+    sCounter[type]++;
+}
+
+void TimeCounter::recordNoCounter(enum Type type, const char* functionName)
+{
+    uint32_t time = sEndWebCoreThreadTime = getThreadMsec();
+    uint32_t elapsed = time - sStartTime[type];
+    sTotalTimeUsed[type] += elapsed;
+    if (elapsed > 1000)
+        LOGW("***** %s() used %d ms\n", functionName, elapsed);
+}
+
+void TimeCounter::report(const KURL& url, int live, int dead, size_t arenaSize)
+{
+    String urlString = url;
+    int totalTime = static_cast<int>((currentTime() - sStartTotalTime) * 1000);
+    int threadTime = getThreadMsec() - sStartThreadTime;
+    LOGD("*-* Total load time: %d ms, thread time: %d ms for %s\n",
+        totalTime, threadTime, urlString.utf8().data());
+    for (Type type = (Type) 0; type < TotalTimeCounterCount; type 
+            = (Type) (type + 1)) {
+        char scratch[256];
+        int index = sprintf(scratch, "*-* Total %s time: %d ms", 
+            timeCounterNames[type], sTotalTimeUsed[type]);
+        if (sCounter[type] > 0)
+            sprintf(&scratch[index], " called %d times", sCounter[type]);
+        LOGD("%s", scratch);
+    }
+    LOGD("Current cache has %d bytes live and %d bytes dead", live, dead);
+    LOGD("Current render arena takes %d bytes", arenaSize);
+#if USE(JSC)
+    JSLock lock(false);
+    Heap::Statistics jsHeapStatistics = JSDOMWindow::commonJSGlobalData()->heap.statistics();
+    LOGD("Current JavaScript heap size is %d and has %d bytes free",
+            jsHeapStatistics.size, jsHeapStatistics.free);
+#endif
+    LOGD("Current CSS styles use %d bytes", StyleBase::reportStyleSize());
+    LOGD("Current DOM nodes use %d bytes", WebCore::Node::reportDOMNodesSize());
+}
+
+void TimeCounter::reportNow()
+{
+    double current = currentTime();
+    uint32_t currentThread = getThreadMsec();
+    int elapsedTime = static_cast<int>((current - sLastTotalTime) * 1000);
+    int elapsedThreadTime = currentThread - sLastThreadTime;
+    LOGD("*-* Elapsed time: %d ms, ui thread time: %d ms, webcore thread time:"
+        " %d ms\n", elapsedTime, elapsedThreadTime, sEndWebCoreThreadTime -
+        sStartWebCoreThreadTime);
+    for (Type type = (Type) 0; type < TotalTimeCounterCount; type 
+            = (Type) (type + 1)) {
+        if (sTotalTimeUsed[type] == sLastTimeUsed[type])
+            continue;
+        char scratch[256];
+        int index = sprintf(scratch, "*-* Diff %s time: %d ms",
+            timeCounterNames[type], sTotalTimeUsed[type] - sLastTimeUsed[type]);
+        if (sCounter[type] > sLastCounter[type])
+            sprintf(&scratch[index], " called %d times", sCounter[type]
+                - sLastCounter[type]);
+        LOGD("%s", scratch);
+    }
+    memcpy(sLastTimeUsed, sTotalTimeUsed, sizeof(sTotalTimeUsed));
+    memcpy(sLastCounter, sCounter, sizeof(sCounter));
+    sLastTotalTime = current;
+    sLastThreadTime = currentThread;
+    sRecordWebCoreTime = true;
+}
+
+void TimeCounter::reset() {
+    bzero(sTotalTimeUsed, sizeof(sTotalTimeUsed));
+    bzero(sCounter, sizeof(sCounter));
+    LOGD("*-* Start browser instrument\n");
+    sStartTotalTime = currentTime();
+    sStartThreadTime = getThreadMsec();
+}
+
+void TimeCounter::start(enum Type type)
+{
+    uint32_t time = getThreadMsec();
+    if (sRecordWebCoreTime) {
+        sStartWebCoreThreadTime = time;
+        sRecordWebCoreTime = false;
+    }
+    sStartTime[type] = time;
+}
+
+#endif  // ANDROID_INSTRUMENT
+
+}
diff --git a/Source/WebKit/android/TimeCounter.h b/Source/WebKit/android/TimeCounter.h
new file mode 100644
index 0000000..ecede27
--- /dev/null
+++ b/Source/WebKit/android/TimeCounter.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TimeCounter_h
+#define TimeCounter_h
+
+#include "hardware_legacy/qemu_tracing.h"
+
+namespace WebCore {
+
+class KURL;
+
+}
+
+namespace android {
+
+uint32_t getThreadMsec();
+
+#ifdef ANDROID_INSTRUMENT
+
+class TimeCounter {
+public:
+    enum Type {
+        // function base counters
+        CSSParseTimeCounter,
+        JavaScriptTimeCounter,
+        JavaScriptInitTimeCounter,
+        JavaScriptParseTimeCounter,
+        JavaScriptExecuteTimeCounter,
+        CalculateStyleTimeCounter,
+        JavaCallbackTimeCounter,
+        ParsingTimeCounter,
+        LayoutTimeCounter,
+        // file base counters
+        NativeCallbackTimeCounter,  // WebCoreFrameBridge.cpp
+        ResourceTimeCounter,        // WebCoreResourceLoader.cpp
+        SharedTimerTimeCounter,     // JavaBridge.cpp
+        WebViewCoreBuildNavTimeCounter,
+        WebViewCoreRecordTimeCounter,
+        WebViewCoreTimeCounter,     // WebViewCore.cpp
+        WebViewUIDrawTimeCounter,
+        TotalTimeCounterCount
+    };
+
+    static void record(enum Type type, const char* functionName);
+    static void recordNoCounter(enum Type type, const char* functionName);
+    static void report(const WebCore::KURL& , int live, int dead, size_t arenaSize);
+    static void reportNow();
+    static void reset();
+    static void start(enum Type type);
+private:
+    static uint32_t sStartWebCoreThreadTime;
+    static uint32_t sEndWebCoreThreadTime;
+    static bool sRecordWebCoreTime;
+    static uint32_t sTotalTimeUsed[TotalTimeCounterCount];
+    static uint32_t sLastTimeUsed[TotalTimeCounterCount];
+    static uint32_t sCounter[TotalTimeCounterCount];
+    static uint32_t sLastCounter[TotalTimeCounterCount];
+    static uint32_t sStartTime[TotalTimeCounterCount];
+    friend class TimeCounterAuto;
+};
+
+class TimeCounterAuto {
+public:
+    TimeCounterAuto(TimeCounter::Type type) : 
+        m_type(type), m_startTime(getThreadMsec()) {}
+    ~TimeCounterAuto() {
+        uint32_t time = getThreadMsec();
+        TimeCounter::sEndWebCoreThreadTime = time;
+        TimeCounter::sTotalTimeUsed[m_type] += time - m_startTime;
+        TimeCounter::sCounter[m_type]++;
+    }
+private:
+    TimeCounter::Type m_type;
+    uint32_t m_startTime;
+};
+
+class QemuTracerAuto {
+public:
+    QemuTracerAuto() {
+        if (!reentry_count)
+            qemu_start_tracing();
+        reentry_count++;
+    }
+
+    ~QemuTracerAuto() {
+        reentry_count--;
+        if (!reentry_count)
+            qemu_stop_tracing();
+    }
+private:
+    static int reentry_count;
+};
+#endif  // ANDROID_INSTRUMENT
+
+}
+
+#endif
diff --git a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
index 907dc3c..ab5fcb0 100644
--- a/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
+++ b/Source/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
@@ -95,7 +95,7 @@
     m_needsLayerSync = true;
     WebViewCore* webViewCore = WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view());
     if (webViewCore)
-        webViewCore->contentDraw();
+        webViewCore->layersDraw();
 }
 
 void ChromeClientAndroid::setNeedsOneShotDrawingSynchronization()
@@ -161,15 +161,8 @@
 }
 void ChromeClientAndroid::unfocus() { notImplemented(); }
 
-bool ChromeClientAndroid::canTakeFocus(FocusDirection direction)
-{
-    return android::WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view())->chromeCanTakeFocus(direction);
-}
-
-void ChromeClientAndroid::takeFocus(FocusDirection direction)
-{
-    android::WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view())->chromeTakeFocus(direction);
-}
+bool ChromeClientAndroid::canTakeFocus(FocusDirection) { notImplemented(); return false; }
+void ChromeClientAndroid::takeFocus(FocusDirection) { notImplemented(); }
 
 void ChromeClientAndroid::focusedNodeChanged(Node* node)
 {
@@ -188,10 +181,10 @@
         return frame->page();
 #endif
 
-    FloatRect window = windowRect();
+    const WebCoreViewBridge* bridge = frame->view()->platformWidget();
     bool dialog = features.dialog || !features.resizable
-            || (features.heightSet && features.height < window.height()
-                    && features.widthSet && features.width < window.width())
+            || (features.heightSet && features.height < bridge->height()
+                    && features.widthSet && features.width < bridge->width())
             || (!features.menuBarVisible && !features.statusBarVisible
                     && !features.toolBarVisible && !features.locationBarVisible
                     && !features.scrollbarsVisible);
@@ -238,7 +231,11 @@
     android::WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view())->addMessageToConsole(message, lineNumber, sourceID, msgLevel);
 }
 
-void ChromeClientAndroid::formDidBlur(const WebCore::Node* node) { notImplemented(); }
+void ChromeClientAndroid::formDidBlur(const WebCore::Node* node)
+{
+    android::WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view())->formDidBlur(node);
+}
+
 bool ChromeClientAndroid::canRunBeforeUnloadConfirmPanel() { return true; }
 bool ChromeClientAndroid::runBeforeUnloadConfirmPanel(const String& message, Frame* frame) {
     String url = frame->document()->documentURI();
@@ -301,7 +298,7 @@
 
 KeyboardUIMode ChromeClientAndroid::keyboardUIMode()
 {
-    return KeyboardAccessTabsToLinks;
+    return KeyboardAccessDefault;
 }
 
 IntRect ChromeClientAndroid::windowResizerRect() const { return IntRect(0, 0, 0, 0); }
@@ -641,11 +638,6 @@
 
 void ChromeClientAndroid::exitFullscreenForNode(Node* node)
 {
-    FrameView* frameView = m_webFrame->page()->mainFrame()->view();
-    android::WebViewCore* core = android::WebViewCore::getWebViewCore(frameView);
-    if (core)
-        core->exitFullscreenVideo();
-    return;
 }
 #endif
 
diff --git a/Source/WebKit/android/WebCoreSupport/ChromiumIncludes.h b/Source/WebKit/android/WebCoreSupport/ChromiumIncludes.h
index 1c898a0..022511a 100644
--- a/Source/WebKit/android/WebCoreSupport/ChromiumIncludes.h
+++ b/Source/WebKit/android/WebCoreSupport/ChromiumIncludes.h
@@ -23,46 +23,31 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// All source files wishing to include Chromium headers must include this file
-// and must not incude Chromium headers directly.
-
 #ifndef ChromiumIncludes_h
 #define ChromiumIncludes_h
 
 #include "config.h"
 
-// Both WebKit and Chromium define LOG. In AOSP, the framework also defines
-// LOG. To avoid conflicts, we undefine LOG before including Chromium code,
-// then define it back to the WebKit macro.
+// Include all external/chromium files in this file so the problems with the LOG
+// and LOG_ASSERT defines can be handled in one place.
+
+// Undefine LOG and LOG_ASSERT before including chrome code, and if they were
+// defined attempt to set the macros to the Android logging macros (which are
+// the only ones that actually log).
+
 #ifdef LOG
-#define LOG_WAS_DEFINED
+#define LOG_WAS_DEFINED LOG
 #undef LOG
 #endif
 
-// In AOSP, the framework still uses LOG_ASSERT (as well as ALOG_ASSERT), which
-// conflicts with Chromium's LOG_ASSERT. So we undefine LOG_ASSERT to allow the
-// Chromium implementation to be picked up. We also redefine ALOG_ASSERT to the
-// underlying framework implementation without using LOG_ASSERT.
-// TODO: Remove this once LOG_ASSERT is removed from the framework in AOSP.
+#ifdef LOG_ASSERT
+#define LOG_ASSERT_WAS_DEFINED LOG_ASSERT
 #undef LOG_ASSERT
-#undef ALOG_ASSERT
-// Copied from log.h.
-#define ALOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__)
-
-// Chromium won't build without NDEBUG set, so we set it for all source files
-// that use Chromium code. This means that if NDEBUG was previously unset, we
-// have to redefine ASSERT() to a no-op, as this is enabled in debug builds.
-// Unfortunately, ASSERT() is defined from config.h, so we can't get in first.
-#ifndef NDEBUG
-#define NDEBUG 1
-#undef ASSERT
-#define ASSERT(assertion) (void(0))
 #endif
 
 #include <android/net/android_network_library_impl.h>
 #include <android/jni/jni_utils.h>
 #include <base/callback.h>
-#include <base/lazy_instance.h>
 #include <base/memory/ref_counted.h>
 #include <base/message_loop_proxy.h>
 #include <base/openssl_util.h>
@@ -115,15 +100,13 @@
 #endif
 
 #undef LOG
-// If LOG was defined, restore it to the WebKit macro.
-#ifdef LOG_WAS_DEFINED
-// If LOG was defined, JOIN_LOG_CHANNEL_WITH_PREFIX must be too.
-// Copied from Assertions.h.
-#if LOG_DISABLED
-#define LOG(channel, ...) ((void)0)
-#else
-#define LOG(channel, ...) WTFLog(&JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__)
+#if defined(LOG_WAS_DEFINED) && defined(LOG_PRI)
+#define LOG(priority, tag, ...) LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__)
 #endif
+
+#undef LOG_ASSERT
+#if defined(LOG_ASSERT_WAS_DEFINED) && defined(LOG_FATAL_IF)
+#define LOG_ASSERT(cond, ...) LOG_FATAL_IF(!(cond), ## __VA_ARGS__)
 #endif
 
 #endif
diff --git a/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp
index 042c227..785f0a8 100644
--- a/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp
+++ b/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp
@@ -228,22 +228,8 @@
 void EditorClientAndroid::checkSpellingOfString(unsigned short const*, int, int*, int*) {}
 String EditorClientAndroid::getAutoCorrectSuggestionForMisspelledWord(const String&) { return String(); }
 void EditorClientAndroid::textFieldDidEndEditing(Element*) {}
-void EditorClientAndroid::textDidChangeInTextArea(Element* element)
-{
-    Frame* frame = m_page->focusController()->focusedOrMainFrame();
-    if (!frame || !frame->view())
-        return;
-    WebViewCore* webViewCore = WebViewCore::getWebViewCore(frame->view());
-    webViewCore->updateTextSizeAndScroll(element);
-}
-void EditorClientAndroid::textDidChangeInTextField(Element* element)
-{
-    Frame* frame = m_page->focusController()->focusedOrMainFrame();
-    if (!frame || !frame->view())
-        return;
-    WebViewCore* webViewCore = WebViewCore::getWebViewCore(frame->view());
-    webViewCore->updateTextSizeAndScroll(element);
-}
+void EditorClientAndroid::textDidChangeInTextArea(Element*) {}
+void EditorClientAndroid::textDidChangeInTextField(Element*) {}
 void EditorClientAndroid::textFieldDidBeginEditing(Element*) {}
 void EditorClientAndroid::ignoreWordInSpellDocument(String const&) {}
 
diff --git a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
index ac5cd9d..0be31eb 100644
--- a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
+++ b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
@@ -70,6 +70,7 @@
 #include "SkRect.h"
 #include "TextEncoding.h"
 #include "WebCoreFrameBridge.h"
+#include "WebCoreResourceLoader.h"
 #include "WebHistory.h"
 #include "WebIconDatabase.h"
 #include "WebFrameView.h"
@@ -78,7 +79,7 @@
 #include "autofill/WebAutofill.h"
 #include "android_graphics.h"
 
-#include <androidfw/AssetManager.h>
+#include <utils/AssetManager.h>
 #include <wtf/text/CString.h>
 
 #define verifiedOk() // Verified that we don't need to implement this.
@@ -266,11 +267,11 @@
     // There is a bug in webkit where cancelling an icon load is treated as a
     // failure. When this is fixed, we can ASSERT again that we have an icon.
     if (icon) {
-        ALOGV("Received icon (%p) for %s", icon,
+        LOGV("Received icon (%p) for %s", icon,
                 url.utf8().data());
         m_webFrame->didReceiveIcon(icon);
     } else {
-        ALOGV("Icon data for %s unavailable, registering for notification...",
+        LOGV("Icon data for %s unavailable, registering for notification...",
                 url.utf8().data());
         registerForIconNotification();
     }
@@ -422,9 +423,7 @@
     // so that about:blank will update the screen.
     if (!m_frame->tree()->parent()) {
         // Only need to notify Java side for the top frame
-        WebViewCore* core = WebViewCore::getWebViewCore(m_frame->view());
-        if (core)
-            core->didFirstLayout();
+        WebViewCore::getWebViewCore(m_frame->view())->didFirstLayout();
     }
 }
 
@@ -947,11 +946,11 @@
     Retain(webViewCore);
 
     // Save the old WebFrameView's bounds and apply them to the new WebFrameView
-    RefPtr<WebCore::FrameView> oldFrameView = m_frame->view();
-    WebFrameView* oldWebFrameView = static_cast<WebFrameView*> (oldFrameView->platformWidget());
-    IntRect bounds;
-    if (oldWebFrameView)
-        bounds = oldWebFrameView->getBounds();
+    WebFrameView* oldWebFrameView = static_cast<WebFrameView*> (m_frame->view()->platformWidget());
+    IntRect bounds = oldWebFrameView->getBounds();
+    IntRect visBounds = oldWebFrameView->getVisibleBounds();
+    IntRect windowBounds = oldWebFrameView->getWindowBounds();
+    WebCore::FrameView* oldFrameView = oldWebFrameView->view();
     const float oldZoomFactor = oldFrameView->frame()->textZoomFactor();
     m_frame->createView(bounds.size(), oldFrameView->baseBackgroundColor(), oldFrameView->isTransparent(),
             oldFrameView->fixedLayoutSize(), oldFrameView->useFixedLayout());
@@ -959,19 +958,21 @@
         m_frame->setTextZoomFactor(oldZoomFactor);
     }
 
-    if (oldWebFrameView) {
-        IntRect visBounds = oldWebFrameView->getVisibleBounds();
-        IntRect windowBounds = oldWebFrameView->getWindowBounds();
-        // Create a new WebFrameView for the new FrameView
-        WebFrameView* newFrameView = new WebFrameView(m_frame->view(), webViewCore);
-        newFrameView->setLocation(bounds.x(), bounds.y());
-        newFrameView->setSize(bounds.width(), bounds.height());
-        newFrameView->setVisibleSize(visBounds.width(), visBounds.height());
-        newFrameView->setWindowBounds(windowBounds.x(), windowBounds.y(), windowBounds.width(), windowBounds.height());
-        // newFrameView attaches itself to FrameView which Retains the reference, so
-        // call Release for newFrameView
-        Release(newFrameView);
-    }
+    // Create a new WebFrameView for the new FrameView
+    WebFrameView* newFrameView = new WebFrameView(m_frame->view(), webViewCore);
+
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+#else
+    webViewCore->clearContent();
+#endif
+
+    newFrameView->setLocation(bounds.x(), bounds.y());
+    newFrameView->setSize(bounds.width(), bounds.height());
+    newFrameView->setVisibleSize(visBounds.width(), visBounds.height());
+    newFrameView->setWindowBounds(windowBounds.x(), windowBounds.y(), windowBounds.width(), windowBounds.height());
+    // newFrameView attaches itself to FrameView which Retains the reference, so
+    // call Release for newFrameView
+    Release(newFrameView);
     // WebFrameView Retains webViewCore, so call Release for webViewCore
     Release(webViewCore);
 
@@ -1007,11 +1008,15 @@
     newFrame->tree()->setName(name);
     // Create a new FrameView and WebFrameView for the child frame to draw into.
     RefPtr<FrameView> frameView = FrameView::create(newFrame);
+    WebFrameView* webFrameView = new WebFrameView(frameView.get(),
+            WebViewCore::getWebViewCore(parent->view()));
+    // frameView Retains webFrameView, so call Release for webFrameView
+    Release(webFrameView);
     // Attach the frameView to the newFrame.
     newFrame->setView(frameView);
     newFrame->init();
     newFrame->selection()->setFocused(true);
-    ALOGV("::WebCore:: createSubFrame returning %p", newFrame);
+    LOGV("::WebCore:: createSubFrame returning %p", newFrame);
 
     // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
     if (!pFrame->page())
@@ -1326,8 +1331,8 @@
         return;
 
     ASSERT(m_frame);
-    ALOGV("::WebCore:: windowObjectCleared called on frame %p for %s\n",
-            m_frame, m_frame->document()->url().string().ascii().data());
+    LOGV("::WebCore:: windowObjectCleared called on frame %p for %s\n",
+    		m_frame, m_frame->loader()->url().string().ascii().data());
     m_webFrame->windowObjectCleared(m_frame);
 }
 
diff --git a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h
index 6eb4745..2464c58 100644
--- a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h
+++ b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h
@@ -26,6 +26,7 @@
 #ifndef FrameLoaderClientAndroid_h
 #define FrameLoaderClientAndroid_h
 
+#include "CacheBuilder.h"
 #include "FrameLoaderClient.h"
 #include "ResourceResponse.h"
 #include "WebIconDatabase.h"
@@ -199,12 +200,14 @@
         virtual void documentElementAvailable();
         virtual void didPerformFirstNavigation() const;
 
-        // TODO: Implement
+#if USE(V8)
+        // TODO(benm): Implement
         virtual void didCreateScriptContextForFrame() { }
         virtual void didDestroyScriptContextForFrame() { }
         virtual void didCreateIsolatedScriptContext() { }
 
-        virtual bool allowScriptExtension(const String& extensionName, int extensionGroup) { return false; }
+         virtual bool allowScriptExtension(const String& extensionName, int extensionGroup) { return false; }
+#endif
         
         virtual void registerForIconNotification(bool listen = true);
 
@@ -215,6 +218,9 @@
         // WebIconDatabaseClient api
         virtual void didAddIconForPageUrl(const String& pageUrl);
         
+        // FIXME: this doesn't really go here, but it's better than Frame
+        CacheBuilder& getCacheBuilder() { return m_cacheBuilder; }
+
         void enableOnDemandPlugins() { m_onDemandPluginsEnabled = true; }
 
         void dispatchDidChangeIcons();
@@ -223,6 +229,7 @@
         virtual void didSaveToPageCache() { }
         virtual void didRestoreFromPageCache() { }
     private:
+        CacheBuilder m_cacheBuilder;
         Frame* m_frame;
         WebFrame* m_webFrame;
         PluginManualLoader* m_manualLoader;
@@ -258,6 +265,7 @@
             ErrorFileNotFound          = -14,
             ErrorTooManyRequests       = -15
         };
+        friend class CacheBuilder;
     };
 
 }
diff --git a/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp b/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp
index 1607b0e..339e91b 100644
--- a/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp
+++ b/Source/WebKit/android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp
@@ -29,6 +29,10 @@
 #if ENABLE(VIDEO)
 
 #include "BaseLayerAndroid.h"
+#include "DocumentLoader.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "FrameView.h"
 #include "GraphicsContext.h"
 #include "SkiaUtils.h"
 #include "TilesManager.h"
@@ -164,19 +168,6 @@
     m_networkState = MediaPlayer::Idle;
 }
 
-void MediaPlayerPrivate::onRequestPlay()
-{
-    play();
-}
-
-void MediaPlayerPrivate::onRestoreState()
-{
-    if (!m_paused) {
-        //Kick off a JNI call to start the video.
-        play();
-    }
-}
-
 void MediaPlayerPrivate::onPaused()
 {
     m_paused = true;
@@ -220,6 +211,11 @@
         if (!env || !m_url.length() || !m_glue->m_javaProxy)
             return;
 
+        // We only play video fullscreen on Android, so stop sites playing fullscreen video in the onload handler.
+        Frame* frame = m_player->frameView()->frame();
+        if (frame && !frame->loader()->documentLoader()->wasOnloadHandled())
+            return;
+
         m_paused = false;
         m_player->playbackStateChanged();
 
@@ -260,9 +256,7 @@
         if (!m_poster || (!m_poster->getPixels() && !m_poster->pixelRef()))
             return;
 
-        SkCanvas*   canvas = ctxt->platformContext()->getCanvas();
-        if (!canvas)
-            return;
+        SkCanvas*   canvas = ctxt->platformContext()->mCanvas;
         // We paint with the following rules in mind:
         // - only downscale the poster, never upscale
         // - maintain the natural aspect ratio of the poster
@@ -299,8 +293,7 @@
         m_player->durationChanged();
         m_player->sizeChanged();
         TilesManager::instance()->videoLayerManager()->updateVideoLayerSize(
-            m_player->platformLayer()->uniqueId(), width * height,
-            width / (float)height);
+            m_player->platformLayer()->uniqueId(), width*height);
     }
 
     virtual bool hasAudio() const { return false; } // do not display the audio UI
@@ -541,14 +534,6 @@
     }
 }
 
-static void OnRequestPlay(JNIEnv* env, jobject obj, int pointer)
-{
-    if (pointer) {
-        WebCore::MediaPlayerPrivate* player = reinterpret_cast<WebCore::MediaPlayerPrivate*>(pointer);
-        player->onRequestPlay();
-    }
-}
-
 static void OnPaused(JNIEnv* env, jobject obj, int pointer)
 {
     if (pointer) {
@@ -585,15 +570,6 @@
     }
 }
 
-static void OnRestoreState(JNIEnv* env, jobject obj, int pointer)
-{
-    if (pointer) {
-        WebCore::MediaPlayerPrivate* player = reinterpret_cast<WebCore::MediaPlayerPrivate*>(pointer);
-        player->onRestoreState();
-    }
-}
-
-
 // This is called on the UI thread only.
 // The video layers are composited on the webkit thread and then copied over
 // to the UI thread with the same ID. For rendering, we are only using the
@@ -617,9 +593,14 @@
     BaseLayerAndroid* layerImpl = reinterpret_cast<BaseLayerAndroid*>(baseLayer);
     if (!layerImpl)
         return false;
+    if (!layerImpl->countChildren())
+        return false;
+    LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(layerImpl->getChild(0));
+    if (!compositedRoot)
+        return false;
 
     VideoLayerAndroid* videoLayer =
-        static_cast<VideoLayerAndroid*>(layerImpl->findById(videoLayerId));
+        static_cast<VideoLayerAndroid*>(compositedRoot->findById(videoLayerId));
     if (!videoLayer)
         return false;
 
@@ -651,8 +632,6 @@
         (void*) OnPaused },
     { "nativeOnPosterFetched", "(Landroid/graphics/Bitmap;I)V",
         (void*) OnPosterFetched },
-    { "nativeOnRestoreState", "(I)V",
-        (void*) OnRestoreState },
     { "nativeSendSurfaceTexture", "(Landroid/graphics/SurfaceTexture;IIII)Z",
         (void*) SendSurfaceTexture },
     { "nativeOnTimeupdate", "(II)V",
@@ -666,8 +645,6 @@
         (void*) OnEnded },
     { "nativeOnPrepared", "(IIII)V",
         (void*) OnPrepared },
-    { "nativeOnRequestPlay", "(I)V",
-        (void*) OnRequestPlay },
     { "nativeOnTimeupdate", "(II)V",
         (void*) OnTimeupdate },
 };
diff --git a/Source/WebKit/android/WebCoreSupport/MemoryUsage.cpp b/Source/WebKit/android/WebCoreSupport/MemoryUsage.cpp
index 592fad3..32cdebf 100644
--- a/Source/WebKit/android/WebCoreSupport/MemoryUsage.cpp
+++ b/Source/WebKit/android/WebCoreSupport/MemoryUsage.cpp
@@ -29,7 +29,9 @@
 #include <malloc.h>
 #include <wtf/CurrentTime.h>
 
+#if USE(V8)
 #include <v8.h>
+#endif // USE(V8)
 
 using namespace WTF;
 
@@ -57,10 +59,12 @@
     struct mallinfo minfo = mallinfo();
     m_cachedMemoryUsage = (minfo.hblkhd + minfo.arena) >> 20;
 
+#if USE(V8)
     v8::HeapStatistics stat;
     v8::V8::GetHeapStatistics(&stat);
     unsigned v8Usage = stat.total_heap_size() >> 20;
     m_cachedMemoryUsage += v8Usage;
+#endif // USE(V8)
 
     m_cacheTime = currentTimeMS();
     return m_cachedMemoryUsage;
diff --git a/Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp b/Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp
index 9b8aac8..27fe208 100644
--- a/Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp
+++ b/Source/WebKit/android/WebCoreSupport/PlatformBridge.cpp
@@ -35,22 +35,18 @@
 #include "KeyGeneratorClient.h"
 #include "MemoryUsage.h"
 #include "PluginView.h"
-#include "RenderLayer.h"
-#include "RenderView.h"
 #include "Settings.h"
 #include "WebCookieJar.h"
 #include "WebRequestContext.h"
 #include "WebViewCore.h"
 #include "npruntime.h"
 
-#include <gui/SurfaceComposerClient.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
 #include <ui/DisplayInfo.h>
 #include <ui/PixelFormat.h>
 #include <wtf/android/AndroidThreading.h>
 #include <wtf/MainThread.h>
 
-#include <algorithm>
-
 using namespace android;
 
 namespace WebCore {
@@ -75,40 +71,62 @@
 
 void PlatformBridge::setCookies(const Document* document, const KURL& url, const String& value)
 {
+#if USE(CHROME_NETWORK_STACK)
     std::string cookieValue(value.utf8().data());
     GURL cookieGurl(url.string().utf8().data());
     bool isPrivateBrowsing = document->settings() && document->settings()->privateBrowsingEnabled();
-    WebCookieJar* cookieJar = WebCookieJar::get(isPrivateBrowsing);
-    if (cookieJar->allowCookies())
-        cookieJar->cookieStore()->SetCookie(cookieGurl, cookieValue);
+    WebCookieJar::get(isPrivateBrowsing)->cookieStore()->SetCookie(cookieGurl, cookieValue);
+#else
+    CookieClient* client = JavaSharedClient::GetCookieClient();
+    if (!client)
+        return;
+
+    client->setCookies(url, value);
+#endif
 }
 
 String PlatformBridge::cookies(const Document* document, const KURL& url)
 {
+#if USE(CHROME_NETWORK_STACK)
     GURL cookieGurl(url.string().utf8().data());
     bool isPrivateBrowsing = document->settings() && document->settings()->privateBrowsingEnabled();
-    WebCookieJar* cookieJar = WebCookieJar::get(isPrivateBrowsing);
-    String cookieString;
-    if (cookieJar->allowCookies()) {
-        std::string cookies = cookieJar->cookieStore()->GetCookies(cookieGurl);
-        cookieString = cookies.c_str();
-    }
+    std::string cookies = WebCookieJar::get(isPrivateBrowsing)->cookieStore()->GetCookies(cookieGurl);
+    String cookieString(cookies.c_str());
     return cookieString;
+#else
+    CookieClient* client = JavaSharedClient::GetCookieClient();
+    if (!client)
+        return String();
+
+    return client->cookies(url);
+#endif
 }
 
 bool PlatformBridge::cookiesEnabled(const Document* document)
 {
+#if USE(CHROME_NETWORK_STACK)
     bool isPrivateBrowsing = document->settings() && document->settings()->privateBrowsingEnabled();
     return WebCookieJar::get(isPrivateBrowsing)->allowCookies();
+#else
+    CookieClient* client = JavaSharedClient::GetCookieClient();
+    if (!client)
+        return false;
+
+    return client->cookiesEnabled();
+#endif
 }
 
 NPObject* PlatformBridge::pluginScriptableObject(Widget* widget)
 {
+#if USE(V8)
     if (!widget->isPluginView())
         return 0;
 
     PluginView* pluginView = static_cast<PluginView*>(widget);
     return pluginView->getNPObject();
+#else
+    return 0;
+#endif
 }
 
 bool PlatformBridge::isWebViewPaused(const WebCore::FrameView* frameView)
@@ -157,11 +175,15 @@
 
 String PlatformBridge::computeDefaultLanguage()
 {
+#if USE(CHROME_NETWORK_STACK)
     String acceptLanguages = WebRequestContext::acceptLanguage();
     size_t length = acceptLanguages.find(',');
     if (length == std::string::npos)
         length = acceptLanguages.length();
     return acceptLanguages.substring(0, length);
+#else
+    return "en";
+#endif
 }
 
 void PlatformBridge::updateViewport(FrameView* frameView)
@@ -177,15 +199,10 @@
 }
 
 void PlatformBridge::setScrollPosition(ScrollView* scrollView, int x, int y) {
-    FrameView* frameView = scrollView->frameView();
-    if (!frameView) return;
     // Check to make sure the view is the main FrameView.
     android::WebViewCore *webViewCore = android::WebViewCore::getWebViewCore(scrollView);
-    if (webViewCore->mainFrame()->view() == scrollView) {
-        x = std::max(0, std::min(frameView->contentsWidth(), x));
-        y = std::max(0, std::min(frameView->contentsHeight(), y));
+    if (webViewCore->mainFrame()->view() == scrollView)
         webViewCore->scrollTo(x, y);
-    }
 }
 
 int PlatformBridge::lowMemoryUsageMB()
diff --git a/Source/WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp b/Source/WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp
index 92c39b8..7f54810 100644
--- a/Source/WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp
+++ b/Source/WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp
@@ -29,6 +29,7 @@
 #include "Frame.h"
 #include "FrameLoaderClientAndroid.h"
 #include "WebCoreFrameBridge.h"
+#include "WebCoreResourceLoader.h"
 #include "WebUrlLoader.h"
 #include "WebViewCore.h"
 
@@ -41,13 +42,18 @@
 {
     // Called on main thread
     FrameLoaderClientAndroid* clientAndroid = static_cast<FrameLoaderClientAndroid*>(client);
+#if USE(CHROME_NETWORK_STACK)
     WebViewCore* webViewCore = WebViewCore::getWebViewCore(clientAndroid->getFrame()->view());
     bool isMainFrame = !(clientAndroid->getFrame()->tree() && clientAndroid->getFrame()->tree()->parent());
     return WebUrlLoader::start(client, handle, request, isMainResource, isMainFrame, isSync, webViewCore->webRequestContext());
+#else
+    return clientAndroid->webFrame()->startLoadingResource(handle, request, isMainResource, isSync);
+#endif
 }
 
 bool ResourceLoaderAndroid::willLoadFromCache(const WebCore::KURL& url, int64_t identifier)
 {
+#if USE(CHROME_NETWORK_STACK)
     // This method is used to determine if a POST request can be repeated from
     // cache, but you cannot really know until you actually try to read from the
     // cache.  Even if we checked now, something else could come along and wipe
@@ -57,6 +63,9 @@
     // reload.  Then in FrameLoaderClientImpl::dispatchWillSendRequest, we
     // fix-up the cache policy of the request to force a load from the cache.
     return true;
+#else
+    return WebCoreResourceLoader::willLoadFromCache(url, identifier);
+#endif
 }
 
 }
diff --git a/Source/WebKit/android/WebCoreSupport/UrlInterceptResponse.cpp b/Source/WebKit/android/WebCoreSupport/UrlInterceptResponse.cpp
index d846daf..77e3c32 100644
--- a/Source/WebKit/android/WebCoreSupport/UrlInterceptResponse.cpp
+++ b/Source/WebKit/android/WebCoreSupport/UrlInterceptResponse.cpp
@@ -30,7 +30,6 @@
 #include "UrlInterceptResponse.h"
 #include "WebCoreJni.h"
 
-#include <ScopedLocalRef.h>
 #include <utils/Log.h>
 
 namespace android {
@@ -39,14 +38,15 @@
 public:
     JavaInputStreamWrapper(JNIEnv* env, jobject inputStream)
             : m_inputStream(env->NewGlobalRef(inputStream))
-            , m_buffer(NULL) {
-        LOG_ALWAYS_FATAL_IF(!m_inputStream);
-        ScopedLocalRef<jclass> inputStreamClass(env, env->FindClass("java/io/InputStream"));
-        LOG_ALWAYS_FATAL_IF(!inputStreamClass.get());
-        m_read = env->GetMethodID(inputStreamClass.get(), "read", "([B)I");
+            , m_buffer(0) {
+        LOG_ALWAYS_FATAL_IF(!inputStream);
+        jclass inputStreamClass = env->FindClass("java/io/InputStream");
+        LOG_ALWAYS_FATAL_IF(!inputStreamClass);
+        m_read = env->GetMethodID(inputStreamClass, "read", "([B)I");
         LOG_ALWAYS_FATAL_IF(!m_read);
-        m_close = env->GetMethodID(inputStreamClass.get(), "close", "()V");
+        m_close = env->GetMethodID(inputStreamClass, "close", "()V");
         LOG_ALWAYS_FATAL_IF(!m_close);
+        env->DeleteLocalRef(inputStreamClass);
     }
 
     ~JavaInputStreamWrapper() {
@@ -63,10 +63,10 @@
         JNIEnv* env = JSC::Bindings::getJNIEnv();
         // Initialize our read buffer to the capacity of out.
         if (!m_buffer) {
-            ScopedLocalRef<jbyteArray> buffer_local(env, env->NewByteArray(out->capacity()));
-            m_buffer = static_cast<jbyteArray>(env->NewGlobalRef(buffer_local.get()));
+            m_buffer = env->NewByteArray(out->capacity());
+            m_buffer = (jbyteArray) env->NewGlobalRef(m_buffer);
         }
-        int size = env->CallIntMethod(m_inputStream, m_read, m_buffer);
+        int size = (int) env->CallIntMethod(m_inputStream, m_read, m_buffer);
         if (checkException(env) || size < 0)
             return;
         // Copy from m_buffer to out.
@@ -82,32 +82,40 @@
 };
 
 UrlInterceptResponse::UrlInterceptResponse(JNIEnv* env, jobject response) {
-    ScopedLocalRef<jclass> javaResponse(env, env->FindClass("android/webkit/WebResourceResponse"));
-    LOG_ALWAYS_FATAL_IF(!javaResponse.get());
-    jfieldID mimeType = env->GetFieldID(javaResponse.get(), "mMimeType", "Ljava/lang/String;");
+    jclass javaResponse = env->FindClass("android/webkit/WebResourceResponse");
+    LOG_ALWAYS_FATAL_IF(!javaResponse);
+    jfieldID mimeType = env->GetFieldID(javaResponse, "mMimeType",
+                                        "Ljava/lang/String;");
     LOG_ALWAYS_FATAL_IF(!mimeType);
-    jfieldID encoding = env->GetFieldID(javaResponse.get(), "mEncoding", "Ljava/lang/String;");
+    jfieldID encoding = env->GetFieldID(javaResponse, "mEncoding",
+                                        "Ljava/lang/String;");
     LOG_ALWAYS_FATAL_IF(!encoding);
-    jfieldID inputStream = env->GetFieldID(javaResponse.get(), "mInputStream", "Ljava/io/InputStream;");
+    jfieldID inputStream = env->GetFieldID(javaResponse, "mInputStream",
+                                           "Ljava/io/InputStream;");
     LOG_ALWAYS_FATAL_IF(!inputStream);
 
-    ScopedLocalRef<jobject> stream(env, env->GetObjectField(response, inputStream));
-    if (stream.get())
-        m_inputStream.set(new JavaInputStreamWrapper(env, stream.get()));
+    jobject stream = env->GetObjectField(response, inputStream);
+    if (stream)
+        m_inputStream.set(new JavaInputStreamWrapper(env, stream));
 
-    ScopedLocalRef<jstring> mimeStr(env, static_cast<jstring>(env->GetObjectField(response, mimeType)));
-    ScopedLocalRef<jstring> encodingStr(env, static_cast<jstring>(env->GetObjectField(response, encoding)));
+    jstring mimeStr = (jstring) env->GetObjectField(response, mimeType);
+    jstring encodingStr = (jstring) env->GetObjectField(response, encoding);
 
-    if (mimeStr.get()) {
-        const char* s = env->GetStringUTFChars(mimeStr.get(), NULL);
-        m_mimeType.assign(s, env->GetStringUTFLength(mimeStr.get()));
-        env->ReleaseStringUTFChars(mimeStr.get(), s);
+    if (mimeStr) {
+        const char* s = env->GetStringUTFChars(mimeStr, NULL);
+        m_mimeType.assign(s, env->GetStringUTFLength(mimeStr));
+        env->ReleaseStringUTFChars(mimeStr, s);
     }
-    if (encodingStr.get()) {
-        const char* s = env->GetStringUTFChars(encodingStr.get(), NULL);
-        m_encoding.assign(s, env->GetStringUTFLength(encodingStr.get()));
-        env->ReleaseStringUTFChars(encodingStr.get(), s);
+    if (encodingStr) {
+        const char* s = env->GetStringUTFChars(encodingStr, NULL);
+        m_encoding.assign(s, env->GetStringUTFLength(encodingStr));
+        env->ReleaseStringUTFChars(encodingStr, s);
     }
+
+    env->DeleteLocalRef(javaResponse);
+    env->DeleteLocalRef(stream);
+    env->DeleteLocalRef(mimeStr);
+    env->DeleteLocalRef(encodingStr);
 }
 
 UrlInterceptResponse::~UrlInterceptResponse() {
diff --git a/Source/WebKit/android/WebCoreSupport/V8Counters.cpp b/Source/WebKit/android/WebCoreSupport/V8Counters.cpp
new file mode 100644
index 0000000..d164f9a
--- /dev/null
+++ b/Source/WebKit/android/WebCoreSupport/V8Counters.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifdef ANDROID_INSTRUMENT
+
+#define LOG_TAG "WebCore"
+
+#include "config.h"
+#include "V8Counters.h"
+
+#include "NotImplemented.h"
+#include <utils/Log.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/StringHash.h>
+
+#if USE(V8)
+
+namespace WebCore {
+
+V8Counters::Counter::Counter(bool isHistogram)
+    : m_count(0), m_sampleTotal(0), m_isHistogram(isHistogram) { }
+
+void V8Counters::Counter::addSample(int sample)
+{
+  m_count++;
+  m_sampleTotal += sample;
+}
+
+HashMap<String, V8Counters::Counter*> V8Counters::m_counters;
+
+// static
+int* V8Counters::counterForName(const char* name)
+{
+    Counter* counter = m_counters.get(name);
+    if (!counter) {
+        counter = new Counter(false);
+        m_counters.add(name, counter);
+    }
+    return *counter;
+}
+
+// static
+void* V8Counters::createHistogram(const char* name, int min, int max,
+        size_t buckets)
+{
+    Counter* counter = new Counter(true);
+    m_counters.add(name, counter);
+    return counter;
+}
+
+// static
+void V8Counters::addHistogramSample(void* histogram, int sample)
+{
+    Counter* counter = reinterpret_cast<Counter*>(histogram);
+    counter->addSample(sample);
+}
+
+// static
+void V8Counters::initCounters()
+{
+    static bool isInitialized = false;
+    if (!isInitialized) {
+        v8::V8::SetCounterFunction(counterForName);
+        v8::V8::SetCreateHistogramFunction(createHistogram);
+        v8::V8::SetAddHistogramSampleFunction(addHistogramSample);
+        isInitialized = true;
+    }
+}
+
+// static
+void V8Counters::dumpCounters()
+{
+    LOGD("+----------------------------------------+-------------+\n");
+    LOGD("| Name                                   | Value       |\n");
+    LOGD("+----------------------------------------+-------------+\n");
+    typedef HashMap<String, V8Counters::Counter*>::iterator CounterIterator;
+    for (CounterIterator iter = m_counters.begin(); iter != m_counters.end(); ++iter) {
+        Counter* counter = iter->second;
+        if (counter->isHistogram()) {
+            LOGD("| c:%-36s | %11i |\n", iter->first.latin1().data(), counter->count());
+            LOGD("| t:%-36s | %11i |\n", iter->first.latin1().data(), counter->sampleTotal());
+          } else {
+            LOGD("| %-38s | %11i |\n", iter->first.latin1().data(), counter->count());
+          }
+    }
+    LOGD("+----------------------------------------+-------------+\n");
+}
+
+}
+
+#endif // ANDROID_INSTRUMENT
+
+#endif // USE(V8)
diff --git a/Source/WebKit/android/WebCoreSupport/V8Counters.h b/Source/WebKit/android/WebCoreSupport/V8Counters.h
new file mode 100644
index 0000000..499b856
--- /dev/null
+++ b/Source/WebKit/android/WebCoreSupport/V8Counters.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef V8Counters_h
+#define V8Counters_h
+
+#if USE(V8)
+
+#ifdef ANDROID_INSTRUMENT
+
+#include <PlatformString.h>
+#include <v8.h>
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+class V8Counters {
+public:
+    // Counter callbacks, see v8.h
+    static int* counterForName(const char* name);
+
+    static void* createHistogram(const char* name,
+                                 int min,
+                                 int max,
+                                 size_t buckets);
+
+    static void addHistogramSample(void* histogram, int sample);
+
+    static void initCounters();
+    static void dumpCounters();
+private:
+    class Counter {
+    public:
+        Counter(bool isHistogram);
+
+        int count() { return m_count; }
+        int sampleTotal() { return m_sampleTotal; }
+        bool isHistogram() { return m_isHistogram; }
+        void addSample(int32_t sample);
+
+        operator int*() { return &m_count; }
+    private:
+        int m_count;
+        int m_sampleTotal;
+        bool m_isHistogram;
+    };
+
+    static HashMap<String, Counter*> m_counters;
+};
+
+}
+
+#endif // ANDROID_INSTRUMENT
+#endif // USE(V8)
+#endif // V8Counters_h
diff --git a/Source/WebKit/android/WebCoreSupport/WebCache.cpp b/Source/WebKit/android/WebCoreSupport/WebCache.cpp
index 82e3b27..9b505ee 100644
--- a/Source/WebKit/android/WebCoreSupport/WebCache.cpp
+++ b/Source/WebKit/android/WebCoreSupport/WebCache.cpp
@@ -30,7 +30,7 @@
 #include "WebCoreJni.h"
 #include "WebRequestContext.h"
 #include "WebUrlLoaderClient.h"
-#include "net/http/http_network_session.h"
+
 #include <wtf/text/CString.h>
 
 using namespace WTF;
@@ -131,21 +131,6 @@
         thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, &WebCache::clearImpl));
 }
 
-void WebCache::certTrustChanged()
-{
-    base::Thread* thread = WebUrlLoaderClient::ioThread();
-    if (thread)
-        thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, &WebCache::certTrustChangedImpl));
-}
-
-void WebCache::certTrustChangedImpl()
-{
-    net::HttpNetworkSession* session = m_cache->GetSession();
-    if (session)
-        session->cert_verifier()->ClearCache();
-    m_cache->CloseAllConnections();
-}
-
 void WebCache::closeIdleConnections()
 {
     base::Thread* thread = WebUrlLoaderClient::ioThread();
diff --git a/Source/WebKit/android/WebCoreSupport/WebCache.h b/Source/WebKit/android/WebCoreSupport/WebCache.h
index ad57d88..c3b623d 100644
--- a/Source/WebKit/android/WebCoreSupport/WebCache.h
+++ b/Source/WebKit/android/WebCoreSupport/WebCache.h
@@ -48,7 +48,7 @@
     net::HttpCache* cache() { return m_cache.get(); }
     net::ProxyConfigServiceAndroid* proxy() { return m_proxyConfigService; }
     void closeIdleConnections();
-    void certTrustChanged();
+
 
 private:
     WebCache(bool isPrivateBrowsing);
@@ -60,7 +60,6 @@
 
     // For closeIdleConnections
     void closeIdleImpl();
-    void certTrustChangedImpl();
 
     // For getEntry()
     void getEntryImpl();
diff --git a/Source/WebKit/android/WebCoreSupport/WebCookieJar.cpp b/Source/WebKit/android/WebCoreSupport/WebCookieJar.cpp
index 0af3cc2..1dc4637 100644
--- a/Source/WebKit/android/WebCoreSupport/WebCookieJar.cpp
+++ b/Source/WebKit/android/WebCoreSupport/WebCookieJar.cpp
@@ -98,7 +98,7 @@
     return databaseFilePath;
 }
 
-static scoped_refptr<WebCookieJar>* instance(bool isPrivateBrowsing)
+scoped_refptr<WebCookieJar>* instance(bool isPrivateBrowsing)
 {
     static scoped_refptr<WebCookieJar> regularInstance;
     static scoped_refptr<WebCookieJar> privateInstance;
@@ -127,16 +127,10 @@
 }
 
 WebCookieJar::WebCookieJar(const std::string& databaseFilePath)
-    : m_cookieStoreInitialized(false)
-    , m_databaseFilePath(databaseFilePath)
-    , m_allowCookies(true) {}
-
-void WebCookieJar::initCookieStore() {
-    MutexLocker lock(m_cookieStoreInitializeMutex);
-    if (m_cookieStoreInitialized)
-        return;
+    : m_allowCookies(true)
+{
     // Setup the permissions for the file
-    const char* cDatabasePath = m_databaseFilePath.c_str();
+    const char* cDatabasePath = databaseFilePath.c_str();
     mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
     if (access(cDatabasePath, F_OK) == 0)
         chmod(cDatabasePath, mode);
@@ -146,10 +140,9 @@
             close(fd);
     }
 
-    FilePath cookiePath(cDatabasePath);
+    FilePath cookiePath(databaseFilePath.c_str());
     m_cookieDb = new SQLitePersistentCookieStore(cookiePath);
     m_cookieStore = new net::CookieMonster(m_cookieDb.get(), 0);
-    m_cookieStoreInitialized = true;
 }
 
 bool WebCookieJar::allowCookies()
@@ -164,6 +157,13 @@
     m_allowCookies = allow;
 }
 
+int WebCookieJar::getNumCookiesInDatabase()
+{
+    if (!m_cookieStore)
+        return 0;
+    return m_cookieStore->GetCookieMonster()->GetAllCookies().size();
+}
+
 // From CookiePolicy in chromium
 int WebCookieJar::CanGetCookies(const GURL&, const GURL&) const
 {
@@ -178,17 +178,6 @@
     return m_allowCookies ? net::OK : net::ERR_ACCESS_DENIED;
 }
 
-net::CookieStore* WebCookieJar::cookieStore()
-{
-    initCookieStore();
-    return m_cookieStore.get();
-}
-
-int WebCookieJar::getNumCookiesInDatabase()
-{
-    return cookieStore()->GetCookieMonster()->GetAllCookies().size();
-}
-
 class FlushSemaphore : public base::RefCounted<FlushSemaphore>
 {
 public:
diff --git a/Source/WebKit/android/WebCoreSupport/WebCookieJar.h b/Source/WebKit/android/WebCoreSupport/WebCookieJar.h
index 7ade9d0..b6490af 100644
--- a/Source/WebKit/android/WebCoreSupport/WebCookieJar.h
+++ b/Source/WebKit/android/WebCoreSupport/WebCookieJar.h
@@ -55,10 +55,9 @@
     static bool acceptFileSchemeCookies();
     static void setAcceptFileSchemeCookies(bool);
 
-    // TODO
     // Instead of this it would probably be better to add the cookie methods
     // here so the rest of WebKit doesn't have to know about Chromium classes
-    net::CookieStore* cookieStore();
+    net::CookieStore* cookieStore() { return m_cookieStore.get(); }
     net::CookiePolicy* cookiePolicy() { return this; }
 
     // Get the number of cookies that have actually been saved to flash.
@@ -67,13 +66,7 @@
 
 private:
     WebCookieJar(const std::string& databaseFilePath);
-    void initCookieStore();
 
-private:
-    bool m_cookieStoreInitialized;
-    WTF::Mutex m_cookieStoreInitializeMutex;
-
-    const std::string m_databaseFilePath;
     scoped_refptr<SQLitePersistentCookieStore> m_cookieDb;
     scoped_refptr<net::CookieStore> m_cookieStore;
     bool m_allowCookies;
diff --git a/Source/WebKit/android/WebCoreSupport/WebRequest.cpp b/Source/WebKit/android/WebCoreSupport/WebRequest.cpp
index 9d16378..90b0939 100644
--- a/Source/WebKit/android/WebCoreSupport/WebRequest.cpp
+++ b/Source/WebKit/android/WebCoreSupport/WebRequest.cpp
@@ -30,7 +30,6 @@
 #include "MainThread.h"
 #include "UrlInterceptResponse.h"
 #include "WebCoreFrameBridge.h"
-#include "WebCoreJni.h"
 #include "WebRequestContext.h"
 #include "WebResourceRequest.h"
 #include "WebUrlLoaderClient.h"
@@ -39,7 +38,7 @@
 #include <cutils/log.h>
 #include <openssl/x509.h>
 #include <string>
-#include <androidfw/AssetManager.h>
+#include <utils/AssetManager.h>
 
 extern android::AssetManager* globalAssetManager();
 
@@ -59,28 +58,12 @@
 namespace android {
 
 namespace {
-const int kInitialReadBufSize = 32768;
-const char* kXRequestedWithHeader = "X-Requested-With";
-
-struct RequestPackageName {
-    std::string value;
-    RequestPackageName();
-};
-
-RequestPackageName::RequestPackageName() {
-    JNIEnv* env = JSC::Bindings::getJNIEnv();
-    jclass bridgeClass = env->FindClass("android/webkit/JniUtil");
-    jmethodID method = env->GetStaticMethodID(bridgeClass, "getPackageName", "()Ljava/lang/String;");
-    value = jstringToStdString(env, static_cast<jstring>(env->CallStaticObjectMethod(bridgeClass, method)));
-    env->DeleteLocalRef(bridgeClass);
-}
-
-base::LazyInstance<RequestPackageName> s_packageName(base::LINKER_INITIALIZED);
-
+    const int kInitialReadBufSize = 32768;
 }
 
 WebRequest::WebRequest(WebUrlLoaderClient* loader, const WebResourceRequest& webResourceRequest)
     : m_urlLoader(loader)
+    , m_androidUrl(false)
     , m_url(webResourceRequest.url())
     , m_userAgent(webResourceRequest.userAgent())
     , m_loadState(Created)
@@ -96,7 +79,6 @@
     m_request = new net::URLRequest(gurl, this);
 
     m_request->SetExtraRequestHeaders(webResourceRequest.requestHeaders());
-    m_request->SetExtraRequestHeaderByName(kXRequestedWithHeader, s_packageName.Get().value, false);
     m_request->set_referrer(webResourceRequest.referrer());
     m_request->set_method(webResourceRequest.method());
     m_request->set_load_flags(webResourceRequest.loadFlags());
@@ -107,6 +89,7 @@
 WebRequest::WebRequest(WebUrlLoaderClient* loader, const WebResourceRequest& webResourceRequest, UrlInterceptResponse* intercept)
     : m_urlLoader(loader)
     , m_interceptResponse(intercept)
+    , m_androidUrl(true)
     , m_url(webResourceRequest.url())
     , m_userAgent(webResourceRequest.userAgent())
     , m_loadState(Created)
@@ -291,9 +274,15 @@
     // Get the MIME type from the URL. "text/html" is a last resort, hopefully overridden.
     std::string mimeType("text/html");
     if (mime == "") {
-        // Get the MIME type from the file extension, if any.
-        FilePath path(m_url);
-        net::GetMimeTypeFromFile(path, &mimeType);
+        // Gmail appends the MIME to the end of the URL, with a ? separator.
+        size_t mimeTypeIndex = m_url.find_last_of('?');
+        if (mimeTypeIndex != std::string::npos) {
+            mimeType.assign(m_url.begin() + mimeTypeIndex + 1, m_url.end());
+        } else {
+            // Get the MIME type from the file extension, if any.
+            FilePath path(m_url);
+            net::GetMimeTypeFromFile(path, &mimeType);
+        }
     } else {
         // Set from the intercept response.
         mimeType = mime;
diff --git a/Source/WebKit/android/WebCoreSupport/WebRequest.h b/Source/WebKit/android/WebCoreSupport/WebRequest.h
index d9054e9..285e577 100644
--- a/Source/WebKit/android/WebCoreSupport/WebRequest.h
+++ b/Source/WebKit/android/WebCoreSupport/WebRequest.h
@@ -107,6 +107,7 @@
     OwnPtr<net::URLRequest> m_request;
     scoped_refptr<net::IOBuffer> m_networkBuffer;
     scoped_ptr<UrlInterceptResponse> m_interceptResponse;
+    bool m_androidUrl;
     std::string m_url;
     std::string m_userAgent;
     LoadState m_loadState;
diff --git a/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp b/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp
index 5df0ed2..43037ab 100644
--- a/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp
+++ b/Source/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp
@@ -37,7 +37,6 @@
 #include "WebRequest.h"
 #include "WebResourceRequest.h"
 
-#include <utils/Log.h>
 #include <wtf/text/CString.h>
 
 using base::Lock;
@@ -157,11 +156,11 @@
                 break;
 #if ENABLE(BLOB)
             case FormDataElement::encodedBlob:
-                ALOG_ASSERT(false, "Unexpected use of FormDataElement::encodedBlob");
+                LOG_ASSERT(false, "Unexpected use of FormDataElement::encodedBlob");
                 break;
 #endif // ENABLE(BLOB)
             default:
-                ALOG_ASSERT(false, "Unexpected default case in WebUrlLoaderClient.cpp");
+                LOG_ASSERT(false, "Unexpected default case in WebUrlLoaderClient.cpp");
                 break;
             }
         }
@@ -200,7 +199,7 @@
 
             syncCondition()->TimedWait(base::TimeDelta::FromSeconds(kCallbackWaitingTime));
             if (m_queue.empty()) {
-                ALOGE("Synchronous request timed out after %d seconds for the %dth try, URL: %s",
+                LOGE("Synchronous request timed out after %d seconds for the %dth try, URL: %s",
                      kCallbackWaitingTime, num_timeout, m_request->getUrl().c_str());
                 num_timeout++;
                 if (num_timeout >= kMaxNumTimeout) {
@@ -254,7 +253,7 @@
         if (!m_isCertMimeType)
             cancel();
     } else {
-        ALOGE("Unexpected call to downloadFile() before didReceiveResponse(). URL: %s", m_request->getUrl().c_str());
+        LOGE("Unexpected call to downloadFile() before didReceiveResponse(). URL: %s", m_request->getUrl().c_str());
         // TODO: Turn off asserts crashing before release
         // http://b/issue?id=2951985
         CRASH();
diff --git a/Source/WebKit/android/WebCoreSupport/WebViewClientError.cpp b/Source/WebKit/android/WebCoreSupport/WebViewClientError.cpp
index 1857e9c..260c76e 100644
--- a/Source/WebKit/android/WebCoreSupport/WebViewClientError.cpp
+++ b/Source/WebKit/android/WebCoreSupport/WebViewClientError.cpp
@@ -79,7 +79,6 @@
         case ERR_CONNECTION_ABORTED:
         case ERR_CONNECTION_FAILED:
         case ERR_SOCKET_NOT_CONNECTED:
-        case ERR_CACHE_MISS:
             return ERROR_CONNECT;
 
         case ERR_ADDRESS_INVALID:
diff --git a/Source/WebKit/android/WebCoreSupport/autofill/FormManagerAndroid.cpp b/Source/WebKit/android/WebCoreSupport/autofill/FormManagerAndroid.cpp
index 2969252..e837244 100644
--- a/Source/WebKit/android/WebCoreSupport/autofill/FormManagerAndroid.cpp
+++ b/Source/WebKit/android/WebCoreSupport/autofill/FormManagerAndroid.cpp
@@ -562,7 +562,7 @@
 
     ResetFrame(frame);
 
-    WTF::RefPtr<HTMLCollection> web_forms = frame->document()->forms();
+    WTF::PassRefPtr<HTMLCollection> web_forms = frame->document()->forms();
 
     for (size_t i = 0; i < web_forms->length(); ++i) {
         // Owned by |form_elements|.
diff --git a/Source/WebKit/android/benchmark/Android.mk b/Source/WebKit/android/benchmark/Android.mk
new file mode 100644
index 0000000..5b189e1
--- /dev/null
+++ b/Source/WebKit/android/benchmark/Android.mk
@@ -0,0 +1,41 @@
+##
+##
+## Copyright 2009, The Android Open Source Project
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions
+## are met:
+##  * Redistributions of source code must retain the above copyright
+##    notice, this list of conditions and the following disclaimer.
+##  * Redistributions in binary form must reproduce the above copyright
+##    notice, this list of conditions and the following disclaimer in the
+##    documentation and/or other materials provided with the distribution.
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+## PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+## EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+## PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+## PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+## OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+##
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+	main.cpp
+
+# Pull the webkit definitions from the base webkit makefile.
+LOCAL_SHARED_LIBRARIES := libwebcore $(WEBKIT_SHARED_LIBRARIES)
+LOCAL_LDLIBS := $(WEBKIT_LDLIBS)
+
+LOCAL_MODULE := webcore_test
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
diff --git a/Source/WebKit/android/benchmark/Intercept.cpp b/Source/WebKit/android/benchmark/Intercept.cpp
new file mode 100644
index 0000000..deffac2
--- /dev/null
+++ b/Source/WebKit/android/benchmark/Intercept.cpp
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "webcore_test"
+#include "config.h"
+
+#include "Base64.h"
+#include "HTTPParsers.h"
+#include "Intercept.h"
+#include "ResourceHandle.h"
+#include "ResourceHandleClient.h"
+#include "ResourceRequest.h"
+#include "ResourceResponse.h"
+#include "TextEncoding.h"
+
+#include <utils/Log.h>
+#include <wtf/HashMap.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/StringHash.h>
+
+PassRefPtr<WebCore::ResourceLoaderAndroid> MyResourceLoader::create(
+        ResourceHandle* handle, String url)
+{
+    return adoptRef<WebCore::ResourceLoaderAndroid>(
+            new MyResourceLoader(handle, url));
+}
+
+void MyResourceLoader::handleRequest()
+{
+    if (protocolIs(m_url, "data"))
+        loadData(m_url.substring(5)); // 5 for data:
+    else if (protocolIs(m_url, "file"))
+        loadFile(m_url.substring(7)); // 7 for file://
+}
+
+void MyResourceLoader::loadData(const String& data)
+{
+    LOGD("Loading data (%s) ...", data.latin1().data());
+    ResourceHandleClient* client = m_handle->client();
+    int index = data.find(',');
+    if (index == -1) {
+        client->cannotShowURL(m_handle);
+        return;
+    }
+
+    String mediaType = data.substring(0, index);
+    String base64 = data.substring(index + 1);
+
+    bool decode = mediaType.endsWith(";base64", false);
+    if (decode)
+        mediaType = mediaType.left(mediaType.length() - 7); // 7 for base64;
+
+    if (mediaType.isEmpty())
+        mediaType = "text/plain;charset=US-ASCII";
+
+    String mimeType = extractMIMETypeFromMediaType(mediaType);
+    String charset = extractCharsetFromMediaType(mediaType);
+
+    ResourceResponse response;
+    response.setMimeType(mimeType);
+
+    if (decode) {
+        base64 = decodeURLEscapeSequences(base64);
+        response.setTextEncodingName(charset);
+        client->didReceiveResponse(m_handle, response);
+
+        // FIXME: This is annoying. WebCore's Base64 decoder chokes on spaces.
+        // That is correct with strict decoding but html authors (particularly
+        // the acid3 authors) put spaces in the data which should be ignored.
+        // Remove them here before sending to the decoder.
+        Vector<char> in;
+        CString str = base64.latin1();
+        const char* chars = str.data();
+        unsigned i = 0;
+        while (i < str.length()) {
+            char c = chars[i];
+            // Don't send spaces or control characters.
+            if (c != ' ' && c != '\n' && c != '\t' && c != '\b'
+                    && c != '\f' && c != '\r')
+                in.append(chars[i]);
+            i++;
+        }
+        Vector<char> out;
+        if (base64Decode(in, out) && out.size() > 0)
+            client->didReceiveData(m_handle, out.data(), out.size(), 0);
+    } else {
+        base64 = decodeURLEscapeSequences(base64, TextEncoding(charset));
+        response.setTextEncodingName("UTF-16");
+        client->didReceiveResponse(m_handle, response);
+        if (base64.length() > 0)
+            client->didReceiveData(m_handle, (const char*)base64.characters(),
+                    base64.length() * sizeof(UChar), 0);
+    }
+    client->didFinishLoading(m_handle, 0);
+}
+static String mimeTypeForExtension(const String& file)
+{
+    static HashMap<String, String, CaseFoldingHash> extensionToMime;
+    if (extensionToMime.isEmpty()) {
+        extensionToMime.set("txt", "text/plain");
+        extensionToMime.set("html", "text/html");
+        extensionToMime.set("htm", "text/html");
+        extensionToMime.set("png", "image/png");
+        extensionToMime.set("jpeg", "image/jpeg");
+        extensionToMime.set("jpg", "image/jpeg");
+        extensionToMime.set("gif", "image/gif");
+        extensionToMime.set("ico", "image/x-icon");
+        extensionToMime.set("js", "text/javascript");
+    }
+    int dot = file.reverseFind('.');
+    String mime("text/plain");
+    if (dot != -1) {
+        String ext = file.substring(dot + 1);
+        if (extensionToMime.contains(ext))
+            mime = extensionToMime.get(ext);
+    }
+    return mime;
+}
+
+void MyResourceLoader::loadFile(const String& file)
+{
+    LOGD("Loading file (%s) ...", file.latin1().data());
+    FILE* f = fopen(file.latin1().data(), "r");
+    ResourceHandleClient* client = m_handle->client();
+    if (!f) {
+        client->didFail(m_handle,
+                ResourceError("", -14, file, "Could not open file"));
+    } else {
+        ResourceResponse response;
+        response.setTextEncodingName("utf-8");
+        response.setMimeType(mimeTypeForExtension(file));
+        client->didReceiveResponse(m_handle, response);
+        char buf[512];
+        while (true) {
+            int res = fread(buf, 1, sizeof(buf), f);
+            if (res <= 0)
+                break;
+            client->didReceiveData(m_handle, buf, res, 0);
+        }
+        fclose(f);
+        client->didFinishLoading(m_handle, 0);
+    }
+}
+
+PassRefPtr<WebCore::ResourceLoaderAndroid> MyWebFrame::startLoadingResource(
+        ResourceHandle* handle, const ResourceRequest& req, bool ignore,
+        bool ignore2)
+{
+    RefPtr<WebCore::ResourceLoaderAndroid> loader =
+            MyResourceLoader::create(handle, req.url().string());
+    m_requests.append(loader);
+    if (!m_timer.isActive())
+        m_timer.startOneShot(0);
+    return loader.release();
+}
+
+void MyWebFrame::timerFired(Timer<MyWebFrame>*)
+{
+    LOGD("Handling requests...");
+    Vector<RefPtr<WebCore::ResourceLoaderAndroid> > reqs;
+    reqs.swap(m_requests);
+    Vector<RefPtr<WebCore::ResourceLoaderAndroid> >::iterator i = reqs.begin();
+    Vector<RefPtr<WebCore::ResourceLoaderAndroid> >::iterator end = reqs.end();
+    for (; i != end; i++)
+        static_cast<MyResourceLoader*>((*i).get())->handleRequest();
+
+    LOGD("...done");
+}
diff --git a/Source/WebKit/android/benchmark/Intercept.h b/Source/WebKit/android/benchmark/Intercept.h
new file mode 100644
index 0000000..6694dba
--- /dev/null
+++ b/Source/WebKit/android/benchmark/Intercept.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Intercept_h
+#define Intercept_h
+
+#include "MyJavaVM.h"
+#include "PlatformString.h"
+#include "Timer.h"
+#include "WebCoreFrameBridge.h"
+#include "WebCoreResourceLoader.h"
+#include <JNIUtility.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+    class Page;
+    class ResourceHandle;
+    class ResourceRequest;
+}
+
+using namespace android;
+using namespace WebCore;
+using namespace WTF;
+
+class MyResourceLoader : public WebCoreResourceLoader {
+public:
+    static PassRefPtr<WebCore::ResourceLoaderAndroid> create(
+            ResourceHandle* handle, String url);
+    void handleRequest();
+
+private:
+    MyResourceLoader(ResourceHandle* handle, String url)
+        : WebCoreResourceLoader(JSC::Bindings::getJNIEnv(), MY_JOBJECT)
+        , m_handle(handle)
+        , m_url(url) {}
+
+    void loadData(const String&);
+    void loadFile(const String&);
+    ResourceHandle* m_handle;
+    String m_url;
+};
+
+class MyWebFrame : public WebFrame {
+public:
+    MyWebFrame(Page* page)
+        : WebFrame(JSC::Bindings::getJNIEnv(), MY_JOBJECT, MY_JOBJECT, page)
+        , m_timer(this, &MyWebFrame::timerFired) {}
+
+    virtual PassRefPtr<WebCore::ResourceLoaderAndroid> startLoadingResource(
+            ResourceHandle* handle, const ResourceRequest& req, bool, bool);
+
+    virtual bool canHandleRequest(const ResourceRequest&) { return true; }
+
+private:
+    void timerFired(Timer<MyWebFrame>*);
+    Vector<RefPtr<WebCore::ResourceLoaderAndroid> > m_requests;
+    Timer<MyWebFrame> m_timer;
+};
+
+#endif
diff --git a/Source/WebKit/android/benchmark/MyJavaVM.cpp b/Source/WebKit/android/benchmark/MyJavaVM.cpp
new file mode 100644
index 0000000..574c745
--- /dev/null
+++ b/Source/WebKit/android/benchmark/MyJavaVM.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MyJavaVM.h"
+
+#include <JNIUtility.h>
+#include <jni.h>
+
+static JNIEnv* s_env;
+static JavaVM* s_jvm;
+
+// JavaVM functions
+jint vm_attachCurrentThread(JavaVM*, JNIEnv** env, void*) {
+    *env = s_env;
+    return JNI_OK;
+}
+
+// JNIEnv functions
+jobject env_callObjectMethodV(JNIEnv*, jobject, jmethodID, va_list) {
+    return MY_JOBJECT;
+}
+void env_callVoidMethodV(JNIEnv*, jobject, jmethodID, va_list) {}
+void env_deleteRef(JNIEnv*, jobject) {}
+jboolean env_exceptionCheck(JNIEnv*) {
+    return false;
+}
+jclass env_findClass(JNIEnv*, const char*) {
+    return (jclass) 1;
+}
+jbyte* env_getByteArrayElements(JNIEnv*, jbyteArray, jboolean*) {
+    return NULL;
+}
+jmethodID env_getMethodID(JNIEnv*, jclass, const char*, const char*) {
+    return (jmethodID) 1;
+}
+jclass env_getObjectClass(JNIEnv*, jobject) {
+    return (jclass) 1;
+}
+static const char* s_fakeString = "Fake Java String";
+const jchar* env_getStringChars(JNIEnv*, jstring, jboolean* isCopy) {
+    if (isCopy)
+        *isCopy = false;
+    return (const jchar*)s_fakeString;
+}
+jsize env_getStringLength(JNIEnv*, jstring) {
+    return sizeof(s_fakeString) - 1;
+}
+jbyteArray env_newByteArray(JNIEnv*, jsize) {
+    return (jbyteArray) 1;
+}
+jobject env_newRef(JNIEnv*, jobject obj) {
+    return obj;
+}
+jobject env_newObjectV(JNIEnv*, jclass, jmethodID, va_list) {
+    return MY_JOBJECT;
+}
+jstring env_newString(JNIEnv*, const jchar*, jsize) {
+    return (jstring) 1;
+}
+void env_releaseByteArrayElements(JNIEnv*, jbyteArray, jbyte*, jint) {}
+void env_releaseStringChars(JNIEnv*, jstring, const jchar*) {}
+void env_setByteArrayRegion(JNIEnv*, jbyteArray, jsize, jsize, const jbyte*) {}
+void env_setIntField(JNIEnv*, jobject, jfieldID, jint) {}
+
+void InitializeJavaVM() {
+    // First, create the fake vm
+    s_jvm = new JavaVM;
+    JNIInvokeInterface* i = new JNIInvokeInterface;
+    memset(i, 0, sizeof(JNIInvokeInterface));
+    s_jvm->functions = i;
+
+    // Now, assign the functions of the vm to our fake ones.
+    i->AttachCurrentThread      = vm_attachCurrentThread;
+
+    // Create the fake env next
+    s_env = new JNIEnv;
+    JNINativeInterface* n = new JNINativeInterface;
+    memset(n, 0, sizeof(JNINativeInterface));
+    s_env->functions = n;
+
+    // Point the functions we care about to out fake ones.
+    n->CallObjectMethodV        = env_callObjectMethodV;
+    n->CallVoidMethodV          = env_callVoidMethodV;
+    n->DeleteLocalRef           = env_deleteRef;
+    n->DeleteGlobalRef          = env_deleteRef;
+    n->DeleteWeakGlobalRef      = env_deleteRef;
+    n->ExceptionCheck           = env_exceptionCheck;
+    n->FindClass                = env_findClass;
+    n->GetByteArrayElements     = env_getByteArrayElements;
+    n->GetMethodID              = env_getMethodID;
+    n->GetObjectClass           = env_getObjectClass;
+    n->GetStringChars           = env_getStringChars;
+    n->GetStringLength          = env_getStringLength;
+    n->NewByteArray             = env_newByteArray;
+    n->NewLocalRef              = env_newRef;
+    n->NewGlobalRef             = env_newRef;
+    n->NewWeakGlobalRef         = env_newRef;
+    n->NewObjectV               = env_newObjectV;
+    n->NewString                = env_newString;
+    n->ReleaseByteArrayElements = env_releaseByteArrayElements;
+    n->ReleaseStringChars       = env_releaseStringChars;
+    n->SetByteArrayRegion       = env_setByteArrayRegion;
+    n->SetIntField              = env_setIntField;
+
+    // Tell WebCore about the vm
+    JSC::Bindings::setJavaVM(s_jvm);
+}
diff --git a/Source/WebCore/platform/graphics/android/rendering/TextureOwner.h b/Source/WebKit/android/benchmark/MyJavaVM.h
similarity index 70%
copy from Source/WebCore/platform/graphics/android/rendering/TextureOwner.h
copy to Source/WebKit/android/benchmark/MyJavaVM.h
index b12d8b7..3092161 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TextureOwner.h
+++ b/Source/WebKit/android/benchmark/MyJavaVM.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010, The Android Open Source Project
+ * Copyright 2009, The Android Open Source Project
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -13,7 +13,7 @@
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -23,25 +23,12 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef TextureOwner_h
-#define TextureOwner_h
+#ifndef MyJavaVM_h
+#define MyJavaVM_h
 
-class SkCanvas;
-class Layer;
+// Make it 1 just to appease any assertions or checks for valid objects
+#define MY_JOBJECT ((jobject) 1)
 
-namespace WebCore {
+void InitializeJavaVM();
 
-class TileTexture;
-class GLWebViewState;
-
-class TextureOwner {
-public:
-    virtual ~TextureOwner() { }
-    virtual bool removeTexture(TileTexture* texture) = 0;
-    virtual bool isRepaintPending() = 0;
-    virtual unsigned long long drawCount() = 0;
-};
-
-}
-
-#endif // TextureOwner_h
+#endif
diff --git a/Source/WebKit/android/benchmark/main.cpp b/Source/WebKit/android/benchmark/main.cpp
new file mode 100644
index 0000000..fcb797d
--- /dev/null
+++ b/Source/WebKit/android/benchmark/main.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "webcore_test"
+
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <utils/Log.h>
+
+namespace android {
+extern void benchmark(const char*, int, int ,int);
+}
+
+int main(int argc, char** argv) {
+    int width = 800;
+    int height = 600;
+    int reloadCount = 0;
+    while (true) {
+        int c = getopt(argc, argv, "d:r:");
+        if (c == -1)
+            break;
+        else if (c == 'd') {
+            char* x = strchr(optarg, 'x');
+            if (x) {
+                width = atoi(optarg);
+                height = atoi(x + 1);
+                LOGD("Rendering page at %dx%d", width, height);
+            }
+        } else if (c == 'r') {
+            reloadCount = atoi(optarg);
+            if (reloadCount < 0)
+                reloadCount = 0;
+            LOGD("Reloading %d times", reloadCount);
+        }
+    }
+    if (optind >= argc) {
+        LOGE("Please supply a file to read\n");
+        return 1;
+    }
+
+    android::benchmark(argv[optind], reloadCount, width, height);
+}
diff --git a/Source/WebKit/android/content/PhoneEmailDetector.cpp b/Source/WebKit/android/content/PhoneEmailDetector.cpp
deleted file mode 100644
index ca97a71..0000000
--- a/Source/WebKit/android/content/PhoneEmailDetector.cpp
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#undef WEBKIT_IMPLEMENTATION
-#undef LOG
-
-#include "base/utf_string_conversions.h"
-#include "net/base/escape.h"
-#include "PhoneEmailDetector.h"
-#include "Settings.h"
-#include "WebString.h"
-
-#define LOG_TAG "PhoneNumberDetector"
-#include <cutils/log.h>
-
-#define PHONE_PATTERN "(200) /-.\\ 100 -. 0000"
-
-static const char kTelSchemaPrefix[] = "tel:";
-static const char kEmailSchemaPrefix[] = "mailto:";
-
-void FindReset(FindState* state);
-void FindResetNumber(FindState* state);
-FoundState FindPartialNumber(const UChar* chars, unsigned length,
-                             FindState* s);
-struct FindState;
-
-static FoundState FindPartialEMail(const UChar* , unsigned length, FindState* );
-static bool IsDomainChar(UChar ch);
-static bool IsMailboxChar(UChar ch);
-
-PhoneEmailDetector::PhoneEmailDetector()
-    : m_foundResult(FOUND_NONE)
-{
-}
-
-bool PhoneEmailDetector::IsEnabled(const WebKit::WebHitTestInfo& hit_test)
-{
-    WebCore::Settings* settings = GetSettings(hit_test);
-    if (!settings)
-        return false;
-    m_isPhoneDetectionEnabled = settings->formatDetectionTelephone();
-    m_isEmailDetectionEnabled = settings->formatDetectionEmail();
-    return m_isEmailDetectionEnabled || m_isPhoneDetectionEnabled;
-}
-
-bool PhoneEmailDetector::FindContent(const string16::const_iterator& begin,
-                             const string16::const_iterator& end,
-                             size_t* start_pos,
-                             size_t* end_pos)
-{
-    FindReset(&m_findState);
-    m_foundResult = FOUND_NONE;
-    if (m_isPhoneDetectionEnabled)
-        m_foundResult = FindPartialNumber(begin, end - begin, &m_findState);
-    if (m_foundResult == FOUND_COMPLETE)
-        m_prefix = kTelSchemaPrefix;
-    else {
-        FindReset(&m_findState);
-        if (m_isEmailDetectionEnabled)
-            m_foundResult = FindPartialEMail(begin, end - begin, &m_findState);
-        m_prefix = kEmailSchemaPrefix;
-    }
-    *start_pos = m_findState.mStartResult;
-    *end_pos = m_findState.mEndResult;
-    return m_foundResult == FOUND_COMPLETE;
-}
-
-std::string PhoneEmailDetector::GetContentText(const WebKit::WebRange& range)
-{
-    if (m_foundResult == FOUND_COMPLETE) {
-        if (m_prefix == kTelSchemaPrefix)
-            return UTF16ToUTF8(m_findState.mStore);
-        else
-            return UTF16ToUTF8(range.toPlainText());
-    }
-    return std::string();
-}
-
-GURL PhoneEmailDetector::GetIntentURL(const std::string& content_text)
-{
-    return GURL(m_prefix +
-            EscapeQueryParamValue(content_text, true));
-}
-
-void FindReset(FindState* state)
-{
-    memset(state, 0, sizeof(FindState));
-    state->mCurrent = ' ';
-    FindResetNumber(state);
-}
-
-void FindResetNumber(FindState* state)
-{
-    state->mOpenParen = false;
-    state->mPattern = (char*) PHONE_PATTERN;
-    state->mStorePtr = state->mStore;
-}
-
-FoundState FindPartialNumber(const UChar* chars, unsigned length,
-    FindState* s)
-{
-    char* pattern = s->mPattern;
-    UChar* store = s->mStorePtr;
-    const UChar* start = chars;
-    const UChar* end = chars + length;
-    const UChar* lastDigit = 0;
-    string16 search16(chars, length);
-    std::string searchSpace = UTF16ToUTF8(search16);
-    do {
-        bool initialized = s->mInitialized;
-        while (chars < end) {
-            if (initialized == false) {
-                s->mBackTwo = s->mBackOne;
-                s->mBackOne = s->mCurrent;
-            }
-            UChar ch = s->mCurrent = *chars;
-            do {
-                char patternChar = *pattern;
-                switch (patternChar) {
-                    case '2':
-                        if (initialized == false) {
-                            s->mStartResult = chars - start;
-                            initialized = true;
-                        }
-                    case '0':
-                    case '1':
-                        if (ch < patternChar || ch > '9')
-                            goto resetPattern;
-                        *store++ = ch;
-                        pattern++;
-                        lastDigit = chars;
-                        goto nextChar;
-                    case '\0':
-                        if (WTF::isASCIIDigit(ch) == false) {
-                            *store = '\0';
-                            goto checkMatch;
-                        }
-                        goto resetPattern;
-                    case ' ':
-                        if (ch == patternChar)
-                            goto nextChar;
-                        break;
-                    case '(':
-                        if (ch == patternChar) {
-                            s->mStartResult = chars - start;
-                            initialized = true;
-                            s->mOpenParen = true;
-                        }
-                        goto commonPunctuation;
-                    case ')':
-                        if ((ch == patternChar) ^ s->mOpenParen)
-                            goto resetPattern;
-                    default:
-                    commonPunctuation:
-                        if (ch == patternChar) {
-                            pattern++;
-                            goto nextChar;
-                        }
-                }
-            } while (++pattern); // never false
-    nextChar:
-            chars++;
-        }
-        break;
-resetPattern:
-        if (s->mContinuationNode)
-            return FOUND_NONE;
-        FindResetNumber(s);
-        pattern = s->mPattern;
-        store = s->mStorePtr;
-    } while (++chars < end);
-checkMatch:
-    if (WTF::isASCIIDigit(s->mBackOne != '1' ? s->mBackOne : s->mBackTwo)) {
-        return FOUND_NONE;
-    }
-    *store = '\0';
-    s->mStorePtr = store;
-    s->mPattern = pattern;
-    s->mEndResult = lastDigit - start + 1;
-    char pState = pattern[0];
-    return pState == '\0' ? FOUND_COMPLETE : pState == '(' || (WTF::isASCIIDigit(pState) && WTF::isASCIIDigit(pattern[-1])) ?
-        FOUND_NONE : FOUND_PARTIAL;
-}
-
-FoundState FindPartialEMail(const UChar* chars, unsigned length,
-    FindState* s)
-{
-    // the following tables were generated by tests/browser/focusNavigation/BrowserDebug.cpp
-    // hand-edit at your own risk
-    static const int domainTwoLetter[] = {
-        0x02df797c,  // a followed by: [cdefgilmnoqrstuwxz]
-        0x036e73fb,  // b followed by: [abdefghijmnorstvwyz]
-        0x03b67ded,  // c followed by: [acdfghiklmnorsuvxyz]
-        0x02005610,  // d followed by: [ejkmoz]
-        0x001e00d4,  // e followed by: [ceghrstu]
-        0x00025700,  // f followed by: [ijkmor]
-        0x015fb9fb,  // g followed by: [abdefghilmnpqrstuwy]
-        0x001a3400,  // h followed by: [kmnrtu]
-        0x000f7818,  // i followed by: [delmnoqrst]
-        0x0000d010,  // j followed by: [emop]
-        0x0342b1d0,  // k followed by: [eghimnprwyz]
-        0x013e0507,  // l followed by: [abcikrstuvy]
-        0x03fffccd,  // m followed by: [acdghklmnopqrstuvwxyz]
-        0x0212c975,  // n followed by: [acefgilopruz]
-        0x00001000,  // o followed by: [m]
-        0x014e3cf1,  // p followed by: [aefghklmnrstwy]
-        0x00000001,  // q followed by: [a]
-        0x00504010,  // r followed by: [eouw]
-        0x032a7fdf,  // s followed by: [abcdeghijklmnortvyz]
-        0x026afeec,  // t followed by: [cdfghjklmnoprtvwz]
-        0x03041441,  // u followed by: [agkmsyz]
-        0x00102155,  // v followed by: [aceginu]
-        0x00040020,  // w followed by: [fs]
-        0x00000000,  // x
-        0x00180010,  // y followed by: [etu]
-        0x00401001,  // z followed by: [amw]
-    };
-
-    static char const* const longDomainNames[] = {
-        "\x03" "ero" "\x03" "rpa",  // aero, arpa
-        "\x02" "iz",  // biz
-        "\x02" "at" "\x02" "om" "\x03" "oop",  // cat, com, coop
-        NULL,  // d
-        "\x02" "du",  // edu
-        NULL,  // f
-        "\x02" "ov",  // gov
-        NULL,  // h
-        "\x03" "nfo" "\x02" "nt",  // info, int
-        "\x03" "obs",  // jobs
-        NULL,  // k
-        NULL,  // l
-        "\x02" "il" "\x03" "obi" "\x05" "useum",  // mil, mobi, museum
-        "\x03" "ame" "\x02" "et",  // name, net
-        "\x02" "rg",  // , org
-        "\x02" "ro",  // pro
-        NULL,  // q
-        NULL,  // r
-        NULL,  // s
-        "\x05" "ravel",  // travel
-        NULL,  // u
-        NULL,  // v
-        NULL,  // w
-        NULL,  // x
-        NULL,  // y
-        NULL,  // z
-    };
-
-    const UChar* start = chars;
-    const UChar* end = chars + length;
-    while (chars < end) {
-        UChar ch = *chars++;
-        if (ch != '@')
-            continue;
-        const UChar* atLocation = chars - 1;
-        // search for domain
-        ch = *chars++ | 0x20; // convert uppercase to lower
-        if (ch < 'a' || ch > 'z')
-            continue;
-        while (chars < end) {
-            ch = *chars++;
-            if (IsDomainChar(ch) == false)
-                goto nextAt;
-            if (ch != '.')
-                continue;
-            UChar firstLetter = *chars++ | 0x20; // first letter of the domain
-            if (chars >= end)
-                return FOUND_NONE; // only one letter; must be at least two
-            firstLetter -= 'a';
-            if (firstLetter > 'z' - 'a')
-                continue; // non-letter followed '.'
-            int secondLetterMask = domainTwoLetter[firstLetter];
-            ch = *chars | 0x20; // second letter of the domain
-            ch -= 'a';
-            if (ch >= 'z' - 'a')
-                continue;
-            bool secondMatch = (secondLetterMask & 1 << ch) != 0;
-            const char* wordMatch = longDomainNames[firstLetter];
-            int wordIndex = 0;
-            while (wordMatch != NULL) {
-                int len = *wordMatch++;
-                char match;
-                do {
-                    match = wordMatch[wordIndex];
-                    if (match < 0x20)
-                        goto foundDomainStart;
-                    if (chars[wordIndex] != match)
-                        break;
-                    wordIndex++;
-                } while (true);
-                wordMatch += len;
-                if (*wordMatch == '\0')
-                    break;
-                wordIndex = 0;
-            }
-            if (secondMatch) {
-                wordIndex = 1;
-        foundDomainStart:
-                chars += wordIndex;
-                if (chars < end) {
-                    ch = *chars;
-                    if (ch != '.') {
-                        if (IsDomainChar(ch))
-                            goto nextDot;
-                    } else if (chars + 1 < end && IsDomainChar(chars[1]))
-                        goto nextDot;
-                }
-                // found domain. Search backwards from '@' for beginning of email address
-                s->mEndResult = chars - start;
-                chars = atLocation;
-                if (chars <= start)
-                    goto nextAt;
-                ch = *--chars;
-                if (ch == '.')
-                    goto nextAt; // mailbox can't end in period
-                do {
-                    if (IsMailboxChar(ch) == false) {
-                        chars++;
-                        break;
-                    }
-                    if (chars == start)
-                        break;
-                    ch = *--chars;
-                } while (true);
-                UChar firstChar = *chars;
-                if (firstChar == '.' || firstChar == '@') // mailbox can't start with period or be empty
-                    goto nextAt;
-                s->mStartResult = chars - start;
-                return FOUND_COMPLETE;
-            }
-    nextDot:
-            ;
-        }
-nextAt:
-        chars = atLocation + 1;
-    }
-    return FOUND_NONE;
-}
-
-bool IsDomainChar(UChar ch)
-{
-    static const unsigned body[] = {0x03ff6000, 0x07fffffe, 0x07fffffe}; // 0-9 . - A-Z a-z
-    ch -= 0x20;
-    if (ch > 'z' - 0x20)
-        return false;
-    return (body[ch >> 5] & 1 << (ch & 0x1f)) != 0;
-}
-
-bool IsMailboxChar(UChar ch)
-{
-    // According to http://en.wikipedia.org/wiki/Email_address
-    // ! # $ % & ' * + - . / 0-9 = ?
-    // A-Z ^ _
-    // ` a-z { | } ~
-    static const unsigned body[] = {0xa3ffecfa, 0xc7fffffe, 0x7fffffff};
-    ch -= 0x20;
-    if (ch > '~' - 0x20)
-        return false;
-    return (body[ch >> 5] & 1 << (ch & 0x1f)) != 0;
-}
diff --git a/Source/WebKit/android/content/PhoneEmailDetector.h b/Source/WebKit/android/content/PhoneEmailDetector.h
deleted file mode 100644
index 74ff5b1..0000000
--- a/Source/WebKit/android/content/PhoneEmailDetector.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "content/content_detector.h"
-#include "PlatformString.h"
-
-#define NAVIGATION_MAX_PHONE_LENGTH 14
-
-struct FindState {
-    int mStartResult;
-    int mEndResult;
-    char* mPattern;
-    UChar mStore[NAVIGATION_MAX_PHONE_LENGTH + 1];
-    UChar* mStorePtr;
-    UChar mBackOne;
-    UChar mBackTwo;
-    UChar mCurrent;
-    bool mOpenParen;
-    bool mInitialized;
-    bool mContinuationNode;
-};
-
-enum FoundState {
-    FOUND_NONE,
-    FOUND_PARTIAL,
-    FOUND_COMPLETE
-};
-
-// Searches for phone numbers (US only) or email addresses based off of the navcache code
-class PhoneEmailDetector : public ContentDetector {
-public:
-    PhoneEmailDetector();
-    virtual ~PhoneEmailDetector() {}
-
-private:
-    // Implementation of ContentDetector.
-    virtual bool FindContent(const string16::const_iterator& begin,
-                             const string16::const_iterator& end,
-                             size_t* start_pos,
-                             size_t* end_pos);
-
-    virtual std::string GetContentText(const WebKit::WebRange& range);
-    virtual GURL GetIntentURL(const std::string& content_text);
-    virtual size_t GetMaximumContentLength() {
-        return NAVIGATION_MAX_PHONE_LENGTH * 4;
-    }
-    virtual bool IsEnabled(const WebKit::WebHitTestInfo& hit_test) OVERRIDE;
-
-    DISALLOW_COPY_AND_ASSIGN(PhoneEmailDetector);
-
-    FindState m_findState;
-    FoundState m_foundResult;
-    const char* m_prefix;
-    // TODO: This shouldn't be done like this. PhoneEmailDetector should be
-    // refactored into two pieces and follow the IsEnabled style. This will
-    // only work because we always call IsEnabled before FindContent
-    bool m_isPhoneDetectionEnabled;
-    bool m_isEmailDetectionEnabled;
-};
diff --git a/Source/WebKit/android/content/address_detector.cpp b/Source/WebKit/android/content/address_detector.cpp
deleted file mode 100644
index f6657d9..0000000
--- a/Source/WebKit/android/content/address_detector.cpp
+++ /dev/null
@@ -1,945 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *    * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *    * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *    * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-// Magic pretend-to-be-a-chromium-build flags
-#undef WEBKIT_IMPLEMENTATION
-#undef LOG
-
-#include "content/address_detector.h"
-
-#include <bitset>
-
-#include "base/utf_string_conversions.h"
-#include "net/base/escape.h"
-#include "Settings.h"
-#include "WebString.h"
-
-#include <wtf/HashSet.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/text/StringHash.h>
-#include <wtf/text/WTFString.h>
-
-namespace {
-
-// Prefix used for geographical address intent URIs.
-static const char kAddressSchemaPrefix[] = "geo:0,0?q=";
-
-// Maximum text length to be searched for address detection.
-static const size_t kMaxAddressLength = 500;
-
-// Minimum number of words in an address after the house number
-// before a state is expected to be found.
-// A value too high can miss short addresses.
-const size_t kMinAddressWords = 3;
-
-// Maximum number of words allowed in an address between the house number
-// and the state, both not included.
-const size_t kMaxAddressWords = 12;
-
-// Maximum number of lines allowed in an address between the house number
-// and the state, both not included.
-const size_t kMaxAddressLines = 5;
-
-// Maximum length allowed for any address word between the house number
-// and the state, both not included.
-const size_t kMaxAddressNameWordLength = 25;
-
-// Maximum number of words after the house number in which the location name
-// should be found.
-const size_t kMaxLocationNameDistance = 4;
-
-// Number of digits for a valid zip code.
-const size_t kZipDigits = 5;
-
-// Number of digits for a valid zip code in the Zip Plus 4 format.
-const size_t kZipPlus4Digits = 9;
-
-// Maximum number of digits of a house number, including possible hyphens.
-const size_t kMaxHouseDigits = 5;
-
-// Additional characters used as new line delimiters.
-const char16 kNewlineDelimiters[] = {
-  ',',
-  '*',
-  0x2022,  // Unicode bullet
-  0,
-};
-
-char16 SafePreviousChar(const string16::const_iterator& it,
-    const string16::const_iterator& begin) {
-  if (it == begin)
-    return ' ';
-  return *(it - 1);
-}
-
-char16 SafeNextChar(const string16::const_iterator& it,
-    const string16::const_iterator& end) {
-  if (it == end)
-    return ' ';
-  return *(it + 1);
-}
-
-bool WordLowerCaseEqualsASCII(string16::const_iterator word_begin,
-    string16::const_iterator word_end, const char* ascii_to_match) {
-  for (string16::const_iterator it = word_begin; it != word_end;
-      ++it, ++ascii_to_match) {
-    if (!*ascii_to_match || base::ToLowerASCII(*it) != *ascii_to_match)
-      return false;
-  }
-  return *ascii_to_match == 0 || *ascii_to_match == ' ';
-}
-
-bool LowerCaseEqualsASCIIWithPlural(string16::const_iterator word_begin,
-    string16::const_iterator word_end, const char* ascii_to_match,
-    bool allow_plural) {
-  for (string16::const_iterator it = word_begin; it != word_end;
-      ++it, ++ascii_to_match) {
-    if (!*ascii_to_match && allow_plural && *it == 's' && it + 1 == word_end)
-      return true;
-
-    if (!*ascii_to_match || base::ToLowerASCII(*it) != *ascii_to_match)
-      return false;
-  }
-  return *ascii_to_match == 0;
-}
-
-}  // anonymous namespace
-
-
-AddressDetector::AddressDetector() {
-}
-
-AddressDetector::~AddressDetector() {
-}
-
-std::string AddressDetector::GetContentText(const WebKit::WebRange& range) {
-  // Get the address and replace unicode bullets with commas.
-  string16 address_16 = CollapseWhitespace(range.toPlainText(), false);
-  std::replace(address_16.begin(), address_16.end(),
-      static_cast<char16>(0x2022), static_cast<char16>(','));
-  return UTF16ToUTF8(address_16);
-}
-
-GURL AddressDetector::GetIntentURL(const std::string& content_text) {
-  return GURL(kAddressSchemaPrefix +
-      EscapeQueryParamValue(content_text, true));
-}
-
-size_t AddressDetector::GetMaximumContentLength() {
-  return kMaxAddressLength;
-}
-
-bool AddressDetector::IsEnabled(const WebKit::WebHitTestInfo& hit_test) {
-  WebCore::Settings* settings = GetSettings(hit_test);
-  return settings && settings->formatDetectionAddress();
-}
-
-bool AddressDetector::FindContent(const string16::const_iterator& begin,
-    const string16::const_iterator& end, size_t* start_pos, size_t* end_pos) {
-  HouseNumberParser house_number_parser;
-
-  // Keep going through the input string until a potential house number is
-  // detected. Start tokenizing the following words to find a valid
-  // street name within a word range. Then, find a state name followed
-  // by a valid zip code for that state. Also keep a look for any other
-  // possible house numbers to continue from in case of no match and for
-  // state names not followed by a zip code (e.g. New York, NY 10000).
-  const string16 newline_delimiters = kNewlineDelimiters;
-  const string16 delimiters = kWhitespaceUTF16 + newline_delimiters;
-  for (string16::const_iterator it = begin; it != end; ) {
-    Word house_number;
-    if (!house_number_parser.Parse(it, end, &house_number))
-      return false;
-
-    String16Tokenizer tokenizer(house_number.end, end, delimiters);
-    tokenizer.set_options(String16Tokenizer::RETURN_DELIMS);
-
-    std::vector<Word> words;
-    words.push_back(house_number);
-
-    bool found_location_name = false;
-    bool continue_on_house_number = true;
-    size_t next_house_number_word = 0;
-    size_t num_lines = 1;
-
-    // Don't include the house number in the word count.
-    size_t next_word = 1;
-    for (; next_word <= kMaxAddressWords + 1; ++next_word) {
-
-      // Extract a new word from the tokenizer.
-      if (next_word == words.size()) {
-        do {
-          if (!tokenizer.GetNext())
-            return false;
-
-          // Check the number of address lines.
-          if (tokenizer.token_is_delim() && newline_delimiters.find(
-              *tokenizer.token_begin()) != string16::npos) {
-            ++num_lines;
-          }
-        } while (tokenizer.token_is_delim());
-
-        if (num_lines > kMaxAddressLines)
-          break;
-
-        words.push_back(Word(tokenizer.token_begin(), tokenizer.token_end()));
-      }
-
-      // Check the word length. If too long, don't try to continue from
-      // the next house number as no address can hold this word.
-      const Word& current_word = words[next_word];
-      DCHECK_GT(std::distance(current_word.begin, current_word.end), 0);
-      size_t current_word_length = std::distance(
-          current_word.begin, current_word.end);
-      if (current_word_length > kMaxAddressNameWordLength) {
-        continue_on_house_number = false;
-        break;
-      }
-
-      // Check if the new word is a valid house number.
-      // This is used to properly resume parsing in case the maximum number
-      // of words is exceeded.
-      if (next_house_number_word == 0 &&
-          house_number_parser.Parse(current_word.begin, current_word.end, NULL)) {
-        next_house_number_word = next_word;
-        continue;
-      }
-
-      // Look for location names in the words after the house number.
-      // A range limitation is introduced to avoid matching
-      // anything that starts with a number before a legitimate address.
-      if (next_word <= kMaxLocationNameDistance &&
-          IsValidLocationName(current_word)) {
-        found_location_name = true;
-        continue;
-      }
-
-      // Don't count the house number.
-      if (next_word > kMinAddressWords) {
-        // Looking for the state is likely to add new words to the list while
-        // checking for multi-word state names.
-        size_t state_first_word = next_word;
-        size_t state_last_word, state_index;
-        if (FindStateStartingInWord(&words, state_first_word, &state_last_word,
-            &tokenizer, &state_index)) {
-
-          // A location name should have been found at this point.
-          if (!found_location_name)
-            break;
-
-          // Explicitly exclude "et al", as "al" is a valid state code.
-          if (current_word_length == 2 && words.size() > 2) {
-            const Word& previous_word = words[state_first_word - 1];
-            if (previous_word.end - previous_word.begin == 2 &&
-                LowerCaseEqualsASCII(previous_word.begin, previous_word.end,
-                    "et") &&
-                LowerCaseEqualsASCII(current_word.begin, current_word.end,
-                    "al"))
-              break;
-          }
-
-          // Extract one more word from the tokenizer if not already available.
-          size_t zip_word = state_last_word + 1;
-          if (zip_word == words.size()) {
-            do {
-              if (!tokenizer.GetNext()) {
-                // Zip is optional
-                *start_pos = words[0].begin - begin;
-                *end_pos = words[state_last_word].end - begin;
-                return true;
-              }
-            } while (tokenizer.token_is_delim());
-            words.push_back(Word(tokenizer.token_begin(),
-                tokenizer.token_end()));
-          }
-
-          // Check the parsing validity and state range of the zip code.
-          next_word = state_last_word;
-          if (!IsZipValid(words[zip_word], state_index))
-            continue;
-
-          *start_pos = words[0].begin - begin;
-          *end_pos = words[zip_word].end - begin;
-          return true;
-        }
-      }
-    }
-
-    // Avoid skipping too many words because of a non-address number
-    // at the beginning of the contents to parse.
-    if (continue_on_house_number && next_house_number_word > 0) {
-      it = words[next_house_number_word].begin;
-    } else {
-      DCHECK(!words.empty());
-      next_word = std::min(next_word, words.size() - 1);
-      it = words[next_word].end;
-    }
-  }
-
-  return false;
-}
-
-bool AddressDetector::HouseNumberParser::IsPreDelimiter(
-    char16 character) {
-  return character == ':' || IsPostDelimiter(character);
-}
-
-bool AddressDetector::HouseNumberParser::IsPostDelimiter(
-    char16 character) {
-  return IsWhitespace(character) || strchr(",\"'", character);
-}
-
-void AddressDetector::HouseNumberParser::RestartOnNextDelimiter() {
-  ResetState();
-  for (; it_ != end_ && !IsPreDelimiter(*it_); ++it_) {}
-}
-
-void AddressDetector::HouseNumberParser::AcceptChars(size_t num_chars) {
-  size_t offset = std::min(static_cast<size_t>(std::distance(it_, end_)),
-      num_chars);
-  it_ += offset;
-  result_chars_ += offset;
-}
-
-void AddressDetector::HouseNumberParser::SkipChars(size_t num_chars) {
-  it_ += std::min(static_cast<size_t>(std::distance(it_, end_)), num_chars);
-}
-
-void AddressDetector::HouseNumberParser::ResetState() {
-  num_digits_ = 0;
-  result_chars_ = 0;
-}
-
-bool AddressDetector::HouseNumberParser::CheckFinished(Word* word) const {
-  // There should always be a number after a hyphen.
-  if (result_chars_ == 0 || SafePreviousChar(it_, begin_) == '-')
-    return false;
-
-  if (word) {
-    word->begin = it_ - result_chars_;
-    word->end = it_;
-  }
-  return true;
-}
-
-bool AddressDetector::HouseNumberParser::Parse(
-    const string16::const_iterator& begin,
-    const string16::const_iterator& end, Word* word) {
-  it_ = begin_ = begin;
-  end_ = end;
-  ResetState();
-
-  // Iterations only used as a fail-safe against any buggy infinite loops.
-  size_t iterations = 0;
-  size_t max_iterations = end - begin + 1;
-  for (; it_ != end_ && iterations < max_iterations; ++iterations) {
-
-    // Word finished case.
-    if (IsPostDelimiter(*it_)) {
-      if (CheckFinished(word))
-        return true;
-      else if (result_chars_)
-        ResetState();
-
-      SkipChars(1);
-      continue;
-    }
-
-    // More digits. There should be no more after a letter was found.
-    if (IsAsciiDigit(*it_)) {
-      if (num_digits_ >= kMaxHouseDigits) {
-        RestartOnNextDelimiter();
-      } else {
-        AcceptChars(1);
-        ++num_digits_;
-      }
-      continue;
-    }
-
-    if (IsAsciiAlpha(*it_)) {
-      // Handle special case 'one'.
-      if (result_chars_ == 0) {
-        if (it_ + 3 <= end_ && LowerCaseEqualsASCII(it_, it_ + 3, "one"))
-          AcceptChars(3);
-        else
-          RestartOnNextDelimiter();
-        continue;
-      }
-
-      // There should be more than 1 character because of result_chars.
-      DCHECK_GT(result_chars_, 0U);
-      DCHECK_NE(it_, begin_);
-      char16 previous = SafePreviousChar(it_, begin_);
-      if (IsAsciiDigit(previous)) {
-        // Check cases like '12A'.
-        char16 next = SafeNextChar(it_, end_);
-        if (IsPostDelimiter(next)) {
-          AcceptChars(1);
-          continue;
-        }
-
-        // Handle cases like 12a, 1st, 2nd, 3rd, 7th.
-        if (IsAsciiAlpha(next)) {
-          char16 last_digit = previous;
-          char16 first_letter = base::ToLowerASCII(*it_);
-          char16 second_letter = base::ToLowerASCII(next);
-          bool is_teen = SafePreviousChar(it_ - 1, begin_) == '1' &&
-              num_digits_ == 2;
-
-          switch (last_digit - '0') {
-          case 1:
-            if ((first_letter == 's' && second_letter == 't') ||
-                (first_letter == 't' && second_letter == 'h' && is_teen)) {
-              AcceptChars(2);
-              continue;
-            }
-            break;
-
-          case 2:
-            if ((first_letter == 'n' && second_letter == 'd') ||
-                (first_letter == 't' && second_letter == 'h' && is_teen)) {
-              AcceptChars(2);
-              continue;
-            }
-            break;
-
-          case 3:
-            if ((first_letter == 'r' && second_letter == 'd') ||
-                (first_letter == 't' && second_letter == 'h' && is_teen)) {
-              AcceptChars(2);
-              continue;
-            }
-            break;
-
-          case 0:
-            // Explicitly exclude '0th'.
-            if (num_digits_ == 1)
-              break;
-
-          case 4:
-          case 5:
-          case 6:
-          case 7:
-          case 8:
-          case 9:
-            if (first_letter == 't' && second_letter == 'h') {
-              AcceptChars(2);
-              continue;
-            }
-            break;
-
-          default:
-            NOTREACHED();
-          }
-        }
-      }
-
-      RestartOnNextDelimiter();
-      continue;
-    }
-
-    if (*it_ == '-' && num_digits_ > 0) {
-      AcceptChars(1);
-      ++num_digits_;
-      continue;
-    }
-
-    RestartOnNextDelimiter();
-    SkipChars(1);
-  }
-
-  if (iterations >= max_iterations)
-    return false;
-
-  return CheckFinished(word);
-}
-
-bool AddressDetector::FindStateStartingInWord(WordList* words,
-    size_t state_first_word, size_t* state_last_word,
-    String16Tokenizer* tokenizer, size_t* state_index) {
-
-  // Bitmasks containing the allowed suffixes for 2-letter state codes.
-  static const int state_two_letter_suffix[23] = {
-    0x02060c00,  // A followed by: [KLRSZ].
-    0x00000000,  // B.
-    0x00084001,  // C followed by: [AOT].
-    0x00000014,  // D followed by: [CE].
-    0x00000000,  // E.
-    0x00001800,  // F followed by: [LM].
-    0x00100001,  // G followed by: [AU].
-    0x00000100,  // H followed by: [I].
-    0x00002809,  // I followed by: [ADLN].
-    0x00000000,  // J.
-    0x01040000,  // K followed by: [SY].
-    0x00000001,  // L followed by: [A].
-    0x000ce199,  // M followed by: [ADEHINOPST].
-    0x0120129c,  // N followed by: [CDEHJMVY].
-    0x00020480,  // O followed by: [HKR].
-    0x00420001,  // P followed by: [ARW].
-    0x00000000,  // Q.
-    0x00000100,  // R followed by: [I].
-    0x0000000c,  // S followed by: [CD].
-    0x00802000,  // T followed by: [NX].
-    0x00080000,  // U followed by: [T].
-    0x00080101,  // V followed by: [AIT].
-    0x01200101   // W followed by: [AIVY].
-  };
-
-  // Accumulative number of states for the 2-letter code indexed by the first.
-  static const int state_two_letter_accumulative[24] = {
-     0,  5,  5,  8, 10, 10, 12, 14,
-    15, 19, 19, 21, 22, 32, 40, 43,
-    46, 46, 47, 49, 51, 52, 55, 59
-  };
-
-  // State names sorted alphabetically with their lengths.
-  // There can be more than one possible name for a same state if desired.
-  static const struct StateNameInfo {
-    const char* string;
-    char first_word_length;
-    char length;
-    char state_index; // Relative to two-character code alphabetical order.
-  } state_names[59] = {
-    { "alabama", 7, 7, 1 }, { "alaska", 6, 6, 0 },
-    { "american samoa", 8, 14, 3 }, { "arizona", 7, 7, 4 },
-    { "arkansas", 8, 8, 2 },
-    { "california", 10, 10, 5 }, { "colorado", 8, 8, 6 },
-    { "connecticut", 11, 11, 7 }, { "delaware", 8, 8, 9 },
-    { "district of columbia", 8, 20, 8 },
-    { "federated states of micronesia", 9, 30, 11 }, { "florida", 7, 7, 10 },
-    { "guam", 4, 4, 13 }, { "georgia", 7, 7, 12 },
-    { "hawaii", 6, 6, 14 },
-    { "idaho", 5, 5, 16 }, { "illinois", 8, 8, 17 }, { "indiana", 7, 7, 18 },
-    { "iowa", 4, 4, 15 },
-    { "kansas", 6, 6, 19 }, { "kentucky", 8, 8, 20 },
-    { "louisiana", 9, 9, 21 },
-    { "maine", 5, 5, 24 }, { "marshall islands", 8, 16, 25 },
-    { "maryland", 8, 8, 23 }, { "massachusetts", 13, 13, 22 },
-    { "michigan", 8, 8, 26 }, { "minnesota", 9, 9, 27 },
-    { "mississippi", 11, 11, 30 }, { "missouri", 8, 8, 28 },
-    { "montana", 7, 7, 31 },
-    { "nebraska", 8, 8, 34 }, { "nevada", 6, 6, 38 },
-    { "new hampshire", 3, 13, 35 }, { "new jersey", 3, 10, 36 },
-    { "new mexico", 3, 10, 37 }, { "new york", 3, 8, 39 },
-    { "north carolina", 5, 14, 32 }, { "north dakota", 5, 12, 33 },
-    { "northern mariana islands", 8, 24, 29 },
-    { "ohio", 4, 4, 40 }, { "oklahoma", 8, 8, 41 }, { "oregon", 6, 6, 42 },
-    { "palau", 5, 5, 45 }, { "pennsylvania", 12, 12, 43 },
-    { "puerto rico", 6, 11, 44 },
-    { "rhode island", 5, 5, 46 },
-    { "south carolina", 5, 14, 47 }, { "south dakota", 5, 12, 48 },
-    { "tennessee", 9, 9, 49 }, { "texas", 5, 5, 50 },
-    { "utah", 4, 4, 51 },
-    { "vermont", 7, 7, 54 }, { "virgin islands", 6, 14, 53 },
-    { "virginia", 8, 8, 52 },
-    { "washington", 10, 10, 55 }, { "west virginia", 4, 13, 57 },
-    { "wisconsin", 9, 9, 56 }, { "wyoming", 7, 7, 58 }
-  };
-
-  // Accumulative number of states for sorted names indexed by the first letter.
-  // Required a different one since there are codes that don't share their
-  // first letter with the name of their state (MP = Northern Mariana Islands).
-  static const int state_names_accumulative[24] = {
-     0,  5,  5,  8, 10, 10, 12, 14,
-    15, 19, 19, 21, 22, 31, 40, 43,
-    46, 46, 47, 49, 51, 52, 55, 59
-  };
-
-  DCHECK_EQ(state_names_accumulative[arraysize(state_names_accumulative) - 1],
-      static_cast<int>(ARRAYSIZE_UNSAFE(state_names)));
-
-  const Word& first_word = words->at(state_first_word);
-  int length = first_word.end - first_word.begin;
-  if (length < 2 || !IsAsciiAlpha(*first_word.begin))
-    return false;
-
-  // No state names start with x, y, z.
-  char16 first_letter = base::ToLowerASCII(*first_word.begin);
-  if (first_letter > 'w')
-    return false;
-
-  DCHECK(first_letter >= 'a');
-  int first_index = first_letter - 'a';
-
-  // Look for two-letter state names.
-  if (length == 2 && IsAsciiAlpha(*(first_word.begin + 1))) {
-    char16 second_letter = base::ToLowerASCII(*(first_word.begin + 1));
-    DCHECK(second_letter >= 'a');
-
-    int second_index = second_letter - 'a';
-    if (!(state_two_letter_suffix[first_index] & (1 << second_index)))
-      return false;
-
-    std::bitset<32> previous_suffixes = state_two_letter_suffix[first_index] &
-        ((1 << second_index) - 1);
-    *state_last_word = state_first_word;
-    *state_index = state_two_letter_accumulative[first_index] +
-        previous_suffixes.count();
-    return true;
-  }
-
-  // Look for full state names by their first letter. Discard by length.
-  for (int state = state_names_accumulative[first_index];
-      state < state_names_accumulative[first_index + 1]; ++state) {
-    if (state_names[state].first_word_length != length)
-      continue;
-
-    bool state_match = false;
-    size_t state_word = state_first_word;
-    for (int pos = 0; true; ) {
-      if (!WordLowerCaseEqualsASCII(words->at(state_word).begin,
-          words->at(state_word).end, &state_names[state].string[pos]))
-        break;
-
-      pos += words->at(state_word).end - words->at(state_word).begin + 1;
-      if (pos >= state_names[state].length) {
-        state_match = true;
-        break;
-      }
-
-      // Ran out of words, extract more from the tokenizer.
-      if (++state_word == words->size()) {
-        do {
-          if (!tokenizer->GetNext())
-            break;
-        } while (tokenizer->token_is_delim());
-        words->push_back(Word(tokenizer->token_begin(), tokenizer->token_end()));
-      }
-    }
-
-    if (state_match) {
-      *state_last_word = state_word;
-      *state_index = state_names[state].state_index;
-      return true;
-    }
-  }
-
-  return false;
-}
-
-bool AddressDetector::IsZipValid(const Word& word, size_t state_index) {
-  size_t length = word.end - word.begin;
-  if (length != kZipDigits && length != kZipPlus4Digits + 1)
-    return false;
-
-  for (string16::const_iterator it = word.begin; it != word.end; ++it) {
-    size_t pos = it - word.begin;
-    if (IsAsciiDigit(*it) || (*it == '-' && pos == kZipDigits))
-      continue;
-    return false;
-  }
-  return IsZipValidForState(word, state_index);
-}
-
-bool AddressDetector::IsZipValidForState(const Word& word, size_t state_index)
-{
-    enum USState {
-        AP = -4, // AP (military base in the Pacific)
-        AA = -3, // AA (military base inside the US)
-        AE = -2, // AE (military base outside the US)
-        XX = -1, // (not in use)
-        AK =  0, // AK Alaska
-        AL =  1, // AL Alabama
-        AR =  2, // AR Arkansas
-        AS =  3, // AS American Samoa
-        AZ =  4, // AZ Arizona
-        CA =  5, // CA California
-        CO =  6, // CO Colorado
-        CT =  7, // CT Connecticut
-        DC =  8, // DC District of Columbia
-        DE =  9, // DE Delaware
-        FL = 10, // FL Florida
-        FM = 11, // FM Federated States of Micronesia
-        GA = 12, // GA Georgia
-        GU = 13, // GU Guam
-        HI = 14, // HI Hawaii
-        IA = 15, // IA Iowa
-        ID = 16, // ID Idaho
-        IL = 17, // IL Illinois
-        IN = 18, // IN Indiana
-        KS = 19, // KS Kansas
-        KY = 20, // KY Kentucky
-        LA = 21, // LA Louisiana
-        MA = 22, // MA Massachusetts
-        MD = 23, // MD Maryland
-        ME = 24, // ME Maine
-        MH = 25, // MH Marshall Islands
-        MI = 26, // MI Michigan
-        MN = 27, // MN Minnesota
-        MO = 28, // MO Missouri
-        MP = 29, // MP Northern Mariana Islands
-        MS = 30, // MS Mississippi
-        MT = 31, // MT Montana
-        NC = 32, // NC North Carolina
-        ND = 33, // ND North Dakota
-        NE = 34, // NE Nebraska
-        NH = 35, // NH New Hampshire
-        NJ = 36, // NJ New Jersey
-        NM = 37, // NM New Mexico
-        NV = 38, // NV Nevada
-        NY = 39, // NY New York
-        OH = 40, // OH Ohio
-        OK = 41, // OK Oklahoma
-        OR = 42, // OR Oregon
-        PA = 43, // PA Pennsylvania
-        PR = 44, // PR Puerto Rico
-        PW = 45, // PW Palau
-        RI = 46, // RI Rhode Island
-        SC = 47, // SC South Carolina
-        SD = 48, // SD South Dakota
-        TN = 49, // TN Tennessee
-        TX = 50, // TX Texas
-        UT = 51, // UT Utah
-        VA = 52, // VA Virginia
-        VI = 53, // VI Virgin Islands
-        VT = 54, // VT Vermont
-        WA = 55, // WA Washington
-        WI = 56, // WI Wisconsin
-        WV = 57, // WV West Virginia
-        WY = 58, // WY Wyoming
-    };
-
-    static const USState stateForZipPrefix[] = {
-    //   0   1   2   3   4   5   6   7   8   9
-        XX, XX, XX, XX, XX, NY, PR, PR, VI, PR, // 000-009
-        MA, MA, MA, MA, MA, MA, MA, MA, MA, MA, // 010-019
-        MA, MA, MA, MA, MA, MA, MA, MA, RI, RI, // 020-029
-        NH, NH, NH, NH, NH, NH, NH, NH, NH, ME, // 030-039
-        ME, ME, ME, ME, ME, ME, ME, ME, ME, ME, // 040-049
-        VT, VT, VT, VT, VT, MA, VT, VT, VT, VT, // 050-059
-        CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, // 060-069
-        NJ, NJ, NJ, NJ, NJ, NJ, NJ, NJ, NJ, NJ, // 070-079
-        NJ, NJ, NJ, NJ, NJ, NJ, NJ, NJ, NJ, NJ, // 080-089
-        AE, AE, AE, AE, AE, AE, AE, AE, AE, XX, // 090-099
-        NY, NY, NY, NY, NY, NY, NY, NY, NY, NY, // 100-109
-        NY, NY, NY, NY, NY, NY, NY, NY, NY, NY, // 110-119
-        NY, NY, NY, NY, NY, NY, NY, NY, NY, NY, // 120-129
-        NY, NY, NY, NY, NY, NY, NY, NY, NY, NY, // 130-139
-        NY, NY, NY, NY, NY, NY, NY, NY, NY, NY, // 140-149
-        PA, PA, PA, PA, PA, PA, PA, PA, PA, PA, // 150-159
-        PA, PA, PA, PA, PA, PA, PA, PA, PA, PA, // 160-169
-        PA, PA, PA, PA, PA, PA, PA, PA, PA, PA, // 170-179
-        PA, PA, PA, PA, PA, PA, PA, PA, PA, PA, // 180-189
-        PA, PA, PA, PA, PA, PA, PA, DE, DE, DE, // 190-199
-        DC, VA, DC, DC, DC, DC, MD, MD, MD, MD, // 200-209
-        MD, MD, MD, XX, MD, MD, MD, MD, MD, MD, // 210-219
-        VA, VA, VA, VA, VA, VA, VA, VA, VA, VA, // 220-229
-        VA, VA, VA, VA, VA, VA, VA, VA, VA, VA, // 230-239
-        VA, VA, VA, VA, VA, VA, VA, WV, WV, WV, // 240-249
-        WV, WV, WV, WV, WV, WV, WV, WV, WV, WV, // 250-259
-        WV, WV, WV, WV, WV, WV, WV, WV, WV, XX, // 260-269
-        NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, // 270-279
-        NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, // 280-289
-        SC, SC, SC, SC, SC, SC, SC, SC, SC, SC, // 290-299
-        GA, GA, GA, GA, GA, GA, GA, GA, GA, GA, // 300-309
-        GA, GA, GA, GA, GA, GA, GA, GA, GA, GA, // 310-319
-        FL, FL, FL, FL, FL, FL, FL, FL, FL, FL, // 320-329
-        FL, FL, FL, FL, FL, FL, FL, FL, FL, FL, // 330-339
-        AA, FL, FL, XX, FL, XX, FL, FL, XX, FL, // 340-349
-        AL, AL, AL, XX, AL, AL, AL, AL, AL, AL, // 350-359
-        AL, AL, AL, AL, AL, AL, AL, AL, AL, AL, // 360-369
-        TN, TN, TN, TN, TN, TN, TN, TN, TN, TN, // 370-379
-        TN, TN, TN, TN, TN, TN, MS, MS, MS, MS, // 380-389
-        MS, MS, MS, MS, MS, MS, MS, MS, GA, GA, // 390-399
-        KY, KY, KY, KY, KY, KY, KY, KY, KY, KY, // 400-409
-        KY, KY, KY, KY, KY, KY, KY, KY, KY, XX, // 410-419
-        KY, KY, KY, KY, KY, KY, KY, KY, XX, XX, // 420-429
-        OH, OH, OH, OH, OH, OH, OH, OH, OH, OH, // 430-439
-        OH, OH, OH, OH, OH, OH, OH, OH, OH, OH, // 440-449
-        OH, OH, OH, OH, OH, OH, OH, OH, OH, OH, // 450-459
-        IN, IN, IN, IN, IN, IN, IN, IN, IN, IN, // 460-469
-        IN, IN, IN, IN, IN, IN, IN, IN, IN, IN, // 470-479
-        MI, MI, MI, MI, MI, MI, MI, MI, MI, MI, // 480-489
-        MI, MI, MI, MI, MI, MI, MI, MI, MI, MI, // 490-499
-        IA, IA, IA, IA, IA, IA, IA, IA, IA, IA, // 500-509
-        IA, IA, IA, IA, IA, IA, IA, XX, XX, XX, // 510-519
-        IA, IA, IA, IA, IA, IA, IA, IA, IA, XX, // 520-529
-        WI, WI, WI, XX, WI, WI, XX, WI, WI, WI, // 530-539
-        WI, WI, WI, WI, WI, WI, WI, WI, WI, WI, // 540-549
-        MN, MN, XX, MN, MN, MN, MN, MN, MN, MN, // 550-559
-        MN, MN, MN, MN, MN, MN, MN, MN, XX, DC, // 560-569
-        SD, SD, SD, SD, SD, SD, SD, SD, XX, XX, // 570-579
-        ND, ND, ND, ND, ND, ND, ND, ND, ND, XX, // 580-589
-        MT, MT, MT, MT, MT, MT, MT, MT, MT, MT, // 590-599
-        IL, IL, IL, IL, IL, IL, IL, IL, IL, IL, // 600-609
-        IL, IL, IL, IL, IL, IL, IL, IL, IL, IL, // 610-619
-        IL, XX, IL, IL, IL, IL, IL, IL, IL, IL, // 620-629
-        MO, MO, XX, MO, MO, MO, MO, MO, MO, MO, // 630-639
-        MO, MO, XX, XX, MO, MO, MO, MO, MO, MO, // 640-649
-        MO, MO, MO, MO, MO, MO, MO, MO, MO, XX, // 650-659
-        KS, KS, KS, XX, KS, KS, KS, KS, KS, KS, // 660-669
-        KS, KS, KS, KS, KS, KS, KS, KS, KS, KS, // 670-679
-        NE, NE, XX, NE, NE, NE, NE, NE, NE, NE, // 680-689
-        NE, NE, NE, NE, XX, XX, XX, XX, XX, XX, // 690-699
-        LA, LA, XX, LA, LA, LA, LA, LA, LA, XX, // 700-709
-        LA, LA, LA, LA, LA, XX, AR, AR, AR, AR, // 710-719
-        AR, AR, AR, AR, AR, AR, AR, AR, AR, AR, // 720-729
-        OK, OK, XX, TX, OK, OK, OK, OK, OK, OK, // 730-739
-        OK, OK, XX, OK, OK, OK, OK, OK, OK, OK, // 740-749
-        TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, // 750-759
-        TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, // 760-769
-        TX, XX, TX, TX, TX, TX, TX, TX, TX, TX, // 770-779
-        TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, // 780-789
-        TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, // 790-799
-        CO, CO, CO, CO, CO, CO, CO, CO, CO, CO, // 800-809
-        CO, CO, CO, CO, CO, CO, CO, XX, XX, XX, // 810-819
-        WY, WY, WY, WY, WY, WY, WY, WY, WY, WY, // 820-829
-        WY, WY, ID, ID, ID, ID, ID, ID, ID, XX, // 830-839
-        UT, UT, UT, UT, UT, UT, UT, UT, XX, XX, // 840-849
-        AZ, AZ, AZ, AZ, XX, AZ, AZ, AZ, XX, AZ, // 850-859
-        AZ, XX, XX, AZ, AZ, AZ, XX, XX, XX, XX, // 860-869
-        NM, NM, NM, NM, NM, NM, XX, NM, NM, NM, // 870-879
-        NM, NM, NM, NM, NM, TX, XX, XX, XX, NV, // 880-889
-        NV, NV, XX, NV, NV, NV, XX, NV, NV, XX, // 890-899
-        CA, CA, CA, CA, CA, CA, CA, CA, CA, XX, // 900-909
-        CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, // 910-919
-        CA, CA, CA, CA, CA, CA, CA, CA, CA, XX, // 920-929
-        CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, // 930-939
-        CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, // 940-949
-        CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, // 950-959
-        CA, CA, AP, AP, AP, AP, AP, HI, HI, GU, // 960-969
-        OR, OR, OR, OR, OR, OR, OR, OR, OR, OR, // 970-979
-        WA, WA, WA, WA, WA, WA, WA, XX, WA, WA, // 980-989
-        WA, WA, WA, WA, WA, AK, AK, AK, AK, AK, // 990-999
-    };
-
-    if (!word.begin || !word.end || (word.end - word.begin) < 3)
-        return false;
-    const char16* zipPtr = word.begin;
-    if (zipPtr[0] < '0' || zipPtr[0] > '9' ||
-        zipPtr[1] < '0' || zipPtr[1] > '9' ||
-        zipPtr[2] < '0' || zipPtr[2] > '9')
-        return false;
-
-    int zip = zipPtr[0] - '0';
-    zip *= 10;
-    zip += zipPtr[1] - '0';
-    zip *= 10;
-    zip += zipPtr[2] - '0';
-    return stateForZipPrefix[zip] == (int) state_index;
-}
-
-static const char* s_rawStreetSuffixes[] = {
-    "allee", "alley", "ally", "aly",
-    "anex", "annex", "anx", "arc", "arcade", "av", "ave", "aven", "avenu",
-    "avenue", "avn", "avnue", "bayoo", "bayou", "bch", "beach", "bend",
-    "bg", "bgs", "blf", "blfs", "bluf", "bluff", "bluffs", "blvd", "bnd",
-    "bot", "bottm", "bottom", "boul", "boulevard", "boulv", "br", "branch",
-    "brdge", "brg", "bridge", "brk", "brks", "brnch", "brook", "brooks",
-    "btm", "burg", "burgs", "byp", "bypa", "bypas", "bypass", "byps", "byu",
-    "camp", "canyn", "canyon", "cape", "causeway", "causway", "cen", "cent",
-    "center", "centers", "centr", "centre", "cir", "circ", "circl",
-    "circle", "circles", "cirs", "ck", "clb", "clf", "clfs", "cliff",
-    "cliffs", "club", "cmn", "cmp", "cnter", "cntr", "cnyn", "common",
-    "cor", "corner", "corners", "cors", "course", "court", "courts", "cove",
-    "coves", "cp", "cpe", "cr", "crcl", "crcle", "crecent", "creek", "cres",
-    "crescent", "cresent", "crest", "crk", "crossing", "crossroad",
-    "crscnt", "crse", "crsent", "crsnt", "crssing", "crssng", "crst", "crt",
-    "cswy", "ct", "ctr", "ctrs", "cts", "curv", "curve", "cv", "cvs", "cyn",
-    "dale", "dam", "div", "divide", "dl", "dm", "dr", "driv", "drive",
-    "drives", "drs", "drv", "dv", "dvd", "est", "estate", "estates", "ests",
-    "exp", "expr", "express", "expressway", "expw", "expy", "ext",
-    "extension", "extensions", "extn", "extnsn", "exts", "fall", "falls",
-    "ferry", "field", "fields", "flat", "flats", "fld", "flds", "fls",
-    "flt", "flts", "ford", "fords", "forest", "forests", "forg", "forge",
-    "forges", "fork", "forks", "fort", "frd", "frds", "freeway", "freewy",
-    "frg", "frgs", "frk", "frks", "frry", "frst", "frt", "frway", "frwy",
-    "fry", "ft", "fwy", "garden", "gardens", "gardn", "gateway", "gatewy",
-    "gatway", "gdn", "gdns", "glen", "glens", "gln", "glns", "grden",
-    "grdn", "grdns", "green", "greens", "grn", "grns", "grov", "grove",
-    "groves", "grv", "grvs", "gtway", "gtwy", "harb", "harbor", "harbors",
-    "harbr", "haven", "havn", "hbr", "hbrs", "height", "heights", "hgts",
-    "highway", "highwy", "hill", "hills", "hiway", "hiwy", "hl", "hllw",
-    "hls", "hollow", "hollows", "holw", "holws", "hrbor", "ht", "hts",
-    "hvn", "hway", "hwy", "inlet", "inlt", "is", "island", "islands",
-    "isle", "isles", "islnd", "islnds", "iss", "jct", "jction", "jctn",
-    "jctns", "jcts", "junction", "junctions", "junctn", "juncton", "key",
-    "keys", "knl", "knls", "knol", "knoll", "knolls", "ky", "kys", "la",
-    "lake", "lakes", "land", "landing", "lane", "lanes", "lck", "lcks",
-    "ldg", "ldge", "lf", "lgt", "lgts", "light", "lights", "lk", "lks",
-    "ln", "lndg", "lndng", "loaf", "lock", "locks", "lodg", "lodge", "loop",
-    "loops", "mall", "manor", "manors", "mdw", "mdws", "meadow", "meadows",
-    "medows", "mews", "mill", "mills", "mission", "missn", "ml", "mls",
-    "mnr", "mnrs", "mnt", "mntain", "mntn", "mntns", "motorway", "mount",
-    "mountain", "mountains", "mountin", "msn", "mssn", "mt", "mtin", "mtn",
-    "mtns", "mtwy", "nck", "neck", "opas", "orch", "orchard", "orchrd",
-    "oval", "overpass", "ovl", "park", "parks", "parkway", "parkways",
-    "parkwy", "pass", "passage", "path", "paths", "pike", "pikes", "pine",
-    "pines", "pk", "pkway", "pkwy", "pkwys", "pky", "pl", "place", "plain",
-    "plaines", "plains", "plaza", "pln", "plns", "plz", "plza", "pne",
-    "pnes", "point", "points", "port", "ports", "pr", "prairie", "prarie",
-    "prk", "prr", "prt", "prts", "psge", "pt", "pts", "rad", "radial",
-    "radiel", "radl", "ramp", "ranch", "ranches", "rapid", "rapids", "rd",
-    "rdg", "rdge", "rdgs", "rds", "real", "rest", "ridge", "ridges", "riv", "river",
-    "rivr", "rnch", "rnchs", "road", "roads", "route", "row", "rpd", "rpds",
-    "rst", "rte", "rue", "run", "rvr", "shl", "shls", "shoal", "shoals",
-    "shoar", "shoars", "shore", "shores", "shr", "shrs", "skwy", "skyway",
-    "smt", "spg", "spgs", "spng", "spngs", "spring", "springs", "sprng",
-    "sprngs", "spur", "spurs", "sq", "sqr", "sqre", "sqrs", "sqs", "squ",
-    "square", "squares", "st", "sta", "station", "statn", "stn", "str",
-    "stra", "strav", "strave", "straven", "stravenue", "stravn", "stream",
-    "street", "streets", "streme", "strm", "strt", "strvn", "strvnue",
-    "sts", "sumit", "sumitt", "summit", "ter", "terr", "terrace",
-    "throughway", "tpk", "tpke", "tr", "trace", "traces", "track", "tracks",
-    "trafficway", "trail", "trails", "trak", "trce", "trfy", "trk", "trks",
-    "trl", "trls", "trnpk", "trpk", "trwy", "tunel", "tunl", "tunls",
-    "tunnel", "tunnels", "tunnl", "turnpike", "turnpk", "un", "underpass",
-    "union", "unions", "uns", "upas", "valley", "valleys", "vally", "vdct",
-    "via", "viadct", "viaduct", "view", "views", "vill", "villag",
-    "village", "villages", "ville", "villg", "villiage", "vis", "vist",
-    "vista", "vl", "vlg", "vlgs", "vlly", "vly", "vlys", "vst", "vsta",
-    "vw", "vws", "walk", "walks", "wall", "way", "ways", "well", "wells",
-    "wl", "wls", "wy", "xing", "xrd",
-    0,
-};
-
-bool AddressDetector::IsValidLocationName(const Word& word) {
-    using namespace WTF;
-    static HashSet<String> streetNames;
-    if (!streetNames.size()) {
-        const char** suffixes = s_rawStreetSuffixes;
-        while (const char* suffix = *suffixes) {
-            int index = suffix[0] - 'a';
-            streetNames.add(suffix);
-            suffixes++;
-        }
-    }
-    char16 first_letter = base::ToLowerASCII(*word.begin);
-    if (first_letter > 'z' || first_letter < 'a')
-        return false;
-    int index = first_letter - 'a';
-    int length = std::distance(word.begin, word.end);
-    if (*word.end == '.')
-        length--;
-    String value(word.begin, length);
-    return streetNames.contains(value.lower());
-}
diff --git a/Source/WebKit/android/content/address_detector.h b/Source/WebKit/android/content/address_detector.h
deleted file mode 100644
index 6dc4ce8..0000000
--- a/Source/WebKit/android/content/address_detector.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *    * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *    * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *    * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CONTENT_RENDERER_ANDROID_ADDRESS_DETECTOR_H_
-#define CONTENT_RENDERER_ANDROID_ADDRESS_DETECTOR_H_
-#pragma once
-
-#include "build/build_config.h"  // Needed for OS_ANDROID
-
-#if defined(OS_ANDROID)
-
-#include <vector>
-
-#include "base/string_tokenizer.h"
-#include "base/string_util.h"
-#include "content/content_detector.h"
-
-// Finds a geographical address (currently US only) in the given text string.
-class AddressDetector : public ContentDetector {
- public:
-  AddressDetector();
-  virtual ~AddressDetector();
-
-  // Implementation of ContentDetector.
-  virtual bool FindContent(const string16::const_iterator& begin,
-                           const string16::const_iterator& end,
-                           size_t* start_pos,
-                           size_t* end_pos) OVERRIDE;
-
- private:
-  friend class AddressDetectorTest;
-
-  virtual std::string GetContentText(const WebKit::WebRange& range) OVERRIDE;
-  virtual GURL GetIntentURL(const std::string& content_text) OVERRIDE;
-  virtual size_t GetMaximumContentLength() OVERRIDE;
-  virtual bool IsEnabled(const WebKit::WebHitTestInfo& hit_test) OVERRIDE;
-
-  // Internal structs and classes. Required to be visible by the unit tests.
-  struct Word {
-    string16::const_iterator begin;
-    string16::const_iterator end;
-
-    Word() {}
-    Word(const string16::const_iterator& begin_it,
-         const string16::const_iterator& end_it)
-        : begin(begin_it),
-          end(end_it) {
-      DCHECK(begin_it <= end_it);
-    }
-  };
-
-  class HouseNumberParser {
-   public:
-    HouseNumberParser() {}
-
-    bool Parse(const string16::const_iterator& begin,
-               const string16::const_iterator& end,
-               Word* word);
-
-   private:
-    static inline bool IsPreDelimiter(char16 character);
-    static inline bool IsPostDelimiter(char16 character);
-    inline void RestartOnNextDelimiter();
-
-    inline bool CheckFinished(Word* word) const;
-    inline void AcceptChars(size_t num_chars);
-    inline void SkipChars(size_t num_chars);
-    inline void ResetState();
-
-    // Iterators to the beginning, current position and ending of the string
-    // being currently parsed.
-    string16::const_iterator begin_;
-    string16::const_iterator it_;
-    string16::const_iterator end_;
-
-    // Number of digits found in the current result candidate.
-    size_t num_digits_;
-
-    // Number of characters previous to the current iterator that belong
-    // to the current result candidate.
-    size_t result_chars_;
-
-    DISALLOW_COPY_AND_ASSIGN(HouseNumberParser);
-  };
-
-  typedef std::vector<Word> WordList;
-  typedef StringTokenizerT<string16, string16::const_iterator>
-      String16Tokenizer;
-
-  static bool FindStateStartingInWord(WordList* words,
-                                      size_t state_first_word,
-                                      size_t* state_last_word,
-                                      String16Tokenizer* tokenizer,
-                                      size_t* state_index);
-
-  static bool IsValidLocationName(const Word& word);
-  static bool IsZipValid(const Word& word, size_t state_index);
-  static bool IsZipValidForState(const Word& word, size_t state_index);
-
-  DISALLOW_COPY_AND_ASSIGN(AddressDetector);
-};
-
-#endif  // defined(OS_ANDROID)
-
-#endif  // CONTENT_RENDERER_ANDROID_ADDRESS_DETECTOR_H_
diff --git a/Source/WebKit/android/content/content_detector.cpp b/Source/WebKit/android/content/content_detector.cpp
deleted file mode 100644
index e423207..0000000
--- a/Source/WebKit/android/content/content_detector.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *    * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *    * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *    * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-// Magic pretend-to-be-a-chromium-build flags
-#undef WEBKIT_IMPLEMENTATION
-#undef LOG
-
-#include "content/content_detector.h"
-
-#include "public/android/WebDOMTextContentWalker.h"
-#include "public/android/WebHitTestInfo.h"
-
-#include "Document.h"
-#include "Node.h"
-#include "Page.h"
-#include "Settings.h"
-
-using WebKit::WebDOMTextContentWalker;
-using WebKit::WebRange;
-
-ContentDetector::Result ContentDetector::FindTappedContent(
-    const WebKit::WebHitTestInfo& hit_test) {
-  if (!IsEnabled(hit_test))
-    return Result();
-  WebKit::WebRange range = FindContentRange(hit_test);
-  if (range.isNull())
-    return Result();
-
-  std::string text = GetContentText(range);
-  GURL intent_url = GetIntentURL(text);
-  return Result(range, text, intent_url);
-}
-
-WebRange ContentDetector::FindContentRange(
-    const WebKit::WebHitTestInfo& hit_test) {
-  WebDOMTextContentWalker content_walker(hit_test, GetMaximumContentLength());
-  string16 content = content_walker.content();
-  if (content.empty())
-    return WebRange();
-
-  size_t selected_offset = content_walker.hitOffsetInContent();
-  for (size_t start_offset = 0; start_offset < content.length();) {
-    size_t relative_start, relative_end;
-    if (!FindContent(content.begin() + start_offset,
-        content.end(), &relative_start, &relative_end)) {
-      break;
-    } else {
-      size_t content_start = start_offset + relative_start;
-      size_t content_end = start_offset + relative_end;
-      DCHECK(content_end <= content.length());
-
-      if (selected_offset >= content_start && selected_offset < content_end) {
-        WebRange range = content_walker.contentOffsetsToRange(
-            content_start, content_end);
-        DCHECK(!range.isNull());
-        return range;
-      } else {
-        start_offset += relative_end;
-      }
-    }
-  }
-
-  return WebRange();
-}
-
-WebCore::Settings* ContentDetector::GetSettings(const WebKit::WebHitTestInfo& hit_test) {
-  if (!hit_test.node() || !hit_test.node()->document())
-    return 0;
-  return hit_test.node()->document()->page()->settings();
-}
diff --git a/Source/WebKit/android/content/content_detector.h b/Source/WebKit/android/content/content_detector.h
deleted file mode 100644
index 270928d..0000000
--- a/Source/WebKit/android/content/content_detector.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *    * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *    * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *    * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CONTENT_RENDERER_ANDROID_CONTENT_DETECTOR_H_
-#define CONTENT_RENDERER_ANDROID_CONTENT_DETECTOR_H_
-#pragma once
-
-#include "build/build_config.h"  // Needed for OS_ANDROID
-
-#if defined(OS_ANDROID)
-
-#include "base/string_util.h"
-#include "googleurl/src/gurl.h"
-#include "public/WebRange.h"
-
-namespace WebKit {
-class WebHitTestInfo;
-}
-
-namespace WebCore {
-class Settings;
-}
-
-// Base class for text-based content detectors.
-class ContentDetector {
- public:
-
-  // Holds the content detection results.
-  struct Result {
-    bool valid; // Flag indicating if the result is valid.
-    WebKit::WebRange range; // Range describing the content boundaries.
-    std::string text; // Processed text of the content.
-    GURL intent_url; // URL of the intent that should process this content.
-
-    Result() : valid(false) {}
-
-    Result(const WebKit::WebRange& range,
-           const std::string& text,
-           const GURL& intent_url)
-        : valid(true),
-          range(range),
-          text(text),
-          intent_url(intent_url) {}
-  };
-
-  virtual ~ContentDetector() {}
-
-  // Returns a WebKit range delimiting the contents found around the tapped
-  // position. If no content is found a null range will be returned.
-  Result FindTappedContent(const WebKit::WebHitTestInfo& hit_test);
-
- protected:
-  // Parses the input string defined by the begin/end iterators returning true
-  // if the desired content is found. The start and end positions relative to
-  // the input iterators are returned in start_pos and end_pos.
-  // The end position is assumed to be non-inclusive.
-  virtual bool FindContent(const string16::const_iterator& begin,
-                           const string16::const_iterator& end,
-                           size_t* start_pos,
-                           size_t* end_pos) = 0;
-
-  virtual bool IsEnabled(const WebKit::WebHitTestInfo& hit_test) = 0;
-  WebCore::Settings* GetSettings(const WebKit::WebHitTestInfo& hit_test);
-
-  // Extracts and processes the text of the detected content.
-  virtual std::string GetContentText(const WebKit::WebRange& range) = 0;
-
-  // Returns the intent URL that should process the content, if any.
-  virtual GURL GetIntentURL(const std::string& content_text) = 0;
-
-  // Returns the maximum length of text to be extracted around the tapped
-  // position in order to search for content.
-  virtual size_t GetMaximumContentLength() = 0;
-
-  ContentDetector() {}
-  WebKit::WebRange FindContentRange(const WebKit::WebHitTestInfo& hit_test);
-
-  DISALLOW_COPY_AND_ASSIGN(ContentDetector);
-};
-
-#endif  // defined(OS_ANDROID)
-
-#endif  // CONTENT_RENDERER_ANDROID_CONTENT_DETECTOR_H_
diff --git a/Source/WebKit/android/jni/AndroidHitTestResult.cpp b/Source/WebKit/android/jni/AndroidHitTestResult.cpp
deleted file mode 100644
index a135c42..0000000
--- a/Source/WebKit/android/jni/AndroidHitTestResult.cpp
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "AndroidHitTestResult"
-
-#include "config.h"
-#include "AndroidHitTestResult.h"
-
-#include "content/address_detector.h"
-#include "content/PhoneEmailDetector.h"
-#include "android/WebHitTestInfo.h"
-#include "Document.h"
-#include "Element.h"
-#include "Frame.h"
-#include "HitTestResult.h"
-#include "KURL.h"
-#include "LayerAndroid.h"
-#include "PlatformString.h"
-#include "Range.h"
-#include "RenderLayer.h"
-#include "RenderLayerBacking.h"
-#include "RenderObject.h"
-#include "WebCoreJni.h"
-#include "WebViewCore.h"
-
-#include <cutils/log.h>
-#include <JNIHelp.h>
-#include <JNIUtility.h>
-
-namespace android {
-
-using namespace WebCore;
-
-static bool gJniInitialized = false;
-static struct {
-    jmethodID m_Init;
-    jfieldID m_LinkUrl;
-    jfieldID m_AnchorText;
-    jfieldID m_ImageUrl;
-    jfieldID m_AltDisplayString;
-    jfieldID m_Title;
-    jfieldID m_Editable;
-    jfieldID m_TouchRects;
-    jfieldID m_TapHighlightColor;
-    jfieldID m_EnclosingParentRects;
-    jfieldID m_HasFocus;
-    jfieldID m_IntentUrl;
-} gHitTestGlue;
-
-struct field {
-    jclass m_class;
-    const char *m_fieldName;
-    const char *m_fieldType;
-    jfieldID *m_jfield;
-};
-
-static void InitJni(JNIEnv* env)
-{
-    if (gJniInitialized)
-        return;
-
-    jclass rectClass = env->FindClass("android/graphics/Rect");
-    ALOG_ASSERT(rectClass, "Could not find android/graphics/Rect");
-    jclass hitTestClass = env->FindClass("android/webkit/WebViewCore$WebKitHitTest");
-    ALOG_ASSERT(hitTestClass, "Could not find android/webkit/WebViewCore$WebKitHitTest");
-
-    gHitTestGlue.m_Init = env->GetMethodID(hitTestClass, "<init>",  "()V");
-    ALOG_ASSERT(gHitTestGlue.m_Init, "Could not find init method on android/webkit/WebViewCore$WebKitHitTest");
-
-    field fields[] = {
-        { hitTestClass, "mTouchRects", "[Landroid/graphics/Rect;", &gHitTestGlue.m_TouchRects },
-        { hitTestClass, "mEditable", "Z", &gHitTestGlue.m_Editable },
-        { hitTestClass, "mLinkUrl", "Ljava/lang/String;", &gHitTestGlue.m_LinkUrl },
-        { hitTestClass, "mIntentUrl", "Ljava/lang/String;", &gHitTestGlue.m_IntentUrl },
-        { hitTestClass, "mAnchorText", "Ljava/lang/String;", &gHitTestGlue.m_AnchorText },
-        { hitTestClass, "mImageUrl", "Ljava/lang/String;", &gHitTestGlue.m_ImageUrl },
-        { hitTestClass, "mAltDisplayString", "Ljava/lang/String;", &gHitTestGlue.m_AltDisplayString },
-        { hitTestClass, "mTitle", "Ljava/lang/String;", &gHitTestGlue.m_Title },
-        { hitTestClass, "mTapHighlightColor", "I", &gHitTestGlue.m_TapHighlightColor },
-        { hitTestClass, "mEnclosingParentRects", "[Landroid/graphics/Rect;", &gHitTestGlue.m_EnclosingParentRects },
-        { hitTestClass, "mHasFocus", "Z", &gHitTestGlue.m_HasFocus },
-        {0, 0, 0, 0},
-    };
-
-    for (int i = 0; fields[i].m_jfield; i++) {
-        field *f = &fields[i];
-        jfieldID field = env->GetFieldID(f->m_class, f->m_fieldName, f->m_fieldType);
-        ALOG_ASSERT(field, "Can't find %s", f->m_fieldName);
-        *(f->m_jfield) = field;
-    }
-
-    gJniInitialized = true;
-}
-
-AndroidHitTestResult::AndroidHitTestResult(WebViewCore* webViewCore, WebCore::HitTestResult& hitTestResult)
-    : m_webViewCore(webViewCore)
-    , m_hitTestResult(hitTestResult)
-{
-    buildHighlightRects();
-}
-
-void AndroidHitTestResult::setURLElement(Element* element)
-{
-    m_hitTestResult.setURLElement(element);
-    buildHighlightRects();
-}
-
-void AndroidHitTestResult::buildHighlightRects()
-{
-    m_highlightRects.clear();
-    Node* node = m_hitTestResult.URLElement();
-    if (!node || !node->renderer())
-        node = m_hitTestResult.innerNode();
-    if (!node || !node->renderer())
-        return;
-    if (!WebViewCore::nodeIsClickableOrFocusable(node))
-        return;
-    Frame* frame = node->document()->frame();
-    IntPoint frameOffset = m_webViewCore->convertGlobalContentToFrameContent(IntPoint(), frame);
-    RenderObject* renderer = node->renderer();
-    Vector<FloatQuad> quads;
-    if (renderer->isInline())
-        renderer->absoluteFocusRingQuads(quads);
-    if (!quads.size())
-        renderer->absoluteQuads(quads); // No fancy rings, grab a bounding box
-    for (size_t i = 0; i < quads.size(); i++) {
-        IntRect boundingBox = quads[i].enclosingBoundingBox();
-        boundingBox.move(-frameOffset.x(), -frameOffset.y());
-        m_highlightRects.append(boundingBox);
-    }
-}
-
-void AndroidHitTestResult::searchContentDetectors()
-{
-    AddressDetector address;
-    PhoneEmailDetector phoneEmail;
-    Node* node = m_hitTestResult.innerNode();
-    if (!node || !node->isTextNode())
-        return;
-    if (!m_hitTestResult.absoluteLinkURL().isEmpty())
-        return;
-    WebKit::WebHitTestInfo webHitTest(m_hitTestResult);
-    m_searchResult = address.FindTappedContent(webHitTest);
-    if (!m_searchResult.valid) {
-        m_searchResult = phoneEmail.FindTappedContent(webHitTest);
-    }
-    if (m_searchResult.valid) {
-        m_highlightRects.clear();
-        RefPtr<Range> range = (PassRefPtr<Range>) m_searchResult.range;
-        range->textRects(m_highlightRects, true);
-    }
-}
-
-void setStringField(JNIEnv* env, jobject obj, jfieldID field, const String& str)
-{
-    jstring jstr = wtfStringToJstring(env, str, false);
-    env->SetObjectField(obj, field, jstr);
-    env->DeleteLocalRef(jstr);
-}
-
-void setStringField(JNIEnv* env, jobject obj, jfieldID field, const GURL& url)
-{
-    jstring jstr = stdStringToJstring(env, url.spec(), false);
-    env->SetObjectField(obj, field, jstr);
-    env->DeleteLocalRef(jstr);
-}
-
-void setRectArray(JNIEnv* env, jobject obj, jfieldID field, Vector<IntRect> &rects)
-{
-    jobjectArray array = intRectVectorToRectArray(env, rects);
-    env->SetObjectField(obj, field, array);
-    env->DeleteLocalRef(array);
-}
-
-// Some helper macros specific to setting hitTest fields
-#define _SET(jtype, jfield, value) env->Set ## jtype ## Field(hitTest, gHitTestGlue.m_ ## jfield, value)
-#define SET_BOOL(jfield, value) _SET(Boolean, jfield, value)
-#define SET_STRING(jfield, value) setStringField(env, hitTest, gHitTestGlue.m_ ## jfield, value)
-#define SET_INT(jfield, value) _SET(Int, jfield, value)
-
-jobject AndroidHitTestResult::createJavaObject(JNIEnv* env)
-{
-    InitJni(env);
-    jclass hitTestClass = env->FindClass("android/webkit/WebViewCore$WebKitHitTest");
-    ALOG_ASSERT(hitTestClass, "Could not find android/webkit/WebViewCore$WebKitHitTest");
-
-    jobject hitTest = env->NewObject(hitTestClass, gHitTestGlue.m_Init);
-    setRectArray(env, hitTest, gHitTestGlue.m_TouchRects, m_highlightRects);
-
-    Vector<IntRect> rects = enclosingParentRects(m_hitTestResult.innerNode());
-    setRectArray(env, hitTest, gHitTestGlue.m_EnclosingParentRects, rects);
-
-    SET_BOOL(Editable, m_hitTestResult.isContentEditable());
-    SET_STRING(LinkUrl, m_hitTestResult.absoluteLinkURL().string());
-    if (m_searchResult.valid)
-        SET_STRING(IntentUrl, m_searchResult.intent_url);
-    SET_STRING(ImageUrl, m_hitTestResult.absoluteImageURL().string());
-    SET_STRING(AltDisplayString, m_hitTestResult.altDisplayString());
-    TextDirection titleTextDirection;
-    SET_STRING(Title, m_hitTestResult.title(titleTextDirection));
-    if (m_hitTestResult.URLElement()) {
-        Element* urlElement = m_hitTestResult.URLElement();
-        SET_STRING(AnchorText, urlElement->innerText());
-        if (urlElement->renderer()) {
-            SET_INT(TapHighlightColor,
-                    urlElement->renderer()->style()->tapHighlightColor().rgb());
-        }
-    }
-    Node* focusedNode = m_webViewCore->focusedFrame()->document()->focusedNode();
-    SET_BOOL(HasFocus,
-             focusedNode == m_hitTestResult.URLElement()
-             || focusedNode == m_hitTestResult.innerNode()
-             || focusedNode == m_hitTestResult.innerNonSharedNode());
-
-    env->DeleteLocalRef(hitTestClass);
-
-    return hitTest;
-}
-
-Vector<IntRect> AndroidHitTestResult::enclosingParentRects(Node* node)
-{
-    int count = 0;
-    int lastX = 0;
-    Vector<IntRect> rects;
-
-    while (node && count < 5) {
-        RenderObject* render = node->renderer();
-        if (!render || render->isBody())
-            break;
-
-        IntPoint frameOffset = m_webViewCore->convertGlobalContentToFrameContent(IntPoint(),
-                node->document()->frame());
-        IntRect rect = render->absoluteBoundingBoxRect();
-        rect.move(-frameOffset.x(), -frameOffset.y());
-        if (count == 0 || rect.x() != lastX) {
-            rects.append(rect);
-            lastX = rect.x();
-            count++;
-        }
-
-        node = node->parentNode();
-    }
-
-    return rects;
-}
-
-} /* namespace android */
diff --git a/Source/WebKit/android/jni/AndroidHitTestResult.h b/Source/WebKit/android/jni/AndroidHitTestResult.h
deleted file mode 100644
index 5bbfc6b..0000000
--- a/Source/WebKit/android/jni/AndroidHitTestResult.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef AndroidHitTestResult_h
-#define AndroidHitTestResult_h
-
-#include "content/content_detector.h"
-#include "Element.h"
-#include "HitTestResult.h"
-#include "IntRect.h"
-#include "wtf/Vector.h"
-
-#include <jni.h>
-
-namespace android {
-
-class WebViewCore;
-
-class AndroidHitTestResult
-{
-public:
-    AndroidHitTestResult(WebViewCore*, WebCore::HitTestResult&);
-    ~AndroidHitTestResult() {}
-
-    WebCore::HitTestResult& hitTestResult() { return m_hitTestResult; }
-    Vector<WebCore::IntRect>& highlightRects() { return m_highlightRects; }
-
-    void setURLElement(WebCore::Element* element);
-    void buildHighlightRects();
-    void searchContentDetectors();
-
-    jobject createJavaObject(JNIEnv*);
-
-private:
-    Vector<WebCore::IntRect> enclosingParentRects(WebCore::Node* node);
-
-    WebViewCore* m_webViewCore;
-    WebCore::HitTestResult m_hitTestResult;
-    Vector<WebCore::IntRect> m_highlightRects;
-    ContentDetector::Result m_searchResult;
-};
-
-}   // namespace android
-
-#endif // AndroidHitTestResult_h
diff --git a/Source/WebKit/android/jni/CacheManager.cpp b/Source/WebKit/android/jni/CacheManager.cpp
index b34776d..f600d00 100644
--- a/Source/WebKit/android/jni/CacheManager.cpp
+++ b/Source/WebKit/android/jni/CacheManager.cpp
@@ -25,6 +25,8 @@
 
 #include "config.h"
 
+#if USE(CHROME_NETWORK_STACK)
+
 #include "ChromiumIncludes.h"
 #include "WebCache.h"
 #include "WebCoreJni.h"
@@ -131,10 +133,12 @@
 {
 #ifndef NDEBUG
     jclass cacheManager = env->FindClass(javaCacheManagerClass);
-    ALOG_ASSERT(cacheManager, "Unable to find class");
+    LOG_ASSERT(cacheManager, "Unable to find class");
     env->DeleteLocalRef(cacheManager);
 #endif
     return jniRegisterNativeMethods(env, javaCacheManagerClass, gCacheManagerMethods, NELEM(gCacheManagerMethods));
 }
 
 } // namespace android
+
+#endif //  USE(CHROME_NETWORK_STACK)
diff --git a/Source/WebKit/android/jni/CookieManager.cpp b/Source/WebKit/android/jni/CookieManager.cpp
index 5db1e16..f8c2dee 100644
--- a/Source/WebKit/android/jni/CookieManager.cpp
+++ b/Source/WebKit/android/jni/CookieManager.cpp
@@ -35,35 +35,54 @@
 
 namespace android {
 
-// JNI for android.webkit.CookieManagerClassic
-static const char* javaCookieManagerClass = "android/webkit/CookieManagerClassic";
+// JNI for android.webkit.CookieManager
+static const char* javaCookieManagerClass = "android/webkit/CookieManager";
 
 static bool acceptCookie(JNIEnv*, jobject)
 {
+#if USE(CHROME_NETWORK_STACK)
     // This is a static method which gets the cookie policy for all WebViews. We
     // always apply the same configuration to the contexts for both regular and
     // private browsing, so expect the same result here.
     bool regularAcceptCookies = WebCookieJar::get(false)->allowCookies();
     ASSERT(regularAcceptCookies == WebCookieJar::get(true)->allowCookies());
     return regularAcceptCookies;
+#else
+    // The Android HTTP stack is implemented Java-side.
+    ASSERT_NOT_REACHED();
+    return false;
+#endif
 }
 
 static jstring getCookie(JNIEnv* env, jobject, jstring url, jboolean privateBrowsing)
 {
+#if USE(CHROME_NETWORK_STACK)
     GURL gurl(jstringToStdString(env, url));
     CookieOptions options;
     options.set_include_httponly();
     std::string cookies = WebCookieJar::get(privateBrowsing)->cookieStore()->GetCookieMonster()->GetCookiesWithOptions(gurl, options);
     return stdStringToJstring(env, cookies);
+#else
+    // The Android HTTP stack is implemented Java-side.
+    ASSERT_NOT_REACHED();
+    return jstring();
+#endif
 }
 
 static bool hasCookies(JNIEnv*, jobject, jboolean privateBrowsing)
 {
+#if USE(CHROME_NETWORK_STACK)
     return WebCookieJar::get(privateBrowsing)->getNumCookiesInDatabase() > 0;
+#else
+    // The Android HTTP stack is implemented Java-side.
+    ASSERT_NOT_REACHED();
+    return false;
+#endif
 }
 
 static void removeAllCookie(JNIEnv*, jobject)
 {
+#if USE(CHROME_NETWORK_STACK)
     WebCookieJar::get(false)->cookieStore()->GetCookieMonster()->DeleteAll(true);
     // This will lazily create a new private browsing context. However, if the
     // context doesn't already exist, there's no need to create it, as cookies
@@ -75,62 +94,84 @@
     // The Java code removes cookies directly from the backing database, so we do the same,
     // but with a NULL callback so it's asynchronous.
     WebCookieJar::get(true)->cookieStore()->GetCookieMonster()->FlushStore(NULL);
+#endif
 }
 
 static void removeExpiredCookie(JNIEnv*, jobject)
 {
+#if USE(CHROME_NETWORK_STACK)
     // This simply forces a GC. The getters delete expired cookies so won't return expired cookies anyway.
     WebCookieJar::get(false)->cookieStore()->GetCookieMonster()->GetAllCookies();
     WebCookieJar::get(true)->cookieStore()->GetCookieMonster()->GetAllCookies();
+#endif
 }
 
 static void removeSessionCookies(WebCookieJar* cookieJar)
 {
+#if USE(CHROME_NETWORK_STACK)
   CookieMonster* cookieMonster = cookieJar->cookieStore()->GetCookieMonster();
   CookieList cookies = cookieMonster->GetAllCookies();
   for (CookieList::const_iterator iter = cookies.begin(); iter != cookies.end(); ++iter) {
     if (iter->IsSessionCookie())
       cookieMonster->DeleteCanonicalCookie(*iter);
   }
+#endif
 }
 
 static void removeSessionCookie(JNIEnv*, jobject)
 {
+#if USE(CHROME_NETWORK_STACK)
   removeSessionCookies(WebCookieJar::get(false));
   removeSessionCookies(WebCookieJar::get(true));
+#endif
 }
 
 static void setAcceptCookie(JNIEnv*, jobject, jboolean accept)
 {
+#if USE(CHROME_NETWORK_STACK)
     // This is a static method which configures the cookie policy for all
     // WebViews, so we configure the contexts for both regular and private
     // browsing.
     WebCookieJar::get(false)->setAllowCookies(accept);
     WebCookieJar::get(true)->setAllowCookies(accept);
+#endif
 }
 
 static void setCookie(JNIEnv* env, jobject, jstring url, jstring value, jboolean privateBrowsing)
 {
+#if USE(CHROME_NETWORK_STACK)
     GURL gurl(jstringToStdString(env, url));
     std::string line(jstringToStdString(env, value));
     CookieOptions options;
     options.set_include_httponly();
     WebCookieJar::get(privateBrowsing)->cookieStore()->GetCookieMonster()->SetCookieWithOptions(gurl, line, options);
+#endif
 }
 
 static void flushCookieStore(JNIEnv*, jobject)
 {
+#if USE(CHROME_NETWORK_STACK)
     WebCookieJar::flush();
+#endif
 }
 
 static bool acceptFileSchemeCookies(JNIEnv*, jobject)
 {
+#if USE(CHROME_NETWORK_STACK)
     return WebCookieJar::acceptFileSchemeCookies();
+#else
+    // File scheme cookies are always accepted with the Android HTTP stack.
+    return true;
+#endif
 }
 
 static void setAcceptFileSchemeCookies(JNIEnv*, jobject, jboolean accept)
 {
+#if USE(CHROME_NETWORK_STACK)
     WebCookieJar::setAcceptFileSchemeCookies(accept);
+#else
+    // File scheme cookies are always accepted with the Android HTTP stack.
+#endif
 }
 
 static JNINativeMethod gCookieManagerMethods[] = {
@@ -151,7 +192,7 @@
 {
 #ifndef NDEBUG
     jclass cookieManager = env->FindClass(javaCookieManagerClass);
-    ALOG_ASSERT(cookieManager, "Unable to find class");
+    LOG_ASSERT(cookieManager, "Unable to find class");
     env->DeleteLocalRef(cookieManager);
 #endif
     return jniRegisterNativeMethods(env, javaCookieManagerClass, gCookieManagerMethods, NELEM(gCookieManagerMethods));
diff --git a/Source/WebKit/android/jni/DeviceMotionAndOrientationManager.cpp b/Source/WebKit/android/jni/DeviceMotionAndOrientationManager.cpp
index b69c2af..8beb372 100644
--- a/Source/WebKit/android/jni/DeviceMotionAndOrientationManager.cpp
+++ b/Source/WebKit/android/jni/DeviceMotionAndOrientationManager.cpp
@@ -46,7 +46,7 @@
 {
 }
 
-void DeviceMotionAndOrientationManager::setUseMock()
+void DeviceMotionAndOrientationManager::useMock()
 {
     m_useMock = true;
 }
@@ -124,9 +124,9 @@
     return reinterpret_cast<WebViewCore*>(env->GetIntField(webViewCoreObject, nativeClassField));
 }
 
-static void setUseMock(JNIEnv* env, jobject, jobject webViewCoreObject)
+static void useMock(JNIEnv* env, jobject, jobject webViewCoreObject)
 {
-    getWebViewCore(env, webViewCoreObject)->deviceMotionAndOrientationManager()->setUseMock();
+    getWebViewCore(env, webViewCoreObject)->deviceMotionAndOrientationManager()->useMock();
 }
 
 static void onMotionChange(JNIEnv* env, jobject, jobject webViewCoreObject, bool canProvideX, double x, bool canProvideY, double y, bool canProvideZ, double z, double interval)
@@ -151,7 +151,7 @@
 }
 
 static JNINativeMethod gDeviceMotionAndOrientationManagerMethods[] = {
-    { "nativeSetUseMock", "(Landroid/webkit/WebViewCore;)V", (void*) setUseMock },
+    { "nativeUseMock", "(Landroid/webkit/WebViewCore;)V", (void*) useMock },
     { "nativeOnMotionChange", "(Landroid/webkit/WebViewCore;ZDZDZDD)V", (void*) onMotionChange },
     { "nativeSetMockOrientation", "(Landroid/webkit/WebViewCore;ZDZDZD)V", (void*) setMockOrientation },
     { "nativeOnOrientationChange", "(Landroid/webkit/WebViewCore;ZDZDZD)V", (void*) onOrientationChange }
@@ -161,7 +161,7 @@
 {
 #ifndef NDEBUG
     jclass deviceMotionAndOrientationManager = env->FindClass(javaDeviceMotionAndOrientationManagerClass);
-    ALOG_ASSERT(deviceMotionAndOrientationManager, "Unable to find class");
+    LOG_ASSERT(deviceMotionAndOrientationManager, "Unable to find class");
     env->DeleteLocalRef(deviceMotionAndOrientationManager);
 #endif
 
diff --git a/Source/WebKit/android/jni/DeviceMotionAndOrientationManager.h b/Source/WebKit/android/jni/DeviceMotionAndOrientationManager.h
index cc6821d..44463c1 100644
--- a/Source/WebKit/android/jni/DeviceMotionAndOrientationManager.h
+++ b/Source/WebKit/android/jni/DeviceMotionAndOrientationManager.h
@@ -46,7 +46,7 @@
 public:
     DeviceMotionAndOrientationManager(WebViewCore*);
 
-    void setUseMock();
+    void useMock();
     void setMockMotion(PassRefPtr<WebCore::DeviceMotionData>);
     void onMotionChange(PassRefPtr<WebCore::DeviceMotionData>);
     void setMockOrientation(PassRefPtr<WebCore::DeviceOrientation>);
diff --git a/Source/WebKit/android/jni/GeolocationPermissionsBridge.cpp b/Source/WebKit/android/jni/GeolocationPermissionsBridge.cpp
index 295b347..a366601 100755
--- a/Source/WebKit/android/jni/GeolocationPermissionsBridge.cpp
+++ b/Source/WebKit/android/jni/GeolocationPermissionsBridge.cpp
@@ -99,10 +99,10 @@
 
 int registerGeolocationPermissions(JNIEnv* env)
 {
-    const char* kGeolocationPermissionsClass = "android/webkit/GeolocationPermissionsClassic";
+    const char* kGeolocationPermissionsClass = "android/webkit/GeolocationPermissions";
 #ifndef NDEBUG
     jclass geolocationPermissions = env->FindClass(kGeolocationPermissionsClass);
-    ALOG_ASSERT(geolocationPermissions, "Unable to find class");
+    LOG_ASSERT(geolocationPermissions, "Unable to find class");
     env->DeleteLocalRef(geolocationPermissions);
 #endif
 
diff --git a/Source/WebKit/android/jni/JavaBridge.cpp b/Source/WebKit/android/jni/JavaBridge.cpp
index 9f89ccd..68eb367 100644
--- a/Source/WebKit/android/jni/JavaBridge.cpp
+++ b/Source/WebKit/android/jni/JavaBridge.cpp
@@ -41,6 +41,9 @@
 #include "PluginDatabase.h"
 #include "Timer.h"
 #include "TimerClient.h"
+#ifdef ANDROID_INSTRUMENT
+#include "TimeCounter.h"
+#endif
 #include "WebCache.h"
 #include "WebCoreJni.h"
 
@@ -145,15 +148,15 @@
     mResolveFilePathForContentUri = env->GetMethodID(clazz, "resolveFilePathForContentUri", "(Ljava/lang/String;)Ljava/lang/String;");
     env->DeleteLocalRef(clazz);
 
-    ALOG_ASSERT(mSetSharedTimer, "Could not find method setSharedTimer");
-    ALOG_ASSERT(mStopSharedTimer, "Could not find method stopSharedTimer");
-    ALOG_ASSERT(mSetCookies, "Could not find method setCookies");
-    ALOG_ASSERT(mCookies, "Could not find method cookies");
-    ALOG_ASSERT(mCookiesEnabled, "Could not find method cookiesEnabled");
-    ALOG_ASSERT(mGetPluginDirectories, "Could not find method getPluginDirectories");
-    ALOG_ASSERT(mGetPluginSharedDataDirectory, "Could not find method getPluginSharedDataDirectory");
-    ALOG_ASSERT(mGetKeyStrengthList, "Could not find method getKeyStrengthList");
-    ALOG_ASSERT(mGetSignedPublicKey, "Could not find method getSignedPublicKey");
+    LOG_ASSERT(mSetSharedTimer, "Could not find method setSharedTimer");
+    LOG_ASSERT(mStopSharedTimer, "Could not find method stopSharedTimer");
+    LOG_ASSERT(mSetCookies, "Could not find method setCookies");
+    LOG_ASSERT(mCookies, "Could not find method cookies");
+    LOG_ASSERT(mCookiesEnabled, "Could not find method cookiesEnabled");
+    LOG_ASSERT(mGetPluginDirectories, "Could not find method getPluginDirectories");
+    LOG_ASSERT(mGetPluginSharedDataDirectory, "Could not find method getPluginSharedDataDirectory");
+    LOG_ASSERT(mGetKeyStrengthList, "Could not find method getKeyStrengthList");
+    LOG_ASSERT(mGetSignedPublicKey, "Could not find method getSignedPublicKey");
 
     JavaSharedClient::SetTimerClient(this);
     JavaSharedClient::SetCookieClient(this);
@@ -280,7 +283,7 @@
 void
 JavaBridge::setSharedTimerCallback(void (*f)())
 {
-    ALOG_ASSERT(!sSharedTimerFiredCallback || sSharedTimerFiredCallback==f,
+    LOG_ASSERT(!sSharedTimerFiredCallback || sSharedTimerFiredCallback==f,
                "Shared timer callback may already be set or null!");
 
     sSharedTimerFiredCallback = f;
@@ -360,8 +363,8 @@
 {
     JavaBridge* javaBridge = (JavaBridge*)
         (env->GetIntField(obj, gJavaBridge_ObjectID));    
-    ALOG_ASSERT(javaBridge, "Finalize should not be called twice for the same java bridge!");
-    ALOGV("webcore_javabridge::nativeFinalize(%p)\n", javaBridge);
+    LOG_ASSERT(javaBridge, "Finalize should not be called twice for the same java bridge!");
+    LOGV("webcore_javabridge::nativeFinalize(%p)\n", javaBridge);
     delete javaBridge;
     env->SetIntField(obj, gJavaBridge_ObjectID, 0);
 }
@@ -370,7 +373,16 @@
 void JavaBridge::SharedTimerFired(JNIEnv* env, jobject)
 {
     if (sSharedTimerFiredCallback)
+    {
+#ifdef ANDROID_INSTRUMENT
+        TimeCounter::start(TimeCounter::SharedTimerTimeCounter);
+#endif
+        SkAutoMemoryUsageProbe  mup("JavaBridge::sharedTimerFired");
         sSharedTimerFiredCallback();
+#ifdef ANDROID_INSTRUMENT
+        TimeCounter::record(TimeCounter::SharedTimerTimeCounter, __FUNCTION__);
+#endif
+    }
 }
 
 void JavaBridge::SetCacheSize(JNIEnv* env, jobject obj, jint bytes)
@@ -469,10 +481,12 @@
 
 void JavaBridge::UpdateProxy(JNIEnv* env, jobject obj, jstring newProxy, jstring newExList)
 {
+#if USE(CHROME_NETWORK_STACK)
     std::string proxy = jstringToStdString(env, newProxy);
     std::string exList = jstringToStdString(env, newExList);
     WebCache::get(false)->proxy()->UpdateProxySettings(proxy, exList);
     WebCache::get(true)->proxy()->UpdateProxySettings(proxy, exList);
+#endif
 }
 
 
diff --git a/Source/WebKit/android/jni/JavaSharedClient.cpp b/Source/WebKit/android/jni/JavaSharedClient.cpp
index 4d073c2..4f40355 100644
--- a/Source/WebKit/android/jni/JavaSharedClient.cpp
+++ b/Source/WebKit/android/jni/JavaSharedClient.cpp
@@ -88,12 +88,12 @@
     FileSystemClient* JavaSharedClient::gFileSystemClient = NULL;
 
     ///////////////////////////////////////////////////////////////////////////
-
+    
     struct FuncPtrRec {
         void (*fProc)(void* payload);
         void* fPayload;
     };
-
+    
     static SkMutex gFuncPtrQMutex;
     static SkDeque gFuncPtrQ(sizeof(FuncPtrRec));
 
@@ -105,34 +105,33 @@
         FuncPtrRec* rec = (FuncPtrRec*)gFuncPtrQ.push_back();
         rec->fProc = proc;
         rec->fPayload = payload;
-
+        
         gFuncPtrQMutex.release();
-
+        
         gTimerClient->signalServiceFuncPtrQueue();
     }
 
     void JavaSharedClient::ServiceFunctionPtrQueue()
     {
-        // Don't let execution block the WebViewCore thread for too long.
-        void (*proc)(void*) = 0;
-        void* payload = 0;
-        const FuncPtrRec* rec;
+        for (;;) {
+            void (*proc)(void*) = 0;
+            void* payload = 0;
+            const FuncPtrRec* rec;
 
-        // we have to copy the proc/payload (if present). we do this so we
-        // don't call the proc inside the mutex (possible deadlock!)
-        gFuncPtrQMutex.acquire();
-        rec = (const FuncPtrRec*)gFuncPtrQ.front();
-        if (rec) {
-            proc = rec->fProc;
-            payload = rec->fPayload;
-            gFuncPtrQ.pop_front();
-        }
-        bool scheduleAdditionalCall = (gFuncPtrQ.count() > 0);
-        gFuncPtrQMutex.release();
+            // we have to copy the proc/payload (if present). we do this so we
+            // don't call the proc inside the mutex (possible deadlock!)
+            gFuncPtrQMutex.acquire();
+            rec = (const FuncPtrRec*)gFuncPtrQ.front();
+            if (rec) {
+                proc = rec->fProc;
+                payload = rec->fPayload;
+                gFuncPtrQ.pop_front();
+            }
+            gFuncPtrQMutex.release();
 
-        if (rec)
+            if (!rec)
+                break;
             proc(payload);
-        if (scheduleAdditionalCall)
-            gTimerClient->signalServiceFuncPtrQueue();
+        }
     }
 }
diff --git a/Source/WebCore/platform/graphics/android/rendering/TextureOwner.h b/Source/WebKit/android/jni/JniUtil.cpp
similarity index 64%
copy from Source/WebCore/platform/graphics/android/rendering/TextureOwner.h
copy to Source/WebKit/android/jni/JniUtil.cpp
index b12d8b7..ee1e3f9 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TextureOwner.h
+++ b/Source/WebKit/android/jni/JniUtil.cpp
@@ -23,25 +23,36 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef TextureOwner_h
-#define TextureOwner_h
+#include "config.h"
 
-class SkCanvas;
-class Layer;
+#include "ChromiumIncludes.h"
+#include <JNIHelp.h>
 
-namespace WebCore {
+namespace android {
 
-class TileTexture;
-class GLWebViewState;
+static const char* javaJniUtilClass = "android/webkit/JniUtil";
 
-class TextureOwner {
-public:
-    virtual ~TextureOwner() { }
-    virtual bool removeTexture(TileTexture* texture) = 0;
-    virtual bool isRepaintPending() = 0;
-    virtual unsigned long long drawCount() = 0;
-};
-
+static bool useChromiumHttpStack(JNIEnv*, jobject)
+{
+#if USE(CHROME_NETWORK_STACK)
+    return true;
+#else
+    return false;
+#endif
 }
 
-#endif // TextureOwner_h
+static JNINativeMethod gJniUtilMethods[] = {
+    { "nativeUseChromiumHttpStack", "()Z", (void*) useChromiumHttpStack },
+};
+
+int registerJniUtil(JNIEnv* env)
+{
+#ifndef NDEBUG
+    jclass jniUtil = env->FindClass(javaJniUtilClass);
+    LOG_ASSERT(jniUtil, "Unable to find class");
+    env->DeleteLocalRef(jniUtil);
+#endif
+    return jniRegisterNativeMethods(env, javaJniUtilClass, gJniUtilMethods, NELEM(gJniUtilMethods));
+}
+
+} // namespace android
diff --git a/Source/WebKit/android/jni/MIMETypeRegistry.cpp b/Source/WebKit/android/jni/MIMETypeRegistry.cpp
index 2734aeb..cbfef6c 100644
--- a/Source/WebKit/android/jni/MIMETypeRegistry.cpp
+++ b/Source/WebKit/android/jni/MIMETypeRegistry.cpp
@@ -44,11 +44,11 @@
     ASSERT(isMainThread());
     JNIEnv* env = JSC::Bindings::getJNIEnv();
     jclass mimeClass = env->FindClass("android/webkit/MimeTypeMap");
-    ALOG_ASSERT(mimeClass, "Could not find class MimeTypeMap");
+    LOG_ASSERT(mimeClass, "Could not find class MimeTypeMap");
     jmethodID mimeTypeFromExtension = env->GetStaticMethodID(mimeClass,
             "mimeTypeFromExtension",
             "(Ljava/lang/String;)Ljava/lang/String;");
-    ALOG_ASSERT(mimeTypeFromExtension,
+    LOG_ASSERT(mimeTypeFromExtension,
             "Could not find method mimeTypeFromExtension");
     jstring extString = wtfStringToJstring(env, ext);
     jobject mimeType = env->CallStaticObjectMethod(mimeClass,
diff --git a/Source/WebKit/android/jni/MockGeolocation.cpp b/Source/WebKit/android/jni/MockGeolocation.cpp
index 250953f..1370715 100755
--- a/Source/WebKit/android/jni/MockGeolocation.cpp
+++ b/Source/WebKit/android/jni/MockGeolocation.cpp
@@ -74,7 +74,7 @@
 {
 #ifndef NDEBUG
     jclass mockGeolocation = env->FindClass(javaMockGeolocationClass);
-    ALOG_ASSERT(mockGeolocation, "Unable to find class");
+    LOG_ASSERT(mockGeolocation, "Unable to find class");
     env->DeleteLocalRef(mockGeolocation);
 #endif
 
diff --git a/Source/WebKit/android/jni/PicturePile.cpp b/Source/WebKit/android/jni/PicturePile.cpp
deleted file mode 100644
index ccdfa59..0000000
--- a/Source/WebKit/android/jni/PicturePile.cpp
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "PicturePile"
-#define LOG_NDEBUG 1
-
-#include "config.h"
-#include "PicturePile.h"
-
-#include "AndroidLog.h"
-#include "FloatRect.h"
-#include "GraphicsContext.h"
-#include "PlatformGraphicsContextSkia.h"
-#include "SkCanvas.h"
-#include "SkNWayCanvas.h"
-#include "SkPicture.h"
-#include "SkPixelRef.h"
-#include "SkRect.h"
-#include "SkRegion.h"
-
-#define ENABLE_PRERENDERED_INVALS true
-#define MAX_OVERLAP_COUNT 2
-#define MAX_OVERLAP_AREA .7
-
-namespace WebCore {
-
-static SkIRect toSkIRect(const IntRect& rect) {
-    return SkIRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height());
-}
-
-static IntRect extractClipBounds(SkCanvas* canvas, const IntSize& size) {
-    SkRect clip;
-    canvas->getClipBounds(&clip);
-    clip.intersect(0, 0, size.width(), size.height());
-    return enclosingIntRect(clip);
-}
-
-PicturePile::PicturePile(const PicturePile& other)
-    : m_size(other.m_size)
-    , m_pile(other.m_pile)
-    , m_webkitInvals(other.m_webkitInvals)
-{
-}
-
-PicturePile::PicturePile(SkPicture* picture)
-{
-    m_size = IntSize(picture->width(), picture->height());
-    PictureContainer pc(IntRect(0, 0, m_size.width(), m_size.height()));
-    pc.picture = picture;
-    pc.dirty = false;
-    m_pile.append(pc);
-}
-
-void PicturePile::draw(SkCanvas* canvas)
-{
-    /* Loop down recursively, subtracting the previous clip from the SkRegion,
-     * stopping when the SkRegion is empty. This will still draw back-to-front,
-     * but it will clip out anything obscured. For performance reasons we use
-     * the rect bounds of the SkRegion for the clip, so this still can't be
-     * used for translucent surfaces
-     */
-    TRACE_METHOD();
-    IntRect clipBounds = extractClipBounds(canvas, m_size);
-    SkRegion clipRegion(toSkIRect(clipBounds));
-    drawWithClipRecursive(canvas, clipRegion, m_pile.size() - 1);
-}
-
-void PicturePile::clearPrerenders()
-{
-    for (size_t i = 0; i < m_pile.size(); i++)
-        m_pile[i].prerendered.clear();
-}
-
-void PicturePile::drawWithClipRecursive(SkCanvas* canvas, SkRegion& clipRegion,
-                                        int index)
-{
-    // TODO: Add some debug visualizations of this
-    if (index < 0 || clipRegion.isEmpty())
-        return;
-    PictureContainer& pc = m_pile[index];
-    IntRect intersection = clipRegion.getBounds();
-    intersection.intersect(pc.area);
-    if (pc.picture && !intersection.isEmpty()) {
-        clipRegion.op(intersection, SkRegion::kDifference_Op);
-        drawWithClipRecursive(canvas, clipRegion, index - 1);
-        int saved = canvas->save();
-        canvas->clipRect(intersection);
-        canvas->translate(pc.area.x(), pc.area.y());
-        canvas->drawPicture(*pc.picture);
-        canvas->restoreToCount(saved);
-    } else
-        drawWithClipRecursive(canvas, clipRegion, index - 1);
-}
-
-// Used by WebViewCore
-void PicturePile::invalidate(const IntRect& dirtyRect)
-{
-    // This will typically happen if the document has been resized but we haven't
-    // drawn yet. As the first draw after a size change will do a full inval anyway,
-    // don't bother tracking individual rects
-    // TODO: Instead of clipping here, we should take the invals as given
-    // and when the size changes just inval the deltas. This prevents a full
-    // redraw for a page that grows
-    IntRect inval = dirtyRect;
-    inval.intersect(IntRect(0, 0, m_size.width(), m_size.height()));
-    if (inval.isEmpty()) {
-        ALOGV("Rejecting inval " INT_RECT_FORMAT, INT_RECT_ARGS(dirtyRect));
-        return;
-    }
-    // TODO: Support multiple non-intersecting webkit invals
-    if (m_webkitInvals.size())
-        m_webkitInvals[0].unite(inval);
-    else
-        m_webkitInvals.append(inval);
-}
-
-void PicturePile::setSize(const IntSize& size)
-{
-    if (m_size == size)
-        return;
-    m_size = size;
-    // TODO: See above about just adding invals for new content
-    m_pile.clear();
-    m_webkitInvals.clear();
-    if (!size.isEmpty()) {
-        IntRect area(0, 0, size.width(), size.height());
-        m_webkitInvals.append(area);
-        m_pile.append(area);
-    }
-}
-
-void PicturePile::updatePicturesIfNeeded(PicturePainter* painter)
-{
-    applyWebkitInvals();
-    for (size_t i = 0; i < m_pile.size(); i++) {
-        PictureContainer& pc = m_pile[i];
-        if (pc.dirty)
-            updatePicture(painter, pc);
-    }
-}
-
-void PicturePile::updatePicture(PicturePainter* painter, PictureContainer& pc)
-{
-    /* The ref counting here is a bit unusual. What happens is begin/end recording
-     * will ref/unref the recording canvas. However, 'canvas' might be pointing
-     * at an SkNWayCanvas instead of the recording canvas, which needs to be
-     * unref'd. Thus what we do is ref the recording canvas so that we can
-     * always unref whatever canvas we have at the end.
-     */
-    TRACE_METHOD();
-    SkPicture* picture = new SkPicture();
-    SkCanvas* canvas = picture->beginRecording(pc.area.width(), pc.area.height(),
-            SkPicture::kUsePathBoundsForClip_RecordingFlag);
-    SkSafeRef(canvas);
-    canvas->translate(-pc.area.x(), -pc.area.y());
-    IntRect drawArea = pc.area;
-    if (pc.prerendered.get()) {
-        SkCanvas* prerender = painter->createPrerenderCanvas(pc.prerendered.get());
-        if (!prerender) {
-            ALOGV("Failed to create prerendered for " INT_RECT_FORMAT,
-                    INT_RECT_ARGS(pc.prerendered->area));
-            pc.prerendered.clear();
-        } else {
-            drawArea.unite(pc.prerendered->area);
-            SkNWayCanvas* nwayCanvas = new SkNWayCanvas(drawArea.width(), drawArea.height());
-            nwayCanvas->translate(-drawArea.x(), -drawArea.y());
-            nwayCanvas->addCanvas(canvas);
-            nwayCanvas->addCanvas(prerender);
-            SkSafeUnref(canvas);
-            SkSafeUnref(prerender);
-            canvas = nwayCanvas;
-        }
-    }
-    WebCore::PlatformGraphicsContextSkia pgc(canvas);
-    WebCore::GraphicsContext gc(&pgc);
-    ALOGV("painting picture: " INT_RECT_FORMAT, INT_RECT_ARGS(drawArea));
-    painter->paintContents(&gc, drawArea);
-    SkSafeUnref(canvas);
-    picture->endRecording();
-
-    SkSafeUnref(pc.picture);
-    pc.picture = picture;
-    pc.dirty = false;
-}
-
-void PicturePile::reset()
-{
-    m_size = IntSize(0,0);
-    m_pile.clear();
-    m_webkitInvals.clear();
-}
-
-void PicturePile::applyWebkitInvals()
-{
-    m_dirtyRegion.setEmpty();
-    if (!m_webkitInvals.size())
-        return;
-    // Build the invals (TODO: Support multiple inval regions)
-    IntRect inval = m_webkitInvals[0];
-    m_dirtyRegion.setRect(toSkIRect(inval));
-    for (size_t i = 1; i < m_webkitInvals.size(); i++) {
-        inval.unite(m_webkitInvals[i]);
-        m_dirtyRegion.op(toSkIRect(m_webkitInvals[i]), SkRegion::kUnion_Op);
-    }
-    m_webkitInvals.clear();
-    ALOGV("Webkit inval: " INT_RECT_FORMAT, INT_RECT_ARGS(inval));
-    if (inval.isEmpty())
-        return;
-
-    // Find the overlaps
-    Vector<int> overlaps;
-    for (size_t i = 0; i < m_pile.size(); i++) {
-        PictureContainer& pc = m_pile[i];
-        if (pc.area.contains(inval)) {
-            if (pc.dirty) {
-                ALOGV("Found already dirty intersection");
-                return;
-            }
-            if (pc.area == inval) {
-                appendToPile(inval);
-                return;
-            }
-            // Don't count the base surface as an overlap
-            if (pc.area.size() != m_size)
-                overlaps.append(i);
-        } else if (pc.area.intersects(inval))
-            overlaps.append(i);
-    }
-
-    if (overlaps.size() >= MAX_OVERLAP_COUNT) {
-        ALOGV("Exceeds overlap count");
-        IntRect overlap = inval;
-        for (int i = (int) overlaps.size() - 1; i >= 0; i--) {
-            overlap.unite(m_pile[overlaps[i]].area);
-            m_pile.remove(overlaps[i]);
-        }
-        float overlapArea = overlap.width() * overlap.height();
-        float totalArea = m_size.width() * m_size.height();
-        if (overlapArea / totalArea > MAX_OVERLAP_AREA)
-            overlap = IntRect(0, 0, m_size.width(), m_size.height());
-        appendToPile(overlap, inval);
-        return;
-    }
-
-    // Append!
-    appendToPile(inval);
-}
-
-void PicturePile::appendToPile(const IntRect& inval, const IntRect& originalInval)
-{
-    ALOGV("Adding inval " INT_RECT_FORMAT " for original inval " INT_RECT_FORMAT,
-            INT_RECT_ARGS(inval), INT_RECT_ARGS(originalInval));
-    // Remove any entries this obscures
-    for (int i = (int) m_pile.size() - 1; i >= 0; i--) {
-        if (inval.contains(m_pile[i].area))
-            m_pile.remove(i);
-    }
-    PictureContainer container(inval);
-    if (ENABLE_PRERENDERED_INVALS) {
-        container.prerendered = PrerenderedInval::create(originalInval.isEmpty()
-                                                         ? inval : originalInval);
-    }
-    m_pile.append(container);
-}
-
-PrerenderedInval* PicturePile::prerenderedInvalForArea(const IntRect& area)
-{
-    for (int i = (int) m_pile.size() - 1; i >= 0; i--) {
-        if (m_pile[i].area.intersects(area)) {
-            RefPtr<PrerenderedInval> inval = m_pile[i].prerendered;
-            if (inval.get() && inval->area.contains(area))
-                return inval.get();
-            return 0;
-        }
-    }
-    return 0;
-}
-
-} // namespace WebCore
diff --git a/Source/WebKit/android/jni/PicturePile.h b/Source/WebKit/android/jni/PicturePile.h
deleted file mode 100644
index b28a792..0000000
--- a/Source/WebKit/android/jni/PicturePile.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef PicturePile_h
-#define PicturePile_h
-
-#include "IntRect.h"
-#include "IntSize.h"
-#include "PrerenderedInval.h"
-#include "SkBitmap.h"
-#include "SkRegion.h"
-#include "SkRefCnt.h"
-
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefCounted.h>
-#include <wtf/ThreadSafeRefCounted.h>
-#include <wtf/Vector.h>
-
-class SkPicture;
-class SkCanvas;
-
-namespace WebCore {
-
-class GraphicsContext;
-
-class PicturePainter {
-public:
-    virtual void paintContents(GraphicsContext* gc, IntRect& dirty) = 0;
-    virtual SkCanvas* createPrerenderCanvas(PrerenderedInval* prerendered)
-    {
-        return 0;
-    }
-    virtual ~PicturePainter() {}
-};
-
-class PictureContainer {
-public:
-    SkPicture* picture;
-    IntRect area;
-    bool dirty;
-    RefPtr<PrerenderedInval> prerendered;
-
-    PictureContainer(const IntRect& area)
-        : picture(0)
-        , area(area)
-        , dirty(true)
-    {}
-
-    PictureContainer(const PictureContainer& other)
-        : picture(other.picture)
-        , area(other.area)
-        , dirty(other.dirty)
-        , prerendered(other.prerendered)
-    {
-        SkSafeRef(picture);
-    }
-
-    ~PictureContainer()
-    {
-        SkSafeUnref(picture);
-    }
-};
-
-class PicturePile {
-public:
-    PicturePile() {}
-    PicturePile(const PicturePile& other);
-    PicturePile(SkPicture* picture);
-
-    const IntSize& size() { return m_size; }
-
-    void clearPrerenders();
-
-    // used by PicturePileLayerContents
-    void draw(SkCanvas* canvas);
-
-    // Used by WebViewCore
-    void invalidate(const IntRect& dirtyRect);
-    void setSize(const IntSize& size);
-    void updatePicturesIfNeeded(PicturePainter* painter);
-    void reset();
-    SkRegion& dirtyRegion() { return m_dirtyRegion; }
-    PrerenderedInval* prerenderedInvalForArea(const IntRect& area);
-
-private:
-    void applyWebkitInvals();
-    void updatePicture(PicturePainter* painter, PictureContainer& container);
-    void appendToPile(const IntRect& inval, const IntRect& originalInval = IntRect());
-    void drawWithClipRecursive(SkCanvas* canvas, SkRegion& clipRegion, int index);
-
-    IntSize m_size;
-    Vector<PictureContainer> m_pile;
-    Vector<IntRect> m_webkitInvals;
-    SkRegion m_dirtyRegion;
-};
-
-} // namespace android
-
-#endif // PicturePile_h
diff --git a/Source/WebKit/android/jni/PictureSet.cpp b/Source/WebKit/android/jni/PictureSet.cpp
new file mode 100644
index 0000000..4d9d16c
--- /dev/null
+++ b/Source/WebKit/android/jni/PictureSet.cpp
@@ -0,0 +1,1236 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "pictureset"
+
+//#include <config.h>
+#include "CachedPrefix.h"
+#include "android_graphics.h"
+#include "PictureSet.h"
+#include "SkBounder.h"
+#include "SkCanvas.h"
+#include "SkPicture.h"
+#include "SkRect.h"
+#include "SkRegion.h"
+#include "SkStream.h"
+#include "TimeCounter.h"
+
+#define MAX_DRAW_TIME 100
+#define MIN_SPLITTABLE 400
+#define MAX_ADDITIONAL_AREA 0.65
+#define MAX_ADDITIONAL_PICTURES 32
+
+#define BUCKET_SIZE 1024
+#define MAX_BUCKET_COUNT_X 16
+#define MAX_BUCKET_COUNT_Y 64
+
+#include <wtf/CurrentTime.h>
+
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOGC
+#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "PictureSet", __VA_ARGS__)
+
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "PictureSet", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+#if PICTURE_SET_DEBUG
+class MeasureStream : public SkWStream {
+public:
+    MeasureStream() : mTotal(0) {}
+    virtual bool write(const void* , size_t size) {
+        mTotal += size;
+        return true;
+    }
+    size_t mTotal;
+};
+#endif
+
+namespace android {
+
+PictureSet::PictureSet() :
+#ifdef FAST_PICTURESET
+    mBucketSizeX(BUCKET_SIZE), mBucketSizeY(BUCKET_SIZE),
+    mBucketCountX(0), mBucketCountY(0),
+#endif
+    mHeight(0), mWidth(0)
+{
+    setDimensions(0, 0);
+    mBaseArea = mAdditionalArea = 0;
+}
+
+PictureSet::PictureSet(SkPicture* picture) :
+#ifdef FAST_PICTURESET
+    mBucketSizeX(BUCKET_SIZE), mBucketSizeY(BUCKET_SIZE),
+    mBucketCountX(0), mBucketCountY(0),
+#endif
+    mHeight(0), mWidth(0)
+{
+    mBaseArea = mAdditionalArea = 0;
+    if (!picture) {
+        setDimensions(0, 0);
+        return;
+    }
+    setDimensions(picture->width(), picture->height());
+    mBaseArea = mWidth * mHeight;
+#ifdef FAST_PICTURESET
+    SkIRect area;
+    area.set(0, 0, mWidth, mHeight);
+    splitAdd(area);
+    WTF::Vector<Bucket*>* buckets = bucketsToUpdate();
+    for (unsigned int i = 0; i < buckets->size(); i++) {
+        Bucket* bucket = (*buckets)[i];
+        for (unsigned int j = 0; j < bucket->size(); j++) {
+            BucketPicture& bucketPicture = (*bucket)[j];
+            const SkIRect& inval = bucketPicture.mRealArea;
+            SkPicture *splitPicture = new SkPicture();
+            SkCanvas *canvas = splitPicture->beginRecording(
+                    inval.width(), inval.height(),
+                    SkPicture::kUsePathBoundsForClip_RecordingFlag);
+            canvas->translate(-inval.fLeft, -inval.fTop);
+            picture->draw(canvas);
+            splitPicture->endRecording();
+            SkSafeUnref(bucketPicture.mPicture);
+            bucketPicture.mPicture = splitPicture;
+        }
+    }
+    buckets->clear();
+#else
+    Pictures pictureAndBounds;
+    pictureAndBounds.mPicture = picture;
+    SkSafeRef(pictureAndBounds.mPicture);
+    pictureAndBounds.mEmpty = false;
+    pictureAndBounds.mArea.setRect(0, 0, mWidth, mHeight);
+    pictureAndBounds.mSplit = false;
+    pictureAndBounds.mBase = true;
+    pictureAndBounds.mElapsed = 0;
+    pictureAndBounds.mWroteElapsed = false;
+    mPictures.append(pictureAndBounds);
+#endif // FAST_PICTURESET
+}
+
+PictureSet::~PictureSet()
+{
+    clear();
+}
+
+#ifdef FAST_PICTURESET
+#else
+void PictureSet::add(const Pictures* temp)
+{
+    Pictures pictureAndBounds = *temp;
+    SkSafeRef(pictureAndBounds.mPicture);
+    pictureAndBounds.mWroteElapsed = false;
+    mPictures.append(pictureAndBounds);
+}
+#endif // FAST_PICTURESET
+
+void PictureSet::add(const SkRegion& area, SkPicture* picture,
+                     uint32_t elapsed, bool split)
+{
+    if (area.isRect()) {
+#ifdef FAST_PICTURESET
+        splitAdd(area.getBounds());
+#else
+        add(area, picture, elapsed, split, false);
+#endif // FAST_PICTURESET
+    } else {
+        SkRegion::Iterator cliperator(area);
+        while (!cliperator.done()) {
+            SkIRect ir = cliperator.rect();
+#ifdef FAST_PICTURESET
+            splitAdd(ir);
+#else
+            SkRegion newArea;
+            newArea.setRect(ir);
+            add(newArea, picture, elapsed, split, false);
+#endif // FAST_PICTURESET
+            cliperator.next();
+        }
+    }
+}
+
+#ifdef FAST_PICTURESET
+
+Bucket* PictureSet::getBucket(int x, int y)
+{
+    // only create buckets for valid, positive coordinates, ignore and return
+    // NULL otherwise
+    if (x < 0 || y < 0)
+        return 0;
+
+    BucketPosition position(x+1, y+1);
+    if (!mBuckets.contains(position)) {
+        XLOG("PictureSet::getBucket(%d, %d) adding new bucket", x, y);
+        Bucket* bucket = new Bucket();
+        mBuckets.add(position, bucket);
+    }
+    return mBuckets.get(position);
+}
+
+void PictureSet::displayBucket(Bucket* bucket)
+{
+    BucketPicture* first = bucket->begin();
+    BucketPicture* last = bucket->end();
+    for (BucketPicture* current = first; current != last; current++) {
+        XLOGC("- in %x, bucketPicture %d,%d,%d,%d - %dx%d, picture: %x, base: %x",
+              bucket,
+              current->mArea.fLeft,
+              current->mArea.fTop,
+              current->mArea.fRight,
+              current->mArea.fBottom,
+              current->mArea.width(),
+              current->mArea.height(),
+              current->mPicture,
+              current->mBase);
+    }
+}
+
+void PictureSet::displayBuckets()
+{
+    XLOGC("\n\n****** DISPLAY BUCKETS ON PictureSet %x ******", this);
+    for (BucketMap::iterator iter = mBuckets.begin(); iter != mBuckets.end(); ++iter) {
+        XLOGC("\n*** Bucket %x for %d, %d", iter->second, iter->first.first, iter->first.second);
+        displayBucket(iter->second);
+    }
+    XLOGC("\n****** END OF DISPLAY BUCKETS ******\n\n");
+}
+
+// When we receive an inval in a Bucket, we try to see if we intersect with
+// existing invals/pictures in the Bucket.
+void PictureSet::addToBucket(Bucket* bucket, int dx, int dy, SkIRect& rect)
+{
+    bool resetBase = false;
+
+    SkIRect totalArea = rect;
+    BucketPicture* first = bucket->begin();
+    BucketPicture* last = bucket->end();
+
+    // If the inval covers a large area of the base inval, let's repaint the
+    // entire bucket.
+    if (rect.width() * rect.height() > MAX_ADDITIONAL_AREA * mBucketSizeX * mBucketSizeY)
+        resetBase = true;
+
+    // let's gather all the BucketPicture intersecting with the new invalidated
+    // area, collect their area and remove their picture
+    for (BucketPicture* current = first; current != last; current++) {
+        bool remove = resetBase;
+        bool intersect = false;
+
+        if (!remove)
+            intersect = SkIRect::Intersects(current->mArea, rect);
+        // If the current picture is not a base, and we intersect, remove it
+        if (!remove && !current->mBase && intersect)
+            remove = true;
+        // If the current picture is a base, check if the new inval completely
+        // contains the base, and if so remove it.
+        if (!remove && current->mBase && rect.contains(current->mArea))
+            remove = true;
+        // If the current picture is a base and it intersects,
+        // also check that it fully covers the bucket -- otherwise,
+        // let's aggregate it with the new inval.
+        if (!remove && current->mBase && intersect
+            && (current->mArea.width() < mBucketSizeX || current->mArea.height() < mBucketSizeY)) {
+            remove = true;
+        }
+
+        if (remove) {
+            totalArea.join(current->mArea);
+            current->mBase = false;
+            current->mArea.setEmpty();
+            SkSafeUnref(current->mPicture);
+            current->mPicture = 0;
+        }
+    }
+
+    // Now, let's add the new BucketPicture to the list, with the correct
+    // area that needs to be repainted
+    SkRegion region;
+    SkIRect area = totalArea;
+    area.offset(dx, dy);
+    BucketPicture picture = { 0, totalArea, area, false };
+
+    bucket->append(picture);
+
+    first = bucket->begin();
+    last = bucket->end();
+
+    bool clearUp = false;
+    if (last - first > MAX_ADDITIONAL_PICTURES) {
+        // too many pictures in the bucket, let's collapse
+        clearUp = true;
+    }
+
+    float bucketBaseArea = 0;
+    float bucketAdditionalArea = 0;
+    for (BucketPicture* current = first; current != last; current++) {
+        float area = current->mArea.width() * current->mArea.height();
+        if (current->mBase)
+            bucketBaseArea += area;
+        else
+            bucketAdditionalArea += area;
+    }
+
+    if (bucketBaseArea > 0 && bucketBaseArea * MAX_ADDITIONAL_AREA <= bucketAdditionalArea) {
+        // additional area too large, not worth maintaining
+        clearUp = true;
+    }
+
+    // To clear things up, we just need to mark the pictures' area as empty
+    // We only keep the base surface.
+    if (clearUp) {
+        for (BucketPicture* current = first; current != last; current++) {
+            if (!current->mBase)
+                current->mArea.setEmpty();
+            SkSafeUnref(current->mPicture);
+            current->mPicture = 0;
+        }
+    }
+
+    // let's do a pass to collapse out empty areas
+    BucketPicture* writer = first;
+    for (BucketPicture* current = first; current != last; current++) {
+        if (current && current->mArea.isEmpty())
+            continue;
+        *writer++ = *current;
+    }
+
+    bucket->shrink(writer - first);
+
+    // let's recompute the bases
+    first = bucket->begin();
+    last = bucket->end();
+    SkRegion drawn;
+    drawn.setEmpty();
+    for (BucketPicture* current = first; current != last; current++) {
+        if (drawn.contains(current->mArea) == false) {
+            current->mBase = true;
+        }
+        drawn.op(current->mArea, SkRegion::kUnion_Op);
+    }
+}
+
+void PictureSet::gatherBucketsForArea(WTF::Vector<Bucket*>& list, const SkIRect& rect)
+{
+    XLOG("\n--- gatherBucketsForArea for rect %d, %d, %d, %d (%d x %d)",
+          rect.fLeft, rect.fTop, rect.fRight, rect.fBottom,
+          rect.width(), rect.height());
+
+    if (!mBucketSizeX || !mBucketSizeY) {
+        XLOGC("PictureSet::gatherBucketsForArea() called with bad bucket size: x=%d y=%d",
+              mBucketSizeX, mBucketSizeY);
+        return;
+    }
+
+    int x = rect.fLeft;
+    int y = rect.fTop;
+    int firstTileX = rect.fLeft / mBucketSizeX;
+    int firstTileY = rect.fTop / mBucketSizeY;
+    int lastTileX = rect.fRight / mBucketSizeX;
+    int lastTileY = rect.fBottom / mBucketSizeY;
+
+    for (int i = firstTileX; i <= lastTileX; i++) {
+        for (int j = firstTileY; j <= lastTileY; j++) {
+            Bucket* bucket = getBucket(i, j);
+            XLOG("gather bucket %x for %d, %d", bucket, i+1, j+1);
+            if (bucket)
+                list.append(bucket);
+        }
+    }
+}
+
+// When we receive a new inval rect, we first find the Buckets that intersect
+// with it; then we split the original inval into a serie of invals (one for
+// each Bucket we intersect with). We then send that inval to the Bucket.
+void PictureSet::splitAdd(const SkIRect& rect)
+{
+    XLOG("\n--- splitAdd for rect %d, %d, %d, %d (%d x %d)",
+          rect.fLeft, rect.fTop, rect.fRight, rect.fBottom,
+          rect.width(), rect.height());
+
+    if (!mBucketSizeX || !mBucketSizeY) {
+        XLOGC("PictureSet::splitAdd() called with bad bucket size: x=%d y=%d",
+              mBucketSizeX, mBucketSizeY);
+        return;
+    }
+
+    // TODO: reuse gatherBucketsForArea() (change Bucket to be a class)
+    int x = rect.fLeft;
+    int y = rect.fTop;
+    int firstTileX = rect.fLeft / mBucketSizeX;
+    int firstTileY = rect.fTop / mBucketSizeY;
+    int lastTileX = rect.fRight / mBucketSizeX;
+    int lastTileY = rect.fBottom / mBucketSizeY;
+
+    XLOG("--- firstTile(%d, %d) lastTile(%d, %d)",
+          firstTileX, firstTileY,
+          lastTileX, lastTileY);
+
+    for (int i = firstTileX; i <= lastTileX; i++) {
+        for (int j = firstTileY; j <= lastTileY; j++) {
+            Bucket* bucket = getBucket(i, j);
+            if (!bucket)
+                continue;
+
+            SkIRect newRect;
+            int deltaX = i * mBucketSizeX;
+            int deltaY = j * mBucketSizeY;
+            int left = (i == firstTileX) ? rect.fLeft - deltaX : 0;
+            int top = (j == firstTileY) ? rect.fTop - deltaY : 0;
+            int right = (i == lastTileX) ? rect.fRight % mBucketSizeX : mBucketSizeX;
+            int bottom = (j == lastTileY) ? rect.fBottom % mBucketSizeY : mBucketSizeY;
+
+            newRect.set(left, top, right, bottom);
+            addToBucket(bucket, deltaX, deltaY, newRect);
+            mUpdatedBuckets.append(bucket);
+        }
+    }
+
+    XLOG("--- splitAdd DONE\n");
+}
+
+#endif // FAST_PICTURESET
+
+// This function is used to maintain the list of Pictures.
+// Pictures contain an SkPicture covering a specific area; some
+// Pictures are "base" Pictures -- i.e. there is no Pictures
+// underneath them.
+// The idea here is to keep a balance between the number of Pictures
+// we have (more Pictures slow us down) and the area of Pictures that
+// need to be repainted (obviously, smaller areas are better).
+// To do so, we try to not update/repaint the base pictures -- by
+// construction, they usually cover a large area (the entire page).
+// We only reset a base picture if the new invalidated area entirely
+// contains it.
+// Most of the time we thus work on smaller pictures on top of the
+// base ones; We compute the total area of all pictures intersecting
+// with the passed invalidated area (as they would need to be invalidated),
+// and use that as the basis for the correct area we want to invalidate
+// (we then can simply delete the pictures we intersect with).
+// In addition, we do a couple of things to limit the total number of pictures
+// we keep in the list:
+// - if the total area of additional textures reach 65% of the base pictures,
+//   we delete the additional pictures and mark the base pictures as
+//   needing a full repaint
+// - we limit the number of pictures to 32 -- above that, we do the same
+//   things (deleting additional pictures + full repaint of base pictures)
+#ifdef FAST_PICTURESET
+#else
+void PictureSet::add(const SkRegion& area, SkPicture* picture,
+    uint32_t elapsed, bool split, bool empty)
+{
+    bool checkForNewBases = false;
+
+    Pictures* first = mPictures.begin();
+    Pictures* last = mPictures.end();
+#ifdef DEBUG
+    XLOG("--- before adding the new inval ---");
+    for (Pictures* working = mPictures.begin(); working != mPictures.end(); working++) {
+        SkIRect currentArea = working->mArea.getBounds();
+        XLOG("picture %d (%d, %d, %d, %d - %d x %d) (isRect? %c) base: %c",
+             working - first,
+             currentArea.fLeft, currentArea.fTop, currentArea.fRight, currentArea.fBottom,
+             currentArea.width(), currentArea.height(),
+             working->mArea.isRect() ? 'Y' : 'N',
+             working->mBase ? 'Y' : 'N');
+    }
+    XLOG("----------------------------------");
+#endif
+
+    // let's gather all the Pictures intersecting with the new invalidated
+    // area, collect their area and remove their picture
+    SkIRect totalArea = area.getBounds();
+    for (Pictures* working = first; working != last; working++) {
+        SkIRect inval = area.getBounds();
+        bool remove = false;
+        if (!working->mBase && working->mArea.intersects(inval))
+            remove = true;
+        if (working->mBase) {
+            SkIRect baseArea = working->mArea.getBounds();
+            if (area.contains(baseArea)) {
+                remove = true;
+                checkForNewBases = true;
+            }
+        }
+
+        if (remove) {
+            SkIRect currentArea = working->mArea.getBounds();
+            if (working->mBase)
+                mBaseArea -= currentArea.width() * currentArea.height();
+            else
+                mAdditionalArea -= currentArea.width() * currentArea.height();
+
+            totalArea.join(currentArea);
+            XLOG("picture %d (%d, %d, %d, %d - %d x %d) (isRect? %c) intersects with the new inval area (%d, %d, %d, %d - %d x %d) (isRect? %c, we remove it",
+                 working - first,
+                 currentArea.fLeft, currentArea.fTop, currentArea.fRight, currentArea.fBottom,
+                 currentArea.width(), currentArea.height(),
+                 working->mArea.isRect() ? 'Y' : 'N',
+                 inval.fLeft, inval.fTop, inval.fRight, inval.fBottom,
+                 inval.width(), inval.height(),
+                 area.isRect() ? 'Y' : 'N');
+            working->mArea.setEmpty();
+            SkSafeUnref(working->mPicture);
+            working->mPicture = 0;
+        }
+    }
+
+    // Now we can add the new Picture to the list, with the correct area
+    // that need to be repainted
+    SkRegion collect;
+    collect.setRect(totalArea);
+    Pictures pictureAndBounds = {collect, 0, collect.getBounds(),
+        elapsed, split, false, false, empty};
+
+#ifdef FAST_PICTURESET
+    if (mPictures.size() == 0)
+        checkForNewBases = true;
+#endif
+
+    mPictures.append(pictureAndBounds);
+    mAdditionalArea += totalArea.width() * totalArea.height();
+    last = mPictures.end();
+    first = mPictures.begin();
+
+    // Then, let's see if we have to clear up the pictures in order to keep
+    // the total number of pictures under our limit
+    bool clearUp = false;
+    if (last - first > MAX_ADDITIONAL_PICTURES) {
+        XLOG("--- too many pictures, only keeping the bases : %d", last - first);
+        clearUp = true;
+    }
+
+    if (!clearUp) {
+        if (mBaseArea > 0 && mBaseArea * MAX_ADDITIONAL_AREA <= mAdditionalArea) {
+            XLOG("+++ the sum of the additional area is > %.2f\% of the base Area (%.2f (%.2f) <= %.2f",
+                 MAX_ADDITIONAL_AREA * 100, mBaseArea * 0.65, mBaseArea, mAdditionalArea);
+            clearUp = true;
+        }
+    }
+
+    if (clearUp) {
+        for (Pictures* working = mPictures.begin(); working != mPictures.end(); working++) {
+            if (!working->mBase)
+                working->mArea.setEmpty();
+            SkSafeUnref(working->mPicture);
+            working->mPicture = 0;
+        }
+    }
+
+#ifdef DEBUG
+    XLOG("--- after adding the new inval, but before collapsing ---");
+    for (Pictures* working = mPictures.begin(); working != mPictures.end(); working++) {
+        SkIRect currentArea = working->mArea.getBounds();
+        XLOG("picture %d (%d, %d, %d, %d - %d x %d) (isRect? %c) base: %c",
+             working - first,
+             currentArea.fLeft, currentArea.fTop, currentArea.fRight, currentArea.fBottom,
+             currentArea.width(), currentArea.height(),
+             working->mArea.isRect() ? 'Y' : 'N',
+             working->mBase ? 'Y' : 'N');
+    }
+    XLOG("----------------------------------");
+    XLOG("let's collapse...");
+#endif
+
+    // Finally, let's do a pass to collapse out empty regions
+    Pictures* writer = first;
+    for (Pictures* working = first; working != last; working++) {
+        if (working && working->mArea.isEmpty())
+            continue;
+        *writer++ = *working;
+    }
+    XLOG("shiking of %d elements", writer - first);
+    mPictures.shrink(writer - first);
+
+#ifdef DEBUG
+    XLOG("--- after adding the new inval ---");
+    for (Pictures* working = mPictures.begin(); working != mPictures.end(); working++) {
+        SkIRect currentArea = working->mArea.getBounds();
+        XLOG("picture %d (%d, %d, %d, %d - %d x %d) (isRect? %c) base: %c picture %x",
+             working - first,
+             currentArea.fLeft, currentArea.fTop, currentArea.fRight, currentArea.fBottom,
+             currentArea.width(), currentArea.height(),
+             working->mArea.isRect() ? 'Y' : 'N',
+             working->mBase ? 'Y' : 'N', working->mPicture);
+    }
+    XLOG("----------------------------------");
+#endif
+
+    // Base pictures might have been removed/added -- let's recompute them
+    SkRegion drawn;
+    if (checkForNewBases) {
+        drawn.setEmpty();
+        Pictures* last = mPictures.end();
+        XLOG("checkForNewBases...");
+        for (Pictures* working = mPictures.begin(); working != last; working++) {
+            SkRegion& area = working->mArea;
+            const SkIRect& a = area.getBounds();
+            if (drawn.contains(working->mArea) == false) {
+                working->mBase = true;
+                float area = a.width() * a.height();
+                mBaseArea += area;
+                mAdditionalArea -= area;
+            }
+            drawn.op(working->mArea, SkRegion::kUnion_Op);
+        }
+    }
+}
+#endif // FAST_PICTURESET
+
+void PictureSet::setDimensions(int width, int height, SkRegion* inval)
+{
+    // Note that setDimensions() may be called by our ctor and should behave accordingly
+    if (mWidth == width && mHeight == height)
+        return;
+    DBG_SET_LOGD("%p old:(w=%d,h=%d) new:(w=%d,h=%d)", this,
+        mWidth, mHeight, width, height);
+    bool clearCache = false;
+    if (inval) {
+        if (mWidth == width && height > mHeight) { // only grew vertically
+            SkIRect rect;
+            rect.set(0, mHeight, width, height);
+            inval->op(rect, SkRegion::kUnion_Op);
+        } else {
+            clearCache = true;
+            inval->setRect(0, 0, width, height);
+        }
+    }
+#ifdef FAST_PICTURESET
+    // First figure out how large each bucket would be if we used all of the buckets
+    int tmpSizeX = (width + MAX_BUCKET_COUNT_X - 1) / MAX_BUCKET_COUNT_X;
+    int tmpSizeY = (height + MAX_BUCKET_COUNT_Y - 1) / MAX_BUCKET_COUNT_Y;
+
+    // Then round the bucket size up to the nearest chunk
+    int bucketSizeX = ((tmpSizeX - 1) / BUCKET_SIZE + 1) * BUCKET_SIZE;
+    int bucketSizeY = ((tmpSizeY - 1) / BUCKET_SIZE + 1) * BUCKET_SIZE;
+
+    int bucketCountX = (width + bucketSizeX - 1) / bucketSizeX;
+    int bucketCountY = (height + bucketSizeY - 1) / bucketSizeY;
+
+    // Clear the cache if the horizontal bucket count changed or the vertical
+    // count shrank
+    if (bucketCountX != mBucketCountX || bucketCountY < mBucketCountY)
+        clearCache = true;
+
+    // Or if the bucket size changed
+    if (bucketSizeX != mBucketSizeX || bucketSizeY != mBucketSizeY)
+        clearCache = true;
+
+    XLOG("old width=%d height=%d bucketSizeX=%d bucketSizeY=%d bucketCountX=%d bucketCountY=%d clearCache=%d",
+         mWidth, mHeight, mBucketSizeX, mBucketSizeY, mBucketCountX, mBucketCountY, clearCache);
+    XLOG("new width=%d height=%d bucketSizeX=%d bucketSizeY=%d bucketCountX=%d bucketCountY=%d clearCache=%d",
+         width, height, bucketSizeX, bucketSizeY, bucketCountX, bucketCountY, clearCache);
+#endif
+    if (clearCache)
+        clear();
+    mWidth = width;
+    mHeight = height;
+#ifdef FAST_PICTURESET
+    mBucketSizeX = bucketSizeX;
+    mBucketSizeY = bucketSizeY;
+    mBucketCountX = bucketCountX;
+    mBucketCountY = bucketCountY;
+#endif
+}
+
+void PictureSet::clear()
+{
+    DBG_SET_LOG("");
+#ifdef FAST_PICTURESET
+    for (BucketMap::iterator iter = mBuckets.begin(); iter != mBuckets.end(); ++iter) {
+         Bucket* bucket = iter->second;
+         BucketPicture* first = bucket->begin();
+         BucketPicture* last = bucket->end();
+         for (BucketPicture* current = first; current != last; current++) {
+             SkSafeUnref(current->mPicture);
+             current->mPicture = 0;
+         }
+         bucket->clear();
+    }
+    mBuckets.clear();
+    mBucketSizeX = mBucketSizeY = BUCKET_SIZE;
+#else
+    Pictures* last = mPictures.end();
+    for (Pictures* working = mPictures.begin(); working != last; working++) {
+        working->mArea.setEmpty();
+        SkSafeUnref(working->mPicture);
+    }
+    mPictures.clear();
+#endif // FAST_PICTURESET
+    mWidth = mHeight = 0;
+}
+
+bool PictureSet::draw(SkCanvas* canvas)
+{
+#ifdef FAST_PICTURESET
+    XLOG("PictureSet %x draw on canvas %x", this, canvas);
+    SkRect bounds;
+    if (canvas->getClipBounds(&bounds) == false)
+        return false;
+    SkIRect irect;
+    bounds.roundOut(&irect);
+
+    WTF::Vector<Bucket*> list;
+    gatherBucketsForArea(list, irect);
+
+    XLOG("PictureSet draw on canvas %x, we have %d buckets", canvas, list.size());
+    for (unsigned int i = 0; i < list.size(); i++) {
+        Bucket* bucket = list[i];
+        XLOG("We paint using bucket %x with %d pictures", bucket, bucket->size());
+        for (unsigned int j = 0; j < bucket->size(); j++)  {
+            BucketPicture& picture = bucket->at(j);
+            if (!picture.mPicture)
+                continue;
+            int saved = canvas->save();
+            SkRect pathBounds;
+            pathBounds.set(picture.mRealArea);
+            XLOG("[%d/%d] draw on canvas with clip %d, %d, %d, %d - %d x %d",
+                  j, bucket->size(),
+                  picture.mRealArea.fLeft,
+                  picture.mRealArea.fTop,
+                  picture.mRealArea.fRight,
+                  picture.mRealArea.fBottom,
+                  picture.mRealArea.width(),
+                  picture.mRealArea.height());
+            canvas->clipRect(pathBounds);
+            canvas->translate(pathBounds.fLeft, pathBounds.fTop);
+            canvas->save();
+            canvas->drawPicture(*picture.mPicture);
+            canvas->restoreToCount(saved);
+        }
+    }
+    return false;
+
+#else
+
+    validate(__FUNCTION__);
+    Pictures* first = mPictures.begin();
+    Pictures* last = mPictures.end();
+    Pictures* working;
+    SkRect bounds;
+    if (canvas->getClipBounds(&bounds) == false)
+        return false;
+    SkIRect irect;
+    bounds.roundOut(&irect);
+    for (working = last; working != first; ) {
+        --working;
+        if (working->mArea.contains(irect)) {
+#if PICTURE_SET_DEBUG
+            const SkIRect& b = working->mArea.getBounds();
+            DBG_SET_LOGD("contains working->mArea={%d,%d,%d,%d}"
+                " irect={%d,%d,%d,%d}", b.fLeft, b.fTop, b.fRight, b.fBottom,
+                irect.fLeft, irect.fTop, irect.fRight, irect.fBottom);
+#endif
+            first = working;
+            break;
+        }
+    }
+    DBG_SET_LOGD("%p first=%d last=%d", this, first - mPictures.begin(),
+        last - mPictures.begin());
+    uint32_t maxElapsed = 0;
+    for (working = first; working != last; working++) {
+        const SkRegion& area = working->mArea;
+        if (area.quickReject(irect)) {
+#if PICTURE_SET_DEBUG
+            const SkIRect& b = area.getBounds();
+            DBG_SET_LOGD("[%d] %p quickReject working->mArea={%d,%d,%d,%d}"
+                " irect={%d,%d,%d,%d}", working - first, working,
+                b.fLeft, b.fTop, b.fRight, b.fBottom,
+                irect.fLeft, irect.fTop, irect.fRight, irect.fBottom);
+#endif
+            working->mElapsed = 0;
+            continue;
+        }
+        int saved = canvas->save();
+        SkRect pathBounds;
+        if (area.isComplex()) {
+            SkPath pathClip;
+            area.getBoundaryPath(&pathClip);
+            canvas->clipPath(pathClip);
+            pathBounds = pathClip.getBounds();
+        } else {
+            pathBounds.set(area.getBounds());
+            canvas->clipRect(pathBounds);
+        }
+        canvas->translate(pathBounds.fLeft, pathBounds.fTop);
+        canvas->save();
+        uint32_t startTime = getThreadMsec();
+        canvas->drawPicture(*working->mPicture);
+        size_t elapsed = working->mElapsed = getThreadMsec() - startTime;
+        working->mWroteElapsed = true;
+        if (maxElapsed < elapsed && (pathBounds.width() >= MIN_SPLITTABLE ||
+                pathBounds.height() >= MIN_SPLITTABLE))
+            maxElapsed = elapsed;
+        canvas->restoreToCount(saved);
+#define DRAW_TEST_IMAGE 01
+#if DRAW_TEST_IMAGE && PICTURE_SET_DEBUG
+        SkColor color = 0x3f000000 | (0xffffff & (unsigned) working);
+        canvas->drawColor(color);
+        SkPaint paint;
+        color ^= 0x00ffffff;
+        paint.setColor(color);
+        char location[256];
+        for (int x = area.getBounds().fLeft & ~0x3f;
+                x < area.getBounds().fRight; x += 0x40) {
+            for (int y = area.getBounds().fTop & ~0x3f;
+                    y < area.getBounds().fBottom; y += 0x40) {
+                int len = snprintf(location, sizeof(location) - 1, "(%d,%d)", x, y);
+                canvas->drawText(location, len, x, y, paint);
+            }
+        }
+#endif
+        DBG_SET_LOGD("[%d] %p working->mArea={%d,%d,%d,%d} elapsed=%d base=%s",
+            working - first, working,
+            area.getBounds().fLeft, area.getBounds().fTop,
+            area.getBounds().fRight, area.getBounds().fBottom,
+            working->mElapsed, working->mBase ? "true" : "false");
+    }
+ //   dump(__FUNCTION__);
+    return maxElapsed >= MAX_DRAW_TIME;
+#endif // FAST_PICTURESET
+}
+
+void PictureSet::dump(const char* label) const
+{
+#if PICTURE_SET_DUMP
+    DBG_SET_LOGD("%p %s (%d) (w=%d,h=%d)", this, label, mPictures.size(),
+        mWidth, mHeight);
+    const Pictures* last = mPictures.end();
+    for (const Pictures* working = mPictures.begin(); working != last; working++) {
+        const SkIRect& bounds = working->mArea.getBounds();
+        const SkIRect& unsplit = working->mUnsplit;
+        MeasureStream measure;
+        if (working->mPicture != NULL)
+            working->mPicture->serialize(&measure);
+        LOGD(" [%d]"
+            " mArea.bounds={%d,%d,r=%d,b=%d}"
+            " mPicture=%p"
+            " mUnsplit={%d,%d,r=%d,b=%d}"
+            " mElapsed=%d"
+            " mSplit=%s"
+            " mWroteElapsed=%s"
+            " mBase=%s"
+            " pict-size=%d",
+            working - mPictures.begin(),
+            bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom,
+            working->mPicture,
+            unsplit.fLeft, unsplit.fTop, unsplit.fRight, unsplit.fBottom,
+            working->mElapsed, working->mSplit ? "true" : "false",
+            working->mWroteElapsed ? "true" : "false",
+            working->mBase ? "true" : "false",
+            measure.mTotal);
+    }
+#endif
+}
+
+class IsEmptyBounder : public SkBounder {
+    virtual bool onIRect(const SkIRect& rect) {
+        return false;
+    }
+};
+
+class IsEmptyCanvas : public SkCanvas {
+public:
+    IsEmptyCanvas(SkBounder* bounder, SkPicture* picture) : 
+            mPicture(picture), mEmpty(true) {
+        setBounder(bounder);
+    }
+    
+    void notEmpty() {
+        mEmpty = false;
+        mPicture->abortPlayback();    
+    }
+
+    virtual bool clipPath(const SkPath&, SkRegion::Op) {
+        // this can be expensive to actually do, and doesn't affect the
+        // question of emptiness, so we make it a no-op
+        return true;
+    }
+
+    virtual void commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* rect,
+            const SkMatrix& , const SkPaint& ) {
+        if (bitmap.width() <= 1 || bitmap.height() <= 1)
+            return;
+        DBG_SET_LOGD("abort {%d,%d}", bitmap.width(), bitmap.height());
+        notEmpty();
+    }
+
+    virtual void drawPaint(const SkPaint& paint) {
+    }
+
+    virtual void drawPath(const SkPath& , const SkPaint& paint) {
+        DBG_SET_LOG("abort");
+        notEmpty();
+    }
+
+    virtual void drawPoints(PointMode , size_t , const SkPoint [],
+                            const SkPaint& paint) {
+    }
+    
+    virtual void drawRect(const SkRect& , const SkPaint& paint) {
+        // wait for visual content
+        if (paint.getColor() != SK_ColorWHITE)
+            notEmpty();
+    }
+
+    virtual void drawSprite(const SkBitmap& , int , int ,
+                            const SkPaint* paint = NULL) {
+        DBG_SET_LOG("abort");
+        notEmpty();
+    }
+    
+    virtual void drawText(const void* , size_t byteLength, SkScalar , 
+                          SkScalar , const SkPaint& paint) {
+        DBG_SET_LOGD("abort %d", byteLength);
+        notEmpty();
+    }
+
+    virtual void drawPosText(const void* , size_t byteLength, 
+                             const SkPoint [], const SkPaint& paint) {
+        DBG_SET_LOGD("abort %d", byteLength);
+        notEmpty();
+    }
+
+    virtual void drawPosTextH(const void* , size_t byteLength,
+                              const SkScalar [], SkScalar ,
+                              const SkPaint& paint) {
+        DBG_SET_LOGD("abort %d", byteLength);
+        notEmpty();
+    }
+
+    virtual void drawTextOnPath(const void* , size_t byteLength, 
+                                const SkPath& , const SkMatrix* , 
+                                const SkPaint& paint) {
+        DBG_SET_LOGD("abort %d", byteLength);
+        notEmpty();
+    }
+
+    virtual void drawPicture(SkPicture& picture) {
+        SkCanvas::drawPicture(picture);
+    }
+    
+    SkPicture* mPicture;
+    bool mEmpty;
+};
+
+bool PictureSet::emptyPicture(SkPicture* picture) const
+{
+    IsEmptyBounder isEmptyBounder;
+    IsEmptyCanvas checker(&isEmptyBounder, picture);
+    SkBitmap bitmap;
+    bitmap.setConfig(SkBitmap::kARGB_8888_Config, mWidth, mHeight);
+    checker.setBitmapDevice(bitmap);
+    checker.drawPicture(*picture);
+    return checker.mEmpty;
+}
+
+bool PictureSet::isEmpty() const
+{
+#ifdef FAST_PICTURESET
+    // For now, just assume the pictureset is *not* empty
+    // if the hashmap contains something
+    for (BucketMap::const_iterator iter = mBuckets.begin(); iter != mBuckets.end(); ++iter) {
+        if (iter->second->size() > 0)
+            return false;
+    }
+    return true;
+#else
+    const Pictures* last = mPictures.end();
+    for (const Pictures* working = mPictures.begin(); working != last; working++) {
+        if (!working->mEmpty)
+            return false;
+    }
+    return true;
+#endif // FAST_PICTURESET
+}
+
+void PictureSet::set(const PictureSet& src)
+{
+    DBG_SET_LOGD("start %p src=%p", this, &src);
+    clear();
+    setDimensions(src.mWidth, src.mHeight);
+#ifdef FAST_PICTURESET
+    XLOG("\n--- set picture ---");
+    for (BucketMap::const_iterator iter = src.mBuckets.begin();
+         iter != src.mBuckets.end(); ++iter) {
+         Bucket* sourceBucket = iter->second;
+         Bucket* targetBucket = getBucket(iter->first.first-1, iter->first.second-1);
+         BucketPicture* first = sourceBucket->begin();
+         BucketPicture* last = sourceBucket->end();
+         XLOG("set from bucket %x (%d, %d), %d pictures", sourceBucket,
+              iter->first.first, iter->first.second, sourceBucket->size());
+         for (BucketPicture* current = first; current != last; current++) {
+             XLOG("set picture %x from bucket %x in bucket %x (%d, %d)",
+                  current->mPicture, sourceBucket, targetBucket,
+                  iter->first.first, iter->first.second);
+             SkSafeRef(current->mPicture);
+             BucketPicture picture = { current->mPicture, current->mArea,
+                                       current->mRealArea, current->mBase };
+             targetBucket->append(picture);
+         }
+    }
+    XLOG("--- DONE set picture ---\n");
+#else
+    const Pictures* last = src.mPictures.end();
+    for (const Pictures* working = src.mPictures.begin(); working != last; working++)
+        add(working);
+ //   dump(__FUNCTION__);
+    validate(__FUNCTION__);
+    DBG_SET_LOG("end");
+#endif // FAST_PICTURESET
+}
+
+#ifdef FAST_PICTURESET
+#else
+
+bool PictureSet::reuseSubdivided(const SkRegion& inval)
+{
+    validate(__FUNCTION__);
+
+    if (inval.isComplex())
+        return false;
+    Pictures* working, * last = mPictures.end();
+    const SkIRect& invalBounds = inval.getBounds();
+    bool steal = false;
+    for (working = mPictures.begin(); working != last; working++) {
+        if (working->mSplit && invalBounds == working->mUnsplit) {
+            steal = true;
+            continue;
+        }
+        if (steal == false)
+            continue;
+        SkRegion temp = SkRegion(inval);
+        temp.op(working->mArea, SkRegion::kIntersect_Op);
+        if (temp.isEmpty() || temp == working->mArea)
+            continue;
+        return false;
+    }
+    if (steal == false)
+        return false;
+    for (working = mPictures.begin(); working != last; working++) {
+        if ((working->mSplit == false || invalBounds != working->mUnsplit) &&
+                inval.contains(working->mArea) == false)
+            continue;
+        SkSafeUnref(working->mPicture);
+        working->mPicture = NULL;
+    }
+    return true;
+}
+
+void PictureSet::setDrawTimes(const PictureSet& src)
+{
+    validate(__FUNCTION__);
+    if (mWidth != src.mWidth || mHeight != src.mHeight)
+        return;
+    Pictures* last = mPictures.end();
+    Pictures* working = mPictures.begin();
+    if (working == last)
+        return;
+    const Pictures* srcLast = src.mPictures.end();
+    const Pictures* srcWorking = src.mPictures.begin();
+    for (; srcWorking != srcLast; srcWorking++) {
+        if (srcWorking->mWroteElapsed == false)
+            continue;
+        while ((srcWorking->mArea != working->mArea ||
+                srcWorking->mPicture != working->mPicture)) {
+            if (++working == last)
+                return;
+        }
+        DBG_SET_LOGD("%p [%d] [%d] {%d,%d,r=%d,b=%d} working->mElapsed=%d <- %d",
+            this, working - mPictures.begin(), srcWorking - src.mPictures.begin(),
+            working->mArea.getBounds().fLeft, working->mArea.getBounds().fTop,
+            working->mArea.getBounds().fRight, working->mArea.getBounds().fBottom,
+            working->mElapsed, srcWorking->mElapsed);
+        working->mElapsed = srcWorking->mElapsed;
+    }
+}
+
+void PictureSet::setPicture(size_t i, SkPicture* p)
+{
+    SkSafeUnref(mPictures[i].mPicture);
+    mPictures[i].mPicture = p;
+    mPictures[i].mEmpty = emptyPicture(p);
+}
+
+void PictureSet::split(PictureSet* out) const
+{
+    dump(__FUNCTION__);
+    DBG_SET_LOGD("%p", this);
+    SkIRect totalBounds;
+    out->mWidth = mWidth;
+    out->mHeight = mHeight;
+    totalBounds.set(0, 0, mWidth, mHeight);
+    SkRegion* total = new SkRegion(totalBounds);
+    const Pictures* last = mPictures.end();
+    const Pictures* working;
+    uint32_t balance = 0;
+    int multiUnsplitFastPictures = 0; // > 1 has more than 1
+    for (working = mPictures.begin(); working != last; working++) {
+        if (working->mElapsed >= MAX_DRAW_TIME || working->mSplit)
+            continue;
+        if (++multiUnsplitFastPictures > 1)
+            break;
+    }
+    for (working = mPictures.begin(); working != last; working++) {
+        uint32_t elapsed = working->mElapsed;
+        if (elapsed < MAX_DRAW_TIME) {
+            bool split = working->mSplit;
+            DBG_SET_LOGD("elapsed=%d working=%p total->getBounds()="
+                "{%d,%d,r=%d,b=%d} split=%s", elapsed, working,
+                total->getBounds().fLeft, total->getBounds().fTop,
+                total->getBounds().fRight, total->getBounds().fBottom,
+                split ? "true" : "false");
+            if (multiUnsplitFastPictures <= 1 || split) {
+                total->op(working->mArea, SkRegion::kDifference_Op);
+                out->add(working->mArea, working->mPicture, elapsed, split,
+                    working->mEmpty);
+            } else if (balance < elapsed)
+                balance = elapsed;
+            continue;
+        }
+        total->op(working->mArea, SkRegion::kDifference_Op);
+        const SkIRect& bounds = working->mArea.getBounds();
+        int width = bounds.width();
+        int height = bounds.height();
+        int across = 1;
+        int down = 1;
+        while (height >= MIN_SPLITTABLE || width >= MIN_SPLITTABLE) {
+            if (height >= width) {
+                height >>= 1;
+                down <<= 1;
+            } else {
+                width >>= 1;
+                across <<= 1 ;
+            }
+            if ((elapsed >>= 1) < MAX_DRAW_TIME)
+                break;
+        }
+        width = bounds.width();
+        height = bounds.height();
+        int top = bounds.fTop;
+        for (int indexY = 0; indexY < down; ) {
+            int bottom = bounds.fTop + height * ++indexY / down;
+            int left = bounds.fLeft;
+            for (int indexX = 0; indexX < across; ) {
+                int right = bounds.fLeft + width * ++indexX / across;
+                SkIRect cBounds;
+                cBounds.set(left, top, right, bottom);
+                out->add(SkRegion(cBounds), (across | down) != 1 ? NULL :
+                    working->mPicture, elapsed, true, 
+                    (across | down) != 1 ? false : working->mEmpty);
+                left = right;
+            }
+            top = bottom;
+        }
+    }
+    DBG_SET_LOGD("%p w=%d h=%d total->isEmpty()=%s multiUnsplitFastPictures=%d",
+        this, mWidth, mHeight, total->isEmpty() ? "true" : "false",
+        multiUnsplitFastPictures);
+    if (!total->isEmpty() && multiUnsplitFastPictures > 1)
+        out->add(*total, NULL, balance, false, false);
+    delete total;
+    validate(__FUNCTION__);
+    out->dump("split-out");
+}
+
+#endif // FAST_PICTURESET
+
+bool PictureSet::validate(const char* funct) const
+{
+#ifdef FAST_PICTURESET
+    return true;
+#else
+    bool valid = true;
+#if PICTURE_SET_VALIDATE
+    SkRegion all;
+    const Pictures* first = mPictures.begin();
+    for (const Pictures* working = mPictures.end(); working != first; ) {
+        --working;
+        const SkPicture* pict = working->mPicture;
+        const SkRegion& area = working->mArea;
+        const SkIRect& bounds = area.getBounds();
+        bool localValid = false;
+        if (working->mUnsplit.isEmpty())
+            LOGD("%s working->mUnsplit.isEmpty()", funct);
+        else if (working->mUnsplit.contains(bounds) == false)
+            LOGD("%s working->mUnsplit.contains(bounds) == false", funct);
+        else if (working->mElapsed >= 1000)
+            LOGD("%s working->mElapsed >= 1000", funct);
+        else if ((working->mSplit & 0xfe) != 0)
+            LOGD("%s (working->mSplit & 0xfe) != 0", funct);
+        else if ((working->mWroteElapsed & 0xfe) != 0)
+            LOGD("%s (working->mWroteElapsed & 0xfe) != 0", funct);
+        else if (pict != NULL) {
+            int pictWidth = pict->width();
+            int pictHeight = pict->height();
+            if (pictWidth < bounds.width())
+                LOGD("%s pictWidth=%d < bounds.width()=%d", funct, pictWidth, bounds.width());
+            else if (pictHeight < bounds.height())
+                LOGD("%s pictHeight=%d < bounds.height()=%d", funct, pictHeight, bounds.height());
+            else if (working->mArea.isEmpty())
+                LOGD("%s working->mArea.isEmpty()", funct);
+            else
+                localValid = true;
+        } else
+            localValid = true;
+        working->mArea.validate();
+        if (localValid == false) {
+            if (all.contains(area) == true)
+                LOGD("%s all.contains(area) == true", funct);
+            else
+                localValid = true;
+        }
+        valid &= localValid;
+        all.op(area, SkRegion::kUnion_Op);
+    }
+    const SkIRect& allBounds = all.getBounds();
+    if (valid) {
+        valid = false;
+        if (allBounds.width() != mWidth)
+            LOGD("%s allBounds.width()=%d != mWidth=%d", funct, allBounds.width(), mWidth);
+        else if (allBounds.height() != mHeight)
+            LOGD("%s allBounds.height()=%d != mHeight=%d", funct, allBounds.height(), mHeight);
+        else
+            valid = true;
+    }
+    while (valid == false)
+        ;
+#endif
+    return valid;
+#endif // FAST_PICTURESET
+}
+
+} /* namespace android */
diff --git a/Source/WebKit/android/jni/PictureSet.h b/Source/WebKit/android/jni/PictureSet.h
new file mode 100644
index 0000000..fe47361
--- /dev/null
+++ b/Source/WebKit/android/jni/PictureSet.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PictureSet_h
+#define PictureSet_h
+
+#define PICTURE_SET_DUMP 0
+#define PICTURE_SET_DEBUG 0
+#define PICTURE_SET_VALIDATE 0
+
+#if PICTURE_SET_DEBUG
+#define DBG_SET_LOG(message) LOGD("%s %s", __FUNCTION__, message)
+#define DBG_SET_LOGD(format, ...) LOGD("%s " format, __FUNCTION__, __VA_ARGS__)
+#define DEBUG_SET_UI_LOGD(...) LOGD(__VA_ARGS__)
+#else
+#define DBG_SET_LOG(message) ((void)0)
+#define DBG_SET_LOGD(format, ...) ((void)0)
+#define DEBUG_SET_UI_LOGD(...) ((void)0)
+#endif
+
+#include "jni.h"
+#include "SkRegion.h"
+#include <wtf/Vector.h>
+#include <wtf/HashMap.h>
+
+// #define FAST_PICTURESET // use a hierarchy of pictures
+
+class SkCanvas;
+class SkPicture;
+class SkIRect;
+
+namespace android {
+
+#ifdef FAST_PICTURESET
+    struct BucketPicture {
+        SkPicture* mPicture;
+        SkIRect mArea;
+        SkIRect mRealArea;
+        bool mBase;
+    };
+
+    typedef std::pair<int, int> BucketPosition;
+    typedef WTF::Vector<BucketPicture> Bucket;
+    typedef WTF::HashMap<BucketPosition , Bucket* > BucketMap;
+#endif
+
+    class PictureSet {
+    public:
+        PictureSet();
+        PictureSet(const PictureSet& src) { set(src); }
+        PictureSet(SkPicture* picture);
+        virtual ~PictureSet();
+
+#ifdef FAST_PICTURESET
+        void displayBucket(Bucket* bucket);
+        void displayBuckets();
+        WTF::Vector<Bucket*>* bucketsToUpdate() { return &mUpdatedBuckets; }
+        Bucket* getBucket(int x, int y);
+        void addToBucket(Bucket* bucket, int dx, int dy, SkIRect& rect);
+        void gatherBucketsForArea(WTF::Vector<Bucket*>& list, const SkIRect& rect);
+        void splitAdd(const SkIRect& rect);
+#endif
+
+        void add(const SkRegion& area, SkPicture* picture,
+            uint32_t elapsed, bool split);
+
+        // Update mWidth/mHeight, and adds any additional inval region
+        void setDimensions(int width, int height, SkRegion* inval = 0);
+        void clear();
+        bool draw(SkCanvas* );
+        static PictureSet* GetNativePictureSet(JNIEnv* env, jobject jpic);
+        int height() const { return mHeight; }
+        bool isEmpty() const; // returns true if empty or only trivial content
+        void set(const PictureSet& );
+
+#ifdef FAST_PICTURESET
+#else
+        void add(const SkRegion& area, SkPicture* picture,
+            uint32_t elapsed, bool split, bool empty);
+        const SkIRect& bounds(size_t i) const {
+            return mPictures[i].mArea.getBounds(); }
+        bool reuseSubdivided(const SkRegion& );
+        void setPicture(size_t i, SkPicture* p);
+        void setDrawTimes(const PictureSet& );
+        size_t size() const { return mPictures.size(); }
+        void split(PictureSet* result) const;
+        bool upToDate(size_t i) const { return mPictures[i].mPicture != NULL; }
+#endif
+        int width() const { return mWidth; }
+        void dump(const char* label) const;
+        bool validate(const char* label) const;
+    private:
+        bool emptyPicture(SkPicture* ) const; // true if no text, images, paths
+
+#ifdef FAST_PICTURESET
+        BucketMap mBuckets;
+        WTF::Vector<Bucket*> mUpdatedBuckets;
+        int mBucketSizeX;
+        int mBucketSizeY;
+        int mBucketCountX;
+        int mBucketCountY;
+#else
+        struct Pictures {
+            SkRegion mArea;
+            SkPicture* mPicture;
+            SkIRect mUnsplit;
+            uint32_t mElapsed;
+            bool mSplit : 8;
+            bool mWroteElapsed : 8;
+            bool mBase : 8; // true if nothing is drawn underneath this
+            bool mEmpty : 8; // true if the picture only draws white
+        };
+        void add(const Pictures* temp);
+        WTF::Vector<Pictures> mPictures;
+#endif
+        float mBaseArea;
+        float mAdditionalArea;
+        int mHeight;
+        int mWidth;
+    };
+}
+
+#endif
diff --git a/Source/WebKit/android/jni/ViewStateSerializer.cpp b/Source/WebKit/android/jni/ViewStateSerializer.cpp
index 02ddca6..6b473f5 100644
--- a/Source/WebKit/android/jni/ViewStateSerializer.cpp
+++ b/Source/WebKit/android/jni/ViewStateSerializer.cpp
@@ -23,23 +23,15 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#define LOG_TAG "ViewStateSerializer"
-#define LOG_NDEBUG 1
-
 #include "config.h"
 
 #include "BaseLayerAndroid.h"
 #include "CreateJavaOutputStreamAdaptor.h"
-#include "FixedPositioning.h"
 #include "ImagesManager.h"
-#include "IFrameContentLayerAndroid.h"
-#include "IFrameLayerAndroid.h"
 #include "Layer.h"
 #include "LayerAndroid.h"
-#include "LayerContent.h"
-#include "PictureLayerContent.h"
+#include "PictureSet.h"
 #include "ScrollableLayerAndroid.h"
-#include "SkFlattenable.h"
 #include "SkPicture.h"
 #include "TilesManager.h"
 
@@ -47,13 +39,24 @@
 #include <JNIHelp.h>
 #include <jni.h>
 
+#ifdef DEBUG
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ViewStateSerializer", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
 namespace android {
 
 enum LayerTypes {
     LTNone = 0,
     LTLayerAndroid = 1,
     LTScrollableLayerAndroid = 2,
-    LTFixedLayerAndroid = 3
 };
 
 static bool nativeSerializeViewState(JNIEnv* env, jobject, jint jbaseLayer,
@@ -69,14 +72,16 @@
 #else
     stream->write32(0);
 #endif
+    SkPicture picture;
+    PictureSet* content = baseLayer->content();
+    baseLayer->drawCanvas(picture.beginRecording(content->width(), content->height(),
+            SkPicture::kUsePathBoundsForClip_RecordingFlag));
+    picture.endRecording();
     if (!stream)
         return false;
-    if (baseLayer->content())
-        baseLayer->content()->serialize(stream);
-    else
-        return false;
+    picture.serialize(stream);
     int childCount = baseLayer->countChildren();
-    ALOGV("BaseLayer has %d child(ren)", childCount);
+    XLOG("BaseLayer has %d child(ren)", childCount);
     stream->write32(childCount);
     for (int i = 0; i < childCount; i++) {
         LayerAndroid* layer = static_cast<LayerAndroid*>(baseLayer->getChild(i));
@@ -86,28 +91,23 @@
     return true;
 }
 
-static BaseLayerAndroid* nativeDeserializeViewState(JNIEnv* env, jobject, jint version,
-                                                    jobject jstream, jbyteArray jstorage)
+static BaseLayerAndroid* nativeDeserializeViewState(JNIEnv* env, jobject, jobject jstream,
+                                      jbyteArray jstorage)
 {
     SkStream* stream = CreateJavaInputStreamAdaptor(env, jstream, jstorage);
     if (!stream)
         return 0;
+    BaseLayerAndroid* layer = new BaseLayerAndroid();
     Color color = stream->readU32();
-    SkPicture* picture = new SkPicture(stream);
-    PictureLayerContent* content = new PictureLayerContent(picture);
-
-    BaseLayerAndroid* layer = new BaseLayerAndroid(content);
+#if USE(ACCELERATED_COMPOSITING)
     layer->setBackgroundColor(color);
-
-    SkRegion dirtyRegion;
-    dirtyRegion.setRect(0, 0, content->width(), content->height());
-    layer->markAsDirty(dirtyRegion);
-
-    SkSafeUnref(content);
+#endif
+    SkPicture* picture = new SkPicture(stream);
+    layer->setContent(picture);
     SkSafeUnref(picture);
     int childCount = stream->readS32();
     for (int i = 0; i < childCount; i++) {
-        LayerAndroid* childLayer = deserializeLayer(version, stream);
+        LayerAndroid* childLayer = deserializeLayer(stream);
         if (childLayer)
             layer->addChild(childLayer);
     }
@@ -242,20 +242,20 @@
 void serializeLayer(LayerAndroid* layer, SkWStream* stream)
 {
     if (!layer) {
-        ALOGV("NULL layer!");
+        XLOG("NULL layer!");
         stream->write8(LTNone);
         return;
     }
     if (layer->isMedia() || layer->isVideo()) {
-        ALOGV("Layer isn't supported for serialization: isMedia: %s, isVideo: %s",
+        XLOG("Layer isn't supported for serialization: isMedia: %s, isVideo: %s",
              layer->isMedia() ? "true" : "false",
              layer->isVideo() ? "true" : "false");
         stream->write8(LTNone);
         return;
     }
-    LayerTypes type = LTLayerAndroid;
-    if (layer->contentIsScrollable())
-        type = LTScrollableLayerAndroid;
+    LayerTypes type = layer->contentIsScrollable()
+            ? LTScrollableLayerAndroid
+            : LTLayerAndroid;
     stream->write8(type);
 
     // Start with Layer fields
@@ -272,43 +272,20 @@
 
     // Next up, LayerAndroid fields
     stream->writeBool(layer->m_haveClip);
-    stream->writeBool(layer->isPositionFixed());
+    stream->writeBool(layer->m_isFixed);
     stream->writeBool(layer->m_backgroundColorSet);
-    stream->writeBool(layer->isIFrame());
-
-    // With the current LayerAndroid hierarchy, LayerAndroid doesn't have
-    // those fields anymore. Let's keep the current serialization format for
-    // now and output blank fields... not great, but probably better than
-    // dealing with multiple versions.
-    if (layer->fixedPosition()) {
-        FixedPositioning* fixedPosition = layer->fixedPosition();
-        writeSkLength(stream, fixedPosition->m_fixedLeft);
-        writeSkLength(stream, fixedPosition->m_fixedTop);
-        writeSkLength(stream, fixedPosition->m_fixedRight);
-        writeSkLength(stream, fixedPosition->m_fixedBottom);
-        writeSkLength(stream, fixedPosition->m_fixedMarginLeft);
-        writeSkLength(stream, fixedPosition->m_fixedMarginTop);
-        writeSkLength(stream, fixedPosition->m_fixedMarginRight);
-        writeSkLength(stream, fixedPosition->m_fixedMarginBottom);
-        writeSkRect(stream, fixedPosition->m_fixedRect);
-        stream->write32(fixedPosition->m_renderLayerPos.x());
-        stream->write32(fixedPosition->m_renderLayerPos.y());
-    } else {
-        SkLength length;
-        SkRect rect;
-        writeSkLength(stream, length); // fixedLeft
-        writeSkLength(stream, length); // fixedTop
-        writeSkLength(stream, length); // fixedRight
-        writeSkLength(stream, length); // fixedBottom
-        writeSkLength(stream, length); // fixedMarginLeft
-        writeSkLength(stream, length); // fixedMarginTop
-        writeSkLength(stream, length); // fixedMarginRight
-        writeSkLength(stream, length); // fixedMarginBottom
-        writeSkRect(stream, rect);     // fixedRect
-        stream->write32(0);            // renderLayerPos.x()
-        stream->write32(0);            // renderLayerPos.y()
-    }
-
+    stream->writeBool(layer->m_isIframe);
+    writeSkLength(stream, layer->m_fixedLeft);
+    writeSkLength(stream, layer->m_fixedTop);
+    writeSkLength(stream, layer->m_fixedRight);
+    writeSkLength(stream, layer->m_fixedBottom);
+    writeSkLength(stream, layer->m_fixedMarginLeft);
+    writeSkLength(stream, layer->m_fixedMarginTop);
+    writeSkLength(stream, layer->m_fixedMarginRight);
+    writeSkLength(stream, layer->m_fixedMarginBottom);
+    writeSkRect(stream, layer->m_fixedRect);
+    stream->write32(layer->m_renderLayerPos.x());
+    stream->write32(layer->m_renderLayerPos.y());
     stream->writeBool(layer->m_backfaceVisibility);
     stream->writeBool(layer->m_visible);
     stream->write32(layer->m_backgroundColor);
@@ -328,10 +305,10 @@
         stream->write32(buffer.size());
         buffer.writeToStream(stream);
     }
-    bool hasRecordingPicture = layer->m_content != 0 && !layer->m_content->isEmpty();
+    bool hasRecordingPicture = layer->m_recordingPicture != 0;
     stream->writeBool(hasRecordingPicture);
     if (hasRecordingPicture)
-        layer->m_content->serialize(stream);
+        layer->m_recordingPicture->serialize(stream);
     // TODO: support m_animations (maybe?)
     stream->write32(0); // placeholder for m_animations.size();
     writeTransformationMatrix(stream, layer->m_transform);
@@ -350,7 +327,7 @@
         serializeLayer(layer->getChild(i), stream);
 }
 
-LayerAndroid* deserializeLayer(int version, SkStream* stream)
+LayerAndroid* deserializeLayer(SkStream* stream)
 {
     int type = stream->readU8();
     if (type == LTNone)
@@ -362,7 +339,7 @@
     else if (type == LTScrollableLayerAndroid)
         layer = new ScrollableLayerAndroid((RenderLayer*) 0);
     else {
-        ALOGV("Unexpected layer type: %d, aborting!", type);
+        XLOG("Unexpected layer type: %d, aborting!", type);
         return 0;
     }
 
@@ -377,55 +354,20 @@
 
     // LayerAndroid fields
     layer->m_haveClip = stream->readBool();
-
-    // Keep the legacy serialization/deserialization format...
-    bool isFixed = stream->readBool();
-
+    layer->m_isFixed = stream->readBool();
     layer->m_backgroundColorSet = stream->readBool();
-
-    bool isIframe = stream->readBool();
-    // If we are a scrollable layer android, we are an iframe content
-    if (isIframe && type == LTScrollableLayerAndroid) {
-         IFrameContentLayerAndroid* iframeContent = new IFrameContentLayerAndroid(*layer);
-         layer->unref();
-         layer = iframeContent;
-    } else if (isIframe) { // otherwise we are just the iframe (we use it to compute offset)
-         IFrameLayerAndroid* iframe = new IFrameLayerAndroid(*layer);
-         layer->unref();
-         layer = iframe;
-    }
-
-    if (isFixed) {
-        FixedPositioning* fixedPosition = new FixedPositioning(layer);
-
-        fixedPosition->m_fixedLeft = readSkLength(stream);
-        fixedPosition->m_fixedTop = readSkLength(stream);
-        fixedPosition->m_fixedRight = readSkLength(stream);
-        fixedPosition->m_fixedBottom = readSkLength(stream);
-        fixedPosition->m_fixedMarginLeft = readSkLength(stream);
-        fixedPosition->m_fixedMarginTop = readSkLength(stream);
-        fixedPosition->m_fixedMarginRight = readSkLength(stream);
-        fixedPosition->m_fixedMarginBottom = readSkLength(stream);
-        fixedPosition->m_fixedRect = readSkRect(stream);
-        fixedPosition->m_renderLayerPos.setX(stream->readS32());
-        fixedPosition->m_renderLayerPos.setY(stream->readS32());
-
-        layer->setFixedPosition(fixedPosition);
-    } else {
-        // Not a fixed element, bypass the values in the stream
-        readSkLength(stream); // fixedLeft
-        readSkLength(stream); // fixedTop
-        readSkLength(stream); // fixedRight
-        readSkLength(stream); // fixedBottom
-        readSkLength(stream); // fixedMarginLeft
-        readSkLength(stream); // fixedMarginTop
-        readSkLength(stream); // fixedMarginRight
-        readSkLength(stream); // fixedMarginBottom
-        readSkRect(stream);   // fixedRect
-        stream->readS32();    // renderLayerPos.x()
-        stream->readS32();    // renderLayerPos.y()
-    }
-
+    layer->m_isIframe = stream->readBool();
+    layer->m_fixedLeft = readSkLength(stream);
+    layer->m_fixedTop = readSkLength(stream);
+    layer->m_fixedRight = readSkLength(stream);
+    layer->m_fixedBottom = readSkLength(stream);
+    layer->m_fixedMarginLeft = readSkLength(stream);
+    layer->m_fixedMarginTop = readSkLength(stream);
+    layer->m_fixedMarginRight = readSkLength(stream);
+    layer->m_fixedMarginBottom = readSkLength(stream);
+    layer->m_fixedRect = readSkRect(stream);
+    layer->m_renderLayerPos.setX(stream->readS32());
+    layer->m_renderLayerPos.setY(stream->readS32());
     layer->m_backfaceVisibility = stream->readBool();
     layer->m_visible = stream->readBool();
     layer->m_backgroundColor = stream->readU32();
@@ -446,11 +388,7 @@
     }
     bool hasRecordingPicture = stream->readBool();
     if (hasRecordingPicture) {
-        SkPicture* picture = new SkPicture(stream);
-        PictureLayerContent* content = new PictureLayerContent(picture);
-        layer->setContent(content);
-        SkSafeUnref(content);
-        SkSafeUnref(picture);
+        layer->m_recordingPicture = new SkPicture(stream);
     }
     int animationCount = stream->readU32(); // TODO: Support (maybe?)
     readTransformationMatrix(stream, layer->m_transform);
@@ -466,11 +404,12 @@
     }
     int childCount = stream->readU32();
     for (int i = 0; i < childCount; i++) {
-        LayerAndroid *childLayer = deserializeLayer(version, stream);
+        LayerAndroid *childLayer = deserializeLayer(stream);
         if (childLayer)
             layer->addChild(childLayer);
     }
-    ALOGV("Created layer with id %d", layer->uniqueId());
+    layer->needsRepaint();
+    XLOG("Created layer with id %d", layer->uniqueId());
     return layer;
 }
 
@@ -480,7 +419,7 @@
 static JNINativeMethod gSerializerMethods[] = {
     { "nativeSerializeViewState", "(ILjava/io/OutputStream;[B)Z",
         (void*) nativeSerializeViewState },
-    { "nativeDeserializeViewState", "(ILjava/io/InputStream;[B)I",
+    { "nativeDeserializeViewState", "(Ljava/io/InputStream;[B)I",
         (void*) nativeDeserializeViewState },
 };
 
diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp
index 4ce3d8e..d53ddb6 100644
--- a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp
+++ b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp
@@ -60,8 +60,6 @@
 #include "IconDatabase.h"
 #include "Image.h"
 #include "InspectorClientAndroid.h"
-#include "JavaNPObjectV8.h"
-#include "JavaInstanceJobjectV8.h"
 #include "KURL.h"
 #include "Page.h"
 #include "PageCache.h"
@@ -83,6 +81,7 @@
 #include "WebArchiveAndroid.h"
 #include "WebCache.h"
 #include "WebCoreJni.h"
+#include "WebCoreResourceLoader.h"
 #include "WebHistory.h"
 #include "WebIconDatabase.h"
 #include "WebFrameView.h"
@@ -100,13 +99,30 @@
 #include <android_runtime/android_util_AssetManager.h>
 #include <openssl/x509.h>
 #include <utils/misc.h>
-#include <androidfw/AssetManager.h>
+#include <utils/AssetManager.h>
 #include <wtf/CurrentTime.h>
 #include <wtf/Platform.h>
 #include <wtf/text/AtomicString.h>
 #include <wtf/text/CString.h>
 #include <wtf/text/StringBuilder.h>
 
+#if USE(JSC)
+#include "GCController.h"
+#include "JSDOMWindow.h"
+#include "JavaInstanceJSC.h"
+#include <runtime_object.h>
+#include <runtime_root.h>
+#include <runtime/JSLock.h>
+#elif USE(V8)
+#include "JavaNPObjectV8.h"
+#include "JavaInstanceJobjectV8.h"
+#include "V8Counters.h"
+#endif  // USE(JSC)
+
+#ifdef ANDROID_INSTRUMENT
+#include "TimeCounter.h"
+#endif
+
 #if ENABLE(WEB_AUTOFILL)
 #include "autofill/WebAutofill.h"
 #endif
@@ -228,6 +244,8 @@
     mJavaFrame = new JavaBrowserFrame;
     mJavaFrame->mObj = env->NewWeakGlobalRef(obj);
     mJavaFrame->mHistoryList = env->NewWeakGlobalRef(historyList);
+    mJavaFrame->mStartLoadingResource = env->GetMethodID(clazz, "startLoadingResource",
+            "(ILjava/lang/String;Ljava/lang/String;Ljava/util/HashMap;[BJIZZZLjava/lang/String;Ljava/lang/String;)Landroid/webkit/LoadListener;");
     mJavaFrame->mMaybeSavePassword = env->GetMethodID(clazz, "maybeSavePassword",
             "([BLjava/lang/String;Ljava/lang/String;)V");
     mJavaFrame->mShouldInterceptRequest =
@@ -283,39 +301,41 @@
             "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
     env->DeleteLocalRef(clazz);
 
-    ALOG_ASSERT(mJavaFrame->mMaybeSavePassword, "Could not find method maybeSavePassword");
-    ALOG_ASSERT(mJavaFrame->mShouldInterceptRequest, "Could not find method shouldInterceptRequest");
-    ALOG_ASSERT(mJavaFrame->mLoadStarted, "Could not find method loadStarted");
-    ALOG_ASSERT(mJavaFrame->mTransitionToCommitted, "Could not find method transitionToCommitted");
-    ALOG_ASSERT(mJavaFrame->mLoadFinished, "Could not find method loadFinished");
-    ALOG_ASSERT(mJavaFrame->mReportError, "Could not find method reportError");
-    ALOG_ASSERT(mJavaFrame->mSetTitle, "Could not find method setTitle");
-    ALOG_ASSERT(mJavaFrame->mWindowObjectCleared, "Could not find method windowObjectCleared");
-    ALOG_ASSERT(mJavaFrame->mSetProgress, "Could not find method setProgress");
-    ALOG_ASSERT(mJavaFrame->mDidReceiveIcon, "Could not find method didReceiveIcon");
-    ALOG_ASSERT(mJavaFrame->mDidReceiveTouchIconUrl, "Could not find method didReceiveTouchIconUrl");
-    ALOG_ASSERT(mJavaFrame->mUpdateVisitedHistory, "Could not find method updateVisitedHistory");
-    ALOG_ASSERT(mJavaFrame->mHandleUrl, "Could not find method handleUrl");
-    ALOG_ASSERT(mJavaFrame->mCreateWindow, "Could not find method createWindow");
-    ALOG_ASSERT(mJavaFrame->mCloseWindow, "Could not find method closeWindow");
-    ALOG_ASSERT(mJavaFrame->mDecidePolicyForFormResubmission, "Could not find method decidePolicyForFormResubmission");
-    ALOG_ASSERT(mJavaFrame->mRequestFocus, "Could not find method requestFocus");
-    ALOG_ASSERT(mJavaFrame->mGetRawResFilename, "Could not find method getRawResFilename");
-    ALOG_ASSERT(mJavaFrame->mDensity, "Could not find method density");
-    ALOG_ASSERT(mJavaFrame->mGetFileSize, "Could not find method getFileSize");
-    ALOG_ASSERT(mJavaFrame->mGetFile, "Could not find method getFile");
-    ALOG_ASSERT(mJavaFrame->mDidReceiveAuthenticationChallenge, "Could not find method didReceiveAuthenticationChallenge");
-    ALOG_ASSERT(mJavaFrame->mReportSslCertError, "Could not find method reportSslCertError");
-    ALOG_ASSERT(mJavaFrame->mRequestClientCert, "Could not find method requestClientCert");
-    ALOG_ASSERT(mJavaFrame->mDownloadStart, "Could not find method downloadStart");
-    ALOG_ASSERT(mJavaFrame->mDidReceiveData, "Could not find method didReceiveData");
-    ALOG_ASSERT(mJavaFrame->mDidFinishLoading, "Could not find method didFinishLoading");
-    ALOG_ASSERT(mJavaFrame->mSetCertificate, "Could not find method setCertificate");
-    ALOG_ASSERT(mJavaFrame->mShouldSaveFormData, "Could not find method shouldSaveFormData");
-    ALOG_ASSERT(mJavaFrame->mSaveFormData, "Could not find method saveFormData");
-    ALOG_ASSERT(mJavaFrame->mAutoLogin, "Could not find method autoLogin");
+    LOG_ASSERT(mJavaFrame->mStartLoadingResource, "Could not find method startLoadingResource");
+    LOG_ASSERT(mJavaFrame->mMaybeSavePassword, "Could not find method maybeSavePassword");
+    LOG_ASSERT(mJavaFrame->mShouldInterceptRequest, "Could not find method shouldInterceptRequest");
+    LOG_ASSERT(mJavaFrame->mLoadStarted, "Could not find method loadStarted");
+    LOG_ASSERT(mJavaFrame->mTransitionToCommitted, "Could not find method transitionToCommitted");
+    LOG_ASSERT(mJavaFrame->mLoadFinished, "Could not find method loadFinished");
+    LOG_ASSERT(mJavaFrame->mReportError, "Could not find method reportError");
+    LOG_ASSERT(mJavaFrame->mSetTitle, "Could not find method setTitle");
+    LOG_ASSERT(mJavaFrame->mWindowObjectCleared, "Could not find method windowObjectCleared");
+    LOG_ASSERT(mJavaFrame->mSetProgress, "Could not find method setProgress");
+    LOG_ASSERT(mJavaFrame->mDidReceiveIcon, "Could not find method didReceiveIcon");
+    LOG_ASSERT(mJavaFrame->mDidReceiveTouchIconUrl, "Could not find method didReceiveTouchIconUrl");
+    LOG_ASSERT(mJavaFrame->mUpdateVisitedHistory, "Could not find method updateVisitedHistory");
+    LOG_ASSERT(mJavaFrame->mHandleUrl, "Could not find method handleUrl");
+    LOG_ASSERT(mJavaFrame->mCreateWindow, "Could not find method createWindow");
+    LOG_ASSERT(mJavaFrame->mCloseWindow, "Could not find method closeWindow");
+    LOG_ASSERT(mJavaFrame->mDecidePolicyForFormResubmission, "Could not find method decidePolicyForFormResubmission");
+    LOG_ASSERT(mJavaFrame->mRequestFocus, "Could not find method requestFocus");
+    LOG_ASSERT(mJavaFrame->mGetRawResFilename, "Could not find method getRawResFilename");
+    LOG_ASSERT(mJavaFrame->mDensity, "Could not find method density");
+    LOG_ASSERT(mJavaFrame->mGetFileSize, "Could not find method getFileSize");
+    LOG_ASSERT(mJavaFrame->mGetFile, "Could not find method getFile");
+    LOG_ASSERT(mJavaFrame->mDidReceiveAuthenticationChallenge, "Could not find method didReceiveAuthenticationChallenge");
+    LOG_ASSERT(mJavaFrame->mReportSslCertError, "Could not find method reportSslCertError");
+    LOG_ASSERT(mJavaFrame->mRequestClientCert, "Could not find method requestClientCert");
+    LOG_ASSERT(mJavaFrame->mDownloadStart, "Could not find method downloadStart");
+    LOG_ASSERT(mJavaFrame->mDidReceiveData, "Could not find method didReceiveData");
+    LOG_ASSERT(mJavaFrame->mDidFinishLoading, "Could not find method didFinishLoading");
+    LOG_ASSERT(mJavaFrame->mSetCertificate, "Could not find method setCertificate");
+    LOG_ASSERT(mJavaFrame->mShouldSaveFormData, "Could not find method shouldSaveFormData");
+    LOG_ASSERT(mJavaFrame->mSaveFormData, "Could not find method saveFormData");
+    LOG_ASSERT(mJavaFrame->mAutoLogin, "Could not find method autoLogin");
 
     mUserAgent = WTF::String();
+    mUserInitiatedAction = false;
     mBlockNetworkLoads = false;
     m_renderSkins = 0;
 }
@@ -342,14 +362,14 @@
 static jobject createJavaMapFromHTTPHeaders(JNIEnv* env, const WebCore::HTTPHeaderMap& map)
 {
     jclass mapClass = env->FindClass("java/util/HashMap");
-    ALOG_ASSERT(mapClass, "Could not find HashMap class!");
+    LOG_ASSERT(mapClass, "Could not find HashMap class!");
     jmethodID init = env->GetMethodID(mapClass, "<init>", "(I)V");
-    ALOG_ASSERT(init, "Could not find constructor for HashMap");
+    LOG_ASSERT(init, "Could not find constructor for HashMap");
     jobject hashMap = env->NewObject(mapClass, init, map.size());
-    ALOG_ASSERT(hashMap, "Could not create a new HashMap");
+    LOG_ASSERT(hashMap, "Could not create a new HashMap");
     jmethodID put = env->GetMethodID(mapClass, "put",
             "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
-    ALOG_ASSERT(put, "Could not find put method on HashMap");
+    LOG_ASSERT(put, "Could not find put method on HashMap");
 
     WebCore::HTTPHeaderMap::const_iterator end = map.end();
     for (WebCore::HTTPHeaderMap::const_iterator i = map.begin(); i != end; ++i) {
@@ -396,10 +416,104 @@
     int m_size;
 };
 
+PassRefPtr<WebCore::ResourceLoaderAndroid>
+WebFrame::startLoadingResource(WebCore::ResourceHandle* loader,
+                                  const WebCore::ResourceRequest& request,
+                                  bool mainResource,
+                                  bool synchronous)
+{
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
+    LOGV("::WebCore:: startLoadingResource(%p, %s)",
+            loader, request.url().string().latin1().data());
+
+    JNIEnv* env = getJNIEnv();
+    AutoJObject javaFrame = mJavaFrame->frame(env);
+    if (!javaFrame.get())
+        return 0;
+
+    WTF::String method = request.httpMethod();
+    WebCore::HTTPHeaderMap headers = request.httpHeaderFields();
+
+    WTF::String urlStr = request.url().string();
+    int colon = urlStr.find(':');
+    bool allLower = true;
+    for (int index = 0; index < colon; index++) {
+        UChar ch = urlStr[index];
+        if (!WTF::isASCIIAlpha(ch))
+            break;
+        allLower &= WTF::isASCIILower(ch);
+        if (index == colon - 1 && !allLower) {
+            urlStr = urlStr.substring(0, colon).lower()
+                    + urlStr.substring(colon);
+        }
+    }
+    LOGV("%s lower=%s", __FUNCTION__, urlStr.latin1().data());
+    jstring jUrlStr = wtfStringToJstring(env, urlStr);
+    jstring jMethodStr = NULL;
+    if (!method.isEmpty())
+        jMethodStr = wtfStringToJstring(env, method);
+    WebCore::FormData* formdata = request.httpBody();
+    jbyteArray jPostDataStr = getPostData(request);
+    jobject jHeaderMap = createJavaMapFromHTTPHeaders(env, headers);
+
+    // Convert the WebCore Cache Policy to a WebView Cache Policy.
+    int cacheMode = 0;  // WebSettings.LOAD_NORMAL
+    switch (request.cachePolicy()) {
+        case WebCore::ReloadIgnoringCacheData:
+            cacheMode = 2; // WebSettings.LOAD_NO_CACHE
+            break;
+        case WebCore::ReturnCacheDataDontLoad:
+            cacheMode = 3; // WebSettings.LOAD_CACHE_ONLY
+            break;
+        case WebCore::ReturnCacheDataElseLoad:
+            cacheMode = 1;   // WebSettings.LOAD_CACHE_ELSE_NETWORK
+            break;
+        case WebCore::UseProtocolCachePolicy:
+        default:
+            break;
+    }
+
+    LOGV("::WebCore:: startLoadingResource %s with cacheMode %d", urlStr.ascii().data(), cacheMode);
+
+    ResourceHandleInternal* loaderInternal = loader->getInternal();
+    jstring jUsernameString = loaderInternal->m_user.isEmpty() ?
+            NULL : wtfStringToJstring(env, loaderInternal->m_user);
+    jstring jPasswordString = loaderInternal->m_pass.isEmpty() ?
+            NULL : wtfStringToJstring(env, loaderInternal->m_pass);
+
+    bool isUserGesture = UserGestureIndicator::processingUserGesture();
+    jobject jLoadListener =
+        env->CallObjectMethod(javaFrame.get(), mJavaFrame->mStartLoadingResource,
+                (int)loader, jUrlStr, jMethodStr, jHeaderMap,
+                jPostDataStr, formdata ? formdata->identifier(): 0,
+                cacheMode, mainResource, isUserGesture,
+                synchronous, jUsernameString, jPasswordString);
+
+    env->DeleteLocalRef(jUrlStr);
+    env->DeleteLocalRef(jMethodStr);
+    env->DeleteLocalRef(jPostDataStr);
+    env->DeleteLocalRef(jHeaderMap);
+    env->DeleteLocalRef(jUsernameString);
+    env->DeleteLocalRef(jPasswordString);
+    if (checkException(env))
+        return 0;
+
+    PassRefPtr<WebCore::ResourceLoaderAndroid> h;
+    if (jLoadListener)
+        h = WebCoreResourceLoader::create(env, jLoadListener);
+    env->DeleteLocalRef(jLoadListener);
+    return h;
+}
+
 UrlInterceptResponse*
 WebFrame::shouldInterceptRequest(const WTF::String& url)
 {
-    ALOGV("::WebCore:: shouldInterceptRequest(%s)", url.latin1().data());
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
+    LOGV("::WebCore:: shouldInterceptRequest(%s)", url.latin1().data());
 
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
@@ -420,7 +534,10 @@
 WebFrame::reportError(int errorCode, const WTF::String& description,
         const WTF::String& failingUrl)
 {
-    ALOGV("::WebCore:: reportError(%d, %s)", errorCode, description.ascii().data());
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
+    LOGV("::WebCore:: reportError(%d, %s)", errorCode, description.ascii().data());
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -436,6 +553,7 @@
 WTF::String
 WebFrame::convertIDNToUnicode(const WebCore::KURL& url) {
     WTF::String converted = url.string();
+#if USE(CHROME_NETWORK_STACK)
     const WTF::String host = url.host();
     if (host.find("xn--") == notFound)  // no punycode IDN found.
         return converted;
@@ -448,12 +566,16 @@
         newUrl.setHost(convertedHost);
         converted = newUrl.string();
     }
+#endif
     return converted;
 }
 
 void
 WebFrame::loadStarted(WebCore::Frame* frame)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -467,7 +589,7 @@
     const WebCore::KURL& url = documentLoader->url();
     if (url.isEmpty())
         return;
-    ALOGV("::WebCore:: loadStarted %s", url.string().ascii().data());
+    LOGV("::WebCore:: loadStarted %s", url.string().ascii().data());
 
     bool isMainFrame = (!frame->tree() || !frame->tree()->parent());
     WebCore::FrameLoadType loadType = frame->loader()->loadType();
@@ -487,7 +609,7 @@
         WebCore::Image* icon = WebCore::iconDatabase().synchronousIconForPageURL(urlString, WebCore::IntSize(16, 16));
         if (icon)
             favicon = webcoreImageToJavaBitmap(env, icon);
-        ALOGV("favicons", "Starting load with icon %p for %s", icon, url.string().utf8().data());
+        LOGV("favicons", "Starting load with icon %p for %s", icon, url.string().utf8().data());
     }
     jstring urlStr = wtfStringToJstring(env, urlString);
 
@@ -511,6 +633,9 @@
 void
 WebFrame::transitionToCommitted(WebCore::Frame* frame)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -525,6 +650,9 @@
 void
 WebFrame::didFinishLoad(WebCore::Frame* frame)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -539,7 +667,7 @@
     const WebCore::KURL& url = documentLoader->url();
     if (url.isEmpty())
         return;
-    ALOGV("::WebCore:: didFinishLoad %s", url.string().ascii().data());
+    LOGV("::WebCore:: didFinishLoad %s", url.string().ascii().data());
 
     bool isMainFrame = (!frame->tree() || !frame->tree()->parent());
     WebCore::FrameLoadType loadType = loader->loadType();
@@ -553,7 +681,10 @@
 void
 WebFrame::addHistoryItem(WebCore::HistoryItem* item)
 {
-    ALOGV("::WebCore:: addHistoryItem");
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
+    LOGV("::WebCore:: addHistoryItem");
     JNIEnv* env = getJNIEnv();
     WebHistory::AddItem(mJavaFrame->history(env), item);
 }
@@ -561,7 +692,10 @@
 void
 WebFrame::removeHistoryItem(int index)
 {
-    ALOGV("::WebCore:: removeHistoryItem at %d", index);
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
+    LOGV("::WebCore:: removeHistoryItem at %d", index);
     JNIEnv* env = getJNIEnv();
     WebHistory::RemoveItem(mJavaFrame->history(env), index);
 }
@@ -569,7 +703,10 @@
 void
 WebFrame::updateHistoryIndex(int newIndex)
 {
-    ALOGV("::WebCore:: updateHistoryIndex to %d", newIndex);
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
+    LOGV("::WebCore:: updateHistoryIndex to %d", newIndex);
     JNIEnv* env = getJNIEnv();
     WebHistory::UpdateHistoryIndex(mJavaFrame->history(env), newIndex);
 }
@@ -577,8 +714,11 @@
 void
 WebFrame::setTitle(const WTF::String& title)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
 #ifndef NDEBUG
-    ALOGV("setTitle(%s)", title.ascii().data());
+    LOGV("setTitle(%s)", title.ascii().data());
 #endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
@@ -595,7 +735,10 @@
 void
 WebFrame::windowObjectCleared(WebCore::Frame* frame)
 {
-    ALOGV("::WebCore:: windowObjectCleared");
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
+    LOGV("::WebCore:: windowObjectCleared");
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -608,6 +751,9 @@
 void
 WebFrame::setProgress(float newProgress)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -627,7 +773,10 @@
 void
 WebFrame::didReceiveIcon(WebCore::Image* icon)
 {
-    ALOG_ASSERT(icon, "DidReceiveIcon called without an image!");
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
+    LOG_ASSERT(icon, "DidReceiveIcon called without an image!");
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -645,6 +794,9 @@
 void
 WebFrame::didReceiveTouchIconURL(const WTF::String& url, bool precomposed)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -660,6 +812,9 @@
 void
 WebFrame::updateVisitedHistory(const WebCore::KURL& url, bool reload)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -676,6 +831,9 @@
 bool
 WebFrame::canHandleRequest(const WebCore::ResourceRequest& request)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -716,6 +874,9 @@
 WebCore::Frame*
 WebFrame::createWindow(bool dialog, bool userGesture)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -729,6 +890,9 @@
 void
 WebFrame::requestFocus() const
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -740,6 +904,9 @@
 void
 WebFrame::closeWindow(WebViewCore* webViewCore)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     assert(webViewCore);
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
@@ -758,6 +925,9 @@
 void
 WebFrame::decidePolicyForFormResubmission(WebCore::FramePolicyFunction func)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -791,9 +961,13 @@
     return dpi;
 }
 
+#if USE(CHROME_NETWORK_STACK)
 void
 WebFrame::didReceiveAuthenticationChallenge(WebUrlLoaderClient* client, const std::string& host, const std::string& realm, bool useCachedCredentials, bool suppressDialog)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -811,6 +985,9 @@
 void
 WebFrame::reportSslCertError(WebUrlLoaderClient* client, int error, const std::string& cert, const std::string& url)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -831,6 +1008,9 @@
 void
 WebFrame::requestClientCert(WebUrlLoaderClient* client, const std::string& hostAndPort)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     int jHandle = reinterpret_cast<int>(client);
 
@@ -844,6 +1024,9 @@
 void
 WebFrame::downloadStart(const std::string& url, const std::string& userAgent, const std::string& contentDisposition, const std::string& mimetype, long long contentLength)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -864,6 +1047,9 @@
 
 void
 WebFrame::didReceiveData(const char* data, int size) {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -878,6 +1064,9 @@
 
 void
 WebFrame::didFinishLoading() {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -889,6 +1078,9 @@
 
 void WebFrame::setCertificate(const std::string& cert)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -902,9 +1094,13 @@
 
     checkException(env);
 }
+#endif // USE(CHROME_NETWORK_STACK)
 
 void WebFrame::autoLogin(const std::string& loginHeader)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimerCoutner::JavaCallbackTimeCounter);
+#endif
     JNIEnv* env = getJNIEnv();
     AutoJObject javaFrame = mJavaFrame->frame(env);
     if (!javaFrame.get())
@@ -978,7 +1174,7 @@
 bool WebFrame::getUsernamePasswordFromDom(WebCore::Frame* frame, WTF::String& username, WTF::String& password)
 {
     bool found = false;
-    WTF::RefPtr<WebCore::HTMLCollection> form = frame->document()->forms();
+    WTF::PassRefPtr<WebCore::HTMLCollection> form = frame->document()->forms();
     WebCore::Node* node = form->firstItem();
     while (node && !found && !node->namespaceURI().isNull() &&
            !node->namespaceURI().isEmpty()) {
@@ -1075,10 +1271,13 @@
 
 static void CallPolicyFunction(JNIEnv* env, jobject obj, jint func, jint decision)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOG_ASSERT(pFrame, "nativeCallPolicyFunction must take a valid frame pointer!");
+    LOG_ASSERT(pFrame, "nativeCallPolicyFunction must take a valid frame pointer!");
     PolicyFunctionWrapper* pFunc = (PolicyFunctionWrapper*)func;
-    ALOG_ASSERT(pFunc, "nativeCallPolicyFunction must take a valid function pointer!");
+    LOG_ASSERT(pFunc, "nativeCallPolicyFunction must take a valid function pointer!");
 
     // If we are resending the form then we should reset the multiple submission protection.
     if (decision == WebCore::PolicyUse)
@@ -1091,9 +1290,17 @@
 {
     ScriptController::initializeThreading();
 
+#if USE(CHROME_NETWORK_STACK)
     // needs to be called before any other chromium code
     initChromium();
+#endif
 
+#ifdef ANDROID_INSTRUMENT
+#if USE(V8)
+    V8Counters::initCounters();
+#endif
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     // Create a new page
     ChromeClientAndroid* chromeC = new ChromeClientAndroid;
     EditorClientAndroid* editorC = new EditorClientAndroid;
@@ -1155,7 +1362,7 @@
     WebCore::SecurityOrigin::setLocalLoadPolicy(
             WebCore::SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData);
 
-    ALOGV("::WebCore:: createFrame %p", frame);
+    LOGV("::WebCore:: createFrame %p", frame);
 
     // Set the mNativeFrame field in Frame
     SET_NATIVE_FRAME(env, obj, (int)frame);
@@ -1163,7 +1370,7 @@
     String directory = webFrame->getRawResourceFilename(
             WebCore::PlatformBridge::DrawableDir);
     if (directory.isEmpty())
-        ALOGE("Can't find the drawable directory");
+        LOGE("Can't find the drawable directory");
     else {
         // Initialize our skinning classes
         webFrame->setRenderSkins(new WebCore::RenderSkinAndroid(directory));
@@ -1177,10 +1384,13 @@
 
 static void DestroyFrame(JNIEnv* env, jobject obj)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOG_ASSERT(pFrame, "nativeDestroyFrame must take a valid frame pointer!");
+    LOG_ASSERT(pFrame, "nativeDestroyFrame must take a valid frame pointer!");
 
-    ALOGV("::WebCore:: deleting frame %p", pFrame);
+    LOGV("::WebCore:: deleting frame %p", pFrame);
 
     WebCore::FrameView* view = pFrame->view();
     view->ref();
@@ -1205,8 +1415,11 @@
 
 static void LoadUrl(JNIEnv *env, jobject obj, jstring url, jobject headers)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOG_ASSERT(pFrame, "nativeLoadUrl must take a valid frame pointer!");
+    LOG_ASSERT(pFrame, "nativeLoadUrl must take a valid frame pointer!");
 
     WTF::String webcoreUrl = jstringToWtfString(env, url);
     WebCore::KURL kurl(WebCore::KURL(), webcoreUrl);
@@ -1250,14 +1463,17 @@
         env->DeleteLocalRef(set);
         env->DeleteLocalRef(mapClass);
     }
-    ALOGV("LoadUrl %s", kurl.string().latin1().data());
+    LOGV("LoadUrl %s", kurl.string().latin1().data());
     pFrame->loader()->load(request, false);
 }
 
 static void PostUrl(JNIEnv *env, jobject obj, jstring url, jbyteArray postData)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOG_ASSERT(pFrame, "nativePostUrl must take a valid frame pointer!");
+    LOG_ASSERT(pFrame, "nativePostUrl must take a valid frame pointer!");
 
     WebCore::KURL kurl(WebCore::KURL(), jstringToWtfString(env, url));
     WebCore::ResourceRequest request(kurl);
@@ -1275,7 +1491,7 @@
         env->ReleaseByteArrayElements(postData, bytes, 0);
     }
 
-    ALOGV("PostUrl %s", kurl.string().latin1().data());
+    LOGV("PostUrl %s", kurl.string().latin1().data());
     WebCore::FrameLoadRequest frameRequest(pFrame->document()->securityOrigin(), request);
     pFrame->loader()->loadFrameRequest(frameRequest, false, false, 0, 0, WebCore::SendReferrer);
 }
@@ -1283,19 +1499,22 @@
 static void LoadData(JNIEnv *env, jobject obj, jstring baseUrl, jstring data,
         jstring mimeType, jstring encoding, jstring failUrl)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOG_ASSERT(pFrame, "nativeLoadData must take a valid frame pointer!");
+    LOG_ASSERT(pFrame, "nativeLoadData must take a valid frame pointer!");
 
     // Setup the resource request
     WebCore::ResourceRequest request(jstringToWtfString(env, baseUrl));
 
     // Setup the substituteData
-    WTF::CString cData = jstringToWtfString(env, data).utf8();
-    const char* dataStr = cData.data();
-    WTF::RefPtr<WebCore::SharedBuffer> sharedBuffer =
+    const char* dataStr = env->GetStringUTFChars(data, NULL);
+    WTF::PassRefPtr<WebCore::SharedBuffer> sharedBuffer =
         WebCore::SharedBuffer::create();
-    ALOG_ASSERT(dataStr, "nativeLoadData has a null data string.");
-    sharedBuffer->append(dataStr, strlen(dataStr)); // copy dataStr
+    LOG_ASSERT(dataStr, "nativeLoadData has a null data string.");
+    sharedBuffer->append(dataStr, strlen(dataStr));
+    env->ReleaseStringUTFChars(data, dataStr);
 
     WebCore::SubstituteData substituteData(sharedBuffer,
             jstringToWtfString(env, mimeType), jstringToWtfString(env, encoding),
@@ -1307,9 +1526,12 @@
 
 static void StopLoading(JNIEnv *env, jobject obj)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOG_ASSERT(pFrame, "nativeStopLoading must take a valid frame pointer!");
-    ALOGV("::WebCore:: stopLoading %p", pFrame);
+    LOG_ASSERT(pFrame, "nativeStopLoading must take a valid frame pointer!");
+    LOGV("::WebCore:: stopLoading %p", pFrame);
 
     // Stop loading the page and do not send an unload event
     pFrame->loader()->stopForUserCancel();
@@ -1357,7 +1579,7 @@
 {
 #if ENABLE(WEB_ARCHIVE)
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOG_ASSERT(pFrame, "nativeSaveWebArchive must take a valid frame pointer!");
+    LOG_ASSERT(pFrame, "nativeSaveWebArchive must take a valid frame pointer!");
     String mimeType = pFrame->loader()->documentLoader()->mainResource()->mimeType();
     if ((mimeType != "text/html") && (mimeType != "application/xhtml+xml"))
         return NULL;
@@ -1375,7 +1597,7 @@
     }
 
     if (filename.isNull() || filename.isEmpty()) {
-        ALOGD("saveWebArchive: Failed to select a filename to save.");
+        LOGD("saveWebArchive: Failed to select a filename to save.");
         releaseCharactersForJStringInEnv(env, basename, basenameNative);
         return NULL;
     }
@@ -1383,7 +1605,7 @@
     const int noCompression = 0;
     xmlTextWriterPtr writer = xmlNewTextWriterFilename(filename.utf8().data(), noCompression);
     if (writer == NULL) {
-        ALOGD("saveWebArchive: Failed to initialize xml writer.");
+        LOGD("saveWebArchive: Failed to initialize xml writer.");
         releaseCharactersForJStringInEnv(env, basename, basenameNative);
         return NULL;
     }
@@ -1404,8 +1626,11 @@
 
 static jstring ExternalRepresentation(JNIEnv *env, jobject obj)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOG_ASSERT(pFrame, "android_webcore_nativeExternalRepresentation must take a valid frame pointer!");
+    LOG_ASSERT(pFrame, "android_webcore_nativeExternalRepresentation must take a valid frame pointer!");
 
     // Request external representation of the render tree
     WTF::String renderDump = WebCore::externalRepresentation(pFrame);
@@ -1436,8 +1661,11 @@
 
 static jstring DocumentAsText(JNIEnv *env, jobject obj)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOG_ASSERT(pFrame, "android_webcore_nativeDocumentAsText must take a valid frame pointer!");
+    LOG_ASSERT(pFrame, "android_webcore_nativeDocumentAsText must take a valid frame pointer!");
 
     WTF::String renderDump = FrameAsText(pFrame, false /* dumpChildFrames */).toString();
     return wtfStringToJstring(env, renderDump);
@@ -1445,8 +1673,11 @@
 
 static jstring ChildFramesAsText(JNIEnv *env, jobject obj)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOG_ASSERT(pFrame, "android_webcore_nativeDocumentAsText must take a valid frame pointer!");
+    LOG_ASSERT(pFrame, "android_webcore_nativeDocumentAsText must take a valid frame pointer!");
 
     StringBuilder renderDumpBuilder;
     for (unsigned i = 0; i < pFrame->tree()->childCount(); ++i) {
@@ -1458,8 +1689,11 @@
 
 static void Reload(JNIEnv *env, jobject obj, jboolean allowStale)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOG_ASSERT(pFrame, "nativeReload must take a valid frame pointer!");
+    LOG_ASSERT(pFrame, "nativeReload must take a valid frame pointer!");
 
     WebCore::FrameLoader* loader = pFrame->loader();
     if (allowStale) {
@@ -1475,8 +1709,11 @@
 
 static void GoBackOrForward(JNIEnv *env, jobject obj, jint pos)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOG_ASSERT(pFrame, "nativeGoBackOrForward must take a valid frame pointer!");
+    LOG_ASSERT(pFrame, "nativeGoBackOrForward must take a valid frame pointer!");
 
     if (pos == 1)
         pFrame->page()->goForward();
@@ -1488,8 +1725,11 @@
 
 static jobject StringByEvaluatingJavaScriptFromString(JNIEnv *env, jobject obj, jstring script)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOG_ASSERT(pFrame, "stringByEvaluatingJavaScriptFromString must take a valid frame pointer!");
+    LOG_ASSERT(pFrame, "stringByEvaluatingJavaScriptFromString must take a valid frame pointer!");
 
     WebCore::ScriptValue value =
             pFrame->script()->executeScript(jstringToWtfString(env, script), true);
@@ -1503,16 +1743,32 @@
 // Wrap the JavaInstance used when binding custom javascript interfaces. Use a
 // weak reference so that the gc can collect the WebView. Override virtualBegin
 // and virtualEnd and swap the weak reference for the real object.
+#if USE(JSC)
+class WeakJavaInstance : public JavaInstance {
+#elif USE(V8)
 class WeakJavaInstance : public JavaInstanceJobject {
+#endif
 public:
+#if USE(JSC)
+    static PassRefPtr<WeakJavaInstance> create(jobject obj, PassRefPtr<RootObject> root)
+    {
+        return adoptRef(new WeakJavaInstance(obj, root));
+    }
+#elif USE(V8)
     static PassRefPtr<WeakJavaInstance> create(jobject obj)
     {
         return adoptRef(new WeakJavaInstance(obj));
     }
+#endif
 
 private:
+#if USE(JSC)
+    WeakJavaInstance(jobject instance, PassRefPtr<RootObject> rootObject)
+        : JavaInstance(instance, rootObject)
+#elif USE(V8)
     WeakJavaInstance(jobject instance)
         : JavaInstanceJobject(instance)
+#endif
         , m_beginEndDepth(0)
     {
         JNIEnv* env = getJNIEnv();
@@ -1524,7 +1780,7 @@
     }
     ~WeakJavaInstance()
     {
-        ALOG_ASSERT(!m_beginEndDepth, "Unbalanced calls to WeakJavaInstance::begin() / end()");
+        LOG_ASSERT(!m_beginEndDepth, "Unbalanced calls to WeakJavaInstance::begin() / end()");
         JNIEnv* env = getJNIEnv();
         // The JavaInstance destructor attempts to delete the global ref stored
         // in m_instance. Since we replaced it in our constructor with a weak
@@ -1562,7 +1818,11 @@
     }
 
 private:
+#if USE(JSC)
+    typedef JavaInstance INHERITED;
+#elif USE(V8)
     typedef JavaInstanceJobject INHERITED;
+#endif
     jweak m_weakRef;
     // The current depth of nested calls to virtualBegin and virtualEnd.
     int m_beginEndDepth;
@@ -1571,17 +1831,42 @@
 static void AddJavascriptInterface(JNIEnv *env, jobject obj, jint nativeFramePointer,
         jobject javascriptObj, jstring interfaceName)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = 0;
     if (nativeFramePointer == 0)
         pFrame = GET_NATIVE_FRAME(env, obj);
     else
         pFrame = (WebCore::Frame*)nativeFramePointer;
-    ALOG_ASSERT(pFrame, "nativeAddJavascriptInterface must take a valid frame pointer!");
+    LOG_ASSERT(pFrame, "nativeAddJavascriptInterface must take a valid frame pointer!");
 
     JavaVM* vm;
     env->GetJavaVM(&vm);
-    ALOGV("::WebCore:: addJSInterface: %p", pFrame);
+    LOGV("::WebCore:: addJSInterface: %p", pFrame);
 
+#if USE(JSC)
+    // Copied from qwebframe.cpp
+    JSC::JSLock lock(JSC::SilenceAssertionsOnly);
+    WebCore::JSDOMWindow *window = WebCore::toJSDOMWindow(pFrame, mainThreadNormalWorld());
+    if (window) {
+        RootObject *root = pFrame->script()->bindingRootObject();
+        setJavaVM(vm);
+        // Add the binding to JS environment
+        JSC::ExecState* exec = window->globalExec();
+        JSC::JSObject* addedObject = WeakJavaInstance::create(javascriptObj,
+                root)->createRuntimeObject(exec);
+        const jchar* s = env->GetStringChars(interfaceName, NULL);
+        if (s) {
+            // Add the binding name to the window's table of child objects.
+            JSC::PutPropertySlot slot;
+            window->put(exec, JSC::Identifier(exec, (const UChar *)s,
+                    env->GetStringLength(interfaceName)), addedObject, slot);
+            env->ReleaseStringChars(interfaceName, s);
+            checkException(env);
+        }
+    }
+#elif USE(V8)
     if (pFrame) {
         RefPtr<JavaInstance> addedObject = WeakJavaInstance::create(javascriptObj);
         const char* name = getCharactersFromJStringInEnv(env, interfaceName);
@@ -1602,6 +1887,24 @@
         NPN_ReleaseObject(npObject);
         releaseCharactersForJString(interfaceName, name);
     }
+#endif
+
+}
+
+static void SetCacheDisabled(JNIEnv *env, jobject obj, jboolean disabled)
+{
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
+    WebCore::memoryCache()->setDisabled(disabled);
+}
+
+static jboolean CacheDisabled(JNIEnv *env, jobject obj)
+{
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
+    return WebCore::memoryCache()->disabled();
 }
 
 static void ClearWebCoreCache()
@@ -1623,32 +1926,59 @@
 
 static void ClearWebViewCache()
 {
+#if USE(CHROME_NETWORK_STACK)
     WebCache::get(false /*privateBrowsing*/)->clear();
+#else
+    // The Android network stack provides a WebView cache in CacheManager.java.
+    // Clearing this is handled entirely Java-side.
+#endif
 }
 
 static void ClearCache(JNIEnv *env, jobject obj)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#if USE(JSC)
+    JSC::JSLock lock(false);
+    JSC::Heap::Statistics jsHeapStatistics = WebCore::JSDOMWindow::commonJSGlobalData()->heap.statistics();
+    LOGD("About to gc and JavaScript heap size is %d and has %d bytes free",
+            jsHeapStatistics.size, jsHeapStatistics.free);
+#endif  // USE(JSC)
+    LOGD("About to clear cache and current cache has %d bytes live and %d bytes dead",
+            memoryCache()->getLiveSize(), memoryCache()->getDeadSize());
+#endif  // ANDROID_INSTRUMENT
     ClearWebCoreCache();
     ClearWebViewCache();
+#if USE(JSC)
+    // force JavaScript to GC when clear cache
+    WebCore::gcController().garbageCollectSoon();
+#elif USE(V8)
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
     pFrame->script()->lowMemoryNotification();
+#endif  // USE(JSC)
 }
 
 static jboolean DocumentHasImages(JNIEnv *env, jobject obj)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOG_ASSERT(pFrame, "DocumentHasImages must take a valid frame pointer!");
+    LOG_ASSERT(pFrame, "DocumentHasImages must take a valid frame pointer!");
 
     return pFrame->document()->images()->length() > 0;
 }
 
 static jboolean HasPasswordField(JNIEnv *env, jobject obj)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOG_ASSERT(pFrame, "HasPasswordField must take a valid frame pointer!");
+    LOG_ASSERT(pFrame, "HasPasswordField must take a valid frame pointer!");
 
     bool found = false;
-    WTF::RefPtr<WebCore::HTMLCollection> form = pFrame->document()->forms();
+    WTF::PassRefPtr<WebCore::HTMLCollection> form = pFrame->document()->forms();
     WebCore::Node* node = form->firstItem();
     // Null/Empty namespace means that node is not created in HTMLFormElement
     // class, but just normal Element class.
@@ -1671,8 +2001,11 @@
 
 static jobjectArray GetUsernamePassword(JNIEnv *env, jobject obj)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOG_ASSERT(pFrame, "GetUsernamePassword must take a valid frame pointer!");
+    LOG_ASSERT(pFrame, "GetUsernamePassword must take a valid frame pointer!");
     jobjectArray strArray = NULL;
     WTF::String username;
     WTF::String password;
@@ -1689,13 +2022,16 @@
 static void SetUsernamePassword(JNIEnv *env, jobject obj,
     jstring username, jstring password)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOG_ASSERT(pFrame, "SetUsernamePassword must take a valid frame pointer!");
+    LOG_ASSERT(pFrame, "SetUsernamePassword must take a valid frame pointer!");
 
     WebCore::HTMLInputElement* usernameEle = NULL;
     WebCore::HTMLInputElement* passwordEle = NULL;
     bool found = false;
-    WTF::RefPtr<WebCore::HTMLCollection> form = pFrame->document()->forms();
+    WTF::PassRefPtr<WebCore::HTMLCollection> form = pFrame->document()->forms();
     WebCore::Node* node = form->firstItem();
     while (node && !found && !node->namespaceURI().isNull() &&
            !node->namespaceURI().isEmpty()) {
@@ -1735,14 +2071,14 @@
     if (form->autoComplete()) {
         JNIEnv* env = getJNIEnv();
         jclass mapClass = env->FindClass("java/util/HashMap");
-        ALOG_ASSERT(mapClass, "Could not find HashMap class!");
+        LOG_ASSERT(mapClass, "Could not find HashMap class!");
         jmethodID init = env->GetMethodID(mapClass, "<init>", "(I)V");
-        ALOG_ASSERT(init, "Could not find constructor for HashMap");
+        LOG_ASSERT(init, "Could not find constructor for HashMap");
         jobject hashMap = env->NewObject(mapClass, init, 1);
-        ALOG_ASSERT(hashMap, "Could not create a new HashMap");
+        LOG_ASSERT(hashMap, "Could not create a new HashMap");
         jmethodID put = env->GetMethodID(mapClass, "put",
                 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
-        ALOG_ASSERT(put, "Could not find put method on HashMap");
+        LOG_ASSERT(put, "Could not find put method on HashMap");
         WTF::Vector<WebCore::FormAssociatedElement*> elements = form->associatedElements();
         size_t size = elements.size();
         for (size_t i = 0; i < size; i++) {
@@ -1757,7 +2093,7 @@
                         const WTF::AtomicString& name = input->name();
                         jstring key = wtfStringToJstring(env, name);
                         jstring val = wtfStringToJstring(env, value);
-                        ALOG_ASSERT(key && val, "name or value not set");
+                        LOG_ASSERT(key && val, "name or value not set");
                         env->CallObjectMethod(hashMap, put, key, val);
                         env->DeleteLocalRef(key);
                         env->DeleteLocalRef(val);
@@ -1773,8 +2109,11 @@
 
 static void OrientationChanged(JNIEnv *env, jobject obj, int orientation)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
+#endif
     WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    ALOGV("Sending orientation: %d", orientation);
+    LOGV("Sending orientation: %d", orientation);
     pFrame->sendOrientationChangeEvent(orientation);
 }
 
@@ -1787,9 +2126,8 @@
     if (document) {
         RenderStyle* style = document->renderer()->style();
         WritingMode writingMode = style->writingMode();
-        ALOG_ASSERT(writingMode != WebCore::BottomToTopWritingMode,
-                "BottomToTopWritingMode isn't possible in any "
-                "language and cannot be specified in w3c writing-mode.");
+        LOG_ASSERT(writingMode != WebCore::BottomToTopWritingMode,
+                "BottomToTopWritingMode isn't supported");
         if (writingMode == WebCore::RightToLeftWritingMode)
             startScrolledRight = true; // vertical-rl pages start scrolled right
         else if (writingMode == WebCore::TopToBottomWritingMode)
@@ -1798,6 +2136,8 @@
     return startScrolledRight;
 }
 
+#if USE(CHROME_NETWORK_STACK)
+
 static void AuthenticationProceed(JNIEnv *env, jobject obj, int handle, jstring jUsername, jstring jPassword)
 {
     WebUrlLoaderClient* client = reinterpret_cast<WebUrlLoaderClient*>(handle);
@@ -1824,49 +2164,7 @@
     client->cancelSslCertError(cert_error);
 }
 
-static scoped_refptr<net::X509Certificate> getX509Cert(JNIEnv *env, jobjectArray chain)
-{
-    // Based on Android's NativeCrypto_SSL_use_certificate
-    int length = env->GetArrayLength(chain);
-    if (length == 0) {
-        return NULL;
-    }
-
-    base::ScopedOpenSSL<X509, X509_free> first;
-    ScopedVector<base::ScopedOpenSSL<X509, X509_free> > rest;
-    for (int i = 0; i < length; i++) {
-        ScopedLocalRef<jbyteArray> cert(env,
-                reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(chain, i)));
-        if (cert.get() == NULL) {
-            return NULL;
-        }
-        ScopedByteArrayRO certBytes(env, cert.get());
-        if (certBytes.get() == NULL) {
-            return NULL;
-        }
-        const char* data = reinterpret_cast<const char*>(certBytes.get());
-        int length = certBytes.size();
-        X509* x509 = net::X509Certificate::CreateOSCertHandleFromBytes(data, length);
-        if (x509 == NULL) {
-            return NULL;
-        }
-        if (i == 0) {
-            first.reset(x509);
-        } else {
-            rest.push_back(new base::ScopedOpenSSL<X509, X509_free>(x509));
-        }
-    }
-
-    std::vector<X509*> certChain(rest.size());
-    for (size_t i = 0; i < rest.size(); i++) {
-        certChain[i] = rest[i]->get();
-    }
-    return net::X509Certificate::CreateFromHandle(first.get(),
-                                                  net::X509Certificate::SOURCE_FROM_NETWORK,
-                                                  certChain);
-}
-
-static void SslClientCertPKCS8(JNIEnv *env, jobject obj, int handle, jbyteArray pkey, jobjectArray chain)
+static void SslClientCert(JNIEnv *env, jobject obj, int handle, jbyteArray pkey, jobjectArray chain)
 {
     WebUrlLoaderClient* client = reinterpret_cast<WebUrlLoaderClient*>(handle);
     if (pkey == NULL || chain == NULL) {
@@ -1893,7 +2191,50 @@
         client->sslClientCert(NULL, NULL);
         return;
     }
-    scoped_refptr<net::X509Certificate> certificate = getX509Cert(env, chain);
+
+    // Based on Android's NativeCrypto_SSL_use_certificate
+    int length = env->GetArrayLength(chain);
+    if (length == 0) {
+        client->sslClientCert(NULL, NULL);
+        return;
+    }
+
+    base::ScopedOpenSSL<X509, X509_free> first;
+    ScopedVector<base::ScopedOpenSSL<X509, X509_free> > rest;
+    for (int i = 0; i < length; i++) {
+        ScopedLocalRef<jbyteArray> cert(env,
+                reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(chain, i)));
+        if (cert.get() == NULL) {
+            client->sslClientCert(NULL, NULL);
+            return;
+        }
+        ScopedByteArrayRO certBytes(env, cert.get());
+        if (certBytes.get() == NULL) {
+            client->sslClientCert(NULL, NULL);
+            return;
+        }
+        const char* data = reinterpret_cast<const char*>(certBytes.get());
+        int length = certBytes.size();
+        X509* x509 = net::X509Certificate::CreateOSCertHandleFromBytes(data, length);
+        if (x509 == NULL) {
+            client->sslClientCert(NULL, NULL);
+            return;
+        }
+        if (i == 0) {
+            first.reset(x509);
+        } else {
+            rest.push_back(new base::ScopedOpenSSL<X509, X509_free>(x509));
+        }
+    }
+
+    std::vector<X509*> certChain(rest.size());
+    for (size_t i = 0; i < rest.size(); i++) {
+        certChain[i] = rest[i]->get();
+    }
+    net::X509Certificate* certificate
+            = net::X509Certificate::CreateFromHandle(first.get(),
+                                                     net::X509Certificate::SOURCE_FROM_NETWORK,
+                                                     certChain);
     if (certificate == NULL) {
         client->sslClientCert(NULL, NULL);
         return;
@@ -1901,23 +2242,34 @@
     client->sslClientCert(privateKey.release(), certificate);
 }
 
-static void SslClientCertCtx(JNIEnv *env, jobject obj, int handle, jint ctx, jobjectArray chain)
+#else
+
+static void AuthenticationProceed(JNIEnv *env, jobject obj, int handle, jstring jUsername, jstring jPassword)
 {
-    WebUrlLoaderClient* client = reinterpret_cast<WebUrlLoaderClient*>(handle);
-    EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(static_cast<uintptr_t>(ctx));
-    if (pkey == NULL || chain == NULL) {
-        client->sslClientCert(NULL, NULL);
-        return;
-    }
-    scoped_refptr<net::X509Certificate> certificate = getX509Cert(env, chain);
-    if (certificate == NULL) {
-        client->sslClientCert(NULL, NULL);
-        return;
-    }
-    CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
-    client->sslClientCert(pkey, certificate);
+    LOGW("Chromium authentication API called, but libchromium is not available");
 }
 
+static void AuthenticationCancel(JNIEnv *env, jobject obj, int handle)
+{
+    LOGW("Chromium authentication API called, but libchromium is not available");
+}
+
+static void SslCertErrorProceed(JNIEnv *env, jobject obj, int handle)
+{
+    LOGW("Chromium SSL API called, but libchromium is not available");
+}
+
+static void SslCertErrorCancel(JNIEnv *env, jobject obj, int handle, int cert_error)
+{
+    LOGW("Chromium SSL API called, but libchromium is not available");
+}
+
+static void SslClientCert(JNIEnv *env, jobject obj, int handle, jbyteArray privateKey, jobjectArray chain)
+{
+    LOGW("Chromium SSL API called, but libchromium is not available");
+}
+#endif // USE(CHROME_NETWORK_STACK)
+
 // ----------------------------------------------------------------------------
 
 /*
@@ -1956,6 +2308,10 @@
     { "stringByEvaluatingJavaScriptFromString",
             "(Ljava/lang/String;)Ljava/lang/String;",
         (void*) StringByEvaluatingJavaScriptFromString },
+    { "setCacheDisabled", "(Z)V",
+        (void*) SetCacheDisabled },
+    { "cacheDisabled", "()Z",
+        (void*) CacheDisabled },
     { "clearCache", "()V",
         (void*) ClearCache },
     { "documentHasImages", "()Z",
@@ -1976,10 +2332,8 @@
         (void*) SslCertErrorProceed },
     { "nativeSslCertErrorCancel", "(II)V",
         (void*) SslCertErrorCancel },
-    { "nativeSslClientCert", "(II[[B)V",
-        (void*) SslClientCertCtx },
     { "nativeSslClientCert", "(I[B[[B)V",
-        (void*) SslClientCertPKCS8 },
+        (void*) SslClientCert },
     { "nativeGetShouldStartScrolledRight", "(I)Z",
         (void*) GetShouldStartScrolledRight },
 };
@@ -1987,9 +2341,9 @@
 int registerWebFrame(JNIEnv* env)
 {
     jclass clazz = env->FindClass("android/webkit/BrowserFrame");
-    ALOG_ASSERT(clazz, "Cannot find BrowserFrame");
+    LOG_ASSERT(clazz, "Cannot find BrowserFrame");
     gFrameField = env->GetFieldID(clazz, "mNativeFrame", "I");
-    ALOG_ASSERT(gFrameField, "Cannot find mNativeFrame on BrowserFrame");
+    LOG_ASSERT(gFrameField, "Cannot find mNativeFrame on BrowserFrame");
     env->DeleteLocalRef(clazz);
 
     return jniRegisterNativeMethods(env, "android/webkit/BrowserFrame",
diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.h b/Source/WebKit/android/jni/WebCoreFrameBridge.h
index 30c1d83..eaee63c 100644
--- a/Source/WebKit/android/jni/WebCoreFrameBridge.h
+++ b/Source/WebKit/android/jni/WebCoreFrameBridge.h
@@ -64,6 +64,10 @@
     // helper function
     static WebFrame* getWebFrame(const WebCore::Frame* frame);
 
+    virtual PassRefPtr<WebCore::ResourceLoaderAndroid> startLoadingResource(WebCore::ResourceHandle*,
+            const WebCore::ResourceRequest& request, bool mainResource,
+            bool synchronous);
+
     UrlInterceptResponse* shouldInterceptRequest(const WTF::String& url);
 
     void reportError(int errorCode, const WTF::String& description,
@@ -113,6 +117,7 @@
 
     float density() const;
 
+#if USE(CHROME_NETWORK_STACK)
     void didReceiveAuthenticationChallenge(WebUrlLoaderClient*, const std::string& host, const std::string& realm, bool useCachedCredentials, bool suppressDialog);
     void reportSslCertError(WebUrlLoaderClient* client, int cert_error, const std::string& cert, const std::string& url);
     void requestClientCert(WebUrlLoaderClient* client, const std::string& hostAndPort);
@@ -120,6 +125,7 @@
     void didReceiveData(const char* data, int size);
     void didFinishLoading();
     void setCertificate(const std::string& cert);
+#endif
 
     void maybeSavePassword(WebCore::Frame* frame, const WebCore::ResourceRequest& request);
 
@@ -128,6 +134,13 @@
     // application.
     void autoLogin(const std::string& loginHeader);
 
+    /**
+     * When the user initiates a click, we set mUserInitiatedAction to true.
+     * If a load happens due to this click, then we ask the application if it wants
+     * to override the load. Otherwise, we attempt to load the resource internally.
+     */
+    void setUserInitiatedAction(bool userInitiatedAction) { mUserInitiatedAction = userInitiatedAction; }
+
     WebCore::Page* page() const { return mPage; }
 
     // Currently used only by the chrome net stack.  A similar field is used by
@@ -156,6 +169,7 @@
     WebCore::Page* mPage;
     WTF::String mUserAgent;
     bool mBlockNetworkLoads;
+    bool mUserInitiatedAction;
     WebCore::RenderSkinAndroid* m_renderSkins;
 };
 
diff --git a/Source/WebKit/android/jni/WebCoreJni.cpp b/Source/WebKit/android/jni/WebCoreJni.cpp
index 72ded59..2a07999 100644
--- a/Source/WebKit/android/jni/WebCoreJni.cpp
+++ b/Source/WebKit/android/jni/WebCoreJni.cpp
@@ -26,9 +26,7 @@
 #define LOG_TAG "webcoreglue"
 
 #include "config.h"
-#include "IntRect.h"
 #include "WebCoreJni.h"
-#include "wtf/Vector.h"
 
 #include "NotImplemented.h"
 #include <JNIUtility.h>
@@ -40,7 +38,7 @@
 AutoJObject getRealObject(JNIEnv* env, jobject obj)
 {
     jobject real = env->NewLocalRef(obj);
-    ALOG_ASSERT(real, "The real object has been deleted!");
+    LOG_ASSERT(real, "The real object has been deleted!");
     return AutoJObject(env, real);
 }
 
@@ -52,7 +50,7 @@
 {
     if (env->ExceptionCheck() != 0)
     {
-        ALOGE("*** Uncaught exception returned from Java call!\n");
+        LOGE("*** Uncaught exception returned from Java call!\n");
         env->ExceptionDescribe();
         return true;
     }
@@ -79,6 +77,8 @@
     return length || validOnZeroLength ? env->NewString(str.characters(), length) : 0;
 }
 
+
+#if USE(CHROME_NETWORK_STACK)
 string16 jstringToString16(JNIEnv* env, jstring jstr)
 {
     if (!jstr || !env)
@@ -112,37 +112,6 @@
     return !str.empty() || validOnZeroLength ? env->NewStringUTF(str.c_str()) : 0;
 }
 
-jobject intRectToRect(JNIEnv* env, const WebCore::IntRect& rect)
-{
-    jclass rectClass = env->FindClass("android/graphics/Rect");
-    ALOG_ASSERT(rectClass, "Could not find android/graphics/Rect");
-    jmethodID rectInit = env->GetMethodID(rectClass, "<init>", "(IIII)V");
-    ALOG_ASSERT(rectInit, "Could not find init method on Rect");
-    jobject jrect = env->NewObject(rectClass, rectInit, rect.x(), rect.y(),
-            rect.maxX(), rect.maxY());
-    env->DeleteLocalRef(rectClass);
-    return jrect;
-}
-
-jobjectArray intRectVectorToRectArray(JNIEnv* env, Vector<WebCore::IntRect>& rects)
-{
-    jclass rectClass = env->FindClass("android/graphics/Rect");
-    ALOG_ASSERT(rectClass, "Could not find android/graphics/Rect");
-    jmethodID rectInit = env->GetMethodID(rectClass, "<init>", "(IIII)V");
-    ALOG_ASSERT(rectInit, "Could not find init method on Rect");
-    jobjectArray array = env->NewObjectArray(rects.size(), rectClass, 0);
-    ALOG_ASSERT(array, "Could not create a Rect array");
-    for (size_t i = 0; i < rects.size(); i++) {
-        jobject rect = env->NewObject(rectClass, rectInit,
-                rects[i].x(), rects[i].y(),
-                rects[i].maxX(), rects[i].maxY());
-        if (rect) {
-            env->SetObjectArrayElement(array, i, rect);
-            env->DeleteLocalRef(rect);
-        }
-    }
-    env->DeleteLocalRef(rectClass);
-    return array;
-}
+#endif
 
 }
diff --git a/Source/WebKit/android/jni/WebCoreJni.h b/Source/WebKit/android/jni/WebCoreJni.h
index e8cc6ea..0f77cc6 100644
--- a/Source/WebKit/android/jni/WebCoreJni.h
+++ b/Source/WebKit/android/jni/WebCoreJni.h
@@ -27,7 +27,6 @@
 #define WebCoreJni_h
 
 #include "ChromiumIncludes.h"
-#include "IntRect.h"
 #include "PlatformString.h"
 #include <jni.h>
 
@@ -82,6 +81,7 @@
 // an empty WTF String returns 0.
 jstring wtfStringToJstring(JNIEnv*, const WTF::String&, bool validOnZeroLength = false);
 
+#if USE(CHROME_NETWORK_STACK)
 string16 jstringToString16(JNIEnv*, jstring);
 
 std::string jstringToStdString(JNIEnv*, jstring);
@@ -89,10 +89,8 @@
 // passing in an empty std::string will result in an empty jstring. Otherwise
 // an empty std::string returns 0.
 jstring stdStringToJstring(JNIEnv*, const std::string&, bool validOnZeroLength = false);
+#endif
 
-jobjectArray intRectVectorToRectArray(JNIEnv*, Vector<WebCore::IntRect>&);
-
-jobject intRectToRect(JNIEnv* env, const WebCore::IntRect& rect);
 }
 
 #endif
diff --git a/Source/WebKit/android/jni/WebCoreJniOnLoad.cpp b/Source/WebKit/android/jni/WebCoreJniOnLoad.cpp
index ec052f1..bb71bf5 100644
--- a/Source/WebKit/android/jni/WebCoreJniOnLoad.cpp
+++ b/Source/WebKit/android/jni/WebCoreJniOnLoad.cpp
@@ -62,6 +62,8 @@
 #include "WebCoreViewBridge.h"
 #include "WebFrameView.h"
 #include "WebViewCore.h"
+#include "benchmark/Intercept.h"
+#include "benchmark/MyJavaVM.h"
 
 #include <JNIUtility.h>
 #include <jni.h>
@@ -73,6 +75,7 @@
 
 extern int registerWebFrame(JNIEnv*);
 extern int registerJavaBridge(JNIEnv*);
+extern int registerJniUtil(JNIEnv*);
 extern int registerResourceLoader(JNIEnv*);
 extern int registerWebViewCore(JNIEnv*);
 extern int registerWebHistory(JNIEnv*);
@@ -91,7 +94,9 @@
 #endif
 extern int registerDeviceMotionAndOrientationManager(JNIEnv*);
 extern int registerCookieManager(JNIEnv*);
+#if USE(CHROME_NETWORK_STACK)
 extern int registerCacheManager(JNIEnv*);
+#endif
 
 }
 
@@ -102,11 +107,13 @@
 
 static RegistrationMethod gWebCoreRegMethods[] = {
     { "JavaBridge", android::registerJavaBridge },
+    { "JniUtil", android::registerJniUtil },
     { "WebFrame", android::registerWebFrame },
+    { "WebCoreResourceLoader", android::registerResourceLoader },
     { "WebViewCore", android::registerWebViewCore },
     { "WebHistory", android::registerWebHistory },
     { "WebIconDatabase", android::registerWebIconDatabase },
-    { "WebSettingsClassic", android::registerWebSettings },
+    { "WebSettings", android::registerWebSettings },
 #if ENABLE(DATABASE)
     { "WebStorage", android::registerWebStorage },
 #endif
@@ -120,7 +127,9 @@
 #endif
     { "DeviceMotionAndOrientationManager", android::registerDeviceMotionAndOrientationManager },
     { "CookieManager", android::registerCookieManager },
+#if USE(CHROME_NETWORK_STACK)
     { "CacheManager", android::registerCacheManager },
+#endif
 };
 
 EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
@@ -132,16 +141,16 @@
     jint result = -1;
 
     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
-        ALOGE("GetEnv failed!");
+        LOGE("GetEnv failed!");
         return result;
     }
-    ALOG_ASSERT(env, "Could not retrieve the env!");
+    LOG_ASSERT(env, "Could not retrieve the env!");
 
     const RegistrationMethod* method = gWebCoreRegMethods;
     const RegistrationMethod* end = method + sizeof(gWebCoreRegMethods)/sizeof(RegistrationMethod);
     while (method != end) {
         if (method->func(env) < 0) {
-            ALOGE("%s registration failed!", method->name);
+            LOGE("%s registration failed!", method->name);
             return result;
         }
         method++;
@@ -153,3 +162,160 @@
 
     return JNI_VERSION_1_4;
 }
+
+class MyJavaSharedClient : public TimerClient, public CookieClient {
+public:
+    MyJavaSharedClient() : m_hasTimer(false) {}
+    virtual void setSharedTimer(long long timemillis) { m_hasTimer = true; }
+    virtual void stopSharedTimer() { m_hasTimer = false; }
+    virtual void setSharedTimerCallback(void (*f)()) { m_func = f; }
+    virtual void signalServiceFuncPtrQueue() {}
+
+    // Cookie methods that do nothing.
+    virtual void setCookies(const KURL&, const String&) {}
+    virtual String cookies(const KURL&) { return ""; }
+    virtual bool cookiesEnabled() { return false; }
+
+    bool m_hasTimer;
+    void (*m_func)();
+};
+
+static void historyItemChanged(HistoryItem* i) {
+    if (i->bridge())
+        i->bridge()->updateHistoryItem(i);
+}
+
+namespace android {
+
+EXPORT void benchmark(const char* url, int reloadCount, int width, int height) {
+    ScriptController::initializeThreading();
+
+    // Setting this allows data: urls to load from a local file.
+    SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForAll);
+
+    // Create the fake JNIEnv and JavaVM
+    InitializeJavaVM();
+
+    // The real function is private to libwebcore but we know what it does.
+    notifyHistoryItemChanged = historyItemChanged;
+
+    // Implement the shared timer callback
+    MyJavaSharedClient client;
+    JavaSharedClient::SetTimerClient(&client);
+    JavaSharedClient::SetCookieClient(&client);
+
+    // Create the page with all the various clients
+    ChromeClientAndroid* chrome = new ChromeClientAndroid;
+    EditorClientAndroid* editor = new EditorClientAndroid;
+    DeviceMotionClientAndroid* deviceMotion = new DeviceMotionClientAndroid;
+    DeviceOrientationClientAndroid* deviceOrientation = new DeviceOrientationClientAndroid;
+    WebCore::Page::PageClients pageClients;
+    pageClients.chromeClient = chrome;
+    pageClients.contextMenuClient = new ContextMenuClientAndroid;
+    pageClients.editorClient = editor;
+    pageClients.dragClient = new DragClientAndroid;
+    pageClients.inspectorClient = new InspectorClientAndroid;
+    pageClients.deviceMotionClient = deviceMotion;
+    pageClients.deviceOrientationClient = deviceOrientation;
+    WebCore::Page* page = new WebCore::Page(pageClients);
+    editor->setPage(page);
+
+    // Create MyWebFrame that intercepts network requests
+    MyWebFrame* webFrame = new MyWebFrame(page);
+    webFrame->setUserAgent("Performance testing"); // needs to be non-empty
+    chrome->setWebFrame(webFrame);
+    // ChromeClientAndroid maintains the reference.
+    Release(webFrame);
+
+    // Create the Frame and the FrameLoaderClient
+    FrameLoaderClientAndroid* loader = new FrameLoaderClientAndroid(webFrame);
+    RefPtr<Frame> frame = Frame::create(page, NULL, loader);
+    loader->setFrame(frame.get());
+
+    // Build our View system, resize it to the given dimensions and release our
+    // references. Note: We keep a referenec to frameView so we can layout and
+    // draw later without risk of it being deleted.
+    WebViewCore* webViewCore = new WebViewCore(JSC::Bindings::getJNIEnv(),
+            MY_JOBJECT, frame.get());
+    RefPtr<FrameView> frameView = FrameView::create(frame.get());
+    WebFrameView* webFrameView = new WebFrameView(frameView.get(), webViewCore);
+    frame->setView(frameView);
+    frameView->resize(width, height);
+    Release(webViewCore);
+    Release(webFrameView);
+
+    // Initialize the frame and turn of low-bandwidth display (it fails an
+    // assertion in the Cache code)
+    frame->init();
+    frame->selection()->setFocused(true);
+    frame->page()->focusController()->setFocused(true);
+
+    deviceMotion->setWebViewCore(webViewCore);
+    deviceOrientation->setWebViewCore(webViewCore);
+
+    // Set all the default settings the Browser normally uses.
+    Settings* s = frame->settings();
+#ifdef ANDROID_LAYOUT
+    s->setLayoutAlgorithm(Settings::kLayoutNormal); // Normal layout for now
+#endif
+    s->setStandardFontFamily("sans-serif");
+    s->setFixedFontFamily("monospace");
+    s->setSansSerifFontFamily("sans-serif");
+    s->setSerifFontFamily("serif");
+    s->setCursiveFontFamily("cursive");
+    s->setFantasyFontFamily("fantasy");
+    s->setMinimumFontSize(8);
+    s->setMinimumLogicalFontSize(8);
+    s->setDefaultFontSize(16);
+    s->setDefaultFixedFontSize(13);
+    s->setLoadsImagesAutomatically(true);
+    s->setJavaScriptEnabled(true);
+    s->setDefaultTextEncodingName("latin1");
+    s->setPluginsEnabled(false);
+    s->setShrinksStandaloneImagesToFit(false);
+#ifdef ANDROID_LAYOUT
+    s->setUseWideViewport(false);
+#endif
+
+    // Finally, load the actual data
+    ResourceRequest req(url);
+    frame->loader()->load(req, false);
+
+    do {
+        // Layout the page and service the timer
+        frame->view()->layout();
+        while (client.m_hasTimer) {
+            client.m_func();
+            JavaSharedClient::ServiceFunctionPtrQueue();
+        }
+        JavaSharedClient::ServiceFunctionPtrQueue();
+
+        // Layout more if needed.
+        while (frame->view()->needsLayout())
+            frame->view()->layout();
+        JavaSharedClient::ServiceFunctionPtrQueue();
+
+        if (reloadCount)
+            frame->loader()->reload(true);
+    } while (reloadCount--);
+
+    // Draw into an offscreen bitmap
+    SkBitmap bmp;
+    bmp.setConfig(SkBitmap::kARGB_8888_Config, width, height);
+    bmp.allocPixels();
+    SkCanvas canvas(bmp);
+    PlatformGraphicsContext ctx(&canvas);
+    GraphicsContext gc(&ctx);
+    frame->view()->paintContents(&gc, IntRect(0, 0, width, height));
+
+    // Write the bitmap to the sdcard
+    SkImageEncoder* enc = SkImageEncoder::Create(SkImageEncoder::kPNG_Type);
+    enc->encodeFile("/sdcard/webcore_test.png", bmp, 100);
+    delete enc;
+
+    // Tear down the world.
+    frame->loader()->detachFromParent();
+    delete page;
+}
+
+}  // namespace android
diff --git a/Source/WebKit/android/jni/WebCoreResourceLoader.cpp b/Source/WebKit/android/jni/WebCoreResourceLoader.cpp
new file mode 100644
index 0000000..f9acc97
--- /dev/null
+++ b/Source/WebKit/android/jni/WebCoreResourceLoader.cpp
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2006, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "webcoreglue"
+
+#include "config.h"
+#include "WebCoreResourceLoader.h"
+
+#include "ResourceError.h"
+#include "ResourceHandle.h"
+#include "ResourceHandleClient.h"
+#include "ResourceHandleInternal.h"
+#include "ResourceResponse.h"
+#include "SkUtils.h"
+#ifdef ANDROID_INSTRUMENT
+#include "TimeCounter.h"
+#endif
+#include "WebCoreJni.h"
+
+#include <JNIHelp.h>
+#include <JNIUtility.h>
+#include <SkTypes.h>
+#include <stdlib.h>
+#include <utils/misc.h>
+#include <wtf/Platform.h>
+#include <wtf/text/CString.h>
+
+namespace android {
+  
+// ----------------------------------------------------------------------------
+
+static struct resourceloader_t {
+    jfieldID    mObject;
+    jmethodID   mCancelMethodID;
+    jmethodID   mDownloadFileMethodID;
+    jmethodID   mWillLoadFromCacheMethodID;
+    jmethodID   mPauseLoadMethodID;
+} gResourceLoader;
+
+// ----------------------------------------------------------------------------
+
+#define GET_NATIVE_HANDLE(env, obj) ((WebCore::ResourceHandle*)env->GetIntField(obj, gResourceLoader.mObject))
+#define SET_NATIVE_HANDLE(env, obj, handle) (env->SetIntField(obj, gResourceLoader.mObject, handle))
+
+//-----------------------------------------------------------------------------
+// ResourceLoadHandler
+
+PassRefPtr<WebCore::ResourceLoaderAndroid> WebCoreResourceLoader::create(JNIEnv *env, jobject jLoadListener)
+{
+    return adoptRef<WebCore::ResourceLoaderAndroid>(new WebCoreResourceLoader(env, jLoadListener));
+}
+
+WebCoreResourceLoader::WebCoreResourceLoader(JNIEnv *env, jobject jLoadListener)
+    : mPausedLoad(false)
+{
+    mJLoader = env->NewGlobalRef(jLoadListener);
+}
+
+WebCoreResourceLoader::~WebCoreResourceLoader()
+{
+    JNIEnv* env = JSC::Bindings::getJNIEnv();
+    SET_NATIVE_HANDLE(env, mJLoader, 0);
+    env->DeleteGlobalRef(mJLoader);
+    mJLoader = 0;
+}
+
+void WebCoreResourceLoader::cancel()
+{
+    JNIEnv* env = JSC::Bindings::getJNIEnv();
+    env->CallVoidMethod(mJLoader, gResourceLoader.mCancelMethodID);
+    checkException(env);
+}
+
+void WebCoreResourceLoader::downloadFile()
+{
+    JNIEnv* env = JSC::Bindings::getJNIEnv();
+    env->CallVoidMethod(mJLoader, gResourceLoader.mDownloadFileMethodID);
+    checkException(env);
+}
+
+void WebCoreResourceLoader::pauseLoad(bool pause)
+{
+    if (mPausedLoad == pause)
+        return;
+
+    mPausedLoad = pause;
+    JNIEnv* env = JSC::Bindings::getJNIEnv();
+    env->CallVoidMethod(mJLoader, gResourceLoader.mPauseLoadMethodID, pause);
+    checkException(env);
+}
+
+/*
+* This static method is called to check to see if a POST response is in
+* the cache. This may be slow, but is only used during a navigation to
+* a POST response.
+*/
+bool WebCoreResourceLoader::willLoadFromCache(const WebCore::KURL& url, int64_t identifier)
+{
+    JNIEnv* env = JSC::Bindings::getJNIEnv();
+    WTF::String urlStr = url.string();
+    jstring jUrlStr = wtfStringToJstring(env, urlStr);
+    jclass resourceLoader = env->FindClass("android/webkit/LoadListener");
+    bool val = env->CallStaticBooleanMethod(resourceLoader, gResourceLoader.mWillLoadFromCacheMethodID, jUrlStr, identifier);
+    checkException(env);
+    env->DeleteLocalRef(resourceLoader);
+    env->DeleteLocalRef(jUrlStr);
+
+    return val;
+}
+
+// ----------------------------------------------------------------------------
+void WebCoreResourceLoader::SetResponseHeader(JNIEnv* env, jobject obj, jint nativeResponse, jstring key, jstring val)
+{
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::ResourceTimeCounter);
+#endif
+    
+    WebCore::ResourceResponse* response = (WebCore::ResourceResponse*)nativeResponse;
+    LOG_ASSERT(response, "nativeSetResponseHeader must take a valid response pointer!");
+
+    LOG_ASSERT(key, "How did a null value become a key?");
+    if (val)
+        response->setHTTPHeaderField(jstringToWtfString(env, key), jstringToWtfString(env, val));
+}
+
+jint WebCoreResourceLoader::CreateResponse(JNIEnv* env, jobject obj, jstring url, jint statusCode,
+                                                    jstring statusText, jstring mimeType, jlong expectedLength,
+                                                    jstring encoding)
+{
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::ResourceTimeCounter);
+#endif
+    LOG_ASSERT(url, "Must have a url in the response!");
+    WebCore::KURL kurl(WebCore::ParsedURLString, jstringToWtfString(env, url));
+    WTF::String encodingStr;
+    WTF::String mimeTypeStr;
+    if (mimeType) {
+        mimeTypeStr = jstringToWtfString(env, mimeType);
+        LOGV("Response setMIMEType: %s", mimeTypeStr.latin1().data());
+    }
+    if (encoding) {
+        encodingStr = jstringToWtfString(env, encoding);
+        LOGV("Response setTextEncodingName: %s", encodingStr.latin1().data());
+    }
+    WebCore::ResourceResponse* response = new WebCore::ResourceResponse(
+            kurl, mimeTypeStr, (long long)expectedLength,
+            encodingStr, WTF::String());
+    response->setHTTPStatusCode(statusCode);
+    if (statusText) {
+        WTF::String status = jstringToWtfString(env, statusText);
+        response->setHTTPStatusText(status);
+        LOGV("Response setStatusText: %s", status.latin1().data());
+    }
+    return (int)response;
+}
+   
+void WebCoreResourceLoader::ReceivedResponse(JNIEnv* env, jobject obj, jint nativeResponse)
+{
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::ResourceTimeCounter);
+#endif
+    WebCore::ResourceHandle* handle = GET_NATIVE_HANDLE(env, obj);
+    LOG_ASSERT(handle, "nativeReceivedResponse must take a valid handle!");
+    // ResourceLoader::didFail() can set handle to be NULL, we need to check
+    if (!handle)
+        return;
+
+    WebCore::ResourceResponse* response = (WebCore::ResourceResponse*)nativeResponse;
+    LOG_ASSERT(response, "nativeReceivedResponse must take a valid resource pointer!");
+    handle->client()->didReceiveResponse(handle, *response);
+    // As the client makes a copy of the response, delete it here.
+    delete response;
+}
+
+void WebCoreResourceLoader::AddData(JNIEnv* env, jobject obj, jbyteArray dataArray, jint length)
+{
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::ResourceTimeCounter);
+#endif
+    LOGV("webcore_resourceloader data(%d)", length);
+
+    WebCore::ResourceHandle* handle = GET_NATIVE_HANDLE(env, obj);
+    LOG_ASSERT(handle, "nativeAddData must take a valid handle!");
+    // ResourceLoader::didFail() can set handle to be NULL, we need to check
+    if (!handle)
+        return;
+
+    SkAutoMemoryUsageProbe  mup("android_webcore_resourceloader_nativeAddData");
+    
+    bool result = false;
+    jbyte * data =  env->GetByteArrayElements(dataArray, NULL);
+
+    LOG_ASSERT(handle->client(), "Why do we not have a client?");
+    handle->client()->didReceiveData(handle, (const char *)data, length, length);
+    env->ReleaseByteArrayElements(dataArray, data, JNI_ABORT);    
+}
+
+void WebCoreResourceLoader::Finished(JNIEnv* env, jobject obj)
+{
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::ResourceTimeCounter);
+#endif
+    LOGV("webcore_resourceloader finished");
+    WebCore::ResourceHandle* handle = GET_NATIVE_HANDLE(env, obj);
+    LOG_ASSERT(handle, "nativeFinished must take a valid handle!");
+    // ResourceLoader::didFail() can set handle to be NULL, we need to check
+    if (!handle)
+        return;
+
+    LOG_ASSERT(handle->client(), "Why do we not have a client?");
+    handle->client()->didFinishLoading(handle, 0);
+}
+
+jstring WebCoreResourceLoader::RedirectedToUrl(JNIEnv* env, jobject obj,
+        jstring baseUrl, jstring redirectTo, jint nativeResponse)
+{
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::ResourceTimeCounter);
+#endif
+    LOGV("webcore_resourceloader redirectedToUrl");
+    WebCore::ResourceHandle* handle = GET_NATIVE_HANDLE(env, obj);
+    LOG_ASSERT(handle, "nativeRedirectedToUrl must take a valid handle!");
+    // ResourceLoader::didFail() can set handle to be NULL, we need to check
+    if (!handle)
+        return NULL;
+
+    LOG_ASSERT(handle->client(), "Why do we not have a client?");
+    WebCore::ResourceRequest r = handle->firstRequest();
+    WebCore::KURL url(WebCore::KURL(WebCore::ParsedURLString, jstringToWtfString(env, baseUrl)),
+            jstringToWtfString(env, redirectTo));
+    WebCore::ResourceResponse* response = (WebCore::ResourceResponse*)nativeResponse;
+    // If the url fails to resolve the relative path, return null.
+    if (url.protocol().isEmpty()) {
+        delete response;
+        return NULL;
+    } else {
+        // Ensure the protocol is lowercase.
+        url.setProtocol(url.protocol().lower());
+    }
+    // Set the url after updating the protocol.
+    r.setURL(url);
+    if (r.httpMethod() == "POST") {
+        r.setHTTPMethod("GET");
+        r.clearHTTPReferrer();
+        r.setHTTPBody(0);
+        r.setHTTPContentType("");
+    }
+    handle->client()->willSendRequest(handle, r, *response);
+    delete response;
+    return wtfStringToJstring(env, url.string());
+}
+
+void WebCoreResourceLoader::Error(JNIEnv* env, jobject obj, jint id, jstring description,
+        jstring failingUrl)
+{
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::ResourceTimeCounter);
+#endif
+    LOGV("webcore_resourceloader error");
+    WebCore::ResourceHandle* handle = GET_NATIVE_HANDLE(env, obj);
+    LOG_ASSERT(handle, "nativeError must take a valid handle!");
+    // ResourceLoader::didFail() can set handle to be NULL, we need to check
+    if (!handle)
+        return;
+
+    handle->client()->didFail(handle, WebCore::ResourceError("", id,
+                jstringToWtfString(env, failingUrl), jstringToWtfString(env, description)));
+}
+
+// ----------------------------------------------------------------------------
+
+/*
+ * JNI registration.
+ */
+static JNINativeMethod gResourceloaderMethods[] = {
+    /* name, signature, funcPtr */
+    { "nativeSetResponseHeader", "(ILjava/lang/String;Ljava/lang/String;)V",
+        (void*) WebCoreResourceLoader::SetResponseHeader },
+    { "nativeCreateResponse", "(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;JLjava/lang/String;)I",
+        (void*) WebCoreResourceLoader::CreateResponse },
+    { "nativeReceivedResponse", "(I)V",
+        (void*) WebCoreResourceLoader::ReceivedResponse },
+    { "nativeAddData", "([BI)V",
+        (void*) WebCoreResourceLoader::AddData },
+    { "nativeFinished", "()V",
+        (void*) WebCoreResourceLoader::Finished },
+    { "nativeRedirectedToUrl", "(Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/String;",
+        (void*) WebCoreResourceLoader::RedirectedToUrl },
+    { "nativeError", "(ILjava/lang/String;Ljava/lang/String;)V",
+        (void*) WebCoreResourceLoader::Error }
+};
+
+int registerResourceLoader(JNIEnv* env)
+{
+    jclass resourceLoader = env->FindClass("android/webkit/LoadListener");
+    LOG_FATAL_IF(resourceLoader == NULL, 
+        "Unable to find class android/webkit/LoadListener");
+    
+    gResourceLoader.mObject = 
+        env->GetFieldID(resourceLoader, "mNativeLoader", "I");
+    LOG_FATAL_IF(gResourceLoader.mObject == NULL, 
+        "Unable to find android/webkit/LoadListener.mNativeLoader");
+    
+    gResourceLoader.mCancelMethodID = 
+        env->GetMethodID(resourceLoader, "cancel", "()V");
+    LOG_FATAL_IF(gResourceLoader.mCancelMethodID == NULL, 
+        "Could not find method cancel on LoadListener");
+    
+    gResourceLoader.mDownloadFileMethodID = 
+        env->GetMethodID(resourceLoader, "downloadFile", "()V");
+    LOG_FATAL_IF(gResourceLoader.mDownloadFileMethodID == NULL, 
+        "Could not find method downloadFile on LoadListener");
+
+    gResourceLoader.mPauseLoadMethodID =
+        env->GetMethodID(resourceLoader, "pauseLoad", "(Z)V");
+    LOG_FATAL_IF(gResourceLoader.mPauseLoadMethodID == NULL,
+        "Could not find method pauseLoad on LoadListener");
+
+    gResourceLoader.mWillLoadFromCacheMethodID = 
+        env->GetStaticMethodID(resourceLoader, "willLoadFromCache", "(Ljava/lang/String;J)Z");
+    LOG_FATAL_IF(gResourceLoader.mWillLoadFromCacheMethodID == NULL, 
+        "Could not find static method willLoadFromCache on LoadListener");
+
+    env->DeleteLocalRef(resourceLoader);
+
+    return jniRegisterNativeMethods(env, "android/webkit/LoadListener", 
+                     gResourceloaderMethods, NELEM(gResourceloaderMethods));
+}
+
+} /* namespace android */
diff --git a/Source/WebKit/android/jni/WebCoreResourceLoader.h b/Source/WebKit/android/jni/WebCoreResourceLoader.h
new file mode 100644
index 0000000..0e34a5b
--- /dev/null
+++ b/Source/WebKit/android/jni/WebCoreResourceLoader.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2006, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebCoreResourceLoader_h
+#define WebCoreResourceLoader_h
+
+#include <KURL.h>
+#include <ResourceLoaderAndroid.h>
+#include <jni.h>
+
+namespace android {
+
+class WebCoreResourceLoader : public WebCore::ResourceLoaderAndroid
+{
+public:
+    static PassRefPtr<WebCore::ResourceLoaderAndroid> create(JNIEnv *env, jobject jLoadListener);
+    virtual ~WebCoreResourceLoader();
+
+    /**
+     * Call to java to cancel the current load.
+     */
+    virtual void cancel();
+
+    /**
+    * Call to java to download the current load rather than feed it
+    * back to WebCore
+    */
+    virtual void downloadFile();
+
+    virtual void pauseLoad(bool);
+
+    /**
+    * Call to java to find out if this URL is in the cache
+    */
+    static bool willLoadFromCache(const WebCore::KURL& url, int64_t identifier);
+
+    // Native jni functions
+    static void SetResponseHeader(JNIEnv*, jobject, jint, jstring, jstring);
+    static jint CreateResponse(JNIEnv*, jobject, jstring, jint, jstring,
+            jstring, jlong, jstring);
+    static void ReceivedResponse(JNIEnv*, jobject, jint);
+    static void AddData(JNIEnv*, jobject, jbyteArray, jint);
+    static void Finished(JNIEnv*, jobject);
+    static jstring RedirectedToUrl(JNIEnv*, jobject, jstring, jstring, jint);
+    static void Error(JNIEnv*, jobject, jint, jstring, jstring);
+
+protected:
+    WebCoreResourceLoader(JNIEnv *env, jobject jLoadListener);
+private:
+    jobject     mJLoader;
+    bool        mPausedLoad;
+};
+
+} // end namespace android
+
+#endif
diff --git a/Source/WebKit/android/jni/WebCoreViewBridge.h b/Source/WebKit/android/jni/WebCoreViewBridge.h
index cca4ca5..b04a0f9 100644
--- a/Source/WebKit/android/jni/WebCoreViewBridge.h
+++ b/Source/WebKit/android/jni/WebCoreViewBridge.h
@@ -48,7 +48,7 @@
 
     virtual ~WebCoreViewBridge() { }
 
-    virtual void draw(WebCore::GraphicsContext* ctx,
+    virtual void draw(WebCore::GraphicsContext* ctx, 
         const WebCore::IntRect& rect) = 0;
 
     const WebCore::IntRect& getBounds() const 
diff --git a/Source/WebKit/android/jni/WebFrameView.cpp b/Source/WebKit/android/jni/WebFrameView.cpp
index 10e31dc..8e5eac4 100644
--- a/Source/WebKit/android/jni/WebFrameView.cpp
+++ b/Source/WebKit/android/jni/WebFrameView.cpp
@@ -54,16 +54,51 @@
     Release(mWebViewCore);
 }
 
-void WebFrameView::draw(WebCore::GraphicsContext* gc, const WebCore::IntRect& rect) {
+void WebFrameView::draw(WebCore::GraphicsContext* ctx, const WebCore::IntRect& rect) {
     WebCore::Frame* frame = mFrameView->frame();
 
-    if (frame->contentRenderer())
-        mFrameView->paintContents(gc, rect);
-    else {
-        // FIXME: I'm not entirely sure this ever happens or is needed
-        gc->setFillColor(WebCore::Color::white, WebCore::ColorSpaceDeviceRGB);
-        gc->fillRect(rect);
+    if (NULL == frame->contentRenderer()) {
+        // We only do this if there is nothing else to draw.
+        // If there is a renderer, it will fill the bg itself, so we don't want to
+        // double-draw (slow)
+        SkCanvas* canvas = ctx->platformContext()->mCanvas;
+        canvas->drawColor(SK_ColorWHITE);
+    } else if (frame->tree()->parent()) {
+        // Note: this code was moved from FrameLoaderClientAndroid
+        //
+        // For subframe, create a new translated rect from the given rectangle.
+        WebCore::IntRect transRect(rect);
+        // In Frame::markAllMatchesForText(), it does a fake paint.  So we need
+        // to handle the case where platformContext() is null.  However, we still
+        // want to call paint, since WebKit must have called the paint for a reason.
+        SkCanvas* canvas = ctx->platformContext() ? ctx->platformContext()->mCanvas : NULL;
+        if (canvas) {
+            const WebCore::IntRect& bounds = getBounds();
+
+            // Grab the intersection of transRect and the frame's bounds.
+            transRect.intersect(bounds);
+            if (transRect.isEmpty())
+                return;
+
+            // Move the transRect into the frame's local coordinates.
+            transRect.move(-bounds.x(), -bounds.y());
+
+            // Translate the canvas, add a clip.
+            canvas->save();
+            canvas->translate(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()));
+            canvas->clipRect(transRect);
+        }
+        mFrameView->paintContents(ctx, transRect);
+        if (canvas)
+            canvas->restore();
+    } else {
+        mFrameView->paintContents(ctx, rect);
     }
 }
 
+void WebFrameView::setView(WebCore::FrameView* frameView) {
+    mFrameView = frameView;
+    mFrameView->setPlatformWidget(this);
+}
+
 }   // namespace android
diff --git a/Source/WebKit/android/jni/WebFrameView.h b/Source/WebKit/android/jni/WebFrameView.h
index ac81afe..117b603 100644
--- a/Source/WebKit/android/jni/WebFrameView.h
+++ b/Source/WebKit/android/jni/WebFrameView.h
@@ -47,6 +47,8 @@
             return mWebViewCore;
         }
 
+        void setView(WebCore::FrameView* frameView);
+
         WebCore::FrameView* view() const {
             return mFrameView;
         }
diff --git a/Source/WebKit/android/jni/WebHistory.cpp b/Source/WebKit/android/jni/WebHistory.cpp
index b6972e4..aa74b81 100644
--- a/Source/WebKit/android/jni/WebHistory.cpp
+++ b/Source/WebKit/android/jni/WebHistory.cpp
@@ -28,7 +28,6 @@
 #include "config.h"
 #include "WebHistory.h"
 
-#include "AndroidLog.h"
 #include "BackForwardList.h"
 #include "BackForwardListImpl.h"
 #include "DocumentLoader.h"
@@ -36,7 +35,6 @@
 #include "FrameLoader.h"
 #include "FrameLoaderClientAndroid.h"
 #include "FrameTree.h"
-#include "GraphicsJNI.h"
 #include "HistoryItem.h"
 #include "IconDatabase.h"
 #include "Page.h"
@@ -56,13 +54,16 @@
 namespace android {
 
 // Forward declarations
-static void writeItem(WTF::Vector<char>& vector, WebCore::HistoryItem* item);
-static void writeChildrenRecursive(WTF::Vector<char>& vector, WebCore::HistoryItem* parent);
-static bool readItemRecursive(WebCore::HistoryItem* child, const char** pData, int length);
+static void write_item(WTF::Vector<char>& v, WebCore::HistoryItem* item);
+static void write_children_recursive(WTF::Vector<char>& v, WebCore::HistoryItem* parent);
+static bool read_item_recursive(WebCore::HistoryItem* child, const char** pData, int length);
 
 // Field ids for WebHistoryItems
 struct WebHistoryItemFields {
     jmethodID   mInit;
+    jmethodID   mUpdate;
+    jfieldID    mTitle;
+    jfieldID    mUrl;
 } gWebHistoryItem;
 
 struct WebBackForwardListFields {
@@ -77,7 +78,7 @@
 
 static void WebHistoryClose(JNIEnv* env, jobject obj, jint frame)
 {
-    ALOG_ASSERT(frame, "Close needs a valid Frame pointer!");
+    LOG_ASSERT(frame, "Close needs a valid Frame pointer!");
     WebCore::Frame* pFrame = (WebCore::Frame*)frame;
 
     WebCore::BackForwardListImpl* list = static_cast<WebCore::BackForwardListImpl*>(pFrame->page()->backForwardList());
@@ -144,7 +145,7 @@
 
 static void WebHistoryRestoreIndex(JNIEnv* env, jobject obj, jint frame, jint index)
 {
-    ALOG_ASSERT(frame, "RestoreState needs a valid Frame pointer!");
+    LOG_ASSERT(frame, "RestoreState needs a valid Frame pointer!");
     WebCore::Frame* pFrame = (WebCore::Frame*)frame;
     WebCore::Page* page = pFrame->page();
     WebCore::HistoryItem* currentItem =
@@ -155,10 +156,10 @@
     page->goToItem(currentItem, FrameLoadTypeIndexedBackForward);
 }
 
-static jint WebHistoryInflate(JNIEnv* env, jobject obj, jint frame, jbyteArray data)
+static void WebHistoryInflate(JNIEnv* env, jobject obj, jint frame, jbyteArray data)
 {
-    ALOG_ASSERT(frame, "Inflate needs a valid frame pointer!");
-    ALOG_ASSERT(data, "Inflate needs a valid data pointer!");
+    LOG_ASSERT(frame, "Inflate needs a valid frame pointer!");
+    LOG_ASSERT(data, "Inflate needs a valid data pointer!");
 
     // Get the actual bytes and the length from the java array.
     const jbyte* bytes = env->GetByteArrayElements(data, NULL);
@@ -167,7 +168,7 @@
     // Inflate the history tree into one HistoryItem or null if the inflation
     // failed.
     RefPtr<WebCore::HistoryItem> newItem = WebCore::HistoryItem::create();
-    WebHistoryItem* bridge = new WebHistoryItem(newItem.get());
+    WebHistoryItem* bridge = new WebHistoryItem(env, obj, newItem.get());
     newItem->setBridge(bridge);
 
     // Inflate the item recursively. If it fails, that is ok. We'll have an
@@ -177,7 +178,7 @@
     // ptr's value. We can't pass &bytes since we have to send bytes to
     // ReleaseByteArrayElements unchanged.
     const char* ptr = reinterpret_cast<const char*>(bytes);
-    readItemRecursive(newItem.get(), &ptr, (int)size);
+    read_item_recursive(newItem.get(), &ptr, (int)size);
     env->ReleaseByteArrayElements(data, const_cast<jbyte*>(bytes), JNI_ABORT);
     bridge->setActive();
 
@@ -187,110 +188,49 @@
 
     // Update the item.
     bridge->updateHistoryItem(newItem.get());
-    // Ref here because Java expects to adopt the reference, and as such will not
-    // call ref on it. However, setBridge has also adopted the reference
-    // TODO: This is confusing as hell, clean up ownership and have setBridge
-    // take a RefPtr instead of a raw ptr and calling adoptRef on it
-    bridge->ref();
-    return reinterpret_cast<jint>(bridge);
-}
-
-static void WebHistoryRef(JNIEnv* env, jobject obj, jint ptr)
-{
-    if (ptr)
-        reinterpret_cast<WebHistoryItem*>(ptr)->ref();
-}
-
-static void WebHistoryUnref(JNIEnv* env, jobject obj, jint ptr)
-{
-    if (ptr)
-        reinterpret_cast<WebHistoryItem*>(ptr)->deref();
-}
-
-static jobject WebHistoryGetTitle(JNIEnv* env, jobject obj, jint ptr)
-{
-    if (!ptr)
-        return 0;
-    WebHistoryItem* item = reinterpret_cast<WebHistoryItem*>(ptr);
-    MutexLocker locker(item->m_lock);
-    return wtfStringToJstring(env, item->m_title, false);
-}
-
-static jobject WebHistoryGetUrl(JNIEnv* env, jobject obj, jint ptr)
-{
-    if (!ptr)
-        return 0;
-    WebHistoryItem* item = reinterpret_cast<WebHistoryItem*>(ptr);
-    MutexLocker locker(item->m_lock);
-    return wtfStringToJstring(env, item->m_url, false);
-}
-
-static jobject WebHistoryGetOriginalUrl(JNIEnv* env, jobject obj, jint ptr)
-{
-    if (!ptr)
-        return 0;
-    WebHistoryItem* item = reinterpret_cast<WebHistoryItem*>(ptr);
-    MutexLocker locker(item->m_lock);
-    return wtfStringToJstring(env, item->m_originalUrl, false);
-}
-
-static jobject WebHistoryGetFlattenedData(JNIEnv* env, jobject obj, jint ptr)
-{
-    if (!ptr)
-        return 0;
-
-    WebHistoryItem* item = reinterpret_cast<WebHistoryItem*>(ptr);
-    MutexLocker locker(item->m_lock);
-
-    if (!item->m_dataCached) {
-        // Try to create a new java byte array.
-        jbyteArray b = env->NewByteArray(item->m_data.size());
-        if (!b)
-            return NULL;
-
-        // Write our flattened data to the java array.
-        env->SetByteArrayRegion(b, 0, item->m_data.size(),
-                                (const jbyte*)item->m_data.data());
-        item->m_dataCached = env->NewGlobalRef(b);
-        env->DeleteLocalRef(b);
-    }
-    return item->m_dataCached;
-}
-
-static jobject WebHistoryGetFavicon(JNIEnv* env, jobject obj, jint ptr)
-{
-    if (!ptr)
-        return 0;
-    WebHistoryItem* item = reinterpret_cast<WebHistoryItem*>(ptr);
-    MutexLocker locker(item->m_lock);
-    if (!item->m_faviconCached && item->m_favicon) {
-        jobject favicon = GraphicsJNI::createBitmap(env,
-                                                    item->m_favicon,
-                                                    false, NULL);
-        item->m_favicon = 0; // Framework now owns the pointer
-        item->m_faviconCached = env->NewGlobalRef(favicon);
-        env->DeleteLocalRef(favicon);
-    }
-    return item->m_faviconCached;
 }
 
 // 6 empty strings + no document state + children count + 2 scales = 10 unsigned values
 // 1 char for isTargetItem.
 #define HISTORY_MIN_SIZE ((int)(sizeof(unsigned) * 10 + sizeof(char)))
 
-void WebHistory::Flatten(JNIEnv* env, WTF::Vector<char>& vector, WebCore::HistoryItem* item)
+jbyteArray WebHistory::Flatten(JNIEnv* env, WTF::Vector<char>& v, WebCore::HistoryItem* item)
 {
     if (!item)
-        return;
+        return NULL;
 
     // Reserve a vector of chars with an initial size of HISTORY_MIN_SIZE.
-    vector.reserveCapacity(HISTORY_MIN_SIZE);
+    v.reserveCapacity(HISTORY_MIN_SIZE);
 
     // Write the top-level history item and then write all the children
     // recursively.
-    ALOG_ASSERT(item->bridge(), "Why don't we have a bridge object here?");
-    writeItem(vector, item);
-    writeChildrenRecursive(vector, item);
+    LOG_ASSERT(item->bridge(), "Why don't we have a bridge object here?");
+    write_item(v, item);
+    write_children_recursive(v, item);
+
+    // Try to create a new java byte array.
+    jbyteArray b = env->NewByteArray(v.size());
+    if (!b)
+        return NULL;
+
+    // Write our flattened data to the java array.
+    env->SetByteArrayRegion(b, 0, v.size(), (const jbyte*)v.data());
+    return b;
+}
+
+WebHistoryItem::WebHistoryItem(JNIEnv* env, jobject obj,
+        WebCore::HistoryItem* item) : WebCore::AndroidWebHistoryBridge(item) {
+    m_object = env->NewWeakGlobalRef(obj);
+    m_parent = 0;
+}
+
+WebHistoryItem::~WebHistoryItem() {
+    if (m_object) {
+        JNIEnv* env = JSC::Bindings::getJNIEnv();
+        if (!env)
+            return;
+        env->DeleteWeakGlobalRef(m_object);
+    }
 }
 
 void WebHistoryItem::updateHistoryItem(WebCore::HistoryItem* item) {
@@ -306,7 +246,7 @@
             // if the parent only has one ref, it is from this WebHistoryItem.
             // This means that the matching WebCore::HistoryItem has been freed.
             // This can happen during clear().
-            ALOGW("Can't updateHistoryItem as the top HistoryItem is gone");
+            LOGW("Can't updateHistoryItem as the top HistoryItem is gone");
             return;
         }
         while (webItem->parent())
@@ -316,7 +256,7 @@
             // If a HistoryItem only exists for page cache, it is possible that
             // the parent HistoryItem destroyed before the child HistoryItem. If
             // it happens, skip updating.
-            ALOGW("Can't updateHistoryItem as the top HistoryItem is gone");
+            LOGW("Can't updateHistoryItem as the top HistoryItem is gone");
             return;
         }
     }
@@ -324,15 +264,23 @@
     if (!env)
         return;
 
-    MutexLocker locker(webItem->m_lock);
+    // Don't do anything if the item has been gc'd already
+    AutoJObject realItem = getRealObject(env, webItem->m_object);
+    if (!realItem.get())
+        return;
 
-    // TODO: Figure out if we can't just use item->urlString() instead...
     const WTF::String urlString = WebFrame::convertIDNToUnicode(item->url());
-    webItem->m_url = urlString.threadsafeCopy();
+    jstring urlStr = NULL;
+    if (!urlString.isNull())
+        urlStr = wtfStringToJstring(env, urlString);
     const WTF::String originalUrlString = WebFrame::convertIDNToUnicode(item->originalURL());
-    webItem->m_originalUrl = originalUrlString.threadsafeCopy();
+    jstring originalUrlStr = NULL;
+    if (!originalUrlString.isNull())
+        originalUrlStr = wtfStringToJstring(env, originalUrlString);
     const WTF::String& titleString = item->title();
-    webItem->m_title = titleString.threadsafeCopy();
+    jstring titleStr = NULL;
+    if (!titleString.isNull())
+        titleStr = wtfStringToJstring(env, titleString);
 
     // Try to get the favicon from the history item. For some pages like Grand
     // Prix, there are history items with anchors. If the icon fails for the
@@ -346,41 +294,24 @@
     // FIXME: This method should not be used from outside WebCore and will be removed.
     // http://trac.webkit.org/changeset/81484
     WebCore::Image* icon = WebCore::iconDatabase().synchronousIconForPageURL(url, WebCore::IntSize(16, 16));
-    delete webItem->m_favicon;
-    webItem->m_favicon = webcoreImageToSkBitmap(icon);
-    if (webItem->m_faviconCached) {
-        env->DeleteGlobalRef(webItem->m_faviconCached);
-        webItem->m_faviconCached = 0;
-    }
 
-    webItem->m_data.clear();
-    WebHistory::Flatten(env, webItem->m_data, item);
-    if (webItem->m_dataCached) {
-        env->DeleteGlobalRef(webItem->m_dataCached);
-        webItem->m_dataCached = 0;
-    }
-}
+    if (icon)
+        favicon = webcoreImageToJavaBitmap(env, icon);
 
-WebHistoryItem::~WebHistoryItem()
-{
-    delete m_favicon;
-    JNIEnv* env = JSC::Bindings::getJNIEnv();
-    if (!env) {
-        ALOGW("Failed to get JNIEnv*! Potential memory leak!");
-        return;
-    }
-    if (m_faviconCached) {
-        env->DeleteGlobalRef(m_faviconCached);
-        m_faviconCached = 0;
-    }
-    if (m_dataCached) {
-        env->DeleteGlobalRef(m_dataCached);
-        m_dataCached = 0;
-    }
+    WTF::Vector<char> data;
+    jbyteArray array = WebHistory::Flatten(env, data, item);
+    env->CallVoidMethod(realItem.get(), gWebHistoryItem.mUpdate, urlStr,
+            originalUrlStr, titleStr, favicon, array);
+    env->DeleteLocalRef(urlStr);
+    env->DeleteLocalRef(originalUrlStr);
+    env->DeleteLocalRef(titleStr);
+    if (favicon)
+        env->DeleteLocalRef(favicon);
+    env->DeleteLocalRef(array);
 }
 
 static void historyItemChanged(WebCore::HistoryItem* item) {
-    ALOG_ASSERT(item, "historyItemChanged called with a null item");
+    LOG_ASSERT(item, "historyItemChanged called with a null item");
 
     if (item->bridge())
         item->bridge()->updateHistoryItem(item);
@@ -388,22 +319,22 @@
 
 void WebHistory::AddItem(const AutoJObject& list, WebCore::HistoryItem* item)
 {
-    ALOG_ASSERT(item, "newItem must take a valid HistoryItem!");
+    LOG_ASSERT(item, "newItem must take a valid HistoryItem!");
     // Item already added. Should only happen when we are inflating the list.
     if (item->bridge() || !list.get())
         return;
 
     JNIEnv* env = list.env();
-    // Create the bridge, make it active, and attach it to the item.
-    WebHistoryItem* bridge = new WebHistoryItem(item);
-    bridge->setActive();
-    item->setBridge(bridge);
     // Allocate a blank WebHistoryItem
     jclass clazz = env->FindClass("android/webkit/WebHistoryItem");
-    jobject newItem = env->NewObject(clazz, gWebHistoryItem.mInit,
-            reinterpret_cast<int>(bridge));
+    jobject newItem = env->NewObject(clazz, gWebHistoryItem.mInit);
     env->DeleteLocalRef(clazz);
 
+    // Create the bridge, make it active, and attach it to the item.
+    WebHistoryItem* bridge = new WebHistoryItem(env, newItem, item);
+    bridge->setActive();
+    item->setBridge(bridge);
+
     // Update the history item which will flatten the data and call update on
     // the java item.
     bridge->updateHistoryItem(item);
@@ -427,7 +358,7 @@
         list.env()->CallVoidMethod(list.get(), gWebBackForwardList.mSetCurrentIndex, newIndex);
 }
 
-static void writeString(WTF::Vector<char>& vector, const WTF::String& str)
+static void write_string(WTF::Vector<char>& v, const WTF::String& str)
 {
     unsigned strLen = str.length();
     // Only do work if the string has data.
@@ -435,96 +366,96 @@
         // Determine how much to grow the vector. Use the worst case for utf8 to
         // avoid reading the string twice. Add sizeof(unsigned) to hold the
         // string length in utf8.
-        unsigned vectorLen = vector.size() + sizeof(unsigned);
+        unsigned vectorLen = v.size() + sizeof(unsigned);
         unsigned length = (strLen << 2) + vectorLen;
         // Grow the vector. This will change the value of v.size() but we
         // remember the original size above.
-        vector.grow(length);
+        v.grow(length);
         // Grab the position to write to.
-        char* data = vector.begin() + vectorLen;
+        char* data = v.begin() + vectorLen;
         // Write the actual string
         int l = SkUTF16_ToUTF8(str.characters(), strLen, data);
-        ALOGV("Writing string          %d %.*s", l, l, data);
+        LOGV("Writing string       %d %.*s", l, l, data);
         // Go back and write the utf8 length. Subtract sizeof(unsigned) from
         // data to get the position to write the length.
         memcpy(data - sizeof(unsigned), (char*)&l, sizeof(unsigned));
         // Shrink the internal state of the vector so we match what was
         // actually written.
-        vector.shrink(vectorLen + l);
+        v.shrink(vectorLen + l);
     } else
-        vector.append((char*)&strLen, sizeof(unsigned));
+        v.append((char*)&strLen, sizeof(unsigned));
 }
 
-static void writeItem(WTF::Vector<char>& vector, WebCore::HistoryItem* item)
+static void write_item(WTF::Vector<char>& v, WebCore::HistoryItem* item)
 {
     // Original url
-    writeString(vector, item->originalURLString());
+    write_string(v, item->originalURLString());
 
     // Url
-    writeString(vector, item->urlString());
+    write_string(v, item->urlString());
 
     // Title
-    writeString(vector, item->title());
+    write_string(v, item->title());
 
     // Form content type
-    writeString(vector, item->formContentType());
+    write_string(v, item->formContentType());
 
     // Form data
     const WebCore::FormData* formData = item->formData();
     if (formData) {
-        writeString(vector, formData->flattenToString());
+        write_string(v, formData->flattenToString());
         // save the identifier as it is not included in the flatten data
         int64_t id = formData->identifier();
-        vector.append((char*)&id, sizeof(int64_t));
+        v.append((char*)&id, sizeof(int64_t));
     } else
-        writeString(vector, WTF::String()); // Empty constructor does not allocate a buffer.
+        write_string(v, WTF::String()); // Empty constructor does not allocate a buffer.
 
     // Target
-    writeString(vector, item->target());
+    write_string(v, item->target());
 
     AndroidWebHistoryBridge* bridge = item->bridge();
-    ALOG_ASSERT(bridge, "We should have a bridge here!");
+    LOG_ASSERT(bridge, "We should have a bridge here!");
     // Screen scale
     const float scale = bridge->scale();
-    ALOGV("Writing scale           %f", scale);
-    vector.append((char*)&scale, sizeof(float));
+    LOGV("Writing scale %f", scale);
+    v.append((char*)&scale, sizeof(float));
     const float textWrapScale = bridge->textWrapScale();
-    ALOGV("Writing text wrap scale %f", textWrapScale);
-    vector.append((char*)&textWrapScale, sizeof(float));
+    LOGV("Writing text wrap scale %f", textWrapScale);
+    v.append((char*)&textWrapScale, sizeof(float));
 
     // Scroll position.
     const int scrollX = item->scrollPoint().x();
-    vector.append((char*)&scrollX, sizeof(int));
+    v.append((char*)&scrollX, sizeof(int));
     const int scrollY = item->scrollPoint().y();
-    vector.append((char*)&scrollY, sizeof(int));
+    v.append((char*)&scrollY, sizeof(int));
 
     // Document state
     const WTF::Vector<WTF::String>& docState = item->documentState();
     WTF::Vector<WTF::String>::const_iterator end = docState.end();
     unsigned stateSize = docState.size();
-    ALOGV("Writing docState        %d", stateSize);
-    vector.append((char*)&stateSize, sizeof(unsigned));
+    LOGV("Writing docState     %d", stateSize);
+    v.append((char*)&stateSize, sizeof(unsigned));
     for (WTF::Vector<WTF::String>::const_iterator i = docState.begin(); i != end; ++i) {
-        writeString(vector, *i);
+        write_string(v, *i);
     }
 
     // Is target item
-    ALOGV("Writing isTargetItem    %d", item->isTargetItem());
-    vector.append((char)item->isTargetItem());
+    LOGV("Writing isTargetItem %d", item->isTargetItem());
+    v.append((char)item->isTargetItem());
 
     // Children count
     unsigned childCount = item->children().size();
-    ALOGV("Writing childCount      %d", childCount);
-    vector.append((char*)&childCount, sizeof(unsigned));
+    LOGV("Writing childCount   %d", childCount);
+    v.append((char*)&childCount, sizeof(unsigned));
 }
 
-static void writeChildrenRecursive(WTF::Vector<char>& vector, WebCore::HistoryItem* parent)
+static void write_children_recursive(WTF::Vector<char>& v, WebCore::HistoryItem* parent)
 {
     const WebCore::HistoryItemVector& children = parent->children();
     WebCore::HistoryItemVector::const_iterator end = children.end();
     for (WebCore::HistoryItemVector::const_iterator i = children.begin(); i != end; ++i) {
         WebCore::HistoryItem* item = (*i).get();
-        ALOG_ASSERT(parent->bridge(),
+        LOG_ASSERT(parent->bridge(),
                 "The parent item should have a bridge object!");
         if (!item->bridge()) {
             WebHistoryItem* bridge = new WebHistoryItem(static_cast<WebHistoryItem*>(parent->bridge()));
@@ -536,223 +467,116 @@
             // parent must not have a parent bridge.
             WebHistoryItem* bridge = static_cast<WebHistoryItem*>(item->bridge());
             WebHistoryItem* parentBridge = static_cast<WebHistoryItem*>(parent->bridge());
-            ALOG_ASSERT(parentBridge->parent() == 0 ||
+            LOG_ASSERT(parentBridge->parent() == 0 ||
                     bridge->parent() == parentBridge,
                     "Somehow this item has an incorrect parent");
             bridge->setParent(parentBridge);
         }
-        writeItem(vector, item);
-        writeChildrenRecursive(vector, item);
+        write_item(v, item);
+        write_children_recursive(v, item);
     }
 }
 
-bool readUnsigned(const char*& data, const char* end, unsigned& result, const char* dbgLabel = 0);
-bool readInt(const char*& data, const char* end, int& result, const char* dbgLabel = 0);
-bool readInt64(const char*& data, const char* end, int64_t& result, const char* dbgLabel = 0);
-bool readFloat(const char*& data, const char* end, float& result, const char* dbgLabel = 0);
-bool readBool(const char*& data, const char* end, bool& result, const char* dbgLabel = 0);
-bool readString(const char*& data, const char* end, String& result, const char* dbgLabel = 0);
-
-bool readUnsigned(const char*& data, const char* end, unsigned& result, const char* dbgLabel)
-{
-    // Check if we have enough data left to continue.
-    if ((end < data) || (static_cast<size_t>(end - data) < sizeof(unsigned))) {
-        ALOGW("\tNot enough data to read unsigned; tag=\"%s\" end=%p data=%p",
-              dbgLabel ? dbgLabel : "<no tag>", end, data);
-        return false;
-    }
-
-    memcpy(&result, data, sizeof(unsigned));
-    data += sizeof(unsigned);
-    if (dbgLabel)
-        ALOGV("Reading %-16s %u", dbgLabel, result);
-    return true;
-}
-
-bool readInt(const char*& data, const char* end, int& result, const char* dbgLabel)
-{
-    // Check if we have enough data left to continue.
-    if ((end < data) || (static_cast<size_t>(end - data) < sizeof(int))) {
-        ALOGW("Not enough data to read int; tag=\"%s\" end=%p data=%p",
-              dbgLabel ? dbgLabel : "<no tag>", end, data);
-        return false;
-    }
-
-    memcpy(&result, data, sizeof(int));
-    data += sizeof(int);
-    if (dbgLabel)
-        ALOGV("Reading %-16s %d", dbgLabel, result);
-    return true;
-}
-
-bool readInt64(const char*& data, const char* end, int64_t& result, const char* dbgLabel)
-{
-    // Check if we have enough data left to continue.
-    if ((end < data) || (static_cast<size_t>(end - data) < sizeof(int64_t))) {
-        ALOGW("Not enough data to read int64_t; tag=\"%s\" end=%p data=%p",
-              dbgLabel ? dbgLabel : "<no tag>", end, data);
-        return false;
-    }
-
-    memcpy(&result, data, sizeof(int64_t));
-    data += sizeof(int64_t);
-    if (dbgLabel)
-        ALOGV("Reading %-16s %ll", dbgLabel, result);
-    return true;
-}
-
-bool readFloat(const char*& data, const char* end, float& result, const char* dbgLabel)
-{
-    // Check if we have enough data left to continue.
-    if ((end < data) || (static_cast<size_t>(end - data) < sizeof(float))) {
-        ALOGW("Not enough data to read float; tag=\"%s\" end=%p data=%p",
-              dbgLabel ? dbgLabel : "<no tag>", end, data);
-        return false;
-    }
-
-    memcpy(&result, data, sizeof(float));
-    data += sizeof(float);
-    if (dbgLabel)
-        ALOGV("Reading %-16s %f", dbgLabel, result);
-    return true;
-}
-
-// Note that the return value indicates success or failure, while the result
-// parameter indicates the read value of the bool
-bool readBool(const char*& data, const char* end, bool& result, const char* dbgLabel)
-{
-    // Check if we have enough data left to continue.
-    if ((end < data) || (static_cast<size_t>(end - data) < sizeof(char))) {
-        ALOGW("Not enough data to read bool; tag=\"%s\" end=%p data=%p",
-              dbgLabel ? dbgLabel : "<no tag>", end, data);
-        return false;
-    }
-
-    char c;
-    memcpy(&c, data, sizeof(char));
-    data += sizeof(char);
-    if (dbgLabel)
-        ALOGV("Reading %-16s %d", dbgLabel, c);
-    result = c;
-
-    // Valid bool results are 0 or 1
-    if ((c != 0) && (c != 1)) {
-        ALOGW("Invalid value for bool; tag=\"%s\" end=%p data=%p c=%u",
-              dbgLabel ? dbgLabel : "<no tag>", end, data, c);
-        return false;
-    }
-
-    return true;
-}
-
-bool readString(const char*& data, const char* end, String& result, const char* dbgLabel)
-{
-    unsigned stringLength;
-    if (!readUnsigned(data, end, stringLength)) {
-        ALOGW("Not enough data to read string length; tag=\"%s\" end=%p data=%p",
-              dbgLabel ? dbgLabel : "<no tag>", end, data);
-        return false;
-    }
-
-    if (dbgLabel)
-        ALOGV("Reading %-16s %d %.*s", dbgLabel, stringLength, stringLength, data);
-
-    // If length was 0, there will be no string content, but still return true
-    if (!stringLength) {
-        result = String();
-        return true;
-    }
-
-    if ((end < data) || ((unsigned)(end - data) < stringLength)) {
-        ALOGW("Not enough data to read content; tag=\"%s\" end=%p data=%p stringLength=%u",
-              dbgLabel ? dbgLabel : "<no tag>", end, data, stringLength);
-        return false;
-    }
-
-    const unsigned MAX_REASONABLE_STRING_LENGTH = 10000;
-    if (stringLength > MAX_REASONABLE_STRING_LENGTH) {
-        ALOGW("String length is suspiciously large (>%d); tag=\"%s\" end=%p data=%p stringLength=%u",
-              MAX_REASONABLE_STRING_LENGTH, dbgLabel ? dbgLabel : "<no tag>",
-              end, data, stringLength);
-    }
-
-    bool decodeFailed = false;
-    static const WebCore::TextEncoding& encoding = WebCore::UTF8Encoding();
-    result = encoding.decode(data, stringLength, true, decodeFailed);
-    if (decodeFailed) {
-        ALOGW("Decode failed, tag=\"%s\" end=%p data=%p stringLength=%u content=\"%s\"",
-              dbgLabel ? dbgLabel : "<no tag>", end, data, stringLength,
-              result.utf8().data());
-        return false;
-    }
-
-    if (stringLength > MAX_REASONABLE_STRING_LENGTH) {
-        ALOGW("\tdecodeFailed=%d (flag is ignored) content=\"%s\"",
-              decodeFailed, result.utf8().data());
-    }
-
-    data += stringLength;
-    return true;
-}
-
-static bool readItemRecursive(WebCore::HistoryItem* newItem,
+static bool read_item_recursive(WebCore::HistoryItem* newItem,
         const char** pData, int length)
 {
-    if (!pData || length < HISTORY_MIN_SIZE) {
-        ALOGW("readItemRecursive() bad params; pData=%p length=%d", pData, length);
+    if (!pData || length < HISTORY_MIN_SIZE)
         return false;
-    }
 
+    const WebCore::TextEncoding& e = WebCore::UTF8Encoding();
     const char* data = *pData;
     const char* end = data + length;
-    String content;
+    int sizeofUnsigned = (int)sizeof(unsigned);
 
     // Read the original url
-    if (readString(data, end, content, "Original url"))
-        newItem->setOriginalURLString(content);
-    else
+    // Read the expected length of the string.
+    unsigned l;
+    memcpy(&l, data, sizeofUnsigned);
+    // Increment data pointer by the size of an unsigned int.
+    data += sizeofUnsigned;
+    if (l) {
+        LOGV("Original url    %d %.*s", l, l, data);
+        // If we have a length, check if that length exceeds the data length
+        // and return null if there is not enough data.
+        if (data + l < end)
+            newItem->setOriginalURLString(e.decode(data, l));
+        else
+            return false;
+        // Increment the data pointer by the length of the string.
+        data += l;
+    }
+    // Check if we have enough data left to continue.
+    if (end - data < sizeofUnsigned)
         return false;
 
     // Read the url
-    if (readString(data, end, content, "Url"))
-        newItem->setURLString(content);
-    else
+    memcpy(&l, data, sizeofUnsigned);
+    data += sizeofUnsigned;
+    if (l) {
+        LOGV("Url             %d %.*s", l, l, data);
+        if (data + l < end)
+            newItem->setURLString(e.decode(data, l));
+        else
+            return false;
+        data += l;
+    }
+    if (end - data < sizeofUnsigned)
         return false;
 
     // Read the title
-    if (readString(data, end, content, "Title"))
-        newItem->setTitle(content);
-    else
+    memcpy(&l, data, sizeofUnsigned);
+    data += sizeofUnsigned;
+    if (l) {
+        LOGV("Title           %d %.*s", l, l, data);
+        if (data + l < end)
+            newItem->setTitle(e.decode(data, l));
+        else
+            return false;
+        data += l;
+    }
+    if (end - data < sizeofUnsigned)
         return false;
 
     // Generate a new ResourceRequest object for populating form information.
-    // Read the form content type
     WTF::String formContentType;
-    if (!readString(data, end, formContentType, "Content type"))
-        return false;
+    WTF::PassRefPtr<WebCore::FormData> formData = NULL;
 
-    // Read the form data size
-    unsigned formDataSize;
-    if (!readUnsigned(data, end, formDataSize, "Form data size"))
+    // Read the form content type
+    memcpy(&l, data, sizeofUnsigned);
+    data += sizeofUnsigned;
+    if (l) {
+        LOGV("Content type    %d %.*s", l, l, data);
+        if (data + l < end)
+            formContentType = e.decode(data, l);
+        else
+            return false;
+        data += l;
+    }
+    if (end - data < sizeofUnsigned)
         return false;
 
     // Read the form data
-    WTF::RefPtr<WebCore::FormData> formData;
-    if (formDataSize) {
-        ALOGV("Reading Form data       %d %.*s", formDataSize, formDataSize, data);
-        if ((end < data) || ((size_t)(end - data) < formDataSize)) {
-            ALOGW("\tNot enough data to read form data; returning");
+    memcpy(&l, data, sizeofUnsigned);
+    data += sizeofUnsigned;
+    if (l) {
+        LOGV("Form data       %d %.*s", l, l, data);
+        if (data + l < end)
+            formData = WebCore::FormData::create(data, l);
+        else
             return false;
-        }
-        formData = WebCore::FormData::create(data, formDataSize);
-        data += formDataSize;
+        data += l;
         // Read the identifier
-        int64_t id;
-        if (!readInt64(data, end, id, "Form id"))
-            return false;
-        if (id)
-            formData->setIdentifier(id);
+        {
+            int64_t id;
+            int size = (int)sizeof(int64_t);
+            memcpy(&id, data, size);
+            data += size;
+            if (id)
+                formData->setIdentifier(id);
+        }
     }
+    if (end - data < sizeofUnsigned)
+        return false;
 
     // Set up the form info
     if (formData != NULL) {
@@ -764,76 +588,112 @@
     }
 
     // Read the target
-    if (readString(data, end, content, "Target"))
-        newItem->setTarget(content);
-    else
+    memcpy(&l, data, sizeofUnsigned);
+    data += sizeofUnsigned;
+    if (l) {
+        LOGV("Target          %d %.*s", l, l, data);
+        if (data + l < end)
+            newItem->setTarget(e.decode(data, l));
+        else
+            return false;
+        data += l;
+    }
+    if (end - data < sizeofUnsigned)
         return false;
 
     AndroidWebHistoryBridge* bridge = newItem->bridge();
-    ALOG_ASSERT(bridge, "There should be a bridge object during inflate");
-
-    // Read the screen scale
+    LOG_ASSERT(bridge, "There should be a bridge object during inflate");
     float fValue;
-    if (readFloat(data, end, fValue, "Screen scale"))
-        bridge->setScale(fValue);
-    else
-        return false;
+    // Read the screen scale
+    memcpy(&fValue, data, sizeof(float));
+    LOGV("Screen scale    %f", fValue);
+    bridge->setScale(fValue);
+    data += sizeof(float);
+    memcpy(&fValue, data, sizeofUnsigned);
+    LOGV("Text wrap scale    %f", fValue);
+    bridge->setTextWrapScale(fValue);
+    data += sizeof(float);
 
-    // Read the text wrap scale
-    if (readFloat(data, end, fValue, "Text wrap scale"))
-        bridge->setTextWrapScale(fValue);
-    else
+    if (end - data < sizeofUnsigned)
         return false;
 
     // Read scroll position.
-    int scrollX;
-    if (!readInt(data, end, scrollX, "Scroll pos x"))
-        return false;
-    int scrollY;
-    if (!readInt(data, end, scrollY, "Scroll pos y"))
-        return false;
+    int scrollX = 0;
+    memcpy(&scrollX, data, sizeofUnsigned);
+    data += sizeofUnsigned;
+    int scrollY = 0;
+    memcpy(&scrollY, data, sizeofUnsigned);
+    data += sizeofUnsigned;
     newItem->setScrollPoint(IntPoint(scrollX, scrollY));
 
-    // Read the document state
-    unsigned docStateCount;
-    if (!readUnsigned(data, end, docStateCount, "Doc state count"))
+    if (end - data < sizeofUnsigned)
         return false;
-    if (docStateCount) {
+
+    // Read the document state
+    memcpy(&l, data, sizeofUnsigned);
+    LOGV("Document state  %d", l);
+    data += sizeofUnsigned;
+    if (l) {
+        // Check if we have enough data to at least parse the sizes of each
+        // document state string.
+        if (data + l * sizeofUnsigned >= end)
+            return false;
         // Create a new vector and reserve enough space for the document state.
         WTF::Vector<WTF::String> docState;
-        docState.reserveCapacity(docStateCount);
-        while (docStateCount--) {
-            // Read a document state string
-            if (readString(data, end, content, "Document state"))
-                docState.append(content);
+        docState.reserveCapacity(l);
+        while (l--) {
+            // Check each time if we have enough to parse the length of the next
+            // string.
+            if (end - data < sizeofUnsigned)
+                return false;
+            int strLen;
+            memcpy(&strLen, data, sizeofUnsigned);
+            data += sizeofUnsigned;
+            if (data + strLen < end)
+                docState.append(e.decode(data, strLen));
             else
                 return false;
+            LOGV("\t\t%d %.*s", strLen, strLen, data);
+            data += strLen;
         }
         newItem->setDocumentState(docState);
     }
+    // Check if we have enough to read the next byte
+    if (data >= end)
+        return false;
 
     // Read is target item
-    bool c;
-    if (readBool(data, end, c, "Target item"))
-        newItem->setIsTargetItem(c);
-    else
+    // Cast the value to unsigned char in order to make a negative value larger
+    // than 1. A value that is not 0 or 1 is a failure.
+    unsigned char c = (unsigned char)data[0];
+    if (c > 1)
+        return false;
+    LOGV("Target item     %d", c);
+    newItem->setIsTargetItem((bool)c);
+    data++;
+    if (end - data < sizeofUnsigned)
         return false;
 
     // Read the child count
-    unsigned count;
-    if (!readUnsigned(data, end, count, "Child count"))
-        return false;
+    memcpy(&l, data, sizeofUnsigned);
+    LOGV("Child count     %d", l);
+    data += sizeofUnsigned;
     *pData = data;
-    if (count) {
-        while (count--) {
+    if (l) {
+        // Check if we have the minimum amount need to parse l children.
+        if (data + l * HISTORY_MIN_SIZE >= end)
+            return false;
+        while (l--) {
             // No need to check the length each time because read_item_recursive
             // will return null if there isn't enough data left to parse.
-            WTF::RefPtr<WebCore::HistoryItem> child = WebCore::HistoryItem::create();
+            WTF::PassRefPtr<WebCore::HistoryItem> child = WebCore::HistoryItem::create();
             // Set a bridge that will not call into java.
             child->setBridge(new WebHistoryItem(static_cast<WebHistoryItem*>(bridge)));
             // Read the child item.
-            if (!readItemRecursive(child.get(), pData, end - data))
+            if (!read_item_recursive(child.get(), pData, end - data)) {
+                child.clear();
                 return false;
+            }
             child->bridge()->setActive();
             newItem->addChildItem(child);
         }
@@ -849,86 +709,83 @@
 // main thread will be incorrect and an assert will fire later.
 // In conclusion, define UNIT_TEST only if you know what you are doing.
 #ifdef UNIT_TEST
-static void unitTest()
+static void unit_test()
 {
-    ALOGD("Entering history unit test!");
+    LOGD("Entering history unit test!");
     const char* test1 = new char[0];
     WTF::RefPtr<WebCore::HistoryItem> item = WebCore::HistoryItem::create();
     WebCore::HistoryItem* testItem = item.get();
     testItem->setBridge(new WebHistoryItem(0));
-    ALOG_ASSERT(!readItemRecursive(testItem, &test1, 0), "0 length array should fail!");
+    LOG_ASSERT(!read_item_recursive(testItem, &test1, 0), "0 length array should fail!");
     delete[] test1;
     const char* test2 = new char[2];
-    ALOG_ASSERT(!readItemRecursive(testItem, &test2, 2), "Small array should fail!");
+    LOG_ASSERT(!read_item_recursive(testItem, &test2, 2), "Small array should fail!");
     delete[] test2;
-    ALOG_ASSERT(!readItemRecursive(testItem, NULL, HISTORY_MIN_SIZE), "Null data should fail!");
+    LOG_ASSERT(!read_item_recursive(testItem, NULL, HISTORY_MIN_SIZE), "Null data should fail!");
     // Original Url
     char* test3 = new char[HISTORY_MIN_SIZE];
     const char* ptr = (const char*)test3;
     memset(test3, 0, HISTORY_MIN_SIZE);
     *(int*)test3 = 4000;
-    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length originalUrl should fail!");
+    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length originalUrl should fail!");
     // Url
     int offset = 4;
     memset(test3, 0, HISTORY_MIN_SIZE);
     ptr = (const char*)test3;
     *(int*)(test3 + offset) = 4000;
-    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length url should fail!");
+    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length url should fail!");
     // Title
     offset += 4;
     memset(test3, 0, HISTORY_MIN_SIZE);
     ptr = (const char*)test3;
     *(int*)(test3 + offset) = 4000;
-    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length title should fail!");
+    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length title should fail!");
     // Form content type
     offset += 4;
     memset(test3, 0, HISTORY_MIN_SIZE);
     ptr = (const char*)test3;
     *(int*)(test3 + offset) = 4000;
-    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length contentType should fail!");
+    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length contentType should fail!");
     // Form data
     offset += 4;
     memset(test3, 0, HISTORY_MIN_SIZE);
     ptr = (const char*)test3;
     *(int*)(test3 + offset) = 4000;
-    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length form data should fail!");
+    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length form data should fail!");
     // Target
     offset += 4;
     memset(test3, 0, HISTORY_MIN_SIZE);
     ptr = (const char*)test3;
     *(int*)(test3 + offset) = 4000;
-    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length target should fail!");
-    offset += 4; // Screen scale
-    offset += 4; // Text wrap scale
-    offset += 4; // Scroll pos x
-    offset += 4; // Scroll pos y
+    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length target should fail!");
+    offset += 4; // Scale
     // Document state 
     offset += 4;
     memset(test3, 0, HISTORY_MIN_SIZE);
     ptr = (const char*)test3;
     *(int*)(test3 + offset) = 4000;
-    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length document state should fail!");
+    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length document state should fail!");
     // Is target item
     offset += 1;
     memset(test3, 0, HISTORY_MIN_SIZE);
     ptr = (const char*)test3;
     *(char*)(test3 + offset) = '!';
-    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "IsTargetItem should fail with ! as the value!");
+    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "IsTargetItem should fail with ! as the value!");
     // Child count
     offset += 4;
     memset(test3, 0, HISTORY_MIN_SIZE);
     ptr = (const char*)test3;
     *(int*)(test3 + offset) = 4000;
-    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 kids should fail!");
+    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 kids should fail!");
+    offset = 36;
     // Test document state
-    offset = 40;
     delete[] test3;
     test3 = new char[HISTORY_MIN_SIZE + sizeof(unsigned)];
     memset(test3, 0, HISTORY_MIN_SIZE + sizeof(unsigned));
     ptr = (const char*)test3;
     *(int*)(test3 + offset) = 1;
     *(int*)(test3 + offset + 4) = 20;
-    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE + sizeof(unsigned)), "1 20 length document state string should fail!");
+    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE + sizeof(unsigned)), "1 20 length document state string should fail!");
     delete[] test3;
     test3 = new char[HISTORY_MIN_SIZE + 2 * sizeof(unsigned)];
     memset(test3, 0, HISTORY_MIN_SIZE + 2 * sizeof(unsigned));
@@ -936,9 +793,8 @@
     *(int*)(test3 + offset) = 2;
     *(int*)(test3 + offset + 4) = 0;
     *(int*)(test3 + offset + 8) = 20;
-    ALOG_ASSERT(!readItemRecursive(testItem, &ptr, HISTORY_MIN_SIZE + 2 * sizeof(unsigned) ), "2 20 length document state string should fail!");
+    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE + 2 * sizeof(unsigned) ), "2 20 length document state string should fail!");
     delete[] test3;
-    ALOGD("Leaving history unit test!");
 }
 #endif
 
@@ -953,22 +809,8 @@
 };
 
 static JNINativeMethod gWebHistoryItemMethods[] = {
-    { "inflate", "(I[B)I",
-        (void*) WebHistoryInflate },
-    { "nativeRef", "(I)V",
-        (void*) WebHistoryRef },
-    { "nativeUnref", "(I)V",
-        (void*) WebHistoryUnref },
-    { "nativeGetTitle", "(I)Ljava/lang/String;",
-        (void*) WebHistoryGetTitle },
-    { "nativeGetUrl", "(I)Ljava/lang/String;",
-        (void*) WebHistoryGetUrl },
-    { "nativeGetOriginalUrl", "(I)Ljava/lang/String;",
-        (void*) WebHistoryGetOriginalUrl },
-    { "nativeGetFlattenedData", "(I)[B",
-        (void*) WebHistoryGetFlattenedData },
-    { "nativeGetFavicon", "(I)Landroid/graphics/Bitmap;",
-        (void*) WebHistoryGetFavicon },
+    { "inflate", "(I[B)V",
+        (void*) WebHistoryInflate }
 };
 
 int registerWebHistory(JNIEnv* env)
@@ -976,27 +818,35 @@
     // Get notified of all changes to history items.
     WebCore::notifyHistoryItemChanged = historyItemChanged;
 #ifdef UNIT_TEST
-    unitTest();
+    unit_test();
 #endif
     // Find WebHistoryItem, its constructor, and the update method.
     jclass clazz = env->FindClass("android/webkit/WebHistoryItem");
-    ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebHistoryItem");
-    gWebHistoryItem.mInit = env->GetMethodID(clazz, "<init>", "(I)V");
-    ALOG_ASSERT(gWebHistoryItem.mInit, "Could not find WebHistoryItem constructor");
+    LOG_ASSERT(clazz, "Unable to find class android/webkit/WebHistoryItem");
+    gWebHistoryItem.mInit = env->GetMethodID(clazz, "<init>", "()V");
+    LOG_ASSERT(gWebHistoryItem.mInit, "Could not find WebHistoryItem constructor");
+    gWebHistoryItem.mUpdate = env->GetMethodID(clazz, "update",
+            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/graphics/Bitmap;[B)V");
+    LOG_ASSERT(gWebHistoryItem.mUpdate, "Could not find method update in WebHistoryItem");
 
+    // Find the field ids for mTitle and mUrl.
+    gWebHistoryItem.mTitle = env->GetFieldID(clazz, "mTitle", "Ljava/lang/String;");
+    LOG_ASSERT(gWebHistoryItem.mTitle, "Could not find field mTitle in WebHistoryItem");
+    gWebHistoryItem.mUrl = env->GetFieldID(clazz, "mUrl", "Ljava/lang/String;");
+    LOG_ASSERT(gWebHistoryItem.mUrl, "Could not find field mUrl in WebHistoryItem");
     env->DeleteLocalRef(clazz);
 
     // Find the WebBackForwardList object and method.
     clazz = env->FindClass("android/webkit/WebBackForwardList");
-    ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebBackForwardList");
+    LOG_ASSERT(clazz, "Unable to find class android/webkit/WebBackForwardList");
     gWebBackForwardList.mAddHistoryItem = env->GetMethodID(clazz, "addHistoryItem",
             "(Landroid/webkit/WebHistoryItem;)V");
-    ALOG_ASSERT(gWebBackForwardList.mAddHistoryItem, "Could not find method addHistoryItem");
+    LOG_ASSERT(gWebBackForwardList.mAddHistoryItem, "Could not find method addHistoryItem");
     gWebBackForwardList.mRemoveHistoryItem = env->GetMethodID(clazz, "removeHistoryItem",
             "(I)V");
-    ALOG_ASSERT(gWebBackForwardList.mRemoveHistoryItem, "Could not find method removeHistoryItem");
+    LOG_ASSERT(gWebBackForwardList.mRemoveHistoryItem, "Could not find method removeHistoryItem");
     gWebBackForwardList.mSetCurrentIndex = env->GetMethodID(clazz, "setCurrentIndex", "(I)V");
-    ALOG_ASSERT(gWebBackForwardList.mSetCurrentIndex, "Could not find method setCurrentIndex");
+    LOG_ASSERT(gWebBackForwardList.mSetCurrentIndex, "Could not find method setCurrentIndex");
     env->DeleteLocalRef(clazz);
 
     int result = jniRegisterNativeMethods(env, "android/webkit/WebBackForwardList",
diff --git a/Source/WebKit/android/jni/WebHistory.h b/Source/WebKit/android/jni/WebHistory.h
index e89959c..fc0b340 100644
--- a/Source/WebKit/android/jni/WebHistory.h
+++ b/Source/WebKit/android/jni/WebHistory.h
@@ -28,12 +28,8 @@
 
 #include "AndroidWebHistoryBridge.h"
 
-#include "PlatformString.h"
-#include "SkBitmap.h"
-
 #include <jni.h>
 #include <wtf/RefCounted.h>
-#include <wtf/Threading.h>
 #include <wtf/Vector.h>
 
 namespace android {
@@ -42,7 +38,7 @@
 
 class WebHistory {
 public:
-    static void Flatten(JNIEnv*, WTF::Vector<char>&, WebCore::HistoryItem*);
+    static jbyteArray Flatten(JNIEnv*, WTF::Vector<char>&, WebCore::HistoryItem*);
     static void AddItem(const AutoJObject&, WebCore::HistoryItem*);
     static void RemoveItem(const AutoJObject&, int);
     static void UpdateHistoryIndex(const AutoJObject&, int);
@@ -55,36 +51,16 @@
 public:
     WebHistoryItem(WebHistoryItem* parent)
         : WebCore::AndroidWebHistoryBridge(0)
-        , m_favicon(0)
-        , m_faviconCached(0)
-        , m_dataCached(0)
         , m_parent(parent)
-    {}
-    WebHistoryItem(WebCore::HistoryItem* item)
-        : WebCore::AndroidWebHistoryBridge(item)
-        , m_favicon(0)
-        , m_faviconCached(0)
-        , m_dataCached(0)
-        , m_parent(0)
-    {}
+        , m_object(NULL) { }
+    WebHistoryItem(JNIEnv*, jobject, WebCore::HistoryItem*);
     ~WebHistoryItem();
     void updateHistoryItem(WebCore::HistoryItem* item);
     void setParent(WebHistoryItem* parent) { m_parent = parent; }
     WebHistoryItem* parent() const { return m_parent.get(); }
-
-    // TODO: This is ugly. Really the whole bindings of WebHistoryItem needs to be
-    // cleaned up, but this will do for now
-    WTF::Mutex m_lock;
-    String m_url;
-    String m_originalUrl;
-    String m_title;
-    SkBitmap* m_favicon;
-    WTF::Vector<char> m_data;
-    jobject m_faviconCached;
-    jobject m_dataCached;
-
 private:
     RefPtr<WebHistoryItem> m_parent;
+    jweak m_object;
 };
 
 };
diff --git a/Source/WebKit/android/jni/WebIconDatabase.cpp b/Source/WebKit/android/jni/WebIconDatabase.cpp
index e9219df..d5f8947 100644
--- a/Source/WebKit/android/jni/WebIconDatabase.cpp
+++ b/Source/WebKit/android/jni/WebIconDatabase.cpp
@@ -50,31 +50,18 @@
 
 namespace android {
 
-SkBitmap* webcoreImageToSkBitmap(WebCore::Image* icon)
-{
-    if (!icon)
-        return 0;
-    WebCore::SharedBuffer* buffer = icon->data();
-    if (!buffer)
-        return 0;
-    SkBitmap* bm = new SkBitmap;
-    if (!SkImageDecoder::DecodeMemory(buffer->data(), buffer->size(), bm,
-                                      SkBitmap::kNo_Config,
-                                      SkImageDecoder::kDecodePixels_Mode)
-            || bm->isNull() || !bm->width() || !bm->height()
-            || bm->config() == SkBitmap::kNo_Config) {
-        delete bm;
-        return 0;
-    }
-    return bm;
-}
-
 jobject webcoreImageToJavaBitmap(JNIEnv* env, WebCore::Image* icon)
 {
-    SkBitmap* bm = webcoreImageToSkBitmap(icon);
-    if (!bm)
-        return 0;
-    return GraphicsJNI::createBitmap(env, bm, false, NULL);
+    if (!icon)
+        return NULL;
+    SkBitmap bm;
+    WebCore::SharedBuffer* buffer = icon->data();
+    if (!buffer || !SkImageDecoder::DecodeMemory(buffer->data(), buffer->size(),
+                                                 &bm, SkBitmap::kNo_Config,
+                                            SkImageDecoder::kDecodePixels_Mode))
+        return NULL;
+
+    return GraphicsJNI::createBitmap(env, new SkBitmap(bm), false, NULL);
 }
 
 static WebIconDatabase* gIconDatabaseClient = new WebIconDatabase();
@@ -181,7 +168,7 @@
         return;
     iconDb.setEnabled(true);
     iconDb.setClient(gIconDatabaseClient);
-    ALOG_ASSERT(path, "No path given to nativeOpen");
+    LOG_ASSERT(path, "No path given to nativeOpen");
     WTF::String pathStr = jstringToWtfString(env, path);
     WTF::CString fullPath = WebCore::pathByAppendingComponent(pathStr,
             WebCore::IconDatabase::defaultDatabaseFilename()).utf8();
@@ -198,12 +185,12 @@
         }
     }
     if (didSetPermissions) {
-        ALOGV("Opening WebIconDatabase file '%s'", pathStr.latin1().data());
+        LOGV("Opening WebIconDatabase file '%s'", pathStr.latin1().data());
         bool res = iconDb.open(pathStr, WebCore::IconDatabase::defaultDatabaseFilename());
         if (!res)
-            ALOGE("Open failed!");
+            LOGE("Open failed!");
     } else
-        ALOGE("Failed to set permissions on '%s'", fullPath.data());
+        LOGE("Failed to set permissions on '%s'", fullPath.data());
 }
 
 static void Close(JNIEnv* env, jobject obj)
@@ -213,37 +200,37 @@
 
 static void RemoveAllIcons(JNIEnv* env, jobject obj)
 {
-    ALOGV("Removing all icons");
+    LOGV("Removing all icons");
     WebCore::iconDatabase().removeAllIcons();
 }
 
 static jobject IconForPageUrl(JNIEnv* env, jobject obj, jstring url)
 {
-    ALOG_ASSERT(url, "No url given to iconForPageUrl");
+    LOG_ASSERT(url, "No url given to iconForPageUrl");
     WTF::String urlStr = jstringToWtfString(env, url);
 
     // FIXME: This method should not be used from outside WebCore and will be removed.
     // http://trac.webkit.org/changeset/81484
     WebCore::Image* icon = WebCore::iconDatabase().synchronousIconForPageURL(urlStr, WebCore::IntSize(16, 16));
-    ALOGV("Retrieving icon for '%s' %p", urlStr.latin1().data(), icon);
+    LOGV("Retrieving icon for '%s' %p", urlStr.latin1().data(), icon);
     return webcoreImageToJavaBitmap(env, icon);
 }
 
 static void RetainIconForPageUrl(JNIEnv* env, jobject obj, jstring url)
 {
-    ALOG_ASSERT(url, "No url given to retainIconForPageUrl");
+    LOG_ASSERT(url, "No url given to retainIconForPageUrl");
     WTF::String urlStr = jstringToWtfString(env, url);
 
-    ALOGV("Retaining icon for '%s'", urlStr.latin1().data());
+    LOGV("Retaining icon for '%s'", urlStr.latin1().data());
     WebCore::iconDatabase().retainIconForPageURL(urlStr);
 }
 
 static void ReleaseIconForPageUrl(JNIEnv* env, jobject obj, jstring url)
 {
-    ALOG_ASSERT(url, "No url given to releaseIconForPageUrl");
+    LOG_ASSERT(url, "No url given to releaseIconForPageUrl");
     WTF::String urlStr = jstringToWtfString(env, url);
 
-    ALOGV("Releasing icon for '%s'", urlStr.latin1().data());
+    LOGV("Releasing icon for '%s'", urlStr.latin1().data());
     WebCore::iconDatabase().releaseIconForPageURL(urlStr);
 }
 
@@ -268,12 +255,12 @@
 int registerWebIconDatabase(JNIEnv* env)
 {
 #ifndef NDEBUG
-    jclass webIconDatabase = env->FindClass("android/webkit/WebIconDatabaseClassic");
-    ALOG_ASSERT(webIconDatabase, "Unable to find class android.webkit.WebIconDatabaseClassic");
+    jclass webIconDatabase = env->FindClass("android/webkit/WebIconDatabase");
+    LOG_ASSERT(webIconDatabase, "Unable to find class android.webkit.WebIconDatabase");
     env->DeleteLocalRef(webIconDatabase);
 #endif
 
-    return jniRegisterNativeMethods(env, "android/webkit/WebIconDatabaseClassic",
+    return jniRegisterNativeMethods(env, "android/webkit/WebIconDatabase",
             gWebIconDatabaseMethods, NELEM(gWebIconDatabaseMethods));
 }
 
diff --git a/Source/WebKit/android/jni/WebIconDatabase.h b/Source/WebKit/android/jni/WebIconDatabase.h
index 7b7c937..3011b9f 100644
--- a/Source/WebKit/android/jni/WebIconDatabase.h
+++ b/Source/WebKit/android/jni/WebIconDatabase.h
@@ -28,7 +28,6 @@
 
 #include "IconDatabaseClient.h"
 #include "PlatformString.h"
-#include "SkBitmap.h"
 #include "utils/threads.h"
 #include <jni.h>
 #include <wtf/Vector.h>
@@ -74,7 +73,6 @@
         bool                    mDeliveryRequested;
     };
 
-    SkBitmap* webcoreImageToSkBitmap(WebCore::Image* icon);
     jobject webcoreImageToJavaBitmap(JNIEnv* env, WebCore::Image* icon);
 
 };
diff --git a/Source/WebKit/android/jni/WebSettings.cpp b/Source/WebKit/android/jni/WebSettings.cpp
index 467da3d..dd847e8 100644
--- a/Source/WebKit/android/jni/WebSettings.cpp
+++ b/Source/WebKit/android/jni/WebSettings.cpp
@@ -49,7 +49,9 @@
 #include "Settings.h"
 #include "WebCoreFrameBridge.h"
 #include "WebCoreJni.h"
+#if USE(V8)
 #include "WorkerContextExecutionProxy.h"
+#endif
 #include "WebRequestContext.h"
 #include "WebViewCore.h"
 
@@ -120,9 +122,6 @@
         mGeolocationEnabled = env->GetFieldID(clazz, "mGeolocationEnabled", "Z");
         mGeolocationDatabasePath = env->GetFieldID(clazz, "mGeolocationDatabasePath", "Ljava/lang/String;");
         mXSSAuditorEnabled = env->GetFieldID(clazz, "mXSSAuditorEnabled", "Z");
-#if ENABLE(LINK_PREFETCH)
-        mLinkPrefetchEnabled = env->GetFieldID(clazz, "mLinkPrefetchEnabled", "Z");
-#endif
         mJavaScriptCanOpenWindowsAutomatically = env->GetFieldID(clazz,
                 "mJavaScriptCanOpenWindowsAutomatically", "Z");
         mUseWideViewport = env->GetFieldID(clazz, "mUseWideViewport", "Z");
@@ -135,8 +134,8 @@
         mPageCacheCapacity = env->GetFieldID(clazz, "mPageCacheCapacity", "I");
 #if ENABLE(WEB_AUTOFILL)
         mAutoFillEnabled = env->GetFieldID(clazz, "mAutoFillEnabled", "Z");
-        mAutoFillProfile = env->GetFieldID(clazz, "mAutoFillProfile", "Landroid/webkit/WebSettingsClassic$AutoFillProfile;");
-        jclass autoFillProfileClass = env->FindClass("android/webkit/WebSettingsClassic$AutoFillProfile");
+        mAutoFillProfile = env->GetFieldID(clazz, "mAutoFillProfile", "Landroid/webkit/WebSettings$AutoFillProfile;");
+        jclass autoFillProfileClass = env->FindClass("android/webkit/WebSettings$AutoFillProfile");
         mAutoFillProfileFullName = env->GetFieldID(autoFillProfileClass, "mFullName", "Ljava/lang/String;");
         mAutoFillProfileEmailAddress = env->GetFieldID(autoFillProfileClass, "mEmailAddress", "Ljava/lang/String;");
         mAutoFillProfileCompanyName = env->GetFieldID(autoFillProfileClass, "mCompanyName", "Ljava/lang/String;");
@@ -149,57 +148,57 @@
         mAutoFillProfilePhoneNumber = env->GetFieldID(autoFillProfileClass, "mPhoneNumber", "Ljava/lang/String;");
         env->DeleteLocalRef(autoFillProfileClass);
 #endif
+#if USE(CHROME_NETWORK_STACK)
         mOverrideCacheMode = env->GetFieldID(clazz, "mOverrideCacheMode", "I");
-        mPasswordEchoEnabled = env->GetFieldID(clazz, "mPasswordEchoEnabled", "Z");
-
-        ALOG_ASSERT(mLayoutAlgorithm, "Could not find field mLayoutAlgorithm");
-        ALOG_ASSERT(mTextSize, "Could not find field mTextSize");
-        ALOG_ASSERT(mStandardFontFamily, "Could not find field mStandardFontFamily");
-        ALOG_ASSERT(mFixedFontFamily, "Could not find field mFixedFontFamily");
-        ALOG_ASSERT(mSansSerifFontFamily, "Could not find field mSansSerifFontFamily");
-        ALOG_ASSERT(mSerifFontFamily, "Could not find field mSerifFontFamily");
-        ALOG_ASSERT(mCursiveFontFamily, "Could not find field mCursiveFontFamily");
-        ALOG_ASSERT(mFantasyFontFamily, "Could not find field mFantasyFontFamily");
-        ALOG_ASSERT(mDefaultTextEncoding, "Could not find field mDefaultTextEncoding");
-        ALOG_ASSERT(mGetUserAgentString, "Could not find method getUserAgentString");
-        ALOG_ASSERT(mGetAcceptLanguage, "Could not find method getAcceptLanguage");
-        ALOG_ASSERT(mMinimumFontSize, "Could not find field mMinimumFontSize");
-        ALOG_ASSERT(mMinimumLogicalFontSize, "Could not find field mMinimumLogicalFontSize");
-        ALOG_ASSERT(mDefaultFontSize, "Could not find field mDefaultFontSize");
-        ALOG_ASSERT(mDefaultFixedFontSize, "Could not find field mDefaultFixedFontSize");
-        ALOG_ASSERT(mLoadsImagesAutomatically, "Could not find field mLoadsImagesAutomatically");
-#ifdef ANDROID_BLOCK_NETWORK_IMAGE
-        ALOG_ASSERT(mBlockNetworkImage, "Could not find field mBlockNetworkImage");
 #endif
-        ALOG_ASSERT(mBlockNetworkLoads, "Could not find field mBlockNetworkLoads");
-        ALOG_ASSERT(mJavaScriptEnabled, "Could not find field mJavaScriptEnabled");
-        ALOG_ASSERT(mAllowUniversalAccessFromFileURLs,
+
+        LOG_ASSERT(mLayoutAlgorithm, "Could not find field mLayoutAlgorithm");
+        LOG_ASSERT(mTextSize, "Could not find field mTextSize");
+        LOG_ASSERT(mStandardFontFamily, "Could not find field mStandardFontFamily");
+        LOG_ASSERT(mFixedFontFamily, "Could not find field mFixedFontFamily");
+        LOG_ASSERT(mSansSerifFontFamily, "Could not find field mSansSerifFontFamily");
+        LOG_ASSERT(mSerifFontFamily, "Could not find field mSerifFontFamily");
+        LOG_ASSERT(mCursiveFontFamily, "Could not find field mCursiveFontFamily");
+        LOG_ASSERT(mFantasyFontFamily, "Could not find field mFantasyFontFamily");
+        LOG_ASSERT(mDefaultTextEncoding, "Could not find field mDefaultTextEncoding");
+        LOG_ASSERT(mGetUserAgentString, "Could not find method getUserAgentString");
+        LOG_ASSERT(mGetAcceptLanguage, "Could not find method getAcceptLanguage");
+        LOG_ASSERT(mMinimumFontSize, "Could not find field mMinimumFontSize");
+        LOG_ASSERT(mMinimumLogicalFontSize, "Could not find field mMinimumLogicalFontSize");
+        LOG_ASSERT(mDefaultFontSize, "Could not find field mDefaultFontSize");
+        LOG_ASSERT(mDefaultFixedFontSize, "Could not find field mDefaultFixedFontSize");
+        LOG_ASSERT(mLoadsImagesAutomatically, "Could not find field mLoadsImagesAutomatically");
+#ifdef ANDROID_BLOCK_NETWORK_IMAGE
+        LOG_ASSERT(mBlockNetworkImage, "Could not find field mBlockNetworkImage");
+#endif
+        LOG_ASSERT(mBlockNetworkLoads, "Could not find field mBlockNetworkLoads");
+        LOG_ASSERT(mJavaScriptEnabled, "Could not find field mJavaScriptEnabled");
+        LOG_ASSERT(mAllowUniversalAccessFromFileURLs,
                     "Could not find field mAllowUniversalAccessFromFileURLs");
-        ALOG_ASSERT(mAllowFileAccessFromFileURLs,
+        LOG_ASSERT(mAllowFileAccessFromFileURLs,
                     "Could not find field mAllowFileAccessFromFileURLs");
-        ALOG_ASSERT(mPluginState, "Could not find field mPluginState");
+        LOG_ASSERT(mPluginState, "Could not find field mPluginState");
 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
-        ALOG_ASSERT(mAppCacheEnabled, "Could not find field mAppCacheEnabled");
-        ALOG_ASSERT(mAppCachePath, "Could not find field mAppCachePath");
-        ALOG_ASSERT(mAppCacheMaxSize, "Could not find field mAppCacheMaxSize");
+        LOG_ASSERT(mAppCacheEnabled, "Could not find field mAppCacheEnabled");
+        LOG_ASSERT(mAppCachePath, "Could not find field mAppCachePath");
+        LOG_ASSERT(mAppCacheMaxSize, "Could not find field mAppCacheMaxSize");
 #endif
 #if ENABLE(WORKERS)
-        ALOG_ASSERT(mWorkersEnabled, "Could not find field mWorkersEnabled");
+        LOG_ASSERT(mWorkersEnabled, "Could not find field mWorkersEnabled");
 #endif
-        ALOG_ASSERT(mJavaScriptCanOpenWindowsAutomatically,
+        LOG_ASSERT(mJavaScriptCanOpenWindowsAutomatically,
                 "Could not find field mJavaScriptCanOpenWindowsAutomatically");
-        ALOG_ASSERT(mUseWideViewport, "Could not find field mUseWideViewport");
-        ALOG_ASSERT(mSupportMultipleWindows, "Could not find field mSupportMultipleWindows");
-        ALOG_ASSERT(mShrinksStandaloneImagesToFit, "Could not find field mShrinksStandaloneImagesToFit");
-        ALOG_ASSERT(mMaximumDecodedImageSize, "Could not find field mMaximumDecodedImageSize");
-        ALOG_ASSERT(mUseDoubleTree, "Could not find field mUseDoubleTree");
-        ALOG_ASSERT(mPageCacheCapacity, "Could not find field mPageCacheCapacity");
-        ALOG_ASSERT(mPasswordEchoEnabled, "Could not find field mPasswordEchoEnabled");
+        LOG_ASSERT(mUseWideViewport, "Could not find field mUseWideViewport");
+        LOG_ASSERT(mSupportMultipleWindows, "Could not find field mSupportMultipleWindows");
+        LOG_ASSERT(mShrinksStandaloneImagesToFit, "Could not find field mShrinksStandaloneImagesToFit");
+        LOG_ASSERT(mMaximumDecodedImageSize, "Could not find field mMaximumDecodedImageSize");
+        LOG_ASSERT(mUseDoubleTree, "Could not find field mUseDoubleTree");
+        LOG_ASSERT(mPageCacheCapacity, "Could not find field mPageCacheCapacity");
 
         jclass enumClass = env->FindClass("java/lang/Enum");
-        ALOG_ASSERT(enumClass, "Could not find Enum class!");
+        LOG_ASSERT(enumClass, "Could not find Enum class!");
         mOrdinal = env->GetMethodID(enumClass, "ordinal", "()I");
-        ALOG_ASSERT(mOrdinal, "Could not find method ordinal");
+        LOG_ASSERT(mOrdinal, "Could not find method ordinal");
         env->DeleteLocalRef(enumClass);
     }
 
@@ -258,9 +257,6 @@
     jfieldID mGeolocationEnabled;
     jfieldID mGeolocationDatabasePath;
     jfieldID mXSSAuditorEnabled;
-#if ENABLE(LINK_PREFETCH)
-    jfieldID mLinkPrefetchEnabled;
-#endif
 #if ENABLE(DATABASE) || ENABLE(DOM_STORAGE)
     jfieldID mDatabasePath;
     jfieldID mDatabasePathHasBeenSet;
@@ -279,8 +275,9 @@
     jfieldID mAutoFillProfileCountry;
     jfieldID mAutoFillProfilePhoneNumber;
 #endif
+#if USE(CHROME_NETWORK_STACK)
     jfieldID mOverrideCacheMode;
-    jfieldID mPasswordEchoEnabled;
+#endif
 };
 
 static struct FieldIds* gFieldIds;
@@ -326,7 +323,7 @@
     static void Sync(JNIEnv* env, jobject obj, jint frame)
     {
         WebCore::Frame* pFrame = (WebCore::Frame*)frame;
-        ALOG_ASSERT(pFrame, "%s must take a valid frame pointer!", __FUNCTION__);
+        LOG_ASSERT(pFrame, "%s must take a valid frame pointer!", __FUNCTION__);
         WebCore::Settings* s = pFrame->settings();
         if (!s)
             return;
@@ -342,7 +339,7 @@
                 pFrame->document()->styleSelectorChanged(WebCore::RecalcStyleImmediately);
                 if (pFrame->document()->renderer()) {
                     recursiveCleanupForFullLayout(pFrame->document()->renderer());
-                    ALOG_ASSERT(pFrame->view(), "No view for this frame when trying to relayout");
+                    LOG_ASSERT(pFrame->view(), "No view for this frame when trying to relayout");
                     pFrame->view()->layout();
                     // FIXME: This call used to scroll the page to put the focus into view.
                     // It worked on the WebViewCore, but now scrolling is done outside of the
@@ -380,6 +377,7 @@
 
         str = (jstring)env->CallObjectMethod(obj, gFieldIds->mGetUserAgentString);
         WebFrame::getWebFrame(pFrame)->setUserAgent(jstringToWtfString(env, str));
+#if USE(CHROME_NETWORK_STACK)
         WebViewCore::getWebViewCore(pFrame->view())->setWebRequestContextUserAgent();
 
         jint cacheMode = env->GetIntField(obj, gFieldIds->mOverrideCacheMode);
@@ -387,6 +385,7 @@
 
         str = (jstring)env->CallObjectMethod(obj, gFieldIds->mGetAcceptLanguage);
         WebRequestContext::setAcceptLanguage(jstringToWtfString(env, str));
+#endif
 
         jint size = env->GetIntField(obj, gFieldIds->mMinimumFontSize);
         s->setMinimumFontSize(size);
@@ -424,11 +423,6 @@
         flag = env->GetBooleanField(obj, gFieldIds->mAllowFileAccessFromFileURLs);
         s->setAllowFileAccessFromFileURLs(flag);
 
-        // Hyperlink auditing (the ping attribute) has similar privacy
-        // considerations as does the running of JavaScript, so to keep the UI
-        // simpler, we leverage the same setting.
-        s->setHyperlinkAuditingEnabled(flag);
-
         // ON = 0
         // ON_DEMAND = 1
         // OFF = 2
@@ -440,38 +434,22 @@
 #endif
 
 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
-        // We only enable AppCache if it's been enabled with a call to
-        // setAppCacheEnabled() and if a valid path has been supplied to
-        // setAppCachePath(). Note that the path is applied to all WebViews
-        // whereas enabling is applied per WebView.
-
-        // WebCore asserts that the path is only set once. Since the path is
-        // shared between WebViews, we can't do the required checks to guard
-        // against this in the Java WebSettings.
-        bool isPathValid = false;
-        if (cacheStorage().cacheDirectory().isNull()) {
-            str = static_cast<jstring>(env->GetObjectField(obj, gFieldIds->mAppCachePath));
-            // Check for non-null string as an optimization, as this is the common case.
-            if (str) {
-                String path = jstringToWtfString(env, str);
-                ALOG_ASSERT(!path.empty(), "Java side should never send empty string for AppCache path");
+        flag = env->GetBooleanField(obj, gFieldIds->mAppCacheEnabled);
+        s->setOfflineWebApplicationCacheEnabled(flag);
+        str = (jstring)env->GetObjectField(obj, gFieldIds->mAppCachePath);
+        if (str) {
+            String path = jstringToWtfString(env, str);
+            if (path.length() && cacheStorage().cacheDirectory().isNull()) {
+                cacheStorage().setCacheDirectory(path);
                 // This database is created on the first load. If the file
                 // doesn't exist, we create it and set its permissions. The
                 // filename must match that in ApplicationCacheStorage.cpp.
                 String filename = pathByAppendingComponent(path, "ApplicationCache.db");
-                int fd = open(filename.utf8().data(), O_CREAT, permissionFlags660);
-                if (fd >= 0) {
+                int fd = open(filename.utf8().data(), O_CREAT | O_EXCL, permissionFlags660);
+                if (fd >= 0)
                     close(fd);
-                    cacheStorage().setCacheDirectory(path);
-                    isPathValid = true;
-              }
             }
-        } else
-            isPathValid = true;
-
-        flag = env->GetBooleanField(obj, gFieldIds->mAppCacheEnabled);
-        s->setOfflineWebApplicationCacheEnabled(flag && isPathValid);
-
+        }
         jlong maxsize = env->GetLongField(obj, gFieldIds->mAppCacheMaxSize);
         cacheStorage().setMaximumSize(maxsize);
 #endif
@@ -569,11 +547,6 @@
         flag = env->GetBooleanField(obj, gFieldIds->mXSSAuditorEnabled);
         s->setXSSAuditorEnabled(flag);
 
-#if ENABLE(LINK_PREFETCH)
-        flag = env->GetBooleanField(obj, gFieldIds->mLinkPrefetchEnabled);
-        s->setLinkPrefetchEnabled(flag);
-#endif
-
         size = env->GetIntField(obj, gFieldIds->mPageCacheCapacity);
         if (size > 0) {
             s->setUsesPageCache(true);
@@ -612,10 +585,6 @@
         // This is required to enable the XMLTreeViewer when loading an XML document that
         // has no style attached to it. http://trac.webkit.org/changeset/79799
         s->setDeveloperExtrasEnabled(true);
-        s->setSpatialNavigationEnabled(true);
-        bool echoPassword = env->GetBooleanField(obj,
-                gFieldIds->mPasswordEchoEnabled);
-        s->setPasswordEchoEnabled(echoPassword);
     }
 };
 
@@ -631,11 +600,11 @@
 
 int registerWebSettings(JNIEnv* env)
 {
-    jclass clazz = env->FindClass("android/webkit/WebSettingsClassic");
-    ALOG_ASSERT(clazz, "Unable to find class WebSettingsClassic!");
+    jclass clazz = env->FindClass("android/webkit/WebSettings");
+    LOG_ASSERT(clazz, "Unable to find class WebSettings!");
     gFieldIds = new FieldIds(env, clazz);
     env->DeleteLocalRef(clazz);
-    return jniRegisterNativeMethods(env, "android/webkit/WebSettingsClassic",
+    return jniRegisterNativeMethods(env, "android/webkit/WebSettings",
             gWebSettingsMethods, NELEM(gWebSettingsMethods));
 }
 
diff --git a/Source/WebKit/android/jni/WebStorage.cpp b/Source/WebKit/android/jni/WebStorage.cpp
index 66a3517..9ce207d 100644
--- a/Source/WebKit/android/jni/WebStorage.cpp
+++ b/Source/WebKit/android/jni/WebStorage.cpp
@@ -174,12 +174,12 @@
 int registerWebStorage(JNIEnv* env)
 {
 #ifndef NDEBUG
-    jclass webStorage = env->FindClass("android/webkit/WebStorageClassic");
-    ALOG_ASSERT(webStorage, "Unable to find class android.webkit.WebStorageClassic");
+    jclass webStorage = env->FindClass("android/webkit/WebStorage");
+    LOG_ASSERT(webStorage, "Unable to find class android.webkit.WebStorage");
     env->DeleteLocalRef(webStorage);
 #endif
 
-    return jniRegisterNativeMethods(env, "android/webkit/WebStorageClassic",
+    return jniRegisterNativeMethods(env, "android/webkit/WebStorage",
             gWebStorageMethods, NELEM(gWebStorageMethods));
 }
 
diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp
index f17e573..1b53a6e 100644
--- a/Source/WebKit/android/jni/WebViewCore.cpp
+++ b/Source/WebKit/android/jni/WebViewCore.cpp
@@ -29,9 +29,10 @@
 #include "WebViewCore.h"
 
 #include "AccessibilityObject.h"
-#include "AndroidHitTestResult.h"
 #include "Attribute.h"
-#include "content/address_detector.h"
+#include "BaseLayerAndroid.h"
+#include "CachedNode.h"
+#include "CachedRoot.h"
 #include "Chrome.h"
 #include "ChromeClientAndroid.h"
 #include "ChromiumIncludes.h"
@@ -42,7 +43,6 @@
 #include "CSSValueKeywords.h"
 #include "DatabaseTracker.h"
 #include "Document.h"
-#include "DocumentMarkerController.h"
 #include "DOMWindow.h"
 #include "DOMSelection.h"
 #include "Element.h"
@@ -53,7 +53,6 @@
 #include "ExceptionCode.h"
 #include "FocusController.h"
 #include "Font.h"
-#include "FontCache.h"
 #include "Frame.h"
 #include "FrameLoader.h"
 #include "FrameLoaderClientAndroid.h"
@@ -62,7 +61,6 @@
 #include "Geolocation.h"
 #include "GraphicsContext.h"
 #include "GraphicsJNI.h"
-#include "GraphicsOperationCollection.h"
 #include "HTMLAnchorElement.h"
 #include "HTMLAreaElement.h"
 #include "HTMLElement.h"
@@ -80,7 +78,6 @@
 #include "HitTestRequest.h"
 #include "HitTestResult.h"
 #include "InlineTextBox.h"
-#include "KeyboardEvent.h"
 #include "MemoryUsage.h"
 #include "NamedNodeMap.h"
 #include "Navigator.h"
@@ -88,8 +85,6 @@
 #include "NodeList.h"
 #include "Page.h"
 #include "PageGroup.h"
-#include "PictureLayerContent.h"
-#include "PicturePileLayerContent.h"
 #include "PlatformKeyboardEvent.h"
 #include "PlatformString.h"
 #include "PluginWidgetAndroid.h"
@@ -98,7 +93,6 @@
 #include "ProgressTracker.h"
 #include "Range.h"
 #include "RenderBox.h"
-#include "RenderImage.h"
 #include "RenderInline.h"
 #include "RenderLayer.h"
 #include "RenderPart.h"
@@ -109,44 +103,39 @@
 #include "ResourceRequest.h"
 #include "RuntimeEnabledFeatures.h"
 #include "SchemeRegistry.h"
-#include "ScopedLocalRef.h"
-#include "ScriptController.h"
 #include "SelectionController.h"
-#include "SelectText.h"
 #include "Settings.h"
 #include "SkANP.h"
 #include "SkTemplates.h"
 #include "SkTDArray.h"
 #include "SkTypes.h"
 #include "SkCanvas.h"
-#include "SkGraphics.h"
 #include "SkPicture.h"
 #include "SkUtils.h"
 #include "Text.h"
-#include "TextIterator.h"
-#include "TilesManager.h"
 #include "TypingCommand.h"
 #include "WebCache.h"
 #include "WebCoreFrameBridge.h"
-#include "WebCoreJni.h"
 #include "WebFrameView.h"
 #include "WindowsKeyboardCodes.h"
 #include "android_graphics.h"
 #include "autofill/WebAutofill.h"
 #include "htmlediting.h"
 #include "markup.h"
-#include "visible_units.h"
 
 #include <JNIHelp.h>
 #include <JNIUtility.h>
-#include <androidfw/KeycodeLabels.h>
-#include <cutils/properties.h>
-#include <v8.h>
+#include <ui/KeycodeLabels.h>
 #include <wtf/CurrentTime.h>
 #include <wtf/text/AtomicString.h>
-#include <wtf/text/CString.h>
 #include <wtf/text/StringImpl.h>
 
+#if USE(V8)
+#include "ScriptController.h"
+#include "V8Counters.h"
+#include <wtf/text/CString.h>
+#endif
+
 #if DEBUG_NAV_UI
 #include "SkTime.h"
 #endif
@@ -164,85 +153,34 @@
 FILE* gRenderTreeFile = 0;
 #endif
 
-#include "BaseLayerAndroid.h"
+#ifdef ANDROID_INSTRUMENT
+#include "TimeCounter.h"
+#endif
 
 #if USE(ACCELERATED_COMPOSITING)
 #include "GraphicsLayerAndroid.h"
 #include "RenderLayerCompositor.h"
 #endif
 
-#define FOREGROUND_TIMER_INTERVAL 0.004 // 4ms
-#define BACKGROUND_TIMER_INTERVAL 1.0 // 1s
+#if USE(V8)
+#include <v8.h>
+#endif
 
-// How many ms to wait for the scroll to "settle" before we will consider doing
-// prerenders
-#define PRERENDER_AFTER_SCROLL_DELAY 750
+// In some cases, too many invalidations passed to the UI will slow us down.
+// Limit ourselves to 32 rectangles, past this just send the area bounds to the UI.
+// see WebViewCore::recordPictureSet().
+#define MAX_INVALIDATIONS 32
 
-#define TOUCH_FLAG_HIT_HANDLER 0x1
-#define TOUCH_FLAG_PREVENT_DEFAULT 0x2
+/*  We pass this flag when recording the actual content, so that we don't spend
+    time actually regionizing complex path clips, when all we really want to do
+    is record them.
+ */
+#define PICT_RECORD_FLAGS   SkPicture::kUsePathBoundsForClip_RecordingFlag
 
 ////////////////////////////////////////////////////////////////////////////////////////////////
 
 namespace android {
 
-// Copied from CacheBuilder, not sure if this is needed/correct
-IntRect getAreaRect(const HTMLAreaElement* area)
-{
-    Node* node = area->document();
-    while ((node = node->traverseNextNode()) != NULL) {
-        RenderObject* renderer = node->renderer();
-        if (renderer && renderer->isRenderImage()) {
-            RenderImage* image = static_cast<RenderImage*>(renderer);
-            HTMLMapElement* map = image->imageMap();
-            if (map) {
-                Node* n;
-                for (n = map->firstChild(); n;
-                        n = n->traverseNextNode(map)) {
-                    if (n == area) {
-                        if (area->isDefault())
-                            return image->absoluteBoundingBoxRect();
-                        return area->computeRect(image);
-                    }
-                }
-            }
-        }
-    }
-    return IntRect();
-}
-
-// Copied from CacheBuilder, not sure if this is needed/correct
-// TODO: See if this is even needed (I suspect not), and if not remove it
-bool validNode(Frame* startFrame, void* matchFrame,
-        void* matchNode)
-{
-    if (matchFrame == startFrame) {
-        if (matchNode == NULL)
-            return true;
-        Node* node = startFrame->document();
-        while (node != NULL) {
-            if (node == matchNode) {
-                const IntRect& rect = node->hasTagName(HTMLNames::areaTag) ?
-                    getAreaRect(static_cast<HTMLAreaElement*>(node)) : node->getRect();
-                // Consider nodes with empty rects that are not at the origin
-                // to be valid, since news.google.com has valid nodes like this
-                if (rect.x() == 0 && rect.y() == 0 && rect.isEmpty())
-                    return false;
-                return true;
-            }
-            node = node->traverseNextNode();
-        }
-        return false;
-    }
-    Frame* child = startFrame->tree()->firstChild();
-    while (child) {
-        bool result = validNode(child, matchFrame, matchNode);
-        if (result)
-            return result;
-        child = child->tree()->nextSibling();
-    }
-    return false;
-}
-
 static SkTDArray<WebViewCore*> gInstanceList;
 
 void WebViewCore::addInstance(WebViewCore* inst) {
@@ -251,7 +189,7 @@
 
 void WebViewCore::removeInstance(WebViewCore* inst) {
     int index = gInstanceList.find(inst);
-    ALOG_ASSERT(index >= 0, "RemoveInstance inst not found");
+    LOG_ASSERT(index >= 0, "RemoveInstance inst not found");
     if (index >= 0) {
         gInstanceList.removeShuffle(index);
     }
@@ -304,6 +242,8 @@
 
 // ----------------------------------------------------------------------------
 
+#define GET_NATIVE_VIEW(env, obj) ((WebViewCore*)env->GetIntField(obj, gWebViewCoreFields.m_nativeClass))
+
 // Field ids for WebViewCore
 struct WebViewCoreFields {
     jfieldID    m_nativeClass;
@@ -314,6 +254,7 @@
     jfieldID    m_viewportMaximumScale;
     jfieldID    m_viewportUserScalable;
     jfieldID    m_viewportDensityDpi;
+    jfieldID    m_webView;
     jfieldID    m_drawIsPaused;
     jfieldID    m_lowMemoryUsageMb;
     jfieldID    m_highMemoryUsageMb;
@@ -326,6 +267,7 @@
     jweak       m_obj;
     jmethodID   m_scrollTo;
     jmethodID   m_contentDraw;
+    jmethodID   m_layersDraw;
     jmethodID   m_requestListBox;
     jmethodID   m_openFileChooser;
     jmethodID   m_requestSingleListBox;
@@ -334,18 +276,17 @@
     jmethodID   m_jsPrompt;
     jmethodID   m_jsUnload;
     jmethodID   m_jsInterrupt;
-    jmethodID   m_getWebView;
     jmethodID   m_didFirstLayout;
     jmethodID   m_updateViewport;
     jmethodID   m_sendNotifyProgressFinished;
     jmethodID   m_sendViewInvalidate;
     jmethodID   m_updateTextfield;
     jmethodID   m_updateTextSelection;
-    jmethodID   m_updateTextSizeAndScroll;
     jmethodID   m_clearTextEntry;
     jmethodID   m_restoreScale;
     jmethodID   m_needTouchEvents;
     jmethodID   m_requestKeyboard;
+    jmethodID   m_requestKeyboardWithSelection;
     jmethodID   m_exceededDatabaseQuota;
     jmethodID   m_reachedMaxAppCacheSize;
     jmethodID   m_populateVisitedLinks;
@@ -354,7 +295,7 @@
     jmethodID   m_getDeviceMotionService;
     jmethodID   m_getDeviceOrientationService;
     jmethodID   m_addMessageToConsole;
-    jmethodID   m_focusNodeChanged;
+    jmethodID   m_formDidBlur;
     jmethodID   m_getPluginClass;
     jmethodID   m_showFullScreenPlugin;
     jmethodID   m_hideFullScreenPlugin;
@@ -364,17 +305,14 @@
     jmethodID   m_destroySurface;
     jmethodID   m_getContext;
     jmethodID   m_keepScreenOn;
+    jmethodID   m_sendFindAgain;
     jmethodID   m_showRect;
     jmethodID   m_centerFitRect;
     jmethodID   m_setScrollbarModes;
     jmethodID   m_setInstallableWebApp;
     jmethodID   m_enterFullscreenForVideoLayer;
-    jmethodID   m_exitFullscreenVideo;
     jmethodID   m_setWebTextViewAutoFillable;
     jmethodID   m_selectAt;
-    jmethodID   m_initEditField;
-    jmethodID   m_chromeCanTakeFocus;
-    jmethodID   m_chromeTakeFocus;
     AutoJObject object(JNIEnv* env) {
         // We hold a weak reference to the Java WebViewCore to avoid memeory
         // leaks due to circular references when WebView.destroy() is not
@@ -387,23 +325,6 @@
     }
 };
 
-struct WebViewCore::TextFieldInitDataGlue {
-    jmethodID  m_constructor;
-    jfieldID   m_fieldPointer;
-    jfieldID   m_text;
-    jfieldID   m_type;
-    jfieldID   m_isSpellCheckEnabled;
-    jfieldID   m_isTextFieldNext;
-    jfieldID   m_isTextFieldPrev;
-    jfieldID   m_isAutoCompleteEnabled;
-    jfieldID   m_name;
-    jfieldID   m_label;
-    jfieldID   m_maxLength;
-    jfieldID   m_contentBounds;
-    jfieldID   m_nodeLayerId;
-    jfieldID   m_contentRect;
-};
-
 /*
  * WebViewCore Implementation
  */
@@ -411,37 +332,58 @@
 static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[], const char signature[])
 {
     jmethodID m = env->GetMethodID(clazz, name, signature);
-    ALOG_ASSERT(m, "Could not find method %s", name);
+    LOG_ASSERT(m, "Could not find method %s", name);
     return m;
 }
 
+Mutex WebViewCore::gFrameCacheMutex;
+Mutex WebViewCore::gCursorBoundsMutex;
+
 WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* mainframe)
-    : m_touchGeneration(0)
+    : m_frameCacheKit(0)
+    , m_navPictureKit(0)
+    , m_moveGeneration(0)
+    , m_touchGeneration(0)
     , m_lastGeneration(0)
+    , m_updatedFrameCache(true)
+    , m_findIsUp(false)
+    , m_hasCursorBounds(false)
+    , m_cursorBounds(WebCore::IntRect(0, 0, 0, 0))
+    , m_cursorHitBounds(WebCore::IntRect(0, 0, 0, 0))
+    , m_cursorFrame(0)
+    , m_cursorLocation(WebCore::IntPoint(0, 0))
+    , m_cursorNode(0)
     , m_javaGlue(new JavaGlue)
-    , m_textFieldInitDataGlue(new TextFieldInitDataGlue)
     , m_mainFrame(mainframe)
     , m_popupReply(0)
+    , m_lastFocused(0)
+    , m_lastFocusedBounds(WebCore::IntRect(0,0,0,0))
+    , m_blurringNodePointer(0)
+    , m_lastFocusedSelStart(0)
+    , m_lastFocusedSelEnd(0)
     , m_blockTextfieldUpdates(false)
     , m_focusBoundsChanged(false)
     , m_skipContentDraw(false)
     , m_textGeneration(0)
+    , m_temp(0)
+    , m_tempPict(0)
     , m_maxXScroll(320/4)
     , m_maxYScroll(240/4)
     , m_scrollOffsetX(0)
     , m_scrollOffsetY(0)
     , m_mousePos(WebCore::IntPoint(0,0))
+    , m_frameCacheOutOfDate(true)
+    , m_progressDone(false)
     , m_screenWidth(320)
     , m_screenHeight(240)
     , m_textWrapWidth(320)
     , m_scale(1.0f)
+    , m_domtree_version(0)
+    , m_check_domtree_version(true)
     , m_groupForVisitedLinks(0)
     , m_isPaused(false)
     , m_cacheMode(0)
-    , m_fullscreenVideoMode(false)
-    , m_matchCount(0)
-    , m_activeMatchIndex(0)
-    , m_activeMatch(0)
+    , m_shouldPaintCaret(true)
     , m_pluginInvalTimer(this, &WebViewCore::pluginInvalTimerFired)
     , m_screenOnCounter(0)
     , m_currentNodeDomNavigationAxis(0)
@@ -449,35 +391,36 @@
 #if ENABLE(TOUCH_EVENTS)
     , m_forwardingTouchEvents(false)
 #endif
+#if USE(CHROME_NETWORK_STACK)
     , m_webRequestContext(0)
-    , m_prerenderEnabled(false)
+#endif
 {
-    ALOG_ASSERT(m_mainFrame, "Uh oh, somehow a frameview was made without an initial frame!");
+    LOG_ASSERT(m_mainFrame, "Uh oh, somehow a frameview was made without an initial frame!");
 
     jclass clazz = env->GetObjectClass(javaWebViewCore);
     m_javaGlue->m_obj = env->NewWeakGlobalRef(javaWebViewCore);
     m_javaGlue->m_scrollTo = GetJMethod(env, clazz, "contentScrollTo", "(IIZZ)V");
     m_javaGlue->m_contentDraw = GetJMethod(env, clazz, "contentDraw", "()V");
+    m_javaGlue->m_layersDraw = GetJMethod(env, clazz, "layersDraw", "()V");
     m_javaGlue->m_requestListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[I[I)V");
-    m_javaGlue->m_openFileChooser = GetJMethod(env, clazz, "openFileChooser", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
+    m_javaGlue->m_openFileChooser = GetJMethod(env, clazz, "openFileChooser", "(Ljava/lang/String;)Ljava/lang/String;");
     m_javaGlue->m_requestSingleListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[II)V");
     m_javaGlue->m_jsAlert = GetJMethod(env, clazz, "jsAlert", "(Ljava/lang/String;Ljava/lang/String;)V");
     m_javaGlue->m_jsConfirm = GetJMethod(env, clazz, "jsConfirm", "(Ljava/lang/String;Ljava/lang/String;)Z");
     m_javaGlue->m_jsPrompt = GetJMethod(env, clazz, "jsPrompt", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
     m_javaGlue->m_jsUnload = GetJMethod(env, clazz, "jsUnload", "(Ljava/lang/String;Ljava/lang/String;)Z");
     m_javaGlue->m_jsInterrupt = GetJMethod(env, clazz, "jsInterrupt", "()Z");
-    m_javaGlue->m_getWebView = GetJMethod(env, clazz, "getWebView", "()Landroid/webkit/WebView;");
     m_javaGlue->m_didFirstLayout = GetJMethod(env, clazz, "didFirstLayout", "(Z)V");
     m_javaGlue->m_updateViewport = GetJMethod(env, clazz, "updateViewport", "()V");
     m_javaGlue->m_sendNotifyProgressFinished = GetJMethod(env, clazz, "sendNotifyProgressFinished", "()V");
     m_javaGlue->m_sendViewInvalidate = GetJMethod(env, clazz, "sendViewInvalidate", "(IIII)V");
     m_javaGlue->m_updateTextfield = GetJMethod(env, clazz, "updateTextfield", "(IZLjava/lang/String;I)V");
-    m_javaGlue->m_updateTextSelection = GetJMethod(env, clazz, "updateTextSelection", "(IIIII)V");
-    m_javaGlue->m_updateTextSizeAndScroll = GetJMethod(env, clazz, "updateTextSizeAndScroll", "(IIIII)V");
+    m_javaGlue->m_updateTextSelection = GetJMethod(env, clazz, "updateTextSelection", "(IIII)V");
     m_javaGlue->m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "()V");
     m_javaGlue->m_restoreScale = GetJMethod(env, clazz, "restoreScale", "(FF)V");
     m_javaGlue->m_needTouchEvents = GetJMethod(env, clazz, "needTouchEvents", "(Z)V");
     m_javaGlue->m_requestKeyboard = GetJMethod(env, clazz, "requestKeyboard", "(Z)V");
+    m_javaGlue->m_requestKeyboardWithSelection = GetJMethod(env, clazz, "requestKeyboardWithSelection", "(IIII)V");
     m_javaGlue->m_exceededDatabaseQuota = GetJMethod(env, clazz, "exceededDatabaseQuota", "(Ljava/lang/String;Ljava/lang/String;JJ)V");
     m_javaGlue->m_reachedMaxAppCacheSize = GetJMethod(env, clazz, "reachedMaxAppCacheSize", "(J)V");
     m_javaGlue->m_populateVisitedLinks = GetJMethod(env, clazz, "populateVisitedLinks", "()V");
@@ -486,7 +429,7 @@
     m_javaGlue->m_getDeviceMotionService = GetJMethod(env, clazz, "getDeviceMotionService", "()Landroid/webkit/DeviceMotionService;");
     m_javaGlue->m_getDeviceOrientationService = GetJMethod(env, clazz, "getDeviceOrientationService", "()Landroid/webkit/DeviceOrientationService;");
     m_javaGlue->m_addMessageToConsole = GetJMethod(env, clazz, "addMessageToConsole", "(Ljava/lang/String;ILjava/lang/String;I)V");
-    m_javaGlue->m_focusNodeChanged = GetJMethod(env, clazz, "focusNodeChanged", "(ILandroid/webkit/WebViewCore$WebKitHitTest;)V");
+    m_javaGlue->m_formDidBlur = GetJMethod(env, clazz, "formDidBlur", "(I)V");
     m_javaGlue->m_getPluginClass = GetJMethod(env, clazz, "getPluginClass", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Class;");
     m_javaGlue->m_showFullScreenPlugin = GetJMethod(env, clazz, "showFullScreenPlugin", "(Landroid/webkit/ViewManager$ChildView;II)V");
     m_javaGlue->m_hideFullScreenPlugin = GetJMethod(env, clazz, "hideFullScreenPlugin", "()V");
@@ -496,40 +439,20 @@
     m_javaGlue->m_destroySurface = GetJMethod(env, clazz, "destroySurface", "(Landroid/webkit/ViewManager$ChildView;)V");
     m_javaGlue->m_getContext = GetJMethod(env, clazz, "getContext", "()Landroid/content/Context;");
     m_javaGlue->m_keepScreenOn = GetJMethod(env, clazz, "keepScreenOn", "(Z)V");
+    m_javaGlue->m_sendFindAgain = GetJMethod(env, clazz, "sendFindAgain", "()V");
     m_javaGlue->m_showRect = GetJMethod(env, clazz, "showRect", "(IIIIIIFFFF)V");
     m_javaGlue->m_centerFitRect = GetJMethod(env, clazz, "centerFitRect", "(IIII)V");
     m_javaGlue->m_setScrollbarModes = GetJMethod(env, clazz, "setScrollbarModes", "(II)V");
     m_javaGlue->m_setInstallableWebApp = GetJMethod(env, clazz, "setInstallableWebApp", "()V");
 #if ENABLE(VIDEO)
     m_javaGlue->m_enterFullscreenForVideoLayer = GetJMethod(env, clazz, "enterFullscreenForVideoLayer", "(ILjava/lang/String;)V");
-    m_javaGlue->m_exitFullscreenVideo = GetJMethod(env, clazz, "exitFullscreenVideo", "()V");
 #endif
     m_javaGlue->m_setWebTextViewAutoFillable = GetJMethod(env, clazz, "setWebTextViewAutoFillable", "(ILjava/lang/String;)V");
     m_javaGlue->m_selectAt = GetJMethod(env, clazz, "selectAt", "(II)V");
-    m_javaGlue->m_initEditField = GetJMethod(env, clazz, "initEditField", "(IIILandroid/webkit/WebViewCore$TextFieldInitData;)V");
-    m_javaGlue->m_chromeCanTakeFocus = GetJMethod(env, clazz, "chromeCanTakeFocus", "(I)Z");
-    m_javaGlue->m_chromeTakeFocus = GetJMethod(env, clazz, "chromeTakeFocus", "(I)V");
     env->DeleteLocalRef(clazz);
 
     env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this);
 
-    jclass tfidClazz = env->FindClass("android/webkit/WebViewCore$TextFieldInitData");
-    m_textFieldInitDataGlue->m_fieldPointer = env->GetFieldID(tfidClazz, "mFieldPointer", "I");
-    m_textFieldInitDataGlue->m_text = env->GetFieldID(tfidClazz, "mText", "Ljava/lang/String;");
-    m_textFieldInitDataGlue->m_type = env->GetFieldID(tfidClazz, "mType", "I");
-    m_textFieldInitDataGlue->m_isSpellCheckEnabled = env->GetFieldID(tfidClazz, "mIsSpellCheckEnabled", "Z");
-    m_textFieldInitDataGlue->m_isTextFieldNext = env->GetFieldID(tfidClazz, "mIsTextFieldNext", "Z");
-    m_textFieldInitDataGlue->m_isTextFieldPrev = env->GetFieldID(tfidClazz, "mIsTextFieldPrev", "Z");
-    m_textFieldInitDataGlue->m_isAutoCompleteEnabled = env->GetFieldID(tfidClazz, "mIsAutoCompleteEnabled", "Z");
-    m_textFieldInitDataGlue->m_name = env->GetFieldID(tfidClazz, "mName", "Ljava/lang/String;");
-    m_textFieldInitDataGlue->m_label = env->GetFieldID(tfidClazz, "mLabel", "Ljava/lang/String;");
-    m_textFieldInitDataGlue->m_maxLength = env->GetFieldID(tfidClazz, "mMaxLength", "I");
-    m_textFieldInitDataGlue->m_contentBounds = env->GetFieldID(tfidClazz, "mContentBounds", "Landroid/graphics/Rect;");
-    m_textFieldInitDataGlue->m_nodeLayerId = env->GetFieldID(tfidClazz, "mNodeLayerId", "I");
-    m_textFieldInitDataGlue->m_contentRect = env->GetFieldID(tfidClazz, "mContentRect", "Landroid/graphics/Rect;");
-    m_textFieldInitDataGlue->m_constructor = GetJMethod(env, tfidClazz, "<init>", "()V");
-    env->DeleteLocalRef(tfidClazz);
-
     PageGroup::setShouldTrackVisitedLinks(true);
 
     clearContent();
@@ -540,23 +463,22 @@
 
     WebViewCore::addInstance(this);
 
+#if USE(CHROME_NETWORK_STACK)
     AndroidNetworkLibraryImpl::InitWithApplicationContext(env, 0);
+#endif
 
-    // increase the font cache size beyond the standard system setting
-    SkGraphics::SetFontCacheLimit(1572864); // 1572864 bytes == 1.5 MB
-
+#if USE(V8)
     // Static initialisation of certain important V8 static data gets performed at system startup when
     // libwebcore gets loaded. We now need to associate the WebCore thread with V8 to complete
     // initialisation.
     v8::V8::Initialize();
+#endif
 
     // Configure any RuntimeEnabled features that we need to change from their default now.
     // See WebCore/bindings/generic/RuntimeEnabledFeatures.h
 
     // HTML5 History API
     RuntimeEnabledFeatures::setPushStateEnabled(true);
-    if (m_mainFrame)
-        m_mainFrame->settings()->setMinDOMTimerInterval(FOREGROUND_TIMER_INTERVAL);
 }
 
 WebViewCore::~WebViewCore()
@@ -572,40 +494,24 @@
         m_javaGlue->m_obj = 0;
     }
     delete m_javaGlue;
+    delete m_frameCacheKit;
+    delete m_navPictureKit;
 }
 
 WebViewCore* WebViewCore::getWebViewCore(const WebCore::FrameView* view)
 {
-    if (!view)
-        return 0;
-    if (view->platformWidget())
-        return static_cast<WebFrameView*>(view->platformWidget())->webViewCore();
-    Frame* frame = view->frame();
-    while (Frame* parent = frame->tree()->parent())
-        frame = parent;
-    WebFrameView* webFrameView = 0;
-    if (frame && frame->view())
-        webFrameView = static_cast<WebFrameView*>(frame->view()->platformWidget());
-    if (!webFrameView)
-        return 0;
-    return webFrameView->webViewCore();
+    return getWebViewCore(static_cast<const WebCore::ScrollView*>(view));
 }
 
 WebViewCore* WebViewCore::getWebViewCore(const WebCore::ScrollView* view)
 {
     if (!view)
         return 0;
-    if (view->platformWidget())
-        return static_cast<WebFrameView*>(view->platformWidget())->webViewCore();
-    const FrameView* frameView = 0;
-    if (view->isFrameView())
-        frameView = static_cast<const FrameView*>(view);
-    else {
-        frameView = static_cast<const FrameView*>(view->root());
-        if (!frameView)
-            return 0;
-    }
-    return getWebViewCore(frameView);
+
+    WebFrameView* webFrameView = static_cast<WebFrameView*>(view->platformWidget());
+    if (!webFrameView)
+        return 0;
+    return webFrameView->webViewCore();
 }
 
 static bool layoutIfNeededRecursive(WebCore::Frame* f)
@@ -616,35 +522,84 @@
     WebCore::FrameView* v = f->view();
     if (!v)
         return true;
-    v->updateLayoutAndStyleIfNeededRecursive();
-    return !v->needsLayout();
+
+    if (v->needsLayout())
+        v->layout(f->tree()->parent());
+
+    WebCore::Frame* child = f->tree()->firstChild();
+    bool success = true;
+    while (child) {
+        success &= layoutIfNeededRecursive(child);
+        child = child->tree()->nextSibling();
+    }
+
+    return success && !v->needsLayout();
+}
+
+CacheBuilder& WebViewCore::cacheBuilder()
+{
+    return FrameLoaderClientAndroid::get(m_mainFrame)->getCacheBuilder();
 }
 
 WebCore::Node* WebViewCore::currentFocus()
 {
-    return focusedFrame()->document()->focusedNode();
+    return cacheBuilder().currentFocus();
 }
 
-void WebViewCore::layout()
+void WebViewCore::recordPicture(SkPicture* picture)
 {
-    TRACE_METHOD();
-
     // if there is no document yet, just return
     if (!m_mainFrame->document()) {
-        ALOGV("!m_mainFrame->document()");
+        DBG_NAV_LOG("no document");
         return;
     }
+    // Call layout to ensure that the contentWidth and contentHeight are correct
+    if (!layoutIfNeededRecursive(m_mainFrame)) {
+        DBG_NAV_LOG("layout failed");
+        return;
+    }
+    // draw into the picture's recording canvas
+    WebCore::FrameView* view = m_mainFrame->view();
+    DBG_NAV_LOGD("view=(w=%d,h=%d)", view->contentsWidth(),
+        view->contentsHeight());
+    SkAutoPictureRecord arp(picture, view->contentsWidth(),
+                            view->contentsHeight(), PICT_RECORD_FLAGS);
+    SkAutoMemoryUsageProbe mup(__FUNCTION__);
 
+    WebCore::PlatformGraphicsContext pgc(arp.getRecordingCanvas());
+    WebCore::GraphicsContext gc(&pgc);
+    view->platformWidget()->draw(&gc, WebCore::IntRect(0, 0,
+        view->contentsWidth(), view->contentsHeight()));
+}
+
+void WebViewCore::recordPictureSet(PictureSet* content)
+{
+    // if there is no document yet, just return
+    if (!m_mainFrame->document()) {
+        DBG_SET_LOG("!m_mainFrame->document()");
+        return;
+    }
+    if (m_addInval.isEmpty()) {
+        DBG_SET_LOG("m_addInval.isEmpty()");
+        return;
+    }
     // Call layout to ensure that the contentWidth and contentHeight are correct
     // it's fine for layout to gather invalidates, but defeat sending a message
     // back to java to call webkitDraw, since we're already in the middle of
     // doing that
+    m_skipContentDraw = true;
     bool success = layoutIfNeededRecursive(m_mainFrame);
+    m_skipContentDraw = false;
 
     // We may be mid-layout and thus cannot draw.
     if (!success)
         return;
 
+    {   // collect WebViewCoreRecordTimeCounter after layoutIfNeededRecursive
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreRecordTimeCounter);
+#endif
+
     // if the webkit page dimensions changed, discard the pictureset and redraw.
     WebCore::FrameView* view = m_mainFrame->view();
     int width = view->contentsWidth();
@@ -695,8 +650,6 @@
     // If the new total is larger than the content, resize the view to include
     // all the content.
     if (!contentRect.contains(total)) {
-        // TODO: Does this ever happen? Is this needed now that we don't flatten
-        // frames?
         // Resize the view to change the overflow clip.
         view->resize(total.fRight, total.fBottom);
 
@@ -705,27 +658,159 @@
         view->forceLayout();
 
         // Relayout similar to above
-        layoutIfNeededRecursive(m_mainFrame);
+        m_skipContentDraw = true;
+        bool success = layoutIfNeededRecursive(m_mainFrame);
+        m_skipContentDraw = false;
+        if (!success)
+            return;
+
+        // Set the computed content width
+        width = view->contentsWidth();
+        height = view->contentsHeight();
+    }
+
+    if (cacheBuilder().pictureSetDisabled())
+        content->clear();
+
+#if USE(ACCELERATED_COMPOSITING)
+    // The invals are not always correct when the content size has changed. For
+    // now, let's just reset the inval so that it invalidates the entire content
+    // -- the pictureset will be fully repainted, tiles will be marked dirty and
+    // will have to be repainted.
+
+    // FIXME: the webkit invals ought to have been enough...
+    if (content->width() != width || content->height() != height) {
+        SkIRect r;
+        r.fLeft = 0;
+        r.fTop = 0;
+        r.fRight = width;
+        r.fBottom = height;
+        m_addInval.setRect(r);
+    }
+#endif
+
+    content->setDimensions(width, height, &m_addInval);
+
+    // Add the current inval rects to the PictureSet, and rebuild it.
+    content->add(m_addInval, 0, 0, false);
+
+    // If we have too many invalidations, just get the area bounds
+    SkRegion::Iterator iterator(m_addInval);
+    int nbInvals = 0;
+    while (!iterator.done()) {
+        iterator.next();
+        nbInvals++;
+        if (nbInvals > MAX_INVALIDATIONS)
+            break;
+    }
+    if (nbInvals > MAX_INVALIDATIONS) {
+        SkIRect r = m_addInval.getBounds();
+        m_addInval.setRect(r);
+    }
+
+    // Rebuild the pictureset (webkit repaint)
+    rebuildPictureSet(content);
+    } // WebViewCoreRecordTimeCounter
+
+    WebCore::Node* oldFocusNode = currentFocus();
+    m_frameCacheOutOfDate = true;
+    WebCore::IntRect oldBounds;
+    int oldSelStart = 0;
+    int oldSelEnd = 0;
+    if (oldFocusNode) {
+        oldBounds = oldFocusNode->getRect();
+        RenderObject* renderer = oldFocusNode->renderer();
+        if (renderer && (renderer->isTextArea() || renderer->isTextField())) {
+            WebCore::RenderTextControl* rtc =
+                static_cast<WebCore::RenderTextControl*>(renderer);
+            oldSelStart = rtc->selectionStart();
+            oldSelEnd = rtc->selectionEnd();
+        }
+    } else
+        oldBounds = WebCore::IntRect(0,0,0,0);
+    unsigned latestVersion = 0;
+    if (m_check_domtree_version) {
+        // as domTreeVersion only increment, we can just check the sum to see
+        // whether we need to update the frame cache
+        for (Frame* frame = m_mainFrame; frame; frame = frame->tree()->traverseNext()) {
+            const Document* doc = frame->document();
+            latestVersion += doc->domTreeVersion() + doc->styleVersion();
+        }
+    }
+    DBG_NAV_LOGD("m_lastFocused=%p oldFocusNode=%p"
+        " m_lastFocusedBounds={%d,%d,%d,%d} oldBounds={%d,%d,%d,%d}"
+        " m_lastFocusedSelection={%d,%d} oldSelection={%d,%d}"
+        " m_check_domtree_version=%s latestVersion=%d m_domtree_version=%d",
+        m_lastFocused, oldFocusNode,
+        m_lastFocusedBounds.x(), m_lastFocusedBounds.y(),
+        m_lastFocusedBounds.width(), m_lastFocusedBounds.height(),
+        oldBounds.x(), oldBounds.y(), oldBounds.width(), oldBounds.height(),
+        m_lastFocusedSelStart, m_lastFocusedSelEnd, oldSelStart, oldSelEnd,
+        m_check_domtree_version ? "true" : "false",
+        latestVersion, m_domtree_version);
+    if (m_lastFocused == oldFocusNode && m_lastFocusedBounds == oldBounds
+            && m_lastFocusedSelStart == oldSelStart
+            && m_lastFocusedSelEnd == oldSelEnd
+            && !m_findIsUp
+            && (!m_check_domtree_version || latestVersion == m_domtree_version))
+    {
+        return;
+    }
+    m_focusBoundsChanged |= m_lastFocused == oldFocusNode
+        && m_lastFocusedBounds != oldBounds;
+    m_lastFocused = oldFocusNode;
+    m_lastFocusedBounds = oldBounds;
+    m_lastFocusedSelStart = oldSelStart;
+    m_lastFocusedSelEnd = oldSelEnd;
+    m_domtree_version = latestVersion;
+    DBG_NAV_LOG("call updateFrameCache");
+    updateFrameCache();
+    if (m_findIsUp) {
+        LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+        JNIEnv* env = JSC::Bindings::getJNIEnv();
+        AutoJObject javaObject = m_javaGlue->object(env);
+        if (javaObject.get()) {
+            env->CallVoidMethod(javaObject.get(), m_javaGlue->m_sendFindAgain);
+            checkException(env);
+        }
     }
 }
 
-void WebViewCore::recordPicturePile()
+// note: updateCursorBounds is called directly by the WebView thread
+// This needs to be called each time we call CachedRoot::setCursor() with
+// non-null CachedNode/CachedFrame, since otherwise the WebViewCore's data
+// about the cursor is incorrect.  When we call setCursor(0,0), we need
+// to set hasCursorBounds to false.
+void WebViewCore::updateCursorBounds(const CachedRoot* root,
+        const CachedFrame* cachedFrame, const CachedNode* cachedNode)
 {
-    // if the webkit page dimensions changed, discard the pictureset and redraw.
-    WebCore::FrameView* view = m_mainFrame->view();
-    int width = view ? view->contentsWidth() : 0;
-    int height = view ? view->contentsHeight() : 0;
-
-    m_content.setSize(IntSize(width, height));
-
-    // Rebuild the pictureset (webkit repaint)
-    m_content.updatePicturesIfNeeded(this);
+    LOG_ASSERT(root, "updateCursorBounds: root cannot be null");
+    LOG_ASSERT(cachedNode, "updateCursorBounds: cachedNode cannot be null");
+    LOG_ASSERT(cachedFrame, "updateCursorBounds: cachedFrame cannot be null");
+    gCursorBoundsMutex.lock();
+    m_hasCursorBounds = !cachedNode->isHidden();
+    // If m_hasCursorBounds is false, we never look at the other
+    // values, so do not bother setting them.
+    if (m_hasCursorBounds) {
+        WebCore::IntRect bounds = cachedNode->bounds(cachedFrame);
+        if (m_cursorBounds != bounds)
+            DBG_NAV_LOGD("new cursor bounds=(%d,%d,w=%d,h=%d)",
+                bounds.x(), bounds.y(), bounds.width(), bounds.height());
+        m_cursorBounds = bounds;
+        m_cursorHitBounds = cachedNode->hitBounds(cachedFrame);
+        m_cursorFrame = cachedFrame->framePointer();
+        root->getSimulatedMousePosition(&m_cursorLocation);
+        m_cursorNode = cachedNode->nodePointer();
+    }
+    gCursorBoundsMutex.unlock();
 }
 
 void WebViewCore::clearContent()
 {
-    m_content.reset();
-    updateLocale();
+    DBG_SET_LOG("");
+    m_content.clear();
+    m_addInval.setEmpty();
+    m_rebuildInval.setEmpty();
 }
 
 bool WebViewCore::focusBoundsChanged()
@@ -735,82 +820,75 @@
     return result;
 }
 
-void WebViewCore::paintContents(WebCore::GraphicsContext* gc, WebCore::IntRect& dirty)
+SkPicture* WebViewCore::rebuildPicture(const SkIRect& inval)
 {
     WebCore::FrameView* view = m_mainFrame->view();
-    if (!view) {
-        gc->setFillColor(WebCore::Color::white, WebCore::ColorSpaceDeviceRGB);
-        gc->fillColor();
-        return;
+    int width = view->contentsWidth();
+    int height = view->contentsHeight();
+    SkPicture* picture = new SkPicture();
+    SkAutoPictureRecord arp(picture, width, height, PICT_RECORD_FLAGS);
+    SkAutoMemoryUsageProbe mup(__FUNCTION__);
+    SkCanvas* recordingCanvas = arp.getRecordingCanvas();
+
+    WebCore::PlatformGraphicsContext pgc(recordingCanvas);
+    WebCore::GraphicsContext gc(&pgc);
+    IntPoint origin = view->minimumScrollPosition();
+    WebCore::IntRect drawArea(inval.fLeft + origin.x(), inval.fTop + origin.y(),
+            inval.width(), inval.height());
+    recordingCanvas->translate(-drawArea.x(), -drawArea.y());
+    recordingCanvas->save();
+    view->platformWidget()->draw(&gc, drawArea);
+    m_rebuildInval.op(inval, SkRegion::kUnion_Op);
+    DBG_SET_LOGD("m_rebuildInval={%d,%d,r=%d,b=%d}",
+        m_rebuildInval.getBounds().fLeft, m_rebuildInval.getBounds().fTop,
+        m_rebuildInval.getBounds().fRight, m_rebuildInval.getBounds().fBottom);
+
+    return picture;
+}
+
+void WebViewCore::rebuildPictureSet(PictureSet* pictureSet)
+{
+    WebCore::FrameView* view = m_mainFrame->view();
+
+#ifdef FAST_PICTURESET
+    WTF::Vector<Bucket*>* buckets = pictureSet->bucketsToUpdate();
+
+    for (unsigned int i = 0; i < buckets->size(); i++) {
+        Bucket* bucket = (*buckets)[i];
+        for (unsigned int j = 0; j < bucket->size(); j++) {
+            BucketPicture& bucketPicture = (*bucket)[j];
+            const SkIRect& inval = bucketPicture.mRealArea;
+            SkPicture* picture = rebuildPicture(inval);
+            SkSafeUnref(bucketPicture.mPicture);
+            bucketPicture.mPicture = picture;
+        }
+    }
+    buckets->clear();
+#else
+    size_t size = pictureSet->size();
+    for (size_t index = 0; index < size; index++) {
+        if (pictureSet->upToDate(index))
+            continue;
+        const SkIRect& inval = pictureSet->bounds(index);
+        DBG_SET_LOGD("pictSet=%p [%d] {%d,%d,w=%d,h=%d}", pictureSet, index,
+            inval.fLeft, inval.fTop, inval.width(), inval.height());
+        pictureSet->setPicture(index, rebuildPicture(inval));
     }
 
-    IntPoint origin = view->minimumScrollPosition();
-    IntRect drawArea = dirty;
-    gc->translate(-origin.x(), -origin.y());
-    drawArea.move(origin.x(), origin.y());
-    view->platformWidget()->draw(gc, drawArea);
+    pictureSet->validate(__FUNCTION__);
+#endif
 }
 
-void WebViewCore::setPrerenderingEnabled(bool enable)
+bool WebViewCore::updateLayers(LayerAndroid* layers)
 {
-    MutexLocker locker(m_prerenderLock);
-    m_prerenderEnabled = enable;
-}
-
-bool WebViewCore::prerenderingEnabled()
-{
-    MutexLocker locker(m_prerenderLock);
-    return m_prerenderEnabled;
-}
-
-SkCanvas* WebViewCore::createPrerenderCanvas(PrerenderedInval* prerendered)
-{
-    // Has WebView disabled prerenders (not attached, etc...)?
-    if (!prerenderingEnabled())
-        return 0;
-    // Does this WebView have focus?
-    if (!m_mainFrame->page()->focusController()->isActive())
-        return 0;
-    // Are we scrolling?
-    if (currentTimeMS() - m_scrollSetTime < PRERENDER_AFTER_SCROLL_DELAY)
-        return 0;
-    // Do we have anything to render?
-    if (prerendered->area.isEmpty())
-        return 0;
-    FloatRect scaleTemp(m_scrollOffsetX, m_scrollOffsetY, m_screenWidth, m_screenHeight);
-    scaleTemp.scale(m_scale);
-    IntRect visibleTileClip = enclosingIntRect(scaleTemp);
-    FloatRect scaledArea = prerendered->area;
-    scaledArea.scale(m_scale);
-    IntRect enclosingScaledArea = enclosingIntRect(scaledArea);
-    if (enclosingScaledArea.isEmpty())
-        return 0;
-    // "round out" the screen to tile boundaries so that we can clip yet still
-    // cover any visible tiles with the prerender
-    int tw = TilesManager::tileWidth();
-    int th = TilesManager::tileHeight();
-    float left = tw * (int) (visibleTileClip.x() / tw);
-    float top = th * (int) (visibleTileClip.y() / th);
-    float right = tw * (int) ceilf(visibleTileClip.maxX() / (float) tw);
-    float bottom = th * (int) ceilf(visibleTileClip.maxY() / (float) th);
-    visibleTileClip = IntRect(left, top, right - left, bottom - top);
-    enclosingScaledArea.intersect(visibleTileClip);
-    if (enclosingScaledArea.isEmpty())
-        return 0;
-    prerendered->screenArea = enclosingScaledArea;
-    FloatRect enclosingDocArea(enclosingScaledArea);
-    enclosingDocArea.scale(1 / m_scale);
-    prerendered->area = enclosingIntRect(enclosingDocArea);
-    if (prerendered->area.isEmpty())
-        return 0;
-    prerendered->bitmap.setConfig(SkBitmap::kARGB_8888_Config,
-                                  enclosingScaledArea.width(),
-                                  enclosingScaledArea.height());
-    prerendered->bitmap.allocPixels();
-    SkCanvas* bitmapCanvas = new SkCanvas(prerendered->bitmap);
-    bitmapCanvas->scale(m_scale, m_scale);
-    bitmapCanvas->translate(-enclosingDocArea.x(), -enclosingDocArea.y());
-    return bitmapCanvas;
+    // We update the layers
+    ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client());
+    GraphicsLayerAndroid* root = static_cast<GraphicsLayerAndroid*>(chromeC->layersSync());
+    if (root) {
+        LayerAndroid* updatedLayer = root->contentLayer();
+        return layers->updateWithTree(updatedLayer);
+    }
+    return true;
 }
 
 void WebViewCore::notifyAnimationStarted()
@@ -824,113 +902,93 @@
 
 }
 
-BaseLayerAndroid* WebViewCore::createBaseLayer(GraphicsLayerAndroid* root)
+BaseLayerAndroid* WebViewCore::createBaseLayer(SkRegion* region)
 {
+    BaseLayerAndroid* base = new BaseLayerAndroid();
+    base->setContent(m_content);
+
+    m_skipContentDraw = true;
+    bool layoutSucceeded = layoutIfNeededRecursive(m_mainFrame);
+    m_skipContentDraw = false;
+    // Layout only fails if called during a layout.
+    LOG_ASSERT(layoutSucceeded, "Can never be called recursively");
+
+#if USE(ACCELERATED_COMPOSITING)
     // We set the background color
-    Color background = Color::white;
-
-    bool bodyHasFixedBackgroundImage = false;
-    bool bodyHasCSSBackground = false;
-
     if (m_mainFrame && m_mainFrame->document()
         && m_mainFrame->document()->body()) {
-
         Document* document = m_mainFrame->document();
         RefPtr<RenderStyle> style = document->styleForElementIgnoringPendingStylesheets(document->body());
         if (style->hasBackground()) {
-            background = style->visitedDependentColor(CSSPropertyBackgroundColor);
-            bodyHasCSSBackground = true;
-        }
-        WebCore::FrameView* view = m_mainFrame->view();
-        if (view) {
-            Color viewBackground = view->baseBackgroundColor();
-            background = bodyHasCSSBackground ? viewBackground.blend(background) : viewBackground;
-        }
-        if (style->hasFixedBackgroundImage()) {
-            Image* backgroundImage = FixedBackgroundImageLayerAndroid::GetCachedImage(style);
-            if (backgroundImage && backgroundImage->width() > 1 && backgroundImage->height() > 1)
-                bodyHasFixedBackgroundImage = true;
+            Color color = style->visitedDependentColor(CSSPropertyBackgroundColor);
+            if (color.isValid() && color.alpha() > 0)
+                base->setBackgroundColor(color);
         }
     }
 
-    PicturePileLayerContent* content = new PicturePileLayerContent(m_content);
-    m_content.clearPrerenders();
-
-    BaseLayerAndroid* realBase = 0;
-    LayerAndroid* base = 0;
-
-    //If we have a fixed background image on the body element, the fixed image
-    // will be contained in the PictureSet (the content object), and the foreground
-    //of the body element will be moved to a layer.
-    //In that case, let's change the hierarchy to obtain:
-    //
-    //BaseLayerAndroid
-    // \- FixedBackgroundBaseLayerAndroid (fixed positioning)
-    // \- ForegroundBaseLayerAndroid
-    //   \- root layer (webkit composited tree)
-
-    if (bodyHasFixedBackgroundImage) {
-        base = new ForegroundBaseLayerAndroid(0);
-        base->setSize(content->width(), content->height());
-
-        Document* document = m_mainFrame->document();
-        RefPtr<RenderStyle> style = document->styleForElementIgnoringPendingStylesheets(document->body());
-
-        FixedBackgroundImageLayerAndroid* baseBackground =
-             new FixedBackgroundImageLayerAndroid(style, content->width(), content->height());
-
-        realBase = new BaseLayerAndroid(0);
-        realBase->setSize(content->width(), content->height());
-        realBase->addChild(baseBackground);
-        realBase->addChild(base);
-        baseBackground->unref();
-        base->unref();
-    } else {
-        realBase = new BaseLayerAndroid(content);
-        base = realBase;
-    }
-
-    realBase->setBackgroundColor(background);
-
-    SkSafeUnref(content);
-
     // We update the layers
+    ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client());
+    GraphicsLayerAndroid* root = static_cast<GraphicsLayerAndroid*>(chromeC->layersSync());
     if (root) {
         LayerAndroid* copyLayer = new LayerAndroid(*root->contentLayer());
         base->addChild(copyLayer);
         copyLayer->unref();
         root->contentLayer()->clearDirtyRegion();
     }
+#endif
 
-    return realBase;
+    return base;
 }
 
-BaseLayerAndroid* WebViewCore::recordContent(SkIPoint* point)
+BaseLayerAndroid* WebViewCore::recordContent(SkRegion* region, SkIPoint* point)
 {
-    m_skipContentDraw = true;
-    layout();
-    ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>(m_mainFrame->page()->chrome()->client());
-    GraphicsLayerAndroid* root = static_cast<GraphicsLayerAndroid*>(chromeC->layersSync());
-    m_skipContentDraw = false;
-    recordPicturePile();
-
-    BaseLayerAndroid* baseLayer = createBaseLayer(root);
-
-    baseLayer->markAsDirty(m_content.dirtyRegion());
-    m_content.dirtyRegion().setEmpty();
+    DBG_SET_LOG("start");
+    // If there is a pending style recalculation, just return.
+    if (m_mainFrame->document()->isPendingStyleRecalc()) {
+        DBG_SET_LOGD("recordContent: pending style recalc, ignoring.");
+        return 0;
+    }
+    float progress = (float) m_mainFrame->page()->progress()->estimatedProgress();
+    m_progressDone = progress <= 0.0f || progress >= 1.0f;
+    recordPictureSet(&m_content);
+    if (!m_progressDone && m_content.isEmpty()) {
+        DBG_SET_LOGD("empty (progress=%g)", progress);
+        return 0;
+    }
+    region->set(m_addInval);
+    m_addInval.setEmpty();
 #if USE(ACCELERATED_COMPOSITING)
 #else
-    baseLayer->markAsDirty(m_rebuildInval);
+    region->op(m_rebuildInval, SkRegion::kUnion_Op);
 #endif
-    point->fX = m_content.size().width();
-    point->fY = m_content.size().height();
+    m_rebuildInval.setEmpty();
+    point->fX = m_content.width();
+    point->fY = m_content.height();
+    DBG_SET_LOGD("region={%d,%d,r=%d,b=%d}", region->getBounds().fLeft,
+        region->getBounds().fTop, region->getBounds().fRight,
+        region->getBounds().fBottom);
+    DBG_SET_LOG("end");
 
-    return baseLayer;
+    return createBaseLayer(region);
+}
+
+void WebViewCore::splitContent(PictureSet* content)
+{
+#ifdef FAST_PICTURESET
+#else
+    bool layoutSucceeded = layoutIfNeededRecursive(m_mainFrame);
+    LOG_ASSERT(layoutSucceeded, "Can never be called recursively");
+    content->split(&m_content);
+    rebuildPictureSet(&m_content);
+    content->set(m_content);
+#endif // FAST_PICTURESET
 }
 
 void WebViewCore::scrollTo(int x, int y, bool animate)
 {
-    ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+    LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+
+//    LOGD("WebViewCore::scrollTo(%d %d)\n", x, y);
 
     JNIEnv* env = JSC::Bindings::getJNIEnv();
     AutoJObject javaObject = m_javaGlue->object(env);
@@ -943,7 +1001,7 @@
 
 void WebViewCore::sendNotifyProgressFinished()
 {
-    ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+    LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
     JNIEnv* env = JSC::Bindings::getJNIEnv();
     AutoJObject javaObject = m_javaGlue->object(env);
     if (!javaObject.get())
@@ -954,7 +1012,7 @@
 
 void WebViewCore::viewInvalidate(const WebCore::IntRect& rect)
 {
-    ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+    LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
     JNIEnv* env = JSC::Bindings::getJNIEnv();
     AutoJObject javaObject = m_javaGlue->object(env);
     if (!javaObject.get())
@@ -975,12 +1033,26 @@
     checkException(env);
 }
 
+void WebViewCore::layersDraw()
+{
+    JNIEnv* env = JSC::Bindings::getJNIEnv();
+    AutoJObject javaObject = m_javaGlue->object(env);
+    if (!javaObject.get())
+        return;
+    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_layersDraw);
+    checkException(env);
+}
+
 void WebViewCore::contentInvalidate(const WebCore::IntRect &r)
 {
-    IntPoint origin = m_mainFrame->view()->minimumScrollPosition();
-    IntRect dirty = r;
-    dirty.move(-origin.x(), -origin.y());
-    m_content.invalidate(dirty);
+    DBG_SET_LOGD("rect={%d,%d,w=%d,h=%d}", r.x(), r.y(), r.width(), r.height());
+    SkIRect rect(r);
+    if (!rect.intersect(0, 0, INT_MAX, INT_MAX))
+        return;
+    m_addInval.op(rect, SkRegion::kUnion_Op);
+    DBG_SET_LOGD("m_addInval={%d,%d,r=%d,b=%d}",
+        m_addInval.getBounds().fLeft, m_addInval.getBounds().fTop,
+        m_addInval.getBounds().fRight, m_addInval.getBounds().fBottom);
     if (!m_skipContentDraw)
         contentDraw();
 }
@@ -1000,9 +1072,19 @@
     contentInvalidate(r);
 }
 
+static int pin_pos(int x, int width, int targetWidth)
+{
+    if (x + width > targetWidth)
+        x = targetWidth - width;
+    if (x < 0)
+        x = 0;
+    return x;
+}
+
 void WebViewCore::didFirstLayout()
 {
-    ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+    DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
+    LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
 
     JNIEnv* env = JSC::Bindings::getJNIEnv();
     AutoJObject javaObject = m_javaGlue->object(env);
@@ -1012,7 +1094,7 @@
     const WebCore::KURL& url = m_mainFrame->document()->url();
     if (url.isEmpty())
         return;
-    ALOGV("::WebCore:: didFirstLayout %s", url.string().ascii().data());
+    LOGV("::WebCore:: didFirstLayout %s", url.string().ascii().data());
 
     WebCore::FrameLoadType loadType = m_mainFrame->loader()->loadType();
 
@@ -1026,11 +1108,17 @@
             // a newly-loaded page.
             || loadType == WebCore::FrameLoadTypeSame);
     checkException(env);
+
+    DBG_NAV_LOG("call updateFrameCache");
+    m_check_domtree_version = false;
+    updateFrameCache();
+    m_history.setDidFirstLayout(true);
 }
 
 void WebViewCore::updateViewport()
 {
-    ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+    DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
+    LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
 
     JNIEnv* env = JSC::Bindings::getJNIEnv();
     AutoJObject javaObject = m_javaGlue->object(env);
@@ -1042,7 +1130,8 @@
 
 void WebViewCore::restoreScale(float scale, float textWrapScale)
 {
-    ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+    DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
+    LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
 
     JNIEnv* env = JSC::Bindings::getJNIEnv();
     AutoJObject javaObject = m_javaGlue->object(env);
@@ -1054,7 +1143,8 @@
 
 void WebViewCore::needTouchEvents(bool need)
 {
-    ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+    DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
+    LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
 
 #if ENABLE(TOUCH_EVENTS)
     JNIEnv* env = JSC::Bindings::getJNIEnv();
@@ -1072,9 +1162,26 @@
 #endif
 }
 
+void WebViewCore::requestKeyboardWithSelection(const WebCore::Node* node,
+        int selStart, int selEnd)
+{
+    DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
+    LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+
+    JNIEnv* env = JSC::Bindings::getJNIEnv();
+    AutoJObject javaObject = m_javaGlue->object(env);
+    if (!javaObject.get())
+        return;
+    env->CallVoidMethod(javaObject.get(),
+            m_javaGlue->m_requestKeyboardWithSelection,
+            reinterpret_cast<int>(node), selStart, selEnd, m_textGeneration);
+    checkException(env);
+}
+
 void WebViewCore::requestKeyboard(bool showKeyboard)
 {
-    ALOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
+    DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
+    LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
 
     JNIEnv* env = JSC::Bindings::getJNIEnv();
     AutoJObject javaObject = m_javaGlue->object(env);
@@ -1086,15 +1193,42 @@
 
 void WebViewCore::notifyProgressFinished()
 {
+    m_check_domtree_version = true;
     sendNotifyProgressFinished();
 }
 
-void WebViewCore::setScrollOffset(bool sendScrollEvent, int dx, int dy)
+void WebViewCore::doMaxScroll(CacheBuilder::Direction dir)
 {
+    int dx = 0, dy = 0;
+
+    switch (dir) {
+    case CacheBuilder::LEFT:
+        dx = -m_maxXScroll;
+        break;
+    case CacheBuilder::UP:
+        dy = -m_maxYScroll;
+        break;
+    case CacheBuilder::RIGHT:
+        dx = m_maxXScroll;
+        break;
+    case CacheBuilder::DOWN:
+        dy = m_maxYScroll;
+        break;
+    case CacheBuilder::UNINITIALIZED:
+    default:
+        LOG_ASSERT(0, "unexpected focus selector");
+    }
+    WebCore::FrameView* view = m_mainFrame->view();
+    this->scrollTo(view->scrollX() + dx, view->scrollY() + dy, true);
+}
+
+void WebViewCore::setScrollOffset(int moveGeneration, bool sendScrollEvent, int dx, int dy)
+{
+    DBG_NAV_LOGD("{%d,%d} m_scrollOffset=(%d,%d), sendScrollEvent=%d", dx, dy,
+        m_scrollOffsetX, m_scrollOffsetY, sendScrollEvent);
     if (m_scrollOffsetX != dx || m_scrollOffsetY != dy) {
         m_scrollOffsetX = dx;
         m_scrollOffsetY = dy;
-        m_scrollSetTime = currentTimeMS();
         // The visible rect is located within our coordinate space so it
         // contains the actual scroll position. Setting the location makes hit
         // testing work correctly.
@@ -1125,10 +1259,19 @@
         // update the currently visible screen
         sendPluginVisibleScreen();
     }
+    gCursorBoundsMutex.lock();
+    bool hasCursorBounds = m_hasCursorBounds;
+    Frame* frame = (Frame*) m_cursorFrame;
+    IntPoint location = m_cursorLocation;
+    gCursorBoundsMutex.unlock();
+    if (!hasCursorBounds)
+        return;
+    moveMouseIfLatest(moveGeneration, frame, location.x(), location.y());
 }
 
 void WebViewCore::setGlobalBounds(int x, int y, int h, int v)
 {
+    DBG_NAV_LOGD("{%d,%d}", x, y);
     m_mainFrame->view()->platformWidget()->setWindowBounds(x, y, h, v);
 }
 
@@ -1147,6 +1290,9 @@
     int osw = m_screenWidth;
     int osh = m_screenHeight;
     int otw = m_textWrapWidth;
+    float oldScale = m_scale;
+    DBG_NAV_LOGD("old:(w=%d,h=%d,sw=%d,scale=%g) new:(w=%d,h=%d,sw=%d,scale=%g)",
+        ow, oh, osw, m_scale, width, height, screenWidth, scale);
     m_screenWidth = screenWidth;
     m_screenHeight = screenHeight;
     m_textWrapWidth = textWrapWidth;
@@ -1165,8 +1311,11 @@
 
     if (ow != width || (!ignoreHeight && oh != height) || reflow) {
         WebCore::RenderObject *r = m_mainFrame->contentRenderer();
+        DBG_NAV_LOGD("renderer=%p view=(w=%d,h=%d)", r,
+                screenWidth, screenHeight);
         if (r) {
             WebCore::IntPoint anchorPoint = WebCore::IntPoint(anchorX, anchorY);
+            DBG_NAV_LOGD("anchorX=%d anchorY=%d", anchorX, anchorY);
             RefPtr<WebCore::Node> node;
             WebCore::IntRect bounds;
             WebCore::IntPoint offset;
@@ -1178,19 +1327,11 @@
                         m_mainFrame->eventHandler()->hitTestResultAtPoint(
                                 anchorPoint, false);
                 node = hitTestResult.innerNode();
-                if (node && !node->isTextNode()) {
-                    // If the hitTestResultAtPoint didn't find a suitable node
-                    // for anchoring, try again with some slop.
-                    static const int HIT_SLOP = 30;
-                    anchorPoint.move(HIT_SLOP, HIT_SLOP);
-                    hitTestResult =
-                        m_mainFrame->eventHandler()->hitTestResultAtPoint(
-                                anchorPoint, false);
-                    node = hitTestResult.innerNode();
-                }
             }
             if (node) {
                 bounds = node->getRect();
+                DBG_NAV_LOGD("ob:(x=%d,y=%d,w=%d,h=%d)",
+                    bounds.x(), bounds.y(), bounds.width(), bounds.height());
                 // sites like nytimes.com insert a non-standard tag <nyt_text>
                 // in the html. If it is the HitTestResult, it may have zero
                 // width and height. In this case, use its parent node.
@@ -1198,6 +1339,8 @@
                     node = node->parentOrHostNode();
                     if (node) {
                         bounds = node->getRect();
+                        DBG_NAV_LOGD("found a zero width node and use its parent, whose ob:(x=%d,y=%d,w=%d,h=%d)",
+                                bounds.x(), bounds.y(), bounds.width(), bounds.height());
                     }
                 }
             }
@@ -1218,6 +1361,9 @@
             // scroll to restore current screen center
             if (node && node->inDocument()) {
                 const WebCore::IntRect& newBounds = node->getRect();
+                DBG_NAV_LOGD("nb:(x=%d,y=%d,w=%d,"
+                    "h=%d)", newBounds.x(), newBounds.y(),
+                    newBounds.width(), newBounds.height());
                 if ((osw && osh && bounds.width() && bounds.height())
                     && (bounds != newBounds)) {
                     WebCore::FrameView* view = m_mainFrame->view();
@@ -1294,6 +1440,13 @@
 #endif
 }
 
+void WebViewCore::dumpNavTree()
+{
+#if DUMP_NAV_CACHE
+    cacheBuilder().mDebug.print();
+#endif
+}
+
 HTMLElement* WebViewCore::retrieveElement(int x, int y,
     const QualifiedName& tagName)
 {
@@ -1302,12 +1455,12 @@
         DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly,
         IntSize(1, 1));
     if (!hitTestResult.innerNode() || !hitTestResult.innerNode()->inDocument()) {
-        ALOGE("Should not happen: no in document Node found");
+        LOGE("Should not happen: no in document Node found");
         return 0;
     }
     const ListHashSet<RefPtr<Node> >& list = hitTestResult.rectBasedTestResult();
     if (list.isEmpty()) {
-        ALOGE("Should not happen: no rect-based-test nodes found");
+        LOGE("Should not happen: no rect-based-test nodes found");
         return 0;
     }
     Node* node = hitTestResult.innerNode();
@@ -1316,6 +1469,9 @@
         || !element->hasTagName(tagName))) {
         element = element->parentNode();
     }
+    DBG_NAV_LOGD("node=%p element=%p x=%d y=%d nodeName=%s tagName=%s", node,
+        element, x, y, node->nodeName().utf8().data(),
+        element ? ((Element*) element)->tagName().utf8().data() : "<none>");
     return static_cast<WebCore::HTMLElement*>(element);
 }
 
@@ -1333,10 +1489,8 @@
 
 WTF::String WebViewCore::retrieveHref(int x, int y)
 {
-    // TODO: This is expensive, cache
-    HitTestResult result = m_mainFrame->eventHandler()->hitTestResultAtPoint(IntPoint(x, y),
-                false, false, DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly, IntSize(1, 1));
-    return result.absoluteLinkURL();
+    WebCore::HTMLAnchorElement* anchor = retrieveAnchorElement(x, y);
+    return anchor ? anchor->href() : WTF::String();
 }
 
 WTF::String WebViewCore::retrieveAnchorText(int x, int y)
@@ -1347,16 +1501,14 @@
 
 WTF::String WebViewCore::retrieveImageSource(int x, int y)
 {
-    // TODO: This is expensive, cache
-    HitTestResult result = m_mainFrame->eventHandler()->hitTestResultAtPoint(IntPoint(x, y),
-                false, false, DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly, IntSize(1, 1));
-    return result.absoluteImageURL();
+    HTMLImageElement* image = retrieveImageElement(x, y);
+    return image ? image->src().string() : WTF::String();
 }
 
 WTF::String WebViewCore::requestLabel(WebCore::Frame* frame,
         WebCore::Node* node)
 {
-    if (node && validNode(m_mainFrame, frame, node)) {
+    if (node && CacheBuilder::validNode(m_mainFrame, frame, node)) {
         RefPtr<WebCore::NodeList> list = node->document()->getElementsByTagName("label");
         unsigned length = list->length();
         for (unsigned i = 0; i < length; i++) {
@@ -1380,18 +1532,17 @@
 
 static bool isContentEditable(const WebCore::Node* node)
 {
-    if (!node)
-        return false;
-    return node->isContentEditable();
+    if (!node) return false;
+    return node->document()->frame()->selection()->isContentEditable();
 }
 
 // Returns true if the node is a textfield, textarea, or contentEditable
 static bool isTextInput(const WebCore::Node* node)
 {
-    if (!node)
-        return false;
     if (isContentEditable(node))
         return true;
+    if (!node)
+        return false;
     WebCore::RenderObject* renderer = node->renderer();
     return renderer && (renderer->isTextField() || renderer->isTextArea());
 }
@@ -1409,9 +1560,107 @@
     focusedFrame->selection()->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
 }
 
+void WebViewCore::updateCacheOnNodeChange()
+{
+    gCursorBoundsMutex.lock();
+    bool hasCursorBounds = m_hasCursorBounds;
+    Frame* frame = (Frame*) m_cursorFrame;
+    Node* node = (Node*) m_cursorNode;
+    IntRect bounds = m_cursorHitBounds;
+    gCursorBoundsMutex.unlock();
+    if (!hasCursorBounds || !node)
+        return;
+    if (CacheBuilder::validNode(m_mainFrame, frame, node)) {
+        RenderObject* renderer = node->renderer();
+        if (renderer && renderer->style()->visibility() != HIDDEN) {
+            IntRect absBox = renderer->absoluteBoundingBoxRect();
+            int globalX, globalY;
+            CacheBuilder::GetGlobalOffset(frame, &globalX, &globalY);
+            absBox.move(globalX, globalY);
+            if (absBox == bounds)
+                return;
+            DBG_NAV_LOGD("absBox=(%d,%d,%d,%d) bounds=(%d,%d,%d,%d)",
+                absBox.x(), absBox.y(), absBox.width(), absBox.height(),
+                bounds.x(), bounds.y(), bounds.width(), bounds.height());
+        }
+    }
+    DBG_NAV_LOGD("updateFrameCache node=%p", node);
+    updateFrameCache();
+}
+
+void WebViewCore::updateFrameCache()
+{
+    if (!m_frameCacheOutOfDate) {
+        DBG_NAV_LOG("!m_frameCacheOutOfDate");
+        return;
+    }
+
+    // If there is a pending style recalculation, do not update the frame cache.
+    // Until the recalculation is complete, there may be internal objects that
+    // are in an inconsistent state (such as font pointers).
+    // In any event, there's not much point to updating the cache while a style
+    // recalculation is pending, since it will simply have to be updated again
+    // once the recalculation is complete.
+    // TODO: Do we need to reschedule an update for after the style is recalculated?
+    if (m_mainFrame && m_mainFrame->document() && m_mainFrame->document()->isPendingStyleRecalc()) {
+        LOGW("updateFrameCache: pending style recalc, ignoring.");
+        return;
+    }
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreBuildNavTimeCounter);
+#endif
+    m_frameCacheOutOfDate = false;
+    m_temp = new CachedRoot();
+    m_temp->init(m_mainFrame, &m_history);
+#if USE(ACCELERATED_COMPOSITING)
+    GraphicsLayerAndroid* graphicsLayer = graphicsRootLayer();
+    if (graphicsLayer)
+        m_temp->setRootLayer(graphicsLayer->contentLayer());
+#endif
+    CacheBuilder& builder = cacheBuilder();
+    WebCore::Settings* settings = m_mainFrame->page()->settings();
+    builder.allowAllTextDetection();
+#ifdef ANDROID_META_SUPPORT
+    if (settings) {
+        if (!settings->formatDetectionAddress())
+            builder.disallowAddressDetection();
+        if (!settings->formatDetectionEmail())
+            builder.disallowEmailDetection();
+        if (!settings->formatDetectionTelephone())
+            builder.disallowPhoneDetection();
+    }
+#endif
+    builder.buildCache(m_temp);
+    m_tempPict = new SkPicture();
+    recordPicture(m_tempPict);
+    m_temp->setPicture(m_tempPict);
+    m_temp->setTextGeneration(m_textGeneration);
+    WebCoreViewBridge* window = m_mainFrame->view()->platformWidget();
+    m_temp->setVisibleRect(WebCore::IntRect(m_scrollOffsetX,
+        m_scrollOffsetY, window->width(), window->height()));
+    gFrameCacheMutex.lock();
+    delete m_frameCacheKit;
+    delete m_navPictureKit;
+    m_frameCacheKit = m_temp;
+    m_navPictureKit = m_tempPict;
+    m_updatedFrameCache = true;
+#if DEBUG_NAV_UI
+    const CachedNode* cachedFocusNode = m_frameCacheKit->currentFocus();
+    DBG_NAV_LOGD("cachedFocusNode=%d (nodePointer=%p)",
+        cachedFocusNode ? cachedFocusNode->index() : 0,
+        cachedFocusNode ? cachedFocusNode->nodePointer() : 0);
+#endif
+    gFrameCacheMutex.unlock();
+}
+
+void WebViewCore::updateFrameCacheIfLoading()
+{
+    if (!m_check_domtree_version)
+        updateFrameCache();
+}
+
 struct TouchNodeData {
-    Node* mUrlNode;
-    Node* mInnerNode;
+    Node* mNode;
     IntRect mBounds;
 };
 
@@ -1419,8 +1668,6 @@
 static IntRect getAbsoluteBoundingBox(Node* node) {
     IntRect rect;
     RenderObject* render = node->renderer();
-    if (!render)
-        return rect;
     if (render->isRenderInline())
         rect = toRenderInline(render)->linesVisualOverflowBoundingBox();
     else if (render->isBox())
@@ -1428,395 +1675,30 @@
     else if (render->isText())
         rect = toRenderText(render)->linesBoundingBox();
     else
-        ALOGE("getAbsoluteBoundingBox failed for node %p, name %s", node, render->renderName());
-    FloatPoint absPos = render->localToAbsolute(FloatPoint(), false, true);
+        LOGE("getAbsoluteBoundingBox failed for node %p, name %s", node, render->renderName());
+    FloatPoint absPos = render->localToAbsolute();
     rect.move(absPos.x(), absPos.y());
     return rect;
 }
 
-WebCore::Frame* WebViewCore::focusedFrame() const
-{
-    return m_mainFrame->page()->focusController()->focusedOrMainFrame();
-}
-
-VisiblePosition WebViewCore::visiblePositionForContentPoint(int x, int y)
-{
-    return visiblePositionForContentPoint(IntPoint(x, y));
-}
-
-VisiblePosition WebViewCore::visiblePositionForContentPoint(const IntPoint& point)
-{
-    // Hit test of this kind required for this to work inside input fields
-    HitTestRequest request(HitTestRequest::Active
-                           | HitTestRequest::MouseMove
-                           | HitTestRequest::ReadOnly
-                           | HitTestRequest::IgnoreClipping);
-    HitTestResult result(point);
-    focusedFrame()->document()->renderView()->layer()->hitTest(request, result);
-
-    // Matching the logic in MouseEventWithHitTestResults::targetNode()
-    Node* node = result.innerNode();
-    if (!node)
-        return VisiblePosition();
-    Element* element = node->parentElement();
-    if (!node->inDocument() && element && element->inDocument())
-        node = element;
-
-    return node->renderer()->positionForPoint(result.localPoint());
-}
-
-bool WebViewCore::selectWordAt(int x, int y)
-{
-    HitTestResult hoverResult;
-    moveMouse(x, y, &hoverResult);
-    if (hoverResult.innerNode()) {
-        Node* node = hoverResult.innerNode();
-        Frame* frame = node->document()->frame();
-        Page* page = m_mainFrame->document()->page();
-        page->focusController()->setFocusedFrame(frame);
-    }
-
-    IntPoint point = convertGlobalContentToFrameContent(IntPoint(x, y));
-
-    // Hit test of this kind required for this to work inside input fields
-    HitTestRequest request(HitTestRequest::Active);
-    HitTestResult result(point);
-
-    focusedFrame()->document()->renderView()->layer()->hitTest(request, result);
-
-    // Matching the logic in MouseEventWithHitTestResults::targetNode()
-    Node* node = result.innerNode();
-    if (!node)
-        return false;
-    Element* element = node->parentElement();
-    if (!node->inDocument() && element && element->inDocument())
-        node = element;
-
-    SelectionController* sc = focusedFrame()->selection();
-    bool wordSelected = false;
-    if (!sc->contains(point) && (node->isContentEditable() || node->isTextNode()) && !result.isLiveLink()
-            && node->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true))) {
-        VisiblePosition pos(node->renderer()->positionForPoint(result.localPoint()));
-        wordSelected = selectWordAroundPosition(node->document()->frame(), pos);
-    }
-    return wordSelected;
-}
-
-bool WebViewCore::selectWordAroundPosition(Frame* frame, VisiblePosition pos)
-{
-    VisibleSelection selection(pos);
-    selection.expandUsingGranularity(WordGranularity);
-    SelectionController* selectionController = frame->selection();
-
-    bool wordSelected = false;
-    if (selectionController->shouldChangeSelection(selection)) {
-        bool allWhitespaces = true;
-        RefPtr<Range> firstRange = selection.firstRange();
-        String text = firstRange.get() ? firstRange->text() : "";
-        for (size_t i = 0; i < text.length(); ++i) {
-            if (!isSpaceOrNewline(text[i])) {
-                allWhitespaces = false;
-                break;
-            }
-        }
-        if (allWhitespaces) {
-            VisibleSelection emptySelection(pos);
-            selectionController->setSelection(emptySelection);
-        } else {
-            selectionController->setSelection(selection);
-            wordSelected = true;
-        }
-    }
-    return wordSelected;
-}
-
-int WebViewCore::platformLayerIdFromNode(Node* node, LayerAndroid** outLayer)
-{
-    if (!node || !node->renderer())
-        return -1;
-    RenderLayer* renderLayer = node->renderer()->enclosingLayer();
-    while (renderLayer && !renderLayer->isComposited())
-        renderLayer = renderLayer->parent();
-    if (!renderLayer || !renderLayer->isComposited())
-        return -1;
-    GraphicsLayer* graphicsLayer = renderLayer->backing()->graphicsLayer();
-    if (!graphicsLayer)
-        return -1;
-    GraphicsLayerAndroid* agl = static_cast<GraphicsLayerAndroid*>(graphicsLayer);
-    LayerAndroid* layer = agl->foregroundLayer();
-    if (!layer)
-        layer = agl->contentLayer();
-    if (!layer)
-        return -1;
-    if (outLayer)
-        *outLayer = layer;
-    return layer->uniqueId();
-}
-
-void WebViewCore::layerToAbsoluteOffset(const LayerAndroid* layer, IntPoint& offset)
-{
-    while (layer) {
-        const SkPoint& pos = layer->getPosition();
-        offset.move(pos.fX, pos.fY);
-        const IntPoint& scroll = layer->getScrollOffset();
-        offset.move(-scroll.x(), -scroll.y());
-        layer = static_cast<LayerAndroid*>(layer->getParent());
-    }
-}
-
-void WebViewCore::setSelectionCaretInfo(SelectText* selectTextContainer,
-        const WebCore::Position& pos, const IntPoint& frameOffset,
-        SelectText::HandleId handleId, int caretRectOffset, EAffinity affinity)
-{
-    Node* node = pos.anchorNode();
-    LayerAndroid* layer = 0;
-    int layerId = platformLayerIdFromNode(node, &layer);
-    selectTextContainer->setCaretLayerId(handleId, layerId);
-    IntPoint offset = frameOffset;
-    layerToAbsoluteOffset(layer, offset);
-    RenderObject* r = node->renderer();
-    RenderText* renderText = toRenderText(r);
-    int caretOffset;
-    InlineBox* inlineBox;
-    pos.getInlineBoxAndOffset(affinity, inlineBox, caretOffset);
-    IntRect caretRect = renderText->localCaretRect(inlineBox, caretOffset);
-    FloatPoint absoluteOffset = renderText->localToAbsolute(caretRect.location());
-    caretRect.setX(absoluteOffset.x() - offset.x() + caretRectOffset);
-    caretRect.setY(absoluteOffset.y() - offset.y());
-    selectTextContainer->setCaretRect(handleId, caretRect);
-    selectTextContainer->setTextRect(handleId,
-            positionToTextRect(pos, affinity, offset));
-}
-
-bool WebViewCore::isLtr(const Position& position)
-{
-    InlineBox* inlineBox = 0;
-    int caretOffset = 0;
-    position.getInlineBoxAndOffset(DOWNSTREAM, inlineBox, caretOffset);
-    bool isLtr;
-    if (inlineBox)
-        isLtr = inlineBox->isLeftToRightDirection();
-    else
-        isLtr = position.primaryDirection() == LTR;
-    return isLtr;
-}
-
-SelectText* WebViewCore::createSelectText(const VisibleSelection& selection)
-{
-    bool isCaret = selection.isCaret();
-    if (selection.isNone() || (!selection.isContentEditable() && isCaret)
-            || !selection.start().anchorNode()
-            || !selection.start().anchorNode()->renderer()
-            || !selection.end().anchorNode()
-            || !selection.end().anchorNode()->renderer())
-        return 0;
-
-    RefPtr<Range> range = selection.firstRange();
-    Node* startContainer = range->startContainer();
-    Node* endContainer = range->endContainer();
-
-    if (!startContainer || !endContainer)
-        return 0;
-    if (!isCaret && startContainer == endContainer
-            && range->startOffset() == range->endOffset())
-        return 0;
-
-    IntPoint frameOffset = convertGlobalContentToFrameContent(IntPoint());
-    SelectText* selectTextContainer = new SelectText();
-    if (isCaret) {
-        setSelectionCaretInfo(selectTextContainer, selection.start(), frameOffset,
-                SelectText::LeftHandle, 0, selection.affinity());
-        setSelectionCaretInfo(selectTextContainer, selection.start(), frameOffset,
-                SelectText::RightHandle, 0, selection.affinity());
-    } else {
-        bool ltr = isLtr(selection.start());
-        Position left = ltr ? selection.start() : selection.end();
-        Position right = ltr ? selection.end() : selection.start();
-        int leftOffset = isLtr(left) ? 0 : -1;
-        int rightOffset = isLtr(right) ? 0 : -1;
-        setSelectionCaretInfo(selectTextContainer, left, frameOffset,
-                SelectText::LeftHandle, leftOffset, selection.affinity());
-        setSelectionCaretInfo(selectTextContainer, right, frameOffset,
-                SelectText::RightHandle, rightOffset, selection.affinity());
-
-        Node* stopNode = range->pastLastNode();
-        for (Node* node = range->firstNode(); node != stopNode; node = node->traverseNextNode()) {
-            RenderObject* r = node->renderer();
-            if (!r || !r->isText() || r->style()->visibility() != VISIBLE)
-                continue;
-            RenderText* renderText = toRenderText(r);
-            int startOffset = node == startContainer ? range->startOffset() : 0;
-            int endOffset = node == endContainer ? range->endOffset() : numeric_limits<int>::max();
-            LayerAndroid* layer = 0;
-            int layerId = platformLayerIdFromNode(node, &layer);
-            Vector<IntRect> rects;
-            renderText->absoluteRectsForRange(rects, startOffset, endOffset, true);
-            selectTextContainer->addHighlightRegion(layer, rects, frameOffset);
-        }
-    }
-    selectTextContainer->setText(range->text());
-    return selectTextContainer;
-}
-
-IntRect WebViewCore::positionToTextRect(const Position& position,
-        EAffinity affinity, const WebCore::IntPoint& offset)
-{
-    IntRect textRect;
-    InlineBox* inlineBox;
-    int offsetIndex;
-    position.getInlineBoxAndOffset(affinity, inlineBox, offsetIndex);
-    if (inlineBox && inlineBox->isInlineTextBox()) {
-        InlineTextBox* box = static_cast<InlineTextBox*>(inlineBox);
-        RootInlineBox* root = box->root();
-        RenderText* renderText = box->textRenderer();
-        int left = root->logicalLeft();
-        int width = root->logicalWidth();
-        int top = root->selectionTop();
-        int height = root->selectionHeight();
-
-        if (!renderText->style()->isHorizontalWritingMode()) {
-            swap(left, top);
-            swap(width, height);
-        }
-        FloatPoint origin(left, top);
-        FloatPoint absoluteOrigin = renderText->localToAbsolute(origin);
-
-        textRect.setX(absoluteOrigin.x() - offset.x());
-        textRect.setWidth(width);
-        textRect.setY(absoluteOrigin.y() - offset.y());
-        textRect.setHeight(height);
-    }
-    return textRect;
-}
-
-IntPoint WebViewCore::convertGlobalContentToFrameContent(const IntPoint& point, WebCore::Frame* frame)
-{
-    if (!frame) frame = focusedFrame();
-    IntPoint frameOffset(-m_scrollOffsetX, -m_scrollOffsetY);
-    frameOffset = frame->view()->windowToContents(frameOffset);
-    return IntPoint(point.x() + frameOffset.x(), point.y() + frameOffset.y());
-}
-
-Position WebViewCore::trimSelectionPosition(const Position &start, const Position& stop)
-{
-    int direction = comparePositions(start, stop);
-    if (direction == 0)
-        return start;
-    bool forward = direction < 0;
-    EAffinity affinity = forward ? DOWNSTREAM : UPSTREAM;
-    bool move;
-    Position pos = start;
-    bool movedTooFar = false;
-    do {
-        move = true;
-        Node* node = pos.anchorNode();
-        if (node && node->isTextNode() && node->renderer()) {
-            RenderText *textRenderer = toRenderText(node->renderer());
-            move = !textRenderer->textLength();
-        }
-        if (move) {
-            Position nextPos = forward ? pos.next() : pos.previous();
-            movedTooFar = nextPos.isNull() || pos == nextPos
-                    || ((comparePositions(nextPos, stop) < 0) != forward);
-            pos = nextPos;
-        }
-    } while (move && !movedTooFar);
-    if (movedTooFar)
-        pos = stop;
-    return pos;
-}
-
-void WebViewCore::selectText(int startX, int startY, int endX, int endY)
-{
-    SelectionController* sc = focusedFrame()->selection();
-    IntPoint startPoint = convertGlobalContentToFrameContent(IntPoint(startX, startY));
-    VisiblePosition startPosition(visiblePositionForContentPoint(startPoint));
-    IntPoint endPoint = convertGlobalContentToFrameContent(IntPoint(endX, endY));
-    VisiblePosition endPosition(visiblePositionForContentPoint(endPoint));
-
-    if (startPosition.isNull() || endPosition.isNull())
-        return;
-
-    // Ensure startPosition is before endPosition
-    if (comparePositions(startPosition, endPosition) > 0)
-        swap(startPosition, endPosition);
-
-    if (sc->isContentEditable()) {
-        startPosition = sc->selection().visibleStart().honorEditableBoundaryAtOrAfter(startPosition);
-        endPosition = sc->selection().visibleEnd().honorEditableBoundaryAtOrBefore(endPosition);
-        if (startPosition.isNull() || endPosition.isNull()) {
-            return;
-        }
-    }
-
-    // Ensure startPosition is not at end of block
-    if (startPosition != endPosition && isEndOfBlock(startPosition)) {
-        VisiblePosition nextStartPosition(startPosition.next());
-        if (!nextStartPosition.isNull())
-            startPosition = nextStartPosition;
-    }
-    // Ensure endPosition is not at start of block
-    if (startPosition != endPosition && isStartOfBlock(endPosition)) {
-        VisiblePosition prevEndPosition(endPosition.previous());
-        if (!prevEndPosition.isNull())
-            endPosition = prevEndPosition;
-    }
-
-    Position start = startPosition.deepEquivalent();
-    Position end = endPosition.deepEquivalent();
-    start = trimSelectionPosition(start, end);
-    end = trimSelectionPosition(end, start);
-    VisibleSelection selection(start, end);
-    // Only allow changes between caret positions or to text selection.
-    bool selectChangeAllowed = (!selection.isCaret() || sc->isCaret());
-    if (selectChangeAllowed && sc->shouldChangeSelection(selection))
-        sc->setSelection(selection);
-}
-
-bool WebViewCore::nodeIsClickableOrFocusable(Node* node)
-{
-    if (!node)
-        return false;
-    if (node->disabled())
-        return false;
-    if (!node->inDocument())
-        return false;
-    if (!node->renderer() || node->renderer()->style()->visibility() != VISIBLE)
-        return false;
-    return node->supportsFocus()
-            || node->hasEventListeners(eventNames().clickEvent)
-            || node->hasEventListeners(eventNames().mousedownEvent)
-            || node->hasEventListeners(eventNames().mouseupEvent)
-            || node->hasEventListeners(eventNames().mouseoverEvent);
-}
-
 // get the highlight rectangles for the touch point (x, y) with the slop
-AndroidHitTestResult WebViewCore::hitTestAtPoint(int x, int y, int slop, bool doMoveMouse)
+Vector<IntRect> WebViewCore::getTouchHighlightRects(int x, int y, int slop)
 {
-    if (doMoveMouse)
-        moveMouse(x, y, 0, true);
+    Vector<IntRect> rects;
+    m_mousePos = IntPoint(x - m_scrollOffsetX, y - m_scrollOffsetY);
     HitTestResult hitTestResult = m_mainFrame->eventHandler()->hitTestResultAtPoint(IntPoint(x, y),
             false, false, DontHitTestScrollbars, HitTestRequest::Active | HitTestRequest::ReadOnly, IntSize(slop, slop));
-    AndroidHitTestResult androidHitResult(this, hitTestResult);
     if (!hitTestResult.innerNode() || !hitTestResult.innerNode()->inDocument()) {
-        ALOGE("Should not happen: no in document Node found");
-        return androidHitResult;
+        LOGE("Should not happen: no in document Node found");
+        return rects;
     }
     const ListHashSet<RefPtr<Node> >& list = hitTestResult.rectBasedTestResult();
     if (list.isEmpty()) {
-        ALOGE("Should not happen: no rect-based-test nodes found");
-        return androidHitResult;
+        LOGE("Should not happen: no rect-based-test nodes found");
+        return rects;
     }
     Frame* frame = hitTestResult.innerNode()->document()->frame();
     Vector<TouchNodeData> nodeDataList;
-    if (hitTestResult.innerNode() != hitTestResult.innerNonSharedNode()
-            && hitTestResult.innerNode()->hasTagName(WebCore::HTMLNames::areaTag)) {
-        HTMLAreaElement* area = static_cast<HTMLAreaElement*>(hitTestResult.innerNode());
-        androidHitResult.hitTestResult().setURLElement(area);
-        androidHitResult.highlightRects().append(area->computeRect(
-                hitTestResult.innerNonSharedNode()->renderer()));
-        return androidHitResult;
-    }
     ListHashSet<RefPtr<Node> >::const_iterator last = list.end();
     for (ListHashSet<RefPtr<Node> >::const_iterator it = list.begin(); it != last; ++it) {
         // TODO: it seems reasonable to not search across the frame. Isn't it?
@@ -1826,12 +1708,14 @@
         // traverse up the tree to find the first node that needs highlight
         bool found = false;
         Node* eventNode = it->get();
-        Node* innerNode = eventNode;
         while (eventNode) {
             RenderObject* render = eventNode->renderer();
             if (render && (render->isBody() || render->isRenderView()))
                 break;
-            if (nodeIsClickableOrFocusable(eventNode)) {
+            if (eventNode->supportsFocus()
+                    || eventNode->hasEventListeners(eventNames().clickEvent)
+                    || eventNode->hasEventListeners(eventNames().mousedownEvent)
+                    || eventNode->hasEventListeners(eventNames().mouseupEvent)) {
                 found = true;
                 break;
             }
@@ -1863,7 +1747,7 @@
         Vector<TouchNodeData>::const_iterator nlast = nodeDataList.end();
         for (Vector<TouchNodeData>::const_iterator n = nodeDataList.begin(); n != nlast; ++n) {
             // found the same node, skip it
-            if (eventNode == n->mUrlNode) {
+            if (eventNode == n->mNode) {
                 found = false;
                 break;
             }
@@ -1904,19 +1788,16 @@
         }
         if (!found) {
             TouchNodeData newNode;
-            newNode.mUrlNode = eventNode;
+            newNode.mNode = eventNode;
             newNode.mBounds = rect;
-            newNode.mInnerNode = innerNode;
             nodeDataList.append(newNode);
         }
     }
-    if (!nodeDataList.size()) {
-        androidHitResult.searchContentDetectors();
-        return androidHitResult;
-    }
+    if (!nodeDataList.size())
+        return rects;
     // finally select the node with the largest overlap with the fat point
     TouchNodeData final;
-    final.mUrlNode = 0;
+    final.mNode = 0;
     IntPoint docPos = frame->view()->windowToContents(m_mousePos);
     IntRect testRect(docPos.x() - slop, docPos.y() - slop, 2 * slop + 1, 2 * slop + 1);
     int area = 0;
@@ -1925,47 +1806,101 @@
         IntRect rect = n->mBounds;
         rect.intersect(testRect);
         int a = rect.width() * rect.height();
-        if (a > area || !final.mUrlNode) {
+        if (a > area) {
             final = *n;
             area = a;
         }
     }
     // now get the node's highlight rectangles in the page coordinate system
-    if (final.mUrlNode) {
-        // Update innerNode and innerNonSharedNode
-        androidHitResult.hitTestResult().setInnerNode(final.mInnerNode);
-        androidHitResult.hitTestResult().setInnerNonSharedNode(final.mInnerNode);
-        if (final.mUrlNode->isElementNode()) {
-            // We found a URL element. Update the hitTestResult
-            androidHitResult.setURLElement(static_cast<Element*>(final.mUrlNode));
-        } else {
-            androidHitResult.setURLElement(0);
+    if (final.mNode) {
+        IntPoint frameAdjust;
+        if (frame != m_mainFrame) {
+            frameAdjust = frame->view()->contentsToWindow(IntPoint());
+            frameAdjust.move(m_scrollOffsetX, m_scrollOffsetY);
         }
-        Vector<IntRect>& highlightRects = androidHitResult.highlightRects();
-        if (doMoveMouse && highlightRects.size() > 0) {
-            // adjust m_mousePos if it is not inside the returned highlight
-            // rectangles
-            IntRect foundIntersection;
-            IntRect inputRect = IntRect(x - slop, y - slop,
-                                        slop * 2 + 1, slop * 2 + 1);
-            for (size_t i = 0; i < highlightRects.size(); i++) {
-                IntRect& hr = highlightRects[i];
-                IntRect test = inputRect;
-                test.intersect(hr);
-                if (!test.isEmpty()) {
-                    foundIntersection = test;
-                    break;
+        if (final.mNode->isLink()) {
+            // most of the links are inline instead of box style. So the bounding box is not
+            // a good representation for the highlights. Get the list of rectangles instead.
+            RenderObject* render = final.mNode->renderer();
+            IntPoint offset = roundedIntPoint(render->localToAbsolute());
+            render->absoluteRects(rects, offset.x() + frameAdjust.x(), offset.y() + frameAdjust.y());
+            bool inside = false;
+            int distance = INT_MAX;
+            int newx = x, newy = y;
+            int i = rects.size();
+            while (i--) {
+                if (rects[i].isEmpty()) {
+                    rects.remove(i);
+                    continue;
+                }
+                // check whether the point (x, y) is inside one of the rectangles.
+                if (inside)
+                    continue;
+                if (rects[i].contains(x, y)) {
+                    inside = true;
+                    continue;
+                }
+                if (x >= rects[i].x() && x < rects[i].maxX()) {
+                    if (y < rects[i].y()) {
+                        if (rects[i].y() - y < distance) {
+                            newx = x;
+                            newy = rects[i].y();
+                            distance = rects[i].y() - y;
+                        }
+                    } else if (y >= rects[i].maxY()) {
+                        if (y - rects[i].maxY() + 1 < distance) {
+                            newx = x;
+                            newy = rects[i].maxY() - 1;
+                            distance = y - rects[i].maxY() + 1;
+                        }
+                    }
+                } else if (y >= rects[i].y() && y < rects[i].maxY()) {
+                    if (x < rects[i].x()) {
+                        if (rects[i].x() - x < distance) {
+                            newx = rects[i].x();
+                            newy = y;
+                            distance = rects[i].x() - x;
+                        }
+                    } else if (x >= rects[i].maxX()) {
+                        if (x - rects[i].maxX() + 1 < distance) {
+                            newx = rects[i].maxX() - 1;
+                            newy = y;
+                            distance = x - rects[i].maxX() + 1;
+                        }
+                    }
                 }
             }
-            if (!foundIntersection.isEmpty() && !foundIntersection.contains(x, y)) {
-                IntPoint pt = foundIntersection.center();
-                moveMouse(pt.x(), pt.y(), 0, true);
+            if (!rects.isEmpty()) {
+                if (!inside) {
+                    // if neither x nor y has overlap, just pick the top/left of the first rectangle
+                    if (newx == x && newy == y) {
+                        newx = rects[0].x();
+                        newy = rects[0].y();
+                    }
+                    m_mousePos.setX(newx - m_scrollOffsetX);
+                    m_mousePos.setY(newy - m_scrollOffsetY);
+                    DBG_NAV_LOGD("Move x/y from (%d, %d) to (%d, %d) scrollOffset is (%d, %d)",
+                            x, y, m_mousePos.x() + m_scrollOffsetX, m_mousePos.y() + m_scrollOffsetY,
+                            m_scrollOffsetX, m_scrollOffsetY);
+                }
+                return rects;
             }
         }
-    } else {
-        androidHitResult.searchContentDetectors();
+        IntRect rect = final.mBounds;
+        rect.move(frameAdjust.x(), frameAdjust.y());
+        rects.append(rect);
+        // adjust m_mousePos if it is not inside the returned highlight rectangle
+        testRect.move(frameAdjust.x(), frameAdjust.y());
+        testRect.intersect(rect);
+        if (!testRect.contains(x, y)) {
+            m_mousePos = testRect.center();
+            m_mousePos.move(-m_scrollOffsetX, -m_scrollOffsetY);
+            DBG_NAV_LOGD("Move x/y from (%d, %d) to (%d, %d) scrollOffset is (%d, %d)",
+                    x, y, m_mousePos.x() + m_scrollOffsetX, m_mousePos.y() + m_scrollOffsetY,
+                    m_scrollOffsetX, m_scrollOffsetY);
+        }
     }
-    return androidHitResult;
+    return rects;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -2136,46 +2071,70 @@
     return 0;
 }
 
+Node* WebViewCore::cursorNodeIsPlugin() {
+    gCursorBoundsMutex.lock();
+    bool hasCursorBounds = m_hasCursorBounds;
+    Frame* frame = (Frame*) m_cursorFrame;
+    Node* node = (Node*) m_cursorNode;
+    gCursorBoundsMutex.unlock();
+    if (hasCursorBounds && CacheBuilder::validNode(m_mainFrame, frame, node)
+            && nodeIsPlugin(node)) {
+        return node;
+    }
+    return 0;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
+void WebViewCore::moveMouseIfLatest(int moveGeneration,
+    WebCore::Frame* frame, int x, int y)
+{
+    DBG_NAV_LOGD("m_moveGeneration=%d moveGeneration=%d"
+        " frame=%p x=%d y=%d",
+        m_moveGeneration, moveGeneration, frame, x, y);
+    if (m_moveGeneration > moveGeneration) {
+        DBG_NAV_LOGD("m_moveGeneration=%d > moveGeneration=%d",
+            m_moveGeneration, moveGeneration);
+        return; // short-circuit if a newer move has already been generated
+    }
+    m_lastGeneration = moveGeneration;
+    moveMouse(frame, x, y);
+}
+
+void WebViewCore::moveFocus(WebCore::Frame* frame, WebCore::Node* node)
+{
+    DBG_NAV_LOGD("frame=%p node=%p", frame, node);
+    if (!node || !CacheBuilder::validNode(m_mainFrame, frame, node)
+            || !node->isElementNode())
+        return;
+    // Code borrowed from FocusController::advanceFocus
+    WebCore::FocusController* focusController
+            = m_mainFrame->page()->focusController();
+    WebCore::Document* oldDoc
+            = focusController->focusedOrMainFrame()->document();
+    if (oldDoc->focusedNode() == node)
+        return;
+    if (node->document() != oldDoc)
+        oldDoc->setFocusedNode(0);
+    focusController->setFocusedFrame(frame);
+    static_cast<WebCore::Element*>(node)->focus(false);
+}
 
 // Update mouse position
-void WebViewCore::moveMouse(int x, int y, HitTestResult* hoveredNode, bool isClickCandidate)
+void WebViewCore::moveMouse(WebCore::Frame* frame, int x, int y)
 {
+    DBG_NAV_LOGD("frame=%p x=%d y=%d scrollOffset=(%d,%d)", frame,
+        x, y, m_scrollOffsetX, m_scrollOffsetY);
+    if (!frame || !CacheBuilder::validNode(m_mainFrame, frame, 0))
+        frame = m_mainFrame;
     // mouse event expects the position in the window coordinate
     m_mousePos = WebCore::IntPoint(x - m_scrollOffsetX, y - m_scrollOffsetY);
-    if (isClickCandidate)
-        m_mouseClickPos = m_mousePos;
     // validNode will still return true if the node is null, as long as we have
     // a valid frame.  Do not want to make a call on frame unless it is valid.
     WebCore::PlatformMouseEvent mouseEvent(m_mousePos, m_mousePos,
         WebCore::NoButton, WebCore::MouseEventMoved, 1, false, false, false,
         false, WTF::currentTime());
-    m_mainFrame->eventHandler()->handleMouseMoveEvent(mouseEvent, hoveredNode);
-}
-
-Position WebViewCore::getPositionForOffset(Node* node, int offset)
-{
-    Position start = firstPositionInNode(node);
-    Position end = lastPositionInNode(node);
-    Document* document = node->document();
-    PassRefPtr<Range> range = Range::create(document, start, end);
-    WebCore::CharacterIterator iterator(range.get());
-    iterator.advance(offset);
-    return iterator.range()->startPosition();
-}
-
-void WebViewCore::setSelection(Node* node, int start, int end)
-{
-    RenderTextControl* control = toRenderTextControl(node);
-    if (control)
-        setSelectionRange(node, start, end);
-    else {
-        Position startPosition = getPositionForOffset(node, start);
-        Position endPosition = getPositionForOffset(node, end);
-        VisibleSelection selection(startPosition, endPosition);
-        SelectionController* selector = node->document()->frame()->selection();
-        selector->setSelection(selection);
-    }
+    frame->eventHandler()->handleMouseMoveEvent(mouseEvent);
+    updateCacheOnNodeChange();
 }
 
 void WebViewCore::setSelection(int start, int end)
@@ -2183,22 +2142,28 @@
     WebCore::Node* focus = currentFocus();
     if (!focus)
         return;
-    if (start > end)
-        swap(start, end);
-
+    WebCore::RenderObject* renderer = focus->renderer();
+    if (!renderer || (!renderer->isTextField() && !renderer->isTextArea()))
+        return;
+    if (start > end) {
+        int temp = start;
+        start = end;
+        end = temp;
+    }
     // Tell our EditorClient that this change was generated from the UI, so it
     // does not need to echo it to the UI.
     EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
             m_mainFrame->editor()->client());
     client->setUiGeneratedSelectionChange(true);
-    setSelection(focus, start, end);
-    RenderTextControl* control = toRenderTextControl(focus);
-    if (start != end && control) {
+    setSelectionRange(focus, start, end);
+    if (start != end) {
         // Fire a select event. No event is sent when the selection reduces to
         // an insertion point
+        RenderTextControl* control = toRenderTextControl(renderer);
         control->selectionChanged(true);
     }
     client->setUiGeneratedSelectionChange(false);
+    WebCore::Frame* focusedFrame = focus->document()->frame();
     bool isPasswordField = false;
     if (focus->isElementNode()) {
         WebCore::Element* element = static_cast<WebCore::Element*>(focus);
@@ -2207,7 +2172,7 @@
     }
     // For password fields, this is done in the UI side via
     // bringPointIntoView, since the UI does the drawing.
-    if ((control && control->isTextArea()) || !isPasswordField)
+    if (renderer->isTextArea() || !isPasswordField)
         revealSelection();
 }
 
@@ -2232,7 +2197,7 @@
         case AXIS_DOCUMENT:
             return modifySelectionDomNavigationAxis(selection, direction, axis);
         default:
-            ALOGE("Invalid navigation axis: %d", axis);
+            LOGE("Invalid navigation axis: %d", axis);
             return String();
     }
 }
@@ -2273,9 +2238,9 @@
     // initialize the selection if necessary
     if (selection->rangeCount() == 0) {
         if (m_currentNodeDomNavigationAxis
-                && validNode(m_mainFrame,
+                && CacheBuilder::validNode(m_mainFrame,
                 m_mainFrame, m_currentNodeDomNavigationAxis)) {
-            RefPtr<Range> rangeRef =
+            PassRefPtr<Range> rangeRef =
                 selection->frame()->document()->createRange();
             rangeRef->selectNode(m_currentNodeDomNavigationAxis, ec);
             m_currentNodeDomNavigationAxis = 0;
@@ -2284,6 +2249,15 @@
             selection->addRange(rangeRef.get());
         } else if (currentFocus()) {
             selection->setPosition(currentFocus(), 0, ec);
+        } else if (m_cursorNode
+                && CacheBuilder::validNode(m_mainFrame,
+                m_mainFrame, m_cursorNode)) {
+            PassRefPtr<Range> rangeRef =
+                selection->frame()->document()->createRange();
+            rangeRef->selectNode(reinterpret_cast<Node*>(m_cursorNode), ec);
+            if (ec)
+                return String();
+            selection->addRange(rangeRef.get());
         } else {
             selection->setPosition(body, 0, ec);
         }
@@ -2482,13 +2456,13 @@
         scrollNodeIntoView(m_mainFrame, selection->anchorNode());
 
     // format markup for the visible content
-    RefPtr<Range> range = selection->getRangeAt(0, ec);
+    PassRefPtr<Range> range = selection->getRangeAt(0, ec);
     if (ec)
         return String();
     IntRect bounds = range->boundingBox();
     selectAt(bounds.center().x(), bounds.center().y());
     markup = formatMarkup(selection);
-    ALOGV("Selection markup: %s", markup.utf8().data());
+    LOGV("Selection markup: %s", markup.utf8().data());
 
     return markup;
 }
@@ -2696,7 +2670,7 @@
     if (!m_currentNodeDomNavigationAxis)
         m_currentNodeDomNavigationAxis = currentFocus();
     if (!m_currentNodeDomNavigationAxis
-            || !validNode(m_mainFrame, m_mainFrame,
+            || !CacheBuilder::validNode(m_mainFrame, m_mainFrame,
                                         m_currentNodeDomNavigationAxis))
         m_currentNodeDomNavigationAxis = body;
     Node* currentNode = m_currentNodeDomNavigationAxis;
@@ -2740,14 +2714,14 @@
         if (direction == DIRECTION_FORWARD)
             currentNode = currentNode->lastDescendant();
     } else {
-        ALOGE("Invalid axis: %d", axis);
+        LOGE("Invalid axis: %d", axis);
         return String();
     }
     if (currentNode) {
         m_currentNodeDomNavigationAxis = currentNode;
         scrollNodeIntoView(m_mainFrame, currentNode);
         String selectionString = createMarkup(currentNode);
-        ALOGV("Selection markup: %s", selectionString.utf8().data());
+        LOGV("Selection markup: %s", selectionString.utf8().data());
         return selectionString;
     }
     return String();
@@ -2797,7 +2771,7 @@
     while (currentNode && currentNode != body) {
         RenderStyle* style = currentNode->computedStyle();
         if (style &&
-                (style->display() == WebCore::NONE || style->visibility() == WebCore::HIDDEN)) {
+                (style->display() == NONE || style->visibility() == HIDDEN)) {
             return false;
         }
         currentNode = currentNode->parentNode();
@@ -2809,7 +2783,7 @@
 {
     ExceptionCode ec = 0;
     String markup = String();
-    RefPtr<Range> wholeRange = selection->getRangeAt(0, ec);
+    PassRefPtr<Range> wholeRange = selection->getRangeAt(0, ec);
     if (ec)
         return String();
     if (!wholeRange->startContainer() || !wholeRange->startContainer())
@@ -2819,7 +2793,7 @@
     Node* firstNode = wholeRange->firstNode();
     Node* pastLastNode = wholeRange->pastLastNode();
     Node* currentNode = firstNode;
-    RefPtr<Range> currentRange;
+    PassRefPtr<Range> currentRange;
 
     while (currentNode != pastLastNode) {
         Node* nextNode = currentNode->traverseNextNode();
@@ -2896,6 +2870,7 @@
     key(up);
     client->setUiGeneratedSelectionChange(false);
     m_textGeneration = textGeneration;
+    m_shouldPaintCaret = true;
 }
 
 void WebViewCore::replaceTextfieldText(int oldStart,
@@ -2911,15 +2886,13 @@
     EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
             m_mainFrame->editor()->client());
     client->setUiGeneratedSelectionChange(true);
-    if (replace.length())
-        WebCore::TypingCommand::insertText(focus->document(), replace,
-                false);
-    else
-        WebCore::TypingCommand::deleteSelection(focus->document());
+    WebCore::TypingCommand::insertText(focus->document(), replace,
+        false);
     client->setUiGeneratedSelectionChange(false);
     // setSelection calls revealSelection, so there is no need to do it here.
     setSelection(start, end);
     m_textGeneration = textGeneration;
+    m_shouldPaintCaret = true;
 }
 
 void WebViewCore::passToJs(int generation, const WTF::String& current,
@@ -2927,6 +2900,13 @@
 {
     WebCore::Node* focus = currentFocus();
     if (!focus) {
+        DBG_NAV_LOG("!focus");
+        clearTextEntry();
+        return;
+    }
+    WebCore::RenderObject* renderer = focus->renderer();
+    if (!renderer || (!renderer->isTextField() && !renderer->isTextArea())) {
+        DBG_NAV_LOGD("renderer==%p || not text", renderer);
         clearTextEntry();
         return;
     }
@@ -2941,36 +2921,42 @@
     client->setUiGeneratedSelectionChange(false);
     m_blockTextfieldUpdates = false;
     m_textGeneration = generation;
-    WTF::String test = getInputText(focus);
+    WebCore::RenderTextControl* renderText =
+        static_cast<WebCore::RenderTextControl*>(renderer);
+    WTF::String test = renderText->text();
     if (test != current) {
         // If the text changed during the key event, update the UI text field.
         updateTextfield(focus, false, test);
+    } else {
+        DBG_NAV_LOG("test == current");
     }
     // Now that the selection has settled down, send it.
     updateTextSelection();
+    m_shouldPaintCaret = true;
 }
 
-WebCore::IntRect WebViewCore::scrollFocusedTextInput(float xPercent, int y)
+void WebViewCore::scrollFocusedTextInput(float xPercent, int y)
 {
     WebCore::Node* focus = currentFocus();
     if (!focus) {
+        DBG_NAV_LOG("!focus");
         clearTextEntry();
-        return WebCore::IntRect();
+        return;
     }
-    WebCore::RenderTextControl* renderText = toRenderTextControl(focus);
-    if (!renderText) {
+    WebCore::RenderObject* renderer = focus->renderer();
+    if (!renderer || (!renderer->isTextField() && !renderer->isTextArea())) {
+        DBG_NAV_LOGD("renderer==%p || not text", renderer);
         clearTextEntry();
-        return WebCore::IntRect();
+        return;
     }
-
+    WebCore::RenderTextControl* renderText =
+        static_cast<WebCore::RenderTextControl*>(renderer);
     int x = (int) (xPercent * (renderText->scrollWidth() -
         renderText->clientWidth()));
+    DBG_NAV_LOGD("x=%d y=%d xPercent=%g scrollW=%d clientW=%d", x, y,
+        xPercent, renderText->scrollWidth(), renderText->clientWidth());
     renderText->setScrollLeft(x);
     renderText->setScrollTop(y);
-    focus->document()->frame()->selection()->recomputeCaretRect();
-    LayerAndroid* layer = 0;
-    platformLayerIdFromNode(focus, &layer);
-    return absoluteContentRect(focus, layer);
 }
 
 void WebViewCore::setFocusControllerActive(bool active)
@@ -2980,7 +2966,7 @@
 
 void WebViewCore::saveDocumentState(WebCore::Frame* frame)
 {
-    if (!validNode(m_mainFrame, frame, 0))
+    if (!CacheBuilder::validNode(m_mainFrame, frame, 0))
         frame = m_mainFrame;
     WebCore::HistoryItem *item = frame->loader()->history()->currentItem();
 
@@ -2996,9 +2982,9 @@
 static jobjectArray makeLabelArray(JNIEnv* env, const uint16_t** labels, size_t count)
 {
     jclass stringClass = env->FindClass("java/lang/String");
-    ALOG_ASSERT(stringClass, "Could not find java/lang/String");
+    LOG_ASSERT(stringClass, "Could not find java/lang/String");
     jobjectArray array = env->NewObjectArray(count, stringClass, 0);
-    ALOG_ASSERT(array, "Could not create new string array");
+    LOG_ASSERT(array, "Could not create new string array");
 
     for (size_t i = 0; i < count; i++) {
         jobject newString = env->NewString(&labels[i][1], labels[i][0]);
@@ -3021,19 +3007,11 @@
         return;
 
     WTF::String acceptType = chooser->acceptTypes();
-    WTF::String capture;
-
-#if ENABLE(MEDIA_CAPTURE)
-    capture = chooser->capture();
-#endif
-
     jstring jAcceptType = wtfStringToJstring(env, acceptType, true);
-    jstring jCapture = wtfStringToJstring(env, capture, true);
     jstring jName = (jstring) env->CallObjectMethod(
-            javaObject.get(), m_javaGlue->m_openFileChooser, jAcceptType, jCapture);
+            javaObject.get(), m_javaGlue->m_openFileChooser, jAcceptType);
     checkException(env);
     env->DeleteLocalRef(jAcceptType);
-    env->DeleteLocalRef(jCapture);
 
     WTF::String wtfString = jstringToWtfString(env, jName);
     env->DeleteLocalRef(jName);
@@ -3045,7 +3023,7 @@
 void WebViewCore::listBoxRequest(WebCoreReply* reply, const uint16_t** labels, size_t count, const int enabled[], size_t enabledCount,
         bool multiple, const int selected[], size_t selectedCountOrSelection)
 {
-    ALOG_ASSERT(m_javaGlue->m_obj, "No java widget associated with this view!");
+    LOG_ASSERT(m_javaGlue->m_obj, "No java widget associated with this view!");
 
     JNIEnv* env = JSC::Bindings::getJNIEnv();
     AutoJObject javaObject = m_javaGlue->object(env);
@@ -3104,15 +3082,14 @@
 {
     WebCore::EventHandler* eventHandler;
     WebCore::Node* focusNode = currentFocus();
+    DBG_NAV_LOGD("keyCode=%s unichar=%d focusNode=%p",
+        event.keyIdentifier().utf8().data(), event.unichar(), focusNode);
     if (focusNode) {
         WebCore::Frame* frame = focusNode->document()->frame();
+        WebFrame* webFrame = WebFrame::getWebFrame(frame);
         eventHandler = frame->eventHandler();
         VisibleSelection old = frame->selection()->selection();
-        EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
-                m_mainFrame->editor()->client());
-        client->setUiGeneratedSelectionChange(true);
         bool handled = eventHandler->keyEvent(event);
-        client->setUiGeneratedSelectionChange(false);
         if (isContentEditable(focusNode)) {
             // keyEvent will return true even if the contentEditable did not
             // change its selection.  In the case that it does not, we want to
@@ -3122,53 +3099,33 @@
         }
         return handled;
     } else {
-        eventHandler = focusedFrame()->eventHandler();
+        eventHandler = m_mainFrame->eventHandler();
     }
     return eventHandler->keyEvent(event);
 }
 
-bool WebViewCore::chromeCanTakeFocus(FocusDirection direction)
-{
-    JNIEnv* env = JSC::Bindings::getJNIEnv();
-    AutoJObject javaObject = m_javaGlue->object(env);
-    if (!javaObject.get())
-        return false;
-    return env->CallBooleanMethod(javaObject.get(), m_javaGlue->m_chromeCanTakeFocus, direction);
-}
-
-void WebViewCore::chromeTakeFocus(FocusDirection direction)
-{
-    JNIEnv* env = JSC::Bindings::getJNIEnv();
-    AutoJObject javaObject = m_javaGlue->object(env);
-    if (!javaObject.get())
-        return;
-    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_chromeTakeFocus, direction);
-}
-
-void WebViewCore::setInitialFocus(const WebCore::PlatformKeyboardEvent& platformEvent)
-{
-    Frame* frame = focusedFrame();
-    Document* document = frame->document();
-    if (document)
-        document->setFocusedNode(0);
-    FocusDirection direction;
-    switch (platformEvent.nativeVirtualKeyCode()) {
-    case AKEYCODE_DPAD_LEFT:
-        direction = FocusDirectionLeft;
-        break;
-    case AKEYCODE_DPAD_RIGHT:
-        direction = FocusDirectionRight;
-        break;
-    case AKEYCODE_DPAD_UP:
-        direction = FocusDirectionUp;
-        break;
-    default:
-        direction = FocusDirectionDown;
-        break;
+// For when the user clicks the trackball, presses dpad center, or types into an
+// unfocused textfield.  In the latter case, 'fake' will be true
+void WebViewCore::click(WebCore::Frame* frame, WebCore::Node* node, bool fake) {
+    if (!node) {
+        WebCore::IntPoint pt = m_mousePos;
+        pt.move(m_scrollOffsetX, m_scrollOffsetY);
+        WebCore::HitTestResult hitTestResult = m_mainFrame->eventHandler()->
+                hitTestResultAtPoint(pt, false);
+        node = hitTestResult.innerNode();
+        frame = node->document()->frame();
+        DBG_NAV_LOGD("m_mousePos=(%d,%d) m_scrollOffset=(%d,%d) pt=(%d,%d)"
+            " node=%p", m_mousePos.x(), m_mousePos.y(),
+            m_scrollOffsetX, m_scrollOffsetY, pt.x(), pt.y(), node);
     }
-    RefPtr<KeyboardEvent> webkitEvent = KeyboardEvent::create(platformEvent, 0);
-    m_mainFrame->page()->focusController()->setInitialFocus(direction,
-            webkitEvent.get());
+    if (node) {
+        EditorClientAndroid* client
+                = static_cast<EditorClientAndroid*>(
+                m_mainFrame->editor()->client());
+        client->setShouldChangeSelectedRange(false);
+        handleMouseClick(frame, node, fake);
+        client->setShouldChangeSelectedRange(true);
+    }
 }
 
 #if USE(ACCELERATED_COMPOSITING)
@@ -3182,9 +3139,9 @@
 }
 #endif
 
-int WebViewCore::handleTouchEvent(int action, Vector<int>& ids, Vector<IntPoint>& points, int actionIndex, int metaState)
+bool WebViewCore::handleTouchEvent(int action, Vector<int>& ids, Vector<IntPoint>& points, int actionIndex, int metaState)
 {
-    int flags = 0;
+    bool preventDefault = false;
 
 #if USE(ACCELERATED_COMPOSITING)
     GraphicsLayerAndroid* rootLayer = graphicsRootLayer();
@@ -3225,10 +3182,18 @@
         type = WebCore::TouchEnd;
         defaultTouchState = WebCore::PlatformTouchPoint::TouchStationary;
         break;
+    case 0x100: // WebViewCore.ACTION_LONGPRESS
+        type = WebCore::TouchLongPress;
+        defaultTouchState = WebCore::PlatformTouchPoint::TouchPressed;
+        break;
+    case 0x200: // WebViewCore.ACTION_DOUBLETAP
+        type = WebCore::TouchDoubleTap;
+        defaultTouchState = WebCore::PlatformTouchPoint::TouchPressed;
+        break;
     default:
         // We do not support other kinds of touch event inside WebCore
         // at the moment.
-        ALOGW("Java passed a touch event type that we do not support in WebCore: %d", action);
+        LOGW("Java passed a touch event type that we do not support in WebCore: %d", action);
         return 0;
     }
 
@@ -3248,41 +3213,52 @@
     }
 
     WebCore::PlatformTouchEvent te(ids, points, type, touchStates, metaState);
-    if (m_mainFrame->eventHandler()->handleTouchEvent(te))
-        flags |= TOUCH_FLAG_PREVENT_DEFAULT;
-    if (te.hitTouchHandler())
-        flags |= TOUCH_FLAG_HIT_HANDLER;
+    preventDefault = m_mainFrame->eventHandler()->handleTouchEvent(te);
 #endif
 
 #if USE(ACCELERATED_COMPOSITING)
     if (rootLayer)
       rootLayer->pauseDisplay(false);
 #endif
-    return flags;
+    return preventDefault;
 }
 
-bool WebViewCore::performMouseClick()
+void WebViewCore::touchUp(int touchGeneration,
+    WebCore::Frame* frame, WebCore::Node* node, int x, int y)
 {
-    WebCore::PlatformMouseEvent mouseDown(m_mouseClickPos, m_mouseClickPos, WebCore::LeftButton,
-            WebCore::MouseEventPressed, 1, false, false, false, false,
-            WTF::currentTime());
-    // ignore the return from as it will return true if the hit point can trigger selection change
-    m_mainFrame->eventHandler()->handleMousePressEvent(mouseDown);
-    WebCore::PlatformMouseEvent mouseUp(m_mouseClickPos, m_mouseClickPos, WebCore::LeftButton,
-            WebCore::MouseEventReleased, 1, false, false, false, false,
-            WTF::currentTime());
-    bool handled = m_mainFrame->eventHandler()->handleMouseReleaseEvent(mouseUp);
-
-    WebCore::Node* focusNode = currentFocus();
-    initializeTextInput(focusNode, false);
-    return handled;
+    if (touchGeneration == 0) {
+        // m_mousePos should be set in getTouchHighlightRects()
+        WebCore::HitTestResult hitTestResult = m_mainFrame->eventHandler()->hitTestResultAtPoint(m_mousePos, false);
+        node = hitTestResult.innerNode();
+        if (node)
+            frame = node->document()->frame();
+        else
+            frame = 0;
+        DBG_NAV_LOGD("touch up on (%d, %d), scrollOffset is (%d, %d), node:%p, frame:%p", m_mousePos.x() + m_scrollOffsetX, m_mousePos.y() + m_scrollOffsetY, m_scrollOffsetX, m_scrollOffsetY, node, frame);
+    } else {
+        if (m_touchGeneration > touchGeneration) {
+            DBG_NAV_LOGD("m_touchGeneration=%d > touchGeneration=%d"
+                " x=%d y=%d", m_touchGeneration, touchGeneration, x, y);
+            return; // short circuit if a newer touch has been generated
+        }
+        // This moves m_mousePos to the correct place, and handleMouseClick uses
+        // m_mousePos to determine where the click happens.
+        moveMouse(frame, x, y);
+        m_lastGeneration = touchGeneration;
+    }
+    if (frame && CacheBuilder::validNode(m_mainFrame, frame, 0)) {
+        frame->loader()->resetMultipleFormSubmissionProtection();
+    }
+    DBG_NAV_LOGD("touchGeneration=%d handleMouseClick frame=%p node=%p"
+        " x=%d y=%d", touchGeneration, frame, node, x, y);
+    handleMouseClick(frame, node, false);
 }
 
 // Check for the "x-webkit-soft-keyboard" attribute.  If it is there and
 // set to hidden, do not show the soft keyboard.  Node passed as a parameter
 // must not be null.
 static bool shouldSuppressKeyboard(const WebCore::Node* node) {
-    ALOG_ASSERT(node, "node passed to shouldSuppressKeyboard cannot be null");
+    LOG_ASSERT(node, "node passed to shouldSuppressKeyboard cannot be null");
     const NamedNodeMap* attributes = node->attributes();
     if (!attributes) return false;
     size_t length = attributes->length();
@@ -3294,160 +3270,84 @@
     return false;
 }
 
-WebViewCore::InputType WebViewCore::getInputType(Node* node)
+// Common code for both clicking with the trackball and touchUp
+// Also used when typing into a non-focused textfield to give the textfield focus,
+// in which case, 'fake' is set to true
+bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* nodePtr, bool fake)
 {
-    WebCore::RenderObject* renderer = node->renderer();
-    if (!renderer)
-        return WebViewCore::NONE;
-    if (renderer->isTextArea())
-        return WebViewCore::TEXT_AREA;
-
-    if (node->hasTagName(WebCore::HTMLNames::inputTag)) {
-        HTMLInputElement* htmlInput = static_cast<HTMLInputElement*>(node);
-        if (htmlInput->isPasswordField())
-            return WebViewCore::PASSWORD;
-        if (htmlInput->isSearchField())
-            return WebViewCore::SEARCH;
-        if (htmlInput->isEmailField())
-            return WebViewCore::EMAIL;
-        if (htmlInput->isNumberField())
-            return WebViewCore::NUMBER;
-        if (htmlInput->isTelephoneField())
-            return WebViewCore::TELEPHONE;
-        if (htmlInput->isTextField())
-            return WebViewCore::NORMAL_TEXT_FIELD;
-    }
-
-    if (node->isContentEditable())
-        return WebViewCore::TEXT_AREA;
-
-    return WebViewCore::NONE;
-}
-
-int WebViewCore::getMaxLength(Node* node)
-{
-    int maxLength = -1;
-    if (node->hasTagName(WebCore::HTMLNames::inputTag)) {
-        HTMLInputElement* htmlInput = static_cast<HTMLInputElement*>(node);
-        maxLength = htmlInput->maxLength();
-    }
-    return maxLength;
-}
-
-String WebViewCore::getFieldName(Node* node)
-{
-    String name;
-    if (node->hasTagName(WebCore::HTMLNames::inputTag)) {
-        HTMLInputElement* htmlInput = static_cast<HTMLInputElement*>(node);
-        name = htmlInput->name();
-    }
-    return name;
-}
-
-bool WebViewCore::isSpellCheckEnabled(Node* node)
-{
-    bool isEnabled = true;
-    if (node->isElementNode()) {
-        WebCore::Element* element = static_cast<WebCore::Element*>(node);
-        isEnabled = element->isSpellCheckingEnabled();
-    }
-    return isEnabled;
-}
-
-bool WebViewCore::isAutoCompleteEnabled(Node* node)
-{
-    bool isEnabled = false;
-    if (node->hasTagName(WebCore::HTMLNames::inputTag)) {
-        HTMLInputElement* htmlInput = static_cast<HTMLInputElement*>(node);
-        isEnabled = htmlInput->autoComplete();
-    }
-    return isEnabled;
-}
-
-WebCore::IntRect WebViewCore::absoluteContentRect(WebCore::Node* node,
-        LayerAndroid* layer)
-{
-    IntRect contentRect;
-    if (node) {
-        RenderObject* render = node->renderer();
-        if (render && render->isBox() && !render->isBody()) {
-            IntPoint offset = convertGlobalContentToFrameContent(IntPoint(),
-                    node->document()->frame());
-            WebViewCore::layerToAbsoluteOffset(layer, offset);
-
-            RenderBox* renderBox = toRenderBox(render);
-            contentRect = renderBox->absoluteContentBox();
-            contentRect.move(-offset.x(), -offset.y());
+    bool valid = !framePtr || CacheBuilder::validNode(m_mainFrame, framePtr, nodePtr);
+    WebFrame* webFrame = WebFrame::getWebFrame(m_mainFrame);
+    if (valid && nodePtr) {
+    // Need to special case area tags because an image map could have an area element in the middle
+    // so when attempting to get the default, the point chosen would be follow the wrong link.
+        if (nodePtr->hasTagName(WebCore::HTMLNames::areaTag)) {
+            webFrame->setUserInitiatedAction(true);
+            nodePtr->dispatchSimulatedClick(0, true, true);
+            webFrame->setUserInitiatedAction(false);
+            DBG_NAV_LOG("area");
+            return true;
         }
     }
-    return contentRect;
-}
+    if (!valid || !framePtr)
+        framePtr = m_mainFrame;
+    webFrame->setUserInitiatedAction(true);
+    WebCore::PlatformMouseEvent mouseDown(m_mousePos, m_mousePos, WebCore::LeftButton,
+            WebCore::MouseEventPressed, 1, false, false, false, false,
+            WTF::currentTime());
+    // ignore the return from as it will return true if the hit point can trigger selection change
+    framePtr->eventHandler()->handleMousePressEvent(mouseDown);
+    WebCore::PlatformMouseEvent mouseUp(m_mousePos, m_mousePos, WebCore::LeftButton,
+            WebCore::MouseEventReleased, 1, false, false, false, false,
+            WTF::currentTime());
+    bool handled = framePtr->eventHandler()->handleMouseReleaseEvent(mouseUp);
+    webFrame->setUserInitiatedAction(false);
 
-jobject WebViewCore::createTextFieldInitData(Node* node)
-{
-    JNIEnv* env = JSC::Bindings::getJNIEnv();
-    TextFieldInitDataGlue* classDef = m_textFieldInitDataGlue;
-    ScopedLocalRef<jclass> clazz(env,
-            env->FindClass("android/webkit/WebViewCore$TextFieldInitData"));
-    jobject initData = env->NewObject(clazz.get(), classDef->m_constructor);
-    env->SetIntField(initData, classDef->m_fieldPointer,
-            reinterpret_cast<int>(node));
-    ScopedLocalRef<jstring> inputText(env,
-            wtfStringToJstring(env, getInputText(node), true));
-    env->SetObjectField(initData, classDef->m_text, inputText.get());
-    env->SetIntField(initData, classDef->m_type, getInputType(node));
-    env->SetBooleanField(initData, classDef->m_isSpellCheckEnabled,
-            isSpellCheckEnabled(node));
-    Document* document = node->document();
-    PlatformKeyboardEvent tab(AKEYCODE_TAB, 0, 0, false, false, false, false);
-    PassRefPtr<KeyboardEvent> tabEvent =
-            KeyboardEvent::create(tab, document->defaultView());
-    env->SetBooleanField(initData, classDef->m_isTextFieldNext,
-            isTextInput(document->nextFocusableNode(node, tabEvent.get())));
-    env->SetBooleanField(initData, classDef->m_isTextFieldPrev,
-            isTextInput(document->previousFocusableNode(node, tabEvent.get())));
-    env->SetBooleanField(initData, classDef->m_isAutoCompleteEnabled,
-            isAutoCompleteEnabled(node));
-    ScopedLocalRef<jstring> fieldName(env,
-            wtfStringToJstring(env, getFieldName(node), false));
-    env->SetObjectField(initData, classDef->m_name, fieldName.get());
-    ScopedLocalRef<jstring> label(env,
-            wtfStringToJstring(env, requestLabel(document->frame(), node), false));
-    env->SetObjectField(initData, classDef->m_label, label.get());
-    env->SetIntField(initData, classDef->m_maxLength, getMaxLength(node));
-    LayerAndroid* layer = 0;
-    int layerId = platformLayerIdFromNode(node, &layer);
-    IntRect bounds = absoluteContentRect(node, layer);
-    ScopedLocalRef<jobject> jbounds(env, intRectToRect(env, bounds));
-    env->SetObjectField(initData, classDef->m_contentBounds, jbounds.get());
-    env->SetIntField(initData, classDef->m_nodeLayerId, layerId);
-    IntRect contentRect;
-    RenderTextControl* rtc = toRenderTextControl(node);
-    if (rtc) {
-        contentRect.setWidth(rtc->scrollWidth());
-        contentRect.setHeight(rtc->scrollHeight());
-        contentRect.move(-rtc->scrollLeft(), -rtc->scrollTop());
+    // If the user clicked on a textfield, make the focusController active
+    // so we show the blinking cursor.
+    WebCore::Node* focusNode = currentFocus();
+    DBG_NAV_LOGD("m_mousePos={%d,%d} focusNode=%p handled=%s", m_mousePos.x(),
+        m_mousePos.y(), focusNode, handled ? "true" : "false");
+    if (focusNode) {
+        WebCore::RenderObject* renderer = focusNode->renderer();
+        if (renderer && (renderer->isTextField() || renderer->isTextArea())) {
+            bool ime = !shouldSuppressKeyboard(focusNode)
+                    && !(static_cast<WebCore::HTMLInputElement*>(focusNode))->readOnly();
+            if (ime) {
+#if ENABLE(WEB_AUTOFILL)
+                if (renderer->isTextField()) {
+                    EditorClientAndroid* editorC = static_cast<EditorClientAndroid*>(framePtr->page()->editorClient());
+                    WebAutofill* autoFill = editorC->getAutofill();
+                    autoFill->formFieldFocused(static_cast<HTMLFormControlElement*>(focusNode));
+                }
+#endif
+                if (!fake) {
+                    RenderTextControl* rtc
+                            = static_cast<RenderTextControl*> (renderer);
+                    // Force an update of the navcache as this will fire off a
+                    // message to WebView that *must* have an updated focus.
+                    m_frameCacheOutOfDate = true;
+                    updateFrameCache();
+                    requestKeyboardWithSelection(focusNode, rtc->selectionStart(),
+                            rtc->selectionEnd());
+                }
+            } else if (!fake) {
+                requestKeyboard(false);
+            }
+        } else if (!fake){
+            // If the selection is contentEditable, show the keyboard so the
+            // user can type.  Otherwise hide the keyboard because no text
+            // input is needed.
+            if (isContentEditable(focusNode)) {
+                requestKeyboard(true);
+            } else if (!nodeIsPlugin(focusNode)) {
+                clearTextEntry();
+            }
+        }
+    } else if (!fake) {
+        // There is no focusNode, so the keyboard is not needed.
+        clearTextEntry();
     }
-    ScopedLocalRef<jobject> jcontentRect(env, intRectToRect(env, contentRect));
-    env->SetObjectField(initData, classDef->m_contentRect, jcontentRect.get());
-    return initData;
-}
-
-void WebViewCore::initEditField(Node* node)
-{
-    JNIEnv* env = JSC::Bindings::getJNIEnv();
-    AutoJObject javaObject = m_javaGlue->object(env);
-    if (!javaObject.get())
-        return;
-    m_textGeneration = 0;
-    int start = 0;
-    int end = 0;
-    getSelectionOffsets(node, start, end);
-    SelectText* selectText = createSelectText(focusedFrame()->selection()->selection());
-    ScopedLocalRef<jobject> initData(env, createTextFieldInitData(node));
-    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_initEditField,
-            start, end, reinterpret_cast<int>(selectText), initData.get());
-    checkException(env);
+    return handled;
 }
 
 void WebViewCore::popupReply(int index)
@@ -3468,99 +3368,28 @@
     }
 }
 
-// This is a slightly modified Node::nextNodeConsideringAtomicNodes() with the
-// extra constraint of limiting the search to inside a containing parent
-WebCore::Node* nextNodeWithinParent(WebCore::Node* parent, WebCore::Node* start)
+void WebViewCore::formDidBlur(const WebCore::Node* node)
 {
-    if (!isAtomicNode(start) && start->firstChild())
-        return start->firstChild();
-    if (start->nextSibling())
-        return start->nextSibling();
-    const Node *n = start;
-    while (n && !n->nextSibling()) {
-        n = n->parentNode();
-        if (n == parent)
-            return 0;
-    }
-    if (n)
-        return n->nextSibling();
-    return 0;
+    // If the blur is on a text input, keep track of the node so we can
+    // hide the soft keyboard when the new focus is set, if it is not a
+    // text input.
+    if (isTextInput(node))
+        m_blurringNodePointer = reinterpret_cast<int>(node);
 }
 
-void WebViewCore::initializeTextInput(WebCore::Node* node, bool fake)
+void WebViewCore::focusNodeChanged(const WebCore::Node* newFocus)
 {
-    if (node) {
-        if (isTextInput(node)) {
-            bool showKeyboard = true;
-            initEditField(node);
-            WebCore::RenderTextControl* rtc = toRenderTextControl(node);
-            if (rtc && node->hasTagName(HTMLNames::inputTag)) {
-                HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(node);
-                bool ime = !shouldSuppressKeyboard(node) && !inputElement->readOnly();
-                if (ime) {
-#if ENABLE(WEB_AUTOFILL)
-                    if (rtc->isTextField()) {
-                        Page* page = node->document()->page();
-                        EditorClient* editorClient = page->editorClient();
-                        EditorClientAndroid* androidEditor =
-                                static_cast<EditorClientAndroid*>(editorClient);
-                        WebAutofill* autoFill = androidEditor->getAutofill();
-                        autoFill->formFieldFocused(inputElement);
-                    }
-#endif
-                } else
-                    showKeyboard = false;
-            }
-            if (!fake)
-                requestKeyboard(showKeyboard);
-        } else if (!fake && !nodeIsPlugin(node)) {
-            // not a text entry field, put away the keyboard.
-            clearTextEntry();
-        }
-    } else if (!fake) {
-        // There is no focusNode, so the keyboard is not needed.
-        clearTextEntry();
-    }
-}
-
-void WebViewCore::focusNodeChanged(WebCore::Node* newFocus)
-{
-    JNIEnv* env = JSC::Bindings::getJNIEnv();
-    AutoJObject javaObject = m_javaGlue->object(env);
-    if (!javaObject.get())
-        return;
     if (isTextInput(newFocus))
-        initializeTextInput(newFocus, true);
-    HitTestResult focusHitResult;
-    focusHitResult.setInnerNode(newFocus);
-    focusHitResult.setInnerNonSharedNode(newFocus);
-    if (newFocus && newFocus->isLink() && newFocus->isElementNode()) {
-        focusHitResult.setURLElement(static_cast<Element*>(newFocus));
-        if (newFocus->hasChildNodes() && !newFocus->hasTagName(HTMLNames::imgTag)) {
-            // Check to see if any of the children are images, and if so
-            // set them as the innerNode and innerNonSharedNode
-            // This will stop when it hits the first image. I'm not sure what
-            // should be done in the case of multiple images inside one anchor...
-            Node* nextNode = newFocus->firstChild();
-            bool found = false;
-            while (nextNode) {
-                if (nextNode->hasTagName(HTMLNames::imgTag)) {
-                    found = true;
-                    break;
-                }
-                nextNode = nextNodeWithinParent(newFocus, nextNode);
-            }
-            if (found) {
-                focusHitResult.setInnerNode(nextNode);
-                focusHitResult.setInnerNonSharedNode(nextNode);
-            }
-        }
+        m_shouldPaintCaret = true;
+    else if (m_blurringNodePointer) {
+        JNIEnv* env = JSC::Bindings::getJNIEnv();
+        AutoJObject javaObject = m_javaGlue->object(env);
+        if (!javaObject.get())
+            return;
+        env->CallVoidMethod(javaObject.get(), m_javaGlue->m_formDidBlur, m_blurringNodePointer);
+        checkException(env);
+        m_blurringNodePointer = 0;
     }
-    AndroidHitTestResult androidHitTest(this, focusHitResult);
-    jobject jHitTestObj = androidHitTest.createJavaObject(env);
-    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_focusNodeChanged,
-            reinterpret_cast<int>(newFocus), jHitTestObj);
-    env->DeleteLocalRef(jHitTestObj);
 }
 
 void WebViewCore::addMessageToConsole(const WTF::String& message, unsigned int lineNumber, const WTF::String& sourceID, int msgLevel) {
@@ -3759,57 +3588,7 @@
     AutoJObject javaObject = m_javaGlue->object(env);
     if (!javaObject.get())
         return 0;
-    return env->CallObjectMethod(javaObject.get(), m_javaGlue->m_getWebView);
-}
-
-RenderTextControl* WebViewCore::toRenderTextControl(Node* node)
-{
-    RenderTextControl* rtc = 0;
-    RenderObject* renderer = node->renderer();
-    if (renderer && renderer->isTextControl()) {
-        rtc = WebCore::toRenderTextControl(renderer);
-    }
-    return rtc;
-}
-
-void WebViewCore::getSelectionOffsets(Node* node, int& start, int& end)
-{
-    RenderTextControl* rtc = toRenderTextControl(node);
-    if (rtc) {
-        start = rtc->selectionStart();
-        end = rtc->selectionEnd();
-    } else {
-        // It must be content editable field.
-        Document* document = node->document();
-        Frame* frame = document->frame();
-        SelectionController* selector = frame->selection();
-        Position selectionStart = selector->start();
-        Position selectionEnd = selector->end();
-        Position startOfNode = firstPositionInNode(node);
-        RefPtr<Range> startRange = Range::create(document, startOfNode,
-                selectionStart);
-        start = TextIterator::rangeLength(startRange.get(), true);
-        RefPtr<Range> endRange = Range::create(document, startOfNode,
-                selectionEnd);
-        end = TextIterator::rangeLength(endRange.get(), true);
-    }
-}
-
-String WebViewCore::getInputText(Node* node)
-{
-    String text;
-    WebCore::RenderTextControl* renderText = toRenderTextControl(node);
-    if (renderText)
-        text = renderText->text();
-    else {
-        // It must be content editable field.
-        Position start = firstPositionInNode(node);
-        Position end = lastPositionInNode(node);
-        VisibleSelection allEditableText(start, end);
-        if (allEditableText.isRange())
-            text = allEditableText.firstRange()->text();
-    }
-    return text;
+    return env->GetObjectField(javaObject.get(), gWebViewCoreFields.m_webView);
 }
 
 void WebViewCore::updateTextSelection()
@@ -3818,33 +3597,16 @@
     AutoJObject javaObject = m_javaGlue->object(env);
     if (!javaObject.get())
         return;
-    VisibleSelection selection = focusedFrame()->selection()->selection();
-    int start = 0;
-    int end = 0;
-    if (selection.isCaretOrRange())
-        getSelectionOffsets(selection.start().anchorNode(), start, end);
-    SelectText* selectText = createSelectText(selection);
+    WebCore::Node* focusNode = currentFocus();
+    if (!focusNode)
+        return;
+    RenderObject* renderer = focusNode->renderer();
+    if (!renderer || (!renderer->isTextArea() && !renderer->isTextField()))
+        return;
+    RenderTextControl* rtc = static_cast<RenderTextControl*>(renderer);
     env->CallVoidMethod(javaObject.get(),
-            m_javaGlue->m_updateTextSelection, reinterpret_cast<int>(currentFocus()),
-            start, end, m_textGeneration, reinterpret_cast<int>(selectText));
-    checkException(env);
-}
-
-void WebViewCore::updateTextSizeAndScroll(WebCore::Node* node)
-{
-    JNIEnv* env = JSC::Bindings::getJNIEnv();
-    AutoJObject javaObject = m_javaGlue->object(env);
-    if (!javaObject.get())
-        return;
-    RenderTextControl* rtc = toRenderTextControl(node);
-    if (!rtc)
-        return;
-    int width = rtc->scrollWidth();
-    int height = rtc->contentHeight();
-    int scrollX = rtc->scrollLeft();
-    int scrollY = rtc->scrollTop();
-    env->CallVoidMethod(javaObject.get(), m_javaGlue->m_updateTextSizeAndScroll,
-            reinterpret_cast<int>(node), width, height, scrollX, scrollY);
+            m_javaGlue->m_updateTextSelection, reinterpret_cast<int>(focusNode),
+            rtc->selectionStart(), rtc->selectionEnd(), m_textGeneration);
     checkException(env);
 }
 
@@ -3888,18 +3650,11 @@
     // need (int) cast to find the right constructor
     WebCore::Color bcolor((int)SkColorGetR(c), (int)SkColorGetG(c),
                           (int)SkColorGetB(c), (int)SkColorGetA(c));
-
-    if (view->baseBackgroundColor() == bcolor)
-        return;
-
     view->setBaseBackgroundColor(bcolor);
 
     // Background color of 0 indicates we want a transparent background
     if (c == 0)
         view->setTransparent(true);
-
-    //invalidate so the new color is shown
-    contentInvalidateAll();
 }
 
 jclass WebViewCore::getPluginClass(const WTF::String& libName, const char* className)
@@ -4025,6 +3780,21 @@
         m_screenOnCounter--;
 }
 
+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;
+}
+
 void WebViewCore::showRect(int left, int top, int width, int height,
         int contentWidth, int contentHeight, float xPercentInDoc,
         float xPercentInView, float yPercentInDoc, float yPercentInView)
@@ -4078,20 +3848,6 @@
         return;
     jstring jUrlStr = wtfStringToJstring(env, url);
     env->CallVoidMethod(javaObject.get(), m_javaGlue->m_enterFullscreenForVideoLayer, layerId, jUrlStr);
-    m_fullscreenVideoMode = true;
-    checkException(env);
-}
-
-void WebViewCore::exitFullscreenVideo()
-{
-    JNIEnv* env = JSC::Bindings::getJNIEnv();
-    AutoJObject javaObject = m_javaGlue->object(env);
-    if (!javaObject.get())
-        return;
-    if (m_fullscreenVideoMode) {
-        env->CallVoidMethod(javaObject.get(), m_javaGlue->m_exitFullscreenVideo);
-        m_fullscreenVideoMode = false;
-    }
     checkException(env);
 }
 #endif
@@ -4117,6 +3873,7 @@
     return false;
 }
 
+#if USE(CHROME_NETWORK_STACK)
 void WebViewCore::setWebRequestContextUserAgent()
 {
     // We cannot create a WebRequestContext, because we might not know it this is a private tab or not yet
@@ -4144,6 +3901,7 @@
     }
     return m_webRequestContext.get();
 }
+#endif
 
 void WebViewCore::scrollRenderLayer(int layer, const SkRect& rect)
 {
@@ -4164,370 +3922,189 @@
     if (!owner)
         return;
 
-    if (owner->isRootLayer()) {
-        FrameView* view = owner->renderer()->frame()->view();
-        IntPoint pt(rect.fLeft, rect.fTop);
-        view->setScrollPosition(pt);
-    } else
+    if (owner->stackingContext())
         owner->scrollToOffset(rect.fLeft, rect.fTop);
 #endif
 }
 
-Vector<VisibleSelection> WebViewCore::getTextRanges(
-        int startX, int startY, int endX, int endY)
-{
-    // These are the positions of the selection handles,
-    // which reside below the line that they are selecting.
-    // Use the vertical position higher, which will include
-    // the selected text.
-    startY--;
-    endY--;
-    VisiblePosition startSelect = visiblePositionForContentPoint(startX, startY);
-    VisiblePosition endSelect =  visiblePositionForContentPoint(endX, endY);
-    Position start = startSelect.deepEquivalent();
-    Position end = endSelect.deepEquivalent();
-    Vector<VisibleSelection> ranges;
-    if (!start.isNull() && !end.isNull()) {
-        if (comparePositions(start, end) > 0) {
-            swap(start, end); // RTL start/end positions may be swapped
-        }
-        Position nextRangeStart = start;
-        Position previousRangeEnd;
-        do {
-            VisibleSelection selection(nextRangeStart, end);
-            ranges.append(selection);
-            previousRangeEnd = selection.end();
-            nextRangeStart = nextCandidate(previousRangeEnd);
-        } while (comparePositions(previousRangeEnd, end) < 0);
-    }
-    return ranges;
-}
-
-void WebViewCore::deleteText(int startX, int startY, int endX, int endY)
-{
-    Vector<VisibleSelection> ranges =
-            getTextRanges(startX, startY, endX, endY);
-
-    EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
-            m_mainFrame->editor()->client());
-    client->setUiGeneratedSelectionChange(true);
-
-    SelectionController* selector = m_mainFrame->selection();
-    for (size_t i = 0; i < ranges.size(); i++) {
-        const VisibleSelection& selection = ranges[i];
-        if (selection.isContentEditable()) {
-            selector->setSelection(selection, CharacterGranularity);
-            Document* document = selection.start().anchorNode()->document();
-            WebCore::TypingCommand::deleteSelection(document, 0);
-        }
-    }
-    client->setUiGeneratedSelectionChange(false);
-}
-
-void WebViewCore::insertText(const WTF::String &text)
-{
-    WebCore::Node* focus = currentFocus();
-    if (!focus || !isTextInput(focus))
-        return;
-
-    Document* document = focus->document();
-
-    EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
-            m_mainFrame->editor()->client());
-    if (!client)
-        return;
-    client->setUiGeneratedSelectionChange(true);
-    WebCore::TypingCommand::insertText(document, text,
-            TypingCommand::PreventSpellChecking);
-    client->setUiGeneratedSelectionChange(false);
-}
-
-void WebViewCore::resetFindOnPage()
-{
-    m_searchText.truncate(0);
-    m_matchCount = 0;
-    m_activeMatchIndex = 0;
-    m_activeMatch = 0;
-}
-
-int WebViewCore::findTextOnPage(const WTF::String &text)
-{
-    resetFindOnPage(); // reset even if parameters are bad
-
-    WebCore::Frame* frame = m_mainFrame;
-    if (!frame)
-        return 0;
-
-    m_searchText = text;
-    FindOptions findOptions = WebCore::CaseInsensitive;
-
-    do {
-        frame->document()->markers()->removeMarkers(DocumentMarker::TextMatch);
-        m_matchCount += frame->editor()->countMatchesForText(text, findOptions,
-            0, true);
-        frame->editor()->setMarkedTextMatchesAreHighlighted(true);
-        frame = frame->tree()->traverseNextWithWrap(false);
-    } while (frame);
-    m_activeMatchIndex = m_matchCount - 1; // prime first findNext
-    return m_matchCount;
-}
-
-int WebViewCore::findNextOnPage(bool forward)
-{
-    if (!m_mainFrame)
-        return -1;
-    if (!m_matchCount)
-        return -1;
-
-    EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
-        m_mainFrame->editor()->client());
-    client->setUiGeneratedSelectionChange(true);
-
-    // Clear previous active match.
-    if (m_activeMatch) {
-        m_mainFrame->document()->markers()->setMarkersActive(
-            m_activeMatch.get(), false);
-    }
-
-    FindOptions findOptions = WebCore::CaseInsensitive
-        | WebCore::StartInSelection | WebCore::WrapAround;
-    if (!forward)
-        findOptions |= WebCore::Backwards;
-
-    // Start from the previous active match.
-    if (m_activeMatch) {
-        m_mainFrame->selection()->setSelection(m_activeMatch.get());
-    }
-
-    bool found = m_mainFrame->editor()->findString(m_searchText, findOptions);
-    if (found) {
-        VisibleSelection selection(m_mainFrame->selection()->selection());
-        if (selection.isNone() || selection.start() == selection.end()) {
-            // Temporary workaround for findString() refusing to select text
-            // marked "-webkit-user-select: none".
-            m_activeMatchIndex = 0;
-            m_activeMatch = 0;
-        } else {
-            // Mark current match "active".
-            if (forward) {
-                ++m_activeMatchIndex;
-                if (m_activeMatchIndex == m_matchCount)
-                    m_activeMatchIndex = 0;
-            } else {
-                if (m_activeMatchIndex == 0)
-                    m_activeMatchIndex = m_matchCount;
-                --m_activeMatchIndex;
-            }
-            m_activeMatch = selection.firstRange();
-            m_mainFrame->document()->markers()->setMarkersActive(
-                m_activeMatch.get(), true);
-            m_mainFrame->selection()->revealSelection(
-                ScrollAlignment::alignCenterIfNeeded, true);
-        }
-    }
-
-    // Clear selection so it doesn't display.
-    m_mainFrame->selection()->clear();
-    client->setUiGeneratedSelectionChange(false);
-    return m_activeMatchIndex;
-}
-
-String WebViewCore::getText(int startX, int startY, int endX, int endY)
-{
-    String text;
-
-    Vector<VisibleSelection> ranges =
-            getTextRanges(startX, startY, endX, endY);
-
-    for (size_t i = 0; i < ranges.size(); i++) {
-        const VisibleSelection& selection = ranges[i];
-        if (selection.isRange()) {
-            PassRefPtr<Range> range = selection.firstRange();
-            String textInRange = range->text();
-            if (textInRange.length() > 0) {
-                if (text.length() > 0)
-                    text.append('\n');
-                text.append(textInRange);
-            }
-        }
-    }
-
-    return text;
-}
-
-/**
- * Read the persistent locale.
- */
-void WebViewCore::getLocale(String& language, String& region)
-{
-    char propLang[PROPERTY_VALUE_MAX], propRegn[PROPERTY_VALUE_MAX];
-
-    property_get("persist.sys.language", propLang, "");
-    property_get("persist.sys.country", propRegn, "");
-    if (*propLang == 0 && *propRegn == 0) {
-        /* Set to ro properties, default is en_US */
-        property_get("ro.product.locale.language", propLang, "en");
-        property_get("ro.product.locale.region", propRegn, "US");
-    }
-    language = String(propLang, 2);
-    region = String(propRegn, 2);
-}
-
-void WebViewCore::updateLocale()
-{
-    static String prevLang;
-    static String prevRegn;
-    String language;
-    String region;
-
-    getLocale(language, region);
-
-    if ((language != prevLang) || (region != prevRegn)) {
-        prevLang = language;
-        prevRegn = region;
-        GlyphPageTreeNode::resetRoots();
-        fontCache()->invalidate();
-    }
-}
-
 //----------------------------------------------------------------------
 // Native JNI methods
 //----------------------------------------------------------------------
-static void RevealSelection(JNIEnv* env, jobject obj, jint nativeClass)
+static void RevealSelection(JNIEnv *env, jobject obj)
 {
-    reinterpret_cast<WebViewCore*>(nativeClass)->revealSelection();
+    GET_NATIVE_VIEW(env, obj)->revealSelection();
 }
 
-static jstring RequestLabel(JNIEnv* env, jobject obj, jint nativeClass,
-        int framePointer, int nodePointer)
+static jstring RequestLabel(JNIEnv *env, jobject obj, int framePointer,
+        int nodePointer)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    return wtfStringToJstring(env, viewImpl->requestLabel(
+    return wtfStringToJstring(env, GET_NATIVE_VIEW(env, obj)->requestLabel(
             (WebCore::Frame*) framePointer, (WebCore::Node*) nodePointer));
 }
 
-static void ClearContent(JNIEnv* env, jobject obj, jint nativeClass)
+static void ClearContent(JNIEnv *env, jobject obj)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
     viewImpl->clearContent();
 }
 
-static void SetSize(JNIEnv* env, jobject obj, jint nativeClass, jint width,
-        jint height, jint textWrapWidth, jfloat scale, jint screenWidth,
-        jint screenHeight, jint anchorX, jint anchorY, jboolean ignoreHeight)
+static void UpdateFrameCacheIfLoading(JNIEnv *env, jobject obj)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ALOGV("webviewcore::nativeSetSize(%u %u)\n viewImpl: %p", (unsigned)width, (unsigned)height, viewImpl);
-    ALOG_ASSERT(viewImpl, "viewImpl not set in nativeSetSize");
+    GET_NATIVE_VIEW(env, obj)->updateFrameCacheIfLoading();
+}
+
+static void SetSize(JNIEnv *env, jobject obj, jint width, jint height,
+        jint textWrapWidth, jfloat scale, jint screenWidth, jint screenHeight,
+        jint anchorX, jint anchorY, jboolean ignoreHeight)
+{
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOGV("webviewcore::nativeSetSize(%u %u)\n viewImpl: %p", (unsigned)width, (unsigned)height, viewImpl);
+    LOG_ASSERT(viewImpl, "viewImpl not set in nativeSetSize");
     viewImpl->setSizeScreenWidthAndScale(width, height, textWrapWidth, scale,
             screenWidth, screenHeight, anchorX, anchorY, ignoreHeight);
 }
 
-static void SetScrollOffset(JNIEnv* env, jobject obj, jint nativeClass,
-        jboolean sendScrollEvent, jint x, jint y)
+static void SetScrollOffset(JNIEnv *env, jobject obj, jint gen, jboolean sendScrollEvent, jint x, jint y)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ALOG_ASSERT(viewImpl, "need viewImpl");
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "need viewImpl");
 
-    viewImpl->setScrollOffset(sendScrollEvent, x, y);
+    viewImpl->setScrollOffset(gen, sendScrollEvent, x, y);
 }
 
-static void SetGlobalBounds(JNIEnv* env, jobject obj, jint nativeClass,
-        jint x, jint y, jint h, jint v)
+static void SetGlobalBounds(JNIEnv *env, jobject obj, jint x, jint y, jint h,
+                            jint v)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ALOG_ASSERT(viewImpl, "need viewImpl");
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "need viewImpl");
 
     viewImpl->setGlobalBounds(x, y, h, v);
 }
 
-static jboolean Key(JNIEnv* env, jobject obj, jint nativeClass, jint keyCode,
-        jint unichar, jint repeatCount, jboolean isShift, jboolean isAlt,
-        jboolean isSym, jboolean isDown)
+static jboolean Key(JNIEnv *env, jobject obj, jint keyCode, jint unichar,
+        jint repeatCount, jboolean isShift, jboolean isAlt, jboolean isSym,
+        jboolean isDown)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    return viewImpl->key(PlatformKeyboardEvent(keyCode,
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    return GET_NATIVE_VIEW(env, obj)->key(PlatformKeyboardEvent(keyCode,
         unichar, repeatCount, isDown, isShift, isAlt, isSym));
 }
 
-static void SetInitialFocus(JNIEnv* env, jobject obj, jint nativeClass,
-                            jint keyDirection)
+static void Click(JNIEnv *env, jobject obj, int framePtr, int nodePtr, jboolean fake)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    viewImpl->setInitialFocus(PlatformKeyboardEvent(keyDirection,
-            0, 0, false, false, false, false));
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in Click");
+
+    viewImpl->click(reinterpret_cast<WebCore::Frame*>(framePtr),
+        reinterpret_cast<WebCore::Node*>(nodePtr), fake);
 }
 
-static void ContentInvalidateAll(JNIEnv* env, jobject obj, jint nativeClass)
+static void ContentInvalidateAll(JNIEnv *env, jobject obj)
 {
-    reinterpret_cast<WebViewCore*>(nativeClass)->contentInvalidateAll();
+    GET_NATIVE_VIEW(env, obj)->contentInvalidateAll();
 }
 
-static void DeleteSelection(JNIEnv* env, jobject obj, jint nativeClass,
-        jint start, jint end, jint textGeneration)
+static void DeleteSelection(JNIEnv *env, jobject obj, jint start, jint end,
+        jint textGeneration)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
     viewImpl->deleteSelection(start, end, textGeneration);
 }
 
-static void SetSelection(JNIEnv* env, jobject obj, jint nativeClass,
-        jint start, jint end)
+static void SetSelection(JNIEnv *env, jobject obj, jint start, jint end)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
     viewImpl->setSelection(start, end);
 }
 
-static jstring ModifySelection(JNIEnv* env, jobject obj, jint nativeClass,
-        jint direction, jint granularity)
+static jstring ModifySelection(JNIEnv *env, jobject obj, jint direction, jint granularity)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
     String selectionString = viewImpl->modifySelection(direction, granularity);
     return wtfStringToJstring(env, selectionString);
 }
 
-static void ReplaceTextfieldText(JNIEnv* env, jobject obj, jint nativeClass,
+static void ReplaceTextfieldText(JNIEnv *env, jobject obj,
     jint oldStart, jint oldEnd, jstring replace, jint start, jint end,
     jint textGeneration)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
     WTF::String webcoreString = jstringToWtfString(env, replace);
     viewImpl->replaceTextfieldText(oldStart,
             oldEnd, webcoreString, start, end, textGeneration);
 }
 
-static void PassToJs(JNIEnv* env, jobject obj, jint nativeClass,
+static void PassToJs(JNIEnv *env, jobject obj,
     jint generation, jstring currentText, jint keyCode,
     jint keyValue, jboolean down, jboolean cap, jboolean fn, jboolean sym)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
     WTF::String current = jstringToWtfString(env, currentText);
-    reinterpret_cast<WebViewCore*>(nativeClass)->passToJs(generation, current,
+    GET_NATIVE_VIEW(env, obj)->passToJs(generation, current,
         PlatformKeyboardEvent(keyCode, keyValue, 0, down, cap, fn, sym));
 }
 
-static void ScrollFocusedTextInput(JNIEnv* env, jobject obj, jint nativeClass,
-        jfloat xPercent, jint y, jobject contentBounds)
+static void ScrollFocusedTextInput(JNIEnv *env, jobject obj, jfloat xPercent,
+    jint y)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    IntRect bounds = viewImpl->scrollFocusedTextInput(xPercent, y);
-    if (contentBounds)
-        GraphicsJNI::irect_to_jrect(bounds, env, contentBounds);
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    viewImpl->scrollFocusedTextInput(xPercent, y);
 }
 
-static void SetFocusControllerActive(JNIEnv* env, jobject obj, jint nativeClass,
-        jboolean active)
+static void SetFocusControllerActive(JNIEnv *env, jobject obj, jboolean active)
 {
-    ALOGV("webviewcore::nativeSetFocusControllerActive()\n");
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ALOG_ASSERT(viewImpl, "viewImpl not set in nativeSetFocusControllerActive");
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    LOGV("webviewcore::nativeSetFocusControllerActive()\n");
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in nativeSetFocusControllerActive");
     viewImpl->setFocusControllerActive(active);
 }
 
-static void SaveDocumentState(JNIEnv* env, jobject obj, jint nativeClass)
+static void SaveDocumentState(JNIEnv *env, jobject obj, jint frame)
 {
-    ALOGV("webviewcore::nativeSaveDocumentState()\n");
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ALOG_ASSERT(viewImpl, "viewImpl not set in nativeSaveDocumentState");
-    viewImpl->saveDocumentState(viewImpl->focusedFrame());
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    LOGV("webviewcore::nativeSaveDocumentState()\n");
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in nativeSaveDocumentState");
+    viewImpl->saveDocumentState((WebCore::Frame*) frame);
 }
 
 void WebViewCore::addVisitedLink(const UChar* string, int length)
@@ -4536,26 +4113,53 @@
         m_groupForVisitedLinks->addVisitedLink(string, length);
 }
 
-static void NotifyAnimationStarted(JNIEnv* env, jobject obj, jint nativeClass)
+static bool UpdateLayers(JNIEnv *env, jobject obj, jint nativeClass, jint jbaseLayer)
+{
+    WebViewCore* viewImpl = (WebViewCore*) nativeClass;
+    BaseLayerAndroid* baseLayer = (BaseLayerAndroid*)  jbaseLayer;
+    if (baseLayer) {
+        LayerAndroid* root = static_cast<LayerAndroid*>(baseLayer->getChild(0));
+        if (root)
+            return viewImpl->updateLayers(root);
+    }
+    return true;
+}
+
+static void NotifyAnimationStarted(JNIEnv *env, jobject obj, jint nativeClass)
 {
     WebViewCore* viewImpl = (WebViewCore*) nativeClass;
     viewImpl->notifyAnimationStarted();
 }
 
-static jint RecordContent(JNIEnv* env, jobject obj, jint nativeClass, jobject pt)
+static jint RecordContent(JNIEnv *env, jobject obj, jobject region, jobject pt)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    SkRegion* nativeRegion = GraphicsJNI::getNativeRegion(env, region);
     SkIPoint nativePt;
-    BaseLayerAndroid* result = viewImpl->recordContent(&nativePt);
+    BaseLayerAndroid* result = viewImpl->recordContent(nativeRegion, &nativePt);
     GraphicsJNI::ipoint_to_jpoint(nativePt, env, pt);
     return reinterpret_cast<jint>(result);
 }
 
-static void SendListBoxChoice(JNIEnv* env, jobject obj, jint nativeClass,
-        jint choice)
+static void SplitContent(JNIEnv *env, jobject obj, jint content)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ALOG_ASSERT(viewImpl, "viewImpl not set in nativeSendListBoxChoice");
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    viewImpl->splitContent(reinterpret_cast<PictureSet*>(content));
+}
+
+static void SendListBoxChoice(JNIEnv* env, jobject obj, jint choice)
+{
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in nativeSendListBoxChoice");
     viewImpl->popupReply(choice);
 }
 
@@ -4565,11 +4169,14 @@
 // number of items in the average multiple-select listbox.
 #define PREPARED_LISTBOX_STORAGE 10
 
-static void SendListBoxChoices(JNIEnv* env, jobject obj, jint nativeClass,
-        jbooleanArray jArray, jint size)
+static void SendListBoxChoices(JNIEnv* env, jobject obj, jbooleanArray jArray,
+        jint size)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ALOG_ASSERT(viewImpl, "viewImpl not set in nativeSendListBoxChoices");
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in nativeSendListBoxChoices");
     jboolean* ptrArray = env->GetBooleanArrayElements(jArray, 0);
     SkAutoSTMalloc<PREPARED_LISTBOX_STORAGE, int> storage(size);
     int* array = storage.get();
@@ -4583,19 +4190,21 @@
     viewImpl->popupReply(array, count);
 }
 
-// TODO: Move this to WebView.cpp since it is only needed there
-static jstring FindAddress(JNIEnv* env, jobject obj, jstring addr,
-        jboolean caseInsensitive)
+static jstring FindAddress(JNIEnv *env, jobject obj, jstring addr,
+    jboolean caseInsensitive)
 {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
     if (!addr)
         return 0;
     int length = env->GetStringLength(addr);
     if (!length)
         return 0;
     const jchar* addrChars = env->GetStringChars(addr, 0);
-    size_t start, end;
-    AddressDetector detector;
-    bool success = detector.FindContent(addrChars, addrChars + length, &start, &end);
+    int start, end;
+    bool success = CacheBuilder::FindAddress(addrChars, length,
+        &start, &end, caseInsensitive) == CacheBuilder::FOUND_COMPLETE;
     jstring ret = 0;
     if (success)
         ret = env->NewString(addrChars + start, end - start);
@@ -4603,12 +4212,15 @@
     return ret;
 }
 
-static jint HandleTouchEvent(JNIEnv* env, jobject obj, jint nativeClass,
-        jint action, jintArray idArray, jintArray xArray, jintArray yArray,
-        jint count, jint actionIndex, jint metaState)
+static jboolean HandleTouchEvent(JNIEnv *env, jobject obj, jint action, jintArray idArray,
+                                 jintArray xArray, jintArray yArray,
+                                 jint count, jint actionIndex, jint metaState)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
     jint* ptrIdArray = env->GetIntArrayElements(idArray, 0);
     jint* ptrXArray = env->GetIntArrayElements(xArray, 0);
     jint* ptrYArray = env->GetIntArrayElements(yArray, 0);
@@ -4626,53 +4238,105 @@
     return viewImpl->handleTouchEvent(action, ids, points, actionIndex, metaState);
 }
 
-static bool MouseClick(JNIEnv* env, jobject obj, jint nativeClass)
+static void TouchUp(JNIEnv *env, jobject obj, jint touchGeneration,
+        jint frame, jint node, jint x, jint y)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    return viewImpl->performMouseClick();
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+    viewImpl->touchUp(touchGeneration,
+        (WebCore::Frame*) frame, (WebCore::Node*) node, x, y);
 }
 
-static jstring RetrieveHref(JNIEnv* env, jobject obj, jint nativeClass,
-        jint x, jint y)
+static jstring RetrieveHref(JNIEnv *env, jobject obj, jint x, jint y)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
     WTF::String result = viewImpl->retrieveHref(x, y);
     if (!result.isEmpty())
         return wtfStringToJstring(env, result);
     return 0;
 }
 
-static jstring RetrieveAnchorText(JNIEnv* env, jobject obj, jint nativeClass,
-        jint x, jint y)
+static jstring RetrieveAnchorText(JNIEnv *env, jobject obj, jint x, jint y)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
     WTF::String result = viewImpl->retrieveAnchorText(x, y);
     if (!result.isEmpty())
         return wtfStringToJstring(env, result);
     return 0;
 }
 
-static jstring RetrieveImageSource(JNIEnv* env, jobject obj, jint nativeClass,
-        jint x, jint y)
+static jstring RetrieveImageSource(JNIEnv *env, jobject obj, jint x, jint y)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    WTF::String result = viewImpl->retrieveImageSource(x, y);
+    WTF::String result = GET_NATIVE_VIEW(env, obj)->retrieveImageSource(x, y);
     return !result.isEmpty() ? wtfStringToJstring(env, result) : 0;
 }
 
-static void MoveMouse(JNIEnv* env, jobject obj, jint nativeClass, jint x, jint y)
+static void StopPaintingCaret(JNIEnv *env, jobject obj)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
-    viewImpl->moveMouse(x, y);
+    GET_NATIVE_VIEW(env, obj)->setShouldPaintCaret(false);
 }
 
-static jint GetContentMinPrefWidth(JNIEnv* env, jobject obj, jint nativeClass)
+static void MoveFocus(JNIEnv *env, jobject obj, jint framePtr, jint nodePtr)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+    viewImpl->moveFocus((WebCore::Frame*) framePtr, (WebCore::Node*) nodePtr);
+}
+
+static void MoveMouse(JNIEnv *env, jobject obj, jint frame,
+        jint x, jint y)
+{
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+    viewImpl->moveMouse((WebCore::Frame*) frame, x, y);
+}
+
+static void MoveMouseIfLatest(JNIEnv *env, jobject obj, jint moveGeneration,
+        jint frame, jint x, jint y)
+{
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+    viewImpl->moveMouseIfLatest(moveGeneration,
+        (WebCore::Frame*) frame, x, y);
+}
+
+static void UpdateFrameCache(JNIEnv *env, jobject obj)
+{
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+    viewImpl->updateFrameCache();
+}
+
+static jint GetContentMinPrefWidth(JNIEnv *env, jobject obj)
+{
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
 
     WebCore::Frame* frame = viewImpl->mainFrame();
     if (frame) {
@@ -4687,11 +4351,13 @@
     return 0;
 }
 
-static void SetViewportSettingsFromNative(JNIEnv* env, jobject obj,
-        jint nativeClass)
+static void SetViewportSettingsFromNative(JNIEnv *env, jobject obj)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
 
     WebCore::Settings* s = viewImpl->mainFrame()->page()->settings();
     if (!s)
@@ -4708,49 +4374,66 @@
 #endif
 }
 
-static void SetBackgroundColor(JNIEnv* env, jobject obj, jint nativeClass,
-        jint color)
+static void SetBackgroundColor(JNIEnv *env, jobject obj, jint color)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
 
     viewImpl->setBackgroundColor((SkColor) color);
 }
 
-static void DumpDomTree(JNIEnv* env, jobject obj, jint nativeClass,
-        jboolean useFile)
+static void DumpDomTree(JNIEnv *env, jobject obj, jboolean useFile)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
 
     viewImpl->dumpDomTree(useFile);
 }
 
-static void DumpRenderTree(JNIEnv* env, jobject obj, jint nativeClass,
-        jboolean useFile)
+static void DumpRenderTree(JNIEnv *env, jobject obj, jboolean useFile)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
 
     viewImpl->dumpRenderTree(useFile);
 }
 
-static void SetJsFlags(JNIEnv* env, jobject obj, jint nativeClass, jstring flags)
+static void DumpNavTree(JNIEnv *env, jobject obj)
 {
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+
+    viewImpl->dumpNavTree();
+}
+
+static void DumpV8Counters(JNIEnv*, jobject)
+{
+#if USE(V8)
+#ifdef ANDROID_INSTRUMENT
+    V8Counters::dumpCounters();
+#endif
+#endif
+}
+
+static void SetJsFlags(JNIEnv *env, jobject obj, jstring flags)
+{
+#if USE(V8)
     WTF::String flagsString = jstringToWtfString(env, flags);
     WTF::CString utf8String = flagsString.utf8();
     WebCore::ScriptController::setFlags(utf8String.data(), utf8String.length());
+#endif
 }
 
 
 // Called from the Java side to set a new quota for the origin or new appcache
 // max size in response to a notification that the original quota was exceeded or
 // that the appcache has reached its maximum size.
-static void SetNewStorageLimit(JNIEnv* env, jobject obj, jint nativeClass,
-        jlong quota)
-{
+static void SetNewStorageLimit(JNIEnv* env, jobject obj, jlong quota) {
 #if ENABLE(DATABASE) || ENABLE(OFFLINE_WEB_APPLICATIONS)
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
     Frame* frame = viewImpl->mainFrame();
 
     // The main thread is blocked awaiting this response, so now we can wake it
@@ -4761,102 +4444,93 @@
 }
 
 // Called from Java to provide a Geolocation permission state for the specified origin.
-static void GeolocationPermissionsProvide(JNIEnv* env, jobject obj,
-        jint nativeClass, jstring origin, jboolean allow, jboolean remember)
-{
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+static void GeolocationPermissionsProvide(JNIEnv* env, jobject obj, jstring origin, jboolean allow, jboolean remember) {
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
     Frame* frame = viewImpl->mainFrame();
 
     ChromeClientAndroid* chromeClient = static_cast<ChromeClientAndroid*>(frame->page()->chrome()->client());
     chromeClient->provideGeolocationPermissions(jstringToWtfString(env, origin), allow, remember);
 }
 
-static void RegisterURLSchemeAsLocal(JNIEnv* env, jobject obj, jint nativeClass,
-        jstring scheme)
-{
+static void RegisterURLSchemeAsLocal(JNIEnv* env, jobject obj, jstring scheme) {
+#ifdef ANDROID_INSTRUMENT
+    TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
+#endif
     WebCore::SchemeRegistry::registerURLSchemeAsLocal(jstringToWtfString(env, scheme));
 }
 
-static bool FocusBoundsChanged(JNIEnv* env, jobject obj, jint nativeClass)
+static bool FocusBoundsChanged(JNIEnv* env, jobject obj)
 {
-    return reinterpret_cast<WebViewCore*>(nativeClass)->focusBoundsChanged();
+    return GET_NATIVE_VIEW(env, obj)->focusBoundsChanged();
 }
 
-static void SetIsPaused(JNIEnv* env, jobject obj, jint nativeClass,
-        jboolean isPaused)
+static void SetIsPaused(JNIEnv* env, jobject obj, jboolean isPaused)
 {
     // tell the webcore thread to stop thinking while we do other work
     // (selection and scrolling). This has nothing to do with the lifecycle
     // pause and resume.
-    reinterpret_cast<WebViewCore*>(nativeClass)->setIsPaused(isPaused);
+    GET_NATIVE_VIEW(env, obj)->setIsPaused(isPaused);
 }
 
-static void Pause(JNIEnv* env, jobject obj, jint nativeClass)
+static void Pause(JNIEnv* env, jobject obj)
 {
     // This is called for the foreground tab when the browser is put to the
     // background (and also for any tab when it is put to the background of the
     // browser). The browser can only be killed by the system when it is in the
     // background, so saving the Geolocation permission state now ensures that
     // is maintained when the browser is killed.
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ChromeClient* chromeClient = viewImpl->mainFrame()->page()->chrome()->client();
+    ChromeClient* chromeClient = GET_NATIVE_VIEW(env, obj)->mainFrame()->page()->chrome()->client();
     ChromeClientAndroid* chromeClientAndroid = static_cast<ChromeClientAndroid*>(chromeClient);
     chromeClientAndroid->storeGeolocationPermissions();
 
-    Frame* mainFrame = viewImpl->mainFrame();
+    Frame* mainFrame = GET_NATIVE_VIEW(env, obj)->mainFrame();
     for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext()) {
         Geolocation* geolocation = frame->domWindow()->navigator()->optionalGeolocation();
         if (geolocation)
             geolocation->suspend();
     }
-    if (mainFrame)
-        mainFrame->settings()->setMinDOMTimerInterval(BACKGROUND_TIMER_INTERVAL);
 
-    viewImpl->deviceMotionAndOrientationManager()->maybeSuspendClients();
+    GET_NATIVE_VIEW(env, obj)->deviceMotionAndOrientationManager()->maybeSuspendClients();
 
     ANPEvent event;
     SkANP::InitEvent(&event, kLifecycle_ANPEventType);
     event.data.lifecycle.action = kPause_ANPLifecycleAction;
-    viewImpl->sendPluginEvent(event);
+    GET_NATIVE_VIEW(env, obj)->sendPluginEvent(event);
 
-    viewImpl->setIsPaused(true);
+    GET_NATIVE_VIEW(env, obj)->setIsPaused(true);
 }
 
-static void Resume(JNIEnv* env, jobject obj, jint nativeClass)
+static void Resume(JNIEnv* env, jobject obj)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    Frame* mainFrame = viewImpl->mainFrame();
+    Frame* mainFrame = GET_NATIVE_VIEW(env, obj)->mainFrame();
     for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext()) {
         Geolocation* geolocation = frame->domWindow()->navigator()->optionalGeolocation();
         if (geolocation)
             geolocation->resume();
     }
-    if (mainFrame)
-        mainFrame->settings()->setMinDOMTimerInterval(FOREGROUND_TIMER_INTERVAL);
 
-    viewImpl->deviceMotionAndOrientationManager()->maybeResumeClients();
+    GET_NATIVE_VIEW(env, obj)->deviceMotionAndOrientationManager()->maybeResumeClients();
 
     ANPEvent event;
     SkANP::InitEvent(&event, kLifecycle_ANPEventType);
     event.data.lifecycle.action = kResume_ANPLifecycleAction;
-    viewImpl->sendPluginEvent(event);
+    GET_NATIVE_VIEW(env, obj)->sendPluginEvent(event);
 
-    viewImpl->setIsPaused(false);
+    GET_NATIVE_VIEW(env, obj)->setIsPaused(false);
 }
 
-static void FreeMemory(JNIEnv* env, jobject obj, jint nativeClass)
+static void FreeMemory(JNIEnv* env, jobject obj)
 {
     ANPEvent event;
     SkANP::InitEvent(&event, kLifecycle_ANPEventType);
     event.data.lifecycle.action = kFreeMemory_ANPLifecycleAction;
-    reinterpret_cast<WebViewCore*>(nativeClass)->sendPluginEvent(event);
+    GET_NATIVE_VIEW(env, obj)->sendPluginEvent(event);
 }
 
-static void ProvideVisitedHistory(JNIEnv* env, jobject obj, jint nativeClass,
-        jobject hist)
+static void ProvideVisitedHistory(JNIEnv *env, jobject obj, jobject hist)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    ALOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
 
     jobjectArray array = static_cast<jobjectArray>(hist);
 
@@ -4871,38 +4545,78 @@
     }
 }
 
-static void PluginSurfaceReady(JNIEnv* env, jobject obj, jint nativeClass)
+static void PluginSurfaceReady(JNIEnv* env, jobject obj)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
     if (viewImpl)
         viewImpl->sendPluginSurfaceReady();
 }
 
 // Notification from the UI thread that the plugin's full-screen surface has been discarded
-static void FullScreenPluginHidden(JNIEnv* env, jobject obj, jint nativeClass,
-        jint npp)
+static void FullScreenPluginHidden(JNIEnv* env, jobject obj, jint npp)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
     PluginWidgetAndroid* plugin = viewImpl->getPluginWidget((NPP)npp);
     if (plugin)
         plugin->exitFullScreen(false);
 }
 
-static jobject HitTest(JNIEnv* env, jobject obj, jint nativeClass, jint x,
-                       jint y, jint slop, jboolean doMoveMouse)
+static WebCore::IntRect jrect_to_webrect(JNIEnv* env, jobject obj)
 {
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    if (!viewImpl)
-        return 0;
-    AndroidHitTestResult result = viewImpl->hitTestAtPoint(x, y, slop, doMoveMouse);
-    return result.createJavaObject(env);
+    int L, T, R, B;
+    GraphicsJNI::get_jrect(env, obj, &L, &T, &R, &B);
+    return WebCore::IntRect(L, T, R - L, B - T);
 }
 
-static void AutoFillForm(JNIEnv* env, jobject obj, jint nativeClass,
-        jint queryId)
+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);
+}
+
+static jobject GetTouchHighlightRects(JNIEnv* env, jobject obj, jint x, jint y, jint slop)
+{
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
+    if (!viewImpl)
+        return 0;
+    Vector<IntRect> rects = viewImpl->getTouchHighlightRects(x, y, slop);
+    if (rects.isEmpty())
+        return 0;
+
+    jclass arrayClass = env->FindClass("java/util/ArrayList");
+    LOG_ASSERT(arrayClass, "Could not find java/util/ArrayList");
+    jmethodID init = env->GetMethodID(arrayClass, "<init>", "(I)V");
+    LOG_ASSERT(init, "Could not find constructor for ArrayList");
+    jobject array = env->NewObject(arrayClass, init, rects.size());
+    LOG_ASSERT(array, "Could not create a new ArrayList");
+    jmethodID add = env->GetMethodID(arrayClass, "add", "(Ljava/lang/Object;)Z");
+    LOG_ASSERT(add, "Could not find add method on ArrayList");
+    jclass rectClass = env->FindClass("android/graphics/Rect");
+    LOG_ASSERT(rectClass, "Could not find android/graphics/Rect");
+    jmethodID rectinit = env->GetMethodID(rectClass, "<init>", "(IIII)V");
+    LOG_ASSERT(rectinit, "Could not find init method on Rect");
+
+    for (size_t i = 0; i < rects.size(); i++) {
+        jobject rect = env->NewObject(rectClass, rectinit, rects[i].x(),
+                rects[i].y(), rects[i].maxX(), rects[i].maxY());
+        if (rect) {
+            env->CallBooleanMethod(array, add, rect);
+            env->DeleteLocalRef(rect);
+        }
+    }
+
+    env->DeleteLocalRef(rectClass);
+    env->DeleteLocalRef(arrayClass);
+    return array;
+}
+
+static void AutoFillForm(JNIEnv* env, jobject obj, jint queryId)
 {
 #if ENABLE(WEB_AUTOFILL)
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
+    WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
     if (!viewImpl)
         return;
 
@@ -4915,87 +4629,19 @@
 #endif
 }
 
-static void CloseIdleConnections(JNIEnv* env, jobject obj, jint nativeClass)
+static void CloseIdleConnections(JNIEnv* env, jobject obj)
 {
+#if USE(CHROME_NETWORK_STACK)
     WebCache::get(true)->closeIdleConnections();
     WebCache::get(false)->closeIdleConnections();
+#endif
 }
 
-static void nativeCertTrustChanged(JNIEnv *env, jobject obj)
-{
-    WebCache::get(true)->certTrustChanged();
-    WebCache::get(false)->certTrustChanged();
-}
-
-static void ScrollRenderLayer(JNIEnv* env, jobject obj, jint nativeClass,
-        jint layer, jobject jRect)
+static void ScrollRenderLayer(JNIEnv* env, jobject obj, jint layer, jobject jRect)
 {
     SkRect rect;
     GraphicsJNI::jrect_to_rect(env, jRect, &rect);
-    reinterpret_cast<WebViewCore*>(nativeClass)->scrollRenderLayer(layer, rect);
-}
-
-static void DeleteText(JNIEnv* env, jobject obj, jint nativeClass,
-        jint startX, jint startY, jint endX, jint endY)
-{
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    viewImpl->deleteText(startX, startY, endX, endY);
-}
-
-static void InsertText(JNIEnv* env, jobject obj, jint nativeClass,
-        jstring text)
-{
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    WTF::String wtfText = jstringToWtfString(env, text);
-    viewImpl->insertText(wtfText);
-}
-
-static jobject GetText(JNIEnv* env, jobject obj, jint nativeClass,
-        jint startX, jint startY, jint endX, jint endY)
-{
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    WTF::String text = viewImpl->getText(startX, startY, endX, endY);
-    return text.isEmpty() ? 0 : wtfStringToJstring(env, text);
-}
-
-static void SelectText(JNIEnv* env, jobject obj, jint nativeClass,
-        jint startX, jint startY, jint endX, jint endY)
-{
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    viewImpl->selectText(startX, startY, endX, endY);
-}
-
-static void ClearSelection(JNIEnv* env, jobject obj, jint nativeClass)
-{
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    viewImpl->focusedFrame()->selection()->clear();
-}
-
-static bool SelectWordAt(JNIEnv* env, jobject obj, jint nativeClass, jint x, jint y)
-{
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    return viewImpl->selectWordAt(x, y);
-}
-
-static void SelectAll(JNIEnv* env, jobject obj, jint nativeClass)
-{
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    viewImpl->focusedFrame()->selection()->selectAll();
-}
-
-static int FindAll(JNIEnv* env, jobject obj, jint nativeClass,
-        jstring text)
-{
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    WTF::String wtfText = jstringToWtfString(env, text);
-    return viewImpl->findTextOnPage(wtfText);
-}
-
-static int FindNext(JNIEnv* env, jobject obj, jint nativeClass,
-        jboolean forward)
-{
-    WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass);
-    return viewImpl->findNextOnPage(forward);
+    GET_NATIVE_VIEW(env, obj)->scrollRenderLayer(layer, rect);
 }
 
 // ----------------------------------------------------------------------------
@@ -5004,159 +4650,164 @@
  * JNI registration.
  */
 static JNINativeMethod gJavaWebViewCoreMethods[] = {
-    { "nativeClearContent", "(I)V",
+    { "nativeClearContent", "()V",
             (void*) ClearContent },
-    { "nativeFocusBoundsChanged", "(I)Z",
+    { "nativeFocusBoundsChanged", "()Z",
         (void*) FocusBoundsChanged } ,
-    { "nativeKey", "(IIIIZZZZ)Z",
+    { "nativeKey", "(IIIZZZZ)Z",
         (void*) Key },
-    { "nativeContentInvalidateAll", "(I)V",
+    { "nativeClick", "(IIZ)V",
+        (void*) Click },
+    { "nativeContentInvalidateAll", "()V",
         (void*) ContentInvalidateAll },
-    { "nativeSendListBoxChoices", "(I[ZI)V",
+    { "nativeSendListBoxChoices", "([ZI)V",
         (void*) SendListBoxChoices },
-    { "nativeSendListBoxChoice", "(II)V",
+    { "nativeSendListBoxChoice", "(I)V",
         (void*) SendListBoxChoice },
-    { "nativeSetSize", "(IIIIFIIIIZ)V",
+    { "nativeSetSize", "(IIIFIIIIZ)V",
         (void*) SetSize },
     { "nativeSetScrollOffset", "(IZII)V",
         (void*) SetScrollOffset },
-    { "nativeSetGlobalBounds", "(IIIII)V",
+    { "nativeSetGlobalBounds", "(IIII)V",
         (void*) SetGlobalBounds },
-    { "nativeSetSelection", "(III)V",
+    { "nativeSetSelection", "(II)V",
         (void*) SetSelection } ,
-    { "nativeModifySelection", "(III)Ljava/lang/String;",
+    { "nativeModifySelection", "(II)Ljava/lang/String;",
         (void*) ModifySelection },
-    { "nativeDeleteSelection", "(IIII)V",
+    { "nativeDeleteSelection", "(III)V",
         (void*) DeleteSelection } ,
-    { "nativeReplaceTextfieldText", "(IIILjava/lang/String;III)V",
+    { "nativeReplaceTextfieldText", "(IILjava/lang/String;III)V",
         (void*) ReplaceTextfieldText } ,
+    { "nativeMoveFocus", "(II)V",
+        (void*) MoveFocus },
     { "nativeMoveMouse", "(III)V",
         (void*) MoveMouse },
-    { "passToJs", "(IILjava/lang/String;IIZZZZ)V",
+    { "nativeMoveMouseIfLatest", "(IIII)V",
+        (void*) MoveMouseIfLatest },
+    { "passToJs", "(ILjava/lang/String;IIZZZZ)V",
         (void*) PassToJs },
-    { "nativeScrollFocusedTextInput", "(IFILandroid/graphics/Rect;)V",
+    { "nativeScrollFocusedTextInput", "(FI)V",
         (void*) ScrollFocusedTextInput },
-    { "nativeSetFocusControllerActive", "(IZ)V",
+    { "nativeSetFocusControllerActive", "(Z)V",
         (void*) SetFocusControllerActive },
     { "nativeSaveDocumentState", "(I)V",
         (void*) SaveDocumentState },
     { "nativeFindAddress", "(Ljava/lang/String;Z)Ljava/lang/String;",
         (void*) FindAddress },
-    { "nativeHandleTouchEvent", "(II[I[I[IIII)I",
-        (void*) HandleTouchEvent },
-    { "nativeMouseClick", "(I)Z",
-        (void*) MouseClick },
-    { "nativeRetrieveHref", "(III)Ljava/lang/String;",
+    { "nativeHandleTouchEvent", "(I[I[I[IIII)Z",
+            (void*) HandleTouchEvent },
+    { "nativeTouchUp", "(IIIII)V",
+        (void*) TouchUp },
+    { "nativeRetrieveHref", "(II)Ljava/lang/String;",
         (void*) RetrieveHref },
-    { "nativeRetrieveAnchorText", "(III)Ljava/lang/String;",
+    { "nativeRetrieveAnchorText", "(II)Ljava/lang/String;",
         (void*) RetrieveAnchorText },
-    { "nativeRetrieveImageSource", "(III)Ljava/lang/String;",
+    { "nativeRetrieveImageSource", "(II)Ljava/lang/String;",
         (void*) RetrieveImageSource },
-    { "nativeGetContentMinPrefWidth", "(I)I",
+    { "nativeStopPaintingCaret", "()V",
+        (void*) StopPaintingCaret },
+    { "nativeUpdateFrameCache", "()V",
+        (void*) UpdateFrameCache },
+    { "nativeGetContentMinPrefWidth", "()I",
         (void*) GetContentMinPrefWidth },
+    { "nativeUpdateLayers", "(II)Z",
+        (void*) UpdateLayers },
     { "nativeNotifyAnimationStarted", "(I)V",
         (void*) NotifyAnimationStarted },
-    { "nativeRecordContent", "(ILandroid/graphics/Point;)I",
+    { "nativeRecordContent", "(Landroid/graphics/Region;Landroid/graphics/Point;)I",
         (void*) RecordContent },
-    { "setViewportSettingsFromNative", "(I)V",
+    { "setViewportSettingsFromNative", "()V",
         (void*) SetViewportSettingsFromNative },
-    { "nativeSetBackgroundColor", "(II)V",
+    { "nativeSplitContent", "(I)V",
+        (void*) SplitContent },
+    { "nativeSetBackgroundColor", "(I)V",
         (void*) SetBackgroundColor },
-    { "nativeRegisterURLSchemeAsLocal", "(ILjava/lang/String;)V",
+    { "nativeRegisterURLSchemeAsLocal", "(Ljava/lang/String;)V",
         (void*) RegisterURLSchemeAsLocal },
-    { "nativeDumpDomTree", "(IZ)V",
+    { "nativeDumpDomTree", "(Z)V",
         (void*) DumpDomTree },
-    { "nativeDumpRenderTree", "(IZ)V",
+    { "nativeDumpRenderTree", "(Z)V",
         (void*) DumpRenderTree },
-    { "nativeSetNewStorageLimit", "(IJ)V",
+    { "nativeDumpNavTree", "()V",
+        (void*) DumpNavTree },
+    { "nativeDumpV8Counters", "()V",
+        (void*) DumpV8Counters },
+    { "nativeSetNewStorageLimit", "(J)V",
         (void*) SetNewStorageLimit },
-    { "nativeGeolocationPermissionsProvide", "(ILjava/lang/String;ZZ)V",
+    { "nativeGeolocationPermissionsProvide", "(Ljava/lang/String;ZZ)V",
         (void*) GeolocationPermissionsProvide },
-    { "nativeSetIsPaused", "(IZ)V", (void*) SetIsPaused },
-    { "nativePause", "(I)V", (void*) Pause },
-    { "nativeResume", "(I)V", (void*) Resume },
-    { "nativeFreeMemory", "(I)V", (void*) FreeMemory },
-    { "nativeSetJsFlags", "(ILjava/lang/String;)V", (void*) SetJsFlags },
-    { "nativeRequestLabel", "(III)Ljava/lang/String;",
+    { "nativeSetIsPaused", "(Z)V", (void*) SetIsPaused },
+    { "nativePause", "()V", (void*) Pause },
+    { "nativeResume", "()V", (void*) Resume },
+    { "nativeFreeMemory", "()V", (void*) FreeMemory },
+    { "nativeSetJsFlags", "(Ljava/lang/String;)V", (void*) SetJsFlags },
+    { "nativeRequestLabel", "(II)Ljava/lang/String;",
         (void*) RequestLabel },
-    { "nativeRevealSelection", "(I)V", (void*) RevealSelection },
-    { "nativeProvideVisitedHistory", "(I[Ljava/lang/String;)V",
+    { "nativeRevealSelection", "()V", (void*) RevealSelection },
+    { "nativeUpdateFrameCacheIfLoading", "()V",
+        (void*) UpdateFrameCacheIfLoading },
+    { "nativeProvideVisitedHistory", "([Ljava/lang/String;)V",
         (void*) ProvideVisitedHistory },
-    { "nativeFullScreenPluginHidden", "(II)V",
+    { "nativeFullScreenPluginHidden", "(I)V",
         (void*) FullScreenPluginHidden },
-    { "nativePluginSurfaceReady", "(I)V",
+    { "nativePluginSurfaceReady", "()V",
         (void*) PluginSurfaceReady },
-    { "nativeHitTest", "(IIIIZ)Landroid/webkit/WebViewCore$WebKitHitTest;",
-        (void*) HitTest },
-    { "nativeAutoFillForm", "(II)V",
+    { "nativeValidNodeAndBounds", "(IILandroid/graphics/Rect;)Z",
+        (void*) ValidNodeAndBounds },
+    { "nativeGetTouchHighlightRects", "(III)Ljava/util/ArrayList;",
+        (void*) GetTouchHighlightRects },
+    { "nativeAutoFillForm", "(I)V",
         (void*) AutoFillForm },
-    { "nativeScrollLayer", "(IILandroid/graphics/Rect;)V",
+    { "nativeScrollLayer", "(ILandroid/graphics/Rect;)V",
         (void*) ScrollRenderLayer },
-    { "nativeCloseIdleConnections", "(I)V",
+    { "nativeCloseIdleConnections", "()V",
         (void*) CloseIdleConnections },
-    { "nativeDeleteText", "(IIIII)V",
-        (void*) DeleteText },
-    { "nativeInsertText", "(ILjava/lang/String;)V",
-        (void*) InsertText },
-    { "nativeGetText", "(IIIII)Ljava/lang/String;",
-        (void*) GetText },
-    { "nativeSelectText", "(IIIII)V",
-        (void*) SelectText },
-    { "nativeClearTextSelection", "(I)V",
-        (void*) ClearSelection },
-    { "nativeSelectWordAt", "(III)Z",
-        (void*) SelectWordAt },
-    { "nativeSelectAll", "(I)V",
-        (void*) SelectAll },
-    { "nativeCertTrustChanged","()V",
-        (void*) nativeCertTrustChanged },
-    { "nativeFindAll", "(ILjava/lang/String;)I",
-        (void*) FindAll },
-    { "nativeFindNext", "(IZ)I",
-        (void*) FindNext },
-    { "nativeSetInitialFocus", "(II)V", (void*) SetInitialFocus },
 };
 
 int registerWebViewCore(JNIEnv* env)
 {
     jclass widget = env->FindClass("android/webkit/WebViewCore");
-    ALOG_ASSERT(widget,
+    LOG_ASSERT(widget,
             "Unable to find class android/webkit/WebViewCore");
     gWebViewCoreFields.m_nativeClass = env->GetFieldID(widget, "mNativeClass",
             "I");
-    ALOG_ASSERT(gWebViewCoreFields.m_nativeClass,
+    LOG_ASSERT(gWebViewCoreFields.m_nativeClass,
             "Unable to find android/webkit/WebViewCore.mNativeClass");
     gWebViewCoreFields.m_viewportWidth = env->GetFieldID(widget,
             "mViewportWidth", "I");
-    ALOG_ASSERT(gWebViewCoreFields.m_viewportWidth,
+    LOG_ASSERT(gWebViewCoreFields.m_viewportWidth,
             "Unable to find android/webkit/WebViewCore.mViewportWidth");
     gWebViewCoreFields.m_viewportHeight = env->GetFieldID(widget,
             "mViewportHeight", "I");
-    ALOG_ASSERT(gWebViewCoreFields.m_viewportHeight,
+    LOG_ASSERT(gWebViewCoreFields.m_viewportHeight,
             "Unable to find android/webkit/WebViewCore.mViewportHeight");
     gWebViewCoreFields.m_viewportInitialScale = env->GetFieldID(widget,
             "mViewportInitialScale", "I");
-    ALOG_ASSERT(gWebViewCoreFields.m_viewportInitialScale,
+    LOG_ASSERT(gWebViewCoreFields.m_viewportInitialScale,
             "Unable to find android/webkit/WebViewCore.mViewportInitialScale");
     gWebViewCoreFields.m_viewportMinimumScale = env->GetFieldID(widget,
             "mViewportMinimumScale", "I");
-    ALOG_ASSERT(gWebViewCoreFields.m_viewportMinimumScale,
+    LOG_ASSERT(gWebViewCoreFields.m_viewportMinimumScale,
             "Unable to find android/webkit/WebViewCore.mViewportMinimumScale");
     gWebViewCoreFields.m_viewportMaximumScale = env->GetFieldID(widget,
             "mViewportMaximumScale", "I");
-    ALOG_ASSERT(gWebViewCoreFields.m_viewportMaximumScale,
+    LOG_ASSERT(gWebViewCoreFields.m_viewportMaximumScale,
             "Unable to find android/webkit/WebViewCore.mViewportMaximumScale");
     gWebViewCoreFields.m_viewportUserScalable = env->GetFieldID(widget,
             "mViewportUserScalable", "Z");
-    ALOG_ASSERT(gWebViewCoreFields.m_viewportUserScalable,
+    LOG_ASSERT(gWebViewCoreFields.m_viewportUserScalable,
             "Unable to find android/webkit/WebViewCore.mViewportUserScalable");
     gWebViewCoreFields.m_viewportDensityDpi = env->GetFieldID(widget,
             "mViewportDensityDpi", "I");
-    ALOG_ASSERT(gWebViewCoreFields.m_viewportDensityDpi,
+    LOG_ASSERT(gWebViewCoreFields.m_viewportDensityDpi,
             "Unable to find android/webkit/WebViewCore.mViewportDensityDpi");
+    gWebViewCoreFields.m_webView = env->GetFieldID(widget,
+            "mWebView", "Landroid/webkit/WebView;");
+    LOG_ASSERT(gWebViewCoreFields.m_webView,
+            "Unable to find android/webkit/WebViewCore.mWebView");
     gWebViewCoreFields.m_drawIsPaused = env->GetFieldID(widget,
             "mDrawIsPaused", "Z");
-    ALOG_ASSERT(gWebViewCoreFields.m_drawIsPaused,
+    LOG_ASSERT(gWebViewCoreFields.m_drawIsPaused,
             "Unable to find android/webkit/WebViewCore.mDrawIsPaused");
     gWebViewCoreFields.m_lowMemoryUsageMb = env->GetFieldID(widget, "mLowMemoryUsageThresholdMb", "I");
     gWebViewCoreFields.m_highMemoryUsageMb = env->GetFieldID(widget, "mHighMemoryUsageThresholdMb", "I");
diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h
index 5264f7f..a19a5b2 100644
--- a/Source/WebKit/android/jni/WebViewCore.h
+++ b/Source/WebKit/android/jni/WebViewCore.h
@@ -26,36 +26,29 @@
 #ifndef WebViewCore_h
 #define WebViewCore_h
 
+#include "CacheBuilder.h"
+#include "CachedHistory.h"
 #include "DeviceMotionAndOrientationManager.h"
 #include "DOMSelection.h"
 #include "FileChooser.h"
-#include "FocusDirection.h"
-#include "HitTestResult.h"
-#include "PicturePile.h"
+#include "PictureSet.h"
 #include "PlatformGraphicsContext.h"
-#include "Position.h"
-#include "ScrollTypes.h"
 #include "SkColor.h"
 #include "SkTDArray.h"
 #include "SkRegion.h"
-#include "Text.h"
 #include "Timer.h"
 #include "WebCoreRefObject.h"
 #include "WebCoreJni.h"
 #include "WebRequestContext.h"
 #include "android_npapi.h"
-#include "VisiblePosition.h"
-#include "SelectText.h"
 
 #include <jni.h>
-#include <androidfw/KeycodeLabels.h>
+#include <ui/KeycodeLabels.h>
 #include <ui/PixelFormat.h>
 #include <utils/threads.h>
-#include <wtf/Threading.h>
 
 namespace WebCore {
     class Color;
-    class GraphicsOperationCollection;
     class FrameView;
     class HTMLAnchorElement;
     class HTMLElement;
@@ -75,7 +68,6 @@
 #if USE(ACCELERATED_COMPOSITING)
 namespace WebCore {
     class GraphicsLayerAndroid;
-    class LayerAndroid;
 }
 #endif
 
@@ -104,8 +96,10 @@
         AXIS_DOCUMENT = 6
     };
 
+    class CachedFrame;
+    class CachedNode;
+    class CachedRoot;
     class ListBoxReply;
-    class AndroidHitTestResult;
 
     class WebCoreReply : public WebCoreRefObject {
     public:
@@ -122,7 +116,7 @@
     };
 
     // one instance of WebViewCore per page for calling into Java's WebViewCore
-    class WebViewCore : public WebCoreRefObject, public WebCore::PicturePainter {
+    class WebViewCore : public WebCoreRefObject {
     public:
         /**
          * Initialize the native WebViewCore with a JNI environment, a Java
@@ -137,7 +131,13 @@
 
         // Followings are called from native WebCore to Java
 
-        void focusNodeChanged(WebCore::Node*);
+        /**
+         * Notification that a form was blurred.  Pass a message to hide the
+         * keyboard if it was showing for that Node.
+         * @param Node The Node that blurred.
+         */
+        void formDidBlur(const WebCore::Node*);
+        void focusNodeChanged(const WebCore::Node*);
 
         /**
          * Scroll to an absolute position.
@@ -161,8 +161,13 @@
          */
         void contentDraw();
 
+        /**
+         * copy the layers to the UI side
+         */
+        void layersDraw();
+
 #if USE(ACCELERATED_COMPOSITING)
-        WebCore::GraphicsLayerAndroid* graphicsRootLayer() const;
+        GraphicsLayerAndroid* graphicsRootLayer() const;
 #endif
 
         /** Invalidate the view/screen, NOT the content/DOM, but expressed in
@@ -202,7 +207,7 @@
          * Tell the java side to update the focused textfield
          * @param pointer   Pointer to the node for the input field.
          * @param   changeToPassword  If true, we are changing the textfield to
-         *          a password field, and ignore the WTF::String
+         *          a password field, and ignore the String
          * @param text  If changeToPassword is false, this is the new text that
          *              should go into the textfield.
          */
@@ -217,12 +222,6 @@
          */
         void updateTextSelection();
 
-        /**
-         * Updates the java side with the node's content size and scroll
-         * position.
-         */
-        void updateTextSizeAndScroll(WebCore::Node* node);
-
         void clearTextEntry();
         // JavaScript support
         void jsAlert(const WTF::String& url, const WTF::String& text);
@@ -278,13 +277,12 @@
         jobject getDeviceMotionService();
         jobject getDeviceOrientationService();
 
-        void addMessageToConsole(const WTF::String& message, unsigned int lineNumber, const WTF::String& sourceID, int msgLevel);
+        void addMessageToConsole(const String& message, unsigned int lineNumber, const String& sourceID, int msgLevel);
 
         /**
          * Tell the Java side of the scrollbar mode
          */
-        void setScrollbarModes(WebCore::ScrollbarMode horizontalMode,
-                               WebCore::ScrollbarMode verticalMode);
+        void setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode);
 
         //
         // Followings support calls from Java to native WebCore
@@ -298,12 +296,16 @@
         // If the focus is a textfield (<input>), textarea, or contentEditable,
         // scroll the selection on screen (if necessary).
         void revealSelection();
+        // Create a single picture to represent the drawn DOM (used by navcache)
+        void recordPicture(SkPicture* picture);
 
-        void moveMouse(int x, int y, WebCore::HitTestResult* hoveredNode = 0,
-                       bool isClickCandidate = false);
+        void moveFocus(WebCore::Frame* frame, WebCore::Node* node);
+        void moveMouse(WebCore::Frame* frame, int x, int y);
+        void moveMouseIfLatest(int moveGeneration,
+            WebCore::Frame* frame, int x, int y);
 
         // set the scroll amount that webview.java is currently showing
-        void setScrollOffset(bool sendScrollEvent, int dx, int dy);
+        void setScrollOffset(int moveGeneration, bool sendScrollEvent, int dx, int dy);
 
         void setGlobalBounds(int x, int y, int h, int v);
 
@@ -316,24 +318,31 @@
          * @return Whether keyCode was handled by this class.
          */
         bool key(const WebCore::PlatformKeyboardEvent& event);
-        bool chromeCanTakeFocus(WebCore::FocusDirection direction);
-        void chromeTakeFocus(WebCore::FocusDirection direction);
-        void setInitialFocus(const WebCore::PlatformKeyboardEvent& event);
+
+        /**
+         * Handle (trackball) click event / dpad center press from Java.
+         * Also used when typing into an unfocused textfield, in which case 'fake'
+         * will be true.
+         */
+        void click(WebCore::Frame* frame, WebCore::Node* node, bool fake);
 
         /**
          * Handle touch event
-         * Returns an int with the following flags:
-         * bit 0: hit an event handler
-         * bit 1: preventDefault was called
          */
-        int handleTouchEvent(int action, WTF::Vector<int>& ids,
-                              WTF::Vector<WebCore::IntPoint>& points,
-                              int actionIndex, int metaState);
+        bool handleTouchEvent(int action, Vector<int>& ids, Vector<IntPoint>& points, int actionIndex, int metaState);
 
         /**
-         * Clicks the mouse at its current location
+         * Handle motionUp event from the UI thread (called touchUp in the
+         * WebCore thread).
+         * @param touchGeneration Generation number for touches so we can ignore
+         *      touches when a newer one has been generated.
+         * @param frame Pointer to Frame containing the node that was touched.
+         * @param node Pointer to Node that was touched.
+         * @param x x-position of the touch.
+         * @param y y-position of the touch.
          */
-        bool performMouseClick();
+        void touchUp(int touchGeneration, WebCore::Frame* frame,
+                WebCore::Node* node, int x, int y);
 
         /**
          * Sets the index of the label from a popup
@@ -363,11 +372,11 @@
          * direction - The direction in which to alter the selection.
          * granularity - The granularity of the selection modification.
          *
-         * returns - The selected HTML as a WTF::String. This is not a well formed
+         * returns - The selected HTML as a string. This is not a well formed
          *           HTML, rather the selection annotated with the tags of all
          *           intermediary elements it crosses.
          */
-        WTF::String modifySelection(const int direction, const int granularity);
+        String modifySelection(const int direction, const int granularity);
 
         /**
          * Moves the selection to the given node in a given frame i.e. selects that node.
@@ -377,11 +386,11 @@
          * frame - The frame in which to select is the node to be selected.
          * node - The node to be selected.
          *
-         * returns - The selected HTML as a WTF::String. This is not a well formed
+         * returns - The selected HTML as a string. This is not a well formed
          *           HTML, rather the selection annotated with the tags of all
          *           intermediary elements it crosses.
          */
-        WTF::String moveSelection(WebCore::Frame* frame, WebCore::Node* node);
+        String moveSelection(WebCore::Frame* frame, WebCore::Node* node);
 
         /**
          *  In the currently focused textfield, replace the characters from oldStart to oldEnd
@@ -396,7 +405,7 @@
         /**
          * Scroll the focused textfield to (x, y) in document space
          */
-        WebCore::IntRect scrollFocusedTextInput(float x, int y);
+        void scrollFocusedTextInput(float x, int y);
         /**
          * Set the FocusController's active and focused states, so that
          * the caret will draw (true) or not.
@@ -416,9 +425,11 @@
         jobject getWebViewJavaObject();
 
         void setBackgroundColor(SkColor c);
-
+        void updateFrameCache();
+        void updateCacheOnNodeChange();
         void dumpDomTree(bool);
         void dumpRenderTree(bool);
+        void dumpNavTree();
 
         /*  We maintain a list of active plugins. The list is edited by the
             pluginview itself. The list is used to service invals to the plugin
@@ -438,7 +449,7 @@
         void sendPluginSurfaceReady();
 
         // send onLoad event to plugins who are descendents of the given frame
-        void notifyPluginsOnFrameLoad(const WebCore::Frame*);
+        void notifyPluginsOnFrameLoad(const Frame*);
 
         // gets a rect representing the current on-screen portion of the document
         void getVisibleScreen(ANPRectI&);
@@ -449,6 +460,9 @@
         // lookup the plugin widget struct given an NPP
         PluginWidgetAndroid* getPluginWidget(NPP npp);
 
+        // return the cursorNode if it is a plugin
+        Node* cursorNodeIsPlugin();
+
         // Notify the Java side whether it needs to pass down the touch events
         void needTouchEvents(bool);
 
@@ -483,6 +497,8 @@
         // Manages requests to keep the screen on while the WebView is visible
         void keepScreenOn(bool screenOn);
 
+        bool validNodeAndBounds(Frame* , Node* , const IntRect& );
+
         // Make the rect (left, top, width, height) visible. If it can be fully
         // fit, center it on the screen. Otherwise make sure the point specified
         // by (left + xPercentInDoc * width, top + yPercentInDoc * height)
@@ -496,11 +512,7 @@
         void centerFitRect(int x, int y, int width, int height);
 
         // return a list of rects matching the touch point (x, y) with the slop
-        WTF::Vector<WebCore::IntRect> getTouchHighlightRects(int x, int y, int slop,
-                WebCore::Node** node, WebCore::HitTestResult* hitTestResult);
-        // This does a sloppy hit test
-        AndroidHitTestResult hitTestAtPoint(int x, int y, int slop, bool doMoveMouse = false);
-        static bool nodeIsClickableOrFocusable(WebCore::Node* node);
+        Vector<IntRect> getTouchHighlightRects(int x, int y, int slop);
 
         // Open a file chooser for selecting a file to upload
         void openFileChooser(PassRefPtr<WebCore::FileChooser> );
@@ -510,37 +522,31 @@
 
         bool focusBoundsChanged();
 
-        // record content in a new BaseLayerAndroid, copying the layer tree as well
-        WebCore::BaseLayerAndroid* recordContent(SkIPoint* );
+        // record the inval area, and the picture size
+        BaseLayerAndroid* recordContent(SkRegion* , SkIPoint* );
 
         // This creates a new BaseLayerAndroid by copying the current m_content
         // and doing a copy of the layers. The layers' content may be updated
         // as we are calling layersSync().
-        WebCore::BaseLayerAndroid* createBaseLayer(GraphicsLayerAndroid* root);
-        bool updateLayers(WebCore::LayerAndroid*);
+        BaseLayerAndroid* createBaseLayer(SkRegion*);
+        bool updateLayers(LayerAndroid*);
         void notifyAnimationStarted();
 
         int textWrapWidth() const { return m_textWrapWidth; }
         float scale() const { return m_scale; }
         float textWrapScale() const { return m_screenWidth * m_scale / m_textWrapWidth; }
         WebCore::Frame* mainFrame() const { return m_mainFrame; }
-        WebCore::Frame* focusedFrame() const;
+        void updateCursorBounds(const CachedRoot* root,
+                const CachedFrame* cachedFrame, const CachedNode* cachedNode);
+        void updateFrameCacheIfLoading();
+
+        // utility to split slow parts of the picture set
+        void splitContent(PictureSet*);
 
         void notifyWebAppCanBeInstalled();
 
-        void deleteText(int startX, int startY, int endX, int endY);
-        WTF::String getText(int startX, int startY, int endX, int endY);
-        void insertText(const WTF::String &text);
-
-        // find on page
-        void resetFindOnPage();
-        int findTextOnPage(const WTF::String &text);
-        int findNextOnPage(bool forward);
-        void updateMatchCount() const;
-
 #if ENABLE(VIDEO)
         void enterFullscreenForVideoLayer(int layerId, const WTF::String& url);
-        void exitFullscreenVideo();
 #endif
 
         void setWebTextViewAutoFillable(int queryId, const string16& previewSummary);
@@ -550,15 +556,19 @@
         void listBoxRequest(WebCoreReply* reply, const uint16_t** labels,
                 size_t count, const int enabled[], size_t enabledCount,
                 bool multiple, const int selected[], size_t selectedCountOrSelection);
+        bool shouldPaintCaret() { return m_shouldPaintCaret; }
+        void setShouldPaintCaret(bool should) { m_shouldPaintCaret = should; }
         bool isPaused() const { return m_isPaused; }
         void setIsPaused(bool isPaused) { m_isPaused = isPaused; }
         bool drawIsPaused() const;
         // The actual content (without title bar) size in doc coordinate
         int  screenWidth() const { return m_screenWidth; }
         int  screenHeight() const { return m_screenHeight; }
+#if USE(CHROME_NETWORK_STACK)
         void setWebRequestContextUserAgent();
         void setWebRequestContextCacheMode(int mode);
         WebRequestContext* webRequestContext();
+#endif
         // Attempts to scroll the layer to the x,y coordinates of rect. The
         // layer is the id of the LayerAndroid.
         void scrollRenderLayer(int layer, const SkRect& rect);
@@ -571,62 +581,35 @@
         // Check whether a media mimeType is supported in Android media framework.
         static bool isSupportedMediaMimeType(const WTF::String& mimeType);
 
-        /**
-         * Returns all text ranges consumed by the cursor points referred
-         * to by startX, startY, endX, and endY. The vector will be empty
-         * if no text is in the given area or if the positions are invalid.
-         */
-        Vector<WebCore::VisibleSelection> getTextRanges(
-                int startX, int startY, int endX, int endY);
-        static int platformLayerIdFromNode(WebCore::Node* node,
-                                           WebCore::LayerAndroid** outLayer = 0);
-        void selectText(int startX, int startY, int endX, int endY);
-        bool selectWordAt(int x, int y);
-
-        // Converts from the global content coordinates that WebView sends
-        // to frame-local content coordinates using the focused frame
-        WebCore::IntPoint convertGlobalContentToFrameContent(const WebCore::IntPoint& point, WebCore::Frame* frame = 0);
-        static void layerToAbsoluteOffset(const WebCore::LayerAndroid* layer,
-                                          WebCore::IntPoint& offset);
-
-        // Retrieves the current locale from system properties
-        void getLocale(String& language, WTF::String& region);
-
-        // Handles changes in system locale
-        void updateLocale();
-
         // these members are shared with webview.cpp
+        static Mutex gFrameCacheMutex;
+        CachedRoot* m_frameCacheKit; // nav data being built by webcore
+        SkPicture* m_navPictureKit;
+        int m_moveGeneration; // copy of state in WebViewNative triggered by move
         int m_touchGeneration; // copy of state in WebViewNative triggered by touch
         int m_lastGeneration; // last action using up to date cache
+        bool m_updatedFrameCache;
+        bool m_findIsUp;
+        bool m_hasCursorBounds;
+        WebCore::IntRect m_cursorBounds;
+        WebCore::IntRect m_cursorHitBounds;
+        void* m_cursorFrame;
+        IntPoint m_cursorLocation;
+        void* m_cursorNode;
+        static Mutex gCursorBoundsMutex;
         // end of shared members
 
-        void setPrerenderingEnabled(bool enable);
-
         // internal functions
     private:
-        enum InputType {
-            NONE = -1,
-            NORMAL_TEXT_FIELD = 0,
-            TEXT_AREA = 1,
-            PASSWORD = 2,
-            SEARCH = 3,
-            EMAIL = 4,
-            NUMBER = 5,
-            TELEPHONE = 6,
-            URL = 7,
-        };
-
+        CacheBuilder& cacheBuilder();
         WebCore::Node* currentFocus();
-        void layout();
         // Create a set of pictures to represent the drawn DOM, driven by
         // the invalidated region and the time required to draw (used to draw)
-        void recordPicturePile();
+        void recordPictureSet(PictureSet* master);
 
-        virtual void paintContents(WebCore::GraphicsContext* gc, WebCore::IntRect& dirty);
-        virtual SkCanvas* createPrerenderCanvas(WebCore::PrerenderedInval* prerendered);
-#ifdef CONTEXT_RECORDING
-        WebCore::GraphicsOperationCollection* rebuildGraphicsOperationCollection(const SkIRect& inval);
-#endif
+        void doMaxScroll(CacheBuilder::Direction dir);
+        SkPicture* rebuildPicture(const SkIRect& inval);
+        void rebuildPictureSet(PictureSet* );
         void sendNotifyProgressFinished();
         /*
          * Handle a mouse click, either from a touch or trackball press.
@@ -635,127 +618,47 @@
          * @param fake This is a fake mouse click, used to put a textfield into focus. Do not
          *      open the IME.
          */
+        bool handleMouseClick(WebCore::Frame*, WebCore::Node*, bool fake);
         WebCore::HTMLAnchorElement* retrieveAnchorElement(int x, int y);
         WebCore::HTMLElement* retrieveElement(int x, int y,
             const WebCore::QualifiedName& );
         WebCore::HTMLImageElement* retrieveImageElement(int x, int y);
         // below are members responsible for accessibility support
-        WTF::String modifySelectionTextNavigationAxis(WebCore::DOMSelection* selection,
-                                                 int direction, int granularity);
-        WTF::String modifySelectionDomNavigationAxis(WebCore::DOMSelection* selection,
-                                                int direction, int granularity);
-        WebCore::Text* traverseNextContentTextNode(WebCore::Node* fromNode,
-                                                   WebCore::Node* toNode,
-                                                   int direction);
-        bool isVisible(WebCore::Node* node);
-        bool isHeading(WebCore::Node* node);
-        WTF::String formatMarkup(WebCore::DOMSelection* selection);
+        String modifySelectionTextNavigationAxis(DOMSelection* selection, int direction, int granularity);
+        String modifySelectionDomNavigationAxis(DOMSelection* selection, int direction, int granularity);
+        Text* traverseNextContentTextNode(Node* fromNode, Node* toNode ,int direction);
+        bool isVisible(Node* node);
+        bool isHeading(Node* node);
+        String formatMarkup(DOMSelection* selection);
         void selectAt(int x, int y);
 
-        void scrollNodeIntoView(WebCore::Frame* frame, WebCore::Node* node);
-        bool isContentTextNode(WebCore::Node* node);
-        WebCore::Node* getIntermediaryInputElement(WebCore::Node* fromNode,
-                                                   WebCore::Node* toNode,
-                                                   int direction);
-        bool isContentInputElement(WebCore::Node* node);
-        bool isDescendantOf(WebCore::Node* parent, WebCore::Node* node);
-        void advanceAnchorNode(WebCore::DOMSelection* selection, int direction,
-                               WTF::String& markup, bool ignoreFirstNode,
-                               WebCore::ExceptionCode& ec);
-        WebCore::Node* getNextAnchorNode(WebCore::Node* anchorNode,
-                                         bool skipFirstHack, int direction);
-        WebCore::Node* getImplicitBoundaryNode(WebCore::Node* node,
-                                               unsigned offset, int direction);
-        jobject createTextFieldInitData(WebCore::Node* node);
-        /**
-         * Calls into java to reset the text edit field with the
-         * current contents and selection.
-         */
-        void initEditField(WebCore::Node* node);
-
-        /**
-         * If node is not a text input field or if it explicitly requests
-         * not to have keyboard input, then the soft keyboard is closed. If
-         * it is a text input field then initEditField is called and
-         * auto-fill information is requested for HTML form input fields.
-         */
-        void initializeTextInput(WebCore::Node* node, bool fake);
-
-        /**
-         * Gets the input type a Node. NONE is returned if it isn't an
-         * input field.
-         */
-        InputType getInputType(WebCore::Node* node);
-
-        /**
-         * If node is an input field, the spellcheck value for the
-         * field is returned. Otherwise true is returned.
-         */
-        static bool isSpellCheckEnabled(WebCore::Node* node);
-
-        /**
-         * Returns the offsets of the selection area for both normal text
-         * fields and content editable fields. start and end are modified
-         * by this method.
-         */
-        static void getSelectionOffsets(WebCore::Node* node, int& start, int& end);
-        /**
-         * Gets the plain text of the specified editable text field. node
-         * may be content-editable or a plain text fields.
-         */
-        static WTF::String getInputText(WebCore::Node* node);
-        /**
-         * Gets the RenderTextControl for the given node if it has one.
-         * If its renderer isn't a RenderTextControl, then NULL is returned.
-         */
-        static WebCore::RenderTextControl* toRenderTextControl(WebCore::Node *node);
-        /**
-         * Sets the selection for node's editable field to the offsets
-         * between start (inclusive) and end (exclusive).
-         */
-        static void setSelection(WebCore::Node* node, int start, int end);
-        /**
-         * Returns the Position for the given offset for an editable
-         * field. The offset is relative to the node start.
-         */
-        static WebCore::Position getPositionForOffset(WebCore::Node* node, int offset);
-
-        WebCore::VisiblePosition visiblePositionForContentPoint(int x, int y);
-        WebCore::VisiblePosition visiblePositionForContentPoint(const WebCore::IntPoint& point);
-        bool selectWordAroundPosition(WebCore::Frame* frame,
-                                      WebCore::VisiblePosition pos);
-        SelectText* createSelectText(const WebCore::VisibleSelection&);
-        void setSelectionCaretInfo(SelectText* selectTextContainer,
-                const WebCore::Position& position,
-                const WebCore::IntPoint& frameOffset,
-                SelectText::HandleId handleId, int offset,
-                EAffinity affinity);
-        static int getMaxLength(WebCore::Node* node);
-        static WTF::String getFieldName(WebCore::Node* node);
-        static bool isAutoCompleteEnabled(WebCore::Node* node);
-        WebCore::IntRect absoluteContentRect(WebCore::Node* node,
-                WebCore::LayerAndroid* layer);
-        static WebCore::IntRect positionToTextRect(const WebCore::Position& position,
-                WebCore::EAffinity affinity, const WebCore::IntPoint& offset);
-        static bool isLtr(const WebCore::Position& position);
-        static WebCore::Position trimSelectionPosition(
-                const WebCore::Position& start, const WebCore::Position& stop);
+        void scrollNodeIntoView(Frame* frame, Node* node);
+        bool isContentTextNode(Node* node);
+        Node* getIntermediaryInputElement(Node* fromNode, Node* toNode, int direction);
+        bool isContentInputElement(Node* node);
+        bool isDescendantOf(Node* parent, Node* node);
+        void advanceAnchorNode(DOMSelection* selection, int direction, String& markup, bool ignoreFirstNode, ExceptionCode& ec);
+        Node* getNextAnchorNode(Node* anchorNode, bool skipFirstHack, int direction);
+        Node* getImplicitBoundaryNode(Node* node, unsigned offset, int direction);
 
         // called from constructor, to add this to a global list
         static void addInstance(WebViewCore*);
         // called from destructor, to remove this from a global list
         static void removeInstance(WebViewCore*);
 
-        bool prerenderingEnabled();
-
         friend class ListBoxReply;
         struct JavaGlue;
         struct JavaGlue*       m_javaGlue;
-        struct TextFieldInitDataGlue;
-        struct TextFieldInitDataGlue* m_textFieldInitDataGlue;
         WebCore::Frame*        m_mainFrame;
         WebCoreReply*          m_popupReply;
-        WebCore::PicturePile m_content; // the set of pictures to draw
+        WebCore::Node* m_lastFocused;
+        WebCore::IntRect m_lastFocusedBounds;
+        int m_blurringNodePointer;
+        int m_lastFocusedSelStart;
+        int m_lastFocusedSelEnd;
+        PictureSet m_content; // the set of pictures to draw
+        SkRegion m_addInval; // the accumulated inval region (not yet drawn)
+        SkRegion m_rebuildInval; // the accumulated region for rebuilt pictures
         // Used in passToJS to avoid updating the UI text field until after the
         // key event has been processed.
         bool m_blockTextfieldUpdates;
@@ -764,33 +667,26 @@
         // Passed in with key events to know when they were generated.  Store it
         // with the cache so that we can ignore stale text changes.
         int m_textGeneration;
+        CachedRoot* m_temp;
+        SkPicture* m_tempPict;
         int m_maxXScroll;
         int m_maxYScroll;
         int m_scrollOffsetX; // webview.java's current scroll in X
         int m_scrollOffsetY; // webview.java's current scroll in Y
-        double m_scrollSetTime; // when the scroll was last set
         WebCore::IntPoint m_mousePos;
-        // This is the location at which we will click. This is tracked
-        // separately from m_mousePos, because m_mousePos may be updated
-        // in the interval between ACTION_UP and when the click fires since
-        // that occurs after a delay. This also works around potential hardware
-        // issues if we get onHoverEvents when using the touch screen, as that
-        // will nullify the slop checking we do in hitTest (aka, ACTION_DOWN)
-        WebCore::IntPoint m_mouseClickPos;
+        bool m_frameCacheOutOfDate;
+        bool m_progressDone;
+        CachedHistory m_history;
         int m_screenWidth; // width of the visible rect in document coordinates
         int m_screenHeight;// height of the visible rect in document coordinates
         int m_textWrapWidth;
         float m_scale;
-        WebCore::PageGroup* m_groupForVisitedLinks;
+        unsigned m_domtree_version;
+        bool m_check_domtree_version;
+        PageGroup* m_groupForVisitedLinks;
         bool m_isPaused;
         int m_cacheMode;
-        bool m_fullscreenVideoMode;
-
-        // find on page data
-        WTF::String m_searchText;
-        int m_matchCount;
-        int m_activeMatchIndex;
-        RefPtr<WebCore::Range> m_activeMatch;
+        bool m_shouldPaintCaret;
 
         SkTDArray<PluginWidgetAndroid*> m_plugins;
         WebCore::Timer<WebViewCore> m_pluginInvalTimer;
@@ -799,17 +695,17 @@
         }
 
         int m_screenOnCounter;
-        WebCore::Node* m_currentNodeDomNavigationAxis;
+        Node* m_currentNodeDomNavigationAxis;
         DeviceMotionAndOrientationManager m_deviceMotionAndOrientationManager;
 
 #if ENABLE(TOUCH_EVENTS)
         bool m_forwardingTouchEvents;
 #endif
 
+#if USE(CHROME_NETWORK_STACK)
         scoped_refptr<WebRequestContext> m_webRequestContext;
+#endif
 
-        WTF::Mutex m_prerenderLock;
-        bool m_prerenderEnabled;
     };
 
 }   // namespace android
diff --git a/Source/WebKit/android/nav/CacheBuilder.cpp b/Source/WebKit/android/nav/CacheBuilder.cpp
new file mode 100644
index 0000000..940991f
--- /dev/null
+++ b/Source/WebKit/android/nav/CacheBuilder.cpp
@@ -0,0 +1,3194 @@
+/*
+ * Copyright 2006, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CachedPrefix.h"
+#include "CachedNode.h"
+#include "CachedRoot.h"
+#include "ColumnInfo.h"
+#include "Document.h"
+#include "EventListener.h"
+#include "EventNames.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "FrameLoaderClientAndroid.h"
+#include "FrameTree.h"
+#include "FrameView.h"
+//#include "GraphicsContext.h"
+#include "HTMLAreaElement.h"
+#include "HTMLImageElement.h"
+#include "HTMLInputElement.h"
+#include "HTMLMapElement.h"
+#include "HTMLNames.h"
+#include "HTMLOptionElement.h"
+#include "HTMLSelectElement.h"
+#include "HTMLTextAreaElement.h"
+#include "InlineTextBox.h"
+#include "KURL.h"
+#include "LayerAndroid.h"
+#include "PluginView.h"
+#include "RegisteredEventListener.h"
+#include "RenderImage.h"
+#include "RenderInline.h"
+#include "RenderLayerBacking.h"
+#include "RenderListBox.h"
+#include "RenderSkinCombo.h"
+#include "RenderTextControl.h"
+#include "RenderView.h"
+#include "RenderWidget.h"
+#include "SkCanvas.h"
+#include "SkPoint.h"
+#include "Text.h"
+#include "WebCoreFrameBridge.h"
+#include "WebCoreViewBridge.h"
+#include "Widget.h"
+#include <wtf/unicode/Unicode.h>
+
+#ifdef DUMP_NAV_CACHE_USING_PRINTF
+    FILE* gNavCacheLogFile = NULL;
+    android::Mutex gWriteLogMutex;
+#endif
+
+#include "CacheBuilder.h"
+
+#define MINIMUM_FOCUSABLE_WIDTH 3
+#define MINIMUM_FOCUSABLE_HEIGHT 3
+#define MAXIMUM_FOCUS_RING_COUNT 32
+
+namespace android {
+
+CacheBuilder* CacheBuilder::Builder(Frame* frame) { 
+    return &((FrameLoaderClientAndroid*) frame->loader()->client())->getCacheBuilder(); 
+}
+
+Frame* CacheBuilder::FrameAnd(CacheBuilder* cacheBuilder) { 
+    FrameLoaderClientAndroid* loader = (FrameLoaderClientAndroid*)
+        ((char*) cacheBuilder - OFFSETOF(FrameLoaderClientAndroid, m_cacheBuilder));
+    return loader->getFrame();
+}
+
+Frame* CacheBuilder::FrameAnd(const CacheBuilder* cacheBuilder) { 
+    FrameLoaderClientAndroid* loader = (FrameLoaderClientAndroid*)
+        ((char*) cacheBuilder - OFFSETOF(FrameLoaderClientAndroid, m_cacheBuilder)); 
+    return loader->getFrame();
+}
+
+CacheBuilder::LayerTracker::~LayerTracker() {
+    // Check for a stacking context to prevent a crash in layers without a
+    // parent.
+    if (mRenderLayer && mRenderLayer->stackingContext())
+        // Restore the scroll position of the layer.  Does not affect layers
+        // without overflow scroll as the layer will not be scrolled.
+        mRenderLayer->scrollToOffset(mScroll.x(), mScroll.y());
+}
+
+#if DUMP_NAV_CACHE
+
+static bool hasEventListener(Node* node, const AtomicString& eventType) {
+    if (!node->isElementNode())
+        return false;
+    Element* element = static_cast<Element*>(node);
+    EventListener* listener = element->getAttributeEventListener(eventType);
+    return 0 != listener;
+}
+
+#define DEBUG_BUFFER_SIZE 256
+#define DEBUG_WRAP_SIZE 150
+#define DEBUG_WRAP_MAX 170
+
+Frame* CacheBuilder::Debug::frameAnd() const {
+    CacheBuilder* nav = (CacheBuilder*) ((char*) this - OFFSETOF(CacheBuilder, mDebug));
+    return CacheBuilder::FrameAnd(nav); 
+}
+
+void CacheBuilder::Debug::attr(const AtomicString& name, const AtomicString& value) {
+    if (name.isNull() || name.isEmpty() || value.isNull() || value.isEmpty())
+        return;
+    uChar(name.characters(), name.length(), false);
+    print("=");
+    wideString(value.characters(), value.length(), false);
+    print(" ");
+}
+
+void CacheBuilder::Debug::comma(const char* str) {
+    print(str);
+    print(", ");
+}
+
+void CacheBuilder::Debug::flush() {
+    int len;
+    do {
+        int limit = mIndex;
+        if (limit < DEBUG_WRAP_SIZE)
+            return;
+        if (limit < DEBUG_WRAP_MAX)
+            len = limit;
+        else {
+            limit = DEBUG_WRAP_MAX;
+            len = DEBUG_WRAP_SIZE;
+            while (len < limit) {
+                char test = mBuffer[len];
+                if (test < '/' || (test > '9' && test < 'A') || (test > 'Z' && test  < 'a') || test > 'z')
+                    break;
+                len++;
+            }
+            while (len > 0 && mBuffer[len - 1] == '\\')
+                len--;
+            while (mBuffer[len] == '"')
+                len++;
+        }
+        const char* prefix = mPrefix;
+        if (prefix[0] == '\"') {
+            // see if we're inside a quote
+            int quoteCount = 0;
+            for (int index = 0; index < len; index++) {
+                if (mBuffer[index] == '\\') {
+                    index++;
+                    continue;
+                }
+                if (mBuffer[index] == '\n') {
+                    quoteCount = 0;
+                    continue;
+                }
+                if (mBuffer[index] == '"')
+                    quoteCount++;
+            }
+            if ((quoteCount & 1) == 0)
+                prefix = "\n";
+        }
+        DUMP_NAV_LOGD("%.*s", len, mBuffer);
+        int copy = mIndex - len;
+        strcpy(mBuffer, prefix);
+        memcpy(&mBuffer[strlen(prefix)], &mBuffer[len], copy);
+        mIndex = strlen(prefix) + copy;
+    } while (true);
+}
+
+void CacheBuilder::Debug::frameName(char*& namePtr, const char* max) const {
+   if (namePtr >= max)
+        return;
+   Frame* frame = frameAnd();
+   Frame* parent = frame->tree()->parent();
+   if (parent)
+        Builder(parent)->mDebug.frameName(namePtr, max);
+    const AtomicString& name = frame->tree()->name();
+    if (name.length() == 0)
+        return;
+    unsigned index = 0;
+    if (name.startsWith(AtomicString("opener")))
+        index = 6;
+    for (; index < name.length(); index++) {
+        char ch = name[index];
+        if (ch <= ' ')
+            ch = '_';
+        if (WTF::isASCIIAlphanumeric(ch) || ch == '_')
+            *namePtr++  = ch;
+    }
+}
+    
+void CacheBuilder::Debug::frames() {
+    Frame* frame = frameAnd();
+    Document* doc = frame->document();
+    if (doc == NULL)
+        return;
+    bool top = frame->tree()->parent() == NULL;
+    if (top) {
+#ifdef DUMP_NAV_CACHE_USING_PRINTF
+        gWriteLogMutex.lock();
+        ASSERT(gNavCacheLogFile == NULL);
+        gNavCacheLogFile = fopen(NAV_CACHE_LOG_FILE, "a");
+#endif
+        groups();
+    }
+    Frame* child = frame->tree()->firstChild();
+    bool hasChild = child != NULL;   
+    if (top && hasChild)
+        DUMP_NAV_LOGD("\nnamespace TEST_SPACE {\n\n");
+    while (child) {
+        Builder(child)->mDebug.frames();
+        child = child->tree()->nextSibling();
+    }
+    if (hasChild) {
+        child = frame->tree()->firstChild();
+        while (child) {
+            char childName[256];
+            char* childNamePtr = childName;
+            Builder(child)->mDebug.frameName(childNamePtr, childNamePtr + sizeof(childName) - 1);
+            *childNamePtr = '\0';
+            if (child == frame->tree()->firstChild())
+                DUMP_NAV_LOGD("DebugTestFrameGroup TEST%s_GROUP[] = {\n", childName);
+            Frame* next = child->tree()->nextSibling();
+            Document* doc = child->document();
+            if (doc != NULL) {        
+                RenderObject* renderer = doc->renderer();
+                if (renderer != NULL) {
+                    RenderLayer* layer = renderer->enclosingLayer();
+                    if (layer != NULL) {
+                        DUMP_NAV_LOGD("{ ");
+                        DUMP_NAV_LOGD("TEST%s_RECTS, ", childName);
+                        DUMP_NAV_LOGD("TEST%s_RECT_COUNT, ", childName);
+                        DUMP_NAV_LOGD("TEST%s_RECTPARTS, ", childName);
+                        DUMP_NAV_LOGD("TEST%s_BOUNDS,\n", childName); 
+                        DUMP_NAV_LOGD("TEST%s_WIDTH, ", childName);
+                        DUMP_NAV_LOGD("TEST%s_HEIGHT,\n", childName);
+                        DUMP_NAV_LOGD("0, 0, 0, 0,\n");
+                        DUMP_NAV_LOGD("TEST%s_FOCUS, ", childName);
+                        Frame* grandChild = child->tree()->firstChild();
+                         if (grandChild) {
+                            char grandChildName[256];
+                            char* grandChildNamePtr = grandChildName;
+                            Builder(grandChild)->mDebug.frameName(grandChildNamePtr, 
+                                grandChildNamePtr + sizeof(grandChildName) - 1);
+                            *grandChildNamePtr = '\0';
+                            DUMP_NAV_LOGD("TEST%s_GROUP, ", grandChildName);
+                            DUMP_NAV_LOGD("sizeof(TEST%s_GROUP) / sizeof(DebugTestFrameGroup), ", grandChildName);
+                        } else
+                            DUMP_NAV_LOGD("NULL, 0, ");
+                        DUMP_NAV_LOGD("\"%s\"\n", childName);
+                        DUMP_NAV_LOGD("}%c\n", next ? ',' : ' ');
+                    }
+                }
+            }
+            child = next;
+        }
+        DUMP_NAV_LOGD("};\n");
+    }
+    if (top) {
+        if (hasChild)
+            DUMP_NAV_LOGD("\n}  // end of namespace\n\n");
+        char name[256];
+        char* frameNamePtr = name;
+        frameName(frameNamePtr, frameNamePtr + sizeof(name) - 1);
+        *frameNamePtr = '\0';
+        DUMP_NAV_LOGD("DebugTestFrameGroup TEST%s_GROUP = {\n", name);
+        DUMP_NAV_LOGD("TEST%s_RECTS, ", name);
+        DUMP_NAV_LOGD("TEST%s_RECT_COUNT, ", name);
+        DUMP_NAV_LOGD("TEST%s_RECTPARTS, ", name);
+        DUMP_NAV_LOGD("TEST%s_BOUNDS,\n", name); 
+        DUMP_NAV_LOGD("TEST%s_WIDTH, ", name);
+        DUMP_NAV_LOGD("TEST%s_HEIGHT,\n", name);
+        DUMP_NAV_LOGD("TEST%s_MAX_H, ", name);
+        DUMP_NAV_LOGD("TEST%s_MIN_H, ", name);
+        DUMP_NAV_LOGD("TEST%s_MAX_V, ", name);
+        DUMP_NAV_LOGD("TEST%s_MIN_V,\n", name);
+        DUMP_NAV_LOGD("TEST%s_FOCUS, ", name);
+        if (hasChild) {
+            child = frame->tree()->firstChild();
+            char childName[256];
+            char* childNamePtr = childName;
+            Builder(child)->mDebug.frameName(childNamePtr, childNamePtr + sizeof(childName) - 1);
+            *childNamePtr = '\0';
+            DUMP_NAV_LOGD("TEST_SPACE::TEST%s_GROUP, ", childName);
+            DUMP_NAV_LOGD("sizeof(TEST_SPACE::TEST%s_GROUP) / sizeof(DebugTestFrameGroup), \n" ,childName);
+        } else
+            DUMP_NAV_LOGD("NULL, 0, ");
+        DUMP_NAV_LOGD("\"%s\"\n", name);
+        DUMP_NAV_LOGD("};\n");
+#ifdef DUMP_NAV_CACHE_USING_PRINTF
+        if (gNavCacheLogFile)
+            fclose(gNavCacheLogFile);
+        gNavCacheLogFile = NULL;
+        gWriteLogMutex.unlock();
+#endif
+    }
+}
+
+void CacheBuilder::Debug::init(char* buffer, size_t size) {
+    mBuffer = buffer;
+    mBufferSize = size;
+    mIndex = 0;
+    mPrefix = "";
+}
+
+void CacheBuilder::Debug::groups() {
+    Frame* frame = frameAnd();
+    Frame* child = frame->tree()->firstChild();
+    bool hasChild = child != NULL;
+    if (frame->tree()->parent() == NULL && hasChild)
+        DUMP_NAV_LOGD("namespace TEST_SPACE {\n\n");
+    while (child) {
+        Builder(child)->mDebug.groups();
+        child = child->tree()->nextSibling();
+    }
+    if (frame->tree()->parent() == NULL && hasChild)
+        DUMP_NAV_LOGD("\n} // end of namespace\n\n"); 
+    Document* doc = frame->document();
+    char name[256];
+    char* frameNamePtr = name;
+    frameName(frameNamePtr, frameNamePtr + sizeof(name) - 1);
+    *frameNamePtr = '\0';
+    if (doc == NULL) {
+        DUMP_NAV_LOGD("// %s has no document\n", name);
+        return;
+    }
+    RenderObject* renderer = doc->renderer();
+    if (renderer == NULL) {
+        DUMP_NAV_LOGD("// %s has no renderer\n", name);
+        return;
+    }
+    RenderLayer* layer = renderer->enclosingLayer();
+    if (layer == NULL) {
+        DUMP_NAV_LOGD("// %s has no enclosingLayer\n", name);
+        return;
+    }
+    Node* node = doc;
+    Node* focus = doc->focusedNode();
+    bool atLeastOne = false;
+    do {
+        if ((atLeastOne |= isFocusable(node)) != false)
+            break;
+    } while ((node = node->traverseNextNode()) != NULL);
+    int focusIndex = -1;
+    if (atLeastOne == false) {
+        DUMP_NAV_LOGD("static DebugTestNode TEST%s_RECTS[] = {\n"
+            "{{0, 0, 0, 0}, \"\", 0, -1, \"\", {0, 0, 0, 0}, false, 0}\n"
+            "};\n\n", name);
+        DUMP_NAV_LOGD("static int TEST%s_RECT_COUNT = 1;"
+            " // no focusable nodes\n", name);
+        DUMP_NAV_LOGD("#define TEST%s_RECTPARTS NULL\n", name);
+    } else {
+        node = doc;
+        int count = 1;
+        DUMP_NAV_LOGD("static DebugTestNode TEST%s_RECTS[] = {\n", name);
+        do {
+            String properties;
+            if (hasEventListener(node, eventNames().clickEvent))
+                properties.append("ONCLICK | ");
+            if (hasEventListener(node, eventNames().mousedownEvent))
+                properties.append("MOUSEDOWN | ");
+            if (hasEventListener(node, eventNames().mouseupEvent))
+                properties.append("MOUSEUP | ");
+            if (hasEventListener(node, eventNames().mouseoverEvent))
+                properties.append("MOUSEOVER | ");
+            if (hasEventListener(node, eventNames().mouseoutEvent))
+                properties.append("MOUSEOUT | ");
+            if (hasEventListener(node, eventNames().keydownEvent))
+                properties.append("KEYDOWN | ");
+            if (hasEventListener(node, eventNames().keyupEvent))
+                properties.append("KEYUP | ");
+            if (CacheBuilder::HasFrame(node))
+                properties.append("FRAME | ");
+            if (focus == node) {
+                properties.append("FOCUS | ");
+                focusIndex = count;
+            }
+            if (node->isKeyboardFocusable(NULL))
+                properties.append("KEYBOARD_FOCUSABLE | ");
+            if (node->isMouseFocusable())
+                properties.append("MOUSE_FOCUSABLE | ");
+            if (node->isFocusable())
+                properties.append("SIMPLE_FOCUSABLE | ");
+            if (properties.isEmpty())
+                properties.append("0");
+            else
+                properties.truncate(properties.length() - 3);
+            IntRect rect = node->getRect();
+            if (node->hasTagName(HTMLNames::areaTag))
+                rect = getAreaRect(static_cast<HTMLAreaElement*>(node));
+            char buffer[DEBUG_BUFFER_SIZE];
+            memset(buffer, 0, sizeof(buffer));
+            mBuffer = buffer;
+            mBufferSize = sizeof(buffer);
+            mPrefix = "\"\n\"";
+            mIndex = snprintf(buffer, sizeof(buffer), "{{%d, %d, %d, %d}, ", rect.x(), rect.y(), 
+                rect.width(), rect.height());
+            localName(node);
+            uChar(properties.characters(), properties.length(), false);
+            print(", ");
+            int parentIndex = ParentIndex(node, count, node->parentNode());
+            char scratch[256];
+            snprintf(scratch, sizeof(scratch), "%d", parentIndex);
+            comma(scratch);
+            Element* element = static_cast<Element*>(node);
+            if (node->isElementNode() && element->hasID())
+                wideString(element->getIdAttribute());
+            else if (node->isTextNode()) {
+ #if 01 // set to one to abbreviate text that can be omitted from the address detection code
+               if (rect.isEmpty() && node->textContent().length() > 100) {
+                    wideString(node->textContent().characters(), 100, false);
+                    snprintf(scratch, sizeof(scratch), "/* + %d bytes */", 
+                        node->textContent().length() - 100);
+                    print(scratch);
+                } else
+ #endif
+                   wideString(node->textContent().characters(), node->textContent().length(), true);
+            } else if (node->hasTagName(HTMLNames::aTag) || 
+                node->hasTagName(HTMLNames::areaTag)) 
+            {
+                HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(node);
+                wideString(anchor->href());
+            } else if (node->hasTagName(HTMLNames::imgTag)) {
+                HTMLImageElement* image = static_cast<HTMLImageElement*>(node);
+                wideString(image->src());
+            } else 
+                print("\"\"");
+            RenderObject* renderer = node->renderer();
+            int tabindex = node->isElementNode() ? node->tabIndex() : 0;
+            RenderLayer* layer = 0;
+            if (renderer) {
+                const IntRect& absB = renderer->absoluteBoundingBoxRect();
+                bool hasLayer = renderer->hasLayer();
+                layer = hasLayer ? toRenderBoxModelObject(renderer)->layer() : 0;
+                snprintf(scratch, sizeof(scratch), ", {%d, %d, %d, %d}, %s"
+                    ", %d, %s, %s},",
+                    absB.x(), absB.y(), absB.width(), absB.height(),
+                    renderer->hasOverflowClip() ? "true" : "false", tabindex,
+                    hasLayer ? "true" : "false",
+                    hasLayer && layer->isComposited() ? "true" : "false");
+                // TODO: add renderer->style()->visibility()
+                print(scratch);
+            } else
+                print(", {0, 0, 0, 0}, false, 0},");
+
+            flush();
+            snprintf(scratch, sizeof(scratch), "// %d: ", count);
+            mPrefix = "\n// ";
+            print(scratch);
+            //print(renderer ? renderer->information().ascii() : "NO_RENDER_INFO");
+            if (node->isElementNode()) {
+                Element* element = static_cast<Element*>(node);
+                NamedNodeMap* attrs = element->attributes();
+                unsigned length = attrs->length();
+                if (length > 0) {
+                    newLine();
+                    print("// attr: ");
+                    for (unsigned i = 0; i < length; i++) {
+                        Attribute* a = attrs->attributeItem(i);
+                        attr(a->localName(), a->value());
+                    }
+                }
+            }
+            if (renderer) {
+                RenderStyle* style = renderer->style();
+                snprintf(scratch, sizeof(scratch), "// renderStyle:"
+                    " visibility=%s hasBackGround=%d"
+                    " tapHighlightColor().alpha()=0x%02x"
+                    " isTransparent()=%s",
+                    style->visibility() == HIDDEN ? "HIDDEN" : "VISIBLE",
+                    renderer->hasBackground(), style->tapHighlightColor().alpha(),
+                    renderer->isTransparent() ? "true" : "false");
+                newLine();
+                print(scratch);
+                RenderBlock* renderBlock = static_cast<RenderBlock*>(renderer);
+                if (renderer->isRenderBlock() && renderBlock->hasColumns()) {
+                    const RenderBox* box = static_cast<RenderBox*>(renderer);
+                    const IntRect& oRect = box->visibleOverflowRect();
+                    snprintf(scratch, sizeof(scratch), "// renderBlock:"
+                        " columnCount=%d columnGap=%d direction=%d"
+                        " hasOverflowClip=%d overflow=(%d,%d,w=%d,h=%d)",
+                        renderBlock->columnInfo()->columnCount(), renderBlock->columnGap(),
+                        renderBlock->style()->direction(), renderer->hasOverflowClip(),
+                        oRect.x(), oRect.y(), oRect.width(), oRect.height());
+                    newLine();
+                    print(scratch);
+                }
+            }
+ #if USE(ACCELERATED_COMPOSITING)
+            if (renderer && renderer->hasLayer()) {
+                RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
+                RenderLayerBacking* back = layer->backing();
+                GraphicsLayer* grLayer = back ? back->graphicsLayer() : 0;
+                LayerAndroid* aLayer = grLayer ? grLayer->platformLayer() : 0;
+                const SkPicture* pict = aLayer ? aLayer->picture() : 0;
+                const IntRect& r = renderer->absoluteBoundingBoxRect();
+                snprintf(scratch, sizeof(scratch), "// layer:%p back:%p"
+                    " gLayer:%p aLayer:%p pict:%p r:(%d,%d,w=%d,h=%d)",
+                    layer, back, grLayer, aLayer, pict, r.x(), r.y(),
+                    r.width(), r.height());
+                newLine();
+                print(scratch);
+            }
+ #endif
+            count++;
+            newLine();
+        } while ((node = node->traverseNextNode()) != NULL);
+        DUMP_NAV_LOGD("}; // focusables = %d\n", count - 1);
+        DUMP_NAV_LOGD("\n");
+        DUMP_NAV_LOGD("static int TEST%s_RECT_COUNT = %d;\n\n", name, count - 1);
+        // look for rects with multiple parts
+        node = doc;
+        count = 1;
+        bool hasRectParts = false;
+        int globalOffsetX, globalOffsetY;
+        GetGlobalOffset(frame, &globalOffsetX, &globalOffsetY);
+        do {
+            IntRect rect;
+            bool _isFocusable = isFocusable(node) || (node->isTextNode() 
+              && node->getRect().isEmpty() == false
+                );
+            int nodeIndex = count++;
+            if (_isFocusable == false)
+                continue;
+            RenderObject* renderer = node->renderer();
+            if (renderer == NULL)
+                continue;
+            WTF::Vector<IntRect> rects;
+            IntRect clipBounds = IntRect(0, 0, INT_MAX, INT_MAX);
+            IntRect focusBounds = IntRect(0, 0, INT_MAX, INT_MAX);
+            IntRect* rectPtr = &focusBounds;
+            int imageCount = 0;
+            if (node->isTextNode()) {
+                Text* textNode = (Text*) node;
+                if (CacheBuilder::ConstructTextRects(textNode, 0, textNode, 
+                        INT_MAX, globalOffsetX, globalOffsetY, rectPtr, 
+                        clipBounds, &rects) == false)
+                    continue;
+            } else {
+                IntRect nodeBounds = node->getRect();
+                if (CacheBuilder::ConstructPartRects(node, nodeBounds, rectPtr, 
+                        globalOffsetX, globalOffsetY, &rects, &imageCount) == false)
+                    continue;
+            }
+            unsigned arraySize = rects.size();
+            if (arraySize > 1 || (arraySize == 1 && (rectPtr->width() != rect.width())) || 
+                    rectPtr->height() != rect.height()) {
+                if (hasRectParts == false) {
+                    DUMP_NAV_LOGD("static DebugTestRectPart TEST%s_RECTPARTS[] = {\n", name);
+                    hasRectParts = true;
+                }
+                if (node->isTextNode() == false) {
+                    unsigned rectIndex = 0;
+                    for (; rectIndex < arraySize; rectIndex++) {
+                        rectPtr = &rects.at(rectIndex);
+                        DUMP_NAV_LOGD("{ %d, %d, %d, %d, %d }, // %d\n", nodeIndex, 
+                            rectPtr->x(), rectPtr->y(), rectPtr->width(), 
+                            rectPtr->height(), rectIndex + 1);
+                    }
+                } else {
+                    RenderText* renderText = (RenderText*) node->renderer();
+                    InlineTextBox* textBox = renderText->firstTextBox();
+                    unsigned rectIndex = 0;
+                    while (textBox) {
+                        FloatPoint pt = renderText->localToAbsolute();
+                        IntRect rect = textBox->selectionRect((int) pt.x(), (int) pt.y(), 0, INT_MAX);
+                        mIndex = 0;
+                        mIndex += snprintf(&mBuffer[mIndex], mBufferSize - mIndex, "{ %d, %d, %d, %d, %d", 
+                            nodeIndex, rect.x(), rect.y(), rect.width(), rect.height());
+                        mIndex += snprintf(&mBuffer[mIndex], mBufferSize - mIndex, ", %d, %d, %d", 
+                            textBox->len(), 0 /*textBox->selectionHeight()*/, 
+                            0 /*textBox->selectionTop()*/);
+                        mIndex += snprintf(&mBuffer[mIndex], mBufferSize - mIndex, ", %d, %d, %d", 
+                            0 /*textBox->spaceAdd()*/, textBox->start(), 0 /*textBox->textPos()*/);
+                        mIndex += snprintf(&mBuffer[mIndex], mBufferSize - mIndex, ", %d, %d, %d, %d", 
+                            textBox->x(), textBox->y(), textBox->logicalWidth(), textBox->logicalHeight());
+                        int baseline = textBox->renderer()->style(textBox->isFirstLineStyle())->font().ascent();
+                        mIndex += snprintf(&mBuffer[mIndex], mBufferSize - mIndex, ", %d, %d }, // %d ",
+                            baseline, imageCount, ++rectIndex);
+                        wideString(node->textContent().characters() + textBox->start(), textBox->len(), true);
+                        DUMP_NAV_LOGD("%.*s\n", mIndex, mBuffer);
+                        textBox = textBox->nextTextBox();
+                    }
+                }
+            }
+        } while ((node = node->traverseNextNode()) != NULL);
+        if (hasRectParts)
+            DUMP_NAV_LOGD("{0}\n};\n\n");
+        else
+            DUMP_NAV_LOGD("static DebugTestRectPart* TEST%s_RECTPARTS = NULL;\n", name);
+    }
+    int contentsWidth = layer->width();
+    int contentsHeight = layer->height();
+    DUMP_NAV_LOGD("static int TEST%s_FOCUS = %d;\n", name, focusIndex);        
+    DUMP_NAV_LOGD("static int TEST%s_WIDTH = %d;\n", name, contentsWidth);
+    DUMP_NAV_LOGD("static int TEST%s_HEIGHT = %d;\n\n", name, contentsHeight);
+}
+
+bool CacheBuilder::Debug::isFocusable(Node* node) {
+    if (node->hasTagName(HTMLNames::areaTag))
+        return true;
+    if (node->renderer() == false)
+        return false;
+    if (node->isKeyboardFocusable(NULL))
+        return true;
+    if (node->isMouseFocusable())
+        return true;
+    if (node->isFocusable())
+        return true;
+    if (CacheBuilder::AnyIsClick(node))
+        return false;
+    if (CacheBuilder::HasTriggerEvent(node))
+        return true;
+    return false;
+}
+
+void CacheBuilder::Debug::localName(Node* node) {
+    const AtomicString& local = node->localName();
+    if (node->isTextNode())
+        print("\"#text\"");
+    else
+        wideString(local.characters(), local.length(), false);
+    print(", ");
+}
+
+void CacheBuilder::Debug::newLine(int indent) {
+    if (mPrefix[0] != '\n')
+        print(&mPrefix[0], 1);
+    flush();
+    int lastnewline = mIndex - 1;
+    while (lastnewline >= 0 && mBuffer[lastnewline] != '\n')
+        lastnewline--;
+    lastnewline++;
+    char* buffer = mBuffer;
+    if (lastnewline > 0) {
+        DUMP_NAV_LOGD("%.*s", lastnewline, buffer);
+        mIndex -= lastnewline;
+        buffer += lastnewline;
+    }
+    size_t prefixLen = strlen(mPrefix);
+    int minPrefix = prefixLen - 1;
+    while (minPrefix >= 0 && mPrefix[minPrefix] != '\n')
+        minPrefix--;
+    minPrefix = prefixLen - minPrefix - 1;
+    if (mIndex > minPrefix)
+        DUMP_NAV_LOGD("%.*s\n", mIndex, buffer);
+    mIndex = 0;
+    setIndent(indent);
+}
+
+int CacheBuilder::Debug::ParentIndex(Node* node, int count, Node* parent) 
+{
+    if (parent == NULL)
+        return -1;
+    ASSERT(node != parent);
+    int result = count;
+    Node* previous = node;
+    do {
+        result--;
+        previous = previous->traversePreviousNode();
+    } while (previous && previous != parent);
+    if (previous != NULL) 
+        return result;
+    result = count;
+    do {
+        result++;
+    } while ((node = node->traverseNextNode()) != NULL && node != parent);
+    if (node != NULL)
+        return result;
+    ASSERT(0);
+    return -1;
+}
+
+void CacheBuilder::Debug::print(const char* name) {
+    print(name, strlen(name));
+}
+
+void CacheBuilder::Debug::print(const char* name, unsigned len) {
+    do {
+        if (mIndex + len >= DEBUG_BUFFER_SIZE)
+            flush();
+        int copyLen = mIndex + len < DEBUG_BUFFER_SIZE ?
+             len : DEBUG_BUFFER_SIZE - mIndex;
+        memcpy(&mBuffer[mIndex], name, copyLen);
+        mIndex += copyLen;
+        name += copyLen;
+        len -= copyLen;
+    } while (len > 0);
+    mBuffer[mIndex] = '\0';
+}
+
+void CacheBuilder::Debug::setIndent(int indent)
+{
+    char scratch[64];
+    snprintf(scratch, sizeof(scratch), "%.*s", indent, 
+        "                                                                    ");
+    print(scratch);
+}
+
+void CacheBuilder::Debug::uChar(const UChar* name, unsigned len, bool hex) {
+    const UChar* end = name + len;
+    bool wroteHex = false;
+    while (name < end) {
+        unsigned ch = *name++;
+        if (ch == '\t' || ch == '\n' || ch == '\r' || ch == 0xa0)
+            ch = ' ';
+        if (ch < ' ' || ch == 0x7f) {
+            if (hex) {
+                mIndex += snprintf(&mBuffer[mIndex], mBufferSize - mIndex, "\\x%02x", ch);
+                wroteHex = true;
+            } else
+                mBuffer[mIndex++] = '?';
+        } else if (ch >= 0x80) {
+            if (hex) {
+                if (ch < 0x800)
+                    mIndex += snprintf(&mBuffer[mIndex], mBufferSize - mIndex,
+                        "\\x%02x\\x%02x", ch >> 6 | 0xc0, (ch & 0x3f) | 0x80);
+                else
+                    mIndex += snprintf(&mBuffer[mIndex], mBufferSize - mIndex,
+                        "\\x%02x\\x%02x\\x%02x", ch >> 12 | 0xe0,
+                        (ch >> 6 & 0x3f) | 0x80, (ch & 0x3f) | 0x80);
+                wroteHex = true;
+            } else
+                mBuffer[mIndex++] = '?';
+        } else {
+            if (wroteHex && WTF::isASCIIHexDigit((UChar) ch))
+                mIndex += snprintf(&mBuffer[mIndex], mBufferSize - mIndex,
+                    "\" \"");
+            else if (ch == '"' || ch == '\\')
+                mBuffer[mIndex++] = '\\';
+            mBuffer[mIndex++] = ch;
+            wroteHex = false;
+        }
+        if (mIndex + 1 >= DEBUG_BUFFER_SIZE)
+            flush();
+    }
+    flush();
+}
+
+void CacheBuilder::Debug::validateFrame() {
+    Frame* frame = frameAnd();
+    Page* page = frame->page();
+    ASSERT(page);
+    ASSERT((int) page > 0x10000);
+    Frame* child = frame->tree()->firstChild();
+    while (child) {
+        Builder(child)->mDebug.validateFrame();
+        child = child->tree()->nextSibling();
+    }
+}
+
+void CacheBuilder::Debug::wideString(const UChar* chars, int length, bool hex) {
+    if (length == 0)
+        print("\"\"");
+    else {
+        print("\"");
+        uChar(chars, length, hex);
+        print("\"");
+    }
+}
+
+void CacheBuilder::Debug::wideString(const String& str) {
+    wideString(str.characters(), str.length(), false);
+}
+
+#endif // DUMP_NAV_CACHE
+
+CacheBuilder::CacheBuilder()
+{
+    mAllowableTypes = ALL_CACHEDNODE_BITS;
+#ifdef DUMP_NAV_CACHE_USING_PRINTF
+    gNavCacheLogFile = NULL;
+#endif
+}
+
+void CacheBuilder::adjustForColumns(const ClipColumnTracker& track, 
+    CachedNode* node, IntRect* bounds, RenderBlock* renderer)
+{
+    if (!renderer->hasColumns())
+        return;
+    int x = 0;
+    int y = 0;
+    int tx = track.mBounds.x();
+    int ty = track.mBounds.y();
+    int columnGap = track.mColumnGap;
+    size_t limit = track.mColumnInfo->columnCount();
+    for (size_t index = 0; index < limit; index++) {
+        IntRect column = renderer->columnRectAt(track.mColumnInfo, index);
+        column.move(tx, ty);
+        IntRect test = *bounds;
+        test.move(x, y);
+        if (column.contains(test)) {
+            if ((x | y) == 0)
+                return;
+            *bounds = test;
+            node->move(x, y);
+            return;
+        }
+        int xOffset = column.width() + columnGap;
+        x += track.mDirection == LTR ? xOffset : -xOffset;
+        y -= column.height();
+    }    
+}
+
+// Checks if a node has one of event listener types.
+bool CacheBuilder::NodeHasEventListeners(Node* node, AtomicString* eventTypes, int length) {
+    for (int i = 0; i < length; ++i) {
+        if (!node->getEventListeners(eventTypes[i]).isEmpty())
+            return true;
+    }
+    return false;
+}
+
+bool CacheBuilder::AnyChildIsClick(Node* node)
+{
+    AtomicString eventTypes[5] = {
+        eventNames().clickEvent,
+        eventNames().mousedownEvent,
+        eventNames().mouseupEvent,
+        eventNames().keydownEvent,
+        eventNames().keyupEvent
+    };
+
+    Node* child = node->firstChild();
+    while (child != NULL) {
+        if (child->isFocusable() ||
+            NodeHasEventListeners(child, eventTypes, 5))
+                return true;
+        if (AnyChildIsClick(child))
+            return true;
+        child = child->nextSibling();
+    }
+    return false;
+}
+
+bool CacheBuilder::AnyIsClick(Node* node)
+{
+    if (node->hasTagName(HTMLNames::bodyTag))
+        return AnyChildIsClick(node);
+
+    AtomicString eventTypeSetOne[4] = {
+        eventNames().mouseoverEvent,
+        eventNames().mouseoutEvent,
+        eventNames().keydownEvent,
+        eventNames().keyupEvent
+    };
+
+    if (!NodeHasEventListeners(node, eventTypeSetOne, 4))
+        return false;
+
+    AtomicString eventTypeSetTwo[3] = {
+        eventNames().clickEvent,
+        eventNames().mousedownEvent,
+        eventNames().mouseupEvent
+    };
+
+    if (NodeHasEventListeners(node, eventTypeSetTwo, 3))
+        return false;
+
+    return AnyChildIsClick(node);
+}
+
+void CacheBuilder::buildCache(CachedRoot* root)
+{
+    Frame* frame = FrameAnd(this);
+    mPictureSetDisabled = false;
+    BuildFrame(frame, frame, root, (CachedFrame*) root);
+    root->finishInit(); // set up frame parent pointers, child pointers
+    setData((CachedFrame*) root);
+}
+
+static Node* ParentWithChildren(Node* node)
+{
+    Node* parent = node;
+    while ((parent = parent->parentNode())) {
+        if (parent->childNodeCount() > 1)
+            return parent;
+    }
+    return 0;
+}
+
+// FIXME
+// Probably this should check for null instead of the caller. If the
+// Tracker object is the last thing in the dom, checking for null in the
+// caller in some cases fails to set up Tracker state which may be useful
+// to the nodes parsed immediately after the tracked noe.
+static Node* OneAfter(Node* node) 
+{
+    Node* parent = node;
+    Node* sibling = NULL;
+    while ((parent = parent->parentNode()) != NULL) {
+        sibling = parent->nextSibling();
+        if (sibling != NULL)
+            break;
+    }
+    return sibling;
+}
+
+// return true if this renderer is really a pluinview, and it wants
+// key-events (i.e. focus)
+static bool checkForPluginViewThatWantsFocus(RenderObject* renderer) {
+    if (renderer->isWidget()) {
+        Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
+        if (widget && (widget->isPluginView() || widget->isPluginViewBase())) {
+            // check if this plugin really wants key events (TODO)
+            return true;
+        }
+    }
+    return false;
+}
+
+#if USE(ACCELERATED_COMPOSITING)
+static void AddLayer(CachedFrame* frame, size_t index, const IntPoint& location, int id)
+{
+    DBG_NAV_LOGD("frame=%p index=%d loc=(%d,%d) id=%d", frame, index,
+        location.x(), location.y(), id);
+    CachedLayer cachedLayer;
+    cachedLayer.setCachedNodeIndex(index);
+    cachedLayer.setOffset(location);
+    cachedLayer.setUniqueId(id);
+    frame->add(cachedLayer);
+}
+#endif
+
+static int FindColorIndex(WTF::Vector<CachedColor>& colorTracker,
+    const CachedColor& cachedColor)
+{
+    CachedColor* work = colorTracker.begin() - 1;
+    CachedColor* end = colorTracker.end();
+    while (++work < end) {
+        if (*work == cachedColor)
+            return work - colorTracker.begin();
+    }
+    int result = colorTracker.size();
+    colorTracker.grow(result + 1);
+    CachedColor& newColor = colorTracker.last();
+    newColor = cachedColor;
+    return result;
+}
+
+static void InitColor(CachedColor* color)
+{
+    color->setFillColor(RenderStyle::initialRingFillColor());
+    color->setInnerWidth(RenderStyle::initialRingInnerWidth());
+    color->setOuterWidth(RenderStyle::initialRingOuterWidth());
+    color->setOutset(RenderStyle::initialRingOutset());
+    color->setPressedInnerColor(RenderStyle::initialRingPressedInnerColor());
+    color->setPressedOuterColor(RenderStyle::initialRingPressedOuterColor());
+    color->setRadius(RenderStyle::initialRingRadius());
+    color->setSelectedInnerColor(RenderStyle::initialRingSelectedInnerColor());
+    color->setSelectedOuterColor(RenderStyle::initialRingSelectedOuterColor());
+}
+
+// when new focus is found, push it's parent on a stack
+    // as long as more focii are found with the same (grand) parent, note it
+    // (which only requires retrieving the last parent on the stack)
+// when the parent's last child is found, pop the stack
+// different from Tracker in that Tracker only pushes focii with children
+
+// making this work with focus - child focus - grandchild focus is tricky
+// if I keep the generation number, I may be able to more quickly determine that
+// a node is a grandchild of the focus's parent
+// this additionally requires being able to find the grandchild's parent
+
+// keep nodes that are focusable
+void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
+    CachedRoot* cachedRoot, CachedFrame* cachedFrame)
+{
+    WTF::Vector<FocusTracker> tracker(1); // sentinel
+    {
+        FocusTracker* baseTracker = tracker.data();
+        bzero(baseTracker, sizeof(FocusTracker));
+        baseTracker->mCachedNodeIndex = -1;
+    }
+    WTF::Vector<LayerTracker> layerTracker(1); // sentinel
+    bzero(layerTracker.data(), sizeof(LayerTracker));
+    WTF::Vector<ClipColumnTracker> clipTracker(1); // sentinel
+    bzero(clipTracker.data(), sizeof(ClipColumnTracker));
+    WTF::Vector<TabIndexTracker> tabIndexTracker(1); // sentinel
+    bzero(tabIndexTracker.data(), sizeof(TabIndexTracker));
+    WTF::Vector<CachedColor> colorTracker(1);
+    InitColor(colorTracker.data());
+#if DUMP_NAV_CACHE
+    char* frameNamePtr = cachedFrame->mDebug.mFrameName;
+    Builder(frame)->mDebug.frameName(frameNamePtr, frameNamePtr + 
+        sizeof(cachedFrame->mDebug.mFrameName) - 1);
+    *frameNamePtr = '\0';
+    int nodeIndex = 1;
+#endif
+    NodeWalk walk;
+    Document* doc = frame->document();
+    Node* parent = doc;
+    CachedNode cachedParentNode;
+    cachedParentNode.init(parent);
+#if DUMP_NAV_CACHE
+    cachedParentNode.mDebug.mNodeIndex = nodeIndex;
+#endif
+    cachedFrame->add(colorTracker[0]);
+    cachedFrame->add(cachedParentNode);
+    Node* node = parent;
+    int cacheIndex = 1;
+    int colorIndex = 0; // assume no special css ring colors
+    const void* lastStyleDataPtr = 0;
+    int textInputIndex = 0;
+    Node* focused = doc->focusedNode();
+    if (focused)
+        cachedRoot->setFocusBounds(focused->getRect());
+    int globalOffsetX, globalOffsetY;
+    GetGlobalOffset(frame, &globalOffsetX, &globalOffsetY);
+#if USE(ACCELERATED_COMPOSITING)
+    // The frame itself might be composited so we need to track the layer.  Do
+    // not track the base frame's layer as the main content is draw as part of
+    // BaseLayerAndroid's picture.
+    if (frame != root && frame->contentRenderer()
+        && frame->contentRenderer()->usesCompositing() && node->lastChild())
+        TrackLayer(layerTracker, frame->contentRenderer(), node->lastChild(),
+            globalOffsetX, globalOffsetY);
+#endif
+    while (walk.mMore || (node = node->traverseNextNode()) != NULL) {
+#if DUMP_NAV_CACHE
+        nodeIndex++;
+#endif
+        FocusTracker* last = &tracker.last();
+        int lastChildIndex = cachedFrame->size() - 1;
+        while (node == last->mLastChild) {
+            if (CleanUpContainedNodes(cachedRoot, cachedFrame, last, lastChildIndex))
+                cacheIndex--;
+            tracker.removeLast();
+            lastChildIndex = last->mCachedNodeIndex;
+            last = &tracker.last();
+        }
+        do {
+            const ClipColumnTracker* lastClip = &clipTracker.last();
+            if (node != lastClip->mLastChild)
+                break;
+            clipTracker.removeLast();
+        } while (true);
+        do {
+            const LayerTracker* lastLayer = &layerTracker.last();
+            if (node != lastLayer->mLastChild)
+                break;
+            layerTracker.removeLast();
+        } while (true);
+        do {
+            const TabIndexTracker* lastTabIndex = &tabIndexTracker.last();
+            if (node != lastTabIndex->mLastChild)
+                break;
+            tabIndexTracker.removeLast();
+        } while (true);
+        Frame* child = HasFrame(node);
+        CachedNode cachedNode;
+        if (child != NULL) {
+            if (child->document() == NULL)
+                continue;
+            RenderObject* nodeRenderer = node->renderer();
+            if (nodeRenderer != NULL && nodeRenderer->style()->visibility() == HIDDEN)
+                continue;
+            CachedFrame cachedChild;
+            cachedChild.init(cachedRoot, cacheIndex, child);
+            int childFrameIndex = cachedFrame->childCount();
+            cachedFrame->addFrame(cachedChild);
+            cachedNode.init(node);
+            cachedNode.setIndex(cacheIndex++);
+            cachedNode.setDataIndex(childFrameIndex);
+            cachedNode.setType(FRAME_CACHEDNODETYPE);
+#if DUMP_NAV_CACHE
+            cachedNode.mDebug.mNodeIndex = nodeIndex;
+            cachedNode.mDebug.mParentGroupIndex = Debug::ParentIndex(
+                node, nodeIndex, NULL);
+#endif
+            cachedFrame->add(cachedNode);
+            CachedFrame* childPtr = cachedFrame->lastChild();
+            BuildFrame(root, child, cachedRoot, childPtr);
+            continue;
+        }
+        int tabIndex = node->tabIndex();
+        Node* lastChild = node->lastChild();
+        if (tabIndex <= 0)
+            tabIndex = tabIndexTracker.last().mTabIndex;
+        else if (tabIndex > 0 && lastChild) {
+            DBG_NAV_LOGD("tabIndex=%d node=%p", tabIndex, node);
+            tabIndexTracker.grow(tabIndexTracker.size() + 1);
+            TabIndexTracker& indexTracker = tabIndexTracker.last();
+            indexTracker.mTabIndex = tabIndex;
+            indexTracker.mLastChild = OneAfter(lastChild);
+        }
+        RenderObject* nodeRenderer = node->renderer();
+        bool isTransparent = false;
+        bool hasCursorRing = true;
+        if (nodeRenderer != NULL) {
+            RenderStyle* style = nodeRenderer->style();
+            if (style->visibility() == HIDDEN)
+                continue;
+            isTransparent = nodeRenderer->hasBackground() == false;
+#ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
+            hasCursorRing = style->tapHighlightColor().alpha() > 0;
+#endif
+#if USE(ACCELERATED_COMPOSITING)
+            // If this renderer has its own layer and the layer is composited,
+            // start tracking it.
+            if (lastChild && nodeRenderer->hasLayer() && toRenderBoxModelObject(nodeRenderer)->layer()->backing())
+                TrackLayer(layerTracker, nodeRenderer, lastChild, globalOffsetX, globalOffsetY);
+#endif
+        }
+        bool more = walk.mMore;
+        walk.reset();
+     //   GetGlobalBounds(node, &bounds, false);
+        bool computeCursorRings = false;
+        bool hasClip = false;
+        bool hasMouseOver = false;
+        bool isUnclipped = false;
+        bool isFocus = node == focused;
+        bool takesFocus = false;
+        int columnGap = 0;
+        int imageCount = 0;
+        TextDirection direction = LTR;
+        String exported;
+        CachedNodeType type = NORMAL_CACHEDNODETYPE;
+        CachedColor cachedColor;
+        CachedInput cachedInput;
+        IntRect bounds;
+        IntRect absBounds;
+        IntRect originalAbsBounds;
+        ColumnInfo* columnInfo = 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
+             // assume areamaps are always visible for now
+            takesFocus = true;
+            goto keepNode;
+        }
+        if (nodeRenderer == NULL)
+            continue;
+
+        // some common setup
+        absBounds = nodeRenderer->absoluteBoundingBoxRect();
+        originalAbsBounds = absBounds;
+        absBounds.move(globalOffsetX, globalOffsetY);
+        hasClip = nodeRenderer->hasOverflowClip();
+
+        if (checkForPluginViewThatWantsFocus(nodeRenderer)) {
+            bounds = absBounds;
+            isUnclipped = true;
+            takesFocus = true;
+            type = PLUGIN_CACHEDNODETYPE;
+            goto keepNode;
+        }
+        // Only use the root contentEditable element
+        if (node->rendererIsEditable() && !node->parentOrHostNode()->rendererIsEditable()) {
+            bounds = absBounds;
+            takesFocus = true;
+            type = CONTENT_EDITABLE_CACHEDNODETYPE;
+            goto keepNode;
+        }
+        if (nodeRenderer->isRenderBlock()) {
+            RenderBlock* renderBlock = (RenderBlock*) nodeRenderer;
+            if (renderBlock->hasColumns()) {
+                columnInfo = renderBlock->columnInfo();
+                columnGap = renderBlock->columnGap();
+                direction = renderBlock->style()->direction();
+            }
+        }
+        if ((hasClip != false || columnInfo != NULL) && lastChild) {
+            clipTracker.grow(clipTracker.size() + 1);
+            ClipColumnTracker& clip = clipTracker.last();
+            clip.mBounds = absBounds;
+            clip.mLastChild = OneAfter(lastChild);
+            clip.mNode = node;
+            clip.mColumnInfo = columnInfo;
+            clip.mColumnGap = columnGap;
+            clip.mHasClip = hasClip;
+            clip.mDirection = direction;
+            if (columnInfo != NULL) {
+                const IntRect& oRect = ((RenderBox*)nodeRenderer)->visualOverflowRect();
+                clip.mBounds.move(oRect.x(), oRect.y());
+            }
+        }
+        if (node->isTextNode() && mAllowableTypes != NORMAL_CACHEDNODE_BITS) {
+            if (last->mSomeParentTakesFocus) // don't look at text inside focusable node
+                continue;
+            CachedNodeType checkType;
+            if (isFocusableText(&walk, more, node, &checkType, 
+                    &exported) == false)
+                continue;
+        #if DUMP_NAV_CACHE
+            { 
+                char buffer[DEBUG_BUFFER_SIZE];
+                mDebug.init(buffer, sizeof(buffer));
+                mDebug.print("text link found: ");
+                mDebug.wideString(exported);
+                DUMP_NAV_LOGD("%s\n", buffer);
+            }
+        #endif
+            type = checkType;
+            // !!! test ! is the following line correctly needed for frames to work?
+            cachedNode.init(node);
+            const ClipColumnTracker& clipTrack = clipTracker.last();
+            const IntRect& clip = clipTrack.mHasClip ? clipTrack.mBounds :
+                IntRect(0, 0, INT_MAX, INT_MAX);
+            if (ConstructTextRects((WebCore::Text*) node, walk.mStart, 
+                    (WebCore::Text*) walk.mFinalNode, walk.mEnd, globalOffsetX,
+                    globalOffsetY, &bounds, clip, &cachedNode.mCursorRing) == false)
+                continue;
+            absBounds = bounds;
+            cachedNode.setBounds(bounds);
+            if (bounds.width() < MINIMUM_FOCUSABLE_WIDTH)
+                continue;
+            if (bounds.height() < MINIMUM_FOCUSABLE_HEIGHT)
+                continue;
+            computeCursorRings = true;
+            isUnclipped = true;  // FIXME: to hide or partially occlude synthesized links, each
+                                 // focus ring will also need the offset and length of characters
+                                 // used to produce it
+            goto keepTextNode;
+        }
+        if (node->hasTagName(WebCore::HTMLNames::inputTag)) {
+            HTMLInputElement* input = static_cast<HTMLInputElement*>(node);
+            if (input->isTextField()) {
+                if (input->readOnly())
+                    continue;
+                type = TEXT_INPUT_CACHEDNODETYPE;
+                cachedInput.init();
+                cachedInput.setAutoComplete(input->autoComplete());
+                cachedInput.setSpellcheck(input->spellcheck());
+                cachedInput.setFormPointer(input->form());
+                cachedInput.setIsTextField(true);
+                exported = input->value().threadsafeCopy();
+                cachedInput.setMaxLength(input->maxLength());
+                cachedInput.setTypeFromElement(input);
+    // If this does not need to be threadsafe, we can use crossThreadString().
+    // See http://trac.webkit.org/changeset/49160.
+                cachedInput.setName(input->name().string().threadsafeCopy());
+    // can't detect if this is drawn on top (example: deviant.com login parts)
+                isUnclipped = isTransparent;
+            } else if (input->isInputTypeHidden())
+                continue;
+            else if (input->isRadioButton() || input->isCheckbox())
+                isTransparent = false;
+        } else if (node->hasTagName(HTMLNames::textareaTag)) {
+            HTMLTextAreaElement* area = static_cast<HTMLTextAreaElement*>(node);
+            if (area->readOnly())
+                continue;
+            cachedInput.init();
+            type = TEXT_INPUT_CACHEDNODETYPE;
+            cachedInput.setFormPointer(area->form());
+            cachedInput.setIsTextArea(true);
+            cachedInput.setSpellcheck(area->spellcheck());
+            exported = area->value().threadsafeCopy();
+        } else if (node->hasTagName(HTMLNames::aTag)) {
+            const HTMLAnchorElement* anchorNode = 
+                (const HTMLAnchorElement*) node;
+            if (!anchorNode->isFocusable() && !HasTriggerEvent(node))
+                continue;
+            if (node->disabled())
+                continue;
+            hasMouseOver = NodeHasEventListeners(node, &eventNames().mouseoverEvent, 1);
+            type = ANCHOR_CACHEDNODETYPE;
+            KURL href = anchorNode->href();
+            if (!href.isEmpty() && !WebCore::protocolIsJavaScript(href.string()))
+                // Set the exported string for all non-javascript anchors.
+                exported = href.string().threadsafeCopy();
+        } else if (node->hasTagName(HTMLNames::selectTag)) {
+            type = SELECT_CACHEDNODETYPE;
+        }
+        if (type == TEXT_INPUT_CACHEDNODETYPE) {
+            RenderTextControl* renderText = 
+                static_cast<RenderTextControl*>(nodeRenderer);
+            if (isFocus)
+                cachedRoot->setSelection(renderText->selectionStart(), renderText->selectionEnd());
+            // FIXME: Are we sure there will always be a style and font, and it's correct?
+            RenderStyle* style = nodeRenderer->style();
+            if (style) {
+                isUnclipped |= !style->hasAppearance();
+                int lineHeight = -1;
+                Length lineHeightLength = style->lineHeight();
+                // If the lineHeight is negative, WebTextView will calculate it
+                // based on the text size, using the Paint.
+                // See RenderStyle.computedLineHeight.
+                if (lineHeightLength.isPositive())
+                    lineHeight = style->computedLineHeight();
+                cachedInput.setLineHeight(lineHeight);
+                cachedInput.setTextSize(style->font().size());
+                cachedInput.setIsRtlText(style->direction() == RTL
+                        || style->textAlign() == WebCore::RIGHT
+                        || style->textAlign() == WebCore::WEBKIT_RIGHT);
+            }
+            cachedInput.setPaddingLeft(renderText->paddingLeft() + renderText->borderLeft());
+            cachedInput.setPaddingTop(renderText->paddingTop() + renderText->borderTop());
+            cachedInput.setPaddingRight(renderText->paddingRight() + renderText->borderRight());
+            cachedInput.setPaddingBottom(renderText->paddingBottom() + renderText->borderBottom());
+        }
+        takesFocus = true;
+        bounds = absBounds;
+        if (type != ANCHOR_CACHEDNODETYPE) {
+            bool isFocusable = node->isKeyboardFocusable(NULL) || 
+                node->isMouseFocusable() || node->isFocusable();
+            if (isFocusable == false) {
+                if (node->disabled())
+                    continue;
+                bool overOrOut = HasOverOrOut(node);
+                bool hasTrigger = HasTriggerEvent(node);
+                if (overOrOut == false && hasTrigger == false)
+                    continue;
+                takesFocus = hasTrigger;
+            }
+        }
+        computeCursorRings = true;
+    keepNode:
+        cachedNode.init(node);
+        if (computeCursorRings == false) {
+            cachedNode.setBounds(bounds);
+            cachedNode.mCursorRing.append(bounds);
+        } else if (ConstructPartRects(node, bounds, &cachedNode.mBounds,
+                globalOffsetX, globalOffsetY, &cachedNode.mCursorRing,
+                &imageCount) == false)
+            continue;
+    keepTextNode:
+        if (nodeRenderer) { // area tags' node->renderer() == 0
+            RenderStyle* style = nodeRenderer->style();
+            const void* styleDataPtr = style->ringData();
+            // to save time, see if we're pointing to the same style data as before
+            if (lastStyleDataPtr != styleDataPtr) {
+                lastStyleDataPtr = styleDataPtr;
+                cachedColor.setFillColor(style->ringFillColor());
+                cachedColor.setInnerWidth(style->ringInnerWidth());
+                cachedColor.setOuterWidth(style->ringOuterWidth());
+                cachedColor.setOutset(style->ringOutset());
+                cachedColor.setPressedInnerColor(style->ringPressedInnerColor());
+                cachedColor.setPressedOuterColor(style->ringPressedOuterColor());
+                cachedColor.setRadius(style->ringRadius());
+                cachedColor.setSelectedInnerColor(style->ringSelectedInnerColor());
+                cachedColor.setSelectedOuterColor(style->ringSelectedOuterColor());
+                int oldSize = colorTracker.size();
+                colorIndex = FindColorIndex(colorTracker, cachedColor);
+                if (colorIndex == oldSize)
+                    cachedFrame->add(cachedColor);
+            }
+        } else
+            colorIndex = 0;
+        IntRect clip = hasClip ? bounds : absBounds;
+        size_t clipIndex = clipTracker.size();
+        if (clipTracker.last().mNode == node)
+            clipIndex -= 1;
+        while (--clipIndex > 0) {
+            const ClipColumnTracker& clipTrack = clipTracker.at(clipIndex);
+            if (clipTrack.mHasClip == false) {
+                adjustForColumns(clipTrack, &cachedNode, &absBounds, static_cast<RenderBlock*>(nodeRenderer));
+                continue;
+            }
+            const IntRect& parentClip = clipTrack.mBounds;
+            if (hasClip == false && type == ANCHOR_CACHEDNODETYPE)
+                clip = parentClip;
+            else
+                clip.intersect(parentClip);
+            hasClip = true;
+        }
+        bool isInLayer = false;
+#if USE(ACCELERATED_COMPOSITING)
+        // If this renderer has a composited parent layer (including itself),
+        // add the node to the cached layer.
+        // FIXME: does not work for area rects
+        RenderLayer* enclosingLayer = nodeRenderer->enclosingLayer();
+        if (enclosingLayer && enclosingLayer->enclosingCompositingLayer()) {
+            LayerAndroid* layer = layerTracker.last().mLayer;
+            if (layer) {
+                const IntRect& layerClip = layerTracker.last().mBounds;
+                if (!layerClip.isEmpty() && !cachedNode.clip(layerClip)) {
+                    DBG_NAV_LOGD("skipped on layer clip %d", cacheIndex);
+                    continue; // skip this node if outside of the clip
+                }
+                isInLayer = true;
+                isUnclipped = true; // assume that layers do not have occluded nodes
+                hasClip = false;
+                AddLayer(cachedFrame, cachedFrame->size(), layerClip.location(),
+                         layer->uniqueId());
+            }
+        }
+#endif
+        if (hasClip) {
+            if (clip.isEmpty())
+                continue; // skip this node if clip prevents all drawing
+            else if (cachedNode.clip(clip) == false)
+                continue; // skip this node if outside of the clip
+        }
+        cachedNode.setColorIndex(colorIndex);
+        cachedNode.setExport(exported);
+        cachedNode.setHasCursorRing(hasCursorRing);
+        cachedNode.setHasMouseOver(hasMouseOver);
+        cachedNode.setHitBounds(absBounds);
+        cachedNode.setIndex(cacheIndex);
+        cachedNode.setIsFocus(isFocus);
+        cachedNode.setIsInLayer(isInLayer);
+        cachedNode.setIsTransparent(isTransparent);
+        cachedNode.setIsUnclipped(isUnclipped);
+        cachedNode.setOriginalAbsoluteBounds(originalAbsBounds);
+        cachedNode.setParentIndex(last->mCachedNodeIndex);
+        cachedNode.setParentGroup(ParentWithChildren(node));
+        cachedNode.setSingleImage(imageCount == 1);
+        cachedNode.setTabIndex(tabIndex);
+        cachedNode.setType(type);
+        if (type == TEXT_INPUT_CACHEDNODETYPE) {
+            cachedFrame->add(cachedInput);
+            cachedNode.setDataIndex(textInputIndex);
+            textInputIndex++;
+        } else
+            cachedNode.setDataIndex(-1);
+#if DUMP_NAV_CACHE
+        cachedNode.mDebug.mNodeIndex = nodeIndex;
+        cachedNode.mDebug.mParentGroupIndex = Debug::ParentIndex(
+            node, nodeIndex, (Node*) cachedNode.parentGroup());
+#endif
+        cachedFrame->add(cachedNode);
+        {
+            int lastIndex = cachedFrame->size() - 1;
+            if (node == focused) {
+                CachedNode* cachedNodePtr = cachedFrame->getIndex(lastIndex);
+                cachedRoot->setCachedFocus(cachedFrame, cachedNodePtr);
+            }
+            if (lastChild != NULL) {
+                tracker.grow(tracker.size() + 1);
+                FocusTracker& working = tracker.last();
+                working.mCachedNodeIndex = lastIndex;
+                working.mLastChild = OneAfter(lastChild);
+                last = &tracker.at(tracker.size() - 2);
+                working.mSomeParentTakesFocus = last->mSomeParentTakesFocus | takesFocus;
+            } 
+        }
+        cacheIndex++;
+    }
+    while (tracker.size() > 1) {
+        FocusTracker* last = &tracker.last();
+        int lastChildIndex = cachedFrame->size() - 1;
+        if (CleanUpContainedNodes(cachedRoot, cachedFrame, last, lastChildIndex))
+            cacheIndex--;
+        tracker.removeLast();
+    }
+}
+
+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
+    // or if inner is keyboard focusable, disable outer
+    // else disable inner by removing it
+    int childCount = lastChildIndex - last->mCachedNodeIndex;
+    if (childCount == 0)
+        return false;
+    CachedNode* lastCached = cachedFrame->getIndex(last->mCachedNodeIndex);
+    Node* lastNode = (Node*) lastCached->nodePointer();
+    if ((childCount > 1 && lastNode->hasTagName(HTMLNames::selectTag) == false) ||
+            lastNode->hasTagName(HTMLNames::bodyTag) ||
+            lastNode->hasTagName(HTMLNames::formTag)) {
+        lastCached->setBounds(IntRect(0, 0, 0, 0));
+        lastCached->mCursorRing.clear();
+        return false;
+    }
+    CachedNode* onlyChildCached = cachedFrame->lastNode();
+    Node* onlyChild = (Node*) onlyChildCached->nodePointer();
+    bool outerIsMouseMoveOnly = 
+        lastNode->isKeyboardFocusable(NULL) == false && 
+        lastNode->isMouseFocusable() == false &&
+        lastNode->isFocusable() == false &&
+        HasOverOrOut(lastNode) == true && 
+        HasTriggerEvent(lastNode) == false;
+    if (onlyChildCached->parent() == lastCached)
+        onlyChildCached->setParentIndex(lastCached->parentIndex());
+    bool hasFocus = lastCached->isFocus() || onlyChildCached->isFocus();
+    if (outerIsMouseMoveOnly || onlyChild->isKeyboardFocusable(NULL)
+            || onlyChildCached->isPlugin()) {
+        int index = lastCached->index();
+        *lastCached = *onlyChildCached;
+        lastCached->setIndex(index);
+        CachedFrame* frame = cachedFrame->hasFrame(lastCached);
+        if (frame)
+            frame->setIndexInParent(index);
+    }
+    cachedFrame->removeLast();
+    if (hasFocus)
+        cachedRoot->setCachedFocus(cachedFrame, cachedFrame->lastNode());
+    return true;
+}
+
+Node* CacheBuilder::currentFocus() const
+{
+    Frame* frame = FrameAnd(this);
+    Document* doc = frame->document();
+    if (doc != NULL) {
+        Node* focus = doc->focusedNode();
+        if (focus != NULL)
+            return focus;
+    }
+    Frame* child = frame->tree()->firstChild();
+    while (child) {
+        CacheBuilder* cacheBuilder = Builder(child);
+        Node* focus = cacheBuilder->currentFocus();
+        if (focus)
+            return focus;
+        child = child->tree()->nextSibling();
+    }
+    return NULL;
+}
+
+static bool strCharCmp(const char* matches, const UChar* test, int wordLength, 
+    int wordCount)
+{
+    for (int index = 0; index < wordCount; index++) {
+        for (int inner = 0; inner < wordLength; inner++) {
+            if (matches[inner] != test[inner]) {
+                matches += wordLength;
+                goto next;
+            }
+        }
+        return true;
+next:
+        ;
+    }
+    return false;
+}
+
+static const int stateTwoLetter[] = {
+    0x02060c00,  // A followed by: [KLRSZ]
+    0x00000000,  // B
+    0x00084001,  // C followed by: [AOT]
+    0x00000014,  // D followed by: [CE]
+    0x00000000,  // E
+    0x00001800,  // F followed by: [LM]
+    0x00100001,  // G followed by: [AU]
+    0x00000100,  // H followed by: [I]
+    0x00002809,  // I followed by: [ADLN]
+    0x00000000,  // J
+    0x01040000,  // K followed by: [SY]
+    0x00000001,  // L followed by: [A]
+    0x000ce199,  // M followed by: [ADEHINOPST]
+    0x0120129c,  // N followed by: [CDEHJMVY]
+    0x00020480,  // O followed by: [HKR]
+    0x00420001,  // P followed by: [ARW]
+    0x00000000,  // Q
+    0x00000100,  // R followed by: [I]
+    0x0000000c,  // S followed by: [CD]
+    0x00802000,  // T followed by: [NX]
+    0x00080000,  // U followed by: [T]
+    0x00080101,  // V followed by: [AIT]
+    0x01200101   // W followed by: [AIVY]
+};
+
+static const char firstIndex[] = {
+     0,  5,  5,  8, 10, 10, 12, 14, 
+    15, 19, 19, 21, 22, 32, 40, 43, 
+    46, 46, 47, 49, 51, 52, 55, 59  
+};
+
+// from http://infolab.stanford.edu/~manku/bitcount/bitcount.html
+#define TWO(c)     (0x1u << (c))
+#define MASK(c)    (((unsigned int)(-1)) / (TWO(TWO(c)) + 1u))
+#define COUNT(x,c) ((x) & MASK(c)) + (((x) >> (TWO(c))) & MASK(c))
+ 
+int bitcount (unsigned int n)
+{
+    n = COUNT(n, 0);
+    n = COUNT(n, 1);
+    n = COUNT(n, 2);
+    n = COUNT(n, 3);
+    return COUNT(n, 4);
+}
+
+#undef TWO
+#undef MASK
+#undef COUNT
+
+static bool isUnicodeSpace(UChar ch)
+{
+    return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' || ch == 0xa0;
+}
+
+static bool validZip(int stateIndex, const UChar* zipPtr) 
+{
+    static const struct {
+        char mLow;
+        char mHigh;
+        char mException1;
+        char mException2;
+    } zipRange[] = { 
+        { 99, 99, -1, -1 }, // AK Alaska
+        { 35, 36, -1, -1 }, // AL Alabama
+        { 71, 72, -1, -1 }, // AR Arkansas
+        { 96, 96, -1, -1 }, // AS American Samoa
+        { 85, 86, -1, -1 }, // AZ Arizona
+        { 90, 96, -1, -1 }, // CA California
+        { 80, 81, -1, -1 }, // CO Colorado
+        {  6,  6, -1, -1 }, // CT Connecticut
+        { 20, 20, -1, -1 }, // DC District of Columbia
+        { 19, 19, -1, -1 }, // DE Delaware
+        { 32, 34, -1, -1 }, // FL Florida
+        { 96, 96, -1, -1 }, // FM Federated States of Micronesia
+        { 30, 31, -1, -1 }, // GA Georgia
+        { 96, 96, -1, -1 }, // GU Guam
+        { 96, 96, -1, -1 }, // HI Hawaii
+        { 50, 52, -1, -1 }, // IA Iowa
+        { 83, 83, -1, -1 }, // ID Idaho
+        { 60, 62, -1, -1 }, // IL Illinois
+        { 46, 47, -1, -1 }, // IN Indiana
+        { 66, 67, 73, -1 }, // KS Kansas
+        { 40, 42, -1, -1 }, // KY Kentucky
+        { 70, 71, -1, -1 }, // LA Louisiana
+        {  1,  2, -1, -1 }, // MA Massachusetts
+        { 20, 21, -1, -1 }, // MD Maryland
+        {  3,  4, -1, -1 }, // ME Maine
+        { 96, 96, -1, -1 }, // MH Marshall Islands
+        { 48, 49, -1, -1 }, // MI Michigan
+        { 55, 56, -1, -1 }, // MN Minnesota
+        { 63, 65, -1, -1 }, // MO Missouri
+        { 96, 96, -1, -1 }, // MP Northern Mariana Islands
+        { 38, 39, -1, -1 }, // MS Mississippi
+        { 55, 56, -1, -1 }, // MT Montana
+        { 27, 28, -1, -1 }, // NC North Carolina
+        { 58, 58, -1, -1 }, // ND North Dakota
+        { 68, 69, -1, -1 }, // NE Nebraska
+        {  3,  4, -1, -1 }, // NH New Hampshire
+        {  7,  8, -1, -1 }, // NJ New Jersey
+        { 87, 88, 86, -1 }, // NM New Mexico
+        { 88, 89, 96, -1 }, // NV Nevada
+        { 10, 14,  0,  6 }, // NY New York
+        { 43, 45, -1, -1 }, // OH Ohio
+        { 73, 74, -1, -1 }, // OK Oklahoma
+        { 97, 97, -1, -1 }, // OR Oregon
+        { 15, 19, -1, -1 }, // PA Pennsylvania
+        {  6,  6,  0,  9 }, // PR Puerto Rico
+        { 96, 96, -1, -1 }, // PW Palau
+        {  2,  2, -1, -1 }, // RI Rhode Island
+        { 29, 29, -1, -1 }, // SC South Carolina
+        { 57, 57, -1, -1 }, // SD South Dakota
+        { 37, 38, -1, -1 }, // TN Tennessee
+        { 75, 79, 87, 88 }, // TX Texas
+        { 84, 84, -1, -1 }, // UT Utah
+        { 22, 24, 20, -1 }, // VA Virginia
+        {  6,  9, -1, -1 }, // VI Virgin Islands
+        {  5,  5, -1, -1 }, // VT Vermont
+        { 98, 99, -1, -1 }, // WA Washington
+        { 53, 54, -1, -1 }, // WI Wisconsin
+        { 24, 26, -1, -1 }, // WV West Virginia
+        { 82, 83, -1, -1 }  // WY Wyoming
+    };
+
+    int zip = zipPtr[0] - '0';
+    zip *= 10;
+    zip += zipPtr[1] - '0';
+    int low = zipRange[stateIndex].mLow;
+    int high = zipRange[stateIndex].mHigh;
+    if (zip >= low && zip <= high)
+        return true;
+    if (zip == zipRange[stateIndex].mException1)
+        return true;
+    if (zip == zipRange[stateIndex].mException2)
+        return true;
+    return false;
+}
+
+#define MAX_PLACE_NAME_LENGTH 25 // the longest allowable one word place name
+
+CacheBuilder::FoundState CacheBuilder::FindAddress(const UChar* chars,
+    unsigned length, int* start, int* end, bool caseInsensitive)
+{
+    FindState addressState;
+    FindReset(&addressState);
+    addressState.mWords[0] = addressState.mStarts[0] = chars;
+    addressState.mCaseInsensitive = caseInsensitive;
+    FoundState state = FindPartialAddress(chars, chars, length, &addressState);
+    if (state == FOUND_PARTIAL && addressState.mProgress == ZIP_CODE &&
+            addressState.mNumberCount == 0) {
+        addressState.mProgress = FIND_STREET;
+        state = FindPartialAddress(NULL, NULL, 0, &addressState);
+    }
+    *start = addressState.mStartResult;
+    *end = addressState.mEndResult;
+    return state;
+}
+
+CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars,
+    const UChar* chars, unsigned length, FindState* s)
+{
+    // lower case letters are optional; trailing asterisk is optional 's'
+    static char const* const longStreetNames[] = {
+        "\x04" "LleY" "\x04" "NneX" "\x05" "RCade" "\x05" "VEnue" "\x06" "LAMEDA", // A
+        "\x04" "aYoU" "\x04" "eaCH" "\x03" "eND" "\x05" "LuFf*" "\x05" "oTtoM"
+            "\x08" "ouLeVarD" "\x05" "Ranch" "\x05" "RidGe" "\x05" "RooK*"
+            "\x04" "urG*" "\x05" "YPass" "\x07" "roadWAY", // B
+        "\x05" "AMINO"
+        "\x03" "amP" "\x05" "anYoN" "\x03" "aPE" "\x07" "auSeWaY" "\x06" "enTeR*"
+            "\x06" "IRcle*" "\x05" "LiFf*" "\x03" "LuB" "\x05" "oMmoN" "\x06" "ORner*"
+            "\x05" "ouRSE" "\x05" "ourT*" "\x04" "oVe*" "\x04" "ReeK" "\x07" "REScent"
+            "\x04" "ReST" "\x07" "ROSSING" "\x08" "ROSSROAD" "\x04" "URVe"
+            "\x05" "AMINO" "\x06" "IRCULO" "\x07" "REScent", // C
+        "\x03" "aLe" "\x02" "aM" "\x05" "iVide" "\x05" "Rive*", // D
+        "\x06" "STate*" "\x09" "XPresswaY" "\x09" "XTension*", // E
+        "\x04" "ALL*" "\x04" "eRrY" "\x05" "ieLD*" "\x04" "LaT*" "\x04" "oRD*"
+            "\x05" "oReST" "\x05" "oRGe*" "\x04" "oRK*" "\x03" "orT" "\x06" "reeWaY", // F
+        "\x06" "arDeN*" "\x06" "aTeWaY" "\x04" "LeN*" "\x05" "ReeN*" "\x05" "RoVe*", // G
+        "\x06" "arBoR*" "\x04" "aVeN" "\x06" "eighTS" "\x06" "ighWaY" "\x04" "iLl*"
+            "\x05" "OLloW", // H
+        "\x04" "NLeT" "\x06" "Sland*" "\x03" "SLE", // I
+        "\x08" "unCTion*", // J
+        "\x03" "eY*" "\x05" "NoLl*", // K
+        "\x04" "aKe*" "\x03" "AND" "\x06" "aNDinG" "\x03" "aNe" "\x05" "iGhT*"
+            "\x03" "oaF" "\x04" "oCK*" "\x04" "oDGe" "\x03" "OOP", // L
+        "\x03" "ALL" "\x05" "aNoR*" "\x06" "eaDoW*" "\x03" "EWS" "\x04" "iLl*"
+            "\x06" "iSsioN" "\x07" "oTorWaY" "\x04" "ounT" "\x08" "ounTaiN*", // M
+        "\x03" "eCK", // N
+        "\x06" "RCHard" "\x03" "VAL" "\x07" "verPASs", // O
+        "\x04" "ARK*" "\x07" "arKWaY*" "\x03" "ASS" "\x06" "aSsaGE" "\x03" "ATH"
+            "\x03" "IKE" "\x04" "iNE*" "\x04" "Lace" "\x05" "LaiN*" "\x04" "LaZa"
+            "\x05" "oinT*" "\x04" "oRT*" "\x06" "Rairie" "\x06" "RIVADA", // P
+        NULL,
+        "\x05" "ADiaL" "\x03" "AMP" "\x04" "aNCH" "\x05" "aPiD*"
+            "\x03" "eST"
+            "\x05" "iDGe*" "\x04" "IVer" "\x04" "oaD*" "\x04" "ouTE" "\x02" "OW"
+            "\x02" "UE" "\x02" "UN", // R
+        "\x05" "HoaL*" "\x05" "HoRe*" "\x05" "KyWaY" "\x06" "PrinG*" "\x04" "PUR*"
+            "\x06" "Quare*" "\x06" "TAtion" "\x08" "TRAvenue" "\x05" "TReaM"
+            "\x06" "Treet*" "\x05" "uMmiT" "\x07" "PeeDWaY", // S
+        "\x06" "ERrace" "\x09" "hRoughWaY" "\x04" "RaCE" "\x04" "RAcK" "\x09" "RaFficwaY"
+            "\x04" "RaiL" "\x05" "UNneL" "\x07" "urnPiKE", // T
+        "\x08" "nderPASs" "\x05" "Nion*", // U
+        "\x06" "aLleY*" "\x06" "IAduct" "\x04" "ieW*" "\x07" "iLlaGe*" "\x04" "iLle"
+            "\x04" "ISta", // V
+        "\x04" "ALK*" "\x03" "ALL" "\x03" "AY*" "\x04" "eLl*", // W
+        "\x03" "ING" "\x02" "RD", // X
+    };
+    
+    static char const* const longStateNames[] = {
+        "\x8e" "la" "\x85" "bama" "\x02" "\x84" "ska" "\x01" "\x8f" "merican Samoa" "\x04"
+             "\x91" "r" "\x86" "izona" "\x05" "\x87" "kansas" "\x03",
+        NULL,
+        "\x8b" "alifornia" "\x06" "\x95" "o" "\x87" "lorado" "\x07" "\x8a" "nnecticut" "\x08",
+        "\x89" "elaware" "\x0a" "\x95" "istrict of Columbia" "\x09",
+        NULL,
+        "\x9f" "ederated States of Micronesia" "\x0c" "\x88" "lorida" "\x0b",
+        "\x85" "uam" "\x0e" "\x88" "eorgia" "\x0d",
+        "\x87" "awaii" "\x0f",
+        "\x86" "daho" "\x11" "\x89" "llinois" "\x12" "\x88" "ndiana" "\x13" "\x85"
+             "owa" "\x10",
+        NULL,
+        "\x87" "ansas" "\x14" "\x89" "entucky" "\x15",
+        "\x8a" "ouisiana" "\x16",
+        "\x86" "aine" "\x19" "\x99" "ar" "\x8e" "shall Islands" "\x1a" "\x86" "yland" "\x18"
+             "\x8e" "assachusetts" "\x17" "\x93" "i" "\x87" "chigan" "\x1b"
+             "\x88" "nnesota" "\x1c" "\x93" "iss" "\x88" "issippi" "\x1f" "\x85"
+             "ouri" "\x1d" "\x88" "ontana" "\x20",
+        "\x90" "e" "\x87" "braska" "\x23" "\x85" "vada" "\x27" "\xa5" "ew " "\x8a"
+             "Hampshire" "\x24" "\x87" "Jersey" "\x25" "\x87" "Mexico" "\x26"
+             "\x85" "York" "\x28" "\x98" "orth " "\x89" "Carolina" "\x21" "\x87"
+             "Dakota" "\x22" "\x99" "orthern Mariana Islands" "\x1e",
+        "\x85" "hio" "\x29" "\x89" "klahoma" "\x2a" "\x87" "regon" "\x2b",
+        "\x86" "alau" "\x2e" "\x8d" "ennsylvania" "\x2c" "\x8c" "uerto Rico" "\x2d",
+        NULL,
+        "\x8d" "hode Island" "\x2f",
+        "\x98" "outh " "\x89" "Carolina" "\x30" "\x87" "Dakota" "\x31",
+        "\x90" "e" "\x88" "nnessee" "\x32" "\x84" "xas" "\x33",
+        "\x85" "tah" "\x34",
+        "\x88" "ermont" "\x37" "\x94" "irgin" "\x89" " Islands" "\x36" "\x83" "ia" "\x35",
+        "\x8b" "ashington" "\x38" "\x8e" "est Virginia" "\x3a" "\x8a" "isconsin" "\x39"
+             "\x88" "yoming" "\x3b"
+    };
+     
+#if 0 // DEBUG_NAV_UI
+    static char const* const progressNames[] = {
+        "NO_ADDRESS",
+        "SKIP_TO_SPACE",
+        "HOUSE_NUMBER",
+        "NUMBER_TRAILING_SPACE",
+        "ADDRESS_LINE",
+        "STATE_NAME",
+        "SECOND_HALF",
+        "ZIP_CODE",
+        "PLUS_4",
+        "FIND_STREET"
+    };
+#endif
+    // strategy: US only support at first
+    // look for a 1 - 5 digit number for a street number (no support for 'One Microsoft Way')
+        // ignore if preceded by '#', Suite, Ste, Rm
+    // look for two or more words (up to 5? North Frank Lloyd Wright Blvd)
+            // note: "The Circle at North Hills St." has six words, and a lower 'at' -- allow at, by, of, in, the, and, ... ?
+        // if a word starts with a lowercase letter, no match
+        // allow: , . - # / (for 1/2) ' " 
+        // don't look for street name type yet
+    // look for one or two delimiters to represent possible 2nd addr line and city name
+    // look for either full state name, or state two letters, and/or zip code (5 or 9 digits)
+    // now look for street suffix, either in full or abbreviated form, with optional 's' if there's an asterisk 
+
+    s->mCurrentStart = chars;
+    s->mEnd = chars + length;
+    int candIndex = 0;
+    bool retryState;
+    bool mustBeAllUpper = false;
+    bool secondHalf = false;
+    chars -= 1;
+    UChar ch = s->mCurrent;
+    while (++chars <= s->mEnd) {
+        UChar prior = ch;
+        ch = chars < s->mEnd ? *chars : ' ';
+        switch (s->mProgress) {
+            case NO_ADDRESS:
+                if (WTF::isASCIIDigit(ch) == false) {
+                    if (ch != 'O') // letter 'O', not zero
+                        continue;
+                    if (s->mEnd - chars < 3)
+                        continue;
+                    prior = *++chars;
+                    ch = *++chars;
+                    if ((prior != 'n' || ch != 'e') && (prior != 'N' || ch != 'E'))
+                        continue;
+                    if (isUnicodeSpace(*++chars) == false)
+                        continue;
+                    s->mProgress = ADDRESS_LINE;
+                    s->mStartResult = chars - 3 - s->mCurrentStart;
+                    continue;
+                }
+                if (isUnicodeSpace(prior) == false) {
+                    s->mProgress = SKIP_TO_SPACE;
+                    continue;
+                }
+                s->mNumberCount = 1;
+                s->mProgress = HOUSE_NUMBER;
+                s->mStartResult = chars - s->mCurrentStart;
+                continue;
+            case SKIP_TO_SPACE:
+                if (isUnicodeSpace(ch) == false)
+                    continue;
+                break;
+            case HOUSE_NUMBER:
+                if (WTF::isASCIIDigit(ch)) {
+                    if (++s->mNumberCount >= 6)
+                        s->mProgress = SKIP_TO_SPACE;
+                    continue;
+                }
+                if (WTF::isASCIIUpper(ch)) { // allow one letter after house number, e.g. 12A SKOLFIELD PL, HARPSWELL, ME 04079
+                    if (WTF::isASCIIDigit(prior) == false)
+                        s->mProgress = SKIP_TO_SPACE;
+                    continue;
+                }
+                if (ch == '-') {
+                    if (s->mNumberCount > 0) { // permit 21-23 ELM ST
+                        ++s->mNumberCount;
+                        continue;
+                    }
+                }
+                s->mNumberCount = 0;
+                s->mProgress = NUMBER_TRAILING_SPACE;
+            case NUMBER_TRAILING_SPACE:
+                if (isUnicodeSpace(ch))
+                    continue;
+                if (0 && WTF::isASCIIDigit(ch)) {
+                    s->mNumberCount = 1;
+                    s->mProgress = HOUSE_NUMBER;
+                    s->mStartResult = chars - s->mCurrentStart;
+                    continue;
+                }
+                if (WTF::isASCIIDigit(ch) == false && WTF::isASCIIUpper(ch) == false)
+                    break;
+                s->mProgress = ADDRESS_LINE;
+            case ADDRESS_LINE:
+                if (WTF::isASCIIAlpha(ch) || ch == '\'' || ch == '-' || ch == '&' || ch == '(' || ch == ')') {
+                    if (++s->mLetterCount > 1) {
+                        s->mNumberWords &= ~(1 << s->mWordCount);
+                        continue;
+                    }
+                    if (s->mNumberCount >= 5)
+                        break;
+// FIXME: the test below was added to give up on a non-address, but it
+// incorrectly discards addresses where the house number is in one node
+// and the street name is in the next; I don't recall what the failing case
+// is that suggested this fix.
+//                    if (s->mWordCount == 0 && s->mContinuationNode)
+//                        return FOUND_NONE;
+                    s->newWord(baseChars, chars);
+                    if (WTF::isASCIILower(ch) && s->mNumberCount == 0)
+                        s->mFirstLower = chars;
+                    s->mNumberCount = 0;
+                    if (WTF::isASCIILower(ch) || (WTF::isASCIIAlpha(ch) == false && ch != '-'))
+                        s->mNumberWords &= ~(1 << s->mWordCount);
+                    s->mUnparsed = true;
+                    continue;
+                } else if (s->mLetterCount >= MAX_PLACE_NAME_LENGTH) {
+                    break;
+                } else if (s->mFirstLower != NULL) {
+                    if (s->mCaseInsensitive)
+                        goto resetWord;
+                    size_t length = chars - s->mFirstLower;
+                    if (length > 3)
+                        break;
+                    if (length == 3 && strCharCmp("and" "the", s->mFirstLower, 3, 2) == false)
+                        break;
+                    if (length == 2 && strCharCmp("at" "by" "el" "in" "of", s->mFirstLower, 2, 5) == false)
+                        break;
+                    goto resetWord;
+                }
+                if (ch == ',' || ch == '*') { // delimits lines
+                    // asterisk as delimiter: http://www.sa.sc.edu/wellness/members.html
+                    if (++s->mLineCount > 5)
+                        break;
+                    goto lookForState;
+                }
+                if (isUnicodeSpace(ch) || prior == '-') {
+            lookForState:
+                    if (s->mUnparsed == false)
+                        continue;
+                    const UChar* candidate = s->mWords[s->mWordCount];
+                    UChar firstLetter = candidate[0];
+                    if (WTF::isASCIIUpper(firstLetter) == false && WTF::isASCIIDigit(firstLetter) == false)
+                        goto resetWord;
+                    s->mWordCount++;
+                    if ((s->mWordCount == 2 && s->mNumberWords == 3 && WTF::isASCIIDigit(s->mWords[1][1])) || // choose second of 8888 333 Main
+                        (s->mWordCount >= sizeof(s->mWords) / sizeof(s->mWords[0]) - 1)) { // subtract 1 since state names may have two parts
+                        // search for simple number already stored since first potential house # didn't pan out 
+                        if (s->mNumberWords == 0)
+                            break;
+                        int shift = 0;
+                        while ((s->mNumberWords & (1 << shift)) == 0)
+                            shift++;
+                        s->mNumberWords >>= ++shift;
+                        if (s->mBases[0] != s->mBases[shift]) // if we're past the original node, bail
+                            break;
+                        s->shiftWords(shift);
+                        s->mStartResult = s->mWords[0] - s->mStarts[0];
+                        s->mWordCount -= shift;
+                        // FIXME: need to adjust lineCount to account for discarded delimiters
+                    }
+                    if (s->mWordCount < 4) 
+                        goto resetWord;
+                    firstLetter -= 'A';
+                    if (firstLetter > 'W' - 'A')
+                        goto resetWord;
+                    UChar secondLetter = candidate[1];
+                    if (prior == '-')
+                        s->mLetterCount--; // trim trailing dashes, to accept CA-94043
+                    if (s->mLetterCount == 2) {
+                        secondLetter -= 'A';
+                        if (secondLetter > 'Z' - 'A')
+                            goto resetWord;
+                        if ((stateTwoLetter[firstLetter] & 1 << secondLetter) != 0) {
+                            // special case to ignore 'et al'
+                            if (strCharCmp("ET", s->mWords[s->mWordCount - 2], 2, 1) == false) {                   
+                                s->mStateWord = s->mWordCount - 1;
+                                s->mZipHint = firstIndex[firstLetter] + 
+                                    bitcount(stateTwoLetter[firstLetter] & ((1 << secondLetter) - 1));
+                                goto foundStateName;
+                            }
+                        }
+                        goto resetWord;
+                    } 
+                    s->mStates = longStateNames[firstLetter];
+                    if (s->mStates == NULL)
+                        goto resetWord;
+                    mustBeAllUpper = false;
+                    s->mProgress = STATE_NAME;
+                    unsigned char section = s->mStates[0];
+                    ASSERT(section > 0x80);
+                    s->mSectionLength = section & 0x7f;
+                    candIndex = 1;
+                    secondHalf = false;
+                    s->mStateWord = s->mWordCount - 1;
+                    goto stateName;
+                }
+                if (WTF::isASCIIDigit(ch)) {
+                    if (s->mLetterCount == 0) {
+                        if (++s->mNumberCount > 1)
+                            continue;
+                        if (s->mWordCount == 0 && s->mContinuationNode)
+                            return FOUND_NONE;
+                        s->newWord(baseChars, chars);
+                        s->mNumberWords |= 1 << s->mWordCount;
+                        s->mUnparsed = true;
+                    }
+                    continue;
+                }
+                if (ch == '.') { // optionally can follow letters
+                    if (s->mLetterCount == 0)
+                        break;
+                    if (s->mNumberCount > 0)
+                        break;
+                    continue;
+                }
+                if (ch == '/') // between numbers (1/2) between words (12 Main / Ste 4d)
+                    goto resetWord;
+                if (ch == '#') // can precede numbers, allow it to appear randomly
+                    goto resetWord;
+                if (ch == '"') // sometimes parts of addresses are quoted (FIXME: cite an example here)
+                    continue;
+                break;
+            case SECOND_HALF:
+                if (WTF::isASCIIAlpha(ch)) {
+                    if (s->mLetterCount == 0) {
+                        s->newWord(baseChars, chars);
+                        s->mWordCount++;
+                    }
+                    s->mLetterCount++;
+                    continue;
+                }
+                if (WTF::isASCIIDigit(ch) == false) {
+                    if (s->mLetterCount > 0) {
+                        s->mProgress = STATE_NAME;
+                        candIndex = 0;
+                        secondHalf = true;
+                        goto stateName;
+                    }
+                    continue;
+                }
+                s->mProgress = ADDRESS_LINE;
+                goto resetState;
+            case STATE_NAME:
+            stateName:
+                // pick up length of first section
+                do {
+                    int stateIndex = 1;
+                    int skip = 0;
+                    int prefix = 0;
+                    bool subStr = false;
+                    do {
+                        unsigned char match = s->mStates[stateIndex];
+                        if (match >= 0x80) {
+                            if (stateIndex == s->mSectionLength)
+                                break;
+                            subStr = true;
+                  //          if (skip > 0)
+                  //              goto foundStateName;
+                            prefix = candIndex;
+                            skip = match & 0x7f;
+                            match = s->mStates[++stateIndex];
+                        }
+                        UChar candChar = s->mWords[s->mWordCount - 1][candIndex];
+                        if (mustBeAllUpper && WTF::isASCIILower(candChar))
+                            goto skipToNext;
+                        if (match != candChar) {
+                            if (match != WTF::toASCIILower(candChar)) {
+                       skipToNext:
+                                if (subStr == false)
+                                    break;
+                                if (stateIndex == s->mSectionLength) {
+                                    if (secondHalf) {
+                                        s->mProgress = ADDRESS_LINE;
+                                        goto resetState;
+                                    }
+                                    break;
+                                }
+                                stateIndex += skip;
+                                skip = 0;
+                                candIndex = prefix;
+                                continue; // try next substring
+                            }
+                            mustBeAllUpper = true;
+                        }
+                        int nextindex = stateIndex + 1;
+                        if (++candIndex >= s->mLetterCount && s->mStates[nextindex] == ' ') {
+                            s->mProgress = SECOND_HALF;
+                            s->mStates += nextindex;
+                            s->mSectionLength -= nextindex;
+                            goto resetWord;
+                        }
+                        if (nextindex + 1 == s->mSectionLength || skip == 2) {
+                            s->mZipHint = s->mStates[nextindex] - 1;
+                            goto foundStateName;
+                        }
+                        stateIndex += 1;
+                        skip -= 1;
+                    } while (true);
+                    s->mStates += s->mSectionLength;
+                    ASSERT(s->mStates[0] == 0 || (unsigned) s->mStates[0] > 0x80);
+                    s->mSectionLength = s->mStates[0] & 0x7f;
+                    candIndex = 1;
+                    subStr = false;
+                } while (s->mSectionLength != 0);
+                s->mProgress = ADDRESS_LINE;
+                goto resetState;
+            foundStateName:
+                s->mEndResult = chars - s->mCurrentStart;
+                s->mEndWord = s->mWordCount - 1;
+                s->mProgress = ZIP_CODE;
+                // a couple of delimiters is an indication that the state name is good
+                // or, a non-space / non-alpha-digit is also good
+                s->mZipDelimiter = s->mLineCount > 2
+                    || isUnicodeSpace(ch) == false
+                    || chars == s->mEnd;
+                if (WTF::isASCIIDigit(ch))
+                    s->mZipStart = chars;
+                goto resetState;
+            case ZIP_CODE:
+                if (WTF::isASCIIDigit(ch)) {
+                    int count = ++s->mNumberCount;
+                    if (count == 1) {
+                        if (WTF::isASCIIDigit(prior))
+                            ++s->mNumberCount;
+                        else
+                            s->mZipStart = chars;
+                    }
+                    if (count <= 9)
+                        continue;
+                } else if (isUnicodeSpace(ch)) {
+                    if (s->mNumberCount == 0) {
+                        s->mZipDelimiter = true; // two spaces delimit state name
+                        continue;
+                    }
+                } else if (ch == '-') {
+                    if (s->mNumberCount == 5 && validZip(s->mZipHint, s->mZipStart)) {
+                        s->mNumberCount = 0;
+                        s->mProgress = PLUS_4;
+                        continue;
+                    }
+                    if (s->mNumberCount == 0)
+                        s->mZipDelimiter = true;
+                } else if (WTF::isASCIIAlpha(ch) == false)
+                    s->mZipDelimiter = true;
+                else {
+                    if (s->mLetterCount == 0) {
+                        s->newWord(baseChars, chars);
+                        s->mUnparsed = true;
+                    }
+                    ++s->mLetterCount;
+                }
+                if (s->mNumberCount == 5 || s->mNumberCount == 9) {
+                    if (validZip(s->mZipHint, s->mZipStart) == false)
+                        goto noZipMatch;
+                    s->mEndResult = chars - s->mCurrentStart;
+                    s->mEndWord = s->mWordCount - 1;
+                } else if (s->mZipDelimiter == false) {
+            noZipMatch:
+                    --chars;
+                    s->mProgress = ADDRESS_LINE;
+                    continue;
+                }
+                s->mProgress = FIND_STREET;
+                goto findStreet;
+            case PLUS_4:
+                if (WTF::isASCIIDigit(ch)) {
+                    if (++s->mNumberCount <= 4)
+                        continue;
+                }
+                if (isUnicodeSpace(ch)) {
+                    if (s->mNumberCount == 0)
+                        continue;
+                }
+                if (s->mNumberCount == 4) {
+                    if (WTF::isASCIIAlpha(ch) == false) {
+                        s->mEndResult = chars - s->mCurrentStart;
+                        s->mEndWord = s->mWordCount - 1;
+                    }
+                } else if (s->mNumberCount != 0)
+                    break;
+                s->mProgress = FIND_STREET;
+            case FIND_STREET:
+            findStreet:
+                retryState = false;
+                for (int wordsIndex = s->mStateWord - 1; wordsIndex >= 0; --wordsIndex) {
+                    const UChar* test = s->mWords[wordsIndex];
+                    UChar letter = test[0];
+                    letter -= 'A';
+                    if (letter > 'X' - 'A')
+                        continue;
+                    const char* names = longStreetNames[letter];
+                    if (names == NULL)
+                        continue;
+                    int offset;
+                    while ((offset = *names++) != 0) {
+                        int testIndex = 1;
+                        bool abbr = false;
+                        for (int idx = 0; idx < offset; idx++) {
+                            char nameLetter = names[idx];
+                            char testUpper = WTF::toASCIIUpper(test[testIndex]);
+                            if (nameLetter == '*') {
+                                if (testUpper == 'S')
+                                    testIndex++;
+                                break;
+                            }
+                            bool fullOnly = WTF::isASCIILower(nameLetter);
+                            nameLetter = WTF::toASCIIUpper(nameLetter);
+                            if (testUpper == nameLetter) {
+                                if (abbr && fullOnly)
+                                    goto nextTest;
+                                testIndex++;
+                                continue;
+                            }
+                            if (fullOnly == false)
+                                goto nextTest;
+                            abbr = true;
+                        }
+                        letter = &test[testIndex] < s->mEnds[wordsIndex] ?
+                            test[testIndex] : ' ';
+                        if (WTF::isASCIIAlpha(letter) == false && WTF::isASCIIDigit(letter) == false) {
+                            if (s->mNumberWords != 0) {
+                                int shift = 0;
+                                int wordReduction = -1;
+                                do {
+                                    while ((s->mNumberWords & (1 << shift)) == 0)
+                                        shift++;
+                                    if (shift > wordsIndex)
+                                        break;
+                                    wordReduction = shift;
+                                } while (s->mNumberWords >> ++shift != 0);
+                                if (wordReduction >= 0) {
+                                    if (s->mContinuationNode) {
+                                        if (retryState)
+                                            break;
+                                        return FOUND_NONE;
+                                    }
+                                    s->mStartResult = s->mWords[wordReduction] - s->mStarts[wordReduction];
+                                }
+                            }
+                            if (wordsIndex != s->mStateWord - 1)
+                                return FOUND_COMPLETE;
+                            retryState = true;
+                        }
+                    nextTest:
+                        names += offset;
+                    }
+                }
+                if (retryState) {
+                    s->mProgress = ADDRESS_LINE;
+                    s->mStates = NULL;
+                    continue;
+                }
+                if (s->mNumberWords != 0) {
+                    unsigned shift = 0;
+                    while ((s->mNumberWords & (1 << shift)) == 0)
+                        shift++;
+                    s->mNumberWords >>= ++shift;
+                    if (s->mBases[0] != s->mBases[shift])
+                        return FOUND_NONE;
+                    s->shiftWords(shift);
+                    s->mStartResult = s->mWords[0] - s->mStarts[0];
+                    s->mWordCount -= shift;
+                    s->mProgress = ADDRESS_LINE;
+                    --chars;
+                    continue;
+                }
+                break;
+        }
+        if (s->mContinuationNode)
+            return FOUND_NONE;
+        s->mProgress = NO_ADDRESS;
+        s->mWordCount = s->mLineCount = 0;
+        s->mNumberWords = 0;
+    resetState:
+        s->mStates = NULL;
+    resetWord:
+        s->mNumberCount = s->mLetterCount = 0;
+        s->mFirstLower = NULL;
+        s->mUnparsed = false;
+    }
+    s->mCurrent = ch;
+    return s->mProgress == NO_ADDRESS ? FOUND_NONE : FOUND_PARTIAL;
+}
+
+// Recogize common email patterns only. Currently has lots of state, walks text forwards and backwards -- will be
+// a real challenge to adapt to walk text across multiple nodes, I imagine
+// FIXME: it's too hard for the caller to call these incrementally -- it's probably best for this to
+// either walk the node tree directly or make a callout to get the next or previous node, if there is one
+// walking directly will avoid adding logic in caller to track the multiple partial or full nodes that compose this 
+// text pattern.
+CacheBuilder::FoundState CacheBuilder::FindPartialEMail(const UChar* chars, unsigned length, 
+    FindState* s)
+{
+    // the following tables were generated by tests/browser/focusNavigation/BrowserDebug.cpp
+    // hand-edit at your own risk
+    static const int domainTwoLetter[] = {
+        0x02df797c,  // a followed by: [cdefgilmnoqrstuwxz]
+        0x036e73fb,  // b followed by: [abdefghijmnorstvwyz]
+        0x03b67ded,  // c followed by: [acdfghiklmnorsuvxyz]
+        0x02005610,  // d followed by: [ejkmoz]
+        0x001e00d4,  // e followed by: [ceghrstu]
+        0x00025700,  // f followed by: [ijkmor]
+        0x015fb9fb,  // g followed by: [abdefghilmnpqrstuwy]
+        0x001a3400,  // h followed by: [kmnrtu]
+        0x000f7818,  // i followed by: [delmnoqrst]
+        0x0000d010,  // j followed by: [emop]
+        0x0342b1d0,  // k followed by: [eghimnprwyz]
+        0x013e0507,  // l followed by: [abcikrstuvy]
+        0x03fffccd,  // m followed by: [acdghklmnopqrstuvwxyz]
+        0x0212c975,  // n followed by: [acefgilopruz]
+        0x00001000,  // o followed by: [m]
+        0x014e3cf1,  // p followed by: [aefghklmnrstwy]
+        0x00000001,  // q followed by: [a]
+        0x00504010,  // r followed by: [eouw]
+        0x032a7fdf,  // s followed by: [abcdeghijklmnortvyz]
+        0x026afeec,  // t followed by: [cdfghjklmnoprtvwz]
+        0x03041441,  // u followed by: [agkmsyz]
+        0x00102155,  // v followed by: [aceginu]
+        0x00040020,  // w followed by: [fs]
+        0x00000000,  // x
+        0x00180010,  // y followed by: [etu]
+        0x00401001,  // z followed by: [amw]
+    };
+
+    static char const* const longDomainNames[] = {
+        "\x03" "ero" "\x03" "rpa",  // aero, arpa  
+        "\x02" "iz",  // biz  
+        "\x02" "at" "\x02" "om" "\x03" "oop",  // cat, com, coop  
+        NULL,  // d
+        "\x02" "du",  // edu  
+        NULL,  // f
+        "\x02" "ov",  // gov  
+        NULL,  // h
+        "\x03" "nfo" "\x02" "nt",  // info, int  
+        "\x03" "obs",  // jobs  
+        NULL,  // k
+        NULL,  // l
+        "\x02" "il" "\x03" "obi" "\x05" "useum",  // mil, mobi, museum  
+        "\x03" "ame" "\x02" "et",  // name, net  
+        "\x02" "rg",  // , org  
+        "\x02" "ro",  // pro  
+        NULL,  // q  
+        NULL,  // r
+        NULL,  // s
+        "\x05" "ravel",  // travel  
+        NULL,  // u
+        NULL,  // v
+        NULL,  // w
+        NULL,  // x
+        NULL,  // y
+        NULL,  // z
+    };
+    
+    const UChar* start = chars;
+    const UChar* end = chars + length;
+    while (chars < end) {
+        UChar ch = *chars++;
+        if (ch != '@')
+            continue;
+        const UChar* atLocation = chars - 1;
+        // search for domain
+        ch = *chars++ | 0x20; // convert uppercase to lower
+        if (ch < 'a' || ch > 'z')
+            continue;
+        while (chars < end) {
+            ch = *chars++;
+            if (IsDomainChar(ch) == false)
+                goto nextAt;
+            if (ch != '.')
+                continue;
+            UChar firstLetter = *chars++ | 0x20; // first letter of the domain
+            if (chars >= end)
+                return FOUND_NONE; // only one letter; must be at least two
+            firstLetter -= 'a';
+            if (firstLetter > 'z' - 'a')
+                continue; // non-letter followed '.'
+            int secondLetterMask = domainTwoLetter[firstLetter];
+            ch = *chars | 0x20; // second letter of the domain
+            ch -= 'a';
+            if (ch >= 'z' - 'a')
+                continue;
+            bool secondMatch = (secondLetterMask & 1 << ch) != 0;
+            const char* wordMatch = longDomainNames[firstLetter];
+            int wordIndex = 0;
+            while (wordMatch != NULL) {
+                int len = *wordMatch++;
+                char match;
+                do {
+                    match = wordMatch[wordIndex];
+                    if (match < 0x20)
+                        goto foundDomainStart;
+                    if (chars[wordIndex] != match)
+                        break;
+                    wordIndex++;
+                } while (true);
+                wordMatch += len;
+                if (*wordMatch == '\0')
+                    break;
+                wordIndex = 0;
+            }
+            if (secondMatch) {
+                wordIndex = 1;
+        foundDomainStart:
+                chars += wordIndex;
+                if (chars < end) {
+                    ch = *chars;
+                    if (ch != '.') {
+                        if (IsDomainChar(ch))
+                            goto nextDot;
+                    } else if (chars + 1 < end && IsDomainChar(chars[1]))
+                        goto nextDot;
+                }
+                // found domain. Search backwards from '@' for beginning of email address
+                s->mEndResult = chars - start;
+                chars = atLocation;
+                if (chars <= start)
+                    goto nextAt;
+                ch = *--chars;
+                if (ch == '.')
+                    goto nextAt; // mailbox can't end in period
+                do {
+                    if (IsMailboxChar(ch) == false) {
+                        chars++;
+                        break;
+                    }
+                    if (chars == start)
+                        break;
+                    ch = *--chars;
+                } while (true);
+                UChar firstChar = *chars;
+                if (firstChar == '.' || firstChar == '@') // mailbox can't start with period or be empty
+                    goto nextAt;
+                s->mStartResult = chars - start;
+                return FOUND_COMPLETE;
+            }
+    nextDot:
+            ;
+        }
+nextAt:
+        chars = atLocation + 1;
+    }
+    return FOUND_NONE;
+}
+
+#define PHONE_PATTERN "(200) /-.\\ 100 -. 0000" // poor man's regex: parens optional, any one of punct, digit smallest allowed
+
+CacheBuilder::FoundState CacheBuilder::FindPartialNumber(const UChar* chars, unsigned length, 
+    FindState* s)
+{
+    char* pattern = s->mPattern;
+    UChar* store = s->mStorePtr;
+    const UChar* start = chars;
+    const UChar* end = chars + length;
+    const UChar* lastDigit = NULL;
+    do {
+        bool initialized = s->mInitialized;
+        while (chars < end) {
+            if (initialized == false) {
+                s->mBackTwo = s->mBackOne;
+                s->mBackOne = s->mCurrent;
+            }
+            UChar ch = s->mCurrent = *chars;
+            do {
+                char patternChar = *pattern;
+                switch (patternChar) {
+                    case '2':
+                            if (initialized == false) {
+                                s->mStartResult = chars - start;
+                                initialized = true;
+                            }
+                    case '0':
+                    case '1':
+                        if (ch < patternChar || ch > '9')
+                            goto resetPattern;
+                        *store++ = ch;
+                        pattern++;
+                        lastDigit = chars;
+                        goto nextChar;
+                    case '\0':
+                        if (WTF::isASCIIDigit(ch) == false) {
+                            *store = '\0';
+                            goto checkMatch;
+                        }
+                        goto resetPattern;
+                    case ' ':
+                        if (ch == patternChar)
+                            goto nextChar;
+                        break;
+                    case '(':
+                        if (ch == patternChar) {
+                            s->mStartResult = chars - start;
+                            initialized = true;
+                            s->mOpenParen = true;
+                        }
+                        goto commonPunctuation;
+                    case ')':
+                        if ((ch == patternChar) ^ s->mOpenParen)
+                            goto resetPattern;
+                    default:
+                    commonPunctuation:
+                        if (ch == patternChar) {
+                            pattern++;
+                            goto nextChar;
+                        }
+                }
+            } while (++pattern); // never false
+    nextChar:
+            chars++;
+        }
+        break;
+resetPattern:
+        if (s->mContinuationNode)
+            return FOUND_NONE;
+        FindResetNumber(s);
+        pattern = s->mPattern;
+        store = s->mStorePtr;
+    } while (++chars < end);
+checkMatch:
+    if (WTF::isASCIIDigit(s->mBackOne != '1' ? s->mBackOne : s->mBackTwo))
+        return FOUND_NONE;
+    *store = '\0';
+    s->mStorePtr = store;
+    s->mPattern = pattern;
+    s->mEndResult = lastDigit - start + 1;
+    char pState = pattern[0];
+    return pState == '\0' ? FOUND_COMPLETE : pState == '(' || (WTF::isASCIIDigit(pState) && WTF::isASCIIDigit(pattern[-1])) ? 
+        FOUND_NONE : FOUND_PARTIAL;
+}
+
+CacheBuilder::FoundState CacheBuilder::FindPhoneNumber(const UChar* chars, unsigned length, 
+    int* start, int* end)
+{
+    FindState state;
+    FindReset(&state);
+    FoundState result = FindPartialNumber(chars, length, &state);
+    *start = state.mStartResult;
+    *end = state.mEndResult;
+    return result;
+}
+
+void CacheBuilder::FindReset(FindState* state)
+{
+    memset(state, 0, sizeof(FindState));
+    state->mCurrent = ' ';
+    FindResetNumber(state);
+}
+
+void CacheBuilder::FindResetNumber(FindState* state)
+{
+    state->mOpenParen = false;
+    state->mPattern = (char*) PHONE_PATTERN;
+    state->mStorePtr = state->mStore;
+}
+
+IntRect CacheBuilder::getAreaRect(const HTMLAreaElement* area)
+{
+    Node* node = area->document();
+    while ((node = node->traverseNextNode()) != NULL) {
+        RenderObject* renderer = node->renderer();
+        if (renderer && renderer->isRenderImage()) {
+            RenderImage* image = static_cast<RenderImage*>(renderer);
+            HTMLMapElement* map = image->imageMap();
+            if (map) {
+                Node* n;
+                for (n = map->firstChild(); n;
+                        n = n->traverseNextNode(map)) {
+                    if (n == area) {
+                        if (area->isDefault())
+                            return image->absoluteBoundingBoxRect();
+                        return area->computeRect(image);
+                    }
+                }
+            }
+        }
+    }
+    return IntRect();
+}
+
+void CacheBuilder::GetGlobalOffset(Node* node, int* x, int * y) 
+{ 
+    GetGlobalOffset(node->document()->frame(), x, y); 
+}
+
+void CacheBuilder::GetGlobalOffset(Frame* frame, int* x, int* y)
+{
+//    TIMER_PROBE(__FUNCTION__);
+    ASSERT(x);
+    ASSERT(y);
+    *x = 0;
+    *y = 0;
+    if (!frame->view())
+        return;
+    Frame* parent;
+    while ((parent = frame->tree()->parent()) != NULL) {
+        const WebCore::IntRect& rect = frame->view()->platformWidget()->getBounds();
+        *x += rect.x();
+        *y += rect.y();
+        frame = parent;
+    }
+ //   TIMER_PROBE_END();
+}
+
+Frame* CacheBuilder::HasFrame(Node* node)
+{
+    RenderObject* renderer = node->renderer();
+    if (renderer == NULL)
+        return NULL;
+    if (renderer->isWidget() == false)
+        return NULL;
+    Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
+    if (widget == NULL)
+        return NULL;
+    if (widget->isFrameView() == false)
+        return NULL;
+    return static_cast<FrameView*>(widget)->frame();
+}
+
+bool CacheBuilder::HasOverOrOut(Node* node)
+{
+    // eventNames are thread-local data, I avoid using 'static' variable here.
+    AtomicString eventTypes[2] = {
+        eventNames().mouseoverEvent,
+        eventNames().mouseoutEvent
+    };
+
+    return NodeHasEventListeners(node, eventTypes, 2);
+}
+
+bool CacheBuilder::HasTriggerEvent(Node* node)
+{
+    AtomicString eventTypes[5] = {
+        eventNames().clickEvent,
+        eventNames().mousedownEvent,
+        eventNames().mouseupEvent,
+        eventNames().keydownEvent,
+        eventNames().keyupEvent
+    };
+
+    return NodeHasEventListeners(node, eventTypes, 5);
+}
+
+// #define EMAIL_PATTERN "x@y.d" // where 'x' is letters, numbers, and '-', '.', '_' ; 'y' is 'x' without the underscore, and 'd' is a valid domain
+//  - 0x2D . 0x2E 0-9 0x30-39 A-Z 0x41-5A  _ 0x5F a-z 0x61-7A 
+
+bool CacheBuilder::IsDomainChar(UChar ch)
+{
+    static const unsigned body[] = {0x03ff6000, 0x07fffffe, 0x07fffffe}; // 0-9 . - A-Z a-z
+    ch -= 0x20;
+    if (ch > 'z' - 0x20)
+        return false;
+    return (body[ch >> 5] & 1 << (ch & 0x1f)) != 0;
+}
+
+bool CacheBuilder::isFocusableText(NodeWalk* walk, bool more, Node* node, 
+    CachedNodeType* type, String* exported) const
+{
+    Text* textNode = static_cast<Text*>(node);
+    StringImpl* string = textNode->dataImpl();
+    const UChar* baseChars = string->characters();
+//    const UChar* originalBase = baseChars;
+    int length = string->length();
+    int index = 0;
+    while (index < length && isUnicodeSpace(baseChars[index]))
+        index++;
+    if (index >= length)
+        return false;
+    if (more == false) {
+        walk->mStart = 0;
+        walk->mEnd = 0;
+        walk->mFinalNode = node;
+        walk->mLastInline = NULL;
+    }
+    // starting with this node, search forward for email, phone number, and address
+    // if any of the three is found, track it so that the remaining can be looked for later
+    FoundState state = FOUND_NONE;
+    RenderText* renderer = (RenderText*) node->renderer();
+    bool foundBetter = false;
+    InlineTextBox* baseInline = walk->mLastInline != NULL ? walk->mLastInline :
+        renderer->firstTextBox();
+    if (baseInline == NULL)
+        return false;
+    int start = walk->mEnd;
+    InlineTextBox* saveInline;
+    int baseStart, firstStart = start;
+    saveInline = baseInline;
+    baseStart = start;
+    for (CachedNodeType checkType = ADDRESS_CACHEDNODETYPE;
+        checkType <= PHONE_CACHEDNODETYPE; 
+        checkType = static_cast<CachedNodeType>(checkType + 1))
+    {
+        if ((1 << (checkType - 1) & mAllowableTypes) == 0)
+            continue;
+        InlineTextBox* inlineTextBox = baseInline;
+        FindState findState;
+        FindReset(&findState);
+        start = baseStart;
+        if (checkType == ADDRESS_CACHEDNODETYPE) {
+            findState.mBases[0] = baseChars;
+            findState.mWords[0] = baseChars + start;
+            findState.mStarts[0] = baseChars + start;
+        }
+        Node* lastPartialNode = NULL;
+        int lastPartialEnd = -1;
+        bool lastPartialMore = false;
+        bool firstPartial = true;
+        InlineTextBox* lastPartialInline = NULL;
+        do {
+            do {
+                const UChar* chars = baseChars + start;
+                length = inlineTextBox == NULL ? 0 :
+                    inlineTextBox->end() - start + 1;
+                bool wasInitialized = findState.mInitialized;
+                switch (checkType) {
+                    case ADDRESS_CACHEDNODETYPE:
+                        state = FindPartialAddress(baseChars, chars, length, &findState);
+                    break;
+                    case EMAIL_CACHEDNODETYPE:
+                        state = FindPartialEMail(chars, length, &findState);
+                    break;
+                    case PHONE_CACHEDNODETYPE:
+                        state = FindPartialNumber(chars, length, &findState);
+                    break;
+                    default:
+                        ASSERT(0);
+                }
+                findState.mInitialized = state != FOUND_NONE;
+                if (wasInitialized != findState.mInitialized)
+                    firstStart = start;
+                if (state == FOUND_PARTIAL) {
+                    lastPartialNode = node;
+                    lastPartialEnd = findState.mEndResult + start;
+                    lastPartialMore = firstPartial && 
+                        lastPartialEnd < (int) string->length();
+                    firstPartial = false;
+                    lastPartialInline = inlineTextBox;
+                    findState.mContinuationNode = true;
+                } else if (state == FOUND_COMPLETE) {
+                    if (foundBetter == false || walk->mStart > findState.mStartResult) {
+                        walk->mStart = findState.mStartResult + firstStart; 
+                        if (findState.mEndResult > 0) {
+                            walk->mFinalNode = node;
+                            walk->mEnd = findState.mEndResult + start;
+                            walk->mMore = node == textNode &&
+                                walk->mEnd < (int) string->length();
+                            walk->mLastInline = inlineTextBox;
+                        } else {
+                            walk->mFinalNode = lastPartialNode;
+                            walk->mEnd = lastPartialEnd;
+                            walk->mMore = lastPartialMore;
+                            walk->mLastInline = lastPartialInline;
+                        }
+                        *type = checkType;
+                        if (checkType == PHONE_CACHEDNODETYPE) {
+                            const UChar* store = findState.mStore;
+                            *exported = String(store);
+                        } else {
+                            Node* temp = textNode;
+                            length = 1;
+                            start = walk->mStart;
+                            exported->truncate(0);
+                            do {
+                                Text* tempText = static_cast<Text*>(temp);
+                                StringImpl* string = tempText->dataImpl();
+                                int end = tempText == walk->mFinalNode ? 
+                                    walk->mEnd : string->length();
+                                exported->append(String(string->substring(
+                                    start, end - start)));
+                                ASSERT(end > start);
+                                length += end - start + 1;
+                                if (temp == walk->mFinalNode)
+                                    break;
+                                start = 0;
+                                do {
+                                    temp = temp->traverseNextNode();
+                                    ASSERT(temp);
+                                } while (temp->isTextNode() == false);
+                                // add a space in between text nodes to avoid 
+                                // words collapsing together
+                                exported->append(" ");
+                            } while (true);
+                        }
+                        foundBetter = true;
+                    }
+                    goto tryNextCheckType;
+                } else if (findState.mContinuationNode)
+                    break;
+                if (inlineTextBox == NULL)
+                    break;
+                inlineTextBox = inlineTextBox->nextTextBox();
+                if (inlineTextBox == NULL)
+                    break;
+                start = inlineTextBox->start();
+                if (state == FOUND_PARTIAL && node == textNode)
+                    findState.mContinuationNode = false;
+            } while (true);
+            if (state == FOUND_NONE)
+                break;
+            // search for next text node, if any
+            Text* nextNode;
+            do {
+                do {
+                    do {
+                        if (node)
+                            node = node->traverseNextNode();
+                        if (node == NULL || node->hasTagName(HTMLNames::aTag)
+                                || node->hasTagName(HTMLNames::inputTag)
+                                || node->hasTagName(HTMLNames::textareaTag)) {
+                            if (state == FOUND_PARTIAL && 
+                                    checkType == ADDRESS_CACHEDNODETYPE && 
+                                    findState.mProgress == ZIP_CODE && 
+                                    findState.mNumberCount == 0) {
+                                baseChars = NULL;
+                                inlineTextBox = NULL;
+                                start = 0;
+                                findState.mProgress = FIND_STREET;
+                                goto finalNode;
+                            }
+                            goto tryNextCheckType;
+                        }
+                    } while (node->isTextNode() == false);
+                    nextNode = static_cast<Text*>(node);
+                    renderer = (RenderText*) nextNode->renderer();
+                } while (renderer == NULL);
+                baseInline = renderer->firstTextBox();
+            } while (baseInline == NULL);
+            string = nextNode->dataImpl();
+            baseChars = string->characters();
+            inlineTextBox = baseInline;
+            start = inlineTextBox->start();
+        finalNode:
+            findState.mEndResult = 0;
+        } while (true);
+tryNextCheckType:
+        node = textNode;
+        baseInline = saveInline;
+        string = textNode->dataImpl();
+        baseChars = string->characters();
+    }
+    if (foundBetter) {
+        CachedNodeType temp = *type;
+        switch (temp) {
+            case ADDRESS_CACHEDNODETYPE: {
+                static const char geoString[] = "geo:0,0?q=";
+                exported->insert(String(geoString), 0);
+                int index = sizeof(geoString) - 1;
+                String escapedComma("%2C");
+                while ((index = exported->find(',', index)) >= 0)
+                    exported->replace(index, 1, escapedComma);
+                } break;
+            case EMAIL_CACHEDNODETYPE: {
+                String encoded = WebCore::encodeWithURLEscapeSequences(*exported);
+                exported->swap(encoded);
+                exported->insert(WTF::String("mailto:"), 0);
+                } break;
+            case PHONE_CACHEDNODETYPE:
+                exported->insert(WTF::String("tel:"), 0);
+                break;
+            default:
+                break;
+        }
+        return true;
+    }
+noTextMatch:
+    walk->reset();
+    return false;
+}
+
+bool CacheBuilder::IsMailboxChar(UChar ch)
+{
+    // According to http://en.wikipedia.org/wiki/Email_address
+    // ! # $ % & ' * + - . / 0-9 = ?
+    // A-Z ^ _
+    // ` a-z { | } ~
+    static const unsigned body[] = {0xa3ffecfa, 0xc7fffffe, 0x7fffffff};
+    ch -= 0x20;
+    if (ch > '~' - 0x20)
+        return false;
+    return (body[ch >> 5] & 1 << (ch & 0x1f)) != 0;
+}
+
+bool CacheBuilder::setData(CachedFrame* cachedFrame) 
+{
+    Frame* frame = FrameAnd(this);
+    Document* doc = frame->document();
+    if (doc == NULL)
+        return false;
+    RenderObject* renderer = doc->renderer();
+    if (renderer == NULL)
+        return false;
+    RenderLayer* layer = renderer->enclosingLayer();
+    if (layer == NULL)
+        return false;
+    if (!frame->view())
+        return false;
+    int x, y;
+    GetGlobalOffset(frame, &x, &y);
+    WebCore::IntRect viewBounds = frame->view()->platformWidget()->getBounds();
+    if ((x | y) != 0)
+        viewBounds.setLocation(WebCore::IntPoint(x, y));
+    cachedFrame->setLocalViewBounds(viewBounds);
+    cachedFrame->setContentsSize(layer->scrollWidth(), layer->scrollHeight());
+    if (cachedFrame->childCount() == 0)
+        return true;
+    CachedFrame* lastCachedFrame = cachedFrame->lastChild();
+    cachedFrame = cachedFrame->firstChild();
+    do {
+        CacheBuilder* cacheBuilder = Builder((Frame* )cachedFrame->framePointer());
+        cacheBuilder->setData(cachedFrame);
+    } while (cachedFrame++ != lastCachedFrame);
+    return true;
+}
+
+#if USE(ACCELERATED_COMPOSITING)
+void CacheBuilder::TrackLayer(WTF::Vector<LayerTracker>& layerTracker,
+    RenderObject* nodeRenderer, Node* lastChild, int offsetX, int offsetY)
+{
+    RenderLayer* layer = nodeRenderer->enclosingLayer();
+    RenderLayerBacking* back = layer->backing();
+    if (!back)
+        return;
+    GraphicsLayer* grLayer = back->graphicsLayer();
+    if (back->hasContentsLayer())
+        grLayer = back->foregroundLayer();
+    if (!grLayer)
+        return;
+    LayerAndroid* aLayer = grLayer->platformLayer();
+    if (!aLayer)
+        return;
+    IntPoint scroll(layer->scrollXOffset(), layer->scrollYOffset());
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+    // If this is an overflow element, track the content layer.
+    if (layer->hasOverflowScroll() && aLayer->getChild(0))
+        aLayer = aLayer->getChild(0)->getChild(0);
+    if (!aLayer)
+        return;
+    // Prevent a crash when scrolling a layer that does not have a parent.
+    if (layer->stackingContext())
+        layer->scrollToOffset(0, 0);
+#endif
+    layerTracker.grow(layerTracker.size() + 1);
+    LayerTracker& indexTracker = layerTracker.last();
+    indexTracker.mLayer = aLayer;
+    indexTracker.mRenderLayer = layer;
+    indexTracker.mBounds = enclosingIntRect(aLayer->bounds());
+    // Use the absolute location of the layer as the bounds location.  This
+    // provides the original offset of nodes in the layer so that we can
+    // translate nodes between their original location and the layer's new
+    // location.
+    indexTracker.mBounds.setLocation(layer->absoluteBoundingBox().location());
+    indexTracker.mBounds.move(offsetX, offsetY);
+    indexTracker.mScroll = scroll;
+    indexTracker.mLastChild = OneAfter(lastChild);
+    DBG_NAV_LOGD("layer=%p [%d] bounds=(%d,%d,w=%d,h=%d)", aLayer,
+        aLayer->uniqueId(), indexTracker.mBounds.x(), indexTracker.mBounds.y(),
+        indexTracker.mBounds.width(), indexTracker.mBounds.height());
+}
+#endif
+
+bool CacheBuilder::validNode(Frame* startFrame, void* matchFrame,
+        void* matchNode)
+{
+    if (matchFrame == startFrame) {
+        if (matchNode == NULL)
+            return true;
+        Node* node = startFrame->document();
+        while (node != NULL) {
+            if (node == matchNode) {
+                const IntRect& rect = node->hasTagName(HTMLNames::areaTag) ? 
+                    getAreaRect(static_cast<HTMLAreaElement*>(node)) : node->getRect();
+                // Consider nodes with empty rects that are not at the origin
+                // to be valid, since news.google.com has valid nodes like this
+                if (rect.x() == 0 && rect.y() == 0 && rect.isEmpty())
+                    return false;
+                return true;
+            }
+            node = node->traverseNextNode();
+        }
+        DBG_NAV_LOGD("frame=%p valid node=%p invalid\n", matchFrame, matchNode);
+        return false;
+    }
+    Frame* child = startFrame->tree()->firstChild();
+    while (child) {
+        bool result = validNode(child, matchFrame, matchNode);
+        if (result)
+            return result;
+        child = child->tree()->nextSibling();
+    }
+#if DEBUG_NAV_UI
+    if (startFrame->tree()->parent() == NULL)
+        DBG_NAV_LOGD("frame=%p node=%p false\n", matchFrame, matchNode);
+#endif
+    return false;
+}
+
+static int Area(const IntRect& rect)
+{
+    return rect.width() * rect.height();
+}
+
+bool CacheBuilder::AddPartRect(IntRect& bounds, int x, int y,
+    WTF::Vector<IntRect>* result, IntRect* focusBounds)
+{
+    if (bounds.isEmpty())
+        return true;
+    bounds.move(x, y);
+    if (bounds.maxX() <= 0 || bounds.maxY() <= 0)
+        return true;
+    IntRect* work = result->begin() - 1; 
+    IntRect* end = result->end();
+    while (++work < end) {
+        if (work->contains(bounds))
+            return true;
+        if (bounds.contains(*work)) {
+            *work = bounds;
+            focusBounds->unite(bounds);
+            return true;
+        }
+        if ((bounds.x() != work->x() || bounds.width() != work->width()) &&
+               (bounds.y() != work->y() || bounds.height() != work->height()))
+            continue;
+        IntRect test = *work;
+        test.unite(bounds);
+        if (Area(test) > Area(*work) + Area(bounds))
+            continue;
+        *work = test;
+        focusBounds->unite(bounds);
+        return true;
+    }
+    if (result->size() >= MAXIMUM_FOCUS_RING_COUNT)
+        return false;
+    result->append(bounds);
+    if (focusBounds->isEmpty())
+        *focusBounds = bounds;
+    else
+        focusBounds->unite(bounds);
+    return true;
+}
+
+bool CacheBuilder::ConstructPartRects(Node* node, const IntRect& bounds, 
+    IntRect* focusBounds, int x, int y, WTF::Vector<IntRect>* result,
+    int* imageCountPtr)
+{
+    WTF::Vector<ClipColumnTracker> clipTracker(1);
+    ClipColumnTracker* baseTracker = clipTracker.data(); // sentinel
+    bzero(baseTracker, sizeof(ClipColumnTracker));
+    if (node->hasChildNodes() && node->hasTagName(HTMLNames::buttonTag) == false
+            && node->hasTagName(HTMLNames::selectTag) == false) {
+        // collect all text rects from first to last child
+        Node* test = node->firstChild();
+        Node* last = NULL;
+        Node* prior = node;
+        while ((prior = prior->lastChild()) != NULL)
+            last = prior;
+        ASSERT(last != NULL);
+        bool nodeIsAnchor = node->hasTagName(HTMLNames::aTag);
+        do {
+            do {
+                const ClipColumnTracker* lastClip = &clipTracker.last();
+                if (test != lastClip->mLastChild)
+                    break;
+                clipTracker.removeLast();
+            } while (true);
+            RenderObject* renderer = test->renderer();
+            if (renderer == NULL)
+                continue;
+            EVisibility vis = renderer->style()->visibility();
+            if (vis == HIDDEN)
+                continue;
+            bool hasClip = renderer->hasOverflowClip();
+            size_t clipIndex = clipTracker.size();
+            IntRect clipBounds = IntRect(0, 0, INT_MAX, INT_MAX);
+            if (hasClip || --clipIndex > 0) {
+                clipBounds = hasClip ? renderer->absoluteBoundingBoxRect() :
+                    clipTracker.at(clipIndex).mBounds; // x, y fixup done by ConstructTextRect
+            }
+            if (test->isTextNode()) {
+                RenderText* renderText = (RenderText*) renderer;
+                InlineTextBox *textBox = renderText->firstTextBox();
+                if (textBox == NULL)
+                    continue;
+                if (ConstructTextRect((Text*) test, textBox, 0, INT_MAX, 
+                        x, y, focusBounds, clipBounds, result) == false) {
+                    return false;
+                }
+                continue;
+            }
+            if (test->hasTagName(HTMLNames::imgTag)) {
+                IntRect bounds = test->getRect();
+                bounds.intersect(clipBounds);
+                if (AddPartRect(bounds, x, y, result, focusBounds) == false)
+                    return false;
+                *imageCountPtr += 1;
+                continue;
+            } 
+            if (hasClip == false) {
+                if (nodeIsAnchor && test->hasTagName(HTMLNames::divTag)) {
+                    IntRect bounds = renderer->absoluteBoundingBoxRect();  // x, y fixup done by AddPartRect
+                    RenderBox* renderBox = static_cast<RenderBox*>(renderer);
+                    int left = bounds.x() + renderBox->paddingLeft() + renderBox->borderLeft();
+                    int top = bounds.y() + renderBox->paddingTop() + renderBox->borderTop();
+                    int right = bounds.maxX() - renderBox->paddingRight() - renderBox->borderRight();
+                    int bottom = bounds.maxY() - renderBox->paddingBottom() - renderBox->borderBottom();
+                    if (left >= right || top >= bottom)
+                        continue;
+                    bounds = IntRect(left, top, right - left, bottom - top);
+                    if (AddPartRect(bounds, x, y, result, focusBounds) == false)
+                        return false;
+                }
+                continue;
+            }
+            Node* lastChild = test->lastChild();
+            if (lastChild == NULL)
+                continue;
+            clipTracker.grow(clipTracker.size() + 1);
+            ClipColumnTracker& clip = clipTracker.last();
+            clip.mBounds = renderer->absoluteBoundingBoxRect(); // x, y fixup done by ConstructTextRect
+            clip.mLastChild = OneAfter(lastChild);
+            clip.mNode = test;
+        } while (test != last && (test = test->traverseNextNode()) != NULL);
+    }
+    if (result->size() == 0 || focusBounds->width() < MINIMUM_FOCUSABLE_WIDTH
+            || focusBounds->height() < MINIMUM_FOCUSABLE_HEIGHT) {
+        if (bounds.width() < MINIMUM_FOCUSABLE_WIDTH)
+            return false;
+        if (bounds.height() < MINIMUM_FOCUSABLE_HEIGHT)
+            return false;
+        result->append(bounds);
+        *focusBounds = bounds;
+    }
+    return true;
+}
+
+static inline bool isNotSpace(UChar c)
+{
+    return c <= 0xA0 ? isUnicodeSpace(c) == false : 
+        WTF::Unicode::direction(c) != WTF::Unicode::WhiteSpaceNeutral;
+}
+
+bool CacheBuilder::ConstructTextRect(Text* textNode,
+    InlineTextBox* textBox, int start, int relEnd, int x, int y, 
+    IntRect* focusBounds, const IntRect& clipBounds, WTF::Vector<IntRect>* result)
+{
+    RenderText* renderText = (RenderText*) textNode->renderer();
+    EVisibility vis = renderText->style()->visibility();
+    StringImpl* string = textNode->dataImpl();
+    const UChar* chars = string->characters();
+    FloatPoint pt = renderText->localToAbsolute();
+    do {
+        int textBoxStart = textBox->start();
+        int textBoxEnd = textBoxStart + textBox->len();
+        if (textBoxEnd <= start)
+            continue;
+        if (textBoxEnd > relEnd)
+            textBoxEnd = relEnd;
+        IntRect bounds = textBox->selectionRect((int) pt.x(), (int) pt.y(), 
+            start, textBoxEnd);
+        bounds.intersect(clipBounds);
+        if (bounds.isEmpty())
+            continue;
+        bool drawable = false;
+        for (int index = start; index < textBoxEnd; index++)
+            if ((drawable |= isNotSpace(chars[index])) != false)
+                break;
+        if (drawable && vis != HIDDEN) {
+            if (AddPartRect(bounds, x, y, result, focusBounds) == false)
+                return false;
+        }
+        if (textBoxEnd == relEnd)
+            break;
+    } while ((textBox = textBox->nextTextBox()) != NULL);
+    return true;
+}
+
+bool CacheBuilder::ConstructTextRects(Text* node, int start, 
+    Text* last, int end, int x, int y, IntRect* focusBounds, 
+    const IntRect& clipBounds, WTF::Vector<IntRect>* result)
+{
+    result->clear();
+    *focusBounds = IntRect(0, 0, 0, 0);
+    do {
+        RenderText* renderText = (RenderText*) node->renderer();
+        int relEnd = node == last ? end : renderText->textLength();
+        InlineTextBox *textBox = renderText->firstTextBox();
+        if (textBox != NULL) {
+            do {
+                if ((int) textBox->end() >= start)
+                    break;
+            } while ((textBox = textBox->nextTextBox()) != NULL);
+            if (textBox && ConstructTextRect(node, textBox, start, relEnd,
+                    x, y, focusBounds, clipBounds, result) == false)
+                return false;
+        }
+        start = 0;
+        do {
+            if (node == last)
+                return true;
+            node = (Text*) node->traverseNextNode();
+            ASSERT(node != NULL);
+        } while (node->isTextNode() == false || node->renderer() == NULL);
+    } while (true);
+}
+
+}
diff --git a/Source/WebKit/android/nav/CacheBuilder.h b/Source/WebKit/android/nav/CacheBuilder.h
new file mode 100644
index 0000000..8f1cc72
--- /dev/null
+++ b/Source/WebKit/android/nav/CacheBuilder.h
@@ -0,0 +1,297 @@
+/*
+ * Copyright 2006, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CacheBuilder_h
+#define CacheBuilder_h
+
+#include "CachedDebug.h"
+#include "CachedNodeType.h"
+#include "IntRect.h"
+#include "PlatformString.h"
+#include "TextDirection.h"
+#include <wtf/Forward.h>
+#include <wtf/Vector.h>
+
+#define NAVIGATION_MAX_PHONE_LENGTH 14
+
+using namespace WebCore;
+
+namespace WebCore {
+
+class ColumnInfo;
+class Document;
+class Frame;
+class HTMLAreaElement;
+class InlineTextBox;
+class LayerAndroid;
+class Node;
+class PlatformGraphicsContext;
+class RenderBlock;
+class RenderFlow;
+class RenderLayer;
+class RenderObject;
+class Text;
+
+}
+
+namespace android {
+
+class CachedFrame;
+class CachedNode;
+class CachedRoot;
+
+class CacheBuilder {
+public:
+    enum Direction {
+        UNINITIALIZED = -1,
+        LEFT,
+        RIGHT,
+        UP,
+        DOWN,
+        DIRECTION_COUNT,
+        UP_DOWN = UP & DOWN,  // mask and result
+        RIGHT_DOWN = RIGHT & DOWN, // mask and result
+    };
+    enum FoundState {
+        FOUND_NONE,
+        FOUND_PARTIAL,
+        FOUND_COMPLETE
+    };
+    CacheBuilder();
+    void allowAllTextDetection() { mAllowableTypes = ALL_CACHEDNODE_BITS; }
+    void buildCache(CachedRoot* root);
+    static bool ConstructPartRects(Node* node, const IntRect& bounds, 
+        IntRect* focusBounds, int x, int y, WTF::Vector<IntRect>* result,
+        int* imageCountPtr);
+    Node* currentFocus() const;
+    void disallowAddressDetection() { mAllowableTypes = (CachedNodeBits) (
+        mAllowableTypes & ~ADDRESS_CACHEDNODE_BIT); }
+    void disallowEmailDetection() { mAllowableTypes = (CachedNodeBits) (
+        mAllowableTypes & ~EMAIL_CACHEDNODE_BIT); }
+    void disallowPhoneDetection() { mAllowableTypes = (CachedNodeBits) (
+        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);
+    bool pictureSetDisabled() { return mPictureSetDisabled; }
+    static bool validNode(Frame* startFrame, void* framePtr, void* nodePtr);
+private:
+    enum AddressProgress {
+        NO_ADDRESS,
+        SKIP_TO_SPACE,
+        HOUSE_NUMBER,
+        NUMBER_TRAILING_SPACE,
+        ADDRESS_LINE,
+        STATE_NAME,
+        SECOND_HALF,
+        ZIP_CODE,
+        PLUS_4,
+        FIND_STREET
+    };
+    struct NodeWalk {
+        NodeWalk() { reset(); }
+        int mStart;
+        int mEnd;
+        Node* mFinalNode;
+        InlineTextBox* mLastInline;
+        bool mMore;
+        void reset() { mMore = false; }
+    };
+    struct BoundsPart {
+        IntRect mRect;
+        int mStart;
+        int mEnd;
+    };
+    struct Bounds {
+        typedef bool (*FindText)(BoundsPart* result, InlineTextBox* , const String& match);
+        IntRect mNodeBounds;
+        BoundsPart mPart;
+        WTF::Vector<BoundsPart> mParts;   
+        char mStore[NAVIGATION_MAX_PHONE_LENGTH + 1];
+        int mPartIndex;
+        Node* mNode;
+        Node* mFinalNode;
+        void reset() { mNode = NULL; }
+    };
+    struct FindState {
+        int mStartResult;
+        int mEndResult;
+        const UChar* mCurrentStart;
+        const UChar* mEnd;
+        AddressProgress mProgress;
+        int mNumberCount;
+        int mLetterCount;
+        unsigned mWordCount;
+        int mLineCount;
+        const UChar* mFirstLower;
+        const UChar* mZipStart;
+        const UChar* mBases[16]; // FIXME: random guess, maybe too small, maybe too big
+        const UChar* mWords[16];
+        const UChar* mEnds[16];
+        const UChar* mStarts[16]; // text is not necessarily contiguous
+        const char* mStates;
+        int mEndWord;
+        int mStateWord;
+        int mZipHint;
+        int mSectionLength;
+        unsigned mNumberWords; // must contain as many bits as mWords contains elements
+        char* mPattern;
+        UChar mStore[NAVIGATION_MAX_PHONE_LENGTH + 1];
+        UChar* mStorePtr;
+        UChar mBackOne;
+        UChar mBackTwo;
+        UChar mCurrent;
+        bool mUnparsed;
+        bool mZipDelimiter;
+        bool mOpenParen;
+        bool mInitialized;
+        bool mContinuationNode;
+        bool mCaseInsensitive;
+        void shiftWords(int shift) {
+            memmove(mBases, &mBases[shift], (sizeof(mBases) /
+                sizeof(mBases[0]) - shift) * sizeof(mBases[0]));
+            memmove(mWords, &mWords[shift], (sizeof(mWords) /
+                sizeof(mWords[0]) - shift) * sizeof(mWords[0]));
+            memmove(mEnds, &mEnds[shift], (sizeof(mEnds) /
+                sizeof(mEnds[0]) - shift) * sizeof(mEnds[0]));
+            memmove(mStarts, &mStarts[shift], (sizeof(mStarts) /
+                sizeof(mStarts[0]) - shift) * sizeof(mStarts[0]));
+        }
+        void newWord(const UChar* baseChars, const UChar* chars) {
+            mBases[mWordCount] = baseChars;
+            mWords[mWordCount] = chars;
+            mEnds[mWordCount] = mEnd;
+            mStarts[mWordCount] = mCurrentStart;
+        }
+    };
+    struct Tracker {
+        Node* mLastChild;
+    };
+    struct ClipColumnTracker : Tracker {
+        Node* mNode;
+        IntRect mBounds;
+        ColumnInfo* mColumnInfo;
+        int mColumnGap;
+        TextDirection mDirection;
+        bool mHasClip;
+    };
+    struct LayerTracker : Tracker {
+        LayerAndroid* mLayer;
+        RenderLayer* mRenderLayer;
+        IntRect mBounds;
+        IntPoint mScroll;
+        ~LayerTracker();
+    };
+    struct TabIndexTracker : Tracker {
+        int mTabIndex;
+    };
+    struct FocusTracker : TabIndexTracker {
+        int mCachedNodeIndex;
+        bool mSomeParentTakesFocus;
+    };
+    void adjustForColumns(const ClipColumnTracker& track, 
+        CachedNode* node, IntRect* bounds, RenderBlock*);
+    static bool AddPartRect(IntRect& bounds, int x, int y,
+        WTF::Vector<IntRect>* result, IntRect* focusBounds);
+    static bool AnyIsClick(Node* node);
+    static bool AnyChildIsClick(Node* node);
+    static bool NodeHasEventListeners(Node* node, AtomicString* eventTypes, int length);
+    void BuildFrame(Frame* root, Frame* frame,
+        CachedRoot* cachedRoot, 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, 
+        IntRect* focusBounds, const IntRect& clip, WTF::Vector<IntRect>* result);
+    static bool ConstructTextRects(Text* node, int start, 
+        Text* last, int end, int x, int y, IntRect* focusBounds, 
+        const IntRect& clip, WTF::Vector<IntRect>* result);
+    static FoundState FindPartialAddress(const UChar* , const UChar* , unsigned length, FindState* );
+    static FoundState FindPartialEMail(const UChar* , unsigned length, FindState* );
+    static FoundState FindPartialNumber(const UChar* , unsigned length, FindState* );
+    static FoundState FindPhoneNumber(const UChar* chars, unsigned length, int* start, int* end);
+    static void FindReset(FindState* );
+    static void FindResetNumber(FindState* );
+    static Frame* FrameAnd(CacheBuilder* focusNav);
+    static Frame* FrameAnd(const CacheBuilder* focusNav);
+    static CacheBuilder* Builder(Frame* );
+    static Frame* HasFrame(Node* );
+    static bool HasOverOrOut(Node* );
+    static bool HasTriggerEvent(Node* );
+    static bool IsDomainChar(UChar ch);
+    bool isFocusableText(NodeWalk* , bool oldMore, Node* , CachedNodeType* type,
+        String* exported) const; //returns true if it is focusable
+    static bool IsMailboxChar(UChar ch);
+    static bool IsRealNode(Frame* , Node* );
+    int overlap(int left, int right); // returns distance scale factor as 16.16 scalar
+    bool setData(CachedFrame* );
+#if USE(ACCELERATED_COMPOSITING)
+    void TrackLayer(WTF::Vector<LayerTracker>& layerTracker,
+        RenderObject* nodeRenderer, Node* lastChild, int offsetX, int offsetY);
+#endif
+    Node* tryFocus(Direction direction);
+    Node* trySegment(Direction direction, int mainStart, int mainEnd);
+    CachedNodeBits mAllowableTypes;
+    bool mPictureSetDisabled;
+#if DUMP_NAV_CACHE
+public:
+    class Debug {
+public:
+        void frameName(char*& namePtr, const char* max) const;
+        void init(char* buffer, size_t size);
+        static int ParentIndex(Node* node, int count, Node* parent);
+        void print() { frames(); }
+        void print(const char* name);
+        void wideString(const String& str);
+private:
+        void attr(const AtomicString& name, const AtomicString& value);
+        void comma(const char* str);
+        void flush();
+        Frame* frameAnd() const;
+        void frames();
+        void groups();
+        bool isFocusable(Node* node);
+        void localName(Node* node);
+        void newLine(int indent = 0);
+        void print(const char* name, unsigned len);
+        void setIndent(int );
+        void uChar(const UChar* name, unsigned len, bool hex);
+        void validateFrame();
+        void validateStringData();
+        void wideString(const UChar* chars, int length, bool hex);
+        char* mBuffer;
+        size_t mBufferSize;
+        int mIndex;
+        const char* mPrefix;
+        int mMinPrefix;
+    } mDebug;
+#endif
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/graphics/android/rendering/TextureOwner.h b/Source/WebKit/android/nav/CachedColor.cpp
similarity index 60%
copy from Source/WebCore/platform/graphics/android/rendering/TextureOwner.h
copy to Source/WebKit/android/nav/CachedColor.cpp
index b12d8b7..c610022 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TextureOwner.h
+++ b/Source/WebKit/android/nav/CachedColor.cpp
@@ -23,25 +23,36 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef TextureOwner_h
-#define TextureOwner_h
+#include "CachedPrefix.h"
+#include "CachedColor.h"
 
-class SkCanvas;
-class Layer;
+namespace android {
 
-namespace WebCore {
+#if DUMP_NAV_CACHE
 
-class TileTexture;
-class GLWebViewState;
+#define DEBUG_PRINT_COLOR(field) \
+    DUMP_NAV_LOGD("// SkColor " #field "=0x%08x;\n", b->field)
 
-class TextureOwner {
-public:
-    virtual ~TextureOwner() { }
-    virtual bool removeTexture(TileTexture* texture) = 0;
-    virtual bool isRepaintPending() = 0;
-    virtual unsigned long long drawCount() = 0;
-};
+CachedColor* CachedColor::Debug::base() const {
+    CachedColor* nav = (CachedColor*) ((char*) this - OFFSETOF(CachedColor, mDebug));
+    return nav;
+}
+
+void CachedColor::Debug::print() const
+{
+    CachedColor* b = base();
+    DEBUG_PRINT_COLOR(mFillColor);
+    DUMP_NAV_LOGD("// int mInnerWidth=%d;\n", b->mInnerWidth);
+    DUMP_NAV_LOGD("// int mOuterWidth=%d;\n", b->mOuterWidth);
+    DUMP_NAV_LOGD("// int mOutset=%d;\n", b->mOutset);
+    DEBUG_PRINT_COLOR(mPressedInnerColor);
+    DEBUG_PRINT_COLOR(mPressedOuterColor);
+    DUMP_NAV_LOGD("// int mRadius=%d;\n", b->mRadius);
+    DEBUG_PRINT_COLOR(mSelectedInnerColor);
+    DEBUG_PRINT_COLOR(mSelectedOuterColor);
+}
+
+#endif
 
 }
 
-#endif // TextureOwner_h
diff --git a/Source/WebKit/android/nav/CachedColor.h b/Source/WebKit/android/nav/CachedColor.h
new file mode 100644
index 0000000..2ba9b18
--- /dev/null
+++ b/Source/WebKit/android/nav/CachedColor.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CachedColor_h
+#define CachedColor_h
+
+#include "CachedDebug.h"
+#include "Color.h"
+#include "Length.h"
+#include "SkColor.h"
+
+using namespace WebCore;
+
+namespace android {
+
+class CachedColor {
+public:
+    CachedColor() {
+        // Initiaized to 0 in its array, so nothing to do in the
+        // constructor
+    }
+    bool operator==(const CachedColor& o) const {
+        return memcmp(&o, this, sizeof(this)) == 0; }
+    SkColor fillColor() const { return mFillColor; }
+    void init();
+    int innerWidth() const { return mInnerWidth; }
+    int outerWidth() const { return mOuterWidth; }
+    int outset() const { return mOutset; }
+    SkColor pressedInnerColor() const { return mPressedInnerColor; }
+    SkColor pressedOuterColor() const { return mPressedOuterColor; }
+    int radius() const { return mRadius; }
+    SkColor selectedInnerColor() const { return mSelectedInnerColor; }
+    SkColor selectedOuterColor() const { return mSelectedOuterColor; }
+    void setFillColor(const Color& c) { mFillColor = c.rgb(); }
+    void setInnerWidth(Length l) { mInnerWidth = l.value(); }
+    void setOuterWidth(Length l) { mOuterWidth = l.value(); }
+    void setOutset(Length l) { mOutset = l.value(); }
+    void setPressedInnerColor(const Color& c) { mPressedInnerColor = c.rgb(); }
+    void setPressedOuterColor(const Color& c) { mPressedOuterColor = c.rgb(); }
+    void setRadius(Length l) { mRadius = l.value(); }
+    void setSelectedInnerColor(const Color& c) { mSelectedInnerColor = c.rgb(); }
+    void setSelectedOuterColor(const Color& c) { mSelectedOuterColor = c.rgb(); }
+private:
+    SkColor mFillColor;
+    int mInnerWidth;
+    int mOuterWidth;
+    int mOutset;
+    SkColor mPressedInnerColor;
+    SkColor mPressedOuterColor;
+    int mRadius;
+    SkColor mSelectedInnerColor;
+    SkColor mSelectedOuterColor;
+#if DUMP_NAV_CACHE
+public:
+    class Debug {
+public:
+        CachedColor* base() const;
+        void print() const;
+    } mDebug;
+#endif
+};
+
+}
+
+#endif
diff --git a/Source/WebKit/android/nav/CachedDebug.h b/Source/WebKit/android/nav/CachedDebug.h
new file mode 100644
index 0000000..f77c07a
--- /dev/null
+++ b/Source/WebKit/android/nav/CachedDebug.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2007, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CachedDebug_h
+#define CachedDebug_h
+
+#define DUMP_NAV_CACHE 0
+#define DEBUG_NAV_UI 0
+#define DEBUG_NAV_UI_VERBOSE 0
+
+#if DEBUG_NAV_UI
+#define DBG_NAV_LOG(message) LOGD("%s %s", __FUNCTION__, message)
+#define DBG_NAV_LOGD(format, ...) LOGD("%s " format, __FUNCTION__, __VA_ARGS__)
+#define DEBUG_NAV_UI_LOGD(...) LOGD(__VA_ARGS__)
+#else
+#define DBG_NAV_LOG(message) ((void)0)
+#define DBG_NAV_LOGD(format, ...) ((void)0)
+#define DEBUG_NAV_UI_LOGD(...) ((void)0)
+#endif
+
+#if DEBUG_NAV_UI_VERBOSE
+#define DBG_NAV_LOGV(format, ...) LOGD("%s " format, __FUNCTION__, __VA_ARGS__)
+#else
+#define DBG_NAV_LOGV(format, ...) ((void)0)
+#endif
+
+#if DUMP_NAV_CACHE != 0 && !defined DUMP_NAV_CACHE_USING_PRINTF && defined NDEBUG
+#define DUMP_NAV_CACHE_USING_PRINTF
+#endif
+
+#if DUMP_NAV_CACHE
+#ifdef DUMP_NAV_CACHE_USING_PRINTF
+#include <stdio.h>
+extern FILE* gNavCacheLogFile;
+#define NAV_CACHE_LOG_FILE "/data/data/com.android.browser/navlog"
+#define DUMP_NAV_LOGD(...) do { if (gNavCacheLogFile) \
+    fprintf(gNavCacheLogFile, __VA_ARGS__); else LOGD(__VA_ARGS__); } while (false)
+#define DUMP_NAV_LOGX(format, ...) do { if (gNavCacheLogFile) \
+    fprintf(gNavCacheLogFile, format, __VA_ARGS__); \
+    else LOGD("%s " format, __FUNCTION__, __VA_ARGS__); } while (false)
+#else
+#define DUMP_NAV_LOGD(...) LOGD(__VA_ARGS__)
+#define DUMP_NAV_LOGX(format, ...) LOGD("%s " format, __FUNCTION__, __VA_ARGS__)
+#endif
+#else
+#define DUMP_NAV_LOGD(...) ((void)0)
+#define DUMP_NAV_LOGX(...) ((void)0)
+#endif
+
+#endif
diff --git a/Source/WebKit/android/nav/CachedFrame.cpp b/Source/WebKit/android/nav/CachedFrame.cpp
new file mode 100644
index 0000000..c51944e
--- /dev/null
+++ b/Source/WebKit/android/nav/CachedFrame.cpp
@@ -0,0 +1,1511 @@
+/*
+ * Copyright 2007, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CachedPrefix.h"
+#include "CachedHistory.h"
+#include "CachedNode.h"
+#include "CachedRoot.h"
+#include "LayerAndroid.h"
+
+#include "CachedFrame.h"
+
+#define OFFSETOF(type, field) ((char*)&(((type*)1)->field) - (char*)1) // avoids gnu warning
+
+#define MIN_OVERLAP 3 // if rects overlap by 2 pixels or fewer, treat them as non-intersecting
+
+namespace android {
+
+WebCore::IntRect CachedFrame::adjustBounds(const CachedNode* node,
+    const WebCore::IntRect& rect) const
+{
+    DBG_NAV_LOGV("node=%p [%d] rect=(%d,%d,w=%d,h=%d) view=(%d,%d,w=%d,h=%d)"
+        " local=(%d,%d,w=%d,h=%d) root=(%d,%d,w=%d,h=%d)",
+        node, node->index(), rect.x(), rect.y(), rect.width(), rect.height(),
+        mViewBounds.x(), mViewBounds.y(),
+        mViewBounds.width(), mViewBounds.height(),
+        mLocalViewBounds.x(), mLocalViewBounds.y(),
+        mLocalViewBounds.width(), mLocalViewBounds.height(),
+        mRoot->mViewBounds.x(), mRoot->mViewBounds.y(),
+        mRoot->mViewBounds.width(), mRoot->mViewBounds.height());
+#if USE(ACCELERATED_COMPOSITING)
+    if (!mRoot)
+        return rect;
+
+    const CachedLayer* cachedLayer = layer(node);
+    if (!cachedLayer)
+        return rect;
+
+    const WebCore::LayerAndroid* rootLayer = mRoot->rootLayer();
+    const LayerAndroid* aLayer = cachedLayer->layer(rootLayer);
+    if (aLayer)
+        return cachedLayer->adjustBounds(rootLayer, rect);
+#endif
+    return rect;
+}
+
+bool CachedFrame::CheckBetween(Direction direction, const WebCore::IntRect& bestRect,
+        const WebCore::IntRect& prior, WebCore::IntRect* result)
+{
+    int left, top, width, height;
+    if (direction & UP_DOWN) {
+        top = direction == UP ? bestRect.maxY() : prior.maxY();
+        int bottom = direction == UP ? prior.y() : bestRect.y();
+        height = bottom - top;
+        if (height < 0)
+            return false;
+        left = prior.x();
+        int testLeft = bestRect.x();
+        if (left > testLeft)
+            left = testLeft;
+        int right = prior.maxX();
+        int testRight = bestRect.maxX();
+        if (right < testRight)
+            right = testRight;
+        width = right - left;
+    } else {
+        left = direction == LEFT ? bestRect.maxX() : prior.maxX();
+        int right = direction == LEFT ? prior.x() : bestRect.x();
+        width = right - left;
+        if (width < 0)
+            return false;
+        top = prior.y();
+        int testTop = bestRect.y();
+        if (top > testTop)
+            top = testTop;
+        int bottom = prior.maxY();
+        int testBottom = bestRect.maxY();
+        if (bottom < testBottom)
+            bottom = testBottom;
+        height = bottom - top;
+    }
+    *result = WebCore::IntRect(left, top, width, height);
+    return true;
+}
+
+bool CachedFrame::checkBetween(BestData* best, Direction direction)
+{
+    const WebCore::IntRect& bestRect = best->bounds();
+    BestData test;
+    test.mDistance = INT_MAX;
+    test.mNode = NULL;
+    int index = direction;
+    int limit = index + DIRECTION_COUNT;
+    do {
+        WebCore::IntRect edges;
+        Direction check = (Direction) (index & DIRECTION_MASK);
+        if (CheckBetween(check, bestRect,
+                history()->priorBounds(), &edges) == false)
+            continue;
+        WebCore::IntRect clip = mRoot->scrolledBounds();
+        clip.intersect(edges);
+        if (clip.isEmpty())
+            continue;
+        findClosest(&test, direction, check, &clip);
+        if (test.mNode == NULL)
+            continue;
+        if (direction == check)
+            break;
+    } while (++index < limit);
+    if (test.mNode == NULL)
+        return false;
+    *best = test;
+    return true;
+}
+
+bool CachedFrame::checkRings(const CachedNode* node,
+        const WebCore::IntRect& testBounds) const
+{
+    return mRoot->checkRings(picture(node), node, testBounds);
+}
+
+bool CachedFrame::checkVisited(const CachedNode* node, Direction direction) const
+{
+    return history()->checkVisited(node, direction);
+}
+
+void CachedFrame::clearCursor()
+{
+    DBG_NAV_LOGD("mCursorIndex=%d", mCursorIndex);
+    if (mCursorIndex < CURSOR_SET)
+        return;
+    CachedNode& cursor = mCachedNodes[mCursorIndex];
+    cursor.clearCursor(this);
+    mCursorIndex = CURSOR_CLEARED; // initialized and explicitly cleared
+}
+
+// returns 0 if test is preferable to best, 1 if not preferable, or -1 if unknown
+int CachedFrame::compare(BestData& testData, const BestData& bestData) const
+{
+    if (testData.mNode->tabIndex() != bestData.mNode->tabIndex()) {
+        if (testData.mNode->tabIndex() < bestData.mNode->tabIndex()
+                || (mRoot->mCursor && mRoot->mCursor->tabIndex() < bestData.mNode->tabIndex())) {
+            testData.mNode->setCondition(CachedNode::HIGHER_TAB_INDEX);
+            return REJECT_TEST;
+        }
+        return TEST_IS_BEST;
+    }
+    // if the test minor axis line intersects the line segment between cursor
+    // center and best center, choose it
+    // give more weight to exact major axis alignment (rows, columns)
+    if (testData.mInNav != bestData.mInNav) {
+        if (bestData.mInNav) {
+            testData.mNode->setCondition(CachedNode::IN_CURSOR);
+            return REJECT_TEST;
+        }
+        return TEST_IS_BEST;
+    }
+    if (testData.mInNav) {
+        if (bestData.mMajorDelta < testData.mMajorDelta) {
+            testData.mNode->setCondition(CachedNode::CLOSER_IN_CURSOR);
+            return REJECT_TEST;
+        }
+        if (testData.mMajorDelta < bestData.mMajorDelta)
+            return TEST_IS_BEST;
+    }
+    if (testData.mMajorDelta < 0 && bestData.mMajorDelta >= 0) {
+        testData.mNode->setCondition(CachedNode::FURTHER);
+        return REJECT_TEST;
+    }
+    if ((testData.mMajorDelta ^ bestData.mMajorDelta) < 0) // one above, one below (or one left, one right)
+        return TEST_IS_BEST;
+    bool bestInWorking = bestData.inOrSubsumesWorking();
+    bool testInWorking = testData.inOrSubsumesWorking();
+    if (bestInWorking && testData.mWorkingOutside && testData.mNavOutside) {
+        testData.mNode->setCondition(CachedNode::IN_WORKING);
+        return REJECT_TEST;
+    }
+    if (testInWorking && bestData.mWorkingOutside && bestData.mNavOutside)
+        return TEST_IS_BEST;
+    bool bestInNav = directionChange() && bestData.inOrSubsumesNav();
+    bool testInNav = directionChange() && testData.inOrSubsumesNav();
+    if (bestInWorking == false && testInWorking == false) {
+        if (bestInNav && testData.mNavOutside) {
+            testData.mNode->setCondition(CachedNode::IN_UMBRA);
+            return REJECT_TEST;
+        }
+        if (testInNav && bestData.mNavOutside)
+            return TEST_IS_BEST;
+    }
+#if 01 // hopefully butt test will remove need for this
+    if (testData.mCursorChild != bestData.mCursorChild) {
+        if (bestData.mCursorChild) {
+            testData.mNode->setCondition(CachedNode::IN_CURSOR_CHILDREN);
+            return REJECT_TEST;
+        }
+        return TEST_IS_BEST;
+    }
+#endif
+    bool bestTestIn = (bestInWorking || bestInNav) && (testInWorking || testInNav);
+    bool testOverlap = bestTestIn || (testData.mWorkingOverlap != 0 && bestData.mWorkingOverlap == 0);
+    bool bestOverlap = bestTestIn || (testData.mWorkingOverlap == 0 && bestData.mWorkingOverlap != 0);
+#if 01 // this isn't working?
+    if (testOverlap == bestOverlap) {
+        if (bestData.mMajorButt < 10 && testData.mMajorButt >= 40) {
+            testData.mNode->setCondition(CachedNode::BUTTED_UP);
+            return REJECT_TEST;
+        }
+        if (testData.mMajorButt < 10 && bestData.mMajorButt >= 40)
+            return TEST_IS_BEST;
+    }
+#endif
+    if (bestOverlap && bestData.mMajorDelta < testData.mMajorDelta) { // choose closest major axis center
+        testData.mNode->setCondition(CachedNode::CLOSER);
+        return REJECT_TEST;
+    }
+    if (testOverlap && testData.mMajorDelta < bestData.mMajorDelta)
+        return TEST_IS_BEST;
+    if (bestOverlap && bestData.mMajorDelta2 < testData.mMajorDelta2) {
+        testData.mNode->setCondition(CachedNode::CLOSER_TOP);
+        return REJECT_TEST;
+    }
+    if (testOverlap && testData.mMajorDelta2 < bestData.mMajorDelta2)
+        return TEST_IS_BEST;
+#if 01
+    if (bestOverlap && ((bestData.mSideDistance <= 0 && testData.mSideDistance > 0) ||
+            abs(bestData.mSideDistance) < abs(testData.mSideDistance))) {
+        testData.mNode->setCondition(CachedNode::LEFTMOST);
+        return REJECT_TEST;
+    }
+    if (testOverlap && ((testData.mSideDistance <= 0 && bestData.mSideDistance > 0) ||
+            abs(testData.mSideDistance) < abs(bestData.mSideDistance)))
+        return TEST_IS_BEST;
+// fix me : the following ASSERT fires -- not sure if this case should be handled or not
+//    ASSERT(bestOverlap == false && testOverlap == false);
+#endif
+    SkFixed testMultiplier = testData.mWorkingOverlap > testData.mNavOverlap ?
+        testData.mWorkingOverlap : testData.mNavOverlap;
+    SkFixed bestMultiplier = bestData.mWorkingOverlap > bestData.mNavOverlap ?
+        bestData.mWorkingOverlap : bestData.mNavOverlap;
+    int testDistance = testData.mDistance;
+    int bestDistance = bestData.mDistance;
+//    start here;
+    // this fails if they're off by 1
+    // try once again to implement sliding scale so that off by 1 is nearly like zero,
+    // and off by a lot causes sideDistance to have little or no effect
+        // try elliptical distance -- lengthen side contribution
+        // these ASSERTs should not fire, but do fire on mail.google.com
+        // can't debug yet, won't reproduce
+    ASSERT(testDistance >= 0);
+    ASSERT(bestDistance >= 0);
+    testDistance += testDistance; // multiply by 2
+    testDistance *= testDistance;
+    bestDistance += bestDistance; // multiply by 2
+    bestDistance *= bestDistance;
+    int side = testData.mSideDistance;
+    int negative = side < 0 && bestData.mSideDistance > 0;
+    side *= side;
+    if (negative)
+        side = -side;
+    testDistance += side;
+    side = bestData.mSideDistance;
+    negative = side < 0 && testData.mSideDistance > 0;
+    side *= side;
+    if (negative)
+        side = -side;
+    bestDistance += side;
+    if (testMultiplier > (SK_Fixed1 >> 1) || bestMultiplier > (SK_Fixed1 >> 1)) { // considerable working overlap?
+       testDistance = SkFixedMul(testDistance, bestMultiplier);
+       bestDistance = SkFixedMul(bestDistance, testMultiplier);
+    }
+    if (bestDistance < testDistance) {
+        testData.mNode->setCondition(CachedNode::CLOSER_OVERLAP);
+        return REJECT_TEST;
+    }
+    if (testDistance < bestDistance)
+        return TEST_IS_BEST;
+#if 0
+    int distance = testData.mDistance + testData.mSideDistance;
+    int best = bestData.mDistance + bestData.mSideDistance;
+    if (distance > best) {
+        testData.mNode->setCondition(CachedNode::CLOSER_RAW_DISTANCE);
+        return REJECT_TEST;
+    }
+    else if (distance < best)
+        return TEST_IS_BEST;
+    best = bestData.mSideDistance;
+    if (testData.mSideDistance > best) {
+        testData.mNode->setCondition(CachedNode::SIDE_DISTANCE);
+        return REJECT_TEST;
+    }
+    if (testData.mSideDistance < best)
+        return TEST_IS_BEST;
+#endif
+    if (testData.mPreferred < bestData.mPreferred) {
+        testData.mNode->setCondition(CachedNode::PREFERRED);
+        return REJECT_TEST;
+    }
+    if (testData.mPreferred > bestData.mPreferred)
+        return TEST_IS_BEST;
+    return UNDECIDED;
+}
+
+const CachedNode* CachedFrame::currentCursor(const CachedFrame** framePtr) const
+{
+    if (framePtr)
+        *framePtr = this;
+    if (mCursorIndex < CURSOR_SET)
+        return NULL;
+    const CachedNode* result = &mCachedNodes[mCursorIndex];
+    const CachedFrame* frame = hasFrame(result);
+    if (frame != NULL)
+        return frame->currentCursor(framePtr);
+    (const_cast<CachedNode*>(result))->fixUpCursorRects(this);
+    return result;
+}
+
+const CachedNode* CachedFrame::currentFocus(const CachedFrame** framePtr) const
+{
+    if (framePtr)
+        *framePtr = this;
+    if (mFocusIndex < 0)
+        return NULL;
+    const CachedNode* result = &mCachedNodes[mFocusIndex];
+    const CachedFrame* frame = hasFrame(result);
+    if (frame != NULL)
+        return frame->currentFocus(framePtr);
+    return result;
+}
+
+bool CachedFrame::directionChange() const
+{
+    return history()->directionChange();
+}
+
+#ifdef BROWSER_DEBUG
+CachedNode* CachedFrame::find(WebCore::Node* node) // !!! probably debugging only
+{
+    for (CachedNode* test = mCachedNodes.begin(); test != mCachedNodes.end(); test++)
+        if (node == test->webCoreNode())
+            return test;
+    for (CachedFrame* frame = mCachedFrames.begin(); frame != mCachedFrames.end();
+            frame++) {
+        CachedNode* result = frame->find(node);
+        if (result != NULL)
+            return result;
+    }
+    return NULL;
+}
+#endif
+
+const CachedNode* CachedFrame::findBestAt(const WebCore::IntRect& rect,
+    int* best, bool* inside, const CachedNode** directHit,
+    const CachedFrame** directHitFramePtr,
+    const CachedFrame** framePtr, int* x, int* y,
+    bool checkForHiddenStart) const
+{
+    const CachedNode* result = NULL;
+    int rectWidth = rect.width();
+    WebCore::IntPoint center = WebCore::IntPoint(rect.x() + (rectWidth >> 1),
+        rect.y() + (rect.height() >> 1));
+    mRoot->setupScrolledBounds();
+    for (const CachedNode* test = mCachedNodes.begin(); test != mCachedNodes.end(); test++) {
+        if (test->disabled())
+            continue;
+        size_t parts = test->navableRects();
+        BestData testData;
+        testData.mNode = test;
+        testData.mFrame = this;
+        WebCore::IntRect bounds = test->bounds(this);
+        testData.setMouseBounds(bounds);
+        testData.setNodeBounds(bounds);
+        bool checkForHidden = checkForHiddenStart;
+        for (size_t part = 0; part < parts; part++) {
+            WebCore::IntRect testRect = test->ring(this, part);
+            if (testRect.intersects(rect)) {
+#if DEBUG_NAV_UI
+                if (test->isInLayer()) {
+                    DBG_NAV_LOGD("[%d] intersects=%s testRect=(%d,%d,w=%d,h=%d)"
+                        " rect=(%d,%d,w=%d,h=%d)", test->index(),
+                        testRect.intersects(rect) ? "true" : "false",
+                        testRect.x(), testRect.y(),
+                        testRect.width(), testRect.height(),
+                        rect.x(), rect.y(), rect.width(), rect.height());
+                }
+#endif
+                if (checkForHidden && mRoot->maskIfHidden(&testData) == true) {
+                    DBG_NAV_LOGD("hidden [%d]", test->index());
+                    break;
+                }
+                checkForHidden = false;
+                testRect.intersect(testData.mouseBounds());
+                if (testRect.contains(center)) {
+                    // We have a direct hit.
+                    if (*directHit == NULL) {
+                        DBG_NAV_LOGD("direct hit 1 [%d]", test->index());
+                        *directHit = test;
+                        *directHitFramePtr = this;
+                        IntRect r(center, IntSize(0, 0));
+                        *x = r.x();
+                        *y = r.y();
+                    } else {
+                        DBG_NAV_LOGD("direct hit 2 [%d]", test->index());
+                        // We have hit another one before
+                        const CachedNode* d = *directHit;
+                        if (d->bounds(this).contains(testRect)) {
+                            // This rectangle is inside the other one, so it is
+                            // the best one.
+                            *directHit = test;
+                            *directHitFramePtr = this;
+                        }
+                    }
+                }
+                if (NULL != *directHit) {
+                    // If we have a direct hit already, there is no need to
+                    // calculate the distances, or check the other parts
+                    break;
+                }
+                DBG_NAV_LOGD("indirect hit [%d]", test->index());
+                WebCore::IntRect both = rect;
+                int smaller = testRect.width() < testRect.height() ?
+                    testRect.width() : testRect.height();
+                smaller -= rectWidth;
+                int inset = smaller < rectWidth ? smaller : rectWidth;
+                inset >>= 1; // inflate doubles the width decrease
+                if (inset > 1)
+                    both.inflate(1 - inset);
+                both.intersect(testRect);
+                if (both.isEmpty())
+                    continue;
+                bool testInside = testRect.contains(center);
+                if (*inside && !testInside)
+                    continue;
+                WebCore::IntPoint testCenter = WebCore::IntPoint(testRect.x() +
+                    (testRect.width() >> 1), testRect.y() + (testRect.height() >> 1));
+                int dx = testCenter.x() - center.x();
+                int dy = testCenter.y() - center.y();
+                int distance = dx * dx + dy * dy;
+                if ((!*inside && testInside) || *best >= distance) {
+                    *best = distance;
+                    *inside = testInside;
+                    result = test;
+                    *framePtr = this;
+                    *x = both.x() + (both.width() >> 1);
+                    *y = both.y() + (both.height() >> 1);
+                }
+            }
+        }
+    }
+    for (const CachedFrame* frame = mCachedFrames.begin();
+            frame != mCachedFrames.end(); frame++) {
+        const CachedNode* frameResult = frame->findBestAt(rect, best, inside,
+            directHit, directHitFramePtr, framePtr, x, y, checkForHiddenStart);
+        if (NULL != frameResult)
+            result = frameResult;
+    }
+    if (NULL != *directHit) {
+        result = *directHit;
+        *framePtr = *directHitFramePtr;
+    }
+    return result;
+}
+
+const CachedFrame* CachedFrame::findBestFrameAt(int x, int y) const
+{
+    if (mLocalViewBounds.contains(x, y) == false)
+        return NULL;
+    const CachedFrame* result = this;
+    for (const CachedFrame* frame = mCachedFrames.begin();
+            frame != mCachedFrames.end(); frame++) {
+        const CachedFrame* frameResult = frame->findBestFrameAt(x, y);
+        if (NULL != frameResult)
+            result = frameResult;
+    }
+    return result;
+}
+
+const CachedNode* CachedFrame::findBestHitAt(const WebCore::IntRect& rect,
+    const CachedFrame** framePtr, int* x, int* y) const
+{
+    mRoot->setupScrolledBounds();
+    for (const CachedFrame* frame = mCachedFrames.end() - 1;
+            frame != mCachedFrames.begin() - 1; frame--) {
+        const CachedNode* frameResult = frame->findBestHitAt(rect,
+            framePtr, x, y);
+        if (NULL != frameResult)
+            return frameResult;
+    }
+    for (const CachedNode* test = mCachedNodes.end() - 1;
+            test != mCachedNodes.begin() - 1; test--) {
+        if (test->disabled())
+            continue;
+        WebCore::IntRect testRect = test->hitBounds(this);
+        if (testRect.intersects(rect) == false)
+            continue;
+        BestData testData;
+        testData.mNode = test;
+        testData.mFrame = this;
+        testData.setMouseBounds(testRect);
+        testData.setNodeBounds(testRect);
+        if (mRoot->maskIfHidden(&testData) == true)
+            continue;
+        DBG_NAV_LOGD("candidate %d rect=(%d,%d,r=%d,b=%d)"
+            " testRect=(%d,%d,r=%d,b=%d)",
+            test->index(), rect.x(), rect.y(), rect.maxX(), rect.maxY(),
+            testRect.x(), testRect.y(), testRect.maxX(), testRect.maxY());
+        for (int i = 0; i < test->navableRects(); i++) {
+            WebCore::IntRect cursorRect = test->ring(this, i);
+            DBG_NAV_LOGD("candidate %d cursorRect=(%d,%d,r=%d,b=%d)",
+                i, cursorRect.x(), cursorRect.y(), cursorRect.maxX(),
+                cursorRect.maxY());
+            if (cursorRect.intersects(rect)) {
+                WebCore::IntRect intersection(cursorRect);
+                intersection.intersect(rect);
+                *x = intersection.x() + (intersection.width() >> 1);
+                *y = intersection.y() + (intersection.height() >> 1);
+                *framePtr = this;
+                return test;
+            }
+        }
+        testRect.intersect(rect);
+        *x = testRect.x() + (testRect.width() >> 1);
+        *y = testRect.y() + (testRect.height() >> 1);
+        *framePtr = this;
+        return test;
+    }
+    return NULL;
+}
+
+void CachedFrame::findClosest(BestData* bestData, Direction originalDirection,
+    Direction direction, WebCore::IntRect* clip) const
+{
+    const CachedNode* test = mCachedNodes.begin();
+    while ((test = test->traverseNextNode()) != NULL) {
+        const CachedFrame* child = hasFrame(test);
+        if (child != NULL) {
+            const CachedNode* childDoc = child->validDocument();
+            if (childDoc == NULL)
+                continue;
+            child->findClosest(bestData, originalDirection, direction, clip);
+        }
+        if (test->noSecondChance())
+            continue;
+        if (test->isNavable(this, *clip) == false)
+            continue;
+        if (checkVisited(test, originalDirection) == false)
+            continue;
+        size_t partMax = test->navableRects();
+        for (size_t part = 0; part < partMax; part++) {
+            WebCore::IntRect testBounds = test->ring(this, part);
+            if (clip->intersects(testBounds) == false)
+                continue;
+            if (clip->contains(testBounds) == false) {
+                if (direction & UP_DOWN) {
+//                    if (testBounds.x() > clip->x() || testBounds.right() < clip->right())
+//                        continue;
+                    testBounds.setX(clip->x());
+                    testBounds.setWidth(clip->width());
+                } else {
+//                    if (testBounds.y() > clip->y() || testBounds.bottom() < clip->bottom())
+//                        continue;
+                    testBounds.setY(clip->y());
+                    testBounds.setHeight(clip->height());
+                }
+                if (clip->contains(testBounds) == false)
+                    continue;
+            }
+            int distance;
+            // seems like distance for UP for instance needs to be 'test top closest to
+            // clip bottom' -- keep the old code but try this instead
+            switch (direction) {
+#if 0
+            case LEFT:
+                distance = testBounds.x() - clip->x();
+                break;
+            case RIGHT:
+                distance = clip->right() - testBounds.right();
+                break;
+            case UP:
+                distance = testBounds.y() - clip->y();
+                break;
+            case DOWN:
+                distance = clip->bottom() - testBounds.bottom();
+                break;
+#else
+            case LEFT:
+                distance = clip->maxX() - testBounds.x();
+                break;
+            case RIGHT:
+                distance = testBounds.maxX() - clip->x();
+                break;
+            case UP:
+                distance = clip->maxY() - testBounds.y();
+                break;
+            case DOWN:
+                distance = testBounds.maxY() - clip->y();
+                break;
+#endif
+            default:
+                distance = 0;
+                ASSERT(false);
+            }
+            if (distance < bestData->mDistance) {
+                bestData->mNode = test;
+                bestData->mFrame = this;
+                bestData->mDistance = distance;
+                WebCore::IntRect rect = test->ring(this, part);
+                bestData->setMouseBounds(rect);
+                bestData->setNodeBounds(rect);
+                CachedHistory* cachedHistory = history();
+                switch (direction) {
+                    case LEFT:
+                        bestData->setLeftDirection(cachedHistory);
+                    break;
+                    case RIGHT:
+                        bestData->setRightDirection(cachedHistory);
+                    break;
+                    case UP:
+                        bestData->setUpDirection(cachedHistory);
+                    break;
+                    case DOWN:
+                        bestData->setDownDirection(cachedHistory);
+                    break;
+                    default:
+                        ASSERT(0);
+                }
+            }
+        }
+    }
+}
+
+void CachedFrame::finishInit()
+{
+    CachedNode* lastCached = lastNode();
+    lastCached->setLast();
+    CachedFrame* child = mCachedFrames.begin();
+    while (child != mCachedFrames.end()) {
+        child->mParent = this;
+        child->finishInit();
+        child++;
+    }
+    CachedFrame* frameParent;
+    if (mFocusIndex >= 0 && (frameParent = parent()))
+        frameParent->setFocusIndex(indexInParent());
+}
+
+const CachedNode* CachedFrame::frameDown(const CachedNode* test,
+    const CachedNode* limit, BestData* bestData) const
+{
+    BestData originalData = *bestData;
+    do {
+        if (moveInFrame(&CachedFrame::frameDown, test, bestData))
+            continue;
+        BestData testData;
+        if (frameNodeCommon(testData, test, bestData, &originalData) == REJECT_TEST)
+            continue;
+        if (checkVisited(test, DOWN) == false)
+            continue;
+        size_t parts = test->navableRects();
+        for (size_t part = 0; part < parts; part++) {
+            testData.setNodeBounds(test->ring(this, part));
+            if (testData.setDownDirection(history()))
+                continue;
+            int result = framePartCommon(testData, test, bestData);
+            if (result == REJECT_TEST)
+                continue;
+            if (result == 0 && limit == NULL) { // retry all data up to this point, since smaller may have replaced node preferable to larger
+                BestData innerData = testData;
+                frameDown(document(), test, &innerData);
+                if (checkVisited(innerData.mNode, DOWN)) {
+                    *bestData = innerData;
+                    continue;
+                }
+            }
+            if (checkVisited(test, DOWN))
+                *bestData = testData;
+        }
+    } while ((test = test->traverseNextNode()) != limit);
+    ASSERT(mRoot->mCursor == NULL || bestData->mNode != mRoot->mCursor);
+    // does the best contain something (or, is it contained by an area which is not the cursor?)
+        // if so, is the conainer/containee should have been chosen, but wasn't -- so there's a better choice
+        // in the doc list prior to this choice
+    //
+    return bestData->mNode;
+}
+
+const CachedNode* CachedFrame::frameLeft(const CachedNode* test,
+    const CachedNode* limit, BestData* bestData) const
+{
+    BestData originalData = *bestData;
+    do {
+        if (moveInFrame(&CachedFrame::frameLeft, test, bestData))
+            continue;
+        BestData testData;
+        if (frameNodeCommon(testData, test, bestData, &originalData) == REJECT_TEST)
+            continue;
+        if (checkVisited(test, LEFT) == false)
+            continue;
+        size_t parts = test->navableRects();
+        for (size_t part = 0; part < parts; part++) {
+            testData.setNodeBounds(test->ring(this, part));
+            if (testData.setLeftDirection(history()))
+                continue;
+            int result = framePartCommon(testData, test, bestData);
+            if (result == REJECT_TEST)
+                continue;
+            if (result == 0 && limit == NULL) { // retry all data up to this point, since smaller may have replaced node preferable to larger
+                BestData innerData = testData;
+                frameLeft(document(), test, &innerData);
+                if (checkVisited(innerData.mNode, LEFT)) {
+                    *bestData = innerData;
+                    continue;
+                }
+            }
+            if (checkVisited(test, LEFT))
+                *bestData = testData;
+        }
+    } while ((test = test->traverseNextNode()) != limit);  // FIXME ??? left and up should use traversePreviousNode to choose reverse document order
+    ASSERT(mRoot->mCursor == NULL || bestData->mNode != mRoot->mCursor);
+    return bestData->mNode;
+}
+
+int CachedFrame::frameNodeCommon(BestData& testData, const CachedNode* test,
+    BestData* bestData, BestData* originalData) const
+{
+    testData.mFrame = this;
+    testData.mNode = test;
+    test->clearCondition();
+    if (test->disabled()) {
+        testData.mNode->setCondition(CachedNode::DISABLED);
+        return REJECT_TEST;
+    }
+    WebCore::IntRect bounds = test->bounds(this);
+    if (bounds.isEmpty()) {
+        testData.mNode->setCondition(CachedNode::NAVABLE);
+        return REJECT_TEST;
+    }
+    if (mRoot->scrolledBounds().intersects(bounds) == false) {
+        testData.mNode->setCondition(CachedNode::NAVABLE);
+        return REJECT_TEST;
+    }
+    if (mRoot->rootLayer() && !test->isInLayer()
+            && !mRoot->baseUncovered().intersects(bounds)) {
+        testData.mNode->setCondition(CachedNode::UNDER_LAYER);
+        return REJECT_TEST;
+    }
+//    if (isNavable(test, &testData.mNodeBounds, walk) == false) {
+//        testData.mNode->setCondition(CachedNode::NAVABLE);
+//        return REJECT_TEST;
+//    }
+//
+    if (test == mRoot->mCursor) {
+        testData.mNode->setCondition(CachedNode::NOT_CURSOR_NODE);
+        return REJECT_TEST;
+    }
+//    if (test->bounds().contains(mRoot->mCursorBounds)) {
+//        testData.mNode->setCondition(CachedNode::NOT_ENCLOSING_CURSOR);
+//        return REJECT_TEST;
+//    }
+    void* par = mRoot->mCursor ? mRoot->mCursor->parentGroup() : NULL;
+    testData.mCursorChild = par ? test->parentGroup() == par : false;
+    if (bestData->mNode == NULL)
+        return TEST_IS_BEST;
+    if (mRoot->mCursor && testData.mNode->parentIndex() != bestData->mNode->parentIndex()) {
+        int cursorParentIndex = mRoot->mCursor->parentIndex();
+        if (cursorParentIndex >= 0) {
+            if (bestData->mNode->parentIndex() == cursorParentIndex)
+                return REJECT_TEST;
+            if (testData.mNode->parentIndex() == cursorParentIndex)
+                return TEST_IS_BEST;
+        }
+    }
+    if (testData.mNode->parent() == bestData->mNode) {
+        testData.mNode->setCondition(CachedNode::CHILD);
+        return REJECT_TEST;
+    }
+    if (testData.mNode == bestData->mNode->parent())
+        return TEST_IS_BEST;
+    int testInBest = testData.isContainer(bestData); /* -1 pick best over test, 0 no containership, 1 pick test over best */
+    if (testInBest == 1) {
+        if (test->isArea() || bestData->mNode->isArea())
+            return UNDECIDED;
+        bestData->mNode = NULL;    // force part tests to be ignored, yet still set up remaining test data for later comparisons
+        return TEST_IS_BEST;
+    }
+    if (testInBest == -1) {
+        testData.mNode->setCondition(CachedNode::OUTSIDE_OF_BEST);
+        return REJECT_TEST;
+    }
+    if (originalData->mNode != NULL) { // test is best case
+        testInBest = testData.isContainer(originalData);
+        if (testInBest == -1) { /* test is inside best */
+            testData.mNode->setCondition(CachedNode::OUTSIDE_OF_ORIGINAL);
+            return REJECT_TEST;
+        }
+    }
+    return UNDECIDED;
+}
+
+int CachedFrame::framePartCommon(BestData& testData,
+    const CachedNode* test, BestData* bestData) const
+{
+    if (mRoot->mCursor
+            && testData.bounds().contains(mRoot->mCursorBounds)
+            && !test->wantsKeyEvents()) {
+        testData.mNode->setCondition(CachedNode::NOT_ENCLOSING_CURSOR);
+        return REJECT_TEST;
+    }
+    testData.setDistances();
+    if (bestData->mNode != NULL) {
+        int compared = compare(testData, *bestData);
+        if (compared == 0 && test->isArea() == false && bestData->mNode->isArea() == false)
+            goto pickTest;
+        if (compared >= 0)
+            return compared;
+    }
+pickTest:
+    return -1; // pick test
+}
+
+const CachedNode* CachedFrame::frameRight(const CachedNode* test,
+    const CachedNode* limit, BestData* bestData) const
+{
+    BestData originalData = *bestData;
+    do {
+        if (moveInFrame(&CachedFrame::frameRight, test, bestData))
+            continue;
+        BestData testData;
+        if (frameNodeCommon(testData, test, bestData, &originalData) == REJECT_TEST)
+            continue;
+        if (checkVisited(test, RIGHT) == false)
+            continue;
+        size_t parts = test->navableRects();
+        for (size_t part = 0; part < parts; part++) {
+            testData.setNodeBounds(test->ring(this, part));
+            if (testData.setRightDirection(history()))
+                continue;
+            int result = framePartCommon(testData, test, bestData);
+            if (result == REJECT_TEST)
+                continue;
+            if (result == 0 && limit == NULL) { // retry all data up to this point, since smaller may have replaced node preferable to larger
+                BestData innerData = testData;
+                frameRight(document(), test, &innerData);
+                if (checkVisited(innerData.mNode, RIGHT)) {
+                    *bestData = innerData;
+                    continue;
+                }
+            }
+            if (checkVisited(test, RIGHT))
+                *bestData = testData;
+        }
+    } while ((test = test->traverseNextNode()) != limit);
+    ASSERT(mRoot->mCursor == NULL || bestData->mNode != mRoot->mCursor);
+    return bestData->mNode;
+}
+
+const CachedNode* CachedFrame::frameUp(const CachedNode* test,
+    const CachedNode* limit, BestData* bestData) const
+{
+    BestData originalData = *bestData;
+    do {
+        if (moveInFrame(&CachedFrame::frameUp, test, bestData))
+            continue;
+        BestData testData;
+        if (frameNodeCommon(testData, test, bestData, &originalData) == REJECT_TEST)
+            continue;
+        if (checkVisited(test, UP) == false)
+            continue;
+        size_t parts = test->navableRects();
+        for (size_t part = 0; part < parts; part++) {
+            testData.setNodeBounds(test->ring(this, part));
+            if (testData.setUpDirection(history()))
+                continue;
+            int result = framePartCommon(testData, test, bestData);
+            if (result == REJECT_TEST)
+                continue;
+            if (result == 0 && limit == NULL) { // retry all data up to this point, since smaller may have replaced node preferable to larger
+                BestData innerData = testData;
+                frameUp(document(), test, &innerData);
+                if (checkVisited(innerData.mNode, UP)) {
+                    *bestData = innerData;
+                    continue;
+                }
+            }
+            if (checkVisited(test, UP))
+                *bestData = testData;
+        }
+    } while ((test = test->traverseNextNode()) != limit);  // FIXME ??? left and up should use traversePreviousNode to choose reverse document order
+    ASSERT(mRoot->mCursor == NULL || bestData->mNode != mRoot->mCursor);
+    return bestData->mNode;
+}
+
+CachedFrame* CachedFrame::hasFrame(const CachedNode* node)
+{
+    return node->isFrame() ? &mCachedFrames[node->childFrameIndex()] : NULL;
+}
+
+void CachedFrame::hideCursor()
+{
+    DBG_NAV_LOGD("mCursorIndex=%d", mCursorIndex);
+    if (mCursorIndex < CURSOR_SET)
+        return;
+    CachedNode& cursor = mCachedNodes[mCursorIndex];
+    cursor.hideCursor(this);
+}
+
+CachedHistory* CachedFrame::history() const
+{
+    return mRoot->rootHistory();
+}
+
+void CachedFrame::init(const CachedRoot* root, int childFrameIndex,
+    WebCore::Frame* frame)
+{
+    mContents = WebCore::IntRect(0, 0, 0, 0); // fixed up for real in setData()
+    mLocalViewBounds = WebCore::IntRect(0, 0, 0, 0);
+    mViewBounds = WebCore::IntRect(0, 0, 0, 0);
+    mRoot = root;
+    mCursorIndex = CURSOR_UNINITIALIZED; // not explicitly cleared
+    mFocusIndex = -1;
+    mFrame = frame;
+    mParent = NULL; // set up parents after stretchy arrays are set up
+    mIndexInParent = childFrameIndex;
+}
+
+#if USE(ACCELERATED_COMPOSITING)
+const CachedLayer* CachedFrame::layer(const CachedNode* node) const
+{
+    if (!node->isInLayer())
+        return 0;
+    CachedLayer test;
+    test.setCachedNodeIndex(node->index());
+    return std::lower_bound(mCachedLayers.begin(), mCachedLayers.end(), test);
+}
+#endif
+
+WebCore::IntRect CachedFrame::localBounds(const CachedNode* node,
+    const WebCore::IntRect& rect) const
+{
+    DBG_NAV_LOGD("node=%p [%d] rect=(%d,%d,w=%d,h=%d)",
+        node, node->index(), rect.x(), rect.y(), rect.width(), rect.height());
+#if USE(ACCELERATED_COMPOSITING)
+    return layer(node)->localBounds(mRoot->rootLayer(), rect);
+#else
+    return rect;
+#endif
+}
+
+int CachedFrame::minWorkingHorizontal() const
+{
+    return history()->minWorkingHorizontal();
+}
+
+int CachedFrame::minWorkingVertical() const
+{
+    return history()->minWorkingVertical();
+}
+
+int CachedFrame::maxWorkingHorizontal() const
+{
+    return history()->maxWorkingHorizontal();
+}
+
+int CachedFrame::maxWorkingVertical() const
+{
+    return history()->maxWorkingVertical();
+}
+
+const CachedNode* CachedFrame::nextTextField(const CachedNode* start,
+        const CachedFrame** framePtr, bool* startFound) const
+{
+    const CachedNode* test = mCachedNodes.begin();
+    while ((test = test->traverseNextNode())) {
+        const CachedFrame* frame = hasFrame(test);
+        if (frame) {
+            if (!frame->validDocument())
+                continue;
+            const CachedNode* node
+                    = frame->nextTextField(start, framePtr, startFound);
+            if (node)
+                return node;
+        } else if (test->isTextInput()) {
+            if (test == start)
+                *startFound = true;
+            else if (*startFound) {
+                if (framePtr)
+                    *framePtr = this;
+                return test;
+            }
+        }
+    }
+    return 0;
+}
+
+bool CachedFrame::moveInFrame(MoveInDirection moveInDirection,
+    const CachedNode* test, BestData* bestData) const
+{
+    const CachedFrame* frame = hasFrame(test);
+    if (frame == NULL)
+        return false; // if it's not a frame, let the caller have another swing at it
+    const CachedNode* childDoc = frame->validDocument();
+    if (childDoc == NULL)
+        return true;
+    (frame->*moveInDirection)(childDoc, NULL, bestData);
+    return true;
+}
+
+const WebCore::IntRect& CachedFrame::_navBounds() const
+{
+    return history()->navBounds();
+}
+
+SkPicture* CachedFrame::picture(const CachedNode* node) const
+{
+#if USE(ACCELERATED_COMPOSITING)
+    if (node->isInLayer())
+        return layer(node)->picture(mRoot->rootLayer());
+#endif
+    return mRoot->mPicture;
+}
+
+SkPicture* CachedFrame::picture(const CachedNode* node, int* xPtr, int* yPtr) const
+{
+#if USE(ACCELERATED_COMPOSITING)
+    if (node->isInLayer()) {
+        const CachedLayer* cachedLayer = layer(node);
+        const LayerAndroid* rootLayer = mRoot->rootLayer();
+        cachedLayer->toLocal(rootLayer, xPtr, yPtr);
+        return cachedLayer->picture(rootLayer);
+    }
+#endif
+    return mRoot->mPicture;
+}
+
+void CachedFrame::resetClippedOut()
+{
+    for (CachedNode* test = mCachedNodes.begin(); test != mCachedNodes.end(); test++)
+    {
+        if (test->clippedOut()) {
+            test->setDisabled(false);
+            test->setClippedOut(false);
+        }
+    }
+    for (CachedFrame* frame = mCachedFrames.begin(); frame != mCachedFrames.end();
+            frame++) {
+        frame->resetClippedOut();
+    }
+}
+
+void CachedFrame::resetLayers()
+{
+#if USE(ACCELERATED_COMPOSITING)
+    for (CachedFrame* frame = mCachedFrames.begin(); frame != mCachedFrames.end();
+            frame++) {
+        frame->resetLayers();
+    }
+#endif
+}
+
+bool CachedFrame::sameFrame(const CachedFrame* test) const
+{
+    ASSERT(test);
+    if (mIndexInParent != test->mIndexInParent)
+        return false;
+    if (mIndexInParent == -1) // index within parent's array of children, or -1 if root
+        return true;
+    return mParent->sameFrame(test->mParent);
+}
+
+void CachedFrame::setData()
+{
+    if (this != mRoot) {
+        mViewBounds = mLocalViewBounds;
+        mViewBounds.intersect(mRoot->mViewBounds);
+    }
+    int x, y;
+    if (parent() == NULL)
+        x = y = 0;
+    else {
+        x = mLocalViewBounds.x();
+        y = mLocalViewBounds.y();
+    }
+    mContents.setX(x);
+    mContents.setY(y);
+    CachedFrame* child = mCachedFrames.begin();
+    while (child != mCachedFrames.end()) {
+        child->setData();
+        child++;
+    }
+}
+
+bool CachedFrame::setCursor(WebCore::Frame* frame, WebCore::Node* node,
+    int x, int y)
+{
+    if (NULL == node) {
+        const_cast<CachedRoot*>(mRoot)->setCursor(NULL, NULL);
+        return true;
+    }
+    if (mFrame != frame) {
+        for (CachedFrame* testF = mCachedFrames.begin(); testF != mCachedFrames.end();
+                testF++) {
+            if (testF->setCursor(frame, node, x, y))
+                return true;
+        }
+        DBG_NAV_LOGD("no frame frame=%p node=%p", frame, node);
+        return false;
+    }
+    bool first = true;
+    CachedNode const * const end = mCachedNodes.end();
+    do {
+        for (CachedNode* test = mCachedNodes.begin(); test != end; test++) {
+            if (test->nodePointer() != node && first)
+                continue;
+            size_t partMax = test->navableRects();
+            for (size_t part = 0; part < partMax; part++) {
+                WebCore::IntRect testBounds = test->ring(this, part);
+                if (testBounds.contains(x, y) == false)
+                    continue;
+                if (test->isCursor()) {
+                    DBG_NAV_LOGD("already set? test=%d frame=%p node=%p x=%d y=%d",
+                        test->index(), frame, node, x, y);
+                    return false;
+                }
+                const_cast<CachedRoot*>(mRoot)->setCursor(this, test);
+                return true;
+            }
+        }
+        DBG_NAV_LOGD("moved? frame=%p node=%p x=%d y=%d", frame, node, x, y);
+    } while ((first ^= true) == false);
+failed:
+    DBG_NAV_LOGD("no match frame=%p node=%p", frame, node);
+    return false;
+}
+
+const CachedNode* CachedFrame::validDocument() const
+{
+    const CachedNode* doc = document();
+    return doc != NULL && mViewBounds.isEmpty() == false ? doc : NULL;
+}
+
+bool CachedFrame::BestData::canBeReachedByAnotherDirection()
+{
+    if (mMajorButt > -MIN_OVERLAP)
+        return false;
+    mMajorButt = -mMajorButt;
+    return mNavOutside;
+}
+
+int CachedFrame::BestData::isContainer(CachedFrame::BestData* other)
+{
+    int _x = x();
+    int otherRight = other->right();
+    if (_x >= otherRight)
+        return 0; // does not intersect
+    int _y = y();
+    int otherBottom = other->bottom();
+    if (_y >= otherBottom)
+        return 0; // does not intersect
+    int _right = right();
+    int otherX = other->x();
+    if (otherX >= _right)
+        return 0; // does not intersect
+    int _bottom = bottom();
+    int otherY = other->y();
+    if (otherY >= _bottom)
+        return 0; // does not intersect
+    int intoX = otherX - _x;
+    int intoY = otherY - _y;
+    int intoRight = otherRight - _right;
+    int intoBottom = otherBottom - _bottom;
+    bool contains = intoX >= 0 && intoY >= 0 && intoRight <= 0 && intoBottom <= 0;
+    if (contains && mNode->partRectsContains(other->mNode)) {
+//        if (mIsArea == false && hasMouseOver())
+//            other->mMouseOver = mNode;
+        return mNode->isArea() ? 1  : -1;
+    }
+    bool containedBy = intoX <= 0 && intoY <= 0 && intoRight >= 0 && intoBottom >= 0;
+    if (containedBy && other->mNode->partRectsContains(mNode)) {
+//        if (other->mIsArea == false && other->hasMouseOver())
+//            mMouseOver = other->mNode;
+        return other->mNode->isArea() ? -1  : 1;
+    }
+    return 0;
+}
+
+// distance scale factor factor as a 16.16 scalar
+SkFixed CachedFrame::BestData::Overlap(int span, int left, int right)
+{
+    unsigned result;
+    if (left > 0 && left < span && right > span)
+        result = (unsigned) left;
+    else if (right > 0 && right < span && left > span)
+        result = (unsigned) right;
+    else if (left > 0 && right > 0)
+        return SK_Fixed1;
+    else
+        return 0;
+    result = (result << 16) / (unsigned) span; // linear proportion, always less than fixed 1
+    return (SkFixed) result;
+// !!! experiment with weight -- enable if overlaps are preferred too much
+// or reverse weighting if overlaps are preferred to little
+//    return (SkFixed) (result * result >> 16); // but fall off with square
+}
+
+void CachedFrame::BestData::setDistances()
+{
+    mDistance = abs(mMajorDelta);
+    int sideDistance = mWorkingDelta;
+    if (mWorkingOverlap < SK_Fixed1) {
+        if (mPreferred > 0)
+            sideDistance = mWorkingDelta2;
+    } else if (sideDistance >= 0 && mWorkingDelta2 >=- 0)
+        sideDistance = 0;
+    else {
+        ASSERT(sideDistance <= 0 && mWorkingDelta2 <= 0);
+        if (sideDistance < mWorkingDelta2)
+            sideDistance = mWorkingDelta2;
+    }
+    // if overlap, smaller abs mWorkingDelta is better, smaller abs majorDelta is better
+    // if not overlap, positive mWorkingDelta is better
+    mSideDistance = sideDistance;
+}
+
+bool CachedFrame::BestData::setDownDirection(const CachedHistory* history)
+{
+    const WebCore::IntRect& navBounds = history->navBounds();
+    mMajorButt = mNodeBounds.y() - navBounds.maxY();
+    int testX = mNodeBounds.x();
+    int testRight = mNodeBounds.maxX();
+    setNavOverlap(navBounds.width(), navBounds.maxX() - testX,
+        testRight - navBounds.x());
+    if (canBeReachedByAnotherDirection()) {
+        mNode->setCondition(CachedNode::BEST_DIRECTION);
+        return REJECT_TEST;
+    }
+    int inNavTop = mNodeBounds.y() - navBounds.y();
+    mMajorDelta2 = inNavTop;
+    mMajorDelta = mMajorDelta2 + ((mNodeBounds.height() -
+        navBounds.height()) >> 1);
+    if (mMajorDelta2 <= 1 && mMajorDelta <= 1) {
+        mNode->setCondition(CachedNode::CENTER_FURTHER); // never move up or sideways
+        return REJECT_TEST;
+    }
+    int inNavBottom = navBounds.maxY() - mNodeBounds.maxY();
+    setNavInclusion(testRight - navBounds.maxX(), navBounds.x() - testX);
+    bool subsumes = navBounds.height() > 0 && inOrSubsumesNav();
+    if (inNavTop <= 0 && inNavBottom <= 0 && subsumes && !mNode->wantsKeyEvents()) {
+        mNode->setCondition(CachedNode::NOT_ENCLOSING_CURSOR);
+        return REJECT_TEST;
+    }
+    int maxV = history->maxWorkingVertical();
+    int minV = history->minWorkingVertical();
+    setWorkingOverlap(testRight - testX, maxV - testX, testRight - minV);
+    setWorkingInclusion(testRight - maxV, minV - testX);
+    if (mWorkingOverlap == 0 && mNavOverlap == 0 && inNavBottom >= 0) {
+        mNode->setCondition(CachedNode::OVERLAP_OR_EDGE_FURTHER);
+        return REJECT_TEST;
+    }
+    mInNav = history->directionChange() && inNavTop >= 0 &&
+        inNavBottom > 0 && subsumes;
+    return false;
+}
+
+bool CachedFrame::BestData::setLeftDirection(const CachedHistory* history)
+{
+    const WebCore::IntRect& navBounds = history->navBounds();
+    mMajorButt = navBounds.x() - mNodeBounds.maxX();
+    int testY = mNodeBounds.y();
+    int testBottom = mNodeBounds.maxY();
+    setNavOverlap(navBounds.height(), navBounds.maxY() - testY,
+        testBottom - navBounds.y());
+    if (canBeReachedByAnotherDirection()) {
+        mNode->setCondition(CachedNode::BEST_DIRECTION);
+        return REJECT_TEST;
+    }
+    int inNavRight = navBounds.maxX() - mNodeBounds.maxX();
+    mMajorDelta2 = inNavRight;
+    mMajorDelta = mMajorDelta2 - ((navBounds.width() -
+        mNodeBounds.width()) >> 1);
+    if (mMajorDelta2 <= 1 && mMajorDelta <= 1) {
+        mNode->setCondition(CachedNode::CENTER_FURTHER); // never move right or sideways
+        return REJECT_TEST;
+    }
+    int inNavLeft = mNodeBounds.x() - navBounds.x();
+    setNavInclusion(navBounds.y() - testY, testBottom - navBounds.maxY());
+    bool subsumes = navBounds.width() > 0 && inOrSubsumesNav();
+    if (inNavLeft <= 0 && inNavRight <= 0 && subsumes && !mNode->wantsKeyEvents()) {
+        mNode->setCondition(CachedNode::NOT_ENCLOSING_CURSOR);
+        return REJECT_TEST;
+    }
+    int maxH = history->maxWorkingHorizontal();
+    int minH = history->minWorkingHorizontal();
+    setWorkingOverlap(testBottom - testY, maxH - testY, testBottom - minH);
+    setWorkingInclusion(minH - testY, testBottom - maxH);
+    if (mWorkingOverlap == 0 && mNavOverlap == 0 && inNavLeft >= 0) {
+        mNode->setCondition(CachedNode::OVERLAP_OR_EDGE_FURTHER);
+        return REJECT_TEST;
+    }
+    mInNav = history->directionChange() && inNavLeft >= 0 &&
+        inNavRight > 0 && subsumes; /* both L/R in or out */
+    return false;
+}
+
+bool CachedFrame::BestData::setRightDirection(const CachedHistory* history)
+{
+    const WebCore::IntRect& navBounds = history->navBounds();
+    mMajorButt = mNodeBounds.x() - navBounds.maxX();
+    int testY = mNodeBounds.y();
+    int testBottom = mNodeBounds.maxY();
+    setNavOverlap(navBounds.height(), navBounds.maxY() - testY,
+        testBottom - navBounds.y());
+    if (canBeReachedByAnotherDirection()) {
+        mNode->setCondition(CachedNode::BEST_DIRECTION);
+        return REJECT_TEST;
+    }
+    int inNavLeft = mNodeBounds.x() - navBounds.x();
+    mMajorDelta2 = inNavLeft;
+    mMajorDelta = mMajorDelta2 + ((mNodeBounds.width() -
+        navBounds.width()) >> 1);
+    if (mMajorDelta2 <= 1 && mMajorDelta <= 1) {
+        mNode->setCondition(CachedNode::CENTER_FURTHER); // never move left or sideways
+        return REJECT_TEST;
+    }
+    int inNavRight = navBounds.maxX() - mNodeBounds.maxX();
+    setNavInclusion(testBottom - navBounds.maxY(), navBounds.y() - testY);
+    bool subsumes = navBounds.width() > 0 && inOrSubsumesNav();
+    if (inNavLeft <= 0 && inNavRight <= 0 && subsumes && !mNode->wantsKeyEvents()) {
+        mNode->setCondition(CachedNode::NOT_ENCLOSING_CURSOR);
+        return REJECT_TEST;
+    }
+    int maxH = history->maxWorkingHorizontal();
+    int minH = history->minWorkingHorizontal();
+    setWorkingOverlap(testBottom - testY, testBottom - minH, maxH - testY);
+    setWorkingInclusion(testBottom - maxH, minH - testY);
+    if (mWorkingOverlap == 0 && mNavOverlap == 0 && inNavRight >= 0) {
+        mNode->setCondition(CachedNode::OVERLAP_OR_EDGE_FURTHER);
+        return REJECT_TEST;
+    }
+    mInNav = history->directionChange() && inNavLeft >= 0 &&
+        inNavRight > 0 && subsumes; /* both L/R in or out */
+    return false;
+}
+
+bool CachedFrame::BestData::setUpDirection(const CachedHistory* history)
+{
+    const WebCore::IntRect& navBounds = history->navBounds();
+    mMajorButt = navBounds.y() - mNodeBounds.maxY();
+    int testX = mNodeBounds.x();
+    int testRight = mNodeBounds.maxX();
+    setNavOverlap(navBounds.width(), navBounds.maxX() - testX,
+        testRight - navBounds.x());
+    if (canBeReachedByAnotherDirection()) {
+        mNode->setCondition(CachedNode::BEST_DIRECTION);
+        return REJECT_TEST;
+    }
+    int inNavBottom = navBounds.maxY() - mNodeBounds.maxY();
+    mMajorDelta2 = inNavBottom;
+    mMajorDelta = mMajorDelta2 - ((navBounds.height() -
+        mNodeBounds.height()) >> 1);
+    if (mMajorDelta2 <= 1 && mMajorDelta <= 1) {
+        mNode->setCondition(CachedNode::CENTER_FURTHER); // never move down or sideways
+        return REJECT_TEST;
+    }
+    int inNavTop = mNodeBounds.y() - navBounds.y();
+    setNavInclusion(navBounds.x() - testX, testRight - navBounds.maxX());
+    bool subsumes = navBounds.height() > 0 && inOrSubsumesNav();
+    if (inNavTop <= 0 && inNavBottom <= 0 && subsumes && !mNode->wantsKeyEvents()) {
+        mNode->setCondition(CachedNode::NOT_ENCLOSING_CURSOR);
+        return REJECT_TEST;
+    }
+    int maxV = history->maxWorkingVertical();
+    int minV = history->minWorkingVertical();
+    setWorkingOverlap(testRight - testX, testRight - minV, maxV - testX);
+    setWorkingInclusion(minV - testX, testRight - maxV);
+    if (mWorkingOverlap == 0 && mNavOverlap == 0 && inNavTop >= 0) {
+        mNode->setCondition(CachedNode::OVERLAP_OR_EDGE_FURTHER);
+        return REJECT_TEST;
+    }
+    mInNav = history->directionChange() && inNavTop >= 0 &&
+        inNavBottom > 0 && subsumes; /* both L/R in or out */
+    return false;
+}
+
+void CachedFrame::BestData::setNavInclusion(int left, int right)
+{
+    // if left and right <= 0, test node is completely in umbra of cursor
+        // prefer leftmost center
+    // if left and right > 0, test node subsumes cursor
+    mNavDelta = left;
+    mNavDelta2 = right;
+}
+
+void CachedFrame::BestData::setNavOverlap(int span, int left, int right)
+{
+    // if left or right < 0, test node is not in umbra of cursor
+    mNavOutside = left < MIN_OVERLAP || right < MIN_OVERLAP;
+    mNavOverlap = Overlap(span, left, right); // prefer smallest negative left
+}
+
+void CachedFrame::BestData::setWorkingInclusion(int left, int right)
+{
+    mWorkingDelta = left;
+    mWorkingDelta2 = right;
+}
+
+// distance scale factor factor as a 16.16 scalar
+void CachedFrame::BestData::setWorkingOverlap(int span, int left, int right)
+{
+    // if left or right < 0, test node is not in umbra of cursor
+    mWorkingOutside = left < MIN_OVERLAP || right < MIN_OVERLAP;
+    mWorkingOverlap = Overlap(span, left, right);
+    mPreferred = left <= 0 ? 0 : left;
+}
+
+#if DUMP_NAV_CACHE
+
+#define DEBUG_PRINT_RECT(prefix, debugName, field) \
+    { const WebCore::IntRect& r = b->field; \
+    DUMP_NAV_LOGD("%s DebugTestRect TEST%s_" #debugName "={%d, %d, %d, %d}; //" #field "\n", \
+        prefix, mFrameName, r.x(), r.y(), r.width(), r.height()); }
+
+CachedFrame* CachedFrame::Debug::base() const {
+    CachedFrame* nav = (CachedFrame*) ((char*) this - OFFSETOF(CachedFrame, mDebug));
+    return nav;
+}
+
+void CachedFrame::Debug::print() const
+{
+    CachedFrame* b = base();
+    DEBUG_PRINT_RECT("//", CONTENTS, mContents);
+    DEBUG_PRINT_RECT("", BOUNDS, mLocalViewBounds);
+    DEBUG_PRINT_RECT("//", VIEW, mViewBounds);
+
+    DUMP_NAV_LOGD("// CachedNode mCachedNodes={ // count=%d\n", b->mCachedNodes.size());
+    for (CachedNode* node = b->mCachedNodes.begin();
+            node != b->mCachedNodes.end(); node++) {
+        node->mDebug.print();
+        const CachedInput* input = b->textInput(node);
+        if (input)
+            input->mDebug.print();
+        DUMP_NAV_LOGD("\n");
+    }
+    DUMP_NAV_LOGD("// }; // end of nodes\n");
+#if USE(ACCELERATED_COMPOSITING)
+    DUMP_NAV_LOGD("// CachedLayer mCachedLayers={ // count=%d\n", b->mCachedLayers.size());
+    for (CachedLayer* layer = b->mCachedLayers.begin();
+            layer != b->mCachedLayers.end(); layer++) {
+        layer->mDebug.print();
+    }
+    DUMP_NAV_LOGD("// }; // end of layers\n");
+#endif // USE(ACCELERATED_COMPOSITING)
+    DUMP_NAV_LOGD("// CachedColor mCachedColors={ // count=%d\n", b->mCachedColors.size());
+    for (CachedColor* color = b->mCachedColors.begin();
+            color != b->mCachedColors.end(); color++) {
+        color->mDebug.print();
+    }
+    DUMP_NAV_LOGD("// }; // end of colors\n");
+    DUMP_NAV_LOGD("// CachedFrame mCachedFrames={ // count=%d\n", b->mCachedFrames.size());
+    for (CachedFrame* child = b->mCachedFrames.begin();
+            child != b->mCachedFrames.end(); child++)
+    {
+        child->mDebug.print();
+    }
+    DUMP_NAV_LOGD("// }; // end of child frames\n");
+    DUMP_NAV_LOGD("// void* mFrame=(void*) %p;\n", b->mFrame);
+    DUMP_NAV_LOGD("// CachedFrame* mParent=%p;\n", b->mParent);
+    DUMP_NAV_LOGD("// int mIndexInParent=%d;\n", b->mIndexInParent);
+    DUMP_NAV_LOGD("// const CachedRoot* mRoot=%p;\n", b->mRoot);
+    DUMP_NAV_LOGD("// int mCursorIndex=%d;\n", b->mCursorIndex);
+    DUMP_NAV_LOGD("// int mFocusIndex=%d;\n", b->mFocusIndex);
+}
+
+bool CachedFrame::Debug::validate(const CachedNode* node) const
+{
+    const CachedFrame* b = base();
+    if (b->mCachedNodes.size() == 0)
+        return false;
+    if (node >= b->mCachedNodes.begin() && node < b->mCachedNodes.end())
+        return true;
+    for (const CachedFrame* child = b->mCachedFrames.begin();
+            child != b->mCachedFrames.end(); child++)
+        if (child->mDebug.validate(node))
+            return true;
+    return false;
+}
+
+#undef DEBUG_PRINT_RECT
+
+#endif
+
+}
diff --git a/Source/WebKit/android/nav/CachedFrame.h b/Source/WebKit/android/nav/CachedFrame.h
new file mode 100644
index 0000000..da86521
--- /dev/null
+++ b/Source/WebKit/android/nav/CachedFrame.h
@@ -0,0 +1,287 @@
+/*
+ * Copyright 2007, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// FIXME: A file of this name already exists in WebCore/history.
+// This file should be renamed.
+#ifndef AndroidCachedFrame_h
+#define AndroidCachedFrame_h
+
+#include "CachedColor.h"
+#include "CachedInput.h"
+#include "CachedLayer.h"
+#include "CachedNode.h"
+#include "IntRect.h"
+#include "SkFixed.h"
+#include "wtf/Vector.h"
+
+class SkPicture;
+
+namespace WebCore {
+    class Frame;
+    class Node;
+}
+
+namespace android {
+
+class CachedHistory;
+class CachedRoot;
+
+    // first node referenced by cache is always document
+class CachedFrame {
+public:
+    enum Direction {
+        UNINITIALIZED = -1,
+        LEFT,
+        RIGHT,
+        UP,
+        DOWN,
+        DIRECTION_COUNT,
+        DIRECTION_MASK = DIRECTION_COUNT - 1,
+        UP_DOWN = UP & DOWN,  // mask and result
+        RIGHT_DOWN = RIGHT & DOWN, // mask and result
+    };
+    enum Compare {
+        UNDECIDED = -1,
+        TEST_IS_BEST,
+        REJECT_TEST 
+    };
+    enum CursorInit {
+        CURSOR_UNINITIALIZED = -2,
+        CURSOR_CLEARED = -1,
+        CURSOR_SET = 0
+    };
+    CachedFrame() {}
+    void add(CachedColor& color) { mCachedColors.append(color); }
+    void add(CachedInput& input) { mCachedTextInputs.append(input); }
+#if USE(ACCELERATED_COMPOSITING)
+    void add(CachedLayer& layer) { mCachedLayers.append(layer); }
+#endif
+    void add(CachedNode& node) { mCachedNodes.append(node); }
+    void addFrame(CachedFrame& child) { mCachedFrames.append(child); }
+    WebCore::IntRect adjustBounds(const CachedNode* ,
+        const WebCore::IntRect& ) const;
+    bool checkRings(const CachedNode* node,
+        const WebCore::IntRect& testBounds) const;
+    bool checkVisited(const CachedNode* , CachedFrame::Direction ) const;
+    size_t childCount() { return mCachedFrames.size(); }
+    void clearCursor();
+    const CachedColor& color(const CachedNode* node) const {
+        return mCachedColors[node->colorIndex()];
+    }
+    const CachedNode* currentCursor() const { return currentCursor(NULL); }
+    const CachedNode* currentCursor(const CachedFrame** ) const;
+    const CachedNode* currentFocus() const { return currentFocus(NULL); }
+    const CachedNode* currentFocus(const CachedFrame** ) const;
+    bool directionChange() const;
+    const CachedNode* document() const { return mCachedNodes.begin(); }
+    bool empty() const { return mCachedNodes.size() < 2; } // must have 1 past doc
+    const CachedNode* findBestAt(const WebCore::IntRect& , int* best,
+        bool* inside, const CachedNode** , const CachedFrame** directFrame,
+        const CachedFrame** resultFrame, int* x,
+        int* y, bool checkForHidden) const;
+    const CachedFrame* findBestFrameAt(int x, int y) const;
+    const CachedNode* findBestHitAt(const WebCore::IntRect& , 
+        const CachedFrame** , int* x, int* y) const;
+    void finishInit();
+    CachedFrame* firstChild() { return mCachedFrames.begin(); }
+    const CachedFrame* firstChild() const { return mCachedFrames.begin(); }
+    void* framePointer() const { return mFrame; }
+    CachedNode* getIndex(int index) { return index >= 0 ?
+        &mCachedNodes[index] : NULL; }
+    const CachedFrame* hasFrame(const CachedNode* node) const {
+        return const_cast<CachedFrame*>(this)->hasFrame(node);
+    }
+    CachedFrame* hasFrame(const CachedNode* node);
+    void hideCursor();
+    int indexInParent() const { return mIndexInParent; }
+    void init(const CachedRoot* root, int index, WebCore::Frame* frame);
+    const CachedFrame* lastChild() const { return &mCachedFrames.last(); }
+#if USE(ACCELERATED_COMPOSITING)
+    const CachedLayer* lastLayer() const { return &mCachedLayers.last(); }
+#endif
+    CachedNode* lastNode() { return &mCachedNodes.last(); }
+    CachedFrame* lastChild() { return &mCachedFrames.last(); }
+#if USE(ACCELERATED_COMPOSITING)
+    const CachedLayer* layer(const CachedNode* ) const;
+    size_t layerCount() const { return mCachedLayers.size(); }
+#endif
+    WebCore::IntRect localBounds(const CachedNode* ,
+        const WebCore::IntRect& ) const;
+    const CachedFrame* parent() const { return mParent; }
+    CachedFrame* parent() { return mParent; }
+    SkPicture* picture(const CachedNode* ) const;
+    SkPicture* picture(const CachedNode* , int* xPtr, int* yPtr) const;
+    void resetLayers();
+    bool sameFrame(const CachedFrame* ) const;
+    void removeLast() { mCachedNodes.removeLast(); }
+    void resetClippedOut();
+    void setContentsSize(int width, int height) { mContents.setWidth(width);
+        mContents.setHeight(height); }
+    bool setCursor(WebCore::Frame* , WebCore::Node* , int x, int y);
+    void setCursorIndex(int index) { mCursorIndex = index; }
+    void setData();
+    bool setFocus(WebCore::Frame* , WebCore::Node* , int x, int y);
+    void setFocusIndex(int index) { mFocusIndex = index; }
+    void setIndexInParent(int index) { mIndexInParent = index; }
+    void setLocalViewBounds(const WebCore::IntRect& bounds) { mLocalViewBounds = bounds; }
+    int size() { return mCachedNodes.size(); }
+    const CachedInput* textInput(const CachedNode* node) const {
+        return node->isTextInput() ? &mCachedTextInputs[node->textInputIndex()]
+            : 0;
+    }
+    const CachedNode* validDocument() const;
+protected:
+    const CachedNode* nextTextField(const CachedNode* start,
+        const CachedFrame** framePtr, bool* found) const;
+    struct BestData {
+        int mDistance;
+        int mSideDistance;
+        int mMajorDelta; // difference of center of object
+            // used only when leading and trailing edges contain another set of edges
+        int mMajorDelta2; // difference of leading edge (only used when center is same)
+        int mMajorButt; // checks for next cell butting up against or close to previous one
+        int mWorkingDelta;
+        int mWorkingDelta2;
+        int mNavDelta;
+        int mNavDelta2;
+        const CachedFrame* mFrame;
+        const CachedNode* mNode;
+        SkFixed mWorkingOverlap;   // this and below are fuzzy answers instead of bools
+        SkFixed mNavOverlap;
+        SkFixed mPreferred;
+        bool mCursorChild;
+        bool mInNav;
+        bool mNavOutside;
+        bool mWorkingOutside;
+        int bottom() const { return bounds().maxY(); }
+        const WebCore::IntRect& bounds() const { return mNodeBounds; }
+        bool canBeReachedByAnotherDirection();
+        int height() const { return bounds().height(); }
+        bool inOrSubsumesNav() const { return (mNavDelta ^ mNavDelta2) >= 0; }
+        bool inOrSubsumesWorking() const { return (mWorkingDelta ^ mWorkingDelta2) >= 0; }
+        int isContainer(BestData* );
+        const WebCore::IntRect& mouseBounds() const { return mMouseBounds; }
+        static SkFixed Overlap(int span, int left, int right);
+        void reset() { mNode = NULL; }
+        int right() const { return bounds().maxX(); }
+        void setMouseBounds(const WebCore::IntRect& b) { mMouseBounds = b; }
+        void setNodeBounds(const WebCore::IntRect& b) { mNodeBounds = b; }
+        void setDistances();
+        bool setDownDirection(const CachedHistory* );
+        bool setLeftDirection(const CachedHistory* );
+        bool setRightDirection(const CachedHistory* );
+        bool setUpDirection(const CachedHistory* );
+        void setNavInclusion(int left, int right);
+        void setNavOverlap(int span, int left, int right);
+        void setWorkingInclusion(int left, int right);
+        void setWorkingOverlap(int span, int left, int right);
+        int width() const { return bounds().width(); }
+        int x() const { return bounds().x(); }
+        int y() const { return bounds().y(); }
+private: // since computing these is complicated, protect them so that the
+         // are only written by appropriate helpers
+        WebCore::IntRect mMouseBounds;
+        WebCore::IntRect mNodeBounds;
+    };
+    typedef const CachedNode* (CachedFrame::*MoveInDirection)(
+        const CachedNode* test, const CachedNode* limit, BestData* ) const;
+    void adjustToTextColumn(int* delta) const;
+    static bool CheckBetween(Direction , const WebCore::IntRect& bestRect, 
+        const WebCore::IntRect& prior, WebCore::IntRect* result);
+    bool checkBetween(BestData* , Direction );
+    int compare(BestData& testData, const BestData& bestData) const;
+    void findClosest(BestData* , Direction original, Direction test,
+        WebCore::IntRect* clip) const;
+    int frameNodeCommon(BestData& testData, const CachedNode* test, 
+        BestData* bestData, BestData* originalData) const;
+    int framePartCommon(BestData& testData, const CachedNode* test, 
+        BestData* ) const;
+    const CachedNode* frameDown(const CachedNode* test, const CachedNode* limit, 
+        BestData* ) const;
+    const CachedNode* frameLeft(const CachedNode* test, const CachedNode* limit, 
+        BestData* ) const;
+    const CachedNode* frameRight(const CachedNode* test, const CachedNode* limit, 
+        BestData* ) const;
+    const CachedNode* frameUp(const CachedNode* test, const CachedNode* limit, 
+        BestData* ) const;
+    int minWorkingHorizontal() const;
+    int minWorkingVertical() const;
+    int maxWorkingHorizontal() const;
+    int maxWorkingVertical() const;
+    bool moveInFrame(MoveInDirection , const CachedNode* test, BestData* ) const;
+    const WebCore::IntRect& _navBounds() const;
+    WebCore::IntRect mContents;
+    WebCore::IntRect mLocalViewBounds;
+    WebCore::IntRect mViewBounds;
+    WTF::Vector<CachedColor> mCachedColors;
+    WTF::Vector<CachedNode> mCachedNodes;
+    WTF::Vector<CachedFrame> mCachedFrames;
+    WTF::Vector<CachedInput> mCachedTextInputs;
+#if USE(ACCELERATED_COMPOSITING)
+    WTF::Vector<CachedLayer> mCachedLayers;
+#endif
+    void* mFrame; // WebCore::Frame*, used only to compare pointers
+    CachedFrame* mParent;
+    int mCursorIndex;
+    int mFocusIndex;
+    int mIndexInParent; // index within parent's array of children, or -1 if root
+    const CachedRoot* mRoot;
+private:
+    CachedHistory* history() const;
+#ifdef BROWSER_DEBUG
+public:
+        CachedNode* find(WebCore::Node* ); // !!! probably debugging only
+        int mDebugIndex;
+        int mDebugLoopbackOffset;
+#endif
+#if !defined NDEBUG || DUMP_NAV_CACHE 
+public:
+    class Debug {
+public:
+        Debug() { 
+#if DUMP_NAV_CACHE
+            mFrameName[0] = '\0'; 
+#endif
+#if !defined NDEBUG
+            mInUse = true; 
+#endif
+        }
+#if !defined NDEBUG
+        ~Debug() { mInUse = false; }
+        bool mInUse;
+#endif
+#if DUMP_NAV_CACHE
+        CachedFrame* base() const;
+        void print() const;
+        bool validate(const CachedNode* ) const;
+        char mFrameName[256];
+#endif
+    } mDebug;
+#endif
+};
+
+}
+
+#endif // AndroidCachedFrame_h
diff --git a/Source/WebKit/android/nav/CachedHistory.cpp b/Source/WebKit/android/nav/CachedHistory.cpp
new file mode 100644
index 0000000..d132cc3
--- /dev/null
+++ b/Source/WebKit/android/nav/CachedHistory.cpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2007, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CachedPrefix.h"
+#include "CachedFrame.h"
+#include "CachedNode.h"
+#if DUMP_NAV_CACHE
+#include "CachedRoot.h"
+#endif
+
+#include "CachedHistory.h"
+
+namespace android {
+
+CachedHistory::CachedHistory() {
+    memset(this, 0, sizeof(CachedHistory)); // this assume the class has no virtuals
+    mLastMove = CachedFrame::UNINITIALIZED;
+    mPriorMove = CachedFrame::UNINITIALIZED;
+}
+
+
+void CachedHistory::addToVisited(const CachedNode* node, CachedFrame::Direction direction)
+{
+    memmove(&mVisited[1], &mVisited[0], sizeof(mVisited) - sizeof(mVisited[0]));
+    mVisited[0].mNode = node;
+    mVisited[0].mDirection = direction;
+}
+
+bool CachedHistory::checkVisited(const CachedNode* node, CachedFrame::Direction direction) const
+{
+    // if the direction is unchanged and we've already visited this node, don't visit it again
+    int index = 0;
+    while (index < NAVIGATION_VISIT_DEPTH - 1) {
+        if (direction != mVisited[index].mDirection)
+            break;
+        index++; // compare with last direction, previous to last node (where the arrow took us from)
+        if (node == mVisited[index].mNode)
+            return false;
+    }
+    return true;
+}
+
+void CachedHistory::pinMaxMin(const WebCore::IntRect& viewBounds)
+{
+    if (mMinWorkingHorizontal < viewBounds.y() || mMinWorkingHorizontal >= viewBounds.maxY())
+        mMinWorkingHorizontal = viewBounds.y();
+    if (mMaxWorkingHorizontal > viewBounds.maxY() || mMaxWorkingHorizontal <= viewBounds.y())
+        mMaxWorkingHorizontal = viewBounds.maxY();
+    if (mMinWorkingVertical < viewBounds.x() || mMinWorkingVertical >= viewBounds.maxX())
+        mMinWorkingVertical = viewBounds.x();
+    if (mMaxWorkingVertical > viewBounds.maxX() || mMaxWorkingVertical <= viewBounds.x())
+        mMaxWorkingVertical = viewBounds.maxX();
+}
+
+void CachedHistory::reset()
+{
+    memset(mVisited, 0, sizeof(mVisited));
+//    mLastScroll = 0;
+    mPriorBounds = WebCore::IntRect(0, 0, 0, 0);
+    mDirectionChange = false;
+    mDidFirstLayout = false;
+    mPriorMove = mLastMove = CachedFrame::UNINITIALIZED;
+    mMinWorkingHorizontal = mMinWorkingVertical = INT_MIN;
+    mMaxWorkingHorizontal = mMaxWorkingVertical = INT_MAX;
+}
+
+void CachedHistory::setWorking(CachedFrame::Direction newMove, 
+    const CachedFrame* cursorFrame, const CachedNode* cursor,
+    const WebCore::IntRect& viewBounds)
+{
+    CachedFrame::Direction lastAxis = (CachedFrame::Direction) (mLastMove & ~CachedFrame::RIGHT_DOWN); // up, left or uninitialized
+    CachedFrame::Direction newAxis = (CachedFrame::Direction) (newMove & ~CachedFrame::RIGHT_DOWN); 
+    bool change = newAxis != lastAxis;
+    mDirectionChange = change && mLastMove != CachedFrame::UNINITIALIZED;
+    if (cursor != NULL || mLastMove != CachedFrame::UNINITIALIZED) {
+        mPriorMove = mLastMove;
+        mLastMove = newMove;
+    }
+    const WebCore::IntRect* navBounds = &mNavBounds;
+    if (cursor != NULL) {
+        WebCore::IntRect cursorBounds = cursor->bounds(cursorFrame);
+        if (cursorBounds.isEmpty() == false)
+            mNavBounds = cursorBounds;
+    }
+    if (change) {   // uninitialized or change in direction
+        if (lastAxis != CachedFrame::LEFT && navBounds->height() > 0) {
+            mMinWorkingHorizontal = navBounds->y();
+            mMaxWorkingHorizontal = navBounds->maxY();
+        }
+        if (lastAxis != CachedFrame::UP && navBounds->width() > 0) {
+            mMinWorkingVertical = navBounds->x();
+            mMaxWorkingVertical = navBounds->maxX();
+        }
+    }
+    pinMaxMin(viewBounds);
+}
+
+#if DUMP_NAV_CACHE
+
+#define DEBUG_PRINT_BOOL(field) \
+    DUMP_NAV_LOGD("// bool " #field "=%s;\n", b->field ? "true" : "false")
+
+#define DEBUG_PRINT_RECT(field) \
+    { const WebCore::IntRect& r = b->field; \
+    DUMP_NAV_LOGD("// IntRect " #field "={%d, %d, %d, %d};\n", \
+        r.x(), r.y(), r.width(), r.height()); }
+
+CachedHistory* CachedHistory::Debug::base() const {
+    CachedHistory* nav = (CachedHistory*) ((char*) this - OFFSETOF(CachedHistory, mDebug));
+    return nav; 
+}
+
+const char* CachedHistory::Debug::direction(CachedFrame::Direction d) const
+{
+    switch (d) {
+        case CachedFrame::LEFT: return "LEFT"; break;
+        case CachedFrame::RIGHT: return "RIGHT"; break;
+        case CachedFrame::UP: return "UP"; break;
+        case CachedFrame::DOWN: return "DOWN"; break;
+        default: return "UNINITIALIZED";
+    }
+}
+
+void CachedHistory::Debug::print(CachedRoot* root) const
+{
+    CachedHistory* b = base();
+    DUMP_NAV_LOGD("// Visited mVisited[]={\n");
+    for (size_t i = 0; i < NAVIGATION_VISIT_DEPTH; i++) {
+        const Visited& visit = b->mVisited[i];
+        const CachedNode* node = visit.mNode;
+        int index = root != NULL && root->CachedFrame::mDebug.validate(node) ?
+            node->index() : -1;
+        DUMP_NAV_LOGD("    // { 0x%p (%d), %s },\n", node, index, direction(visit.mDirection));
+    }
+    DUMP_NAV_LOGD("// };\n");
+//    DUMP_NAV_LOGD("// int mLastScroll=%d;\n", b->mLastScroll);
+    DEBUG_PRINT_RECT(mMouseBounds);
+    DEBUG_PRINT_RECT(mNavBounds);
+    DEBUG_PRINT_RECT(mPriorBounds);
+    DEBUG_PRINT_BOOL(mDirectionChange);
+    DEBUG_PRINT_BOOL(mDidFirstLayout);
+    DUMP_NAV_LOGD("// CachedFrame::Direction mLastMove=%s, mPriorMove=%s;\n", 
+        direction(b->mLastMove), direction(b->mPriorMove));
+    int max = b->mMaxWorkingHorizontal;
+    DUMP_NAV_LOGD("static int TEST_MAX_H = %d;\n",  max);
+    int min = b->mMinWorkingHorizontal;
+    if (min == INT_MIN)
+        min++;
+    DUMP_NAV_LOGD("static int TEST_MIN_H = %d;\n",  min);
+    max = b->mMaxWorkingVertical;
+    DUMP_NAV_LOGD("static int TEST_MAX_V = %d;\n",  max);
+    min = b->mMinWorkingVertical;
+    if (min == INT_MIN)
+        min++;
+    DUMP_NAV_LOGD("static int TEST_MIN_V = %d;\n",  min);
+    DUMP_NAV_LOGD("\n");
+}
+
+#endif
+
+}
diff --git a/Source/WebKit/android/nav/CachedHistory.h b/Source/WebKit/android/nav/CachedHistory.h
new file mode 100644
index 0000000..96975ca
--- /dev/null
+++ b/Source/WebKit/android/nav/CachedHistory.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2007, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CachedHistory_h
+#define CachedHistory_h
+
+#include "CachedFrame.h"
+
+#define NAVIGATION_VISIT_DEPTH 8    // the number of nodes last visited -- used to detect ping-ponging (number should be tuned)
+
+namespace android {
+
+class CachedRoot;
+
+// CachedHistory is maintained even if DOM is rebuilt by running script.
+// It uses blind pointers for comparison in the previously visited nodes.
+class CachedHistory {
+public:
+    CachedHistory();
+    void addToVisited(const CachedNode* , CachedFrame::Direction );
+    bool checkVisited(const CachedNode* , CachedFrame::Direction ) const;
+    bool didFirstLayout() const { return mDidFirstLayout; }
+    bool directionChange() const { return mDirectionChange; }
+    int minWorkingHorizontal() const { return mMinWorkingHorizontal; }
+    int minWorkingVertical() const { return mMinWorkingVertical; }
+    int maxWorkingHorizontal() const { return mMaxWorkingHorizontal; }
+    int maxWorkingVertical() const { return mMaxWorkingVertical; }
+    const WebCore::IntRect& navBounds() const { return mNavBounds; }
+    const WebCore::IntRect& priorBounds() const { return mPriorBounds; }
+    void setDidFirstLayout(bool did) { mDidFirstLayout = did; }
+    void setMouseBounds(const WebCore::IntRect& loc) { mMouseBounds = loc; }
+    void setNavBounds(const WebCore::IntRect& loc) { mNavBounds = loc; }
+    void setWorking(CachedFrame::Direction , const CachedFrame* ,
+        const CachedNode* , const WebCore::IntRect& viewBounds);
+    void reset();
+private:
+    void pinMaxMin(const WebCore::IntRect& viewBounds);
+    struct Visited {
+        const CachedNode* mNode;
+        CachedFrame::Direction mDirection;
+    } mVisited[NAVIGATION_VISIT_DEPTH];
+    WebCore::IntRect mMouseBounds; // constricted bounds, if cursor ring is partially visible
+    WebCore::IntRect mNavBounds; // cursor ring bounds plus optional keystroke movement
+    WebCore::IntRect mPriorBounds; // prior chosen cursor ring (for reversing narrowing)
+    bool mDirectionChange;
+    bool mDidFirstLayout; // set true when page is newly laid out
+    CachedFrame::Direction mLastMove;
+    CachedFrame::Direction mPriorMove;
+    int mMinWorkingHorizontal;
+    int mMaxWorkingHorizontal;
+    int mMinWorkingVertical;
+    int mMaxWorkingVertical;
+    friend class CachedRoot;
+#if DUMP_NAV_CACHE
+public:
+    class Debug {
+public:
+        CachedHistory* base() const;
+        const char* direction(CachedFrame::Direction d) const;
+        void print(CachedRoot* ) const;
+    } mDebug;
+#endif
+};
+
+}
+
+#endif
diff --git a/Source/WebKit/android/nav/CachedInput.cpp b/Source/WebKit/android/nav/CachedInput.cpp
new file mode 100644
index 0000000..a6a57ef
--- /dev/null
+++ b/Source/WebKit/android/nav/CachedInput.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CachedPrefix.h"
+#include "CachedInput.h"
+
+namespace android {
+
+void CachedInput::init() {
+    bzero(this, sizeof(CachedInput));
+    mName = WTF::String();
+}
+
+void CachedInput::setTypeFromElement(WebCore::HTMLInputElement* element)
+{
+    ASSERT(element);
+
+    if (element->isPasswordField())
+        mType = PASSWORD;
+    else if (element->isSearchField())
+        mType = SEARCH;
+    else if (element->isEmailField())
+        mType = EMAIL;
+    else if (element->isNumberField())
+        mType = NUMBER;
+    else if (element->isTelephoneField())
+        mType = TELEPHONE;
+    else if (element->isURLField())
+        mType = URL;
+    else
+        mType = NORMAL_TEXT_FIELD;
+}
+
+#if DUMP_NAV_CACHE
+
+#define DEBUG_PRINT_BOOL(field) \
+    DUMP_NAV_LOGD("// bool " #field "=%s;\n", b->field ? "true" : "false")
+
+CachedInput* CachedInput::Debug::base() const {
+    CachedInput* nav = (CachedInput*) ((char*) this - OFFSETOF(CachedInput, mDebug));
+    return nav;
+}
+
+static void printWebCoreString(const char* label,
+        const WTF::String& string) {
+    char scratch[256];
+    size_t index = snprintf(scratch, sizeof(scratch), label);
+    const UChar* ch = string.characters();
+    while (ch && *ch && index < sizeof(scratch)) {
+        UChar c = *ch++;
+        if (c < ' ' || c >= 0x7f) c = ' ';
+        scratch[index++] = c;
+    }
+    DUMP_NAV_LOGD("%.*s\"\n", index, scratch);
+}
+
+void CachedInput::Debug::print() const
+{
+    CachedInput* b = base();
+    DEBUG_PRINT_BOOL(mAutoComplete);
+    DUMP_NAV_LOGD("// void* mForm=%p;\n", b->mForm);
+    printWebCoreString("// char* mName=\"", b->mName);
+    DUMP_NAV_LOGD("// int mMaxLength=%d;\n", b->mMaxLength);
+    DUMP_NAV_LOGD("// int mPaddingLeft=%d;\n", b->mPaddingLeft);
+    DUMP_NAV_LOGD("// int mPaddingTop=%d;\n", b->mPaddingTop);
+    DUMP_NAV_LOGD("// int mPaddingRight=%d;\n", b->mPaddingRight);
+    DUMP_NAV_LOGD("// int mPaddingBottom=%d;\n", b->mPaddingBottom);
+    DUMP_NAV_LOGD("// float mTextSize=%f;\n", b->mTextSize);
+    DUMP_NAV_LOGD("// int mLineHeight=%d;\n", b->mLineHeight);
+    DUMP_NAV_LOGD("// Type mType=%d;\n", b->mType);
+    DEBUG_PRINT_BOOL(mIsRtlText);
+    DEBUG_PRINT_BOOL(mIsTextField);
+    DEBUG_PRINT_BOOL(mIsTextArea);
+}
+
+#endif
+
+}
diff --git a/Source/WebKit/android/nav/CachedInput.h b/Source/WebKit/android/nav/CachedInput.h
new file mode 100644
index 0000000..77ae57b
--- /dev/null
+++ b/Source/WebKit/android/nav/CachedInput.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CachedInput_h
+#define CachedInput_h
+
+#include "CachedDebug.h"
+#include "HTMLInputElement.h"
+#include "PlatformString.h"
+
+namespace android {
+
+class CachedInput {
+public:
+    CachedInput() {
+        // Initiaized to 0 in its array, so nothing to do in the
+        // constructor
+    }
+
+    enum Type {
+        NONE = -1,
+        NORMAL_TEXT_FIELD = 0,
+        TEXT_AREA = 1,
+        PASSWORD = 2,
+        SEARCH = 3,
+        EMAIL = 4,
+        NUMBER = 5,
+        TELEPHONE = 6,
+        URL = 7
+    };
+
+    bool autoComplete() const { return mAutoComplete; }
+    void* formPointer() const { return mForm; }
+    void init();
+    void setTypeFromElement(WebCore::HTMLInputElement*);
+    Type getType() const { return mType; }
+    bool isRtlText() const { return mIsRtlText; }
+    bool isTextField() const { return mIsTextField; }
+    bool isTextArea() const { return mIsTextArea; }
+    int lineHeight() const { return mLineHeight; }
+    int maxLength() const { return mMaxLength; };
+    const WTF::String& name() const { return mName; }
+    int paddingBottom() const { return mPaddingBottom; }
+    int paddingLeft() const { return mPaddingLeft; }
+    int paddingRight() const { return mPaddingRight; }
+    int paddingTop() const { return mPaddingTop; }
+    void setAutoComplete(bool autoComplete) { mAutoComplete = autoComplete; }
+    void setFormPointer(void* form) { mForm = form; }
+    void setIsRtlText(bool isRtlText) { mIsRtlText = isRtlText; }
+    void setIsTextField(bool isTextField) { mIsTextField = isTextField; }
+    void setIsTextArea(bool isTextArea) { mIsTextArea = isTextArea; }
+    void setLineHeight(int height) { mLineHeight = height; }
+    void setMaxLength(int maxLength) { mMaxLength = maxLength; }
+    void setName(const WTF::String& name) { mName = name; }
+    void setPaddingBottom(int bottom) { mPaddingBottom = bottom; }
+    void setPaddingLeft(int left) { mPaddingLeft = left; }
+    void setPaddingRight(int right) { mPaddingRight = right; }
+    void setPaddingTop(int top) { mPaddingTop = top; }
+    void setSpellcheck(bool spellcheck) { mSpellcheck = spellcheck; }
+    void setTextSize(float textSize) { mTextSize = textSize; }
+    bool spellcheck() const { return mSpellcheck; }
+    float textSize() const { return mTextSize; }
+
+private:
+
+    void* mForm;
+    int mLineHeight;
+    int mMaxLength;
+    WTF::String mName;
+    int mPaddingBottom;
+    int mPaddingLeft;
+    int mPaddingRight;
+    int mPaddingTop;
+    float mTextSize;
+    Type mType;
+    bool mAutoComplete : 1;
+    bool mSpellcheck : 1;
+    bool mIsRtlText : 1;
+    bool mIsTextField : 1;
+    bool mIsTextArea : 1;
+#if DUMP_NAV_CACHE
+public:
+    class Debug {
+public:
+        CachedInput* base() const;
+        void print() const;
+    } mDebug;
+#endif
+};
+
+}
+
+#endif
diff --git a/Source/WebKit/android/nav/CachedLayer.cpp b/Source/WebKit/android/nav/CachedLayer.cpp
new file mode 100644
index 0000000..f6dfb88
--- /dev/null
+++ b/Source/WebKit/android/nav/CachedLayer.cpp
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CachedPrefix.h"
+
+#include "CachedLayer.h"
+#include "FloatRect.h"
+#include "LayerAndroid.h"
+
+namespace android {
+
+#if USE(ACCELERATED_COMPOSITING)
+
+IntRect CachedLayer::adjustBounds(const LayerAndroid* root,
+    const IntRect& bounds) const
+{
+    const LayerAndroid* aLayer = layer(root);
+    if (!aLayer) {
+        DBG_NAV_LOGD("no layer in root=%p uniqueId=%d", root, mUniqueId);
+#if DUMP_NAV_CACHE
+        if (root)
+            mDebug.printRootLayerAndroid(root);
+#endif
+        return bounds;
+    }
+    FloatRect temp = bounds;
+    // First, remove the original offset from the bounds.
+    temp.move(-mOffset.x(), -mOffset.y());
+
+    // Next, add in the new position of the layer (could be different due to a
+    // fixed position layer).
+    FloatPoint position = getGlobalPosition(aLayer);
+    temp.move(position.x(), position.y());
+
+    // Add in any layer translation.
+    // FIXME: Should use bounds() and apply the entire transformation matrix.
+    const FloatPoint& translation = aLayer->translation();
+    temp.move(translation.x(), translation.y());
+
+    SkRect clip;
+    aLayer->bounds(&clip);
+
+    // Do not try to traverse the parent chain if this is the root as the parent
+    // will not be a LayerAndroid.
+    if (aLayer != root) {
+        LayerAndroid* parent = static_cast<LayerAndroid*>(aLayer->getParent());
+        while (parent) {
+            SkRect pClip;
+            parent->bounds(&pClip);
+
+            // Move our position into our parent's coordinate space.
+            clip.offset(pClip.fLeft, pClip.fTop);
+            // Clip our visible rectangle to the parent.
+            clip.intersect(pClip);
+
+            // Stop at the root.
+            if (parent == root)
+                break;
+            parent = static_cast<LayerAndroid*>(parent->getParent());
+        }
+    }
+
+    // Intersect the result with the visible clip.
+    temp.intersect(clip);
+
+    IntRect result = enclosingIntRect(temp);
+
+    DBG_NAV_LOGV("root=%p aLayer=%p [%d]"
+        " bounds=(%d,%d,w=%d,h=%d) trans=(%g,%g) pos=(%f,%f)"
+        " offset=(%d,%d)"
+        " result=(%d,%d,w=%d,h=%d)",
+        root, aLayer, aLayer->uniqueId(),
+        bounds.x(), bounds.y(), bounds.width(), bounds.height(),
+        translation.x(), translation.y(), position.x(), position.y(),
+        mOffset.x(), mOffset.y(),
+        result.x(), result.y(), result.width(), result.height());
+    return result;
+}
+
+FloatPoint CachedLayer::getGlobalPosition(const LayerAndroid* aLayer) const
+{
+    SkPoint result = aLayer->getPosition();
+    const Layer* parent = aLayer->getParent();
+    while (parent) {
+        result += parent->getPosition();
+        DBG_NAV_LOGV("result=(%g,%g) parent=%p [%d]", result.fX, result.fY,
+            parent, ((LayerAndroid*) parent)->uniqueId());
+        parent = parent->getParent();
+    }
+    return result;
+}
+
+const LayerAndroid* CachedLayer::layer(const LayerAndroid* root) const
+{
+    if (!root)
+        return 0;
+    return root->findById(mUniqueId);
+}
+
+// return bounds relative to the layer as recorded when walking the dom
+IntRect CachedLayer::localBounds(const LayerAndroid* root,
+    const IntRect& bounds) const
+{
+    IntRect temp = bounds;
+    // Remove the original offset from the bounds.
+    temp.move(-mOffset.x(), -mOffset.y());
+
+#if DEBUG_NAV_UI
+    const LayerAndroid* aLayer = layer(root);
+    DBG_NAV_LOGD("aLayer=%p [%d] bounds=(%d,%d,w=%d,h=%d) offset=(%d,%d)"
+        " result=(%d,%d,w=%d,h=%d)",
+        aLayer, aLayer ? aLayer->uniqueId() : 0,
+        bounds.x(), bounds.y(), bounds.width(), bounds.height(), 
+        mOffset.x(), mOffset.y(),
+        temp.x(), temp.y(), temp.width(), temp.height());
+#endif
+
+    return temp;
+}
+
+SkPicture* CachedLayer::picture(const LayerAndroid* root) const
+{
+    const LayerAndroid* aLayer = layer(root);
+    if (!aLayer)
+        return 0;
+    DBG_NAV_LOGD("root=%p aLayer=%p [%d] picture=%p",
+        root, aLayer, aLayer->uniqueId(), aLayer->picture());
+    return aLayer->picture();
+}
+
+void CachedLayer::toLocal(const LayerAndroid* root, int* xPtr, int* yPtr) const
+{
+    const LayerAndroid* aLayer = layer(root);
+    if (!aLayer)
+        return;
+    DBG_NAV_LOGD("root=%p aLayer=%p [%d]", root, aLayer, aLayer->uniqueId());
+    SkRect localBounds;
+    aLayer->bounds(&localBounds);
+    *xPtr -= localBounds.fLeft;
+    *yPtr -= localBounds.fTop;
+}
+
+#if DUMP_NAV_CACHE
+
+CachedLayer* CachedLayer::Debug::base() const {
+    return (CachedLayer*) ((char*) this - OFFSETOF(CachedLayer, mDebug));
+}
+
+void CachedLayer::Debug::print() const
+{
+    CachedLayer* b = base();
+    DUMP_NAV_LOGD("    // int mCachedNodeIndex=%d;\n", b->mCachedNodeIndex);
+    DUMP_NAV_LOGD("    // int mOffset=(%d, %d);\n",
+        b->mOffset.x(), b->mOffset.y());
+    DUMP_NAV_LOGD("    // int mUniqueId=%p;\n", b->mUniqueId);
+    DUMP_NAV_LOGD("%s\n", "");
+}
+
+#endif
+
+#if DUMP_NAV_CACHE
+
+int CachedLayer::Debug::spaces;
+
+void CachedLayer::Debug::printLayerAndroid(const LayerAndroid* layer)
+{
+    ++spaces;
+    SkRect bounds;
+    layer->bounds(&bounds);
+    DBG_NAV_LOGD("%.*s layer=%p [%d] (%g,%g,%g,%g)"
+        " position=(%g,%g) translation=(%g,%g) anchor=(%g,%g)"
+        " matrix=(%g,%g) childMatrix=(%g,%g) picture=%p clipped=%s"
+        " scrollable=%s\n",
+        spaces, "                   ", layer, layer->uniqueId(),
+        bounds.fLeft, bounds.fTop, bounds.width(), bounds.height(),
+        layer->getPosition().fX, layer->getPosition().fY,
+        layer->translation().x(), layer->translation().y(),
+        layer->getAnchorPoint().fX, layer->getAnchorPoint().fY,
+        layer->getMatrix().getTranslateX(), layer->getMatrix().getTranslateY(),
+        layer->getChildrenMatrix().getTranslateX(),
+        layer->getChildrenMatrix().getTranslateY(),
+        layer->picture(), layer->m_haveClip ? "true" : "false",
+        layer->contentIsScrollable() ? "true" : "false");
+    for (int i = 0; i < layer->countChildren(); i++)
+        printLayerAndroid(layer->getChild(i));
+    --spaces;
+}
+
+void CachedLayer::Debug::printRootLayerAndroid(const LayerAndroid* layer)
+{
+    spaces = 0;
+    printLayerAndroid(layer);
+}
+#endif
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+}
+
diff --git a/Source/WebKit/android/nav/CachedLayer.h b/Source/WebKit/android/nav/CachedLayer.h
new file mode 100644
index 0000000..fa427d2
--- /dev/null
+++ b/Source/WebKit/android/nav/CachedLayer.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CachedLayer_h
+#define CachedLayer_h
+
+#include "CachedDebug.h"
+#include "IntRect.h"
+
+class SkPicture;
+
+namespace WebCore {
+    class FloatPoint;
+    class LayerAndroid;
+}
+
+using namespace WebCore;
+
+namespace android {
+
+class CachedLayer {
+public:
+#if USE(ACCELERATED_COMPOSITING)
+    bool operator<(const CachedLayer& l) const {
+        return mCachedNodeIndex < l.mCachedNodeIndex;
+    }
+    // FIXME: adjustBounds should be renamed globalBounds or toGlobal
+    IntRect adjustBounds(const LayerAndroid* root, const IntRect& bounds) const;
+    int cachedNodeIndex() const { return mCachedNodeIndex; }
+    FloatPoint getGlobalPosition(const LayerAndroid* ) const;
+    const LayerAndroid* layer(const LayerAndroid* root) const;
+    IntRect localBounds(const LayerAndroid* root, const IntRect& bounds) const;
+    SkPicture* picture(const LayerAndroid* root) const;
+    void toLocal(const LayerAndroid* root, int* xPtr, int* yPtr) const;
+    void setCachedNodeIndex(int index) { mCachedNodeIndex = index; }
+    // Set the global position of the layer.  This is recorded by the nav cache
+    // and corresponds to RenderLayer::absoluteBoundingBox() which is in
+    // document coordinates.  This can be different from the global position of
+    // the layer if the layer is fixed positioned or scrollable.
+    void setOffset(const IntPoint& offset) { mOffset = offset; }
+    void setUniqueId(int uniqueId) { mUniqueId = uniqueId; }
+    int uniqueId() const { return mUniqueId; }
+private:
+    int mCachedNodeIndex;
+    IntPoint mOffset;
+    int mUniqueId;
+
+#if DUMP_NAV_CACHE
+public:
+    class Debug {
+public:
+        CachedLayer* base() const;
+        void print() const;
+        static void printLayerAndroid(const LayerAndroid* );
+        static void printRootLayerAndroid(const LayerAndroid* );
+        static int spaces;
+    } mDebug;
+#endif
+#endif // USE(ACCELERATED_COMPOSITING)
+};
+
+}
+
+#endif
diff --git a/Source/WebKit/android/nav/CachedNode.cpp b/Source/WebKit/android/nav/CachedNode.cpp
new file mode 100644
index 0000000..e500875
--- /dev/null
+++ b/Source/WebKit/android/nav/CachedNode.cpp
@@ -0,0 +1,431 @@
+/*
+ * Copyright 2007, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CachedPrefix.h"
+#include "android_graphics.h"
+#include "CachedFrame.h"
+#include "CachedHistory.h"
+#include "Node.h"
+#include "PlatformString.h"
+
+#include "CachedNode.h"
+
+namespace android {
+
+WebCore::IntRect CachedNode::bounds(const CachedFrame* frame) const
+{
+    return mIsInLayer ? frame->adjustBounds(this, mBounds) : mBounds;
+}
+
+void CachedNode::clearCursor(CachedFrame* parent)
+{
+    if (isFrame()) {
+        CachedFrame* child = const_cast<CachedFrame*>(parent->hasFrame(this));
+        child->clearCursor();
+    }
+    mIsCursor = false;
+}
+
+bool CachedNode::Clip(const WebCore::IntRect& outer, WebCore::IntRect* inner,
+    WTF::Vector<WebCore::IntRect>* rings)
+{
+    if (outer.contains(*inner))
+        return true;
+//    DBG_NAV_LOGD("outer:{%d,%d,%d,%d} does not contain inner:{%d,%d,%d,%d}",
+//        outer.x(), outer.y(), outer.width(), outer.height(),
+//        inner->x(), inner->y(), inner->width(), inner->height());
+    bool intersects = outer.intersects(*inner);
+    size_t size = intersects ? rings->size() : 0;
+    *inner = WebCore::IntRect(0, 0, 0, 0);
+    if (intersects) {
+        WebCore::IntRect * const start = rings->begin();
+        WebCore::IntRect* ring = start + size - 1;
+        do {
+            ring->intersect(outer);
+            if (ring->isEmpty()) {
+                if ((size_t) (ring - start) != --size)
+                    *ring = start[size];
+            } else
+                inner->unite(*ring);
+        } while (ring-- != start);
+    }
+    rings->shrink(size);
+//    DBG_NAV_LOGD("size:%d", size);
+    return size != 0;
+}
+
+bool CachedNode::clip(const WebCore::IntRect& bounds)
+{
+    return Clip(bounds, &mBounds, &mCursorRing);
+}
+
+
+void CachedNode::cursorRings(const CachedFrame* frame,
+    WTF::Vector<WebCore::IntRect>* rings) const
+{
+    rings->clear();
+    for (unsigned index = 0; index < mCursorRing.size(); index++)
+        rings->append(ring(frame, index));
+}
+
+WebCore::IntRect CachedNode::cursorRingBounds(const CachedFrame* frame) const
+{
+    int partMax = navableRects();
+    WebCore::IntRect bounds;
+    for (int partIndex = 0; partIndex < partMax; partIndex++)
+        bounds.unite(mCursorRing[partIndex]);
+    bounds.inflate(CURSOR_RING_HIT_TEST_RADIUS);
+    return mIsInLayer ? frame->adjustBounds(this, bounds) : bounds;
+}
+
+#define OVERLAP 3
+
+void CachedNode::fixUpCursorRects(const CachedFrame* frame)
+{
+    if (mFixedUpCursorRects)
+        return;
+    mFixedUpCursorRects = true;
+    // if the hit-test rect doesn't intersect any other rect, use it
+    if (mHitBounds != mBounds && mHitBounds.contains(mBounds) &&
+            frame->checkRings(this, mHitBounds)) {
+        DBG_NAV_LOGD("use mHitBounds (%d,%d,%d,%d)", mHitBounds.x(),
+            mHitBounds.y(), mHitBounds.width(), mHitBounds.height());
+        mUseHitBounds = true;
+        return;
+    }
+    if (navableRects() <= 1)
+        return;
+    // if there is more than 1 rect, and the bounds doesn't intersect
+    // any other cursor ring bounds, use it
+    IntRect sloppyBounds = mBounds;
+    sloppyBounds.inflate(2); // give it a couple of extra pixels
+    if (frame->checkRings(this, sloppyBounds)) {
+        DBG_NAV_LOGD("use mBounds (%d,%d,%d,%d)", mBounds.x(),
+            mBounds.y(), mBounds.width(), mBounds.height());
+        mUseBounds = true;
+        return;
+    }
+#if DEBUG_NAV_UI
+    {
+        WebCore::IntRect* boundsPtr = mCursorRing.begin() - 1;
+        const WebCore::IntRect* const boundsEnd = mCursorRing.begin() + mCursorRing.size();
+        while (++boundsPtr < boundsEnd)
+            LOGD("%s %d:(%d, %d, %d, %d)\n", __FUNCTION__, boundsPtr - mCursorRing.begin(),
+                boundsPtr->x(), boundsPtr->y(), boundsPtr->width(), boundsPtr->height());
+    }
+#endif
+    // q: need to know when rects are for drawing and hit-testing, but not mouse down calcs?
+    bool again;
+    do {
+        again = false;
+        size_t size = mCursorRing.size();
+        WebCore::IntRect* unitBoundsPtr = mCursorRing.begin() - 1;
+        const WebCore::IntRect* const unitBoundsEnd = mCursorRing.begin() + size;
+        while (++unitBoundsPtr < unitBoundsEnd) {
+            // any other unitBounds to the left or right of this one?
+            int unitTop = unitBoundsPtr->y();
+            int unitBottom = unitBoundsPtr->maxY();
+            int unitLeft = unitBoundsPtr->x();
+            int unitRight = unitBoundsPtr->maxX();
+            WebCore::IntRect* testBoundsPtr = mCursorRing.begin() - 1;
+            while (++testBoundsPtr < unitBoundsEnd) {
+                if (unitBoundsPtr == testBoundsPtr)
+                    continue;
+                int testTop = testBoundsPtr->y();
+                int testBottom = testBoundsPtr->maxY();
+                int testLeft = testBoundsPtr->x();
+                int testRight = testBoundsPtr->maxX();
+                int candidateTop = unitTop > testTop ? unitTop : testTop;
+                int candidateBottom = unitBottom < testBottom ? unitBottom : testBottom;
+                int candidateLeft = unitRight < testLeft ? unitRight : testRight;
+                int candidateRight = unitRight > testLeft ? unitLeft : testLeft;
+                bool leftRight = true;
+                if (candidateTop + OVERLAP >= candidateBottom ||
+                        candidateLeft + OVERLAP >= candidateRight) {
+                    candidateTop = unitBottom < testTop ? unitBottom : testBottom;
+                    candidateBottom = unitBottom > testTop ? unitTop : testTop;
+                    candidateLeft = unitLeft > testLeft ? unitLeft : testLeft;
+                    candidateRight = unitRight < testRight ? unitRight : testRight;
+                    if (candidateTop + OVERLAP >= candidateBottom ||
+                            candidateLeft + OVERLAP >= candidateRight)
+                        continue;
+                    leftRight = false;
+                }
+                // construct candidate to add
+                WebCore::IntRect candidate = WebCore::IntRect(candidateLeft, candidateTop, 
+                    candidateRight - candidateLeft, candidateBottom - candidateTop);
+                // does a different unit bounds intersect the candidate? if so, don't add
+                WebCore::IntRect* checkBoundsPtr = mCursorRing.begin() - 1;
+                while (++checkBoundsPtr < unitBoundsEnd) {
+                    if (checkBoundsPtr->intersects(candidate) == false)
+                        continue;
+                    if (leftRight) {
+                        if (candidateTop >= checkBoundsPtr->y() &&
+                                candidateBottom > checkBoundsPtr->maxY())
+                            candidateTop = checkBoundsPtr->maxY();
+                        else if (candidateTop < checkBoundsPtr->y() &&
+                                candidateBottom <= checkBoundsPtr->maxY())
+                            candidateBottom = checkBoundsPtr->y();
+                        else
+                            goto nextCheck;
+                    } else {
+                        if (candidateLeft >= checkBoundsPtr->x() &&
+                                candidateRight > checkBoundsPtr->maxX())
+                            candidateLeft = checkBoundsPtr->maxX();
+                        else if (candidateLeft < checkBoundsPtr->x() &&
+                                candidateRight <= checkBoundsPtr->maxX())
+                            candidateRight = checkBoundsPtr->x();
+                        else
+                            goto nextCheck;
+                    }
+                 } 
+                 candidate = WebCore::IntRect(candidateLeft, candidateTop, 
+                    candidateRight - candidateLeft, candidateBottom - candidateTop);
+                 ASSERT(candidate.isEmpty() == false);
+#if DEBUG_NAV_UI
+                LOGD("%s %d:(%d, %d, %d, %d)\n", __FUNCTION__, mCursorRing.size(),
+                    candidate.x(), candidate.y(), candidate.width(), candidate.height());
+#endif
+                mCursorRing.append(candidate);
+                again = true;
+                goto tryAgain;
+        nextCheck:
+                continue;
+            }
+        }
+tryAgain:
+        ;
+    } while (again);
+}
+
+
+void CachedNode::hideCursor(CachedFrame* parent)
+{
+    if (isFrame()) {
+        CachedFrame* child = const_cast<CachedFrame*>(parent->hasFrame(this));
+        child->hideCursor();
+    }
+    mIsHidden = true;
+}
+
+WebCore::IntRect CachedNode::hitBounds(const CachedFrame* frame) const
+{
+    return mIsInLayer ? frame->adjustBounds(this, mHitBounds) : mHitBounds;
+}
+
+void CachedNode::init(WebCore::Node* node)
+{
+    bzero(this, sizeof(CachedNode));
+    mExport = WTF::String();
+    mNode = node;
+    mParentIndex = mDataIndex = -1;
+    mType = android::NORMAL_CACHEDNODETYPE;
+}
+
+bool CachedNode::isTextField(const CachedFrame* frame) const
+{
+    const CachedInput* input = frame->textInput(this);
+    return input ? input->isTextField() : false;
+}
+
+void CachedNode::localCursorRings(const CachedFrame* frame,
+    WTF::Vector<WebCore::IntRect>* rings) const
+{
+    rings->clear();
+    for (unsigned index = 0; index < mCursorRing.size(); index++)
+        rings->append(localRing(frame, index));
+}
+
+WebCore::IntRect CachedNode::localBounds(const CachedFrame* frame) const
+{
+    return mIsInLayer ? frame->localBounds(this, mBounds) : mBounds;
+}
+
+WebCore::IntRect CachedNode::localHitBounds(const CachedFrame* frame) const
+{
+    return mIsInLayer ? frame->localBounds(this, mHitBounds) : mHitBounds;
+}
+
+WebCore::IntRect CachedNode::localRing(const CachedFrame* frame,
+    size_t part) const
+{
+    const WebCore::IntRect& rect = mCursorRing.at(part);
+    return mIsInLayer ? frame->localBounds(this, rect) : rect;
+}
+
+void CachedNode::move(int x, int y)
+{
+    mBounds.move(x, y);
+    // mHitTestBounds will be moved by caller
+    WebCore::IntRect* first = mCursorRing.begin();
+    WebCore::IntRect* last = first + mCursorRing.size();
+    --first;
+    while (++first != last)
+        first->move(x, y);
+}
+
+bool CachedNode::partRectsContains(const CachedNode* other) const
+{    
+    int outerIndex = 0;
+    int outerMax = navableRects();
+    int innerMax = other->navableRects();
+    do {
+        const WebCore::IntRect& outerBounds = mCursorRing[outerIndex];
+        int innerIndex = 0;
+        do {
+            const WebCore::IntRect& innerBounds = other->mCursorRing[innerIndex];
+            if (innerBounds.contains(outerBounds))
+                return true;
+        } while (++innerIndex < innerMax);
+    } while (++outerIndex < outerMax);
+    return false;
+}
+
+WebCore::IntRect CachedNode::ring(const CachedFrame* frame, size_t part) const
+{
+    const WebCore::IntRect& rect = mCursorRing.at(part);
+    return mIsInLayer ? frame->adjustBounds(this, rect) : rect;
+}
+
+#if DUMP_NAV_CACHE
+
+#define DEBUG_PRINT_BOOL(field) \
+    DUMP_NAV_LOGD("// bool " #field "=%s;\n", b->field ? "true" : "false")
+
+#define DEBUG_PRINT_RECT(field) \
+    { const WebCore::IntRect& r = b->field; \
+    DUMP_NAV_LOGD("// IntRect " #field "={%d, %d, %d, %d};\n", \
+        r.x(), r.y(), r.width(), r.height()); }
+
+CachedNode* CachedNode::Debug::base() const {
+    CachedNode* nav = (CachedNode*) ((char*) this - OFFSETOF(CachedNode, mDebug));
+    return nav; 
+}
+
+const char* CachedNode::Debug::condition(Condition t) const
+{
+    switch (t) {
+        case NOT_REJECTED: return "NOT_REJECTED"; break;
+        case BUTTED_UP: return "BUTTED_UP"; break;
+        case CENTER_FURTHER: return "CENTER_FURTHER"; break;
+        case CLOSER: return "CLOSER"; break;
+        case CLOSER_IN_CURSOR: return "CLOSER_IN_CURSOR"; break;
+        case CLOSER_OVERLAP: return "CLOSER_OVERLAP"; break;
+        case CLOSER_TOP: return "CLOSER_TOP"; break;
+        case NAVABLE: return "NAVABLE"; break;
+        case FURTHER: return "FURTHER"; break;
+        case IN_UMBRA: return "IN_UMBRA"; break;
+        case IN_WORKING: return "IN_WORKING"; break;
+        case LEFTMOST: return "LEFTMOST"; break;
+        case OVERLAP_OR_EDGE_FURTHER: return "OVERLAP_OR_EDGE_FURTHER"; break;
+        case PREFERRED: return "PREFERRED"; break;
+        case ANCHOR_IN_ANCHOR: return "ANCHOR_IN_ANCHOR"; break;
+        case BEST_DIRECTION: return "BEST_DIRECTION"; break;
+        case CHILD: return "CHILD"; break;
+        case DISABLED: return "DISABLED"; break;
+        case HIGHER_TAB_INDEX: return "HIGHER_TAB_INDEX"; break;
+        case IN_CURSOR: return "IN_CURSOR"; break;
+        case IN_CURSOR_CHILDREN: return "IN_CURSOR_CHILDREN"; break;
+        case NOT_ENCLOSING_CURSOR: return "NOT_ENCLOSING_CURSOR"; break;
+        case NOT_CURSOR_NODE: return "NOT_CURSOR_NODE"; break;
+        case OUTSIDE_OF_BEST: return "OUTSIDE_OF_BEST"; break;
+        case OUTSIDE_OF_ORIGINAL: return "OUTSIDE_OF_ORIGINAL"; break;
+        default: return "???";
+    }
+}
+
+const char* CachedNode::Debug::type(android::CachedNodeType t) const
+{
+    switch (t) {
+        case NORMAL_CACHEDNODETYPE: return "NORMAL"; break;
+        case ADDRESS_CACHEDNODETYPE: return "ADDRESS"; break;
+        case EMAIL_CACHEDNODETYPE: return "EMAIL"; break;
+        case PHONE_CACHEDNODETYPE: return "PHONE"; break;
+        case ANCHOR_CACHEDNODETYPE: return "ANCHOR"; break;
+        case AREA_CACHEDNODETYPE: return "AREA"; break;
+        case FRAME_CACHEDNODETYPE: return "FRAME"; break;
+        case PLUGIN_CACHEDNODETYPE: return "PLUGIN"; break;
+        case TEXT_INPUT_CACHEDNODETYPE: return "INPUT"; break;
+        case SELECT_CACHEDNODETYPE: return "SELECT"; break;
+        case CONTENT_EDITABLE_CACHEDNODETYPE: return "CONTENT_EDITABLE"; break;
+        default: return "???";
+    }
+}
+
+void CachedNode::Debug::print() const
+{
+    CachedNode* b = base();
+    char scratch[256];
+    size_t index = snprintf(scratch, sizeof(scratch), "// char* mExport=\"");
+    const UChar* ch = b->mExport.characters();
+    while (ch && *ch && index < sizeof(scratch)) {
+        UChar c = *ch++;
+        if (c < ' ' || c >= 0x7f) c = ' ';
+        scratch[index++] = c;
+    }
+    DUMP_NAV_LOGD("%.*s\"\n", index, scratch);
+    DEBUG_PRINT_RECT(mBounds);
+    DEBUG_PRINT_RECT(mHitBounds);
+    DEBUG_PRINT_RECT(mOriginalAbsoluteBounds);
+    const WTF::Vector<WebCore::IntRect>* rects = &b->mCursorRing;
+    size_t size = rects->size();
+    DUMP_NAV_LOGD("// IntRect cursorRings={ // size=%d\n", size);
+    for (size_t i = 0; i < size; i++) {
+        const WebCore::IntRect& rect = (*rects)[i];
+        DUMP_NAV_LOGD("    // {%d, %d, %d, %d}, // %d\n", rect.x(), rect.y(),
+            rect.width(), rect.height(), i);
+    }
+    DUMP_NAV_LOGD("// };\n");
+    DUMP_NAV_LOGD("// void* mNode=%p; // (%d) \n", b->mNode, mNodeIndex);
+    DUMP_NAV_LOGD("// void* mParentGroup=%p; // (%d) \n", b->mParentGroup, mParentGroupIndex);
+    DUMP_NAV_LOGD("// int mDataIndex=%d;\n", b->mDataIndex);
+    DUMP_NAV_LOGD("// int mIndex=%d;\n", b->mIndex);
+    DUMP_NAV_LOGD("// int navableRects()=%d;\n", b->navableRects());
+    DUMP_NAV_LOGD("// int mParentIndex=%d;\n", b->mParentIndex);
+    DUMP_NAV_LOGD("// int mTabIndex=%d;\n", b->mTabIndex);
+    DUMP_NAV_LOGD("// int mColorIndex=%d;\n", b->mColorIndex);
+    DUMP_NAV_LOGD("// Condition mCondition=%s;\n", condition(b->mCondition));
+    DUMP_NAV_LOGD("// Type mType=%s;\n", type(b->mType));
+    DEBUG_PRINT_BOOL(mClippedOut);
+    DEBUG_PRINT_BOOL(mDisabled);
+    DEBUG_PRINT_BOOL(mFixedUpCursorRects);
+    DEBUG_PRINT_BOOL(mHasCursorRing);
+    DEBUG_PRINT_BOOL(mHasMouseOver);
+    DEBUG_PRINT_BOOL(mIsCursor);
+    DEBUG_PRINT_BOOL(mIsFocus);
+    DEBUG_PRINT_BOOL(mIsHidden);
+    DEBUG_PRINT_BOOL(mIsInLayer);
+    DEBUG_PRINT_BOOL(mIsParentAnchor);
+    DEBUG_PRINT_BOOL(mIsTransparent);
+    DEBUG_PRINT_BOOL(mIsUnclipped);
+    DEBUG_PRINT_BOOL(mLast);
+    DEBUG_PRINT_BOOL(mUseBounds);
+    DEBUG_PRINT_BOOL(mUseHitBounds);
+    DEBUG_PRINT_BOOL(mSingleImage);
+}
+
+#endif
+
+}
diff --git a/Source/WebKit/android/nav/CachedNode.h b/Source/WebKit/android/nav/CachedNode.h
new file mode 100644
index 0000000..321b7fd
--- /dev/null
+++ b/Source/WebKit/android/nav/CachedNode.h
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2007, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CachedNode_h
+#define CachedNode_h
+
+#include "CachedDebug.h"
+#include "CachedNodeType.h"
+#include "IntRect.h"
+#include "PlatformString.h"
+
+#include <wtf/Vector.h>
+#include <wtf/text/AtomicString.h>
+
+class SkPicture;
+
+namespace WebCore {
+    class Node;
+}
+
+namespace android {
+
+class CachedFrame;
+class CachedRoot;
+
+class CachedNode {
+public:
+// Nodes are rejected because either they are spacially not the best (first set)
+// or because they have the wrong DOM attribute (in focus, a focused child, etc)
+// findClosest() gives only spacially rejected nodes a second chance
+    enum Condition { // if bigger than 32, increase bitfield size below
+        // rejections that get a second chance
+        NOT_REJECTED = 0,
+        SECOND_CHANCE_START = NOT_REJECTED, // must be first in list
+        BUTTED_UP,
+        CENTER_FURTHER,
+        CLOSER,
+        CLOSER_IN_CURSOR,
+        CLOSER_OVERLAP,
+        CLOSER_TOP,
+        NAVABLE,
+        FURTHER,
+        IN_UMBRA,
+        IN_WORKING,
+        LEFTMOST,
+        NOT_ENCLOSING_CURSOR,
+        OVERLAP_OR_EDGE_FURTHER,
+        PREFERRED, // better overlap measure
+        SECOND_CHANCE_END = PREFERRED, // must be last in list
+        // rejections that don't get a second chance
+        ANCHOR_IN_ANCHOR,
+        BEST_DIRECTION, // can be reached by another direction
+        CHILD,
+        DISABLED,
+        HIGHER_TAB_INDEX,
+        IN_CURSOR,
+        IN_CURSOR_CHILDREN,
+        NOT_CURSOR_NODE,
+        OUTSIDE_OF_BEST, // containership
+        OUTSIDE_OF_ORIGINAL, // containership
+        UNDER_LAYER,
+        CONDITION_SIZE // FIXME: test that CONDITION_SIZE fits in mCondition
+    };
+    CachedNode() {
+        // The node is initiaized to 0 in its array, so nothing to do in the
+        // constructor
+    }
+
+    WebCore::IntRect bounds(const CachedFrame* ) const;
+    int childFrameIndex() const { return isFrame() ? mDataIndex : -1; }
+    void clearCondition() const { mCondition = NOT_REJECTED; }
+    void clearCursor(CachedFrame* );
+    static bool Clip(const WebCore::IntRect& outer, WebCore::IntRect* inner,
+        WTF::Vector<WebCore::IntRect>* rings);
+    bool clip(const WebCore::IntRect& );
+    bool clippedOut() { return mClippedOut; }
+    int colorIndex() const { return mColorIndex; }
+    WebCore::IntRect cursorRingBounds(const CachedFrame* ) const;
+    void cursorRings(const CachedFrame* , WTF::Vector<WebCore::IntRect>* ) const;
+    bool disabled() const { return mDisabled; }
+    const CachedNode* document() const { return &this[-mIndex]; }
+    void fixUpCursorRects(const CachedFrame* frame);
+    const WTF::String& getExport() const { return mExport; }
+    bool hasCursorRing() const { return mHasCursorRing; }
+    bool hasMouseOver() const { return mHasMouseOver; }
+    void hideCursor(CachedFrame* );
+    WebCore::IntRect hitBounds(const CachedFrame* ) const;
+    int index() const { return mIndex; }
+    void init(WebCore::Node* node);
+    bool isAnchor() const { return mType == ANCHOR_CACHEDNODETYPE; }
+    bool isContentEditable() const { return mType == CONTENT_EDITABLE_CACHEDNODETYPE; }
+    bool isCursor() const { return mIsCursor; }
+    bool isArea() const { return mType == AREA_CACHEDNODETYPE; }
+    bool isFocus() const { return mIsFocus; }
+    bool isFrame() const { return mType == FRAME_CACHEDNODETYPE; }
+    bool isHidden() const { return mIsHidden; }
+    bool isInLayer() const { return mIsInLayer; }
+    bool isNavable(const CachedFrame* frame, const WebCore::IntRect& clip) const {
+        return clip.intersects(bounds(frame));
+    }
+    bool isPlugin() const { return mType == PLUGIN_CACHEDNODETYPE; }
+    bool isSelect() const { return mType == SELECT_CACHEDNODETYPE; }
+    bool isSyntheticLink() const {
+        return mType >= ADDRESS_CACHEDNODETYPE && mType <= PHONE_CACHEDNODETYPE;
+    }
+    bool isTextField(const CachedFrame*) const;
+    bool isTextInput() const { return mType == TEXT_INPUT_CACHEDNODETYPE; }
+    bool isTransparent() const { return mIsTransparent; }
+    bool isUnclipped() const { return mIsUnclipped; }
+    // localXXX functions are used only for drawing cursor rings
+    WebCore::IntRect localBounds(const CachedFrame* ) const;
+    void localCursorRings(const CachedFrame* ,
+        WTF::Vector<WebCore::IntRect>* ) const;
+    WebCore::IntRect localHitBounds(const CachedFrame* ) const;
+    WebCore::IntRect localRing(const CachedFrame* , size_t part) const;
+    void move(int x, int y);
+    int navableRects() const { return mCursorRing.size(); }
+    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; }
+    bool partRectsContains(const CachedNode* other) const;
+    const WebCore::IntRect& rawBounds() const { return mBounds; }
+    void reset();
+    WebCore::IntRect ring(const CachedFrame* , size_t part) const;
+    const WTF::Vector<WebCore::IntRect>& rings() const { return mCursorRing; }
+    void setBounds(const WebCore::IntRect& bounds) { mBounds = bounds; }
+    void setClippedOut(bool clipped) { mClippedOut = clipped; }
+    void setColorIndex(int index) { mColorIndex = index; }
+    void setCondition(Condition condition) const { mCondition = condition; }
+    void setDataIndex(int index) { mDataIndex = index; }
+    void setDisabled(bool disabled) { mDisabled = disabled; }
+    void setExport(const WTF::String& exported) { mExport = exported; }
+    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; }
+    void setIsInLayer(bool isInLayer) { mIsInLayer = isInLayer; }
+    void setIsParentAnchor(bool isAnchor) { mIsParentAnchor = isAnchor; }
+    void setIsTransparent(bool isTransparent) { mIsTransparent = isTransparent; }
+    void setIsUnclipped(bool unclipped) { mIsUnclipped = unclipped; }
+    void setLast() { mLast = true; }
+    void setParentGroup(void* group) { mParentGroup = group; }
+    void setParentIndex(int parent) { mParentIndex = parent; }
+    void setSingleImage(bool single) { mSingleImage = single; }
+    void setTabIndex(int index) { mTabIndex = index; }
+    void setType(CachedNodeType type) { mType = type; }
+    void show() { mIsHidden = false; }
+    bool singleImage() const { return mSingleImage; }
+    int tabIndex() const { return mTabIndex; }
+    int textInputIndex() const { return isTextInput() ? mDataIndex : -1; }
+    const CachedNode* traverseNextNode() const { return mLast ? NULL : &this[1]; }
+    bool useBounds() const { return mUseBounds; }
+    bool useHitBounds() const { return mUseHitBounds; }
+    bool wantsKeyEvents() const { return isTextInput() || isPlugin()
+        || isContentEditable() || isFrame(); }
+private:
+    friend class CacheBuilder;
+    WTF::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
+    int mDataIndex; // child frame if a frame; input data index; or -1
+    int mIndex; // index of itself, to find first in array (document)
+    int mParentIndex;
+    int mTabIndex;
+    int mColorIndex; // index to ring color and other stylable properties
+    mutable Condition mCondition : 5; // why the node was not chosen on the first pass
+    CachedNodeType mType : 4;
+    bool mClippedOut : 1;
+    bool mDisabled : 1;
+    bool mFixedUpCursorRects : 1;
+    bool mHasCursorRing : 1;
+    bool mHasMouseOver : 1;
+    bool mIsCursor : 1;
+    bool mIsFocus : 1;
+    bool mIsHidden : 1;
+    bool mIsInLayer : 1;
+    bool mIsParentAnchor : 1;
+    bool mIsTransparent : 1;
+    bool mIsUnclipped : 1;
+    bool mLast : 1;             // true if this is the last node in a group
+    bool mSingleImage : 1;
+    bool mUseBounds : 1;
+    bool mUseHitBounds : 1;
+#ifdef BROWSER_DEBUG
+public:
+    WebCore::Node* webCoreNode() const { return (WebCore::Node*) mNode; }
+    bool mDisplayMeasure;
+    mutable bool mInCompare;
+    int mSideDistance;
+    int mSecondSide;
+#endif    
+#if DEBUG_NAV_UI || DUMP_NAV_CACHE
+public:
+    class Debug {
+public:
+        CachedNode* base() const;
+        const char* condition(Condition t) const;
+        void print() const;
+        const char* type(CachedNodeType t) const;
+#if DUMP_NAV_CACHE
+        int mNodeIndex;
+        int mParentGroupIndex;
+#endif
+    } mDebug;
+    friend class CachedNode::Debug;
+#endif
+};
+
+}
+
+#endif
diff --git a/Source/WebCore/platform/graphics/android/context/android_graphics.h b/Source/WebKit/android/nav/CachedNodeType.h
similarity index 64%
copy from Source/WebCore/platform/graphics/android/context/android_graphics.h
copy to Source/WebKit/android/nav/CachedNodeType.h
index 7faa781..f922946 100644
--- a/Source/WebCore/platform/graphics/android/context/android_graphics.h
+++ b/Source/WebKit/android/nav/CachedNodeType.h
@@ -23,20 +23,34 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef android_graphics_DEFINED
-#define android_graphics_DEFINED
+#ifndef CachedNodeType_h
+#define CachedNodeType_h
 
-namespace WebCore {
-    class GraphicsContext;
+namespace android {
+
+enum CachedNodeType {
+    NORMAL_CACHEDNODETYPE,
+    ADDRESS_CACHEDNODETYPE,
+    EMAIL_CACHEDNODETYPE,
+    PHONE_CACHEDNODETYPE,
+    ANCHOR_CACHEDNODETYPE,
+    AREA_CACHEDNODETYPE,
+    FRAME_CACHEDNODETYPE,
+    PLUGIN_CACHEDNODETYPE,
+    TEXT_INPUT_CACHEDNODETYPE,
+    SELECT_CACHEDNODETYPE,
+    CONTENT_EDITABLE_CACHEDNODETYPE
+};
+
+enum CachedNodeBits {
+    NORMAL_CACHEDNODE_BITS = 0,
+    ADDRESS_CACHEDNODE_BIT = 1 << (ADDRESS_CACHEDNODETYPE - 1),
+    EMAIL_CACHEDNODE_BIT = 1 << (EMAIL_CACHEDNODETYPE - 1),
+    PHONE_CACHEDNODE_BIT = 1 << (PHONE_CACHEDNODETYPE - 1),
+    ALL_CACHEDNODE_BITS = ADDRESS_CACHEDNODE_BIT | EMAIL_CACHEDNODE_BIT
+        | PHONE_CACHEDNODE_BIT
+};
+
 }
-class SkCanvas;
-
-// TODO: Move this somewhere else. The implementation for this is actually in
-// GraphicsContextAndroid.cpp, but this is used by a handful of other files
-SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc);
-
-// used to inflate node cache entry
-#define CURSOR_RING_HIT_TEST_RADIUS 5
-
 
 #endif
diff --git a/Source/WebCore/platform/graphics/android/context/android_graphics.h b/Source/WebKit/android/nav/CachedPrefix.h
similarity index 68%
rename from Source/WebCore/platform/graphics/android/context/android_graphics.h
rename to Source/WebKit/android/nav/CachedPrefix.h
index 7faa781..576aa4a 100644
--- a/Source/WebCore/platform/graphics/android/context/android_graphics.h
+++ b/Source/WebKit/android/nav/CachedPrefix.h
@@ -23,20 +23,31 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef android_graphics_DEFINED
-#define android_graphics_DEFINED
+#ifndef CachedPrefix_h
+#define CachedPrefix_h
 
-namespace WebCore {
-    class GraphicsContext;
-}
-class SkCanvas;
+#ifndef LOG_TAG
+#define LOG_TAG "navcache"
+#endif
 
-// TODO: Move this somewhere else. The implementation for this is actually in
-// GraphicsContextAndroid.cpp, but this is used by a handful of other files
-SkCanvas* android_gc2canvas(WebCore::GraphicsContext* gc);
+#include "config.h"
+#include "CachedDebug.h"
 
-// used to inflate node cache entry
-#define CURSOR_RING_HIT_TEST_RADIUS 5
+#ifndef _LIBS_CUTILS_LOG_H
+    #ifdef LOG
+    #undef LOG
+    #endif
 
+    #include <utils/Log.h>
+#endif
+
+#define OFFSETOF(type, field) ((char*)&(((type*)1)->field) - (char*)1) // avoids gnu warning
+
+#ifndef BZERO_DEFINED
+#define BZERO_DEFINED
+// http://www.opengroup.org/onlinepubs/000095399/functions/bzero.html
+// For maximum portability, it is recommended to replace the function call to bzero() as follows:
+#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
+#endif
 
 #endif
diff --git a/Source/WebKit/android/nav/CachedRoot.cpp b/Source/WebKit/android/nav/CachedRoot.cpp
new file mode 100644
index 0000000..2371c4f
--- /dev/null
+++ b/Source/WebKit/android/nav/CachedRoot.cpp
@@ -0,0 +1,1815 @@
+/*
+ * Copyright 2007, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "CachedPrefix.h"
+#include "android_graphics.h"
+#include "CachedHistory.h"
+#include "CachedInput.h"
+#include "CachedLayer.h"
+#include "CachedNode.h"
+#include "FindCanvas.h"
+#include "FloatRect.h"
+#include "LayerAndroid.h"
+#include "ParseCanvas.h"
+#include "SkBitmap.h"
+#include "SkBounder.h"
+#include "SkPixelRef.h"
+#include "SkRegion.h"
+
+#include "CachedRoot.h"
+
+#if DEBUG_NAV_UI
+#include "wtf/text/CString.h"
+#endif
+
+#define DONT_CENTER_IF_ALREADY_VISIBLE
+
+using std::min;
+using std::max;
+
+#ifdef DUMP_NAV_CACHE_USING_PRINTF
+    extern android::Mutex gWriteLogMutex;
+#endif
+
+namespace android {
+
+class CommonCheck : public SkBounder {
+public:
+    enum Type {
+        kNo_Type,
+        kDrawBitmap_Type,
+        kDrawGlyph_Type,
+        kDrawPaint_Type,
+        kDrawPath_Type,
+        kDrawPicture_Type,
+        kDrawPoints_Type,
+        kDrawPosText_Type,
+        kDrawPosTextH_Type,
+        kDrawRect_Type,
+        kDrawSprite_Type,
+        kDrawText_Type,
+        kDrawTextOnPath_Type,
+        kPopLayer_Type,
+        kPushLayer_Type,
+        kPushSave_Type
+    };
+
+    static bool isTextType(Type t) {
+        return t == kDrawPosTextH_Type || t == kDrawText_Type;
+    }
+
+    CommonCheck() : mType(kNo_Type), mAllOpaque(true), mIsOpaque(true) {
+        setEmpty();
+    }
+
+    bool doRect(Type type) {
+        mType = type;
+        return doIRect(mUnion);
+    }
+
+    bool isEmpty() { return mUnion.isEmpty(); }
+
+    bool joinGlyphs(const SkIRect& rect) {
+        bool isGlyph = mType == kDrawGlyph_Type;
+        if (isGlyph)
+            mUnion.join(rect);
+        return isGlyph;
+    }
+
+    void setAllOpaque(bool opaque) { mAllOpaque = opaque; }
+    void setEmpty() { mUnion.setEmpty(); }
+    void setIsOpaque(bool opaque) { mIsOpaque = opaque; }
+    void setType(Type type) { mType = type; }
+
+    Type mType;
+    SkIRect mUnion;
+    bool mAllOpaque;
+    bool mIsOpaque;
+};
+
+#if DEBUG_NAV_UI
+    static const char* TypeNames[] = {
+        "kNo_Type",
+        "kDrawBitmap_Type",
+        "kDrawGlyph_Type",
+        "kDrawPaint_Type",
+        "kDrawPath_Type",
+        "kDrawPicture_Type",
+        "kDrawPoints_Type",
+        "kDrawPosText_Type",
+        "kDrawPosTextH_Type",
+        "kDrawRect_Type",
+        "kDrawSprite_Type",
+        "kDrawText_Type",
+        "kDrawTextOnPath_Type",
+        "kPopLayer_Type",
+        "kPushLayer_Type",
+        "kPushSave_Type"
+    };
+#endif
+
+#define kMargin 16
+#define kSlop 2
+
+class BoundsCanvas : public ParseCanvas {
+public:
+
+    BoundsCanvas(CommonCheck* bounder) : mBounder(*bounder) {
+        mTransparentLayer = 0;
+        setBounder(bounder);
+    }
+
+    virtual void drawPaint(const SkPaint& paint) {
+        mBounder.setType(CommonCheck::kDrawPaint_Type);
+        INHERITED::drawPaint(paint);
+    }
+
+    virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
+                            const SkPaint& paint) {
+        mBounder.setType(CommonCheck::kDrawPoints_Type);
+        INHERITED::drawPoints(mode, count, pts, paint);
+    }
+
+    virtual void drawRect(const SkRect& rect, const SkPaint& paint) {
+        mBounder.setType(CommonCheck::kDrawRect_Type);
+        INHERITED::drawRect(rect, paint);
+    }
+
+    virtual void drawPath(const SkPath& path, const SkPaint& paint) {
+        mBounder.setType(CommonCheck::kDrawPath_Type);
+        INHERITED::drawPath(path, paint);
+    }
+
+    virtual void commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* rect,
+                              const SkMatrix& matrix, const SkPaint& paint) {
+        mBounder.setType(CommonCheck::kDrawBitmap_Type);
+        mBounder.setIsOpaque(bitmap.isOpaque());
+        INHERITED::commonDrawBitmap(bitmap, rect, matrix, paint);
+    }
+
+    virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
+                            const SkPaint* paint) {
+        mBounder.setType(CommonCheck::kDrawSprite_Type);
+        mBounder.setIsOpaque(bitmap.isOpaque() &&
+            (!paint || paint->getAlpha() == 255));
+        INHERITED::drawSprite(bitmap, left, top, paint);
+    }
+
+    virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+                          SkScalar y, const SkPaint& paint) {
+        mBounder.setEmpty();
+        mBounder.setType(CommonCheck::kDrawGlyph_Type);
+        INHERITED::drawText(text, byteLength, x, y, paint);
+        mBounder.doRect(CommonCheck::kDrawText_Type);
+    }
+
+    virtual void drawPosText(const void* text, size_t byteLength,
+                             const SkPoint pos[], const SkPaint& paint) {
+        mBounder.setEmpty();
+        mBounder.setType(CommonCheck::kDrawGlyph_Type);
+        INHERITED::drawPosText(text, byteLength, pos, paint);
+        if (!mBounder.isEmpty())
+            mBounder.doRect(CommonCheck::kDrawPosText_Type);
+    }
+
+    virtual void drawPosTextH(const void* text, size_t byteLength,
+                              const SkScalar xpos[], SkScalar constY,
+                              const SkPaint& paint) {
+        mBounder.setEmpty();
+        mBounder.setType(CommonCheck::kDrawGlyph_Type);
+        INHERITED::drawPosTextH(text, byteLength, xpos, constY, paint);
+        if (mBounder.mUnion.isEmpty()) {
+            DBG_NAV_LOGD("empty constY=%g", SkScalarToFloat(constY));
+            return;
+        }
+        SkPaint::FontMetrics metrics;
+        paint.getFontMetrics(&metrics);
+        SkPoint upDown[2] = { {xpos[0], constY + metrics.fAscent},
+            {xpos[0], constY + metrics.fDescent} };
+        const SkMatrix& matrix = getTotalMatrix();
+        matrix.mapPoints(upDown, 2);
+        if (upDown[0].fX == upDown[1].fX) {
+            mBounder.mUnion.fTop = SkScalarFloor(upDown[0].fY);
+            mBounder.mUnion.fBottom = SkScalarFloor(upDown[1].fY);
+        }
+        mBounder.doRect(CommonCheck::kDrawPosTextH_Type);
+    }
+
+    virtual void drawTextOnPath(const void* text, size_t byteLength,
+                                const SkPath& path, const SkMatrix* matrix,
+                                const SkPaint& paint) {
+        mBounder.setEmpty();
+        mBounder.setType(CommonCheck::kDrawGlyph_Type);
+        INHERITED::drawTextOnPath(text, byteLength, path, matrix, paint);
+        mBounder.doRect(CommonCheck::kDrawTextOnPath_Type);
+    }
+
+    virtual void drawPicture(SkPicture& picture) {
+        mBounder.setType(CommonCheck::kDrawPicture_Type);
+        INHERITED::drawPicture(picture);
+    }
+
+    virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
+                          SaveFlags flags) {
+        int depth = INHERITED::saveLayer(bounds, paint, flags);
+        if (mTransparentLayer == 0 && paint && paint->getAlpha() < 255) {
+            mTransparentLayer = depth;
+            mBounder.setAllOpaque(false);
+        }
+        return depth;
+    }
+
+    virtual void restore() {
+        mBounder.setType(CommonCheck::kDrawSprite_Type); // for layer draws
+        int depth = getSaveCount();
+        if (depth == mTransparentLayer) {
+            mTransparentLayer = 0;
+            mBounder.setAllOpaque(true);
+        }
+        INHERITED::restore();
+    }
+
+    int mTransparentLayer;
+    CommonCheck& mBounder;
+private:
+    typedef ParseCanvas INHERITED;
+};
+
+/*
+LeftCheck examines the text in a picture, within a viewable rectangle,
+and returns via left() the position of the left edge of the paragraph.
+It first looks at the left edge of the test point, then looks above and below
+it for more lines of text to determine the div's left edge.
+*/
+class LeftCheck : public CommonCheck {
+public:
+    LeftCheck(int x, int y) : mX(x), mY(y), mHitLeft(INT_MAX),
+            mMostLeft(INT_MAX) {
+        mHit.set(x - (HIT_SLOP << 1), y - HIT_SLOP, x, y + HIT_SLOP);
+        mPartial.setEmpty();
+        mBounds.setEmpty();
+        mPartialType = kNo_Type;
+    }
+
+    int left() {
+        if (isTextType(mType))
+            doRect(); // process the final line of text
+        return mMostLeft != INT_MAX ? mMostLeft : mX >> 1;
+    }
+
+    // FIXME: this is identical to CenterCheck::onIRect()
+    // refactor so that LeftCheck and CenterCheck inherit common functions
+    virtual bool onIRect(const SkIRect& rect) {
+        bool opaqueBitmap = mType == kDrawBitmap_Type && mIsOpaque;
+        if (opaqueBitmap && rect.contains(mX, mY)) {
+            mMostLeft = rect.fLeft;
+            return false;
+        }
+        if (joinGlyphs(rect)) // assembles glyphs into a text string
+            return false;
+        if (!isTextType(mType) && !opaqueBitmap)
+            return false;
+        /* Text on one line may be broken into several parts. Reassemble
+           the text into a rectangle before considering it. */
+        if (rect.fTop < mPartial.fBottom
+                && rect.fBottom > mPartial.fTop
+                && mPartial.fRight + JOIN_SLOP_X >= rect.fLeft
+                && (mPartialType != kDrawBitmap_Type
+                || mPartial.height() <= rect.height() + JOIN_SLOP_Y)) {
+            DBG_NAV_LOGD("LeftCheck join mPartial=(%d, %d, %d, %d)"
+                " rect=(%d, %d, %d, %d)",
+                mPartial.fLeft, mPartial.fTop, mPartial.fRight, mPartial.fBottom,
+                rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
+            mPartial.join(rect);
+            return false;
+        }
+        if (mPartial.isEmpty() == false) {
+            doRect(); // process the previous line of text
+#if DEBUG_NAV_UI
+            if (mHitLeft == INT_MAX)
+                DBG_NAV_LOGD("LeftCheck disabled rect=(%d, %d, %d, %d)",
+                    rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
+#endif
+        }
+        mPartial = rect;
+        mPartialType = mType;
+        return false;
+    }
+
+    void doRect()
+    {
+        /* Record the outer bounds of the lines of text that intersect the
+           touch coordinates, given some slop */
+        if (SkIRect::Intersects(mPartial, mHit)) {
+            if (mHitLeft > mPartial.fLeft)
+                mHitLeft = mPartial.fLeft;
+            DBG_NAV_LOGD("LeftCheck mHitLeft=%d", mHitLeft);
+        } else if (mHitLeft == INT_MAX)
+            return; // wait for intersect success
+        /* If text is too far away vertically, don't consider it */
+        if (!mBounds.isEmpty() && (mPartial.fTop > mBounds.fBottom + HIT_SLOP
+                || mPartial.fBottom < mBounds.fTop - HIT_SLOP)) {
+            DBG_NAV_LOGD("LeftCheck stop mPartial=(%d, %d, %d, %d)"
+                " mBounds=(%d, %d, %d, %d)",
+                mPartial.fLeft, mPartial.fTop, mPartial.fRight, mPartial.fBottom,
+                mBounds.fLeft, mBounds.fTop, mBounds.fRight, mBounds.fBottom);
+            mHitLeft = INT_MAX; // and disable future comparisons
+            return;
+        }
+        /* If the considered text is completely to the left or right of the
+           touch coordinates, skip it, turn off further detection */
+        if (mPartial.fLeft > mX || mPartial.fRight < mX) {
+            DBG_NAV_LOGD("LeftCheck stop mX=%d mPartial=(%d, %d, %d, %d)", mX,
+                mPartial.fLeft, mPartial.fTop, mPartial.fRight, mPartial.fBottom);
+            mHitLeft = INT_MAX;
+            return;
+        }
+        /* record the smallest margins on the left and right */
+        if (mMostLeft > mPartial.fLeft) {
+            DBG_NAV_LOGD("LeftCheck new mMostLeft=%d (old=%d)", mPartial.fLeft,
+                mMostLeft);
+            mMostLeft = mPartial.fLeft;
+        }
+        if (mBounds.isEmpty())
+            mBounds = mPartial;
+        else if (mPartial.fBottom > mBounds.fBottom) {
+            DBG_NAV_LOGD("LeftCheck new bottom=%d (old=%d)", mPartial.fBottom,
+                mBounds.fBottom);
+            mBounds.fBottom = mPartial.fBottom;
+        }
+    }
+
+    static const int JOIN_SLOP_X = 30; // horizontal space between text parts
+    static const int JOIN_SLOP_Y = 5; // vertical space between text lines
+    static const int HIT_SLOP = 30; // diameter allowing for tap size
+    /* const */ SkIRect mHit; // sloppy hit rectangle
+    SkIRect mBounds; // reference bounds
+    SkIRect mPartial; // accumulated text bounds, per line
+    const int mX; // touch location
+    const int mY;
+    int mHitLeft; // touched text extremes
+    int mMostLeft; // paragraph extremes
+    Type mPartialType;
+};
+
+/*
+CenterCheck examines the text in a picture, within a viewable rectangle,
+and returns via center() the optimal amount to scroll in x to display the
+paragraph of text.
+
+The caller of CenterCheck has configured (but not allocated) a bitmap
+the height and three times the width of the view. The picture is drawn centered
+in the bitmap, so text that would be revealed, if the view was scrolled up to
+a view-width to the left or right, is considered.
+*/
+class CenterCheck : public CommonCheck {
+public:
+    CenterCheck(int x, int y, int width) : mX(x), mY(y),
+            mHitLeft(x), mHitRight(x), mMostLeft(INT_MAX), mMostRight(-INT_MAX),
+            mViewLeft(width), mViewRight(width << 1) {
+        mHit.set(x - CENTER_SLOP, y - CENTER_SLOP,
+            x + CENTER_SLOP, y + CENTER_SLOP);
+        mPartial.setEmpty();
+    }
+
+    int center() {
+        doRect(); // process the final line of text
+        /* If the touch coordinates aren't near any text, return 0 */
+        if (mHitLeft == mHitRight) {
+            DBG_NAV_LOGD("abort: mHitLeft=%d ==mHitRight", mHitLeft);
+            return 0;
+        }
+        int leftOver = mHitLeft - mViewLeft;
+        int rightOver = mHitRight - mViewRight;
+        int center;
+        /* If the touched text is too large to entirely fit on the screen,
+           center it. */
+        if (leftOver < 0 && rightOver > 0) {
+            center = (leftOver + rightOver) >> 1;
+            DBG_NAV_LOGD("overlap: leftOver=%d rightOver=%d center=%d",
+                leftOver, rightOver, center);
+            return center;
+        }
+        center = (mMostLeft + mMostRight) >> 1; // the paragraph center
+        if (leftOver > 0 && rightOver >= 0) { // off to the right
+            if (center > mMostLeft) // move to center loses left-most text?
+                center = mMostLeft;
+        } else if (rightOver < 0 && leftOver <= 0) { // off to the left
+            if (center < mMostRight) // move to center loses right-most text?
+                center = mMostRight;
+        } else {
+#ifdef DONT_CENTER_IF_ALREADY_VISIBLE
+            center = 0; // paragraph is already fully visible
+#endif
+        }
+        DBG_NAV_LOGD("scroll: leftOver=%d rightOver=%d center=%d",
+            leftOver, rightOver, center);
+        return center;
+    }
+
+protected:
+    virtual bool onIRect(const SkIRect& rect) {
+        if (joinGlyphs(rect)) // assembles glyphs into a text string
+            return false;
+        if (!isTextType(mType))
+            return false;
+        /* Text on one line may be broken into several parts. Reassemble
+           the text into a rectangle before considering it. */
+        if (rect.fTop < mPartial.fBottom && rect.fBottom >
+                mPartial.fTop && mPartial.fRight + CENTER_SLOP >= rect.fLeft) {
+            DBG_NAV_LOGD("join mPartial=(%d, %d, %d, %d) rect=(%d, %d, %d, %d)",
+                mPartial.fLeft, mPartial.fTop, mPartial.fRight, mPartial.fBottom,
+                rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
+            mPartial.join(rect);
+            return false;
+        }
+        if (mPartial.isEmpty() == false)
+            doRect(); // process the previous line of text
+        mPartial = rect;
+        return false;
+    }
+
+    void doRect()
+    {
+        /* Record the outer bounds of the lines of text that was 'hit' by the
+           touch coordinates, given some slop */
+        if (SkIRect::Intersects(mPartial, mHit)) {
+            if (mHitLeft > mPartial.fLeft)
+                mHitLeft = mPartial.fLeft;
+            if (mHitRight < mPartial.fRight)
+                mHitRight = mPartial.fRight;
+            DBG_NAV_LOGD("mHitLeft=%d mHitRight=%d", mHitLeft, mHitRight);
+        }
+        /* If the considered text is completely to the left or right of the
+           touch coordinates, skip it */
+        if (mPartial.fLeft > mX || mPartial.fRight < mX)
+            return;
+        int leftOver = mPartial.fLeft - mViewLeft;
+        int rightOver = mPartial.fRight - mViewRight;
+        /* If leftOver <= 0, the text starts off the screen.
+           If rightOver >= 0, the text ends off the screen.
+        */
+        if (leftOver <= 0 && rightOver >= 0) // discard wider than screen
+            return;
+#ifdef DONT_CENTER_IF_ALREADY_VISIBLE
+        if (leftOver > 0 && rightOver < 0)   // discard already visible
+            return;
+#endif
+        /* record the smallest margins on the left and right */
+        if (mMostLeft > leftOver)
+            mMostLeft = leftOver;
+        if (mMostRight < rightOver)
+            mMostRight = rightOver;
+        DBG_NAV_LOGD("leftOver=%d rightOver=%d mMostLeft=%d mMostRight=%d",
+            leftOver, rightOver, mMostLeft, mMostRight);
+    }
+
+    static const int CENTER_SLOP = 10; // space between text parts and lines
+    /* const */ SkIRect mHit; // sloppy hit rectangle
+    SkIRect mPartial; // accumulated text bounds, per line
+    const int mX; // touch location
+    const int mY;
+    int mHitLeft; // touched text extremes
+    int mHitRight;
+    int mMostLeft; // paragraph extremes
+    int mMostRight;
+    const int mViewLeft; // middle third of 3x-wide view
+    const int mViewRight;
+};
+
+class ImageCanvas : public ParseCanvas {
+public:
+    ImageCanvas(SkBounder* bounder) : mURI(NULL) {
+        setBounder(bounder);
+    }
+
+    const char* getURI() { return mURI; }
+
+protected:
+// Currently webkit's bitmap draws always seem to be cull'd before this entry
+// point is called, so we assume that any bitmap that gets here is inside our
+// tiny clip (may not be true in the future)
+    virtual void commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* rect,
+                              const SkMatrix& , const SkPaint& ) {
+        SkPixelRef* pixelRef = bitmap.pixelRef();
+        if (pixelRef != NULL) {
+            mURI = pixelRef->getURI();
+        }
+    }
+
+private:
+    const char* mURI;
+};
+
+class ImageCheck : public SkBounder {
+public:
+    virtual bool onIRect(const SkIRect& rect) {
+        return false;
+    }
+};
+
+class JiggleCheck : public CommonCheck {
+public:
+    JiggleCheck(int delta, int width) : mDelta(delta), mMaxX(width) {
+        mMaxJiggle = 0;
+        mMinX = mMinJiggle = abs(delta);
+        mMaxWidth = width + mMinX;
+    }
+
+    int jiggle() {
+        if (mMinJiggle > mMaxJiggle)
+            return mDelta;
+        int avg = (mMinJiggle + mMaxJiggle + 1) >> 1;
+        return mDelta < 0 ? -avg : avg;
+    }
+
+    virtual bool onIRect(const SkIRect& rect) {
+        if (joinGlyphs(rect))
+            return false;
+        if (mType != kDrawBitmap_Type && !isTextType(mType))
+            return false;
+        int min, max;
+        if (mDelta < 0) {
+            min = mMinX - rect.fLeft;
+            max = mMaxWidth - rect.fRight;
+        } else {
+            min = rect.fRight - mMaxX;
+            max = rect.fLeft;
+        }
+        if (min <= 0)
+            return false;
+        if (max >= mMinX)
+            return false;
+        if (mMinJiggle > min)
+            mMinJiggle = min;
+        if (mMaxJiggle < max)
+            mMaxJiggle = max;
+        return false;
+    }
+
+    int mDelta;
+    int mMaxJiggle;
+    int mMaxX;
+    int mMinJiggle;
+    int mMinX;
+    int mMaxWidth;
+};
+
+class RingCheck : public CommonCheck {
+public:
+    RingCheck(const WTF::Vector<WebCore::IntRect>& rings,
+        const WebCore::IntRect& bitBounds, const WebCore::IntRect& testBounds,
+        bool singleImage)
+        : mTestBounds(testBounds)
+        , mBitBounds(bitBounds)
+        , mPushPop(false)
+        , mSingleImage(singleImage)
+    {
+        const WebCore::IntRect* r;
+        for (r = rings.begin(); r != rings.end(); r++) {
+            SkIRect fatter = {r->x(), r->y(), r->maxX(), r->maxY()};
+            fatter.inset(-CURSOR_RING_HIT_TEST_RADIUS, -CURSOR_RING_HIT_TEST_RADIUS);
+            DBG_NAV_LOGD("RingCheck fat=(%d,%d,r=%d,b=%d)", fatter.fLeft, fatter.fTop,
+                fatter.fRight, fatter.fBottom);
+            mTextSlop.op(fatter, SkRegion::kUnion_Op);
+            mTextTest.op(*r, SkRegion::kUnion_Op);
+        }
+        int dx = -bitBounds.x();
+        int dy = -bitBounds.y();
+        DBG_NAV_LOGD("RingCheck translate=(%d,%d)", dx, dy);
+        mTextSlop.translate(dx, dy);
+        mTextTest.translate(dx, dy);
+        mTestBounds.translate(dx, dy);
+        mEmpty.setEmpty();
+    }
+
+    bool hiddenRings(SkRegion* clipped)
+    {
+        findBestLayer();
+        if (!mBestLayer) {
+            DBG_NAV_LOG("RingCheck empty");
+            clipped->setEmpty();
+            return true;
+        }
+        const SkRegion* layersEnd = mLayers.end();
+        const Type* layerTypes = &mLayerTypes[mBestLayer - mLayers.begin()];
+        bool collectGlyphs = true;
+        bool collectOvers = false;
+        SkRegion over;
+        for (const SkRegion* layers = mBestLayer; layers != layersEnd; layers++) {
+            Type layerType = *layerTypes++;
+            DBG_NAV_LOGD("RingCheck #%d %s (%d,%d,r=%d,b=%d)",
+                layers - mLayers.begin(), TypeNames[layerType],
+                layers->getBounds().fLeft, layers->getBounds().fTop,
+                layers->getBounds().fRight, layers->getBounds().fBottom);
+            if (collectGlyphs && (layerType == kDrawGlyph_Type
+                || ((layerType == kDrawRect_Type && mTextTest.contains(*layers))
+                || (layerType == kDrawBitmap_Type && mTextSlop.contains(*layers))))) {
+                DBG_NAV_LOGD("RingCheck #%d collectOvers", layers - mLayers.begin());
+                collectOvers = true;
+                clipped->op(*layers, SkRegion::kUnion_Op);
+                continue;
+            }
+            collectGlyphs &= layerType != kPushLayer_Type;
+            if (collectOvers && (layerType == kDrawRect_Type
+                || layerType == kDrawBitmap_Type
+                || (!collectGlyphs && layerType == kDrawSprite_Type))) {
+                DBG_NAV_LOGD("RingCheck #%d over.op", layers - mLayers.begin());
+                over.op(*layers, SkRegion::kUnion_Op);
+            }
+        }
+        bool result = !collectOvers || clipped->intersects(over);
+        const SkIRect t = clipped->getBounds();
+        const SkIRect o = over.getBounds();
+        clipped->op(over, SkRegion::kDifference_Op);
+        clipped->translate(mBitBounds.x(), mBitBounds.y());
+        const SkIRect c = clipped->getBounds();
+        DBG_NAV_LOGD("RingCheck intersects=%s text=(%d,%d,r=%d,b=%d)"
+            " over=(%d,%d,r=%d,b=%d) clipped=(%d,%d,r=%d,b=%d)",
+            result ? "true" : "false",
+            t.fLeft, t.fTop, t.fRight, t.fBottom,
+            o.fLeft, o.fTop, o.fRight, o.fBottom,
+            c.fLeft, c.fTop, c.fRight, c.fBottom);
+        return result;
+    }
+
+    void push(Type type, const SkIRect& bounds)
+    {
+#if DEBUG_NAV_UI
+        // this caches the push string and subquently ignores if pushSave
+        // is immediately followed by popLayer. Push/pop pairs happen
+        // frequently and just add noise to the log.
+        static String lastLog;
+        String currentLog = String("RingCheck append #")
+            + String::number(mLayers.size())
+            + " type=" + TypeNames[type] + " bounds=("
+            + String::number(bounds.fLeft)
+            + "," + String::number(bounds.fTop) + ","
+            + String::number(bounds.fRight) + ","
+            + String::number(bounds.fBottom) + ")";
+        if (lastLog.length() == 0 || type != kPopLayer_Type) {
+            if (lastLog.length() != 0)
+                DBG_NAV_LOGD("%s", lastLog.latin1().data());
+            if (type == kPushSave_Type)
+                lastLog = currentLog;
+            else
+                DBG_NAV_LOGD("%s", currentLog.latin1().data());
+        } else
+            lastLog = "";
+#endif
+        popEmpty();
+        mPushPop |= type >= kPopLayer_Type;
+        if (type == kPopLayer_Type) {
+            Type last = mLayerTypes.last();
+            // remove empty brackets
+            if (last == kPushLayer_Type || last == kPushSave_Type) {
+                mLayers.removeLast();
+                mLayerTypes.removeLast();
+                return;
+            }
+            // remove push/pop from push/bitmap/pop
+            size_t pushIndex = mLayerTypes.size() - 2;
+            if (last == kDrawBitmap_Type
+                && mLayerTypes.at(pushIndex) == kPushLayer_Type) {
+                mLayers.at(pushIndex) = mLayers.last();
+                mLayerTypes.at(pushIndex) = kDrawBitmap_Type;
+                mLayers.removeLast();
+                mLayerTypes.removeLast();
+                return;
+            }
+            // remove non-layer brackets
+            int stack = 0;
+            Type* types = mLayerTypes.end();
+            while (types != mLayerTypes.begin()) {
+                Type type = *--types;
+                if (type == kPopLayer_Type) {
+                    stack++;
+                    continue;
+                }
+                if (type != kPushLayer_Type && type != kPushSave_Type)
+                    continue;
+                if (--stack >= 0)
+                    continue;
+                if (type == kPushLayer_Type)
+                    break;
+                int remove = types - mLayerTypes.begin();
+                DBG_NAV_LOGD("RingCheck remove=%d mLayers.size=%d"
+                    " mLayerTypes.size=%d", remove, mLayers.size(),
+                    mLayerTypes.size());
+                mLayers.remove(remove);
+                mLayerTypes.remove(remove);
+                mAppendLikeTypes = false;
+                return;
+            }
+        }
+        mLayers.append(bounds);
+        mLayerTypes.append(type);
+    }
+
+    void startText(const SkPaint& paint)
+    {
+        mPaint = &paint;
+        if (!mLayerTypes.isEmpty() && mLayerTypes.last() == kDrawGlyph_Type
+            && !mLayers.last().isEmpty()) {
+            push(kDrawGlyph_Type, mEmpty);
+        }
+    }
+
+    bool textOutsideRings()
+    {
+        findBestLayer();
+        if (!mBestLayer) {
+            DBG_NAV_LOG("RingCheck empty");
+            return false;
+        }
+        const SkRegion* layers = mBestLayer;
+        const Type* layerTypes = &mLayerTypes[layers - mLayers.begin()];
+        // back up to include text drawn before the best layer
+        SkRegion active = SkRegion(mBitBounds);
+        active.translate(-mBitBounds.x(), -mBitBounds.y());
+        while (layers != mLayers.begin()) {
+            --layers;
+            Type layerType = *--layerTypes;
+            DBG_NAV_LOGD("RingCheck #%d %s"
+                " mTestBounds=(%d,%d,r=%d,b=%d) layers=(%d,%d,r=%d,b=%d)"
+                " active=(%d,%d,r=%d,b=%d)",
+                layers - mLayers.begin(), TypeNames[layerType],
+                mTestBounds.getBounds().fLeft, mTestBounds.getBounds().fTop,
+                mTestBounds.getBounds().fRight, mTestBounds.getBounds().fBottom,
+                layers->getBounds().fLeft, layers->getBounds().fTop,
+                layers->getBounds().fRight, layers->getBounds().fBottom,
+                active.getBounds().fLeft, active.getBounds().fTop,
+                active.getBounds().fRight, active.getBounds().fBottom);
+            if (layerType == kDrawRect_Type || layerType == kDrawBitmap_Type) {
+                SkRegion temp = *layers;
+                temp.op(mTestBounds, SkRegion::kIntersect_Op);
+                active.op(temp, SkRegion::kDifference_Op);
+                if (active.isEmpty()) {
+                    DBG_NAV_LOGD("RingCheck #%d empty", layers - mLayers.begin());
+                    break;
+                }
+            } else if (layerType == kDrawGlyph_Type) {
+                SkRegion temp = *layers;
+                temp.op(active, SkRegion::kIntersect_Op);
+                if (!mTestBounds.intersects(temp))
+                    continue;
+                if (!mTestBounds.contains(temp))
+                    return false;
+            } else
+                break;
+        }
+        layers = mBestLayer;
+        layerTypes = &mLayerTypes[layers - mLayers.begin()];
+        bool foundGlyph = false;
+        bool collectGlyphs = true;
+        do {
+            Type layerType = *layerTypes++;
+            DBG_NAV_LOGD("RingCheck #%d %s mTestBounds=(%d,%d,r=%d,b=%d)"
+            " layers=(%d,%d,r=%d,b=%d) collects=%s intersects=%s contains=%s",
+                layers - mLayers.begin(), TypeNames[layerType],
+                mTestBounds.getBounds().fLeft, mTestBounds.getBounds().fTop,
+                mTestBounds.getBounds().fRight, mTestBounds.getBounds().fBottom,
+                layers->getBounds().fLeft, layers->getBounds().fTop,
+                layers->getBounds().fRight, layers->getBounds().fBottom,
+                collectGlyphs ? "true" : "false",
+                mTestBounds.intersects(*layers) ? "true" : "false",
+                mTextSlop.contains(*layers) ? "true" : "false");
+            if (collectGlyphs && layerType == kDrawGlyph_Type) {
+                if (!mTestBounds.intersects(*layers))
+                    continue;
+                if (!mTextSlop.contains(*layers))
+                    return false;
+                foundGlyph = true;
+            }
+            collectGlyphs &= layerType != kPushLayer_Type;
+        } while (++layers != mLayers.end());
+        DBG_NAV_LOGD("RingCheck foundGlyph=%s", foundGlyph ? "true" : "false");
+        return foundGlyph;
+    }
+
+protected:
+    virtual bool onIRect(const SkIRect& rect)
+    {
+        joinGlyphs(rect);
+        if (mType != kDrawGlyph_Type && mType != kDrawRect_Type
+                && mType != kDrawSprite_Type && mType != kDrawBitmap_Type)
+            return false;
+        if (mLayerTypes.isEmpty() || mLayerTypes.last() != mType
+            || !mAppendLikeTypes || mPushPop || mSingleImage
+            // if the last and current were not glyphs,
+            // and the two bounds have a gap between, don't join them -- push
+            // an empty between them
+            || (mType != kDrawGlyph_Type && !joinable(rect))) {
+            push(mType, mEmpty);
+        }
+        DBG_NAV_LOGD("RingCheck join %s (%d,%d,r=%d,b=%d) '%c'",
+            TypeNames[mType], rect.fLeft, rect.fTop, rect.fRight, rect.fBottom,
+            mCh);
+        mLayers.last().op(rect, SkRegion::kUnion_Op);
+        mAppendLikeTypes = true;
+        mPushPop = false;
+        return false;
+    }
+
+    virtual bool onIRectGlyph(const SkIRect& rect,
+        const SkBounder::GlyphRec& rec)
+    {
+        mCh = ' ';
+        if (mPaint) {
+            SkUnichar unichar;
+            SkPaint utfPaint = *mPaint;
+            utfPaint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+            utfPaint.glyphsToUnichars(&rec.fGlyphID, 1, &unichar);
+            mCh = unichar < 0x7f ? unichar : '?';
+        }
+        return onIRect(rect);
+    }
+
+private:
+    int calcOverlap(SkRegion& testRegion)
+    {
+        if (testRegion.isEmpty())
+            return INT_MAX;
+        testRegion.op(mTextTest, SkRegion::kXOR_Op);
+        SkRegion::Iterator iter(testRegion);
+        int area = 0;
+        while (!iter.done()) {
+            const SkIRect& cr = iter.rect();
+            area += cr.width() * cr.height();
+            iter.next();
+        }
+        DBG_NAV_LOGD("RingCheck area=%d", area);
+        return area;
+    }
+
+    void findBestLayer()
+    {
+        popEmpty();
+        mBestLayer = 0;
+        const SkRegion* layers = mLayers.begin();
+        const SkRegion* layersEnd = mLayers.end();
+        if (layers == layersEnd) {
+            DBG_NAV_LOG("RingCheck empty");
+            return;
+        }
+        // find text most like focus rings by xoring found with original
+        int bestArea = INT_MAX;
+        const SkRegion* testLayer = 0;
+        SkRegion testRegion;
+        const Type* layerTypes = &mLayerTypes[layers - mLayers.begin()];
+        for (; layers != mLayers.end(); layers++) {
+            Type layerType = *layerTypes++;
+#if DEBUG_NAV_UI
+            const SkIRect& gb = layers->getBounds();
+            const SkIRect& tb = mTextSlop.getBounds();
+            DBG_NAV_LOGD("RingCheck #%d %s mTextSlop=(%d,%d,%d,%d)"
+                " contains=%s bounds=(%d,%d,%d,%d)",
+                layers - mLayers.begin(), TypeNames[layerType],
+                tb.fLeft, tb.fTop, tb.fRight, tb.fBottom,
+                mTextSlop.contains(*layers) ? "true" : "false",
+                gb.fLeft, gb.fTop, gb.fRight, gb.fBottom);
+#endif
+            if (((layerType == kDrawGlyph_Type || layerType == kDrawBitmap_Type)
+                && mTextSlop.contains(*layers))
+                || (layerType == kDrawRect_Type
+                && mTextTest.contains(*layers))) {
+                if (!testLayer)
+                    testLayer = layers;
+                testRegion.op(*layers, SkRegion::kUnion_Op);
+                continue;
+            }
+            if (testLayer) {
+                int area = calcOverlap(testRegion);
+                if (bestArea > area) {
+                    bestArea = area;
+                    mBestLayer = testLayer;
+                }
+                DBG_NAV_LOGD("RingCheck #%d push test=%d best=%d",
+                    layers - mLayers.begin(), testLayer - mLayers.begin(),
+                    mBestLayer ? mBestLayer - mLayers.begin() : -1);
+                testRegion.setEmpty();
+                testLayer = 0;
+            }
+        }
+        if (testLayer && bestArea > calcOverlap(testRegion)) {
+            DBG_NAV_LOGD("RingCheck last best=%d", testLayer - mLayers.begin());
+            mBestLayer = testLayer;
+        }
+    }
+
+    bool joinable(const SkIRect& rect)
+    {
+        SkRegion region = mLayers.last();
+        if (!region.isRect())
+            return false;
+        const SkIRect& bounds1 = region.getBounds();
+        int area1 = bounds1.width() * bounds1.height();
+        area1 += rect.width() * rect.height();
+        region.op(rect, SkRegion::kUnion_Op);
+        const SkIRect& bounds2 = region.getBounds();
+        int area2 = bounds2.width() * bounds2.height();
+        return area2 <= area1;
+    }
+
+    void popEmpty()
+    {
+        if (mLayerTypes.size() == 0)
+            return;
+        Type last = mLayerTypes.last();
+        if (last >= kPopLayer_Type)
+            return;
+        const SkRegion& area = mLayers.last();
+        if (!area.isEmpty())
+            return;
+        DBG_NAV_LOGD("RingCheck #%d %s", mLayers.size() - 1, TypeNames[last]);
+        mLayers.removeLast();
+        mLayerTypes.removeLast();
+    }
+
+    SkRegion mTestBounds;
+    IntRect mBitBounds;
+    SkIRect mEmpty;
+    const SkRegion* mBestLayer;
+    SkRegion mTextSlop; // outset rects for inclusion test
+    SkRegion mTextTest; // exact rects for xor area test
+    Type mLastType;
+    Vector<SkRegion> mLayers;
+    Vector<Type> mLayerTypes;
+    const SkPaint* mPaint;
+    char mCh;
+    bool mAppendLikeTypes;
+    bool mPushPop;
+    bool mSingleImage;
+};
+
+class RingCanvas : public BoundsCanvas {
+public:
+    RingCanvas(RingCheck* bounder)
+        : INHERITED(bounder)
+    {
+    }
+
+protected:
+    virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+                          SkScalar y, const SkPaint& paint) {
+        static_cast<RingCheck&>(mBounder).startText(paint);
+        INHERITED::drawText(text, byteLength, x, y, paint);
+    }
+
+    virtual void drawPosText(const void* text, size_t byteLength,
+                             const SkPoint pos[], const SkPaint& paint) {
+        static_cast<RingCheck&>(mBounder).startText(paint);
+        INHERITED::drawPosText(text, byteLength, pos, paint);
+    }
+
+    virtual void drawTextOnPath(const void* text, size_t byteLength,
+                                const SkPath& path, const SkMatrix* matrix,
+                                const SkPaint& paint) {
+        static_cast<RingCheck&>(mBounder).startText(paint);
+        INHERITED::drawTextOnPath(text, byteLength, path, matrix, paint);
+    }
+
+    virtual void drawPosTextH(const void* text, size_t byteLength,
+                              const SkScalar xpos[], SkScalar constY,
+                              const SkPaint& paint) {
+        static_cast<RingCheck&>(mBounder).startText(paint);
+        INHERITED::drawPosTextH(text, byteLength, xpos, constY, paint);
+    }
+
+    virtual int save(SaveFlags flags)
+    {
+        RingCheck& bounder = static_cast<RingCheck&>(mBounder);
+        bounder.push(CommonCheck::kPushSave_Type, getTotalClip().getBounds());
+        return INHERITED::save(flags);
+    }
+
+    virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
+        SaveFlags flags)
+    {
+        RingCheck& bounder = static_cast<RingCheck&>(mBounder);
+        bounder.push(CommonCheck::kPushLayer_Type, getTotalClip().getBounds());
+        return INHERITED::save(flags);
+    }
+
+    virtual void restore()
+    {
+        RingCheck& bounder = static_cast<RingCheck&>(mBounder);
+        bounder.push(CommonCheck::kPopLayer_Type, getTotalClip().getBounds());
+        INHERITED::restore();
+    }
+
+private:
+    typedef BoundsCanvas INHERITED;
+};
+
+bool CachedRoot::adjustForScroll(BestData* best, CachedFrame::Direction direction,
+    WebCore::IntPoint* scrollPtr, bool findClosest)
+{
+    WebCore::IntRect newOutset;
+    const CachedNode* newNode = best->mNode;
+    // see if there's a middle node
+        // if the middle node is in the visited list,
+        // or if none was computed and the newNode is in the visited list,
+        // treat result as NULL
+    if (newNode != NULL && findClosest) {
+        if (best->bounds().intersects(mHistory->mPriorBounds) == false &&
+                checkBetween(best, direction))
+            newNode = best->mNode;
+        if (findClosest && maskIfHidden(best)) {
+            innerMove(document(), best, direction, scrollPtr, false);
+            return true;
+        }
+        newOutset = newNode->cursorRingBounds(best->mFrame);
+    }
+    int delta;
+    bool newNodeInView = scrollDelta(newOutset, direction, &delta);
+    if (delta && scrollPtr && (newNode == NULL || newNodeInView == false ||
+            (best->mNavOutside && best->mWorkingOutside)))
+        *scrollPtr = WebCore::IntPoint(direction & UP_DOWN ? 0 : delta,
+            direction & UP_DOWN ? delta : 0);
+    return false;
+}
+
+void CachedRoot::calcBitBounds(const IntRect& nodeBounds, IntRect* bitBounds) const
+{
+    IntRect contentBounds = IntRect(0, 0, mPicture->width(), mPicture->height());
+    IntRect overBounds = nodeBounds;
+    overBounds.inflate(kMargin);
+    IntRect viewableBounds = mScrolledBounds;
+    viewableBounds.unite(mViewBounds);
+    *bitBounds = contentBounds;
+    bitBounds->intersect(overBounds);
+    if (!bitBounds->intersects(viewableBounds))
+        *bitBounds = IntRect(0, 0, 0, 0);
+    DBG_NAV_LOGD("contentBounds=(%d,%d,r=%d,b=%d) overBounds=(%d,%d,r=%d,b=%d)"
+        " mScrolledBounds=(%d,%d,r=%d,b=%d) mViewBounds=(%d,%d,r=%d,b=%d)"
+        " bitBounds=(%d,%d,r=%d,b=%d)",
+        contentBounds.x(), contentBounds.y(), contentBounds.maxX(),
+        contentBounds.maxY(),
+        overBounds.x(), overBounds.y(), overBounds.maxX(), overBounds.maxY(),
+        mScrolledBounds.x(), mScrolledBounds.y(), mScrolledBounds.maxX(),
+        mScrolledBounds.maxY(),
+        mViewBounds.x(), mViewBounds.y(), mViewBounds.maxX(),
+        mViewBounds.maxY(),
+        bitBounds->x(), bitBounds->y(), bitBounds->maxX(),
+        bitBounds->maxY());
+}
+
+
+int CachedRoot::checkForCenter(int x, int y) const
+{
+    int width = mViewBounds.width();
+    SkPicture* picture = pictureAt(&x, &y);
+    CenterCheck centerCheck(x + width - mViewBounds.x(), y - mViewBounds.y(),
+        width);
+    BoundsCanvas checker(&centerCheck);
+    SkBitmap bitmap;
+    bitmap.setConfig(SkBitmap::kARGB_8888_Config, width * 3,
+        mViewBounds.height());
+    checker.setBitmapDevice(bitmap);
+    checker.translate(SkIntToScalar(width - mViewBounds.x()),
+        SkIntToScalar(-mViewBounds.y()));
+    checker.drawPicture(*picture);
+    return centerCheck.center();
+}
+
+void CachedRoot::checkForJiggle(int* xDeltaPtr) const
+{
+    int xDelta = *xDeltaPtr;
+    JiggleCheck jiggleCheck(xDelta, mViewBounds.width());
+    BoundsCanvas checker(&jiggleCheck);
+    SkBitmap bitmap;
+    int absDelta = abs(xDelta);
+    bitmap.setConfig(SkBitmap::kARGB_8888_Config, mViewBounds.width() +
+        absDelta, mViewBounds.height());
+    checker.setBitmapDevice(bitmap);
+    int x = -mViewBounds.x() - (xDelta < 0 ? xDelta : 0);
+    int y = -mViewBounds.y();
+    SkPicture* picture = pictureAt(&x, &y);
+    checker.translate(SkIntToScalar(x), SkIntToScalar(y));
+    checker.drawPicture(*picture);
+    *xDeltaPtr = jiggleCheck.jiggle();
+}
+
+bool CachedRoot::checkRings(SkPicture* picture, const CachedNode* node,
+        const WebCore::IntRect& testBounds) const
+{
+    if (!picture)
+        return false;
+    const WTF::Vector<WebCore::IntRect>& rings = node->rings();
+    const WebCore::IntRect& nodeBounds = node->rawBounds();
+    IntRect bitBounds;
+    calcBitBounds(nodeBounds, &bitBounds);
+    RingCheck ringCheck(rings, bitBounds, testBounds, node->singleImage());
+    RingCanvas checker(&ringCheck);
+    SkBitmap bitmap;
+    bitmap.setConfig(SkBitmap::kARGB_8888_Config, bitBounds.width(),
+        bitBounds.height());
+    checker.setBitmapDevice(bitmap);
+    checker.translate(SkIntToScalar(-bitBounds.x()),
+        SkIntToScalar(-bitBounds.y()));
+    checker.drawPicture(*picture);
+    bool result = ringCheck.textOutsideRings();
+    DBG_NAV_LOGD("bitBounds=(%d,%d,r=%d,b=%d) nodeBounds=(%d,%d,r=%d,b=%d)"
+        " testBounds=(%d,%d,r=%d,b=%d) success=%s",
+        bitBounds.x(), bitBounds.y(), bitBounds.maxX(), bitBounds.maxY(),
+        nodeBounds.x(), nodeBounds.y(), nodeBounds.maxX(), nodeBounds.maxY(),
+        testBounds.x(), testBounds.y(), testBounds.maxX(), testBounds.maxY(),
+        result ? "true" : "false");
+    return result;
+}
+
+void CachedRoot::draw(FindCanvas& canvas) const
+{
+    canvas.setLayerId(-1); // overlays change the ID as their pictures draw
+    canvas.drawPicture(*mPicture);
+#if USE(ACCELERATED_COMPOSITING)
+    if (!mRootLayer)
+        return;
+    canvas.drawLayers(mRootLayer);
+#endif
+}
+
+const CachedNode* CachedRoot::findAt(const WebCore::IntRect& rect,
+    const CachedFrame** framePtr, int* x, int* y, bool checkForHidden) const
+{
+#if DEBUG_NAV_UI
+    DBG_NAV_LOGD("rect=(%d,%d,w=%d,h=%d) xy=(%d,%d)", rect.x(), rect.y(),
+        rect.width(), rect.height(), *x, *y);
+#if DUMP_NAV_CACHE
+    if (mRootLayer) CachedLayer::Debug::printRootLayerAndroid(mRootLayer);
+#endif
+#endif
+    int best = INT_MAX;
+    bool inside = false;
+    (const_cast<CachedRoot*>(this))->resetClippedOut();
+    const CachedFrame* directHitFramePtr;
+    const CachedNode* directHit = NULL;
+    const CachedNode* node = findBestAt(rect, &best, &inside, &directHit,
+        &directHitFramePtr, framePtr, x, y, checkForHidden);
+    DBG_NAV_LOGD("node=%d (%p) xy=(%d,%d)", node == NULL ? 0 : node->index(),
+        node == NULL ? NULL : node->nodePointer(), *x, *y);
+    if (node == NULL) {
+        node = findBestHitAt(rect, framePtr, x, y);
+        DBG_NAV_LOGD("node=%d (%p)", node == NULL ? 0 : node->index(),
+            node == NULL ? NULL : node->nodePointer());
+    }
+    if (node == NULL) {
+        *framePtr = findBestFrameAt(rect.x() + (rect.width() >> 1),
+            rect.y() + (rect.height() >> 1));
+    }
+    return node;
+}
+
+WebCore::IntPoint CachedRoot::cursorLocation() const
+{
+    const WebCore::IntRect& bounds = mHistory->mNavBounds;
+    return WebCore::IntPoint(bounds.x() + (bounds.width() >> 1),
+        bounds.y() + (bounds.height() >> 1));
+}
+
+WebCore::IntPoint CachedRoot::focusLocation() const
+{
+    return WebCore::IntPoint(mFocusBounds.x() + (mFocusBounds.width() >> 1),
+        mFocusBounds.y() + (mFocusBounds.height() >> 1));
+}
+
+// These reset the values because we only want to get the selection the first time.
+// After that, the selection is no longer accurate.
+int CachedRoot::getAndResetSelectionEnd()
+{
+    int end = mSelectionEnd;
+    mSelectionEnd = -1;
+    return end;
+}
+
+int CachedRoot::getAndResetSelectionStart()
+{
+    int start = mSelectionStart;
+    mSelectionStart = -1;
+    return start;
+}
+
+int CachedRoot::getBlockLeftEdge(int x, int y, float scale) const
+{
+    DBG_NAV_LOGD("x=%d y=%d scale=%g mViewBounds=(%d,%d,%d,%d)", x, y, scale,
+        mViewBounds.x(), mViewBounds.y(), mViewBounds.width(),
+        mViewBounds.height());
+    // if (x, y) is in a textArea or textField, return that
+    const int slop = 1;
+    WebCore::IntRect rect = WebCore::IntRect(x - slop, y - slop,
+        slop * 2, slop * 2);
+    const CachedFrame* frame;
+    int fx, fy;
+    const CachedNode* node = findAt(rect, &frame, &fx, &fy, true);
+    if (node && node->wantsKeyEvents()) {
+        DBG_NAV_LOGD("x=%d (%s)", node->bounds(frame).x(),
+            node->isTextInput() ? "text" : "plugin");
+        return node->bounds(frame).x();
+    }
+    SkPicture* picture = node ? frame->picture(node, &x, &y) : pictureAt(&x, &y);
+    if (!picture)
+        return x;
+    int halfW = (int) (mViewBounds.width() * scale * 0.5f);
+    int fullW = halfW << 1;
+    int halfH = (int) (mViewBounds.height() * scale * 0.5f);
+    int fullH = halfH << 1;
+    LeftCheck leftCheck(fullW, halfH);
+    BoundsCanvas checker(&leftCheck);
+    SkBitmap bitmap;
+    bitmap.setConfig(SkBitmap::kARGB_8888_Config, fullW, fullH);
+    checker.setBitmapDevice(bitmap);
+    checker.translate(SkIntToScalar(fullW - x), SkIntToScalar(halfH - y));
+    checker.drawPicture(*picture);
+    int result = x + leftCheck.left() - fullW;
+    DBG_NAV_LOGD("halfW=%d halfH=%d mMostLeft=%d x=%d",
+        halfW, halfH, leftCheck.mMostLeft, result);
+    return result;
+}
+
+void CachedRoot::getSimulatedMousePosition(WebCore::IntPoint* point) const
+{
+#ifndef NDEBUG
+    ASSERT(CachedFrame::mDebug.mInUse);
+#endif
+    const WebCore::IntRect& mouseBounds = mHistory->mMouseBounds;
+    int x = mouseBounds.x();
+    int y = mouseBounds.y();
+    int width = mouseBounds.width();
+    int height = mouseBounds.height();
+    point->setX(x + (width >> 1)); // default to box center
+    point->setY(y + (height >> 1));
+#if DEBUG_NAV_UI
+    const WebCore::IntRect& navBounds = mHistory->mNavBounds;
+    DBG_NAV_LOGD("mHistory->mNavBounds={%d,%d,%d,%d} "
+        "mHistory->mMouseBounds={%d,%d,%d,%d} point={%d,%d}",
+        navBounds.x(), navBounds.y(), navBounds.width(), navBounds.height(),
+        mouseBounds.x(), mouseBounds.y(), mouseBounds.width(),
+        mouseBounds.height(), point->x(), point->y());
+#endif
+}
+
+void CachedRoot::init(WebCore::Frame* frame, CachedHistory* history)
+{
+    CachedFrame::init(this, -1, frame);
+    reset();
+    mHistory = history;
+    mPicture = NULL;
+}
+
+bool CachedRoot::innerDown(const CachedNode* test, BestData* bestData) const
+{
+    ASSERT(minWorkingVertical() >= mViewBounds.x());
+    ASSERT(maxWorkingVertical() <= mViewBounds.maxX());
+    setupScrolledBounds();
+    // (line up)
+    mScrolledBounds.setHeight(mScrolledBounds.height() + mMaxYScroll);
+    int testTop = mScrolledBounds.y();
+    int viewBottom = mViewBounds.maxY();
+    const WebCore::IntRect& navBounds = mHistory->mNavBounds;
+    if (navBounds.isEmpty() == false &&
+            navBounds.maxY() > viewBottom && viewBottom < mContents.height())
+        return false;
+    if (navBounds.isEmpty() == false) {
+        int navTop = navBounds.y();
+        int scrollBottom;
+        if (testTop < navTop && navTop < (scrollBottom = mScrolledBounds.maxY())) {
+            mScrolledBounds.setHeight(scrollBottom - navTop);
+            mScrolledBounds.setY(navTop);
+        }
+    }
+    setCursorCache(0, mMaxYScroll);
+    frameDown(test, NULL, bestData);
+    return true;
+}
+
+bool CachedRoot::innerLeft(const CachedNode* test, BestData* bestData) const
+{
+    ASSERT(minWorkingHorizontal() >= mViewBounds.y());
+    ASSERT(maxWorkingHorizontal() <= mViewBounds.maxY());
+    setupScrolledBounds();
+    mScrolledBounds.setX(mScrolledBounds.x() - mMaxXScroll);
+    mScrolledBounds.setWidth(mScrolledBounds.width() + mMaxXScroll);
+    int testRight = mScrolledBounds.maxX();
+    int viewLeft = mViewBounds.x();
+    const WebCore::IntRect& navBounds = mHistory->mNavBounds;
+    if (navBounds.isEmpty() == false &&
+            navBounds.x() < viewLeft && viewLeft > mContents.x())
+        return false;
+    if (navBounds.isEmpty() == false) {
+        int navRight = navBounds.maxX();
+        int scrollLeft;
+        if (testRight > navRight && navRight > (scrollLeft = mScrolledBounds.x()))
+            mScrolledBounds.setWidth(navRight - scrollLeft);
+    }
+    setCursorCache(-mMaxXScroll, 0);
+    frameLeft(test, NULL, bestData);
+    return true;
+}
+
+
+void CachedRoot::innerMove(const CachedNode* node, BestData* bestData,
+    Direction direction, WebCore::IntPoint* scroll, bool firstCall)
+{
+    bestData->reset();
+    bool outOfCursor = mCursorIndex == CURSOR_CLEARED;
+    DBG_NAV_LOGD("mHistory->didFirstLayout()=%s && mCursorIndex=%d",
+        mHistory->didFirstLayout() ? "true" : "false", mCursorIndex);
+    if (mHistory->didFirstLayout() && mCursorIndex < CURSOR_SET) {
+        mHistory->reset();
+        outOfCursor = true;
+    }
+    const CachedFrame* cursorFrame;
+    const CachedNode* cursor = currentCursor(&cursorFrame);
+    mHistory->setWorking(direction, cursorFrame, cursor, mViewBounds);
+    bool findClosest = false;
+    if (mScrollOnly == false) {
+        switch (direction) {
+            case LEFT:
+                if (outOfCursor)
+                    mHistory->mNavBounds = WebCore::IntRect(mViewBounds.maxX(),
+                        mViewBounds.y(), 1, mViewBounds.height());
+                findClosest = innerLeft(node, bestData);
+                break;
+            case RIGHT:
+                if (outOfCursor)
+                    mHistory->mNavBounds = WebCore::IntRect(mViewBounds.x() - 1,
+                        mViewBounds.y(), 1, mViewBounds.height());
+                findClosest = innerRight(node, bestData);
+                break;
+            case UP:
+                if (outOfCursor)
+                    mHistory->mNavBounds = WebCore::IntRect(mViewBounds.x(),
+                        mViewBounds.maxY(), mViewBounds.width(), 1);
+                findClosest = innerUp(node, bestData);
+                break;
+            case DOWN:
+                if (outOfCursor)
+                    mHistory->mNavBounds = WebCore::IntRect(mViewBounds.x(),
+                        mViewBounds.y() - 1, mViewBounds.width(), 1);
+                findClosest = innerDown(node, bestData);
+                break;
+            case UNINITIALIZED:
+            default:
+                ASSERT(0);
+        }
+    }
+    if (firstCall)
+        mHistory->mPriorBounds = mHistory->mNavBounds; // bounds always advances, even if new node is ultimately NULL
+    bestData->setMouseBounds(bestData->bounds());
+    if (adjustForScroll(bestData, direction, scroll, findClosest))
+        return;
+    if (bestData->mNode != NULL) {
+        mHistory->addToVisited(bestData->mNode, direction);
+        mHistory->mNavBounds = bestData->bounds();
+        mHistory->mMouseBounds = bestData->mouseBounds();
+    } else if (scroll->x() != 0 || scroll->y() != 0) {
+        WebCore::IntRect newBounds = mHistory->mNavBounds;
+        int offsetX = scroll->x();
+        int offsetY = scroll->y();
+        newBounds.move(offsetX, offsetY);
+        if (mViewBounds.x() > newBounds.x())
+            offsetX = mViewBounds.x() - mHistory->mNavBounds.x();
+        else if (mViewBounds.maxX() < newBounds.maxX())
+            offsetX = mViewBounds.maxX() - mHistory->mNavBounds.maxX();
+        if (mViewBounds.y() > newBounds.y())
+            offsetY = mViewBounds.y() - mHistory->mNavBounds.y();
+        else if (mViewBounds.maxY() < newBounds.maxY())
+            offsetY = mViewBounds.maxY() - mHistory->mNavBounds.maxY();
+        mHistory->mNavBounds.move(offsetX, offsetY);
+    }
+    mHistory->setDidFirstLayout(false);
+}
+
+bool CachedRoot::innerRight(const CachedNode* test, BestData* bestData) const
+{
+    ASSERT(minWorkingHorizontal() >= mViewBounds.y());
+    ASSERT(maxWorkingHorizontal() <= mViewBounds.maxY());
+    setupScrolledBounds();
+    // (align)
+    mScrolledBounds.setWidth(mScrolledBounds.width() + mMaxXScroll);
+    int testLeft = mScrolledBounds.x();
+    int viewRight = mViewBounds.maxX();
+    const WebCore::IntRect& navBounds = mHistory->mNavBounds;
+    if (navBounds.isEmpty() == false &&
+            navBounds.maxX() > viewRight && viewRight < mContents.width())
+        return false;
+    if (navBounds.isEmpty() == false) {
+        int navLeft = navBounds.x();
+        int scrollRight;
+        if (testLeft < navLeft && navLeft < (scrollRight = mScrolledBounds.maxX())) {
+            mScrolledBounds.setWidth(scrollRight - navLeft);
+            mScrolledBounds.setX(navLeft);
+        }
+    }
+    setCursorCache(mMaxXScroll, 0);
+    frameRight(test, NULL, bestData);
+    return true;
+}
+
+bool CachedRoot::innerUp(const CachedNode* test, BestData* bestData) const
+{
+    ASSERT(minWorkingVertical() >= mViewBounds.x());
+    ASSERT(maxWorkingVertical() <= mViewBounds.maxX());
+    setupScrolledBounds();
+    mScrolledBounds.setY(mScrolledBounds.y() - mMaxYScroll);
+    mScrolledBounds.setHeight(mScrolledBounds.height() + mMaxYScroll);
+    int testBottom = mScrolledBounds.maxY();
+    int viewTop = mViewBounds.y();
+    const WebCore::IntRect& navBounds = mHistory->mNavBounds;
+    if (navBounds.isEmpty() == false &&
+            navBounds.y() < viewTop && viewTop > mContents.y())
+        return false;
+    if (navBounds.isEmpty() == false) {
+        int navBottom = navBounds.maxY();
+        int scrollTop;
+        if (testBottom > navBottom && navBottom > (scrollTop = mScrolledBounds.y()))
+            mScrolledBounds.setHeight(navBottom - scrollTop);
+    }
+    setCursorCache(0, -mMaxYScroll);
+    frameUp(test, NULL, bestData);
+    return true;
+}
+
+WTF::String CachedRoot::imageURI(int x, int y) const
+{
+    DBG_NAV_LOGD("x/y=(%d,%d)", x, y);
+    ImageCheck imageCheck;
+    ImageCanvas checker(&imageCheck);
+    SkBitmap bitmap;
+    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
+    checker.setBitmapDevice(bitmap);
+    SkPicture* picture = pictureAt(&x, &y);
+    checker.translate(SkIntToScalar(-x), SkIntToScalar(-y));
+    checker.drawPicture(*picture);
+    DBG_NAV_LOGD("uri=%s", checker.getURI());
+    return WTF::String(checker.getURI());
+}
+
+bool CachedRoot::maskIfHidden(BestData* best) const
+{
+    const CachedNode* bestNode = best->mNode;
+    if (bestNode->isUnclipped())
+        return false;
+    const CachedFrame* frame = best->mFrame;
+    SkPicture* picture = frame->picture(bestNode);
+    if (picture == NULL) {
+        DBG_NAV_LOG("missing picture");
+        return false;
+    }
+    Vector<IntRect> rings;
+    bestNode->cursorRings(frame, &rings);
+    const WebCore::IntRect& bounds = bestNode->bounds(frame);
+    IntRect bitBounds;
+    calcBitBounds(bounds, &bitBounds);
+    RingCheck ringCheck(rings, bitBounds, bounds, bestNode->singleImage());
+    RingCanvas checker(&ringCheck);
+    SkBitmap bitmap;
+    bitmap.setConfig(SkBitmap::kARGB_8888_Config, bitBounds.width(),
+        bitBounds.height());
+    checker.setBitmapDevice(bitmap);
+    checker.translate(SkIntToScalar(-bitBounds.x()),
+        SkIntToScalar(-bitBounds.y()));
+    checker.drawPicture(*picture);
+    SkRegion clipRgn;
+    bool clipped = ringCheck.hiddenRings(&clipRgn);
+    CachedNode* node = const_cast<CachedNode*>(best->mNode);
+    DBG_NAV_LOGD("clipped=%s clipRgn.isEmpty=%s", clipped ? "true" : "false",
+        clipRgn.isEmpty() ? "true" : "false");
+    if (clipped && clipRgn.isEmpty()) {
+        node->setDisabled(true);
+        IntRect clippedBounds = bounds;
+        clippedBounds.intersect(bitBounds);
+        node->setClippedOut(clippedBounds != bounds);
+        return true;
+    }
+    // was it partially occluded by later drawing?
+    // if partially occluded, modify the bounds so that the mouse click has a better x,y
+    if (clipped) {
+        DBG_NAV_LOGD("clipped clipRgn={%d,%d,r=%d,b=%d}",
+            clipRgn.getBounds().fLeft, clipRgn.getBounds().fTop,
+            clipRgn.getBounds().fRight, clipRgn.getBounds().fBottom);
+        best->setMouseBounds(clipRgn.getBounds());
+        if (!node->clip(best->mouseBounds())) {
+            node->setDisabled(true);
+            node->setClippedOut(true);
+            return true;
+        }
+    } else
+        node->fixUpCursorRects(frame);
+    return false;
+}
+
+const CachedNode* CachedRoot::moveCursor(Direction direction, const CachedFrame** framePtr,
+    WebCore::IntPoint* scroll)
+{
+#ifndef NDEBUG
+    ASSERT(CachedFrame::mDebug.mInUse);
+#endif
+    CachedRoot* frame = this;
+    const CachedNode* node = frame->document();
+    if (node == NULL)
+        return NULL;
+    if (mViewBounds.isEmpty())
+        return NULL;
+    resetClippedOut();
+    setData();
+    BestData bestData;
+    innerMove(node, &bestData, direction, scroll, true);
+    // if node is partially or fully concealed by layer, scroll it into view
+    if (mRootLayer && bestData.mNode && !bestData.mNode->isInLayer()) {
+#if USE(ACCELERATED_COMPOSITING)
+#if DUMP_NAV_CACHE
+        CachedLayer::Debug::printRootLayerAndroid(mRootLayer);
+#endif
+        SkIRect original = bestData.mNode->cursorRingBounds(bestData.mFrame);
+        DBG_NAV_LOGD("original=(%d,%d,w=%d,h=%d) scroll=(%d,%d)",
+            original.fLeft, original.fTop, original.width(), original.height(),
+            scroll->x(), scroll->y());
+        original.offset(-scroll->x(), -scroll->y());
+        SkRegion rings(original);
+        SkTDArray<SkRect> region;
+        mRootLayer->clipArea(&region);
+        SkRegion layers;
+        for (int index = 0; index < region.count(); index++) {
+            SkIRect enclosing;
+            region[index].round(&enclosing);
+            rings.op(enclosing, SkRegion::kDifference_Op);
+            layers.op(enclosing, SkRegion::kUnion_Op);
+        }
+        SkIRect layerBounds(layers.getBounds());
+        SkIRect ringBounds(rings.getBounds());
+        int scrollX = scroll->x();
+        int scrollY = scroll->y();
+        if (rings.getBounds() != original) {
+            int topOverlap = layerBounds.fBottom - original.fTop;
+            int bottomOverlap = original.fBottom - layerBounds.fTop;
+            int leftOverlap = layerBounds.fRight - original.fLeft;
+            int rightOverlap = original.fRight - layerBounds.fLeft;
+            if (direction & UP_DOWN) {
+                if (layerBounds.fLeft < original.fLeft && leftOverlap < 0)
+                    scroll->setX(leftOverlap);
+                if (original.fRight < layerBounds.fRight && rightOverlap > 0
+                        && -leftOverlap > rightOverlap)
+                    scroll->setX(rightOverlap);
+                bool topSet = scrollY > topOverlap && (direction == UP
+                    || !scrollY);
+                if (topSet)
+                    scroll->setY(topOverlap);
+                if (scrollY < bottomOverlap && (direction == DOWN || (!scrollY
+                        && (!topSet || -topOverlap > bottomOverlap))))
+                    scroll->setY(bottomOverlap);
+            } else {
+                if (layerBounds.fTop < original.fTop && topOverlap < 0)
+                    scroll->setY(topOverlap);
+                if (original.fBottom < layerBounds.fBottom && bottomOverlap > 0
+                        && -topOverlap > bottomOverlap)
+                    scroll->setY(bottomOverlap);
+                bool leftSet = scrollX > leftOverlap && (direction == LEFT
+                    || !scrollX);
+                if (leftSet)
+                    scroll->setX(leftOverlap);
+                if (scrollX < rightOverlap && (direction == RIGHT || (!scrollX
+                        && (!leftSet || -leftOverlap > rightOverlap))))
+                    scroll->setX(rightOverlap);
+           }
+            DBG_NAV_LOGD("rings=(%d,%d,w=%d,h=%d) layers=(%d,%d,w=%d,h=%d)"
+                " scroll=(%d,%d)",
+                ringBounds.fLeft, ringBounds.fTop, ringBounds.width(), ringBounds.height(),
+                layerBounds.fLeft, layerBounds.fTop, layerBounds.width(), layerBounds.height(),
+                scroll->x(), scroll->y());
+        }
+#endif
+    }
+    *framePtr = bestData.mFrame;
+    return const_cast<CachedNode*>(bestData.mNode);
+}
+
+const CachedNode* CachedRoot::nextTextField(const CachedNode* start,
+        const CachedFrame** framePtr) const
+{
+    bool startFound = false;
+    return CachedFrame::nextTextField(start, framePtr, &startFound);
+}
+
+SkPicture* CachedRoot::pictureAt(int* xPtr, int* yPtr, int* id) const
+{
+#if USE(ACCELERATED_COMPOSITING)
+    if (mRootLayer) {
+        const LayerAndroid* layer = mRootLayer->find(xPtr, yPtr, mPicture);
+        if (layer) {
+            SkPicture* picture = layer->picture();
+            DBG_NAV_LOGD("layer %d picture=%p (%d,%d)", layer->uniqueId(),
+                picture, picture ? picture->width() : 0,
+                picture ? picture->height() : 0);
+            if (picture) {
+                if (id)
+                    *id = layer->uniqueId();
+                return picture;
+            }
+        }
+    }
+#endif
+    DBG_NAV_LOGD("root mPicture=%p (%d,%d)", mPicture, mPicture ?
+        mPicture->width() : 0, mPicture ? mPicture->height() : 0);
+    if (id)
+        *id = -1;
+    return mPicture;
+}
+
+void CachedRoot::reset()
+{
+#ifndef NDEBUG
+    ASSERT(CachedFrame::mDebug.mInUse);
+#endif
+    mContents = mViewBounds = WebCore::IntRect(0, 0, 0, 0);
+    mMaxXScroll = mMaxYScroll = 0;
+    mRootLayer = 0;
+    mSelectionStart = mSelectionEnd = -1;
+    mScrollOnly = false;
+}
+
+bool CachedRoot::scrollDelta(WebCore::IntRect& newOutset, Direction direction, int* delta)
+{
+    switch (direction) {
+        case LEFT:
+            *delta = -mMaxXScroll;
+            return newOutset.x() >= mViewBounds.x();
+        case RIGHT:
+            *delta = mMaxXScroll;
+            return newOutset.maxX() <= mViewBounds.maxX();
+        case UP:
+            *delta = -mMaxYScroll;
+            return newOutset.y() >= mViewBounds.y();
+        case DOWN:
+            *delta = mMaxYScroll;
+            return newOutset.maxY() <= mViewBounds.maxY();
+        default:
+            *delta = 0;
+            ASSERT(0);
+    }
+    return false;
+}
+
+void CachedRoot::setCachedFocus(CachedFrame* frame, CachedNode* node)
+{
+    mFocusBounds = WebCore::IntRect(0, 0, 0, 0);
+    if (node == NULL)
+        return;
+    node->setIsFocus(true);
+    mFocusBounds = node->bounds(frame);
+    frame->setFocusIndex(node - frame->document());
+    CachedFrame* parent;
+    while ((parent = frame->parent()) != NULL) {
+        parent->setFocusIndex(frame->indexInParent());
+        frame = parent;
+    }
+#if DEBUG_NAV_UI
+    const CachedFrame* focusFrame;
+    const CachedNode* focus = currentFocus(&focusFrame);
+    WebCore::IntRect bounds = WebCore::IntRect(0, 0, 0, 0);
+    if (focus)
+        bounds = focus->bounds(focusFrame);
+    DBG_NAV_LOGD("new focus %d (nodePointer=%p) bounds={%d,%d,%d,%d}",
+        focus ? focus->index() : 0,
+        focus ? focus->nodePointer() : NULL, bounds.x(), bounds.y(),
+        bounds.width(), bounds.height());
+#endif
+}
+
+void CachedRoot::setCursor(CachedFrame* frame, CachedNode* node)
+{
+#if DEBUG_NAV_UI
+    const CachedFrame* cursorFrame;
+    const CachedNode* cursor = currentCursor(&cursorFrame);
+    WebCore::IntRect bounds;
+    if (cursor)
+        bounds = cursor->bounds(cursorFrame);
+    DBG_NAV_LOGD("old cursor %d (nodePointer=%p) bounds={%d,%d,%d,%d}",
+        cursor ? cursor->index() : 0,
+        cursor ? cursor->nodePointer() : NULL, bounds.x(), bounds.y(),
+        bounds.width(), bounds.height());
+#endif
+    clearCursor();
+    if (node == NULL)
+        return;
+    node->setIsCursor(true);
+    node->show();
+    frame->setCursorIndex(node - frame->document());
+    CachedFrame* parent;
+    while ((parent = frame->parent()) != NULL) {
+        parent->setCursorIndex(frame->indexInParent());
+        frame = parent;
+    }
+#if DEBUG_NAV_UI
+    cursor = currentCursor(&cursorFrame);
+    bounds = WebCore::IntRect(0, 0, 0, 0);
+    if (cursor)
+        bounds = cursor->bounds(cursorFrame);
+    DBG_NAV_LOGD("new cursor %d (nodePointer=%p) bounds={%d,%d,%d,%d}",
+        cursor ? cursor->index() : 0,
+        cursor ? cursor->nodePointer() : NULL, bounds.x(), bounds.y(),
+        bounds.width(), bounds.height());
+#endif
+}
+
+void CachedRoot::setCursorCache(int scrollX, int scrollY) const
+{
+    mCursor = currentCursor();
+    if (mCursor)
+        mCursorBounds = mCursor->bounds(this);
+    if (!mRootLayer)
+        return;
+    SkRegion baseScrolled(mScrolledBounds);
+    mBaseUncovered = SkRegion(mScrolledBounds);
+#if USE(ACCELERATED_COMPOSITING)
+#if DUMP_NAV_CACHE
+    CachedLayer::Debug::printRootLayerAndroid(mRootLayer);
+#endif
+    SkTDArray<SkRect> region;
+    mRootLayer->clipArea(&region);
+    WebCore::IntSize offset(
+        copysign(min(max(0, mContents.width() - mScrolledBounds.width()),
+        abs(scrollX)), scrollX),
+        copysign(min(max(0, mContents.height() - mScrolledBounds.height()),
+        abs(scrollY)), scrollY));
+    bool hasOffset = offset.width() || offset.height();
+    // restrict scrollBounds to that which is not under layer
+    for (int index = 0; index < region.count(); index++) {
+        SkIRect less;
+        region[index].round(&less);
+        DBG_NAV_LOGD("less=(%d,%d,w=%d,h=%d)", less.fLeft, less.fTop,
+            less.width(), less.height());
+        mBaseUncovered.op(less, SkRegion::kDifference_Op);
+        if (!hasOffset)
+            continue;
+        less.offset(offset.width(), offset.height());
+        baseScrolled.op(less, SkRegion::kDifference_Op);
+    }
+    if (hasOffset)
+        mBaseUncovered.op(baseScrolled, SkRegion::kUnion_Op);
+#endif
+}
+
+#if DUMP_NAV_CACHE
+
+#define DEBUG_PRINT_BOOL(field) \
+    DUMP_NAV_LOGD("// bool " #field "=%s;\n", b->field ? "true" : "false")
+
+#define DEBUG_PRINT_RECT(field) \
+    { const WebCore::IntRect& r = b->field; \
+    DUMP_NAV_LOGD("// IntRect " #field "={%d, %d, %d, %d};\n", \
+        r.x(), r.y(), r.width(), r.height()); }
+
+CachedRoot* CachedRoot::Debug::base() const {
+    CachedRoot* nav = (CachedRoot*) ((char*) this - OFFSETOF(CachedRoot, mDebug));
+    return nav;
+}
+
+void CachedRoot::Debug::print() const
+{
+#ifdef DUMP_NAV_CACHE_USING_PRINTF
+    gWriteLogMutex.lock();
+    ASSERT(gNavCacheLogFile == NULL);
+    gNavCacheLogFile = fopen(NAV_CACHE_LOG_FILE, "a");
+#endif
+    CachedRoot* b = base();
+    b->CachedFrame::mDebug.print();
+    b->mHistory->mDebug.print(b);
+    DUMP_NAV_LOGD("// int mMaxXScroll=%d, mMaxYScroll=%d;\n",
+        b->mMaxXScroll, b->mMaxYScroll);
+    if (b->mRootLayer)
+        CachedLayer::Debug::printRootLayerAndroid(b->mRootLayer);
+#ifdef DUMP_NAV_CACHE_USING_PRINTF
+    if (gNavCacheLogFile)
+        fclose(gNavCacheLogFile);
+    gNavCacheLogFile = NULL;
+    gWriteLogMutex.unlock();
+#endif
+}
+
+#endif
+
+}
diff --git a/Source/WebKit/android/nav/CachedRoot.h b/Source/WebKit/android/nav/CachedRoot.h
new file mode 100644
index 0000000..65c6062
--- /dev/null
+++ b/Source/WebKit/android/nav/CachedRoot.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2007, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CachedRoot_h
+#define CachedRoot_h
+
+#include "CachedFrame.h"
+#include "IntRect.h"
+#include "SkPicture.h"
+#include "SkRegion.h"
+#include "wtf/Vector.h"
+
+class SkRect;
+
+namespace WebCore {
+    class LayerAndroid;
+}
+
+namespace android {
+
+class CachedHistory;
+class CachedNode;
+class FindCanvas;
+
+class CachedRoot : public CachedFrame {
+public:
+    bool adjustForScroll(BestData* , Direction , WebCore::IntPoint* scrollPtr,
+        bool findClosest);
+    const SkRegion& baseUncovered() const { return mBaseUncovered; }
+    void calcBitBounds(const IntRect& , IntRect* ) const;
+    int checkForCenter(int x, int y) const;
+    void checkForJiggle(int* ) const;
+    bool checkRings(SkPicture* , const CachedNode* ,
+        const WebCore::IntRect& testBounds) const;
+    WebCore::IntPoint cursorLocation() const;
+    int documentHeight() { return mContents.height(); }
+    int documentWidth() { return mContents.width(); }
+    void draw(FindCanvas& ) const;
+    const CachedNode* findAt(const WebCore::IntRect& , const CachedFrame** ,
+        int* x, int* y, bool checkForHidden) const;
+    const WebCore::IntRect& focusBounds() const { return mFocusBounds; }
+    WebCore::IntPoint focusLocation() const;
+    int getAndResetSelectionEnd();
+    int getAndResetSelectionStart();
+    int getBlockLeftEdge(int x, int y, float scale) const;
+    void getSimulatedMousePosition(WebCore::IntPoint* ) const;
+    void init(WebCore::Frame* , CachedHistory* );
+    bool innerDown(const CachedNode* , BestData* ) const;
+    bool innerLeft(const CachedNode* , BestData* ) const;
+    void innerMove(const CachedNode* ,BestData* bestData, Direction , 
+        WebCore::IntPoint* scroll, bool firstCall);
+    bool innerRight(const CachedNode* , BestData* ) const;
+    bool innerUp(const CachedNode* , BestData* ) const;
+    WTF::String imageURI(int x, int y) const;
+    bool maskIfHidden(BestData* ) const;
+    const CachedNode* moveCursor(Direction , const CachedFrame** , WebCore::IntPoint* scroll);
+    /**
+     * Find the next textfield/textarea
+     * @param start         The textfield/textarea to search from.
+     * @param framePtr      If non-zero, returns CachedFrame* containing result.
+     * @return CachedNode*  Next textfield/textarea or null (0) if none.
+     */
+    const CachedNode* nextTextField(const CachedNode* start,
+        const CachedFrame** framePtr) const;
+    SkPicture* pictureAt(int* xPtr, int* yPtr, int* id) const;
+    SkPicture* pictureAt(int* xPtr, int* yPtr) const {
+        return pictureAt(xPtr, yPtr, 0); }
+    void reset();
+    CachedHistory* rootHistory() const { return mHistory; }
+    WebCore::LayerAndroid* rootLayer() const { return mRootLayer; }
+    bool scrollDelta(WebCore::IntRect& cursorRingBounds, Direction , int* delta);
+    const WebCore::IntRect& scrolledBounds() const { return mScrolledBounds; }
+    void setCursor(CachedFrame* , CachedNode* );
+    void setCursorCache(int scrollX, int scrollY) const; // compute cached state used to find next cursor
+    void setCachedFocus(CachedFrame* , CachedNode* );
+    void setFocusBounds(const WebCore::IntRect& r) { mFocusBounds = r; }
+    void setTextGeneration(int textGeneration) { mTextGeneration = textGeneration; }
+    void setMaxScroll(int x, int y) { mMaxXScroll = x; mMaxYScroll = y; }
+    void setPicture(SkPicture* picture) { mPicture = picture; }
+    void setRootLayer(WebCore::LayerAndroid* layer) {
+        mRootLayer = layer;
+        resetLayers();
+    }
+    void setScrollOnly(bool state) { mScrollOnly = state; }
+    void setSelection(int start, int end) { mSelectionStart = start; mSelectionEnd = end; }
+    void setupScrolledBounds() const { mScrolledBounds = mViewBounds; }
+    void setVisibleRect(const WebCore::IntRect& r) { mViewBounds = r; }
+    int textGeneration() const { return mTextGeneration; }
+    int width() const { return mPicture ? mPicture->width() : 0; }
+private:
+    friend class CachedFrame;
+    CachedHistory* mHistory;
+    SkPicture* mPicture;
+    WebCore::LayerAndroid* mRootLayer;
+    WebCore::IntRect mFocusBounds; // dom text input focus node bounds
+    mutable WebCore::IntRect mScrolledBounds; // view bounds + amount visible as result of scroll
+    int mTextGeneration;
+    int mMaxXScroll;
+    int mMaxYScroll;
+    // These two are ONLY used when the tree is rebuilt and the focus is a textfield/area
+    int mSelectionStart;
+    int mSelectionEnd;
+    // these four set up as cache for use by frameDown/Up/Left/Right etc
+    mutable WebCore::IntRect mCursorBounds;
+    mutable const CachedNode* mCursor;
+    mutable SkRegion mBaseUncovered;
+    bool mScrollOnly;
+#if DUMP_NAV_CACHE
+public:
+    class Debug {
+public:
+        CachedRoot* base() const;
+        void print() const;
+    } mDebug;
+#endif
+};
+
+}
+
+#endif
diff --git a/Source/WebKit/android/nav/DrawExtra.cpp b/Source/WebKit/android/nav/DrawExtra.cpp
deleted file mode 100644
index 2f57dc1..0000000
--- a/Source/WebKit/android/nav/DrawExtra.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include "DrawExtra.h"
-#include "GLExtras.h"
-#include "LayerAndroid.h"
-#include "SkCanvas.h"
-#include "SkRegion.h"
-#include "WebViewCore.h"
-
-RegionLayerDrawExtra::RegionLayerDrawExtra()
-    : m_highlightColor(COLOR_HOLO_LIGHT)
-{}
-
-RegionLayerDrawExtra::~RegionLayerDrawExtra()
-{
-    HighlightRegionMap::iterator end = m_highlightRegions.end();
-    for (HighlightRegionMap::iterator it = m_highlightRegions.begin(); it != end; ++it) {
-        delete it->second;
-        it->second = 0;
-    }
-}
-
-SkRegion* RegionLayerDrawExtra::getHighlightRegionsForLayer(const LayerAndroid* layer)
-{
-    int layerId = layer ? layer->uniqueId() : 0;
-    return m_highlightRegions.get(layerId);
-}
-
-void RegionLayerDrawExtra::addHighlightRegion(const LayerAndroid* layer, const Vector<IntRect>& rects,
-                                              const IntPoint& additionalOffset)
-{
-    if (rects.isEmpty())
-        return;
-    int layerId = layer ? layer->uniqueId() : 0;
-    SkRegion* region = m_highlightRegions.get(layerId);
-    if (!region) {
-        region = new SkRegion();
-        m_highlightRegions.set(layerId, region);
-    }
-    IntPoint offset = additionalOffset;
-    WebViewCore::layerToAbsoluteOffset(layer, offset);
-    for (size_t i = 0; i < rects.size(); i++) {
-        IntRect r = rects.at(i);
-        r.move(-offset.x(), -offset.y());
-        region->op(r.x(), r.y(), r.maxX(), r.maxY(), SkRegion::kUnion_Op);
-    }
-}
-
-void RegionLayerDrawExtra::draw(SkCanvas* canvas, LayerAndroid* layer)
-{
-    SkRegion* region = getHighlightRegionsForLayer(layer);
-    if (!region || region->isEmpty())
-        return;
-    SkRegion::Iterator rgnIter(*region);
-    SkPaint paint;
-    paint.setColor(m_highlightColor.rgb());
-    while (!rgnIter.done()) {
-        const SkIRect& rect = rgnIter.rect();
-        canvas->drawIRect(rect, paint);
-        rgnIter.next();
-    }
-}
-
-void RegionLayerDrawExtra::drawGL(GLExtras* glExtras, const LayerAndroid* layer)
-{
-    SkRegion* region = getHighlightRegionsForLayer(layer);
-    if (!region || region->isEmpty())
-        return;
-    const TransformationMatrix* transform = layer ? layer->drawTransform() : 0;
-    glExtras->drawRegion(*region, true, false, transform, m_highlightColor);
-}
diff --git a/Source/WebKit/android/nav/DrawExtra.h b/Source/WebKit/android/nav/DrawExtra.h
index cc94476..6716a65 100644
--- a/Source/WebKit/android/nav/DrawExtra.h
+++ b/Source/WebKit/android/nav/DrawExtra.h
@@ -26,25 +26,11 @@
 #ifndef DrawExtra_h
 #define DrawExtra_h
 
-#include "config.h"
-
-#include "Color.h"
-#include "IntPoint.h"
-#include "IntRect.h"
-#include "wtf/HashMap.h"
-#include "wtf/Vector.h"
-
-// Color of the ring copied from framework's holo_light
-#define COLOR_HOLO_LIGHT 0x6633B5E5
-// Color of the ring copied from framework's holo_dark
-#define COLOR_HOLO_DARK 0x660099CC
-
 class SkCanvas;
-class SkRegion;
 
 namespace WebCore {
+    class IntRect;
     class LayerAndroid;
-    class GLExtras;
 }
 
 using namespace WebCore;
@@ -54,27 +40,7 @@
 class DrawExtra {
 public:
     virtual ~DrawExtra() {}
-    virtual void draw(SkCanvas*, LayerAndroid*) {}
-    virtual void drawGL(GLExtras*, const LayerAndroid*) {}
-};
-
-// A helper extra that has a SkRegion per LayerAndroid
-class RegionLayerDrawExtra : public DrawExtra {
-public:
-    RegionLayerDrawExtra();
-    virtual ~RegionLayerDrawExtra();
-
-    void addHighlightRegion(const LayerAndroid* layer, const Vector<IntRect>& rects,
-                            const IntPoint& additionalOffset = IntPoint());
-    virtual void draw(SkCanvas*, LayerAndroid*);
-    virtual void drawGL(GLExtras*, const LayerAndroid*);
-
-private:
-    SkRegion* getHighlightRegionsForLayer(const LayerAndroid* layer);
-
-    typedef HashMap<int, SkRegion* > HighlightRegionMap;
-    HighlightRegionMap m_highlightRegions;
-    Color m_highlightColor;
+    virtual void draw(SkCanvas* , LayerAndroid* , IntRect* ) = 0;
 };
 
 }
diff --git a/Source/WebKit/android/nav/FindCanvas.cpp b/Source/WebKit/android/nav/FindCanvas.cpp
new file mode 100644
index 0000000..ca3cfba
--- /dev/null
+++ b/Source/WebKit/android/nav/FindCanvas.cpp
@@ -0,0 +1,700 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "webviewglue"
+
+#include "config.h"
+#include "FindCanvas.h"
+#include "LayerAndroid.h"
+#include "IntRect.h"
+#include "SelectText.h"
+#include "SkBlurMaskFilter.h"
+#include "SkCornerPathEffect.h"
+#include "SkRect.h"
+#include "SkUtils.h"
+
+#include <utils/Log.h>
+
+#define INTEGER_OUTSET 2
+
+namespace android {
+
+// MatchInfo methods
+////////////////////////////////////////////////////////////////////////////////
+
+MatchInfo::MatchInfo() {
+    m_picture = 0;
+}
+
+MatchInfo::~MatchInfo() {
+    SkSafeUnref(m_picture);
+}
+
+MatchInfo::MatchInfo(const MatchInfo& src) {
+    m_layerId = src.m_layerId;
+    m_location = src.m_location;
+    m_picture = src.m_picture;
+    SkSafeRef(m_picture);
+}
+
+void MatchInfo::set(const SkRegion& region, SkPicture* pic, int layerId) {
+    SkSafeUnref(m_picture);
+    m_layerId = layerId;
+    m_location = region;
+    m_picture = pic;
+    SkASSERT(pic);
+    pic->ref();
+}
+
+// GlyphSet methods
+////////////////////////////////////////////////////////////////////////////////
+
+GlyphSet::GlyphSet(const SkPaint& paint, const UChar* lower, const UChar* upper,
+            size_t byteLength) {
+    SkPaint clonePaint(paint);
+    clonePaint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+    mTypeface = paint.getTypeface();
+    mCount = clonePaint.textToGlyphs(lower, byteLength, NULL);
+    if (mCount > MAX_STORAGE_COUNT) {
+        mLowerGlyphs = new uint16_t[2*mCount];
+    } else {
+        mLowerGlyphs = &mStorage[0];
+    }
+    // Use one array, and have mUpperGlyphs point to a portion of it,
+    // so that we can reduce the number of new/deletes
+    mUpperGlyphs = mLowerGlyphs + mCount;
+    int count2 = clonePaint.textToGlyphs(lower, byteLength, mLowerGlyphs);
+    SkASSERT(mCount == count2);
+    count2 = clonePaint.textToGlyphs(upper, byteLength, mUpperGlyphs);
+    SkASSERT(mCount == count2);
+}
+
+GlyphSet::~GlyphSet() {
+    // Do not need to delete mTypeface, which is not owned by us.
+    if (mCount > MAX_STORAGE_COUNT) {
+        delete[] mLowerGlyphs;
+    }   // Otherwise, we just used local storage space, so no need to delete
+    // Also do not need to delete mUpperGlyphs, which simply points to a
+    // part of mLowerGlyphs
+}
+
+GlyphSet& GlyphSet::operator=(GlyphSet& src) {
+    mTypeface = src.mTypeface;
+    mCount = src.mCount;
+    if (mCount > MAX_STORAGE_COUNT) {
+        mLowerGlyphs = new uint16_t[2*mCount];
+    } else {
+        mLowerGlyphs = &mStorage[0];
+    }
+    memcpy(mLowerGlyphs, src.mLowerGlyphs, 2*mCount*sizeof(uint16_t));
+    mUpperGlyphs = mLowerGlyphs + mCount;
+    return *this;
+}
+
+bool GlyphSet::characterMatches(uint16_t c, int index) {
+    SkASSERT(index < mCount && index >= 0);
+    return c == mLowerGlyphs[index] || c == mUpperGlyphs[index];
+}
+
+// FindCanvas methods
+////////////////////////////////////////////////////////////////////////////////
+
+FindCanvas::FindCanvas(int width, int height, const UChar* lower,
+        const UChar* upper, size_t byteLength)
+        : mLowerText(lower)
+        , mUpperText(upper)
+        , mLength(byteLength)
+        , mNumFound(0) {
+    // the text has been provided in read order. Reverse as needed so the
+    // result contains left-to-right characters.
+    const uint16_t* start = mLowerText;
+    size_t count = byteLength >> 1;
+    const uint16_t* end = mLowerText + count;
+    while (start < end) {
+        SkUnichar ch = SkUTF16_NextUnichar(&start);
+        WTF::Unicode::Direction charDirection = WTF::Unicode::direction(ch);
+        if (WTF::Unicode::RightToLeftArabic == charDirection
+                || WTF::Unicode::RightToLeft == charDirection) {
+            mLowerReversed.clear();
+            mLowerReversed.append(mLowerText, count);
+            WebCore::ReverseBidi(mLowerReversed.begin(), count);
+            mLowerText = mLowerReversed.begin();
+            mUpperReversed.clear();
+            mUpperReversed.append(mUpperText, count);
+            WebCore::ReverseBidi(mUpperReversed.begin(), count);
+            mUpperText = mUpperReversed.begin();
+            break;
+        }
+    }
+
+    setBounder(&mBounder);
+    mOutset = -SkIntToScalar(INTEGER_OUTSET);
+    mMatches = new WTF::Vector<MatchInfo>();
+    mWorkingIndex = 0;
+    mWorkingCanvas = 0;
+    mWorkingPicture = 0;
+}
+
+FindCanvas::~FindCanvas() {
+    setBounder(NULL);
+    /* Just in case getAndClear was not called. */
+    delete mMatches;
+    SkSafeUnref(mWorkingPicture);
+}
+
+// Each version of addMatch returns a rectangle for a match.
+// Not all of the parameters are used by each version.
+SkRect FindCanvas::addMatchNormal(int index,
+        const SkPaint& paint, int count, const uint16_t* glyphs,
+        const SkScalar pos[], SkScalar y) {
+    const uint16_t* lineStart = glyphs - index;
+    /* Use the original paint, since "text" is in glyphs */
+    SkScalar before = paint.measureText(lineStart, index * sizeof(uint16_t), 0);
+    SkRect rect;
+    rect.fLeft = pos[0] + before;
+    int countInBytes = count * sizeof(uint16_t);
+    rect.fRight = paint.measureText(glyphs, countInBytes, 0) + rect.fLeft;
+    SkPaint::FontMetrics fontMetrics;
+    paint.getFontMetrics(&fontMetrics);
+    SkScalar baseline = y;
+    rect.fTop = baseline + fontMetrics.fAscent;
+    rect.fBottom = baseline + fontMetrics.fDescent;
+    const SkMatrix& matrix = getTotalMatrix();
+    matrix.mapRect(&rect);
+    // Add the text to our picture.
+    SkCanvas* canvas = getWorkingCanvas();
+    int saveCount = canvas->save();
+    canvas->concat(matrix);
+    canvas->drawText(glyphs, countInBytes, pos[0] + before, y, paint);
+    canvas->restoreToCount(saveCount);
+    return rect;
+}
+
+SkRect FindCanvas::addMatchPos(int index,
+        const SkPaint& paint, int count, const uint16_t* glyphs,
+        const SkScalar xPos[], SkScalar /* y */) {
+    SkRect r;
+    r.setEmpty();
+    const SkPoint* temp = reinterpret_cast<const SkPoint*> (xPos);
+    const SkPoint* points = &temp[index];
+    int countInBytes = count * sizeof(uint16_t);
+    SkPaint::FontMetrics fontMetrics;
+    paint.getFontMetrics(&fontMetrics);
+    // Need to check each character individually, since the heights may be
+    // different.
+    for (int j = 0; j < count; j++) {
+        SkRect bounds;
+        bounds.fLeft = points[j].fX;
+        bounds.fRight = bounds.fLeft +
+                paint.measureText(&glyphs[j], sizeof(uint16_t), 0);
+        SkScalar baseline = points[j].fY;
+        bounds.fTop = baseline + fontMetrics.fAscent;
+        bounds.fBottom = baseline + fontMetrics.fDescent;
+        /* Accumulate and then add the resulting rect to mMatches */
+        r.join(bounds);
+    }
+    SkMatrix matrix = getTotalMatrix();
+    matrix.mapRect(&r);
+    SkCanvas* canvas = getWorkingCanvas();
+    int saveCount = canvas->save();
+    canvas->concat(matrix);
+    canvas->drawPosText(glyphs, countInBytes, points, paint);
+    canvas->restoreToCount(saveCount);
+    return r;
+}
+
+SkRect FindCanvas::addMatchPosH(int index,
+        const SkPaint& paint, int count, const uint16_t* glyphs,
+        const SkScalar position[], SkScalar constY) {
+    SkRect r;
+    // We only care about the positions starting at the index of our match
+    const SkScalar* xPos = &position[index];
+    // This assumes that the position array is monotonic increasing
+    // The left bounds will be the position of the left most character
+    r.fLeft = xPos[0];
+    // The right bounds will be the position of the last character plus its
+    // width
+    int lastIndex = count - 1;
+    r.fRight = paint.measureText(&glyphs[lastIndex], sizeof(uint16_t), 0)
+            + xPos[lastIndex];
+    // Grab font metrics to determine the top and bottom of the bounds
+    SkPaint::FontMetrics fontMetrics;
+    paint.getFontMetrics(&fontMetrics);
+    r.fTop = constY + fontMetrics.fAscent;
+    r.fBottom = constY + fontMetrics.fDescent;
+    const SkMatrix& matrix = getTotalMatrix();
+    matrix.mapRect(&r);
+    SkCanvas* canvas = getWorkingCanvas();
+    int saveCount = canvas->save();
+    canvas->concat(matrix);
+    canvas->drawPosTextH(glyphs, count * sizeof(uint16_t), xPos, constY, paint);
+    canvas->restoreToCount(saveCount);
+    return r;
+}
+
+void FindCanvas::drawLayers(LayerAndroid* layer) {
+#if USE(ACCELERATED_COMPOSITING)
+    SkPicture* picture = layer->picture();
+    if (picture) {
+        setLayerId(layer->uniqueId());
+        drawPicture(*picture);
+    }
+    for (int i = 0; i < layer->countChildren(); i++)
+        drawLayers(layer->getChild(i));
+#endif
+}
+
+void FindCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
+                          SkScalar y, const SkPaint& paint) {
+    findHelper(text, byteLength, paint, &x, y, &FindCanvas::addMatchNormal);
+}
+
+void FindCanvas::drawPosText(const void* text, size_t byteLength,
+                             const SkPoint pos[], const SkPaint& paint) {
+    // Pass in the first y coordinate for y so that we can check to see whether
+    // it is lower than the last draw call (to check if we are continuing to
+    // another line).
+    findHelper(text, byteLength, paint, (const SkScalar*) pos, pos[0].fY,
+            &FindCanvas::addMatchPos);
+}
+
+void FindCanvas::drawPosTextH(const void* text, size_t byteLength,
+                              const SkScalar xpos[], SkScalar constY,
+                              const SkPaint& paint) {
+    findHelper(text, byteLength, paint, xpos, constY,
+            &FindCanvas::addMatchPosH);
+}
+
+/* The current behavior is to skip substring matches. This means that in the
+ * string
+ *      batbatbat
+ * a search for
+ *      batbat
+ * will return 1 match.  If the desired behavior is to return 2 matches, define
+ * INCLUDE_SUBSTRING_MATCHES to be 1.
+ */
+#define INCLUDE_SUBSTRING_MATCHES 0
+
+// Need a quick way to know a maximum distance between drawText calls to know if
+// they are part of the same logical phrase when searching.  By crude
+// inspection, half the point size seems a good guess at the width of a space
+// character.
+static inline SkScalar approximateSpaceWidth(const SkPaint& paint) {
+    return SkScalarHalf(paint.getTextSize());
+}
+
+void FindCanvas::findHelper(const void* text, size_t byteLength,
+                          const SkPaint& paint, const SkScalar positions[], 
+                          SkScalar y,
+                          SkRect (FindCanvas::*addMatch)(int index,
+                          const SkPaint& paint, int count,
+                          const uint16_t* glyphs,
+                          const SkScalar positions[], SkScalar y)) {
+    SkASSERT(paint.getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
+    SkASSERT(mMatches);
+    GlyphSet* glyphSet = getGlyphs(paint);
+    const int count = glyphSet->getCount();
+    int numCharacters = byteLength >> 1;
+    const uint16_t* chars = (const uint16_t*) text;
+    // This block will check to see if we are continuing from another line.  If
+    // so, the user needs to have added a space, which we do not draw.
+    if (mWorkingIndex) {
+        SkPoint newY;
+        getTotalMatrix().mapXY(0, y, &newY);
+        SkIRect workingBounds = mWorkingRegion.getBounds();
+        int newYInt = SkScalarRound(newY.fY);
+        if (workingBounds.fTop > newYInt) {
+            // The new text is above the working region, so we know it's not
+            // a continuation.
+            resetWorkingCanvas();
+            mWorkingIndex = 0;
+            mWorkingRegion.setEmpty();
+        } else if (workingBounds.fBottom < newYInt) {
+            // Now we know that this line is lower than our partial match.
+            SkPaint clonePaint(paint);
+            clonePaint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
+            uint16_t space;
+            clonePaint.textToGlyphs(" ", 1, &space);
+            if (glyphSet->characterMatches(space, mWorkingIndex)) {
+                mWorkingIndex++;
+                if (mWorkingIndex == count) {
+                    // We already know that it is not clipped out because we
+                    // checked for that before saving the working region.
+                    insertMatchInfo(mWorkingRegion);
+
+                    resetWorkingCanvas();
+                    mWorkingIndex = 0;
+                    mWorkingRegion.setEmpty();
+                    // We have found a match, so continue on this line from
+                    // scratch.
+                }
+            } else {
+                resetWorkingCanvas();
+                mWorkingIndex = 0;
+                mWorkingRegion.setEmpty();
+            }
+        }
+        // If neither one is true, then we are likely continuing on the same
+        // line, but are in a new draw call because the paint has changed.  In
+        // this case, we can continue without adding a space.
+    }
+    // j is the position in the search text
+    // Start off with mWorkingIndex in case we are continuing from a prior call
+    int j = mWorkingIndex;
+    // index is the position in the drawn text
+    int index = 0;
+    for ( ; index != numCharacters; index++) {
+        if (glyphSet->characterMatches(chars[index], j)) {
+            // The jth character in the search text matches the indexth position
+            // in the drawn text, so increase j.
+            j++;
+            if (j != count) {
+                continue;
+            }
+            // The last count characters match, so we found the entire
+            // search string.
+            int remaining = count - mWorkingIndex;
+            int matchIndex = index - remaining + 1;
+            // Set up a pointer to the matching text in 'chars'.
+            const uint16_t* glyphs = chars + matchIndex;
+            SkRect rect = (this->*addMatch)(matchIndex, paint,
+                    remaining, glyphs, positions, y);
+            // We need an SkIRect for SkRegion operations.
+            SkIRect iRect;
+            rect.roundOut(&iRect);
+            // Want to outset the drawn rectangle by the same amount as
+            // mOutset
+            iRect.inset(-INTEGER_OUTSET, -INTEGER_OUTSET);
+            SkRegion regionToAdd(iRect);
+            if (!mWorkingRegion.isEmpty()) {
+                // If this is on the same line as our working region, make
+                // sure that they are close enough together that they are
+                // supposed to be part of the same text string.
+                // The width of two spaces has arbitrarily been chosen.
+                const SkIRect& workingBounds = mWorkingRegion.getBounds();
+                if (workingBounds.fTop <= iRect.fBottom &&
+                        workingBounds.fBottom >= iRect.fTop &&
+                        SkIntToScalar(iRect.fLeft - workingBounds.fRight) >
+                        approximateSpaceWidth(paint)) {
+                    index = -1;     // Will increase to 0 on next run
+                    // In this case, we need to start from the beginning of
+                    // the text being searched and our search term.
+                    j = 0;
+                    mWorkingIndex = 0;
+                    mWorkingRegion.setEmpty();
+                    continue;
+                }
+                // Add the mWorkingRegion, which contains rectangles from
+                // the previous line(s).
+                regionToAdd.op(mWorkingRegion, SkRegion::kUnion_Op);
+            }
+            insertMatchInfo(regionToAdd);
+#if INCLUDE_SUBSTRING_MATCHES
+            // Reset index to the location of the match and reset j to the
+            // beginning, so that on the next iteration of the loop, index
+            // will advance by 1 and we will compare the next character in
+            // chars to the first character in the GlyphSet.
+            index = matchIndex;
+#endif
+            // Whether the clip contained it or not, we need to start over
+            // with our recording canvas
+            resetWorkingCanvas();
+        } else {
+            // Index needs to be set to index - j + 1.
+            // This is a ridiculous case, but imagine the situation where the
+            // user is looking for the string "jjog" in the drawText call for
+            // "jjjog".  The first two letters match.  However, when the index
+            // is 2, and we discover that 'o' and 'j' do not match, we should go
+            // back to 1, where we do, in fact, have a match
+            // FIXME: This does not work if (as in our example) "jj" is in one
+            // draw call and "jog" is in the next.  Doing so would require a
+            // stack, keeping track of multiple possible working indeces and
+            // regions.  This is likely an uncommon case.
+            index = index - j;  // index will be increased by one on the next
+                                // iteration
+        }
+        // We reach here in one of two cases:
+        // 1) We just completed a match, so any working rectangle/index is no
+        // longer needed, and we will start over from the beginning
+        // 2) The glyphs do not match, so we start over at the beginning of
+        // the search string.
+        j = 0;
+        mWorkingIndex = 0;
+        mWorkingRegion.setEmpty();
+    }
+    // At this point, we have searched all of the text in the current drawText
+    // call.
+    // Keep track of a partial match that may start on this line.
+    if (j > 0) {    // if j is greater than 0, we have a partial match
+        int relativeCount = j - mWorkingIndex;  // Number of characters in this
+                                                // part of the match.
+        int partialIndex = index - relativeCount; // Index that starts our
+                                                  // partial match.
+        const uint16_t* partialGlyphs = chars + partialIndex;
+        SkRect partial = (this->*addMatch)(partialIndex, paint, relativeCount,
+                partialGlyphs, positions, y);
+        partial.inset(mOutset, mOutset);
+        SkIRect dest;
+        partial.roundOut(&dest);
+        mWorkingRegion.op(dest, SkRegion::kUnion_Op);
+        mWorkingIndex = j;
+        return;
+    }
+    // This string doesn't go into the next drawText, so reset our working
+    // variables
+    mWorkingRegion.setEmpty();
+    mWorkingIndex = 0;
+}
+
+SkCanvas* FindCanvas::getWorkingCanvas() {
+    if (!mWorkingPicture) {
+        mWorkingPicture = new SkPicture;
+        mWorkingCanvas = mWorkingPicture->beginRecording(0,0);
+    }
+    return mWorkingCanvas;
+}
+
+GlyphSet* FindCanvas::getGlyphs(const SkPaint& paint) {
+    SkTypeface* typeface = paint.getTypeface();
+    GlyphSet* end = mGlyphSets.end();
+    for (GlyphSet* ptr = mGlyphSets.begin();ptr != end; ptr++) {
+        if (ptr->getTypeface() == typeface) {
+            return ptr;
+        }
+    }
+
+    GlyphSet set(paint, mLowerText, mUpperText, mLength);
+    *mGlyphSets.append() = set;
+    return &(mGlyphSets.top());
+}
+
+void FindCanvas::insertMatchInfo(const SkRegion& region) {
+    mNumFound++;
+    mWorkingPicture->endRecording();
+    MatchInfo matchInfo;
+    mMatches->append(matchInfo);
+    LOGD("%s region=%p pict=%p layer=%d", __FUNCTION__,
+        &region, mWorkingPicture, mLayerId);
+    mMatches->last().set(region, mWorkingPicture, mLayerId);
+}
+
+void FindCanvas::resetWorkingCanvas() {
+    mWorkingPicture->unref();
+    mWorkingPicture = 0;
+    // Do not need to reset mWorkingCanvas itself because we only access it via
+    // getWorkingCanvas.
+}
+
+// This function sets up the paints that are used to draw the matches.
+void FindOnPage::setUpFindPaint() {
+    // Set up the foreground paint
+    m_findPaint.setAntiAlias(true);
+    const SkScalar roundiness = SkIntToScalar(2);
+    SkCornerPathEffect* cornerEffect = new SkCornerPathEffect(roundiness);
+    m_findPaint.setPathEffect(cornerEffect);
+    m_findPaint.setARGB(255, 132, 190, 0);
+
+    // Set up the background blur paint.
+    m_findBlurPaint.setAntiAlias(true);
+    m_findBlurPaint.setARGB(204, 0, 0, 0);
+    m_findBlurPaint.setPathEffect(cornerEffect);
+    cornerEffect->unref();
+    SkMaskFilter* blurFilter = SkBlurMaskFilter::Create(SK_Scalar1,
+            SkBlurMaskFilter::kNormal_BlurStyle);
+    m_findBlurPaint.setMaskFilter(blurFilter)->unref();
+    m_isFindPaintSetUp = true;
+}
+
+IntRect FindOnPage::currentMatchBounds() const {
+    IntRect noBounds = IntRect(0, 0, 0, 0);
+    if (!m_matches || !m_matches->size())
+        return noBounds;
+    MatchInfo& info = (*m_matches)[m_findIndex];
+    return info.getLocation().getBounds();
+}
+
+bool FindOnPage::currentMatchIsInLayer() const {
+    if (!m_matches || !m_matches->size())
+        return false;
+    MatchInfo& info = (*m_matches)[m_findIndex];
+    return info.isInLayer();
+}
+
+int FindOnPage::currentMatchLayerId() const {
+    return (*m_matches)[m_findIndex].layerId();
+}
+
+// This function is only used by findNext and setMatches.  In it, we store
+// upper left corner of the match specified by m_findIndex in
+// m_currentMatchLocation.
+void FindOnPage::storeCurrentMatchLocation() {
+    SkASSERT(m_findIndex < m_matches->size());
+    const SkIRect& bounds = (*m_matches)[m_findIndex].getLocation().getBounds();
+    m_currentMatchLocation.set(bounds.fLeft, bounds.fTop);
+    m_hasCurrentLocation = true;
+}
+
+// Put a cap on the number of matches to draw.  If the current page has more
+// matches than this, only draw the focused match.
+#define MAX_NUMBER_OF_MATCHES_TO_DRAW 101
+
+void FindOnPage::draw(SkCanvas* canvas, LayerAndroid* layer, IntRect* inval) {
+    if (!m_lastBounds.isEmpty()) {
+        inval->unite(m_lastBounds);
+        m_lastBounds.setEmpty();
+    }
+    if (!m_hasCurrentLocation || !m_matches || !m_matches->size())
+        return;
+    int layerId = layer->uniqueId();
+    if (m_findIndex >= m_matches->size())
+        m_findIndex = 0;
+    const MatchInfo& matchInfo = (*m_matches)[m_findIndex];
+    const SkRegion& currentMatchRegion = matchInfo.getLocation();
+
+    // Set up the paints used for drawing the matches
+    if (!m_isFindPaintSetUp)
+        setUpFindPaint();
+
+    // Draw the current match
+    if (matchInfo.layerId() == layerId) {
+        drawMatch(currentMatchRegion, canvas, true);
+        // Now draw the picture, so that it shows up on top of the rectangle
+        int saveCount = canvas->save();
+        SkPath matchPath;
+        currentMatchRegion.getBoundaryPath(&matchPath);
+        canvas->clipPath(matchPath);
+        canvas->drawPicture(*matchInfo.getPicture());
+        canvas->restoreToCount(saveCount);
+        const SkMatrix& matrix = canvas->getTotalMatrix();
+        const SkRect& localBounds = matchPath.getBounds();
+        SkRect globalBounds;
+        matrix.mapRect(&globalBounds, localBounds);
+        globalBounds.round(&m_lastBounds);
+        inval->unite(m_lastBounds);
+    }
+    // Draw the rest
+    unsigned numberOfMatches = m_matches->size();
+    if (numberOfMatches > 1
+            && numberOfMatches < MAX_NUMBER_OF_MATCHES_TO_DRAW) {
+        for (unsigned i = 0; i < numberOfMatches; i++) {
+            // The current match has already been drawn
+            if (i == m_findIndex)
+                continue;
+            if ((*m_matches)[i].layerId() != layerId)
+                continue;
+            const SkRegion& region = (*m_matches)[i].getLocation();
+            // Do not draw matches which intersect the current one, or if it is
+            // offscreen
+            if (currentMatchRegion.intersects(region))
+                continue;
+            SkRect bounds;
+            bounds.set(region.getBounds());
+            if (canvas->quickReject(bounds, SkCanvas::kAA_EdgeType))
+                continue;
+            drawMatch(region, canvas, false);
+        }
+    }
+}
+
+// Draw the match specified by region to the canvas.
+void FindOnPage::drawMatch(const SkRegion& region, SkCanvas* canvas,
+        bool focused)
+{
+    // For the match which has focus, use a filled paint.  For the others, use
+    // a stroked paint.
+    if (focused) {
+        m_findPaint.setStyle(SkPaint::kFill_Style);
+        m_findBlurPaint.setStyle(SkPaint::kFill_Style);
+    } else {
+        m_findPaint.setStyle(SkPaint::kStroke_Style);
+        m_findPaint.setStrokeWidth(SK_Scalar1);
+        m_findBlurPaint.setStyle(SkPaint::kStroke_Style);
+        m_findBlurPaint.setStrokeWidth(SkIntToScalar(2));
+    }
+    // Find the path for the current match
+    SkPath matchPath;
+    region.getBoundaryPath(&matchPath);
+    // Offset the path for a blurred shadow
+    SkPath blurPath;
+    matchPath.offset(SK_Scalar1, SkIntToScalar(2), &blurPath);
+    int saveCount = 0;
+    if (!focused) {
+        saveCount = canvas->save();
+        canvas->clipPath(matchPath, SkRegion::kDifference_Op);
+    }
+    // Draw the blurred background
+    canvas->drawPath(blurPath, m_findBlurPaint);
+    if (!focused)
+        canvas->restoreToCount(saveCount);
+    // Draw the foreground
+    canvas->drawPath(matchPath, m_findPaint);
+}
+
+void FindOnPage::findNext(bool forward)
+{
+    if (!m_matches || !m_matches->size() || !m_hasCurrentLocation)
+        return;
+    if (forward) {
+        m_findIndex++;
+        if (m_findIndex == m_matches->size())
+            m_findIndex = 0;
+    } else {
+        if (m_findIndex == 0) {
+            m_findIndex = m_matches->size() - 1;
+        } else {
+            m_findIndex--;
+        }
+    }
+    storeCurrentMatchLocation();
+}
+
+// With this call, WebView takes ownership of matches, and is responsible for
+// deleting it.
+void FindOnPage::setMatches(WTF::Vector<MatchInfo>* matches)
+{
+    if (m_matches)
+        delete m_matches;
+    m_matches = matches;
+    if (m_matches->size()) {
+        if (m_hasCurrentLocation) {
+            for (unsigned i = 0; i < m_matches->size(); i++) {
+                const SkIRect& rect = (*m_matches)[i].getLocation().getBounds();
+                if (rect.fLeft == m_currentMatchLocation.fX
+                        && rect.fTop == m_currentMatchLocation.fY) {
+                    m_findIndex = i;
+                    return;
+                }
+            }
+        }
+        // If we did not have a stored location, or if we were unable to restore
+        // it, store the new one.
+        m_findIndex = 0;
+        storeCurrentMatchLocation();
+    } else {
+        m_hasCurrentLocation = false;
+    }
+}
+
+}
diff --git a/Source/WebKit/android/nav/FindCanvas.h b/Source/WebKit/android/nav/FindCanvas.h
new file mode 100644
index 0000000..0fa095c
--- /dev/null
+++ b/Source/WebKit/android/nav/FindCanvas.h
@@ -0,0 +1,259 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef Find_Canvas_h
+#define Find_Canvas_h
+
+#include "DrawExtra.h"
+#include "IntRect.h"
+#include "SkBounder.h"
+#include "SkCanvas.h"
+#include "SkPicture.h"
+#include "SkRect.h"
+#include "SkRegion.h"
+#include "SkTDArray.h"
+
+#include <unicode/umachine.h>
+#include <wtf/Vector.h>
+
+namespace android {
+
+// Stores both region information and an SkPicture of the match, so that the
+// region can be drawn, followed by drawing the matching text on top of it.
+// This class owns its SkPicture
+class MatchInfo {
+public:
+    MatchInfo();
+    ~MatchInfo();
+    MatchInfo(const MatchInfo& src);
+    const SkRegion& getLocation() const { return m_location; }
+    // Return a pointer to our picture, representing the matching text.  Does
+    // not transfer ownership of the picture.
+    SkPicture* getPicture() const { return m_picture; }
+    // This will make a copy of the region, and increase the ref count on the
+    // SkPicture.  If this MatchInfo already had one, unref it.
+    void set(const SkRegion& region, SkPicture* pic, int layerId);
+    bool isInLayer() const { return m_layerId >= 0; }
+    int layerId() const { return m_layerId; }
+private:
+    MatchInfo& operator=(MatchInfo& src);
+    SkRegion    m_location;
+    SkPicture*  m_picture;
+    int         m_layerId;
+};
+
+// A class containing a typeface for reference, the length in glyphs, and
+// the upper and lower case representations of the search string.
+class GlyphSet {
+public:
+    GlyphSet(const SkPaint& paint, const UChar* lower, const UChar* upper,
+            size_t byteLength);
+    ~GlyphSet();
+    GlyphSet& operator=(GlyphSet& src);
+
+    // Return true iff c matches one of our glyph arrays at index
+    bool characterMatches(uint16_t c, int index);
+    
+    int getCount() const { return mCount; }
+
+    const SkTypeface* getTypeface() const { return mTypeface; }
+
+private:
+    // Disallow copy constructor
+    GlyphSet(GlyphSet& src) { }
+
+    // mTypeface is used for comparison only
+    const SkTypeface* mTypeface;
+    // mLowerGlyphs points to all of our storage space: the lower set followed
+    // by the upper set.  mUpperGlyphs is purely a convenience pointer to the
+    // start of the upper case glyphs.
+    uint16_t*   mLowerGlyphs;
+    uint16_t*   mUpperGlyphs;
+    // mCount is the number of glyphs of the search string.  Must be the same
+    // for both the lower case set and the upper case set.
+    int         mCount;
+
+    // Arbitrarily chose the maximum storage to use in the GlyphSet.  This is
+    // based on the length of the word being searched.  If users are always
+    // searching for 3 letter words (for example), an ideal number would be 3.
+    // Each time the user searches for a word longer than (in this case, 3) that
+    // will result in calling new/delete.
+    enum Storage {
+        MAX_STORAGE_COUNT = 16
+    };
+    // In order to eliminate new/deletes, create storage that will be enough
+    // most of the time
+    uint16_t    mStorage[2*MAX_STORAGE_COUNT];
+};
+
+class FindBounder : public SkBounder {
+public:
+    FindBounder() {}
+    ~FindBounder() {}
+protected:
+    virtual bool onIRect(const SkIRect&) { return false; }
+};
+
+class FindCanvas : public SkCanvas {
+public:
+    FindCanvas(int width, int height, const UChar* , const UChar*,
+            size_t byteLength);
+
+    virtual ~FindCanvas();
+
+    virtual void drawText(const void* text, size_t byteLength, SkScalar x,
+                          SkScalar y, const SkPaint& paint);
+
+    /* FIXME: This path has not been tested. */
+    virtual void drawPosText(const void* text, size_t byteLength,
+                             const SkPoint pos[], const SkPaint& paint);
+
+    /* Also untested */
+    virtual void drawPosTextH(const void* text, size_t byteLength,
+                              const SkScalar xpos[], SkScalar constY,
+                              const SkPaint& paint);
+
+    /* Not sure what to do here or for drawTextOnPathHV */
+    virtual void drawTextOnPath(const void* text, size_t byteLength,
+                                const SkPath& path, const SkMatrix* matrix,
+                                const SkPaint& paint) {
+    }
+
+    void drawLayers(LayerAndroid*);
+    int found() const { return mNumFound; }
+    void setLayerId(int layerId) { mLayerId = layerId; }
+
+    // This method detaches our array of matches and passes ownership to
+    // the caller, who is then responsible for deleting them.
+    WTF::Vector<MatchInfo>* detachMatches() {
+        WTF::Vector<MatchInfo>* array = mMatches;
+        mMatches = NULL;
+        return array;
+    }
+
+private:
+    // These calls are made by findHelper to store information about each match
+    // that is found.  They return a rectangle which is used to highlight the
+    // match.  They also add to our SkPicture (which can be accessed with
+    // getDrawnMatches) a draw of each match.  This way it can be drawn after
+    // the rectangle.  The rect that is returned is in device coordinates.
+    SkRect addMatchNormal(int index,
+        const SkPaint& paint, int count, const uint16_t* glyphs,
+        const SkScalar pos[], SkScalar y);
+
+    SkRect addMatchPos(int index,
+        const SkPaint& paint, int count, const uint16_t* glyphs,
+        const SkScalar xPos[], SkScalar /* y */);
+
+    SkRect addMatchPosH(int index,
+        const SkPaint& paint, int count, const uint16_t* glyphs,
+        const SkScalar position[], SkScalar constY);
+
+    // Helper for each of our draw calls
+    void findHelper(const void* text, size_t byteLength, const SkPaint& paint,
+                    const SkScalar xPos[], SkScalar y,
+                    SkRect (FindCanvas::*addMatch)(int index,
+                    const SkPaint& paint, int count, const uint16_t* glyphs,
+                    const SkScalar pos[], SkScalar y));
+
+    // If we already have a working canvas, grab it.  Otherwise, create a new
+    // one.
+    SkCanvas* getWorkingCanvas();
+
+    // Return the set of glyphs and its count for the text being searched for
+    // and the parameter paint.  If one has already been created and cached
+    // for this paint, use it.  If not, create a new one and cache it.
+    GlyphSet* getGlyphs(const SkPaint& paint);
+
+    // Store all the accumulated info about a match in our vector.
+    void insertMatchInfo(const SkRegion& region);
+
+    // Throw away our cumulative information about our working SkCanvas.  After
+    // this call, next call to getWorkingCanvas will create a new one.
+    void resetWorkingCanvas();
+
+    // Since we may transfer ownership of this array (see detachRects()), we
+    // hold a pointer to the array instead of just the array itself.
+    WTF::Vector<MatchInfo>* mMatches;
+    const UChar*            mLowerText;
+    const UChar*            mUpperText;
+    Vector<UChar>           mLowerReversed;
+    Vector<UChar>           mUpperReversed;
+    size_t                  mLength;
+    FindBounder             mBounder;
+    int                     mNumFound;
+    SkScalar                mOutset;
+    SkTDArray<GlyphSet>     mGlyphSets;
+
+    SkPicture*              mWorkingPicture;
+    SkCanvas*               mWorkingCanvas;
+    SkRegion                mWorkingRegion;
+    int                     mWorkingIndex;
+    int                     mLayerId;
+};
+
+class FindOnPage : public DrawExtra {
+public:
+    FindOnPage() {
+        m_matches = 0;
+        m_hasCurrentLocation = false;
+        m_isFindPaintSetUp = false;
+        m_lastBounds.setEmpty();
+    }
+    virtual ~FindOnPage() { if (m_matches) delete m_matches; }
+    void clearCurrentLocation() { m_hasCurrentLocation = false; }
+    IntRect currentMatchBounds() const;
+    int currentMatchIndex() const { return m_findIndex; }
+    bool currentMatchIsInLayer() const;
+    // This requires the current match to be in a layer. See
+    // currentMatchIsInLayer().
+    int currentMatchLayerId() const;
+    virtual void draw(SkCanvas* , LayerAndroid* , IntRect* );
+    void findNext(bool forward);
+    bool isCurrentLocationValid() { return m_hasCurrentLocation; }
+    void setMatches(WTF::Vector<MatchInfo>* matches);
+    WTF::Vector<MatchInfo>* matches() { return m_matches; }
+private:
+    void drawMatch(const SkRegion& region, SkCanvas* canvas, bool focused);
+    void setUpFindPaint();
+    void storeCurrentMatchLocation();
+    WTF::Vector<MatchInfo>* m_matches;
+    // Stores the location of the current match.
+    SkIPoint m_currentMatchLocation;
+    // Tells whether the value in m_currentMatchLocation is valid.
+    bool m_hasCurrentLocation;
+    // Tells whether we have done the setup to draw the Find matches.
+    bool m_isFindPaintSetUp;
+    // Paint used to draw our Find matches.
+    SkPaint m_findPaint;
+    // Paint used for the background of our Find matches.
+    SkPaint m_findBlurPaint;
+    unsigned m_findIndex;
+    SkIRect m_lastBounds;
+};
+
+}
+
+#endif  // Find_Canvas_h
diff --git a/Source/WebKit/android/nav/SelectText.cpp b/Source/WebKit/android/nav/SelectText.cpp
index 7ce32c3..d20c44a 100644
--- a/Source/WebKit/android/nav/SelectText.cpp
+++ b/Source/WebKit/android/nav/SelectText.cpp
@@ -25,20 +25,23 @@
 
 #define LOG_TAG "webviewglue"
 
-#include "config.h"
-
+#include "CachedPrefix.h"
 #include "BidiResolver.h"
 #include "BidiRunList.h"
-#include "GLExtras.h"
+#include "CachedRoot.h"
 #include "LayerAndroid.h"
+#include "ParseCanvas.h"
 #include "SelectText.h"
 #include "SkBitmap.h"
 #include "SkBounder.h"
-#include "SkCanvas.h"
+#include "SkGradientShader.h"
+#include "SkMatrix.h"
 #include "SkPicture.h"
+#include "SkPixelXorXfermode.h"
 #include "SkPoint.h"
 #include "SkRect.h"
 #include "SkRegion.h"
+#include "SkUtils.h"
 #include "TextRun.h"
 
 #ifdef DEBUG_NAV_UI
@@ -49,7 +52,7 @@
 // #define EXTRA_NOISY_LOGGING 1
 #define DEBUG_TOUCH_HANDLES 0
 #if DEBUG_TOUCH_HANDLES
-#define DBG_HANDLE_LOG(format, ...) ALOGD("%s " format, __FUNCTION__, __VA_ARGS__)
+#define DBG_HANDLE_LOG(format, ...) LOGD("%s " format, __FUNCTION__, __VA_ARGS__)
 #else
 #define DBG_HANDLE_LOG(...)
 #endif
@@ -144,3 +147,1921 @@
 
 }
 
+namespace android {
+
+#define HYPHEN_MINUS 0x2D // ASCII hyphen
+#define SOLIDUS 0x2F // ASCII slash
+#define REVERSE_SOLIDUS 0x5C // ASCII backslash
+#define HYPHEN 0x2010 // unicode hyphen, first in range of dashes
+#define HORZ_BAR 0x2015 // unicode horizontal bar, last in range of dashes
+#define TOUCH_SLOP 10 // additional distance from character rect when hit
+
+class CommonCheck : public SkBounder {
+public:
+    CommonCheck(const SkIRect& area)
+        : mArea(area)
+        , mLastUni(0)
+    {
+        mLastGlyph.fGlyphID = static_cast<uint16_t>(-1);
+        mLastCandidate.fGlyphID = static_cast<uint16_t>(-1);
+        mMatrix.reset();
+        reset();
+    }
+
+    /* called only while the picture is parsed */
+    int base() {
+        if (mBase == INT_MAX) {
+            SkPoint result;
+            mMatrix.mapXY(0, mY, &result);
+            mBase = SkScalarFloor(result.fY);
+        }
+        return mBase;
+    }
+
+    /* called only while the picture is parsed */
+     int bottom() {
+        if (mBottom == INT_MAX) {
+            SkPoint result;
+            SkPaint::FontMetrics metrics;
+            mPaint.getFontMetrics(&metrics);
+            mMatrix.mapXY(0, metrics.fDescent + mY, &result);
+            mBottom = SkScalarCeil(result.fY);
+        }
+        return mBottom;
+    }
+
+#if DEBUG_NAV_UI
+    // make current (possibily uncomputed) value visible for debugging
+    int bottomDebug() const
+    {
+        return mBottom;
+    }
+#endif
+
+    bool addNewLine(const SkBounder::GlyphRec& rec)
+    {
+        SkFixed lineSpacing = SkFixedAbs(mLastGlyph.fLSB.fY - rec.fLSB.fY);
+        SkFixed lineHeight = SkIntToFixed(bottom() - top());
+        return lineSpacing >= lineHeight + (lineHeight >> 1); // 1.5
+    }
+
+    bool addSpace(const SkBounder::GlyphRec& rec)
+    {
+        bool newBaseLine = mLastGlyph.fLSB.fY != rec.fLSB.fY;
+        if (((mLastUni >= HYPHEN && mLastUni <= HORZ_BAR)
+            || mLastUni == HYPHEN_MINUS || mLastUni == SOLIDUS
+            || mLastUni == REVERSE_SOLIDUS) && newBaseLine)
+        {
+            return false;
+        }
+        return isSpace(rec);
+    }
+
+    void finishGlyph()
+    {
+        mLastGlyph = mLastCandidate;
+        mLastUni = mLastUniCandidate;
+        mLastPaint = mLastPaintCandidate;
+    }
+
+    const SkIRect& getArea() const {
+        return mArea;
+    }
+
+    /* called only while the picture is parsed */
+    SkUnichar getUniChar(const SkBounder::GlyphRec& rec)
+    {
+        SkUnichar unichar;
+        SkPaint::TextEncoding save = mPaint.getTextEncoding();
+        mPaint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+        mPaint.glyphsToUnichars(&rec.fGlyphID, 1, &unichar);
+        mPaint.setTextEncoding(save);
+        return unichar;
+    }
+
+    bool isSpace(const SkBounder::GlyphRec& rec)
+    {
+        if (mLastGlyph.fGlyphID == static_cast<uint16_t>(-1))
+            return true;
+        DBG_NAV_LOGD("mLastGlyph=((%g, %g),(%g, %g), %d)"
+            " rec=((%g, %g),(%g, %g), %d) mLastUni=0x%04x '%c'",
+            SkFixedToScalar(mLastGlyph.fLSB.fX),
+            SkFixedToScalar(mLastGlyph.fLSB.fY),
+            SkFixedToScalar(mLastGlyph.fRSB.fX),
+            SkFixedToScalar(mLastGlyph.fRSB.fY), mLastGlyph.fGlyphID,
+            SkFixedToScalar(rec.fLSB.fX), SkFixedToScalar(rec.fLSB.fY),
+            SkFixedToScalar(rec.fRSB.fX), SkFixedToScalar(rec.fRSB.fY),
+            rec.fGlyphID,
+            mLastUni, mLastUni && mLastUni < 0x7f ? mLastUni : '?');
+        bool newBaseLine = mLastGlyph.fLSB.fY != rec.fLSB.fY;
+        if (newBaseLine)
+            return true;
+        SkFixed gapOne = mLastGlyph.fLSB.fX - rec.fRSB.fX;
+        SkFixed gapTwo = rec.fLSB.fX - mLastGlyph.fRSB.fX;
+        if (gapOne < 0 && gapTwo < 0)
+            return false; // overlaps
+        const SkBounder::GlyphRec& first = mLastGlyph.fLSB.fX < rec.fLSB.fX
+            ? mLastGlyph : rec;
+        const SkBounder::GlyphRec& second = mLastGlyph.fLSB.fX < rec.fLSB.fX
+            ? rec : mLastGlyph;
+        uint16_t firstGlyph = first.fGlyphID;
+        SkScalar firstWidth = mLastPaint.measureText(&firstGlyph, sizeof(firstGlyph));
+        SkFixed ceilWidth = SkIntToFixed(SkScalarCeil(firstWidth));
+        SkFixed posNoSpace = first.fLSB.fX + ceilWidth;
+        SkFixed ceilSpace = SkIntToFixed(SkFixedCeil(minSpaceWidth(mLastPaint)));
+        SkFixed posWithSpace = posNoSpace + ceilSpace;
+        SkFixed diffNoSpace = SkFixedAbs(second.fLSB.fX - posNoSpace);
+        SkFixed diffWithSpace = SkFixedAbs(second.fLSB.fX - posWithSpace);
+        DBG_NAV_LOGD("second=%g width=%g (%g) noSpace=%g (%g) withSpace=%g (%g)"
+            " fontSize=%g",
+            SkFixedToScalar(second.fLSB.fX),
+            firstWidth, SkFixedToScalar(ceilWidth),
+            SkFixedToScalar(posNoSpace), SkFixedToScalar(diffNoSpace),
+            SkFixedToScalar(posWithSpace), SkFixedToScalar(diffWithSpace),
+            mLastPaint.getTextSize());
+        return diffWithSpace <= diffNoSpace;
+    }
+
+    SkFixed minSpaceWidth(SkPaint& paint)
+    {
+        if (mMinSpaceWidth == SK_FixedMax) {
+            SkPaint::TextEncoding save = paint.getTextEncoding();
+            paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
+            SkScalar width = paint.measureText(" ", 1);
+            mMinSpaceWidth = SkScalarToFixed(width * mMatrix.getScaleX());
+            paint.setTextEncoding(save);
+            DBG_NAV_LOGV("width=%g matrix sx/sy=(%g, %g) tx/ty=(%g, %g)"
+                " mMinSpaceWidth=%g", width,
+                mMatrix.getScaleX(), mMatrix.getScaleY(),
+                mMatrix.getTranslateX(), mMatrix.getTranslateY(),
+                SkFixedToScalar(mMinSpaceWidth));
+        }
+        return mMinSpaceWidth;
+    }
+
+    void recordGlyph(const SkBounder::GlyphRec& rec)
+    {
+        mLastCandidate = rec;
+        mLastUniCandidate = getUniChar(rec);
+        mLastPaintCandidate = mPaint;
+    }
+
+    void reset()
+    {
+        mMinSpaceWidth = SK_FixedMax; // mark as uninitialized
+        mBase = mBottom = mTop = INT_MAX; // mark as uninitialized
+    }
+
+    void set(CommonCheck& check)
+    {
+        mLastGlyph = check.mLastGlyph;
+        mLastUni = check.mLastUni;
+        mMatrix = check.mMatrix;
+        mLastPaint = check.mLastPaint;
+        reset();
+    }
+
+    void setGlyph(CommonCheck& check)
+    {
+        mLastGlyph = check.mLastGlyph;
+        mLastUni = check.mLastUni;
+        mLastPaint = check.mLastPaint;
+    }
+
+    void setUp(const SkPaint& paint, const SkMatrix& matrix, SkScalar y,
+            const void* text)
+    {
+        mMatrix = matrix;
+        mPaint = paint;
+        mText = static_cast<const uint16_t*>(text);
+        mY = y;
+        reset();
+    }
+
+    /* called only while the picture is parsed */
+    int top() {
+        if (mTop == INT_MAX) {
+            SkPoint result;
+            SkPaint::FontMetrics metrics;
+            mPaint.getFontMetrics(&metrics);
+            mMatrix.mapXY(0, metrics.fAscent + mY, &result);
+            mTop = SkScalarFloor(result.fY);
+        }
+        return mTop;
+    }
+
+#if DEBUG_NAV_UI
+    // make current (possibily uncomputed) value visible for debugging
+    int topDebug() const
+    {
+        return mTop;
+    }
+#endif
+
+protected:
+    SkIRect mArea;
+    SkBounder::GlyphRec mLastCandidate;
+    SkBounder::GlyphRec mLastGlyph;
+    SkPaint mLastPaint; // available after picture has been parsed
+    SkPaint mLastPaintCandidate; // associated with candidate glyph
+    SkUnichar mLastUni;
+    SkUnichar mLastUniCandidate;
+    SkMatrix mMatrix;
+    SkPaint mPaint; // only set up while the picture is parsed
+    const uint16_t* mText;
+    SkScalar mY;
+private:
+    int mBase;
+    int mBottom;
+    SkFixed mMinSpaceWidth;
+    int mTop;
+    friend class EdgeCheck;
+};
+
+// generate the limit area for the new selection
+class LineCheck : public CommonCheck {
+public:
+    LineCheck(int x, int y, const SkIRect& area)
+        : INHERITED(area)
+        , mX(x)
+        , mY(y)
+        , mInBetween(false)
+    {
+        mLast.setEmpty();
+    }
+
+    void finish(const SkRegion& selectedRgn)
+    {
+        if (!mParagraphs.count() && mLast.isEmpty())
+            return;
+        processLine();
+        bool above = false;
+        bool below = false;
+        bool selected = false;
+        SkRegion localRgn(selectedRgn);
+        localRgn.translate(-mArea.fLeft, -mArea.fTop, &localRgn);
+        DBG_NAV_LOGD("localRgn=(%d,%d,%d,%d)",
+            localRgn.getBounds().fLeft, localRgn.getBounds().fTop,
+            localRgn.getBounds().fRight, localRgn.getBounds().fBottom);
+        for (int index = 0; index < mParagraphs.count(); index++) {
+            const SkIRect& rect = mParagraphs[index];
+            bool localSelected = localRgn.intersects(rect);
+            DBG_NAV_LOGD("[%d] rect=(%d,%d,%d,%d)", index, rect.fLeft, rect.fTop,
+                rect.fRight, rect.fBottom);
+            if (localSelected) {
+                DBG_NAV_LOGD("[%d] localSelected=true", index);
+                *mSelected.append() = rect;
+            }
+            if (rect.fRight <= mX || rect.fLeft >= mX)
+                continue;
+            if (mY > rect.fBottom) {
+                below = true;
+                selected |= localSelected;
+                DBG_NAV_LOGD("[%d] below=true localSelected=%s", index,
+                    localSelected ? "true" : "false");
+           }
+            if (mY < rect.fTop) {
+                above = true;
+                selected |= localSelected;
+                DBG_NAV_LOGD("[%d] above=true localSelected=%s", index,
+                    localSelected ? "true" : "false");
+            }
+        }
+        DBG_NAV_LOGD("mX=%d mY=%d above=%s below=%s selected=%s",
+            mX, mY, above ? "true" : "false", below ? "true" : "false",
+            selected ? "true" : "false");
+        mInBetween = above && below && selected;
+    }
+
+    bool inBetween() const
+    {
+        return mInBetween;
+    }
+
+    bool inColumn(const SkIRect& test) const
+    {
+        for (int index = 0; index < mSelected.count(); index++) {
+            const SkIRect& rect = mSelected[index];
+            if (rect.fRight > test.fLeft && rect.fLeft < test.fRight)
+                return true;
+        }
+        return false;
+    }
+
+    bool inColumn(int x, int y) const
+    {
+        for (int index = 0; index < mSelected.count(); index++) {
+            const SkIRect& rect = mSelected[index];
+            if (rect.contains(x, y))
+                return true;
+        }
+        return false;
+    }
+
+    virtual bool onIRect(const SkIRect& rect)
+    {
+        SkIRect bounds;
+        bounds.set(rect.fLeft, top(), rect.fRight, bottom());
+        // assume that characters must be consecutive to describe spaces
+        // (i.e., don't join rects drawn at different times)
+        if (bounds.fTop != mLast.fTop || bounds.fBottom != mLast.fBottom
+            || bounds.fLeft > mLast.fRight + minSpaceWidth(mPaint)
+            || bounds.fLeft < mLast.fLeft) {
+            processLine();
+            mLast = bounds;
+        } else
+            mLast.join(bounds);
+        return false;
+    }
+
+    void processLine()
+    {
+        // assume line spacing of 1.5
+        int lineHeight = bottom() - top();
+        mLast.inset(0, -lineHeight >> 1);
+        // collect arrays of rectangles making up glyphs below or above this one
+        for (int index = 0; index < mParagraphs.count(); index++) {
+            SkIRect& rect = mParagraphs[index];
+            if (SkIRect::Intersects(rect, mLast)) {
+                rect.join(mLast);
+                return;
+            }
+        }
+        *mParagraphs.append() = mLast;
+    }
+
+protected:
+    int mX;
+    int mY;
+    SkIRect mLast;
+    SkTDArray<SkIRect> mParagraphs;
+    SkTDArray<SkIRect> mSelected;
+    bool mInBetween;
+private:
+    typedef CommonCheck INHERITED;
+};
+
+class SelectText::FirstCheck : public CommonCheck {
+public:
+    FirstCheck(int x, int y, const SkIRect& area)
+        : INHERITED(area)
+        , mLineCheck(0)
+        , mFocusX(x - area.fLeft)
+        , mFocusY(y - area.fTop)
+        , mBestInColumn(false)
+        , mRecordGlyph(false)
+    {
+        reset();
+    }
+
+    const SkIRect& adjustedBounds(int* base)
+    {
+        *base = mBestBase + mArea.fTop;
+        mBestBounds.offset(mArea.fLeft, mArea.fTop);
+        DBG_NAV_LOGD("FirstCheck mBestBounds:(%d, %d, %d, %d) mTop=%d mBottom=%d",
+            mBestBounds.fLeft, mBestBounds.fTop, mBestBounds.fRight, 
+            mBestBounds.fBottom, topDebug(), bottomDebug());
+        return mBestBounds;
+    }
+
+    int focusX() const { return mFocusX; }
+    int focusY() const { return mFocusY; }
+
+    virtual bool onIRectGlyph(const SkIRect& rect,
+        const SkBounder::GlyphRec& rec)
+    {
+        /* compute distance from rectangle center.
+         * centerX = (rect.L + rect.R) / 2
+         * multiply centerX and comparison x by 2 to retain better precision
+         */
+        SkIRect testBounds = {rect.fLeft, top(), rect.fRight, bottom()};
+        // dx and dy are the distances from the tested edge
+        // The edge distance is paramount if the test point is far away
+        int dx = std::max(0, std::max(testBounds.fLeft - mFocusX,
+            mFocusX - testBounds.fRight));
+        int dy = std::max(0, std::max(testBounds.fTop - mFocusY,
+            mFocusY - testBounds.fBottom));
+        bool testInColumn = false;
+        bool inBetween = false;
+        bool inFocus = false;
+        if (mLineCheck) {
+            testInColumn = mLineCheck->inColumn(testBounds);
+            inBetween = mLineCheck->inBetween();
+            inFocus = mLineCheck->inColumn(mFocusX, mFocusY);
+        }
+#ifdef EXTRA_NOISY_LOGGING
+        if (dy < 10) {
+            SkUnichar ch = getUniChar(rec);
+            DBG_NAV_LOGD("FC dx/y=%d,%d mDx/y=%d,%d test=%d,%d,%d,%d"
+                " best=%d,%d,%d,%d bestIn=%s tween=%s testIn=%s focus=%s ch=%c",
+                dx, dy, mDx, mDy,
+                testBounds.fLeft, testBounds.fTop, testBounds.fRight,
+                testBounds.fBottom, mBestBounds.fLeft, mBestBounds.fTop,
+                mBestBounds.fRight, mBestBounds.fBottom, 
+                mBestInColumn ? "true" : "false", inBetween ? "true" : "false",
+                testInColumn ? "true" : "false", inFocus ? "true" : "false",
+                ch < 0x7f ? ch : '?');
+        }
+#endif
+        if ((mBestInColumn || inBetween) && !testInColumn) {
+#ifdef EXTRA_NOISY_LOGGING
+            if (dy < 10) DBG_NAV_LOG("FirstCheck reject column");
+#endif
+            return false;
+        }
+        bool ignoreColumn = mBestInColumn == testInColumn || !inFocus;
+        if (ignoreColumn && dy > 0 && (mDy < dy
+            || (mDy == dy && dx > 0 && mDx <= dx))) {
+#ifdef EXTRA_NOISY_LOGGING
+            if (dy < 10) DBG_NAV_LOG("FirstCheck reject edge");
+#endif
+            return false;
+        }
+        // cx and cy are the distances from the tested center
+        // The center distance is used when the test point is over the text
+        int cx = std::abs(((testBounds.fLeft + testBounds.fRight) >> 1)
+                - mFocusX);
+        int cy = std::abs(((testBounds.fTop + testBounds.fBottom) >> 1)
+                - mFocusY);
+        if (ignoreColumn && dy == 0 && mDy == 0) {
+            if (mCy < cy) {
+#ifdef EXTRA_NOISY_LOGGING
+                DBG_NAV_LOGD("FirstCheck reject cy=%d mCy=%d", cy, mCy);
+#endif
+                return false;
+            }
+            if (mCy == cy) {
+                if (dx == 0 && mDx == 0) {
+                    if (mCx < cx) {
+#ifdef EXTRA_NOISY_LOGGING
+                        DBG_NAV_LOGD("FirstCheck reject cx=%d mCx=%d", cx, mCx);
+#endif
+                        return false;
+                    }
+                } else if (dx > 0 && mDx <= dx) {
+#ifdef EXTRA_NOISY_LOGGING
+                    DBG_NAV_LOGD("FirstCheck reject dx=%d mDx=%d", dx, mDx);
+#endif
+                    return false;
+                }
+            }
+        }
+#ifdef EXTRA_NOISY_LOGGING
+        if (dy < 10) {
+            DBG_NAV_LOGD("FirstCheck cx/y=(%d,%d)", cx, cy);
+        }
+#endif
+        mBestBase = base();
+        mBestBounds = testBounds;
+        mBestInColumn = testInColumn;
+#ifndef EXTRA_NOISY_LOGGING
+        if (dy < 10 && dx < 10)
+#endif
+        {
+#if DEBUG_NAV_UI
+            SkUnichar ch = getUniChar(rec);
+#endif
+            DBG_NAV_LOGD("FirstCheck dx/y=(%d,%d) mFocus=(%d,%d)"
+                " mBestBounds={%d,%d,r=%d,b=%d} inColumn=%s ch=%c",
+                dx, dy, mFocusX, mFocusY,
+                mBestBounds.fLeft, mBestBounds.fTop,
+                mBestBounds.fRight, mBestBounds.fBottom,
+                mBestInColumn ? "true" : "false", ch < 0x7f ? ch : '?');
+        }
+        mCx = cx;
+        mCy = cy;
+        mDx = dx;
+        mDy = dy;
+        if (mRecordGlyph)
+            recordGlyph(rec);
+        return false;
+    }
+
+    void reset()
+    {
+        mBestBounds.setEmpty();
+        mDx = mDy = mCx = mCy = INT_MAX;
+    }
+
+    void setLines(const LineCheck* lineCheck) { mLineCheck = lineCheck; }
+    void setRecordGlyph() { mRecordGlyph = true; }
+
+protected:
+    const LineCheck* mLineCheck;
+    int mBestBase;
+    SkIRect mBestBounds;
+    int mCx;
+    int mCy;
+    int mDx;
+    int mDy;
+    int mFocusX;
+    int mFocusY;
+    bool mBestInColumn;
+    bool mRecordGlyph;
+private:
+    typedef CommonCheck INHERITED;
+};
+
+class SelectText::EdgeCheck : public SelectText::FirstCheck {
+public:
+    EdgeCheck(int x, int y, const SkIRect& area, CommonCheck& last, bool left)
+        : INHERITED(x, y, area)
+        , mLast(area)
+        , mLeft(left)
+    {
+        mLast.set(last); // CommonCheck::set()
+        setGlyph(last);
+    }
+
+    bool adjacent()
+    {
+        return !mLast.isSpace(mLastGlyph);
+    }
+
+    const SkIRect& bestBounds(int* base)
+    {
+        *base = mBestBase;
+        return mBestBounds;
+    }
+
+    virtual bool onIRectGlyph(const SkIRect& rect,
+        const SkBounder::GlyphRec& rec)
+    {
+        int dx = mLeft ? mFocusX - rect.fRight : rect.fLeft - mFocusX;
+        int dy = ((top() + bottom()) >> 1) - mFocusY;
+        dx = abs(dx);
+        dy = abs(dy);
+        if (mLeft ? mFocusX <= rect.fLeft : mFocusX >= rect.fRight) {
+            if (dx <= 10 && dy <= 10) {
+                DBG_NAV_LOGD("EdgeCheck fLeft=%d fRight=%d mFocusX=%d dx=%d dy=%d",
+                    rect.fLeft, rect.fRight, mFocusX, dx, dy);
+            }
+            return false;
+        }
+        if (mDy > dy || (mDy == dy && mDx > dx)) {
+            if (rec.fLSB == mLastGlyph.fLSB && rec.fRSB == mLastGlyph.fRSB) {
+                DBG_NAV_LOGD("dup rec.fLSB.fX=%g rec.fRSB.fX=%g",
+                SkFixedToScalar(rec.fLSB.fX), SkFixedToScalar(rec.fRSB.fX));
+                return false;
+            }
+            recordGlyph(rec);
+            mDx = dx;
+            mDy = dy;
+            mBestBase = base();
+            mBestBounds.set(rect.fLeft, top(), rect.fRight, bottom());
+            if (dx <= 10 && dy <= 10) {
+                DBG_NAV_LOGD("EdgeCheck mBestBounds={%d,%d,r=%d,b=%d} dx/y=(%d, %d)",
+                    mBestBounds.fLeft, mBestBounds.fTop,
+                    mBestBounds.fRight, mBestBounds.fBottom, dx, dy);
+            }
+        }
+        return false;
+    }
+
+    void shiftStart(SkIRect bounds)
+    {
+        DBG_NAV_LOGD("EdgeCheck mFocusX=%d mLeft=%s bounds.fLeft=%d bounds.fRight=%d",
+            mFocusX, mLeft ? "true" : "false", bounds.fLeft, bounds.fRight);
+        reset();
+        mFocusX = mLeft ? bounds.fLeft : bounds.fRight;
+        mLast.set(*this); // CommonCheck::set()
+    }
+
+protected:
+    CommonCheck mLast;
+    bool mLeft;
+private:
+    typedef SelectText::FirstCheck INHERITED;
+};
+
+class FindFirst : public CommonCheck {
+public:
+    FindFirst(const SkIRect& area)
+        : INHERITED(area)
+    {
+        mBestBounds.set(area.width(), area.height(), area.width(), area.height());
+    }
+
+    const SkIRect& bestBounds(int* base)
+    {
+        *base = mBestBase;
+        return mBestBounds;
+    }
+
+    virtual bool onIRect(const SkIRect& rect)
+    {
+        if (mBestBounds.isEmpty()) {
+            mBestBase = base();
+            mBestBounds.set(rect.fLeft, top(), rect.fRight, bottom());
+        }
+        return false;
+    }
+
+protected:
+    int mBestBase;
+    SkIRect mBestBounds;
+private:
+    typedef CommonCheck INHERITED;
+};
+
+class FindLast : public FindFirst {
+public:
+    FindLast(const SkIRect& area)
+        : INHERITED(area)
+    {
+        mBestBounds.setEmpty();
+    }
+
+    virtual bool onIRect(const SkIRect& rect)
+    {
+        mBestBase = base();
+        mBestBounds.set(rect.fLeft, top(), rect.fRight, bottom());
+        return false;
+    }
+
+private:
+    typedef FindFirst INHERITED;
+};
+
+static bool baseLinesAgree(const SkIRect& rectA, int baseA,
+    const SkIRect& rectB, int baseB)
+{
+    return (rectA.fTop < baseB && rectA.fBottom >= baseB)
+        || (rectB.fTop < baseA && rectB.fBottom >= baseA);
+}
+
+class BuilderCheck : public CommonCheck {
+protected:
+    enum IntersectionType {
+        NO_INTERSECTION, // debugging printf expects this to equal zero
+        LAST_INTERSECTION, // debugging printf expects this to equal one
+        WAIT_FOR_INTERSECTION
+    };
+
+    BuilderCheck(const SkIRect& start, int startBase, const SkIRect& end,
+        int endBase, const SkIRect& area)
+        : INHERITED(area)
+        , mCapture(false)
+        , mEnd(end)
+        , mEndBase(endBase)
+        , mStart(start)
+        , mStartBase(startBase)
+    {
+        mEnd.offset(-area.fLeft, -area.fTop);
+        mEndBase -= area.fTop;
+        mEndExtra.setEmpty();
+        mLast.setEmpty();
+        mLastBase = INT_MAX;
+        mSelectRect.setEmpty();
+        mStart.offset(-area.fLeft, -area.fTop);
+        mStartBase -= area.fTop;
+        mStartExtra.setEmpty();
+        DBG_NAV_LOGD(" mStart=(%d,%d,r=%d,b=%d) mStartBase=%d"
+            " mEnd=(%d,%d,r=%d,b=%d) mEndBase=%d",
+            mStart.fLeft, mStart.fTop, mStart.fRight, mStart.fBottom, mStartBase,
+            mEnd.fLeft, mEnd.fTop, mEnd.fRight, mEnd.fBottom, mEndBase);
+    }
+
+    int checkFlipRect(const SkIRect& full, int fullBase) {
+        mCollectFull = false;
+        // is the text to collect between the selection top and bottom?
+        if (fullBase < mStart.fTop || fullBase > mEnd.fBottom) {
+            if (VERBOSE_LOGGING && !mLast.isEmpty()) DBG_NAV_LOGD("%s 1"
+                " full=(%d,%d,r=%d,b=%d) fullBase=%d"
+                " mLast=(%d,%d,r=%d,b=%d) mLastBase=%d",
+                mLastIntersects ? "LAST_INTERSECTION" : "NO_INTERSECTION",
+                full.fLeft, full.fTop, full.fRight, full.fBottom, fullBase,
+                mLast.fLeft, mLast.fTop, mLast.fRight, mLast.fBottom, mLastBase);
+            return mLastIntersects;
+        }
+        // is the text to the left of the selection start?
+        if (baseLinesAgree(mStart, mStartBase, full, fullBase)
+            && full.fLeft < mStart.fLeft) {
+            if (VERBOSE_LOGGING) DBG_NAV_LOGD("%s 2"
+                " full=(%d,%d,r=%d,b=%d) fullBase=%d"
+                " mLast=(%d,%d,r=%d,b=%d) mLastBase=%d"
+                " mStart=(%d,%d,r=%d,b=%d) mStartBase=%d",
+                mLastIntersects ? "LAST_INTERSECTION" : "NO_INTERSECTION",
+                full.fLeft, full.fTop, full.fRight, full.fBottom, fullBase,
+                mLast.fLeft, mLast.fTop, mLast.fRight, mLast.fBottom, mLastBase,
+                mStart.fLeft, mStart.fTop, mStart.fRight, mStart.fBottom, mStartBase);
+            mStartExtra.join(full);
+            return mLastIntersects;
+        }
+        // is the text to the right of the selection end?
+        if (baseLinesAgree(mEnd, mEndBase, full, fullBase)
+            && full.fRight > mEnd.fRight) {
+            if (VERBOSE_LOGGING) DBG_NAV_LOGD("%s 3"
+                " full=(%d,%d,r=%d,b=%d) fullBase=%d"
+                " mLast=(%d,%d,r=%d,b=%d) mLastBase=%d"
+                " mEnd=(%d,%d,r=%d,b=%d) mEndBase=%d",
+                mLastIntersects ? "LAST_INTERSECTION" : "NO_INTERSECTION",
+                full.fLeft, full.fTop, full.fRight, full.fBottom, fullBase,
+                mLast.fLeft, mLast.fTop, mLast.fRight, mLast.fBottom, mLastBase,
+                mEnd.fLeft, mEnd.fTop, mEnd.fRight, mEnd.fBottom, mEndBase);
+            mEndExtra.join(full);
+            return mLastIntersects;
+        }
+        int spaceGap = SkFixedRound(minSpaceWidth(mPaint) * 3);
+        // should text to the left of the start be added to the selection bounds?
+        if (!mStartExtra.isEmpty()) {
+            if (VERBOSE_LOGGING) DBG_NAV_LOGD("mSelectRect=(%d,%d,r=%d,b=%d)"
+                " mStartExtra=(%d,%d,r=%d,b=%d)",
+                mSelectRect.fLeft, mSelectRect.fTop, mSelectRect.fRight, mSelectRect.fBottom,
+                mStartExtra.fLeft, mStartExtra.fTop, mStartExtra.fRight, mStartExtra.fBottom);
+            if (mStartExtra.fRight + spaceGap >= mStart.fLeft)
+                mSelectRect.join(mStartExtra);
+            mStartExtra.setEmpty();
+        }
+        // should text to the right of the end be added to the selection bounds?
+        if (!mEndExtra.isEmpty()) {
+            if (VERBOSE_LOGGING) DBG_NAV_LOGD("mSelectRect=(%d,%d,r=%d,b=%d)"
+                " mEndExtra=(%d,%d,r=%d,b=%d)",
+                mSelectRect.fLeft, mSelectRect.fTop, mSelectRect.fRight, mSelectRect.fBottom,
+                mEndExtra.fLeft, mEndExtra.fTop, mEndExtra.fRight, mEndExtra.fBottom);
+            if (mEndExtra.fLeft - spaceGap <= mEnd.fRight)
+                mSelectRect.join(mEndExtra);
+            mEndExtra.setEmpty();
+        }
+        bool sameBaseLine = baseLinesAgree(mLast, mLastBase, full, fullBase);
+        bool adjacent = (full.fLeft - mLast.fRight) < spaceGap;
+        // is this the first, or are there more characters on the same line?
+        if (mLast.isEmpty() || (sameBaseLine && adjacent)) {
+            if (VERBOSE_LOGGING) DBG_NAV_LOGD("WAIT_FOR_INTERSECTION"
+                " full=(%d,%d,r=%d,b=%d) fullBase=%d"
+                " mLast=(%d,%d,r=%d,b=%d) mLastBase=%d"
+                " mSelectRect=(%d,%d,r=%d,b=%d)",
+                full.fLeft, full.fTop, full.fRight, full.fBottom, fullBase,
+                mLast.fLeft, mLast.fTop, mLast.fRight, mLast.fBottom, mLastBase,
+                mSelectRect.fLeft, mSelectRect.fTop, mSelectRect.fRight, mSelectRect.fBottom);
+            mLast.join(full);
+            mLastIntersects = SkIRect::Intersects(mLast, mSelectRect);
+            return WAIT_FOR_INTERSECTION;
+        }
+        if (VERBOSE_LOGGING) DBG_NAV_LOGD("%s 4"
+            " mLast=(%d,%d,r=%d,b=%d) mLastBase=%d"
+            " full=(%d,%d,r=%d,b=%d) fullBase=%d"
+            " mSelectRect=(%d,%d,r=%d,b=%d)"
+            " mStartExtra=(%d,%d,r=%d,b=%d)"
+            " mEndExtra=(%d,%d,r=%d,b=%d)",
+            mLastIntersects ? "LAST_INTERSECTION" : "NO_INTERSECTION",
+            mLast.fLeft, mLast.fTop, mLast.fRight, mLast.fBottom, mLastBase,
+            full.fLeft, full.fTop, full.fRight, full.fBottom, fullBase,
+            mSelectRect.fLeft, mSelectRect.fTop, mSelectRect.fRight, mSelectRect.fBottom,
+            mStartExtra.fLeft, mStartExtra.fTop, mStartExtra.fRight, mStartExtra.fBottom,
+            mEndExtra.fLeft, mEndExtra.fTop, mEndExtra.fRight, mEndExtra.fBottom);
+        // after the caller determines what to do with the last collection,
+        // start the collection over with full and fullBase.
+        mCollectFull = true;
+        return mLastIntersects;
+    }
+
+    bool resetLast(const SkIRect& full, int fullBase)
+    {
+        if (mCollectFull) {
+            mLast = full;
+            mLastBase = fullBase;
+            mLastIntersects = SkIRect::Intersects(mLast, mSelectRect);
+        } else {
+            mLast.setEmpty();
+            mLastBase = INT_MAX;
+            mLastIntersects = false;
+        }
+        return mCollectFull;
+    }
+
+    void setFlippedState()
+    {
+        mSelectRect = mStart;
+        mSelectRect.join(mEnd);
+        DBG_NAV_LOGD("mSelectRect=(%d,%d,r=%d,b=%d)",
+            mSelectRect.fLeft, mSelectRect.fTop, mSelectRect.fRight, mSelectRect.fBottom);
+        mLast.setEmpty();
+        mLastBase = INT_MAX;
+        mLastIntersects = NO_INTERSECTION;
+    }
+
+    bool mCapture;
+    bool mCollectFull;
+    SkIRect mEnd;
+    int mEndBase;
+    SkIRect mEndExtra;
+    bool mFlipped;
+    SkIRect mLast;
+    int mLastBase;
+    int mLastIntersects;
+    SkIRect mSelectRect;
+    SkIRect mStart;
+    SkIRect mStartExtra;
+    int mStartBase;
+private:
+    typedef CommonCheck INHERITED;
+
+};
+
+class MultilineBuilder : public BuilderCheck {
+public:
+    MultilineBuilder(const SkIRect& start, int startBase, const SkIRect& end,
+            int endBase, const SkIRect& area, SkRegion* region)
+        : INHERITED(start, startBase, end, endBase, area)
+        , mSelectRegion(region)
+    {
+        mFlipped = false;
+    }
+
+    void addLastToRegion() {
+        if (VERBOSE_LOGGING) DBG_NAV_LOGD(" mLast=(%d,%d,r=%d,b=%d)",
+            mLast.fLeft, mLast.fTop, mLast.fRight, mLast.fBottom);
+        mSelectRegion->op(mLast, SkRegion::kUnion_Op);
+    }
+
+    void finish() {
+        if (!mFlipped || !mLastIntersects)
+            return;
+        addLastToRegion();
+    }
+
+    // return true if capture end was not found after capture begin
+    bool flipped() {
+        DBG_NAV_LOGD("flipped=%s", mCapture ? "true" : "false");
+        if (!mCapture)
+            return false;
+        mFlipped = true;
+        setFlippedState();
+        mSelectRegion->setEmpty();
+        return true;
+    }
+
+    virtual bool onIRect(const SkIRect& rect) {
+        SkIRect full;
+        full.set(rect.fLeft, top(), rect.fRight, bottom());
+        int fullBase = base();
+        if (mFlipped) {
+            int intersectType = checkFlipRect(full, fullBase);
+            if (intersectType == LAST_INTERSECTION)
+                addLastToRegion();
+            if (intersectType != WAIT_FOR_INTERSECTION)
+                resetLast(full, fullBase);
+            return false;
+        }
+        if (full == mStart) {
+            if (VERBOSE_LOGGING) DBG_NAV_LOGD("full == mStart full=(%d,%d,r=%d,b=%d)",
+                full.fLeft, full.fTop, full.fRight, full.fBottom);
+            mCapture = true;
+        }
+        if (mCapture) {
+            bool sameLines = baseLinesAgree(mLast, mLastBase, full, fullBase);
+            if (sameLines)
+                mLast.join(full);
+            if (!sameLines || full == mEnd) {
+                if (VERBOSE_LOGGING) DBG_NAV_LOGD("finish mLast=(%d,%d,r=%d,b=%d)",
+                    mLast.fLeft, mLast.fTop, mLast.fRight, mLast.fBottom);
+                addLastToRegion();
+                mLast = full;
+                mLastBase = fullBase;
+            }
+        }
+        if (full == mEnd) {
+            if (VERBOSE_LOGGING) DBG_NAV_LOGD("full == mEnd full=(%d,%d,r=%d,b=%d)",
+                full.fLeft, full.fTop, full.fRight, full.fBottom);
+            mCapture = false;
+            if (full == mStart)
+                addLastToRegion();
+        }
+        return false;
+    }
+
+protected:
+    SkRegion* mSelectRegion;
+private:
+    typedef BuilderCheck INHERITED;
+};
+
+static inline bool compareBounds(const SkIRect* first, const SkIRect* second)
+{
+    return first->fTop < second->fTop;
+}
+
+class TextExtractor : public BuilderCheck {
+public:
+    TextExtractor(const SkIRect& start, int startBase, const SkIRect& end,
+        int endBase, const SkIRect& area, bool flipped)
+        : INHERITED(start, startBase, end, endBase, area)
+        , mSelectStartIndex(-1)
+        , mSkipFirstSpace(true) // don't start with a space
+    {
+        mFlipped = flipped;
+        if (flipped)
+            setFlippedState();
+    }
+
+    void addCharacter(const SkBounder::GlyphRec& rec)
+    {
+        if (mSelectStartIndex < 0)
+            mSelectStartIndex = mSelectText.count();
+        if (!mSkipFirstSpace) {
+            if (addNewLine(rec)) {
+                DBG_NAV_LOG("write new line");
+                *mSelectText.append() = '\n';
+                *mSelectText.append() = '\n';
+            } else if (addSpace(rec)) {
+                DBG_NAV_LOG("write space");
+                *mSelectText.append() = ' ';
+            }
+        } else
+            mSkipFirstSpace = false;
+        recordGlyph(rec);
+        finishGlyph();
+        if (VERBOSE_LOGGING) DBG_NAV_LOGD("glyphID=%d uni=%d '%c'", rec.fGlyphID,
+            mLastUni, mLastUni && mLastUni < 0x7f ? mLastUni : '?');
+        if (mLastUni) {
+            uint16_t chars[2];
+            size_t count = SkUTF16_FromUnichar(mLastUni, chars);
+            *mSelectText.append() = chars[0];
+            if (count == 2)
+                *mSelectText.append() = chars[1];
+        }
+    }
+
+    void addLast()
+    {
+        *mSelectBounds.append() = mLast;
+        *mSelectStart.append() = mSelectStartIndex;
+        *mSelectEnd.append() = mSelectText.count();
+    }
+
+    /* Text characters are collected before it's been determined that the
+       characters are part of the selection. The bounds describe valid parts
+       of the selection, but the bounds are out of order.
+
+       This sorts the characters by sorting the bounds, then copying the
+       characters that were captured.
+     */
+    void finish()
+    {
+        if (mLastIntersects)
+            addLast();
+        Vector<SkIRect*> sortedBounds;
+        SkTDArray<uint16_t> temp;
+        int index;
+        DBG_NAV_LOGD("mSelectBounds.count=%d text=%d", mSelectBounds.count(),
+            mSelectText.count());
+        for (index = 0; index < mSelectBounds.count(); index++)
+            sortedBounds.append(&mSelectBounds[index]);
+        std::sort(sortedBounds.begin(), sortedBounds.end(), compareBounds);
+        int lastEnd = -1;
+        for (index = 0; index < mSelectBounds.count(); index++) {
+            int order = sortedBounds[index] - &mSelectBounds[0];
+            int start = mSelectStart[order];
+            int end = mSelectEnd[order];
+            DBG_NAV_LOGD("order=%d start=%d end=%d top=%d", order, start, end,
+                mSelectBounds[order].fTop);
+            int count = temp.count();
+            if (count > 0 && temp[count - 1] != '\n' && start != lastEnd) {
+                // always separate paragraphs when original text is out of order
+                DBG_NAV_LOG("write new line");
+                *temp.append() = '\n';
+                *temp.append() = '\n';
+            }
+            temp.append(end - start, &mSelectText[start]);
+            lastEnd = end;
+        }
+        mSelectText.swap(temp);
+    }
+
+    virtual bool onIRectGlyph(const SkIRect& rect,
+        const SkBounder::GlyphRec& rec)
+    {
+        SkIRect full;
+        full.set(rect.fLeft, top(), rect.fRight, bottom());
+        int fullBase = base();
+        if (mFlipped) {
+            int intersectType = checkFlipRect(full, fullBase);
+            if (WAIT_FOR_INTERSECTION == intersectType)
+                addCharacter(rec); // may not be copied
+            else {
+                if (LAST_INTERSECTION == intersectType)
+                    addLast();
+                else
+                    mSkipFirstSpace = true;
+                mSelectStartIndex = -1;
+                if (resetLast(full, fullBase))
+                    addCharacter(rec); // may not be copied
+            }
+            return false;
+        }
+        if (full == mStart)
+            mCapture = true;
+        if (mCapture)
+            addCharacter(rec);
+        else
+            mSkipFirstSpace = true;
+        if (full == mEnd)
+            mCapture = false;
+        return false;
+    }
+
+    WTF::String text() {
+        if (mFlipped)
+            finish();
+        // the text has been copied in visual order. Reverse as needed if
+        // result contains right-to-left characters.
+        const uint16_t* start = mSelectText.begin();
+        const uint16_t* end = mSelectText.end();
+        while (start < end) {
+            SkUnichar ch = SkUTF16_NextUnichar(&start);
+            WTF::Unicode::Direction charDirection = WTF::Unicode::direction(ch);
+            if (WTF::Unicode::RightToLeftArabic == charDirection
+                    || WTF::Unicode::RightToLeft == charDirection) {
+                WebCore::ReverseBidi(mSelectText.begin(), mSelectText.count());
+                break;
+            }
+        }
+        return WTF::String(mSelectText.begin(), mSelectText.count());
+    }
+
+protected:
+    SkIRect mEmpty;
+    SkTDArray<SkIRect> mSelectBounds;
+    SkTDArray<int> mSelectEnd;
+    SkTDArray<int> mSelectStart;
+    int mSelectStartIndex;
+    SkTDArray<uint16_t> mSelectText;
+    bool mSkipFirstSpace;
+private:
+    typedef BuilderCheck INHERITED;
+};
+
+class TextCanvas : public ParseCanvas {
+public:
+
+    TextCanvas(CommonCheck* bounder)
+            : mBounder(*bounder) {
+        setBounder(bounder);
+        SkBitmap bitmap;
+        const SkIRect& area = bounder->getArea();
+        bitmap.setConfig(SkBitmap::kARGB_8888_Config, area.width(), 
+            area.height());
+        setBitmapDevice(bitmap);
+        translate(SkIntToScalar(-area.fLeft), SkIntToScalar(-area.fTop));
+#ifdef DEBUG_NAV_UI
+        const SkIRect& clip = getTotalClip().getBounds();
+        const SkMatrix& matrix = getTotalMatrix();
+        DBG_NAV_LOGD("bitmap=(%d,%d) clip=(%d,%d,%d,%d) matrix=(%g,%g)",
+            bitmap.width(), bitmap.height(), clip.fLeft, clip.fTop,
+            clip.fRight, clip.fBottom, matrix.getTranslateX(), matrix.getTranslateY());
+#endif
+    }
+
+    virtual void drawPaint(const SkPaint& paint) {
+    }
+
+    virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
+                            const SkPaint& paint) {
+    }
+
+    virtual void drawRect(const SkRect& rect, const SkPaint& paint) {
+    }
+
+    virtual void drawPath(const SkPath& path, const SkPaint& paint) {
+    }
+
+    virtual void commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* rect,
+                              const SkMatrix& matrix, const SkPaint& paint) {
+    }
+
+    virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
+                            const SkPaint* paint = NULL) {
+    }
+
+    virtual void drawText(const void* text, size_t byteLength, SkScalar x, 
+                          SkScalar y, const SkPaint& paint) {
+        mBounder.setUp(paint, getTotalMatrix(), y, text);
+        INHERITED::drawText(text, byteLength, x, y, paint);
+    }
+
+    virtual void drawPosTextH(const void* text, size_t byteLength,
+                              const SkScalar xpos[], SkScalar constY,
+                              const SkPaint& paint) {
+        mBounder.setUp(paint, getTotalMatrix(), constY, text);
+        INHERITED::drawPosTextH(text, byteLength, xpos, constY, paint);
+    }
+
+    virtual void drawVertices(VertexMode vmode, int vertexCount,
+                              const SkPoint vertices[], const SkPoint texs[],
+                              const SkColor colors[], SkXfermode* xmode,
+                              const uint16_t indices[], int indexCount,
+                              const SkPaint& paint) {
+    }
+
+    CommonCheck& mBounder;
+private:
+    typedef ParseCanvas INHERITED;
+};
+
+static bool buildSelection(const SkPicture& picture, const SkIRect& area,
+        const SkIRect& selStart, int startBase,
+        const SkIRect& selEnd, int endBase, SkRegion* region)
+{
+    DBG_NAV_LOGD("area=(%d, %d, %d, %d) selStart=(%d, %d, %d, %d)"
+        " selEnd=(%d, %d, %d, %d)",
+        area.fLeft, area.fTop, area.fRight, area.fBottom,
+        selStart.fLeft, selStart.fTop, selStart.fRight, selStart.fBottom,
+        selEnd.fLeft, selEnd.fTop, selEnd.fRight, selEnd.fBottom);
+    MultilineBuilder builder(selStart, startBase, selEnd, endBase, area, region);
+    TextCanvas checker(&builder);
+    checker.drawPicture(const_cast<SkPicture&>(picture));
+    bool flipped = builder.flipped();
+    if (flipped) {
+        TextCanvas checker(&builder);
+        checker.drawPicture(const_cast<SkPicture&>(picture));
+    }
+    builder.finish();
+    region->translate(area.fLeft, area.fTop);
+    return flipped;
+}
+
+static SkIRect findFirst(const SkPicture& picture, int* base)
+{
+    SkIRect area;
+    area.set(0, 0, picture.width(), picture.height());
+    FindFirst finder(area);
+    TextCanvas checker(&finder);
+    checker.drawPicture(const_cast<SkPicture&>(picture));
+    return finder.bestBounds(base);
+}
+
+static SkIRect findLast(const SkPicture& picture, int* base)
+{
+    SkIRect area;
+    area.set(0, 0, picture.width(), picture.height());
+    FindLast finder(area);
+    TextCanvas checker(&finder);
+    checker.drawPicture(const_cast<SkPicture&>(picture));
+    return finder.bestBounds(base);
+}
+
+static WTF::String text(const SkPicture& picture, const SkIRect& area,
+        const SkIRect& start, int startBase, const SkIRect& end,
+        int endBase, bool flipped)
+{
+    TextExtractor extractor(start, startBase, end, endBase, area, flipped);
+    TextCanvas checker(&extractor);
+    checker.drawPicture(const_cast<SkPicture&>(picture));
+    return extractor.text();
+}
+
+#define CONTROL_NOTCH 16
+// TODO: Now that java is the one actually drawing these, get the real values
+// from the drawable itself
+#define CONTROL_HEIGHT 47
+#define CONTROL_WIDTH 26
+#define CONTROL_SLOP 5
+#define STROKE_WIDTH 1.0f
+#define STROKE_OUTSET 3.5f
+#define STROKE_I_OUTSET 4 // (int) ceil(STROKE_OUTSET)
+#define STROKE_COLOR 0x66000000
+#define OUTER_COLOR 0x33000000
+#define INNER_COLOR 0xe6aae300
+
+SelectText::SelectText()
+    : m_controlWidth(CONTROL_WIDTH)
+    , m_controlHeight(CONTROL_HEIGHT)
+    , m_controlSlop(CONTROL_SLOP)
+{
+    m_picture = 0;
+    reset();
+    SkPaint paint;
+    SkRect oval;
+
+    SkPath startOuterPath;
+    oval.set(-CONTROL_WIDTH - STROKE_OUTSET, CONTROL_NOTCH - STROKE_OUTSET,
+        -CONTROL_WIDTH + STROKE_OUTSET, CONTROL_NOTCH + STROKE_OUTSET);
+    startOuterPath.arcTo(oval, 180, 45, true);
+    oval.set(-STROKE_OUTSET, -STROKE_OUTSET,  STROKE_OUTSET, STROKE_OUTSET);
+    startOuterPath.arcTo(oval, 180 + 45, 135, false);
+    oval.set(-STROKE_OUTSET, CONTROL_HEIGHT - STROKE_OUTSET,
+        STROKE_OUTSET, CONTROL_HEIGHT + STROKE_OUTSET);
+    startOuterPath.arcTo(oval, 0, 90, false);
+    oval.set(-CONTROL_WIDTH - STROKE_OUTSET, CONTROL_HEIGHT - STROKE_OUTSET,
+        -CONTROL_WIDTH + STROKE_OUTSET, CONTROL_HEIGHT + STROKE_OUTSET);
+    startOuterPath.arcTo(oval, 90, 90, false);
+    startOuterPath.close();
+    SkPath startInnerPath;
+    startInnerPath.moveTo(-CONTROL_WIDTH, CONTROL_NOTCH);
+    startInnerPath.lineTo(-CONTROL_WIDTH, CONTROL_HEIGHT);
+    startInnerPath.lineTo(0, CONTROL_HEIGHT);
+    startInnerPath.lineTo(0, 0);
+    startInnerPath.close();
+    startOuterPath.addPath(startInnerPath, 0, 0);
+
+    SkCanvas* canvas = m_startControl.beginRecording(
+        CONTROL_WIDTH + STROKE_OUTSET * 2,
+        CONTROL_HEIGHT + STROKE_OUTSET * 2);
+    paint.setAntiAlias(true);
+    paint.setColor(INNER_COLOR);
+    paint.setStyle(SkPaint::kFill_Style);
+    canvas->drawPath(startInnerPath, paint);
+    paint.setColor(OUTER_COLOR);
+    canvas->drawPath(startOuterPath, paint);
+    paint.setStyle(SkPaint::kStroke_Style);
+    paint.setColor(STROKE_COLOR);
+    paint.setStrokeWidth(STROKE_WIDTH);
+    canvas->drawPath(startInnerPath, paint);
+    m_startControl.endRecording();
+
+    SkPath endOuterPath;
+    oval.set(-STROKE_OUTSET, -STROKE_OUTSET,  STROKE_OUTSET, STROKE_OUTSET);
+    endOuterPath.arcTo(oval, 180, 135, true);
+    oval.set(CONTROL_WIDTH - STROKE_OUTSET, CONTROL_NOTCH - STROKE_OUTSET,
+        CONTROL_WIDTH + STROKE_OUTSET, CONTROL_NOTCH + STROKE_OUTSET);
+    endOuterPath.arcTo(oval, 360 - 45, 45, false);
+    oval.set(CONTROL_WIDTH - STROKE_OUTSET, CONTROL_HEIGHT - STROKE_OUTSET,
+        CONTROL_WIDTH + STROKE_OUTSET, CONTROL_HEIGHT + STROKE_OUTSET);
+    endOuterPath.arcTo(oval, 0, 90, false);
+    oval.set(-STROKE_OUTSET, CONTROL_HEIGHT - STROKE_OUTSET,
+        STROKE_OUTSET, CONTROL_HEIGHT + STROKE_OUTSET);
+    endOuterPath.arcTo(oval, 90, 90, false);
+    startOuterPath.close();
+    SkPath endInnerPath;
+    endInnerPath.moveTo(0, 0);
+    endInnerPath.lineTo(0, CONTROL_HEIGHT);
+    endInnerPath.lineTo(CONTROL_WIDTH, CONTROL_HEIGHT);
+    endInnerPath.lineTo(CONTROL_WIDTH, CONTROL_NOTCH);
+    endInnerPath.close();
+    endOuterPath.addPath(endInnerPath, 0, 0);
+
+    canvas = m_endControl.beginRecording(CONTROL_WIDTH + STROKE_OUTSET * 2,
+        CONTROL_HEIGHT + STROKE_OUTSET * 2);
+    paint.setColor(INNER_COLOR);
+    paint.setStyle(SkPaint::kFill_Style);
+    canvas->drawPath(endInnerPath, paint);
+    paint.setColor(OUTER_COLOR);
+    canvas->drawPath(endOuterPath, paint);
+    paint.setStyle(SkPaint::kStroke_Style);
+    paint.setColor(STROKE_COLOR);
+    paint.setStrokeWidth(STROKE_WIDTH);
+    canvas->drawPath(endInnerPath, paint);
+    m_endControl.endRecording();
+}
+
+SelectText::~SelectText()
+{
+    SkSafeUnref(m_picture);
+}
+
+void SelectText::draw(SkCanvas* canvas, LayerAndroid* layer, IntRect* inval)
+{
+    if (m_layerId != layer->uniqueId())
+        return;
+    // reset m_picture to match m_layerId
+    SkSafeUnref(m_picture);
+    m_picture = layer->picture();
+    SkSafeRef(m_picture);
+    DBG_NAV_LOGD("m_extendSelection=%d m_drawPointer=%d layer [%d]",
+        m_extendSelection, m_drawPointer, layer->uniqueId());
+    if (m_extendSelection)
+        drawSelectionRegion(canvas, inval);
+    if (m_drawPointer)
+        drawSelectionPointer(canvas, inval);
+}
+
+static void addInval(IntRect* inval, const SkCanvas* canvas,
+        const SkRect& bounds) {
+    const SkMatrix& matrix = canvas->getTotalMatrix();
+    SkRect transformed;
+    matrix.mapRect(&transformed, bounds);
+    SkIRect iTrans;
+    transformed.round(&iTrans);
+    inval->unite(iTrans);
+}
+
+void SelectText::drawSelectionPointer(SkCanvas* canvas, IntRect* inval)
+{
+    SkPath path;
+    if (m_extendSelection)
+        getSelectionCaret(&path);
+    else
+        getSelectionArrow(&path);
+    SkPixelXorXfermode xorMode(SK_ColorWHITE);
+    SkPaint paint;
+    paint.setAntiAlias(true);
+    paint.setStyle(SkPaint::kStroke_Style);
+    paint.setColor(SK_ColorBLACK);
+    if (m_extendSelection)
+        paint.setXfermode(&xorMode);
+    else
+        paint.setStrokeWidth(SK_Scalar1 * 2);
+    int sc = canvas->save();
+    canvas->scale(m_inverseScale, m_inverseScale);
+    canvas->translate(m_selectX, m_selectY);
+    canvas->drawPath(path, paint);
+    if (!m_extendSelection) {
+        paint.setStyle(SkPaint::kFill_Style);
+        paint.setColor(SK_ColorWHITE);
+        canvas->drawPath(path, paint);
+    }
+    SkRect bounds = path.getBounds();
+    bounds.inset(-SK_Scalar1 * 2, -SK_Scalar1 * 2); // stroke width
+    addInval(inval, canvas, bounds);
+    canvas->restoreToCount(sc);
+}
+
+static void addStart(SkRegion* diff, const SkIRect& rect)
+{
+    SkIRect bounds;
+    bounds.set(rect.fLeft - CONTROL_WIDTH - STROKE_I_OUTSET,
+        rect.fBottom - STROKE_I_OUTSET, rect.fLeft + STROKE_I_OUTSET,
+        rect.fBottom + CONTROL_HEIGHT + STROKE_I_OUTSET);
+    diff->op(bounds, SkRegion::kUnion_Op);
+}
+
+static void addEnd(SkRegion* diff, const SkIRect& rect)
+{
+    SkIRect bounds;
+    bounds.set(rect.fRight - STROKE_I_OUTSET, rect.fBottom - STROKE_I_OUTSET,
+        rect.fRight + CONTROL_WIDTH + STROKE_I_OUTSET,
+        rect.fBottom + CONTROL_HEIGHT + STROKE_I_OUTSET);
+    diff->op(bounds, SkRegion::kUnion_Op);
+}
+
+void SelectText::getSelectionRegion(const IntRect& vis, SkRegion *region,
+                                    LayerAndroid* root)
+{
+    SkIRect ivisBounds = vis;
+    ivisBounds.join(m_selStart);
+    ivisBounds.join(m_selEnd);
+    region->setEmpty();
+    buildSelection(*m_picture, ivisBounds, m_selStart, m_startBase,
+        m_selEnd, m_endBase, region);
+    if (root && m_layerId) {
+        Layer* layer = root->findById(m_layerId);
+        while (layer) {
+            const SkPoint& pos = layer->getPosition();
+            region->translate(pos.fX, pos.fY);
+            layer = layer->getParent();
+        }
+    }
+}
+
+void SelectText::drawSelectionRegion(SkCanvas* canvas, IntRect* inval)
+{
+    if (!m_picture)
+        return;
+    SkIRect ivisBounds = m_visibleRect;
+    ivisBounds.join(m_selStart);
+    ivisBounds.join(m_selEnd);
+    DBG_NAV_LOGD("m_selStart=(%d,%d,r=%d,b=%d) m_selEnd=(%d,%d,r=%d,b=%d)"
+        " ivisBounds=(%d,%d,r=%d,b=%d)",
+        m_selStart.fLeft, m_selStart.fTop, m_selStart.fRight, m_selStart.fBottom,
+        m_selEnd.fLeft, m_selEnd.fTop, m_selEnd.fRight, m_selEnd.fBottom,
+        ivisBounds.fLeft, ivisBounds.fTop, ivisBounds.fRight, ivisBounds.fBottom);
+    if (m_lastSelRegion != m_selRegion)
+        m_lastSelRegion.set(m_selRegion);
+    SkRegion diff(m_lastSelRegion);
+    m_selRegion.setEmpty();
+    m_flipped = buildSelection(*m_picture, ivisBounds, m_selStart, m_startBase,
+        m_selEnd, m_endBase, &m_selRegion);
+    SkPath path;
+    m_selRegion.getBoundaryPath(&path);
+    path.setFillType(SkPath::kEvenOdd_FillType);
+
+    SkPaint paint;
+    paint.setAntiAlias(true);
+    paint.setColor(SkColorSetARGB(0x80, 0x83, 0xCC, 0x39));
+    canvas->drawPath(path, paint);
+    // experiment to draw touchable controls that resize the selection
+    float scale = m_controlHeight / (float)CONTROL_HEIGHT;
+    canvas->save();
+    canvas->translate(m_selStart.fLeft, m_selStart.fBottom);
+    canvas->scale(scale, scale);
+    canvas->drawPicture(m_startControl);
+    canvas->restore();
+    canvas->save();
+    canvas->translate(m_selEnd.fRight, m_selEnd.fBottom);
+    canvas->scale(scale, scale);
+    canvas->drawPicture(m_endControl);
+    canvas->restore();
+
+#if DEBUG_TOUCH_HANDLES
+    SkRect touchHandleRect;
+    paint.setColor(SkColorSetARGB(0x60, 0xFF, 0x00, 0x00));
+    touchHandleRect.set(0, m_selStart.fBottom, m_selStart.fLeft, 0);
+    touchHandleRect.fBottom = touchHandleRect.fTop + m_controlHeight;
+    touchHandleRect.fLeft = touchHandleRect.fRight - m_controlWidth;
+    canvas->drawRect(touchHandleRect, paint);
+    touchHandleRect.inset(-m_controlSlop, -m_controlSlop);
+    canvas->drawRect(touchHandleRect, paint);
+    touchHandleRect.set(m_selEnd.fRight, m_selEnd.fBottom, 0, 0);
+    touchHandleRect.fBottom = touchHandleRect.fTop + m_controlHeight;
+    touchHandleRect.fRight = touchHandleRect.fLeft + m_controlWidth;
+    canvas->drawRect(touchHandleRect, paint);
+    touchHandleRect.inset(-m_controlSlop, -m_controlSlop);
+    canvas->drawRect(touchHandleRect, paint);
+#endif
+
+    SkIRect a = diff.getBounds();
+    SkIRect b = m_selRegion.getBounds();
+    diff.op(m_selRegion, SkRegion::kXOR_Op);
+    SkIRect c = diff.getBounds();
+    DBG_NAV_LOGD("old=(%d,%d,r=%d,b=%d) new=(%d,%d,r=%d,b=%d) diff=(%d,%d,r=%d,b=%d)",
+        a.fLeft, a.fTop, a.fRight, a.fBottom, b.fLeft, b.fTop, b.fRight, b.fBottom,
+        c.fLeft, c.fTop, c.fRight, c.fBottom);
+    DBG_NAV_LOGD("lastStart=(%d,%d,r=%d,b=%d) m_lastEnd=(%d,%d,r=%d,b=%d)",
+        m_lastStart.fLeft, m_lastStart.fTop, m_lastStart.fRight, m_lastStart.fBottom,
+        m_lastEnd.fLeft, m_lastEnd.fTop, m_lastEnd.fRight, m_lastEnd.fBottom);
+    if (!m_lastDrawnStart.isEmpty())
+        addStart(&diff, m_lastDrawnStart);
+    if (m_lastStart != m_selStart) {
+        m_lastDrawnStart = m_lastStart;
+        m_lastStart = m_selStart;
+    }
+    addStart(&diff, m_selStart);
+    if (!m_lastDrawnEnd.isEmpty())
+        addEnd(&diff, m_lastDrawnEnd);
+    if (m_lastEnd != m_selEnd) {
+        m_lastDrawnEnd = m_lastEnd;
+        m_lastEnd = m_selEnd;
+    }
+    addEnd(&diff, m_selEnd);
+    SkIRect iBounds = diff.getBounds();
+    DBG_NAV_LOGD("diff=(%d,%d,r=%d,b=%d)",
+        iBounds.fLeft, iBounds.fTop, iBounds.fRight, iBounds.fBottom);
+    SkRect bounds;
+    bounds.set(iBounds);
+    addInval(inval, canvas, bounds);
+}
+
+void SelectText::extendSelection(const IntRect& vis, int x, int y)
+{
+    if (!m_picture)
+        return;
+    setVisibleRect(vis);
+    SkIRect clipRect = m_visibleRect;
+    int base;
+    DBG_NAV_LOGD("extend x/y=%d,%d m_startOffset=%d,%d", x, y,
+        m_startOffset.fX, m_startOffset.fY);
+    x -= m_startOffset.fX;
+    y -= m_startOffset.fY;
+    if (m_startSelection) {
+        if (!clipRect.contains(x, y)
+                || !clipRect.contains(m_original.fX, m_original.fY)) {
+            clipRect.set(m_original.fX, m_original.fY, x, y);
+            clipRect.sort();
+            clipRect.inset(-m_visibleRect.width(), -m_visibleRect.height());
+        }
+        FirstCheck center(m_original.fX, m_original.fY, clipRect);
+        m_selStart = m_selEnd = findClosest(center, *m_picture, &base);
+        if (m_selStart.isEmpty())
+            return;
+        DBG_NAV_LOGD("selStart clip=(%d,%d,%d,%d) m_original=%d,%d"
+            " m_selStart=(%d,%d,%d,%d)", clipRect.fLeft, clipRect.fTop,
+            clipRect.fRight, clipRect.fBottom, m_original.fX, m_original.fY,
+            m_selStart.fLeft, m_selStart.fTop, m_selStart.fRight, m_selStart.fBottom);
+        m_startBase = m_endBase = base;
+        m_startSelection = false;
+        m_extendSelection = true;
+        m_original.fX = m_original.fY = 0;
+    }
+    DBG_NAV_LOGD("extend x/y=%d,%d m_original=%d,%d", x, y,
+        m_original.fX, m_original.fY);
+    x -= m_original.fX;
+    y -= m_original.fY;
+    if (!clipRect.contains(x, y) || !clipRect.contains(m_selStart)) {
+        clipRect.set(m_selStart.fLeft, m_selStart.fTop, x, y);
+        clipRect.sort();
+        clipRect.inset(-m_visibleRect.width(), -m_visibleRect.height());
+    }
+    DBG_NAV_LOGD("extend clip=(%d,%d,%d,%d) x/y=%d,%d wordSel=%s outsideWord=%s",
+        clipRect.fLeft, clipRect.fTop, clipRect.fRight, clipRect.fBottom, x, y,
+        m_wordSelection ? "true" : "false", m_outsideWord ? "true" : "false");
+    FirstCheck extension(x, y, clipRect);
+    SkIRect found = findClosest(extension, *m_picture, &base);
+    if (m_wordSelection) {
+        SkIRect wordBounds = m_wordBounds;
+        if (!m_outsideWord)
+            wordBounds.inset(-TOUCH_SLOP, -TOUCH_SLOP);
+        DBG_NAV_LOGD("x=%d y=%d wordBounds=(%d,%d,r=%d,b=%d)"
+            " found=(%d,%d,r=%d,b=%d)", x, y, wordBounds.fLeft, wordBounds.fTop,
+            wordBounds.fRight, wordBounds.fBottom, found.fLeft, found.fTop,
+            found.fRight, found.fBottom);
+        if (wordBounds.contains(x, y)) {
+            DBG_NAV_LOG("wordBounds.contains=true");
+            m_outsideWord = false;
+            return;
+        }
+        m_outsideWord = true;
+        if (found.fBottom <= wordBounds.fTop)
+            m_hitTopLeft = true;
+        else if (found.fTop >= wordBounds.fBottom)
+            m_hitTopLeft = false;
+        else
+            m_hitTopLeft = (found.fLeft + found.fRight)
+                < (wordBounds.fLeft + wordBounds.fRight);
+    }
+    DBG_NAV_LOGD("x=%d y=%d m_startSelection=%s %s=(%d, %d, %d, %d)"
+        " m_extendSelection=%s",
+        x, y, m_startSelection ? "true" : "false",
+        m_hitTopLeft ? "m_selStart" : "m_selEnd",
+        found.fLeft, found.fTop, found.fRight, found.fBottom,
+        m_extendSelection ? "true" : "false");
+    if (m_hitTopLeft) {
+        m_startBase = base;
+        m_selStart = found;
+    } else {
+        m_endBase = base;
+        m_selEnd = found;
+    }
+    swapAsNeeded();
+}
+
+SkIRect SelectText::findClosest(FirstCheck& check, const SkPicture& picture,
+        int* base)
+{
+    LineCheck lineCheck(check.focusX(), check.focusY(), check.getArea());
+    TextCanvas lineChecker(&lineCheck);
+    lineChecker.drawPicture(const_cast<SkPicture&>(picture));
+    lineCheck.finish(m_selRegion);
+    check.setLines(&lineCheck);
+    TextCanvas checker(&check);
+    checker.drawPicture(const_cast<SkPicture&>(picture));
+    check.finishGlyph();
+    return check.adjustedBounds(base);
+}
+
+SkIRect SelectText::findEdge(const SkPicture& picture, const SkIRect& area,
+        int x, int y, bool left, int* base)
+{
+    SkIRect result;
+    result.setEmpty();
+    FirstCheck center(x, y, area);
+    center.setRecordGlyph();
+    int closestBase;
+    SkIRect closest = findClosest(center, picture, &closestBase);
+    SkIRect sloppy = closest;
+    sloppy.inset(-TOUCH_SLOP, -TOUCH_SLOP);
+    if (!sloppy.contains(x, y)) {
+        DBG_NAV_LOGD("sloppy=(%d, %d, %d, %d) area=(%d, %d, %d, %d) x/y=%d,%d",
+            sloppy.fLeft, sloppy.fTop, sloppy.fRight, sloppy.fBottom,
+            area.fLeft, area.fTop, area.fRight, area.fBottom, x, y);
+        return result;
+    }
+    EdgeCheck edge(x, y, area, center, left);
+    do { // detect left or right until there's a gap
+        DBG_NAV_LOGD("edge=%p picture=%p area=%d,%d,%d,%d",
+            &edge, &picture, area.fLeft, area.fTop, area.fRight, area.fBottom);
+        TextCanvas checker(&edge);
+        checker.drawPicture(const_cast<SkPicture&>(picture));
+        edge.finishGlyph();
+        if (!edge.adjacent()) {
+            if (result.isEmpty()) {
+                *base = closestBase;
+                DBG_NAV_LOGD("closest=%d,%d,%d,%d", closest.fLeft,
+                    closest.fTop, closest.fRight, closest.fBottom);
+                return closest;
+            }
+            DBG_NAV_LOG("adjacent break");
+            break;
+        }
+        int nextBase;
+        const SkIRect& next = edge.bestBounds(&nextBase);
+        if (next.isEmpty()) {
+            DBG_NAV_LOG("empty");
+            break;
+        }
+        if (result == next) {
+            DBG_NAV_LOG("result == next");
+            break;
+        }
+        *base = nextBase;
+        result = next;
+        edge.shiftStart(result);
+    } while (true);
+    if (!result.isEmpty()) {
+        *base += area.fTop;
+        result.offset(area.fLeft, area.fTop);
+    }
+    return result;
+}
+
+SkIRect SelectText::findLeft(const SkPicture& picture, const SkIRect& area,
+        int x, int y, int* base)
+{
+    return findEdge(picture, area, x, y, true, base);
+}
+
+SkIRect SelectText::findRight(const SkPicture& picture, const SkIRect& area,
+        int x, int y, int* base)
+{
+    return findEdge(picture, area, x, y, false, base);
+}
+
+const String SelectText::getSelection()
+{
+    if (!m_picture)
+        return String();
+    SkIRect clipRect;
+    clipRect.set(0, 0, m_picture->width(), m_picture->height());
+    String result = text(*m_picture, clipRect, m_selStart, m_startBase,
+        m_selEnd, m_endBase, m_flipped);
+    DBG_NAV_LOGD("clip=(%d,%d,%d,%d)"
+        " m_selStart=(%d, %d, %d, %d) m_selEnd=(%d, %d, %d, %d)",
+        clipRect.fLeft, clipRect.fTop, clipRect.fRight, clipRect.fBottom,
+        m_selStart.fLeft, m_selStart.fTop, m_selStart.fRight, m_selStart.fBottom,
+        m_selEnd.fLeft, m_selEnd.fTop, m_selEnd.fRight, m_selEnd.fBottom);
+    DBG_NAV_LOGD("text=%s", result.latin1().data()); // uses CString
+    return result;
+}
+
+void SelectText::getSelectionArrow(SkPath* path)
+{
+    const int arrow[] = {
+        0, 14, 3, 11, 5, 15, 9, 15, 7, 11, 11, 11
+    };
+    for (unsigned index = 0; index < sizeof(arrow)/sizeof(arrow[0]); index += 2)
+        path->lineTo(arrow[index], arrow[index + 1]);
+    path->close();
+}
+
+void SelectText::getSelectionCaret(SkPath* path)
+{
+    SkScalar height = m_selStart.fBottom - m_selStart.fTop;
+    SkScalar dist = height / 4;
+    path->moveTo(0, -height / 2);
+    path->rLineTo(0, height);
+    path->rLineTo(-dist, dist);
+    path->rMoveTo(0, -0.5f);
+    path->rLineTo(dist * 2, 0);
+    path->rMoveTo(0, 0.5f);
+    path->rLineTo(-dist, -dist);
+}
+
+bool SelectText::hitCorner(int cx, int cy, int x, int y) const
+{
+    SkIRect test;
+    test.set(cx, cy, cx + m_controlWidth, cy + m_controlHeight);
+    test.inset(-m_controlSlop, -m_controlSlop);
+    DBG_HANDLE_LOG("checking if %dx%d,%d-%d contains %dx%d",
+                   cx, cy, m_controlWidth, m_controlHeight, x,  y);
+    return test.contains(x, y);
+}
+
+bool SelectText::hitStartHandle(int x, int y) const
+{
+    int left = m_selStart.fLeft - m_controlWidth;
+    return hitCorner(left, m_selStart.fBottom, x, y);
+}
+
+bool SelectText::hitEndHandle(int x, int y) const
+{
+    int left = m_selEnd.fRight;
+    return hitCorner(left, m_selEnd.fBottom, x, y);
+}
+
+bool SelectText::hitSelection(int x, int y) const
+{
+    x -= m_startOffset.fX;
+    y -= m_startOffset.fY;
+    if (hitStartHandle(x, y))
+        return true;
+    if (hitEndHandle(x, y))
+        return true;
+    return m_selRegion.contains(x, y);
+}
+
+void SelectText::getSelectionHandles(int* handles, LayerAndroid* root)
+{
+    handles[0] = m_selStart.fLeft;
+    handles[1] = m_selStart.fBottom;
+    handles[2] = m_selEnd.fRight;
+    handles[3] = m_selEnd.fBottom;
+    if (root && m_layerId) {
+        Layer* layer = root->findById(m_layerId);
+        while (layer) {
+            const SkPoint& pos = layer->getPosition();
+            handles[0] += pos.fX;
+            handles[2] += pos.fX;
+            handles[1] += pos.fY;
+            handles[3] += pos.fY;
+            layer = layer->getParent();
+        }
+    }
+}
+
+void SelectText::moveSelection(const IntRect& vis, int x, int y)
+{
+    if (!m_picture)
+        return;
+    x -= m_startOffset.fX;
+    y -= m_startOffset.fY;
+    setVisibleRect(vis);
+    SkIRect clipRect = m_visibleRect;
+    clipRect.join(m_selStart);
+    clipRect.join(m_selEnd);
+    FirstCheck center(x, y, clipRect);
+    int base;
+    SkIRect found = findClosest(center, *m_picture, &base);
+    if (m_hitTopLeft || !m_extendSelection) {
+        m_startBase = base;
+        m_selStart = found;
+    }
+    if (!m_hitTopLeft || !m_extendSelection) {
+        m_endBase = base;
+        m_selEnd = found;
+    }
+    swapAsNeeded();
+    DBG_NAV_LOGD("x=%d y=%d extendSelection=%s m_selStart=(%d, %d, %d, %d)"
+        " m_selEnd=(%d, %d, %d, %d)", x, y, m_extendSelection ? "true" : "false",
+        m_selStart.fLeft, m_selStart.fTop, m_selStart.fRight, m_selStart.fBottom,
+        m_selEnd.fLeft, m_selEnd.fTop, m_selEnd.fRight, m_selEnd.fBottom);
+}
+
+void SelectText::reset()
+{
+    DBG_NAV_LOG("m_extendSelection=false");
+    m_selStart.setEmpty();
+    m_lastStart.setEmpty();
+    m_lastDrawnStart.setEmpty();
+    m_selEnd.setEmpty();
+    m_lastEnd.setEmpty();
+    m_lastDrawnEnd.setEmpty();
+    m_extendSelection = false;
+    m_startSelection = false;
+    SkSafeUnref(m_picture);
+    m_picture = 0;
+    m_layerId = 0;
+}
+
+IntPoint SelectText::selectableText(const CachedRoot* root)
+{
+    int x = 0;
+    int y = 0;
+    SkPicture* picture = root->pictureAt(&x, &y, &m_layerId);
+    if (!picture) {
+        DBG_NAV_LOG("picture==0");
+        return IntPoint(0, 0);
+    }
+    int width = picture->width();
+    int height = picture->height();
+    IntRect vis(0, 0, width, height);
+    FirstCheck center(width >> 1, height >> 1, vis);
+    int base;
+    const SkIRect& closest = findClosest(center, *picture, &base);
+    return IntPoint((closest.fLeft + closest.fRight) >> 1,
+        (closest.fTop + closest.fBottom) >> 1);
+}
+
+void SelectText::selectAll()
+{
+    if (!m_picture)
+        return;
+    m_selStart = findFirst(*m_picture, &m_startBase);
+    m_selEnd = findLast(*m_picture, &m_endBase);
+    m_extendSelection = true;
+}
+
+int SelectText::selectionX() const
+{
+    return (m_hitTopLeft ? m_selStart.fLeft : m_selEnd.fRight) + m_startOffset.fX;
+}
+
+int SelectText::selectionY() const
+{
+    const SkIRect& rect = m_hitTopLeft ? m_selStart : m_selEnd;
+    return ((rect.fTop + rect.fBottom) >> 1) + m_startOffset.fY;
+}
+
+void SelectText::setVisibleRect(const IntRect& vis)
+{
+    DBG_NAV_LOGD("vis=(%d,%d,w=%d,h=%d) offset=(%d,%d)",
+        vis.x(), vis.y(), vis.width(), vis.height(), m_startOffset.fX,
+        m_startOffset.fY);
+    m_visibleRect = vis;
+    m_visibleRect.offset(-m_startOffset.fX, -m_startOffset.fY);
+}
+
+bool SelectText::startSelection(const CachedRoot* root, const IntRect& vis,
+    int x, int y)
+{
+    m_wordSelection = false;
+    m_startOffset.set(x, y);
+    DBG_NAV_LOGD("x/y=(%d,%d)", x, y);
+    SkSafeUnref(m_picture);
+    m_picture = root->pictureAt(&x, &y, &m_layerId);
+    DBG_NAV_LOGD("m_picture=%p m_layerId=%d x/y=(%d,%d)", m_picture, m_layerId,
+        x, y);
+    if (!m_picture) {
+        DBG_NAV_LOG("picture==0");
+        return false;
+    }
+    m_picture->ref();
+    m_startOffset.fX -= x;
+    m_startOffset.fY -= y;
+    m_original.fX = x;
+    m_original.fY = y;
+    setVisibleRect(vis);
+    if (m_selStart.isEmpty()) {
+        DBG_NAV_LOGD("empty start picture=(%d,%d) x=%d y=%d", 
+             m_picture->width(), m_picture->height(), x, y);
+        m_startSelection = true;
+        return true;
+    }
+    m_hitTopLeft = hitStartHandle(x, y);
+    bool hitBottomRight = hitEndHandle(x, y);
+    DBG_NAV_LOGD("picture=(%d,%d) left=%d top=%d right=%d bottom=%d x=%d y=%d",
+        m_picture->width(), m_picture->height(),left, top, right, bottom, x, y);
+    if (m_hitTopLeft) {
+        DBG_NAV_LOG("hit top left");
+        m_original.fX -= m_selStart.fLeft;
+        m_original.fY -= (m_selStart.fTop + m_selStart.fBottom) >> 1;
+    } else if (hitBottomRight) {
+        DBG_NAV_LOG("hit bottom right");
+        m_original.fX -= m_selEnd.fRight;
+        m_original.fY -= (m_selEnd.fTop + m_selEnd.fBottom) >> 1;
+    }
+    return m_hitTopLeft || hitBottomRight;
+}
+
+void SelectText::updateHandleScale(float handleScale)
+{
+    m_controlHeight = CONTROL_HEIGHT * handleScale;
+    m_controlWidth = CONTROL_WIDTH * handleScale;
+    m_controlSlop = CONTROL_SLOP * handleScale;
+}
+
+/* selects the word at (x, y)
+* a word is normally delimited by spaces
+* a string of digits (even with inside spaces) is a word (for phone numbers)
+* FIXME: digit find isn't implemented yet
+* returns true if a word was selected
+*/
+bool SelectText::wordSelection(const CachedRoot* root, const IntRect& vis,
+    int x, int y)
+{
+    IntRect tapArea = IntRect(x - TOUCH_SLOP, y - TOUCH_SLOP, TOUCH_SLOP * 2,
+        TOUCH_SLOP * 2);
+    if (!startSelection(root, tapArea, x, y))
+        return false;
+    extendSelection(tapArea, x, y);
+    if (m_selStart.isEmpty())
+        return false;
+    setDrawPointer(false);
+    setVisibleRect(vis);
+    SkIRect ivisBounds = m_visibleRect;
+    ivisBounds.join(m_selStart);
+    ivisBounds.join(m_selEnd);
+    DBG_NAV_LOGD("m_selStart=(%d,%d,r=%d,b=%d) m_selEnd=(%d,%d,r=%d,b=%d)"
+        " ivisBounds=(%d,%d,r=%d,b=%d)",
+        m_selStart.fLeft, m_selStart.fTop, m_selStart.fRight, m_selStart.fBottom,
+        m_selEnd.fLeft, m_selEnd.fTop, m_selEnd.fRight, m_selEnd.fBottom,
+        ivisBounds.fLeft, ivisBounds.fTop, ivisBounds.fRight, ivisBounds.fBottom);
+    m_selRegion.setEmpty();
+    buildSelection(*m_picture, ivisBounds, m_selStart, m_startBase,
+        m_selEnd, m_endBase, &m_selRegion);
+    x = m_selStart.fLeft;
+    y = (m_selStart.fTop + m_selStart.fBottom) >> 1;
+    SkIRect clipRect = m_visibleRect;
+    clipRect.fLeft -= m_visibleRect.width() >> 1;
+    clipRect.fLeft = std::max(clipRect.fLeft, 0);
+    int base;
+    SkIRect left = findLeft(*m_picture, clipRect, x, y, &base);
+    if (!left.isEmpty()) {
+        m_startBase = base;
+        m_selStart = left;
+    }
+    x = m_selEnd.fRight;
+    y = (m_selEnd.fTop + m_selEnd.fBottom) >> 1;
+    clipRect = m_visibleRect;
+    clipRect.fRight += m_visibleRect.width() >> 1;
+    SkIRect right = findRight(*m_picture, clipRect, x, y, &base);
+    if (!right.isEmpty()) {
+        m_endBase = base;
+        m_selEnd = right;
+    }
+    DBG_NAV_LOGD("m_selStart=(%d, %d, %d, %d) m_selEnd=(%d, %d, %d, %d)",
+        m_selStart.fLeft, m_selStart.fTop, m_selStart.fRight, m_selStart.fBottom,
+        m_selEnd.fLeft, m_selEnd.fTop, m_selEnd.fRight, m_selEnd.fBottom);
+    if (!left.isEmpty() || !right.isEmpty()) {
+        m_wordBounds = m_selStart;
+        m_wordBounds.join(m_selEnd);
+        m_extendSelection = m_wordSelection = true;
+        m_outsideWord = false;
+        return true;
+    }
+    return false;
+}
+
+void SelectText::swapAsNeeded()
+{
+    if (m_selStart.fTop >= (m_selEnd.fTop + m_selEnd.fBottom) >> 1
+            || (m_selEnd.fTop < (m_selStart.fTop + m_selStart.fBottom) >> 1
+            && m_selStart.fRight > m_selEnd.fLeft))
+    {
+        SkTSwap(m_startBase, m_endBase);
+        SkTSwap(m_selStart, m_selEnd);
+        m_hitTopLeft ^= true;
+        DBG_NAV_LOGD("m_hitTopLeft=%s", m_hitTopLeft ? "true" : "false");
+    }
+}
+
+}
diff --git a/Source/WebKit/android/nav/SelectText.h b/Source/WebKit/android/nav/SelectText.h
index aaaf3bb..b454b8e 100644
--- a/Source/WebKit/android/nav/SelectText.h
+++ b/Source/WebKit/android/nav/SelectText.h
@@ -27,33 +27,90 @@
 #define SelectText_h
 
 #include "DrawExtra.h"
+#include "IntPoint.h"
 #include "IntRect.h"
 #include "PlatformString.h"
+#include "SkPath.h"
+#include "SkPicture.h"
+#include "SkRect.h"
+#include "SkRegion.h"
 
 namespace android {
 
-class SelectText : public RegionLayerDrawExtra {
+class CachedRoot;
+
+class SelectText : public DrawExtra {
 public:
-    enum HandleId {
-        LeftHandle = 0,
-        RightHandle = 1,
-    };
-
-    IntRect& caretRect(HandleId id) { return m_caretRects[id]; }
-    void setCaretRect(HandleId id, const IntRect& rect) { m_caretRects[id] = rect; }
-    IntRect& textRect(HandleId id) { return m_textRects[id]; }
-    void setTextRect(HandleId id, const IntRect& rect) { m_textRects[id] = rect; }
-    int caretLayerId(HandleId id) { return m_caretLayerId[id]; }
-    void setCaretLayerId(HandleId id, int layerId) { m_caretLayerId[id] = layerId; }
-
-    void setText(const String& text) { m_text = text.threadsafeCopy(); }
-    String& getText() { return m_text; }
-
+    SelectText();
+    virtual ~SelectText();
+    virtual void draw(SkCanvas* , LayerAndroid* , IntRect* );
+    void extendSelection(const IntRect& vis, int x, int y);
+    const String getSelection();
+    bool hitSelection(int x, int y) const;
+    void moveSelection(const IntRect& vis, int x, int y);
+    void reset();
+    IntPoint selectableText(const CachedRoot* );
+    void selectAll();
+    int selectionX() const;
+    int selectionY() const;
+    void setDrawPointer(bool drawPointer) { m_drawPointer = drawPointer; }
+    void setExtendSelection(bool extend) { m_extendSelection = extend; }
+    bool startSelection(const CachedRoot* , const IntRect& vis, int x, int y);
+    bool wordSelection(const CachedRoot* , const IntRect& vis, int x, int y);
+    void getSelectionRegion(const IntRect& vis, SkRegion *region, LayerAndroid* root);
+    void updateHandleScale(float handleScale);
+    void getSelectionHandles(int* handles, LayerAndroid* root);
+public:
+    float m_inverseScale; // inverse scale, x, y used for drawing select path
+    int m_selectX;
+    int m_selectY;
 private:
-    IntRect m_caretRects[2];
-    IntRect m_textRects[2];
-    int m_caretLayerId[2];
-    String m_text;
+    int m_controlWidth;
+    int m_controlHeight;
+    int m_controlSlop;
+    class FirstCheck;
+    class EdgeCheck;
+    void drawSelectionPointer(SkCanvas* , IntRect* );
+    void drawSelectionRegion(SkCanvas* , IntRect* );
+    SkIRect findClosest(FirstCheck& , const SkPicture& , int* base);
+    SkIRect findEdge(const SkPicture& , const SkIRect& area,
+        int x, int y, bool left, int* base);
+    SkIRect findLeft(const SkPicture& picture, const SkIRect& area,
+        int x, int y, int* base);
+    SkIRect findRight(const SkPicture& picture, const SkIRect& area,
+        int x, int y, int* base);
+    static void getSelectionArrow(SkPath* );
+    void getSelectionCaret(SkPath* );
+    bool hitCorner(int cx, int cy, int x, int y) const;
+    bool hitStartHandle(int x, int y) const;
+    bool hitEndHandle(int x, int y) const;
+    void setVisibleRect(const IntRect& );
+    void swapAsNeeded();
+    SkIPoint m_original; // computed start of extend selection
+    SkIPoint m_startOffset; // difference from global to layer
+    SkIRect m_selStart;
+    SkIRect m_selEnd;
+    SkIRect m_lastStart;
+    SkIRect m_lastEnd;
+    SkIRect m_lastDrawnStart;
+    SkIRect m_lastDrawnEnd;
+    SkIRect m_wordBounds;
+    int m_startBase;
+    int m_endBase;
+    int m_layerId;
+    SkIRect m_visibleRect; // constrains picture computations to visible area
+    SkRegion m_lastSelRegion;
+    SkRegion m_selRegion; // computed from sel start, end
+    SkPicture m_startControl;
+    SkPicture m_endControl;
+    const SkPicture* m_picture;
+    bool m_drawPointer;
+    bool m_extendSelection; // false when trackball is moving pointer
+    bool m_flipped;
+    bool m_hitTopLeft;
+    bool m_startSelection;
+    bool m_wordSelection;
+    bool m_outsideWord;
 };
 
 }
diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp
index a67b5fd..7cb41d9 100644
--- a/Source/WebKit/android/nav/WebView.cpp
+++ b/Source/WebKit/android/nav/WebView.cpp
@@ -30,16 +30,17 @@
 #include "AndroidAnimation.h"
 #include "AndroidLog.h"
 #include "BaseLayerAndroid.h"
-#include "BaseRenderer.h"
+#include "CachedFrame.h"
+#include "CachedNode.h"
+#include "CachedRoot.h"
 #include "DrawExtra.h"
+#include "FindCanvas.h"
 #include "Frame.h"
-#include "GLWebViewState.h"
 #include "GraphicsJNI.h"
 #include "HTMLInputElement.h"
 #include "IntPoint.h"
 #include "IntRect.h"
 #include "LayerAndroid.h"
-#include "LayerContent.h"
 #include "Node.h"
 #include "utils/Functor.h"
 #include "private/hwui/DrawGlInfo.h"
@@ -52,8 +53,10 @@
 #include "SkPicture.h"
 #include "SkRect.h"
 #include "SkTime.h"
+#ifdef ANDROID_INSTRUMENT
+#include "TimeCounter.h"
+#endif
 #include "TilesManager.h"
-#include "TransferQueue.h"
 #include "WebCoreJni.h"
 #include "WebRequestContext.h"
 #include "WebViewCore.h"
@@ -68,7 +71,7 @@
 #include <JNIUtility.h>
 #include <JNIHelp.h>
 #include <jni.h>
-#include <androidfw/KeycodeLabels.h>
+#include <ui/KeycodeLabels.h>
 #include <wtf/text/AtomicString.h>
 #include <wtf/text/CString.h>
 
@@ -92,7 +95,7 @@
 static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[], const char signature[])
 {
     jmethodID m = env->GetMethodID(clazz, name, signature);
-    ALOG_ASSERT(m, "Could not find method %s", name);
+    LOG_ASSERT(m, "Could not find method %s", name);
     return m;
 }
 
@@ -107,81 +110,105 @@
     AllowNewer
 };
 
-#define DRAW_EXTRAS_SIZE 2
 enum DrawExtras { // keep this in sync with WebView.java
     DrawExtrasNone = 0,
-    DrawExtrasSelection = 1,
-    DrawExtrasCursorRing = 2
+    DrawExtrasFind = 1,
+    DrawExtrasSelection = 2,
+    DrawExtrasCursorRing = 3
 };
 
 struct JavaGlue {
     jweak       m_obj;
+    jmethodID   m_overrideLoading;
     jmethodID   m_scrollBy;
+    jmethodID   m_sendMoveFocus;
+    jmethodID   m_sendMoveMouse;
+    jmethodID   m_sendMoveMouseIfLatest;
+    jmethodID   m_sendMotionUp;
+    jmethodID   m_domChangedFocus;
     jmethodID   m_getScaledMaxXScroll;
     jmethodID   m_getScaledMaxYScroll;
-    jmethodID   m_updateRectsForGL;
+    jmethodID   m_getVisibleRect;
+    jmethodID   m_rebuildWebTextView;
     jmethodID   m_viewInvalidate;
     jmethodID   m_viewInvalidateRect;
     jmethodID   m_postInvalidateDelayed;
     jmethodID   m_pageSwapCallback;
+    jmethodID   m_inFullScreenMode;
     jfieldID    m_rectLeft;
     jfieldID    m_rectTop;
     jmethodID   m_rectWidth;
     jmethodID   m_rectHeight;
-    jfieldID    m_quadFP1;
-    jfieldID    m_quadFP2;
-    jfieldID    m_quadFP3;
-    jfieldID    m_quadFP4;
+    jfieldID    m_rectFLeft;
+    jfieldID    m_rectFTop;
+    jmethodID   m_rectFWidth;
+    jmethodID   m_rectFHeight;
+    jmethodID   m_getTextHandleScale;
     AutoJObject object(JNIEnv* env) {
         return getRealObject(env, m_obj);
     }
 } m_javaGlue;
 
 WebView(JNIEnv* env, jobject javaWebView, int viewImpl, WTF::String drawableDir,
-        bool isHighEndGfx)
-    : m_isHighEndGfx(isHighEndGfx)
+        bool isHighEndGfx) :
+    m_ring((WebViewCore*) viewImpl)
+    , m_isHighEndGfx(isHighEndGfx)
 {
-    memset(m_extras, 0, DRAW_EXTRAS_SIZE * sizeof(DrawExtra*));
-    jclass clazz = env->FindClass("android/webkit/WebViewClassic");
+    jclass clazz = env->FindClass("android/webkit/WebView");
+ //   m_javaGlue = new JavaGlue;
     m_javaGlue.m_obj = env->NewWeakGlobalRef(javaWebView);
     m_javaGlue.m_scrollBy = GetJMethod(env, clazz, "setContentScrollBy", "(IIZ)Z");
+    m_javaGlue.m_overrideLoading = GetJMethod(env, clazz, "overrideLoading", "(Ljava/lang/String;)V");
+    m_javaGlue.m_sendMoveFocus = GetJMethod(env, clazz, "sendMoveFocus", "(II)V");
+    m_javaGlue.m_sendMoveMouse = GetJMethod(env, clazz, "sendMoveMouse", "(IIII)V");
+    m_javaGlue.m_sendMoveMouseIfLatest = GetJMethod(env, clazz, "sendMoveMouseIfLatest", "(ZZ)V");
+    m_javaGlue.m_sendMotionUp = GetJMethod(env, clazz, "sendMotionUp", "(IIIII)V");
+    m_javaGlue.m_domChangedFocus = GetJMethod(env, clazz, "domChangedFocus", "()V");
     m_javaGlue.m_getScaledMaxXScroll = GetJMethod(env, clazz, "getScaledMaxXScroll", "()I");
     m_javaGlue.m_getScaledMaxYScroll = GetJMethod(env, clazz, "getScaledMaxYScroll", "()I");
-    m_javaGlue.m_updateRectsForGL = GetJMethod(env, clazz, "updateRectsForGL", "()V");
+    m_javaGlue.m_getVisibleRect = GetJMethod(env, clazz, "sendOurVisibleRect", "()Landroid/graphics/Rect;");
+    m_javaGlue.m_rebuildWebTextView = GetJMethod(env, clazz, "rebuildWebTextView", "()V");
     m_javaGlue.m_viewInvalidate = GetJMethod(env, clazz, "viewInvalidate", "()V");
     m_javaGlue.m_viewInvalidateRect = GetJMethod(env, clazz, "viewInvalidate", "(IIII)V");
     m_javaGlue.m_postInvalidateDelayed = GetJMethod(env, clazz,
         "viewInvalidateDelayed", "(JIIII)V");
     m_javaGlue.m_pageSwapCallback = GetJMethod(env, clazz, "pageSwapCallback", "(Z)V");
+    m_javaGlue.m_inFullScreenMode = GetJMethod(env, clazz, "inFullScreenMode", "()Z");
+    m_javaGlue.m_getTextHandleScale = GetJMethod(env, clazz, "getTextHandleScale", "()F");
     env->DeleteLocalRef(clazz);
 
     jclass rectClass = env->FindClass("android/graphics/Rect");
-    ALOG_ASSERT(rectClass, "Could not find Rect class");
+    LOG_ASSERT(rectClass, "Could not find Rect class");
     m_javaGlue.m_rectLeft = env->GetFieldID(rectClass, "left", "I");
     m_javaGlue.m_rectTop = env->GetFieldID(rectClass, "top", "I");
     m_javaGlue.m_rectWidth = GetJMethod(env, rectClass, "width", "()I");
     m_javaGlue.m_rectHeight = GetJMethod(env, rectClass, "height", "()I");
     env->DeleteLocalRef(rectClass);
 
-    jclass quadFClass = env->FindClass("android/webkit/QuadF");
-    ALOG_ASSERT(quadFClass, "Could not find QuadF class");
-    m_javaGlue.m_quadFP1 = env->GetFieldID(quadFClass, "p1", "Landroid/graphics/PointF;");
-    m_javaGlue.m_quadFP2 = env->GetFieldID(quadFClass, "p2", "Landroid/graphics/PointF;");
-    m_javaGlue.m_quadFP3 = env->GetFieldID(quadFClass, "p3", "Landroid/graphics/PointF;");
-    m_javaGlue.m_quadFP4 = env->GetFieldID(quadFClass, "p4", "Landroid/graphics/PointF;");
-    env->DeleteLocalRef(quadFClass);
+    jclass rectClassF = env->FindClass("android/graphics/RectF");
+    LOG_ASSERT(rectClassF, "Could not find RectF class");
+    m_javaGlue.m_rectFLeft = env->GetFieldID(rectClassF, "left", "F");
+    m_javaGlue.m_rectFTop = env->GetFieldID(rectClassF, "top", "F");
+    m_javaGlue.m_rectFWidth = GetJMethod(env, rectClassF, "width", "()F");
+    m_javaGlue.m_rectFHeight = GetJMethod(env, rectClassF, "height", "()F");
+    env->DeleteLocalRef(rectClassF);
 
     env->SetIntField(javaWebView, gWebViewField, (jint)this);
     m_viewImpl = (WebViewCore*) viewImpl;
+    m_frameCacheUI = 0;
+    m_navPictureUI = 0;
     m_generation = 0;
     m_heightCanMeasure = false;
     m_lastDx = 0;
     m_lastDxTime = 0;
+    m_ringAnimationEnd = 0;
     m_baseLayer = 0;
     m_glDrawFunctor = 0;
     m_isDrawingPaused = false;
+    m_buttonSkin = drawableDir.isEmpty() ? 0 : new RenderSkinButton(drawableDir);
 #if USE(ACCELERATED_COMPOSITING)
     m_glWebViewState = 0;
+    m_pageSwapCallbackRegistered = false;
 #endif
 }
 
@@ -199,17 +226,11 @@
     // deallocated base layer.
     stopGL();
 #endif
+    delete m_frameCacheUI;
+    delete m_navPictureUI;
     SkSafeUnref(m_baseLayer);
     delete m_glDrawFunctor;
-    for (int i = 0; i < DRAW_EXTRAS_SIZE; i++)
-        delete m_extras[i];
-}
-
-DrawExtra* getDrawExtra(DrawExtras extras)
-{
-    if (extras == DrawExtrasNone)
-        return 0;
-    return m_extras[extras - 1];
+    delete m_buttonSkin;
 }
 
 void stopGL()
@@ -224,6 +245,126 @@
     return m_viewImpl;
 }
 
+float getTextHandleScale()
+{
+    LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
+    JNIEnv* env = JSC::Bindings::getJNIEnv();
+    AutoJObject javaObject = m_javaGlue.object(env);
+    if (!javaObject.get())
+        return 0;
+    float result = env->CallFloatMethod(javaObject.get(), m_javaGlue.m_getTextHandleScale);
+    checkException(env);
+    return result;
+}
+
+void updateSelectionHandles()
+{
+    if (!m_baseLayer)
+        return;
+    // Adjust for device density & scale
+    m_selectText.updateHandleScale(getTextHandleScale());
+}
+
+// removes the cursor altogether (e.g., when going to a new page)
+void clearCursor()
+{
+    CachedRoot* root = getFrameCache(AllowNewer);
+    if (!root)
+        return;
+    DBG_NAV_LOG("");
+    m_viewImpl->m_hasCursorBounds = false;
+    root->clearCursor();
+    viewInvalidate();
+}
+
+// leaves the cursor where it is, but suppresses drawing it
+void hideCursor()
+{
+    CachedRoot* root = getFrameCache(AllowNewer);
+    if (!root)
+        return;
+    DBG_NAV_LOG("");
+    hideCursor(root);
+    viewInvalidate();
+}
+
+void hideCursor(CachedRoot* root)
+{
+    DBG_NAV_LOG("inner");
+    m_viewImpl->m_hasCursorBounds = false;
+    root->hideCursor();
+}
+
+#if DUMP_NAV_CACHE
+void debugDump()
+{
+    CachedRoot* root = getFrameCache(DontAllowNewer);
+    if (root)
+        root->mDebug.print();
+}
+#endif
+
+void scrollToCurrentMatch()
+{
+    if (!m_findOnPage.currentMatchIsInLayer()) {
+        scrollRectOnScreen(m_findOnPage.currentMatchBounds());
+        return;
+    }
+
+    SkRect matchBounds = m_findOnPage.currentMatchBounds();
+    LayerAndroid* rootLayer = getFrameCache(DontAllowNewer)->rootLayer();
+    Layer* layerContainingMatch = rootLayer->findById(m_findOnPage.currentMatchLayerId());
+    ASSERT(layerContainingMatch);
+
+    // If the match is in a fixed position layer, there's nothing to do.
+    if (layerContainingMatch->shouldInheritFromRootTransform())
+        return;
+
+    // If the match is in a scrollable layer or a descendant of such a layer,
+    // there may be a range of of scroll configurations that will make the
+    // current match visible. Our approach is the simplest possible. Starting at
+    // the layer in which the match is found, we move up the layer tree,
+    // scrolling any scrollable layers as little as possible to make sure that
+    // the current match is in view. This approach has the disadvantage that we
+    // may end up scrolling a larger number of elements than is necessary, which
+    // may be visually jarring. However, minimising the number of layers
+    // scrolled would complicate the code significantly.
+
+    bool didScrollLayer = false;
+    for (Layer* layer = layerContainingMatch; layer; layer = layer->getParent()) {
+        ASSERT(layer->getParent() || layer == rootLayer);
+
+        if (layer->contentIsScrollable()) {
+            // Convert the match location to layer's local space and scroll it.
+            // Repeatedly calling Layer::localToAncestor() is inefficient as
+            // each call repeats part of the calculation. It would be more
+            // efficient to maintain the transform here and update it on each
+            // iteration, but that would mean duplicating logic from
+            // Layer::localToAncestor() and would complicate things.
+            SkMatrix transform;
+            layerContainingMatch->localToAncestor(layer, &transform);
+            SkRect transformedMatchBounds;
+            transform.mapRect(&transformedMatchBounds, matchBounds);
+            SkIRect roundedTransformedMatchBounds;
+            transformedMatchBounds.roundOut(&roundedTransformedMatchBounds);
+            // Only ScrollableLayerAndroid returns true for contentIsScrollable().
+            didScrollLayer |= static_cast<ScrollableLayerAndroid*>(layer)->scrollRectIntoView(roundedTransformedMatchBounds);
+        }
+    }
+    // Invalidate, as the call below to scroll the main page may be a no-op.
+    if (didScrollLayer)
+        viewInvalidate();
+
+    // Convert matchBounds to the global space so we can scroll the main page.
+    SkMatrix transform;
+    layerContainingMatch->localToGlobal(&transform);
+    SkRect transformedMatchBounds;
+    transform.mapRect(&transformedMatchBounds, matchBounds);
+    SkIRect roundedTransformedMatchBounds;
+    transformedMatchBounds.roundOut(&roundedTransformedMatchBounds);
+    scrollRectOnScreen(roundedTransformedMatchBounds);
+}
+
 void scrollRectOnScreen(const IntRect& rect)
 {
     if (rect.isEmpty())
@@ -231,59 +372,147 @@
     int dx = 0;
     int left = rect.x();
     int right = rect.maxX();
-    if (left < m_visibleContentRect.fLeft)
-        dx = left - m_visibleContentRect.fLeft;
+    if (left < m_visibleRect.fLeft)
+        dx = left - m_visibleRect.fLeft;
     // Only scroll right if the entire width can fit on screen.
-    else if (right > m_visibleContentRect.fRight
-            && right - left < m_visibleContentRect.width())
-        dx = right - m_visibleContentRect.fRight;
+    else if (right > m_visibleRect.fRight
+            && right - left < m_visibleRect.width())
+        dx = right - m_visibleRect.fRight;
     int dy = 0;
     int top = rect.y();
     int bottom = rect.maxY();
-    if (top < m_visibleContentRect.fTop)
-        dy = top - m_visibleContentRect.fTop;
+    if (top < m_visibleRect.fTop)
+        dy = top - m_visibleRect.fTop;
     // Only scroll down if the entire height can fit on screen
-    else if (bottom > m_visibleContentRect.fBottom
-            && bottom - top < m_visibleContentRect.height())
-        dy = bottom - m_visibleContentRect.fBottom;
+    else if (bottom > m_visibleRect.fBottom
+            && bottom - top < m_visibleRect.height())
+        dy = bottom - m_visibleRect.fBottom;
     if ((dx|dy) == 0 || !scrollBy(dx, dy))
         return;
     viewInvalidate();
 }
 
-int drawGL(WebCore::IntRect& invScreenRect, WebCore::IntRect* invalRect,
-        WebCore::IntRect& screenRect, int titleBarHeight,
-        WebCore::IntRect& screenClip, float scale, int extras, bool shouldDraw)
+void resetCursorRing()
+{
+    m_ringAnimationEnd = 0;
+    m_viewImpl->m_hasCursorBounds = false;
+}
+
+bool drawCursorPreamble(CachedRoot* root)
+{
+    if (!root) return false;
+    const CachedFrame* frame;
+    const CachedNode* node = root->currentCursor(&frame);
+    if (!node) {
+        DBG_NAV_LOGV("%s", "!node");
+        resetCursorRing();
+        return false;
+    }
+    m_ring.setIsButton(node);
+    if (node->isHidden()) {
+        DBG_NAV_LOG("node->isHidden()");
+        m_viewImpl->m_hasCursorBounds = false;
+        return false;
+    }
+#if USE(ACCELERATED_COMPOSITING)
+    if (node->isInLayer() && root->rootLayer()) {
+        LayerAndroid* layer = root->rootLayer();
+        layer->updateFixedLayersPositions(m_visibleRect);
+        layer->updatePositions();
+    }
+#endif
+    setVisibleRect(root);
+    m_ring.m_root = root;
+    m_ring.m_frame = frame;
+    m_ring.m_node = node;
+    SkMSec time = SkTime::GetMSecs();
+    m_ring.m_isPressed = time < m_ringAnimationEnd
+        && m_ringAnimationEnd != UINT_MAX;
+    return true;
+}
+
+void drawCursorPostamble()
+{
+    if (m_ringAnimationEnd == UINT_MAX)
+        return;
+    SkMSec time = SkTime::GetMSecs();
+    if (time < m_ringAnimationEnd) {
+        // views assume that inval bounds coordinates are non-negative
+        WebCore::IntRect invalBounds(0, 0, INT_MAX, INT_MAX);
+        invalBounds.intersect(m_ring.m_absBounds);
+        postInvalidateDelayed(m_ringAnimationEnd - time, invalBounds);
+    } else {
+        hideCursor(const_cast<CachedRoot*>(m_ring.m_root));
+    }
+}
+
+bool drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect,
+        WebCore::IntRect& webViewRect, int titleBarHeight,
+        WebCore::IntRect& clip, float scale, int extras)
 {
 #if USE(ACCELERATED_COMPOSITING)
-    if (!m_baseLayer)
-        return 0;
-
-    if (m_viewImpl)
-        m_viewImpl->setPrerenderingEnabled(!m_isDrawingPaused);
+    if (!m_baseLayer || inFullScreenMode())
+        return false;
 
     if (!m_glWebViewState) {
-        TilesManager::instance()->setHighEndGfx(m_isHighEndGfx);
         m_glWebViewState = new GLWebViewState();
-        m_glWebViewState->setBaseLayer(m_baseLayer, false, true);
+        m_glWebViewState->setHighEndGfx(m_isHighEndGfx);
+        m_glWebViewState->glExtras()->setCursorRingExtra(&m_ring);
+        m_glWebViewState->glExtras()->setFindOnPageExtra(&m_findOnPage);
+        if (m_baseLayer->content()) {
+            SkRegion region;
+            SkIRect rect;
+            rect.set(0, 0, m_baseLayer->content()->width(), m_baseLayer->content()->height());
+            region.setRect(rect);
+            m_glWebViewState->setBaseLayer(m_baseLayer, region, false, true);
+        }
     }
 
-    DrawExtra* extra = getDrawExtra((DrawExtras) extras);
+    CachedRoot* root = getFrameCache(AllowNewer);
+    if (!root) {
+        DBG_NAV_LOG("!root");
+        if (extras == DrawExtrasCursorRing)
+            resetCursorRing();
+    }
+    DrawExtra* extra = 0;
+    switch (extras) {
+        case DrawExtrasFind:
+            extra = &m_findOnPage;
+            break;
+        case DrawExtrasSelection:
+            // This will involve a JNI call, but under normal circumstances we will
+            // not hit this anyway. Only if USE_JAVA_TEXT_SELECTION is disabled
+            // in WebView.java will we hit this (so really debug only)
+            updateSelectionHandles();
+            extra = &m_selectText;
+            break;
+        case DrawExtrasCursorRing:
+            if (drawCursorPreamble(root) && m_ring.setup()) {
+                if (m_ring.m_isPressed || m_ringAnimationEnd == UINT_MAX)
+                    extra = &m_ring;
+                drawCursorPostamble();
+            }
+            break;
+        default:
+            ;
+    }
 
+    unsigned int pic = m_glWebViewState->currentPictureCounter();
     m_glWebViewState->glExtras()->setDrawExtra(extra);
 
     // Make sure we have valid coordinates. We might not have valid coords
     // if the zoom manager is still initializing. We will be redrawn
     // once the correct scale is set
-    if (!m_visibleContentRect.isFinite())
-        return 0;
+    if (!m_visibleRect.isFinite())
+        return false;
     bool treesSwapped = false;
     bool newTreeHasAnim = false;
-    int ret = m_glWebViewState->drawGL(invScreenRect, m_visibleContentRect, invalRect,
-                                        screenRect, titleBarHeight, screenClip, scale,
-                                        &treesSwapped, &newTreeHasAnim, shouldDraw);
-    if (treesSwapped) {
-        ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
+    bool ret = m_glWebViewState->drawGL(viewRect, m_visibleRect, invalRect,
+                                        webViewRect, titleBarHeight, clip, scale,
+                                        &treesSwapped, &newTreeHasAnim);
+    if (treesSwapped && (m_pageSwapCallbackRegistered || newTreeHasAnim)) {
+        m_pageSwapCallbackRegistered = false;
+        LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
         JNIEnv* env = JSC::Bindings::getJNIEnv();
         AutoJObject javaObject = m_javaGlue.object(env);
         if (javaObject.get()) {
@@ -291,45 +520,237 @@
             checkException(env);
         }
     }
-    return m_isDrawingPaused ? 0 : ret;
+    if (ret || m_glWebViewState->currentPictureCounter() != pic)
+        return !m_isDrawingPaused;
 #endif
-    return 0;
+    return false;
 }
 
-void draw(SkCanvas* canvas, SkColor bgColor, DrawExtras extras)
+PictureSet* draw(SkCanvas* canvas, SkColor bgColor, int extras, bool split)
 {
+    PictureSet* ret = 0;
     if (!m_baseLayer) {
         canvas->drawColor(bgColor);
-        return;
+        return ret;
     }
 
     // draw the content of the base layer first
-    LayerContent* content = m_baseLayer->content();
+    PictureSet* content = m_baseLayer->content();
     int sc = canvas->save(SkCanvas::kClip_SaveFlag);
-    if (content) {
-        canvas->clipRect(SkRect::MakeLTRB(0, 0, content->width(), content->height()),
-                         SkRegion::kDifference_Op);
-    }
-    Color c = m_baseLayer->getBackgroundColor();
-    canvas->drawColor(SkColorSetARGBInline(c.alpha(), c.red(), c.green(), c.blue()));
+    canvas->clipRect(SkRect::MakeLTRB(0, 0, content->width(),
+                content->height()), SkRegion::kDifference_Op);
+    canvas->drawColor(bgColor);
     canvas->restoreToCount(sc);
+    if (content->draw(canvas))
+        ret = split ? new PictureSet(*content) : 0;
 
-    // call this to be sure we've adjusted for any scrolling or animations
-    // before we actually draw
-    m_baseLayer->updatePositionsRecursive(m_visibleContentRect);
-    m_baseLayer->updatePositions();
+    CachedRoot* root = getFrameCache(AllowNewer);
+    if (!root) {
+        DBG_NAV_LOG("!root");
+        if (extras == DrawExtrasCursorRing)
+            resetCursorRing();
+    }
+    LayerAndroid mainPicture(m_navPictureUI);
+    DrawExtra* extra = 0;
+    switch (extras) {
+        case DrawExtrasFind:
+            extra = &m_findOnPage;
+            break;
+        case DrawExtrasSelection:
+            // This will involve a JNI call, but under normal circumstances we will
+            // not hit this anyway. Only if USE_JAVA_TEXT_SELECTION is disabled
+            // in WebView.java will we hit this (so really debug only)
+            updateSelectionHandles();
+            extra = &m_selectText;
+            break;
+        case DrawExtrasCursorRing:
+            if (drawCursorPreamble(root) && m_ring.setup()) {
+                extra = &m_ring;
+                drawCursorPostamble();
+            }
+            break;
+        default:
+            ;
+    }
+#if USE(ACCELERATED_COMPOSITING)
+    LayerAndroid* compositeLayer = compositeRoot();
+    if (compositeLayer) {
+        // call this to be sure we've adjusted for any scrolling or animations
+        // before we actually draw
+        compositeLayer->updateFixedLayersPositions(m_visibleRect);
+        compositeLayer->updatePositions();
+        // We have to set the canvas' matrix on the base layer
+        // (to have fixed layers work as intended)
+        SkAutoCanvasRestore restore(canvas, true);
+        m_baseLayer->setMatrix(canvas->getTotalMatrix());
+        canvas->resetMatrix();
+        m_baseLayer->draw(canvas);
+    }
+#endif
+    if (extra) {
+        IntRect dummy; // inval area, unused for now
+        extra->draw(canvas, &mainPicture, &dummy);
+    }
+    return ret;
+}
 
-    // We have to set the canvas' matrix on the base layer
-    // (to have fixed layers work as intended)
-    SkAutoCanvasRestore restore(canvas, true);
-    m_baseLayer->setMatrix(canvas->getTotalMatrix());
-    canvas->resetMatrix();
-    m_baseLayer->draw(canvas, getDrawExtra(extras));
+
+bool cursorIsTextInput(FrameCachePermission allowNewer)
+{
+    CachedRoot* root = getFrameCache(allowNewer);
+    if (!root) {
+        DBG_NAV_LOG("!root");
+        return false;
+    }
+    const CachedNode* cursor = root->currentCursor();
+    if (!cursor) {
+        DBG_NAV_LOG("!cursor");
+        return false;
+    }
+    DBG_NAV_LOGD("%s", cursor->isTextInput() ? "true" : "false");
+    return cursor->isTextInput();
+}
+
+void cursorRingBounds(WebCore::IntRect* bounds)
+{
+    DBG_NAV_LOGD("%s", "");
+    CachedRoot* root = getFrameCache(DontAllowNewer);
+    if (root) {
+        const CachedFrame* cachedFrame;
+        const CachedNode* cachedNode = root->currentCursor(&cachedFrame);
+        if (cachedNode) {
+            *bounds = cachedNode->cursorRingBounds(cachedFrame);
+            DBG_NAV_LOGD("bounds={%d,%d,%d,%d}", bounds->x(), bounds->y(),
+                bounds->width(), bounds->height());
+            return;
+        }
+    }
+    *bounds = WebCore::IntRect(0, 0, 0, 0);
+}
+
+void fixCursor()
+{
+    m_viewImpl->gCursorBoundsMutex.lock();
+    bool hasCursorBounds = m_viewImpl->m_hasCursorBounds;
+    IntRect bounds = m_viewImpl->m_cursorBounds;
+    m_viewImpl->gCursorBoundsMutex.unlock();
+    if (!hasCursorBounds)
+        return;
+    int x, y;
+    const CachedFrame* frame;
+    const CachedNode* node = m_frameCacheUI->findAt(bounds, &frame, &x, &y, true);
+    if (!node)
+        return;
+    // require that node have approximately the same bounds (+/- 4) and the same
+    // center (+/- 2)
+    IntPoint oldCenter = IntPoint(bounds.x() + (bounds.width() >> 1),
+        bounds.y() + (bounds.height() >> 1));
+    IntRect newBounds = node->bounds(frame);
+    IntPoint newCenter = IntPoint(newBounds.x() + (newBounds.width() >> 1),
+        newBounds.y() + (newBounds.height() >> 1));
+    DBG_NAV_LOGD("oldCenter=(%d,%d) newCenter=(%d,%d)"
+        " bounds=(%d,%d,w=%d,h=%d) newBounds=(%d,%d,w=%d,h=%d)",
+        oldCenter.x(), oldCenter.y(), newCenter.x(), newCenter.y(),
+        bounds.x(), bounds.y(), bounds.width(), bounds.height(),
+        newBounds.x(), newBounds.y(), newBounds.width(), newBounds.height());
+    if (abs(oldCenter.x() - newCenter.x()) > 2)
+        return;
+    if (abs(oldCenter.y() - newCenter.y()) > 2)
+        return;
+    if (abs(bounds.x() - newBounds.x()) > 4)
+        return;
+    if (abs(bounds.y() - newBounds.y()) > 4)
+        return;
+    if (abs(bounds.maxX() - newBounds.maxX()) > 4)
+        return;
+    if (abs(bounds.maxY() - newBounds.maxY()) > 4)
+        return;
+    DBG_NAV_LOGD("node=%p frame=%p x=%d y=%d bounds=(%d,%d,w=%d,h=%d)",
+        node, frame, x, y, bounds.x(), bounds.y(), bounds.width(),
+        bounds.height());
+    m_frameCacheUI->setCursor(const_cast<CachedFrame*>(frame),
+        const_cast<CachedNode*>(node));
+}
+
+CachedRoot* getFrameCache(FrameCachePermission allowNewer)
+{
+    if (!m_viewImpl->m_updatedFrameCache) {
+        DBG_NAV_LOGV("%s", "!m_viewImpl->m_updatedFrameCache");
+        return m_frameCacheUI;
+    }
+    if (allowNewer == DontAllowNewer && m_viewImpl->m_lastGeneration < m_generation) {
+        DBG_NAV_LOGD("allowNewer==DontAllowNewer m_viewImpl->m_lastGeneration=%d"
+            " < m_generation=%d", m_viewImpl->m_lastGeneration, m_generation);
+        return m_frameCacheUI;
+    }
+    DBG_NAV_LOGD("%s", "m_viewImpl->m_updatedFrameCache == true");
+    const CachedFrame* oldCursorFrame;
+    const CachedNode* oldCursorNode = m_frameCacheUI ?
+        m_frameCacheUI->currentCursor(&oldCursorFrame) : 0;
+#if USE(ACCELERATED_COMPOSITING)
+    int layerId = -1;
+    if (oldCursorNode && oldCursorNode->isInLayer()) {
+        const LayerAndroid* cursorLayer = oldCursorFrame->layer(oldCursorNode)
+            ->layer(m_frameCacheUI->rootLayer());
+        if (cursorLayer)
+            layerId = cursorLayer->uniqueId();
+    }
+#endif
+    // get id from old layer and use to find new layer
+    bool oldFocusIsTextInput = false;
+    void* oldFocusNodePointer = 0;
+    if (m_frameCacheUI) {
+        const CachedNode* oldFocus = m_frameCacheUI->currentFocus();
+        if (oldFocus) {
+            oldFocusIsTextInput = oldFocus->isTextInput();
+            oldFocusNodePointer = oldFocus->nodePointer();
+        }
+    }
+    m_viewImpl->gFrameCacheMutex.lock();
+    delete m_frameCacheUI;
+    SkSafeUnref(m_navPictureUI);
+    m_viewImpl->m_updatedFrameCache = false;
+    m_frameCacheUI = m_viewImpl->m_frameCacheKit;
+    m_navPictureUI = m_viewImpl->m_navPictureKit;
+    m_viewImpl->m_frameCacheKit = 0;
+    m_viewImpl->m_navPictureKit = 0;
+    m_viewImpl->gFrameCacheMutex.unlock();
+    if (m_frameCacheUI)
+        m_frameCacheUI->setRootLayer(compositeRoot());
+#if USE(ACCELERATED_COMPOSITING)
+    if (layerId >= 0) {
+        LayerAndroid* layer = const_cast<LayerAndroid*>(
+                                                m_frameCacheUI->rootLayer());
+        if (layer) {
+            layer->updateFixedLayersPositions(m_visibleRect);
+            layer->updatePositions();
+        }
+    }
+#endif
+    fixCursor();
+    if (oldFocusIsTextInput) {
+        const CachedNode* newFocus = m_frameCacheUI->currentFocus();
+        if (newFocus && oldFocusNodePointer != newFocus->nodePointer()
+                && newFocus->isTextInput()
+                && newFocus != m_frameCacheUI->currentCursor()) {
+            // The focus has changed.  We may need to update things.
+            LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
+            JNIEnv* env = JSC::Bindings::getJNIEnv();
+            AutoJObject javaObject = m_javaGlue.object(env);
+            if (javaObject.get()) {
+                env->CallVoidMethod(javaObject.get(), m_javaGlue.m_domChangedFocus);
+                checkException(env);
+            }
+        }
+    }
+    if (oldCursorNode && (!m_frameCacheUI || !m_frameCacheUI->currentCursor()))
+        viewInvalidate(); // redraw in case cursor ring is still visible
+    return m_frameCacheUI;
 }
 
 int getScaledMaxXScroll()
 {
-    ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
+    LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
     JNIEnv* env = JSC::Bindings::getJNIEnv();
     AutoJObject javaObject = m_javaGlue.object(env);
     if (!javaObject.get())
@@ -341,7 +762,7 @@
 
 int getScaledMaxYScroll()
 {
-    ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
+    LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
     JNIEnv* env = JSC::Bindings::getJNIEnv();
     AutoJObject javaObject = m_javaGlue.object(env);
     if (!javaObject.get())
@@ -351,37 +772,294 @@
     return result;
 }
 
-// Call through JNI to ask Java side to update the rectangles for GL functor.
-// This is called at every draw when it is not in process mode, so we should
-// keep this route as efficient as possible. Currently, its average cost on Xoom
-// is about 0.1ms - 0.2ms.
-// Alternatively, this can be achieved by adding more listener on Java side, but
-// that will be more likely causing jank when triggering GC.
-void updateRectsForGL()
+IntRect getVisibleRect()
 {
+    IntRect rect;
+    LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
     JNIEnv* env = JSC::Bindings::getJNIEnv();
     AutoJObject javaObject = m_javaGlue.object(env);
     if (!javaObject.get())
-        return;
-    env->CallVoidMethod(javaObject.get(), m_javaGlue.m_updateRectsForGL);
+        return rect;
+    jobject jRect = env->CallObjectMethod(javaObject.get(), m_javaGlue.m_getVisibleRect);
     checkException(env);
+    rect.setX(env->GetIntField(jRect, m_javaGlue.m_rectLeft));
+    checkException(env);
+    rect.setY(env->GetIntField(jRect, m_javaGlue.m_rectTop));
+    checkException(env);
+    rect.setWidth(env->CallIntMethod(jRect, m_javaGlue.m_rectWidth));
+    checkException(env);
+    rect.setHeight(env->CallIntMethod(jRect, m_javaGlue.m_rectHeight));
+    checkException(env);
+    env->DeleteLocalRef(jRect);
+    checkException(env);
+    return rect;
+}
+
+static CachedFrame::Direction KeyToDirection(int32_t keyCode)
+{
+    switch (keyCode) {
+        case AKEYCODE_DPAD_RIGHT:
+            DBG_NAV_LOGD("keyCode=%s", "right");
+            return CachedFrame::RIGHT;
+        case AKEYCODE_DPAD_LEFT:
+            DBG_NAV_LOGD("keyCode=%s", "left");
+            return CachedFrame::LEFT;
+        case AKEYCODE_DPAD_DOWN:
+            DBG_NAV_LOGD("keyCode=%s", "down");
+            return CachedFrame::DOWN;
+        case AKEYCODE_DPAD_UP:
+            DBG_NAV_LOGD("keyCode=%s", "up");
+            return CachedFrame::UP;
+        default:
+            DBG_NAV_LOGD("bad key %d sent", keyCode);
+            return CachedFrame::UNINITIALIZED;
+    }
+}
+
+WTF::String imageURI(int x, int y)
+{
+    const CachedRoot* root = getFrameCache(DontAllowNewer);
+    return root ? root->imageURI(x, y) : WTF::String();
+}
+
+bool cursorWantsKeyEvents()
+{
+    const CachedRoot* root = getFrameCache(DontAllowNewer);
+    if (root) {
+        const CachedNode* focus = root->currentCursor();
+        if (focus)
+            return focus->wantsKeyEvents();
+    }
+    return false;
+}
+
+
+/* returns true if the key had no effect (neither scrolled nor changed cursor) */
+bool moveCursor(int keyCode, int count, bool ignoreScroll)
+{
+    CachedRoot* root = getFrameCache(AllowNewer);
+    if (!root) {
+        DBG_NAV_LOG("!root");
+        return true;
+    }
+
+    m_viewImpl->m_moveGeneration++;
+    CachedFrame::Direction direction = KeyToDirection(keyCode);
+    const CachedFrame* cachedFrame, * oldFrame = 0;
+    const CachedNode* cursor = root->currentCursor(&oldFrame);
+    WebCore::IntPoint cursorLocation = root->cursorLocation();
+    DBG_NAV_LOGD("old cursor %d (nativeNode=%p) cursorLocation={%d, %d}",
+        cursor ? cursor->index() : 0,
+        cursor ? cursor->nodePointer() : 0, cursorLocation.x(), cursorLocation.y());
+    WebCore::IntRect visibleRect = setVisibleRect(root);
+    int xMax = getScaledMaxXScroll();
+    int yMax = getScaledMaxYScroll();
+    root->setMaxScroll(xMax, yMax);
+    const CachedNode* cachedNode = 0;
+    int dx = 0;
+    int dy = 0;
+    int counter = count;
+    while (--counter >= 0) {
+        WebCore::IntPoint scroll = WebCore::IntPoint(0, 0);
+        cachedNode = root->moveCursor(direction, &cachedFrame, &scroll);
+        dx += scroll.x();
+        dy += scroll.y();
+    }
+    DBG_NAV_LOGD("new cursor %d (nativeNode=%p) cursorLocation={%d, %d}"
+        "bounds={%d,%d,w=%d,h=%d}", cachedNode ? cachedNode->index() : 0,
+        cachedNode ? cachedNode->nodePointer() : 0,
+            root->cursorLocation().x(), root->cursorLocation().y(),
+            cachedNode ? cachedNode->bounds(cachedFrame).x() : 0,
+            cachedNode ? cachedNode->bounds(cachedFrame).y() : 0,
+            cachedNode ? cachedNode->bounds(cachedFrame).width() : 0,
+            cachedNode ? cachedNode->bounds(cachedFrame).height() : 0);
+    // If !m_heightCanMeasure (such as in the browser), we want to scroll no
+    // matter what
+    if (!ignoreScroll && (!m_heightCanMeasure ||
+            !cachedNode ||
+            (cursor && cursor->nodePointer() == cachedNode->nodePointer())))
+    {
+        if (count == 1 && dx != 0 && dy == 0 && -m_lastDx == dx &&
+                SkTime::GetMSecs() - m_lastDxTime < 1000)
+            root->checkForJiggle(&dx);
+        DBG_NAV_LOGD("scrollBy %d,%d", dx, dy);
+        if ((dx | dy))
+            this->scrollBy(dx, dy);
+        m_lastDx = dx;
+        m_lastDxTime = SkTime::GetMSecs();
+    }
+    bool result = false;
+    if (cachedNode) {
+        showCursorUntimed();
+        m_viewImpl->updateCursorBounds(root, cachedFrame, cachedNode);
+        root->setCursor(const_cast<CachedFrame*>(cachedFrame),
+                const_cast<CachedNode*>(cachedNode));
+        const CachedNode* focus = root->currentFocus();
+        bool clearTextEntry = cachedNode != focus && focus
+                && cachedNode->nodePointer() != focus->nodePointer() && focus->isTextInput();
+        // Stop painting the caret if the old focus was a text input and so is the new cursor.
+        bool stopPaintingCaret = clearTextEntry && cachedNode->wantsKeyEvents();
+        sendMoveMouseIfLatest(clearTextEntry, stopPaintingCaret);
+    } else {
+        int docHeight = root->documentHeight();
+        int docWidth = root->documentWidth();
+        if (visibleRect.maxY() + dy > docHeight)
+            dy = docHeight - visibleRect.maxY();
+        else if (visibleRect.y() + dy < 0)
+            dy = -visibleRect.y();
+        if (visibleRect.maxX() + dx > docWidth)
+            dx = docWidth - visibleRect.maxX();
+        else if (visibleRect.x() < 0)
+            dx = -visibleRect.x();
+        result = direction == CachedFrame::LEFT ? dx >= 0 :
+            direction == CachedFrame::RIGHT ? dx <= 0 :
+            direction == CachedFrame::UP ? dy >= 0 : dy <= 0;
+    }
+    return result;
+}
+
+void notifyProgressFinished()
+{
+    DBG_NAV_LOGD("cursorIsTextInput=%d", cursorIsTextInput(DontAllowNewer));
+    rebuildWebTextView();
+#if DEBUG_NAV_UI
+    if (m_frameCacheUI) {
+        const CachedNode* focus = m_frameCacheUI->currentFocus();
+        DBG_NAV_LOGD("focus %d (nativeNode=%p)",
+            focus ? focus->index() : 0,
+            focus ? focus->nodePointer() : 0);
+    }
+#endif
+}
+
+const CachedNode* findAt(CachedRoot* root, const WebCore::IntRect& rect,
+    const CachedFrame** framePtr, int* rxPtr, int* ryPtr)
+{
+    *rxPtr = 0;
+    *ryPtr = 0;
+    *framePtr = 0;
+    if (!root)
+        return 0;
+    setVisibleRect(root);
+    return root->findAt(rect, framePtr, rxPtr, ryPtr, true);
+}
+
+IntRect setVisibleRect(CachedRoot* root)
+{
+    IntRect visibleRect = getVisibleRect();
+    DBG_NAV_LOGD("getVisibleRect %d,%d,%d,%d",
+        visibleRect.x(), visibleRect.y(), visibleRect.width(), visibleRect.height());
+    root->setVisibleRect(visibleRect);
+    return visibleRect;
+}
+
+void selectBestAt(const WebCore::IntRect& rect)
+{
+    const CachedFrame* frame;
+    int rx, ry;
+    CachedRoot* root = getFrameCache(AllowNewer);
+    if (!root)
+        return;
+    const CachedNode* node = findAt(root, rect, &frame, &rx, &ry);
+    if (!node) {
+        DBG_NAV_LOGD("no nodes found root=%p", root);
+        root->rootHistory()->setMouseBounds(rect);
+        m_viewImpl->m_hasCursorBounds = false;
+        root->setCursor(0, 0);
+        viewInvalidate();
+    } else {
+        DBG_NAV_LOGD("CachedNode:%p (%d)", node, node->index());
+        WebCore::IntRect bounds = node->bounds(frame);
+        root->rootHistory()->setMouseBounds(bounds);
+        m_viewImpl->updateCursorBounds(root, frame, node);
+        showCursorTimed();
+        root->setCursor(const_cast<CachedFrame*>(frame),
+                const_cast<CachedNode*>(node));
+    }
+    sendMoveMouseIfLatest(false, false);
+}
+
+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;
+    IntRect rect = IntRect(x - slop, y - slop, slop * 2, slop * 2);
+    int rx, ry;
+    CachedRoot* root = getFrameCache(AllowNewer);
+    if (!root)
+        return 0;
+    const CachedFrame* frame = 0;
+    const CachedNode* result = findAt(root, rect, &frame, &rx, &ry);
+    CachedHistory* history = root->rootHistory();
+    if (!result) {
+        DBG_NAV_LOGD("no nodes found root=%p", root);
+        history->setNavBounds(rect);
+        m_viewImpl->m_hasCursorBounds = false;
+        root->hideCursor();
+        int dx = root->checkForCenter(x, y);
+        if (dx) {
+            scrollBy(dx, 0);
+            pageScrolled = true;
+        }
+        sendMotionUp(frame ? (WebCore::Frame*) frame->framePointer() : 0,
+            0, x, y);
+        viewInvalidate();
+        return pageScrolled;
+    }
+    DBG_NAV_LOGD("CachedNode:%p (%d) x=%d y=%d rx=%d ry=%d", result,
+        result->index(), x, y, rx, ry);
+    WebCore::IntRect navBounds = WebCore::IntRect(rx, ry, 1, 1);
+    history->setNavBounds(navBounds);
+    history->setMouseBounds(navBounds);
+    m_viewImpl->updateCursorBounds(root, frame, result);
+    root->setCursor(const_cast<CachedFrame*>(frame),
+        const_cast<CachedNode*>(result));
+    if (result->isSyntheticLink())
+        overrideUrlLoading(result->getExport());
+    else {
+        sendMotionUp(
+            (WebCore::Frame*) frame->framePointer(),
+            (WebCore::Node*) result->nodePointer(), rx, ry);
+    }
+    if (result->isTextInput() || result->isSelect()
+            || result->isContentEditable()) {
+        showCursorUntimed();
+    } else
+        showCursorTimed();
+    return pageScrolled;
 }
 
 #if USE(ACCELERATED_COMPOSITING)
 static const ScrollableLayerAndroid* findScrollableLayer(
     const LayerAndroid* parent, int x, int y, SkIRect* foundBounds) {
-    IntRect bounds = enclosingIntRect(parent->fullContentAreaMapped());
-
+    SkRect bounds;
+    parent->bounds(&bounds);
     // Check the parent bounds first; this will clip to within a masking layer's
     // bounds.
     if (parent->masksToBounds() && !bounds.contains(x, y))
         return 0;
-
+    // Move the hit test local to parent.
+    x -= bounds.fLeft;
+    y -= bounds.fTop;
     int count = parent->countChildren();
     while (count--) {
         const LayerAndroid* child = parent->getChild(count);
-        const ScrollableLayerAndroid* result = findScrollableLayer(child, x, y, foundBounds);
+        const ScrollableLayerAndroid* result = findScrollableLayer(child, x, y,
+            foundBounds);
         if (result) {
+            foundBounds->offset(bounds.fLeft, bounds.fTop);
             if (parent->masksToBounds()) {
                 if (bounds.width() < foundBounds->width())
                     foundBounds->fRight = foundBounds->fLeft + bounds.width();
@@ -392,7 +1070,7 @@
         }
     }
     if (parent->contentIsScrollable()) {
-        foundBounds->set(bounds.x(), bounds.y(), bounds.width(), bounds.height());
+        foundBounds->set(0, 0, bounds.width(), bounds.height());
         return static_cast<const ScrollableLayerAndroid*>(parent);
     }
     return 0;
@@ -402,9 +1080,11 @@
 int scrollableLayer(int x, int y, SkIRect* layerRect, SkIRect* bounds)
 {
 #if USE(ACCELERATED_COMPOSITING)
-    if (!m_baseLayer)
+    const LayerAndroid* layerRoot = compositeRoot();
+    if (!layerRoot)
         return 0;
-    const ScrollableLayerAndroid* result = findScrollableLayer(m_baseLayer, x, y, bounds);
+    const ScrollableLayerAndroid* result = findScrollableLayer(layerRoot, x, y,
+        bounds);
     if (result) {
         result->getScrollRect(layerRect);
         return result->uniqueId();
@@ -419,6 +1099,52 @@
         m_glWebViewState->scrollLayer(layerId, x, y);
 }
 
+int getBlockLeftEdge(int x, int y, float scale)
+{
+    CachedRoot* root = getFrameCache(AllowNewer);
+    if (root)
+        return root->getBlockLeftEdge(x, y, scale);
+    return -1;
+}
+
+void overrideUrlLoading(const WTF::String& url)
+{
+    JNIEnv* env = JSC::Bindings::getJNIEnv();
+    AutoJObject javaObject = m_javaGlue.object(env);
+    if (!javaObject.get())
+        return;
+    jstring jName = wtfStringToJstring(env, url);
+    env->CallVoidMethod(javaObject.get(), m_javaGlue.m_overrideLoading, jName);
+    env->DeleteLocalRef(jName);
+}
+
+void setFindIsUp(bool up)
+{
+    DBG_NAV_LOGD("up=%d", up);
+    m_viewImpl->m_findIsUp = up;
+}
+
+void setFindIsEmpty()
+{
+    DBG_NAV_LOG("");
+    m_findOnPage.clearCurrentLocation();
+}
+
+void showCursorTimed()
+{
+    DBG_NAV_LOG("");
+    m_ringAnimationEnd = SkTime::GetMSecs() + PRESSED_STATE_DURATION;
+    viewInvalidate();
+}
+
+void showCursorUntimed()
+{
+    DBG_NAV_LOG("");
+    m_ring.m_isPressed = false;
+    m_ringAnimationEnd = UINT_MAX;
+    viewInvalidate();
+}
+
 void setHeightCanMeasure(bool measure)
 {
     m_heightCanMeasure = measure;
@@ -426,16 +1152,170 @@
 
 String getSelection()
 {
-    SelectText* select = static_cast<SelectText*>(
-            getDrawExtra(WebView::DrawExtrasSelection));
-    if (select)
-        return select->getText();
-    return String();
+    return m_selectText.getSelection();
+}
+
+void moveSelection(int x, int y)
+{
+    m_selectText.moveSelection(getVisibleRect(), x, y);
+}
+
+IntPoint selectableText()
+{
+    const CachedRoot* root = getFrameCache(DontAllowNewer);
+    if (!root)
+        return IntPoint(0, 0);
+    return m_selectText.selectableText(root);
+}
+
+void selectAll()
+{
+    m_selectText.selectAll();
+}
+
+int selectionX()
+{
+    return m_selectText.selectionX();
+}
+
+int selectionY()
+{
+    return m_selectText.selectionY();
+}
+
+void resetSelection()
+{
+    m_selectText.reset();
+}
+
+bool startSelection(int x, int y)
+{
+    const CachedRoot* root = getFrameCache(DontAllowNewer);
+    if (!root)
+        return false;
+    updateSelectionHandles();
+    return m_selectText.startSelection(root, getVisibleRect(), x, y);
+}
+
+bool wordSelection(int x, int y)
+{
+    const CachedRoot* root = getFrameCache(DontAllowNewer);
+    if (!root)
+        return false;
+    updateSelectionHandles();
+    return m_selectText.wordSelection(root, getVisibleRect(), x, y);
+}
+
+bool extendSelection(int x, int y)
+{
+    m_selectText.extendSelection(getVisibleRect(), x, y);
+    return true;
+}
+
+bool hitSelection(int x, int y)
+{
+    updateSelectionHandles();
+    return m_selectText.hitSelection(x, y);
+}
+
+void setExtendSelection()
+{
+    m_selectText.setExtendSelection(true);
+}
+
+void setSelectionPointer(bool set, float scale, int x, int y)
+{
+    m_selectText.setDrawPointer(set);
+    if (!set)
+        return;
+    m_selectText.m_inverseScale = scale;
+    m_selectText.m_selectX = x;
+    m_selectText.m_selectY = y;
+}
+
+void sendMoveFocus(WebCore::Frame* framePtr, WebCore::Node* nodePtr)
+{
+    DBG_NAV_LOGD("framePtr=%p nodePtr=%p", framePtr, nodePtr);
+    JNIEnv* env = JSC::Bindings::getJNIEnv();
+    AutoJObject javaObject = m_javaGlue.object(env);
+    if (!javaObject.get())
+        return;
+    env->CallVoidMethod(javaObject.get(), m_javaGlue.m_sendMoveFocus, (jint) framePtr, (jint) nodePtr);
+    checkException(env);
+}
+
+void sendMoveMouse(WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y)
+{
+    DBG_NAV_LOGD("framePtr=%p nodePtr=%p x=%d y=%d", framePtr, nodePtr, x, y);
+    JNIEnv* env = JSC::Bindings::getJNIEnv();
+    AutoJObject javaObject = m_javaGlue.object(env);
+    if (!javaObject.get())
+        return;
+    env->CallVoidMethod(javaObject.get(), m_javaGlue.m_sendMoveMouse, reinterpret_cast<jint>(framePtr), reinterpret_cast<jint>(nodePtr), x, y);
+    checkException(env);
+}
+
+void sendMoveMouseIfLatest(bool clearTextEntry, bool stopPaintingCaret)
+{
+    LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
+    JNIEnv* env = JSC::Bindings::getJNIEnv();
+    AutoJObject javaObject = m_javaGlue.object(env);
+    if (!javaObject.get())
+        return;
+    env->CallVoidMethod(javaObject.get(), m_javaGlue.m_sendMoveMouseIfLatest, clearTextEntry, stopPaintingCaret);
+    checkException(env);
+}
+
+void sendMotionUp(WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y)
+{
+    DBG_NAV_LOGD("m_generation=%d framePtr=%p nodePtr=%p x=%d y=%d", m_generation, framePtr, nodePtr, x, y);
+    LOG_ASSERT(m_javaGlue.m_obj, "A WebView was not associated with this WebViewNative!");
+
+    JNIEnv* env = JSC::Bindings::getJNIEnv();
+    AutoJObject javaObject = m_javaGlue.object(env);
+    if (!javaObject.get())
+        return;
+    m_viewImpl->m_touchGeneration = ++m_generation;
+    env->CallVoidMethod(javaObject.get(), m_javaGlue.m_sendMotionUp, m_generation, (jint) framePtr, (jint) nodePtr, x, y);
+    checkException(env);
+}
+
+void findNext(bool forward)
+{
+    m_findOnPage.findNext(forward);
+    scrollToCurrentMatch();
+    viewInvalidate();
+}
+
+// With this call, WebView takes ownership of matches, and is responsible for
+// deleting it.
+void setMatches(WTF::Vector<MatchInfo>* matches, jboolean sameAsLastSearch)
+{
+    // If this search is the same as the last one, check against the old
+    // location to determine whether to scroll.  If the same word is found
+    // in the same place, then do not scroll.
+    IntRect oldLocation;
+    bool checkAgainstOldLocation = false;
+    if (sameAsLastSearch && m_findOnPage.isCurrentLocationValid()) {
+        oldLocation = m_findOnPage.currentMatchBounds();
+        checkAgainstOldLocation = true;
+    }
+
+    m_findOnPage.setMatches(matches);
+
+    if (!checkAgainstOldLocation || oldLocation != m_findOnPage.currentMatchBounds())
+        scrollToCurrentMatch();
+    viewInvalidate();
+}
+
+int currentMatchIndex()
+{
+    return m_findOnPage.currentMatchIndex();
 }
 
 bool scrollBy(int dx, int dy)
 {
-    ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
+    LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
 
     JNIEnv* env = JSC::Bindings::getJNIEnv();
     AutoJObject javaObject = m_javaGlue.object(env);
@@ -454,6 +1334,44 @@
 #endif
 }
 
+bool hasCursorNode()
+{
+    CachedRoot* root = getFrameCache(DontAllowNewer);
+    if (!root) {
+        DBG_NAV_LOG("!root");
+        return false;
+    }
+    const CachedNode* cursorNode = root->currentCursor();
+    DBG_NAV_LOGD("cursorNode=%d (nodePointer=%p)",
+        cursorNode ? cursorNode->index() : -1,
+        cursorNode ? cursorNode->nodePointer() : 0);
+    return cursorNode;
+}
+
+bool hasFocusNode()
+{
+    CachedRoot* root = getFrameCache(DontAllowNewer);
+    if (!root) {
+        DBG_NAV_LOG("!root");
+        return false;
+    }
+    const CachedNode* focusNode = root->currentFocus();
+    DBG_NAV_LOGD("focusNode=%d (nodePointer=%p)",
+        focusNode ? focusNode->index() : -1,
+        focusNode ? focusNode->nodePointer() : 0);
+    return focusNode;
+}
+
+void rebuildWebTextView()
+{
+    JNIEnv* env = JSC::Bindings::getJNIEnv();
+    AutoJObject javaObject = m_javaGlue.object(env);
+    if (!javaObject.get())
+        return;
+    env->CallVoidMethod(javaObject.get(), m_javaGlue.m_rebuildWebTextView);
+    checkException(env);
+}
+
 void viewInvalidate()
 {
     JNIEnv* env = JSC::Bindings::getJNIEnv();
@@ -485,64 +1403,112 @@
     checkException(env);
 }
 
-#if ENABLE(ANDROID_OVERFLOW_SCROLL)
-static void copyScrollPosition(const LayerAndroid* fromRoot,
-                               LayerAndroid* toRoot, int layerId)
+bool inFullScreenMode()
 {
-    if (!fromRoot || !toRoot)
+    JNIEnv* env = JSC::Bindings::getJNIEnv();
+    AutoJObject javaObject = m_javaGlue.object(env);
+    if (!javaObject.get())
+        return false;
+    jboolean result = env->CallBooleanMethod(javaObject.get(), m_javaGlue.m_inFullScreenMode);
+    checkException(env);
+    return result;
+}
+
+int moveGeneration()
+{
+    return m_viewImpl->m_moveGeneration;
+}
+
+LayerAndroid* compositeRoot() const
+{
+    LOG_ASSERT(!m_baseLayer || m_baseLayer->countChildren() == 1,
+            "base layer can't have more than one child %s", __FUNCTION__);
+    if (m_baseLayer && m_baseLayer->countChildren() == 1)
+        return static_cast<LayerAndroid*>(m_baseLayer->getChild(0));
+    else
+        return 0;
+}
+
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+static void copyScrollPositionRecursive(const LayerAndroid* from,
+                                        LayerAndroid* root)
+{
+    if (!from || !root)
         return;
-    const LayerAndroid* from = fromRoot->findById(layerId);
-    LayerAndroid* to = toRoot->findById(layerId);
-    if (!from || !to || !from->contentIsScrollable() || !to->contentIsScrollable())
-        return;
-    // TODO: Support this for iframes.
-    if (to->isIFrameContent() || from->isIFrameContent())
-        return;
-    to->setScrollOffset(from->getScrollOffset());
+    for (int i = 0; i < from->countChildren(); i++) {
+        const LayerAndroid* l = from->getChild(i);
+        if (l->contentIsScrollable()) {
+            const SkPoint& pos = l->getPosition();
+            LayerAndroid* match = root->findById(l->uniqueId());
+            if (match && match->contentIsScrollable())
+                match->setPosition(pos.fX, pos.fY);
+        }
+        copyScrollPositionRecursive(l, root);
+    }
 }
 #endif
 
-BaseLayerAndroid* getBaseLayer() const { return m_baseLayer; }
-
-bool setBaseLayer(BaseLayerAndroid* newBaseLayer, bool showVisualIndicator,
-                  bool isPictureAfterFirstLayout, int scrollingLayer)
+void registerPageSwapCallback()
 {
-    bool queueFull = false;
+    m_pageSwapCallbackRegistered = true;
+}
+
+void setBaseLayer(BaseLayerAndroid* layer, SkRegion& inval, bool showVisualIndicator,
+                  bool isPictureAfterFirstLayout, bool registerPageSwapCallback)
+{
 #if USE(ACCELERATED_COMPOSITING)
     if (m_glWebViewState)
-        queueFull = m_glWebViewState->setBaseLayer(newBaseLayer, showVisualIndicator,
-                                                   isPictureAfterFirstLayout);
+        m_glWebViewState->setBaseLayer(layer, inval, showVisualIndicator,
+                                       isPictureAfterFirstLayout);
+    m_pageSwapCallbackRegistered |= registerPageSwapCallback;
 #endif
 
 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
-    copyScrollPosition(m_baseLayer, newBaseLayer, scrollingLayer);
+    if (layer) {
+        // TODO: the below tree copies are only necessary in software rendering
+        LayerAndroid* newCompositeRoot = static_cast<LayerAndroid*>(layer->getChild(0));
+        copyScrollPositionRecursive(compositeRoot(), newCompositeRoot);
+    }
 #endif
     SkSafeUnref(m_baseLayer);
-    m_baseLayer = newBaseLayer;
+    m_baseLayer = layer;
+    CachedRoot* root = getFrameCache(DontAllowNewer);
+    if (!root)
+        return;
+    root->resetLayers();
+    root->setRootLayer(compositeRoot());
+}
 
-    return queueFull;
+void getTextSelectionRegion(SkRegion *region)
+{
+    m_selectText.getSelectionRegion(getVisibleRect(), region, compositeRoot());
+}
+
+void getTextSelectionHandles(int* handles)
+{
+    m_selectText.getSelectionHandles(handles, compositeRoot());
+}
+
+void replaceBaseContent(PictureSet* set)
+{
+    if (!m_baseLayer)
+        return;
+    m_baseLayer->setContent(*set);
+    delete set;
 }
 
 void copyBaseContentToPicture(SkPicture* picture)
 {
-    if (!m_baseLayer || !m_baseLayer->content())
+    if (!m_baseLayer)
         return;
-    LayerContent* content = m_baseLayer->content();
-    SkCanvas* canvas = picture->beginRecording(content->width(), content->height(),
-                                              SkPicture::kUsePathBoundsForClip_RecordingFlag);
-
-    // clear the BaseLayerAndroid's previous matrix (set at each draw)
-    SkMatrix baseMatrix;
-    baseMatrix.reset();
-    m_baseLayer->setMatrix(baseMatrix);
-
-    m_baseLayer->draw(canvas, 0);
-
+    PictureSet* content = m_baseLayer->content();
+    m_baseLayer->drawCanvas(picture->beginRecording(content->width(), content->height(),
+            SkPicture::kUsePathBoundsForClip_RecordingFlag));
     picture->endRecording();
 }
 
 bool hasContent() {
-    if (!m_baseLayer || !m_baseLayer->content())
+    if (!m_baseLayer)
         return false;
     return !m_baseLayer->content()->isEmpty();
 }
@@ -556,197 +1522,37 @@
     return m_glDrawFunctor;
 }
 
-void setVisibleContentRect(SkRect& visibleContentRect) {
-    m_visibleContentRect = visibleContentRect;
+BaseLayerAndroid* getBaseLayer() {
+    return m_baseLayer;
 }
 
-void setDrawExtra(DrawExtra *extra, DrawExtras type)
-{
-    if (type == DrawExtrasNone)
-        return;
-    DrawExtra* old = m_extras[type - 1];
-    m_extras[type - 1] = extra;
-    if (old != extra) {
-        delete old;
-    }
+void setVisibleRect(SkRect& visibleRect) {
+    m_visibleRect = visibleRect;
 }
 
-void setTextSelection(SelectText *selection) {
-    setDrawExtra(selection, DrawExtrasSelection);
-}
-
-const TransformationMatrix* getLayerTransform(int layerId) {
-    if (layerId != -1 && m_baseLayer) {
-        LayerAndroid* layer = m_baseLayer->findById(layerId);
-        // We need to make sure the drawTransform is up to date as this is
-        // called before a draw() or drawGL()
-        if (layer) {
-            m_baseLayer->updatePositionsRecursive(m_visibleContentRect);
-            return layer->drawTransform();
-        }
-    }
-    return 0;
-}
-
-int getHandleLayerId(SelectText::HandleId handleId, SkIPoint& cursorPoint,
-        FloatQuad& textBounds) {
-    SelectText* selectText = static_cast<SelectText*>(getDrawExtra(DrawExtrasSelection));
-    if (!selectText || !m_baseLayer)
-        return -1;
-    int layerId = selectText->caretLayerId(handleId);
-    IntRect cursorRect = selectText->caretRect(handleId);
-    IntRect textRect = selectText->textRect(handleId);
-    // Rects exclude the last pixel on right/bottom. We want only included pixels.
-    cursorPoint.set(cursorRect.x(), cursorRect.maxY() - 1);
-    textRect.setHeight(std::max(1, textRect.height() - 1));
-    textRect.setWidth(std::max(1, textRect.width() - 1));
-    textBounds = FloatQuad(textRect);
-
-    const TransformationMatrix* transform = getLayerTransform(layerId);
-    if (transform) {
-        // We're overloading the concept of Rect to be just the two
-        // points (bottom-left and top-right.
-        cursorPoint = transform->mapPoint(cursorPoint);
-        textBounds = transform->mapQuad(textBounds);
-    }
-    return layerId;
-}
-
-void mapLayerRect(int layerId, SkIRect& rect) {
-    const TransformationMatrix* transform = getLayerTransform(layerId);
-    if (transform)
-        rect = transform->mapRect(rect);
-}
-
-void floatQuadToQuadF(JNIEnv* env, const FloatQuad& nativeTextQuad,
-        jobject textQuad)
-{
-    jobject p1 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP1);
-    jobject p2 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP2);
-    jobject p3 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP3);
-    jobject p4 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP4);
-    GraphicsJNI::point_to_jpointf(nativeTextQuad.p1(), env, p1);
-    GraphicsJNI::point_to_jpointf(nativeTextQuad.p2(), env, p2);
-    GraphicsJNI::point_to_jpointf(nativeTextQuad.p3(), env, p3);
-    GraphicsJNI::point_to_jpointf(nativeTextQuad.p4(), env, p4);
-    env->DeleteLocalRef(p1);
-    env->DeleteLocalRef(p2);
-    env->DeleteLocalRef(p3);
-    env->DeleteLocalRef(p4);
-}
-
-// This is called when WebView switches rendering modes in a more permanent fashion
-// such as when the layer type is set or the view is attached/detached from the window
-int setHwAccelerated(bool hwAccelerated) {
-    if (!m_glWebViewState)
-        return 0;
-    LayerAndroid* root = m_baseLayer;
-    if (root)
-        return root->setHwAccelerated(hwAccelerated);
-    return 0;
-}
-
-void setDrawingPaused(bool isPaused)
-{
-    m_isDrawingPaused = isPaused;
-    if (m_viewImpl)
-        m_viewImpl->setPrerenderingEnabled(!isPaused);
-}
-
-// Finds the rectangles within world to the left, right, top, and bottom
-// of rect and adds them to rects. If no intersection exists, false is returned.
-static bool findMaskedRects(const FloatRect& world,
-        const FloatRect& rect, Vector<FloatRect>& rects) {
-    if (!world.intersects(rect))
-        return false; // nothing to subtract
-
-    // left rectangle
-    if (rect.x() > world.x())
-        rects.append(FloatRect(world.x(), world.y(),
-                rect.x() - world.x(), world.height()));
-    // top rectangle
-    if (rect.y() > world.y())
-        rects.append(FloatRect(world.x(), world.y(),
-                world.width(), rect.y() - world.y()));
-    // right rectangle
-    if (rect.maxX() < world.maxX())
-        rects.append(FloatRect(rect.maxX(), world.y(),
-                world.maxX() - rect.maxX(), world.height()));
-    // bottom rectangle
-    if (rect.maxY() < world.maxY())
-        rects.append(FloatRect(world.x(), rect.maxY(),
-                world.width(), world.maxY() - rect.maxY()));
-    return true;
-}
-
-// Returns false if layerId is a fixed position layer, otherwise
-// all fixed position layer rectangles are subtracted from those within
-// rects. Rects will be modified to contain rectangles that don't include
-// the fixed position layer rectangles.
-static bool findMaskedRectsForLayer(LayerAndroid* layer,
-        Vector<FloatRect>& rects, int layerId)
-{
-    if (layer->isPositionFixed()) {
-        if (layerId == layer->uniqueId())
-            return false;
-        FloatRect layerRect = layer->fullContentAreaMapped();
-        for (int i = rects.size() - 1; i >= 0; i--)
-            if (findMaskedRects(rects[i], layerRect, rects))
-                rects.remove(i);
-    }
-
-    int childIndex = 0;
-    while (LayerAndroid* child = layer->getChild(childIndex++))
-        if (!findMaskedRectsForLayer(child, rects, layerId))
-            return false;
-
-    return true;
-}
-
-// Finds the largest rectangle not masked by any fixed layer.
-void findMaxVisibleRect(int movingLayerId, SkIRect& visibleContentRect)
-{
-    if (!m_baseLayer)
-        return;
-
-    FloatRect visibleContentFloatRect(visibleContentRect);
-    m_baseLayer->updatePositionsRecursive(visibleContentFloatRect);
-    Vector<FloatRect> rects;
-    rects.append(visibleContentFloatRect);
-    if (findMaskedRectsForLayer(m_baseLayer, rects, movingLayerId)) {
-        float maxSize = 0.0;
-        const FloatRect* largest = 0;
-        for (int i = 0; i < rects.size(); i++) {
-            const FloatRect& rect = rects[i];
-            float size = rect.width() * rect.height();
-            if (size > maxSize) {
-                maxSize = size;
-                largest = &rect;
-            }
-        }
-        if (largest) {
-            SkRect largeRect = *largest;
-            largeRect.round(&visibleContentRect);
-        }
-    }
-}
-
-private: // local state for WebView
     bool m_isDrawingPaused;
+private: // local state for WebView
     // private to getFrameCache(); other functions operate in a different thread
+    CachedRoot* m_frameCacheUI; // navigation data ready for use
     WebViewCore* m_viewImpl;
     int m_generation; // associate unique ID with sent kit focus to match with ui
+    SkPicture* m_navPictureUI;
+    SkMSec m_ringAnimationEnd;
     // Corresponds to the same-named boolean on the java side.
     bool m_heightCanMeasure;
     int m_lastDx;
     SkMSec m_lastDxTime;
-    DrawExtra* m_extras[DRAW_EXTRAS_SIZE];
+    SelectText m_selectText;
+    FindOnPage m_findOnPage;
+    CursorRing m_ring;
     BaseLayerAndroid* m_baseLayer;
     Functor* m_glDrawFunctor;
 #if USE(ACCELERATED_COMPOSITING)
     GLWebViewState* m_glWebViewState;
+    bool m_pageSwapCallbackRegistered;
 #endif
-    SkRect m_visibleContentRect;
+    RenderSkinButton* m_buttonSkin;
+    SkRect m_visibleRect;
     bool m_isHighEndGfx;
 }; // end of WebView class
 
@@ -759,54 +1565,45 @@
 class GLDrawFunctor : Functor {
     public:
     GLDrawFunctor(WebView* _wvInstance,
-            int (WebView::*_funcPtr)(WebCore::IntRect&, WebCore::IntRect*,
-                    WebCore::IntRect&, int, WebCore::IntRect&, jfloat, jint, bool),
-            WebCore::IntRect _invScreenRect, float _scale, int _extras) {
+            bool(WebView::*_funcPtr)(WebCore::IntRect&, WebCore::IntRect*,
+                    WebCore::IntRect&, int, WebCore::IntRect&,
+                    jfloat, jint),
+            WebCore::IntRect _viewRect, float _scale, int _extras) {
         wvInstance = _wvInstance;
         funcPtr = _funcPtr;
-        invScreenRect = _invScreenRect;
+        viewRect = _viewRect;
         scale = _scale;
         extras = _extras;
     };
-
     status_t operator()(int messageId, void* data) {
-        TRACE_METHOD();
-        bool shouldDraw = (messageId == uirenderer::DrawGlInfo::kModeDraw);
-        if (shouldDraw)
-            wvInstance->updateRectsForGL();
-
-        if (invScreenRect.isEmpty()) {
+        if (viewRect.isEmpty()) {
             // NOOP operation if viewport is empty
             return 0;
         }
 
         WebCore::IntRect inval;
-        int titlebarHeight = screenRect.height() - invScreenRect.height();
+        int titlebarHeight = webViewRect.height() - viewRect.height();
 
         uirenderer::DrawGlInfo* info = reinterpret_cast<uirenderer::DrawGlInfo*>(data);
-        WebCore::IntRect screenClip(info->clipLeft, info->clipTop,
-                                    info->clipRight - info->clipLeft,
-                                    info->clipBottom - info->clipTop);
+        WebCore::IntRect localViewRect = viewRect;
+        if (info->isLayer)
+            localViewRect.move(-1 * localViewRect.x(), -1 * localViewRect.y());
 
-        WebCore::IntRect localInvScreenRect = invScreenRect;
-        if (info->isLayer) {
-            // When webview is on a layer, we need to use the viewport relative
-            // to the FBO, rather than the screen(which will use invScreenRect).
-            localInvScreenRect.setX(screenClip.x());
-            localInvScreenRect.setY(info->height - screenClip.y() - screenClip.height());
-        }
-        // Send the necessary info to the shader.
-        TilesManager::instance()->shader()->setGLDrawInfo(info);
+        WebCore::IntRect clip(info->clipLeft, info->clipTop,
+                              info->clipRight - info->clipLeft,
+                              info->clipBottom - info->clipTop);
+        TilesManager::instance()->shader()->setWebViewMatrix(info->transform, info->isLayer);
 
-        int returnFlags = (*wvInstance.*funcPtr)(localInvScreenRect, &inval, screenRect,
-                titlebarHeight, screenClip, scale, extras, shouldDraw);
-        if ((returnFlags & uirenderer::DrawGlInfo::kStatusDraw) != 0) {
+        bool retVal = (*wvInstance.*funcPtr)(localViewRect, &inval, webViewRect,
+                titlebarHeight, clip, scale, extras);
+        if (retVal) {
             IntRect finalInval;
-            if (inval.isEmpty())
-                finalInval = screenRect;
-            else {
-                finalInval.setX(screenRect.x() + inval.x());
-                finalInval.setY(screenRect.y() + titlebarHeight + inval.y());
+            if (inval.isEmpty()) {
+                finalInval = webViewRect;
+                retVal = true;
+            } else {
+                finalInval.setX(webViewRect.x() + inval.x());
+                finalInval.setY(webViewRect.y() + titlebarHeight + inval.y());
                 finalInval.setWidth(inval.width());
                 finalInval.setHeight(inval.height());
             }
@@ -815,45 +1612,201 @@
             info->dirtyRight = finalInval.maxX();
             info->dirtyBottom = finalInval.maxY();
         }
-        // return 1 if invalidation needed, 2 to request non-drawing functor callback, 0 otherwise
-        ALOGV("returnFlags are %d, shouldDraw %d", returnFlags, shouldDraw);
-        return returnFlags;
+        // return 1 if invalidation needed, 0 otherwise
+        return retVal ? 1 : 0;
     }
-    void updateScreenRect(WebCore::IntRect& _screenRect) {
-        screenRect = _screenRect;
+    void updateRect(WebCore::IntRect& _viewRect) {
+        viewRect = _viewRect;
     }
-    void updateInvScreenRect(WebCore::IntRect& _invScreenRect) {
-        invScreenRect = _invScreenRect;
-    }
-    void updateScale(float _scale) {
-        scale = _scale;
-    }
-    void updateExtras(jint _extras) {
-        extras = _extras;
+    void updateViewRect(WebCore::IntRect& _viewRect) {
+        webViewRect = _viewRect;
     }
     private:
     WebView* wvInstance;
-    int (WebView::*funcPtr)(WebCore::IntRect&, WebCore::IntRect*,
-            WebCore::IntRect&, int, WebCore::IntRect&, float, int, bool);
-    WebCore::IntRect invScreenRect;
-    WebCore::IntRect screenRect;
+    bool (WebView::*funcPtr)(WebCore::IntRect&, WebCore::IntRect*,
+            WebCore::IntRect&, int, WebCore::IntRect&, float, int);
+    WebCore::IntRect viewRect;
+    WebCore::IntRect webViewRect;
     jfloat scale;
     jint extras;
 };
 
+static jobject createJavaRect(JNIEnv* env, int x, int y, int right, int bottom)
+{
+    jclass rectClass = env->FindClass("android/graphics/Rect");
+    jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
+    jobject rect = env->NewObject(rectClass, init, x, y, right, bottom);
+    env->DeleteLocalRef(rectClass);
+    return rect;
+}
+
 /*
  * Native JNI methods
  */
+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();
+    return createJavaRect(env, bounds.x(), bounds.y(),
+                          bounds.maxX(), bounds.maxY());
+}
+
+static int nativeCacheHitNodePointer(JNIEnv *env, jobject obj)
+{
+    return reinterpret_cast<int>(GET_NATIVE_VIEW(env, obj)
+        ->m_cacheHitNode->nodePointer());
+}
+
+static bool nativeCacheHitIsPlugin(JNIEnv *env, jobject obj)
+{
+    return GET_NATIVE_VIEW(env, obj)->m_cacheHitNode->isPlugin();
+}
+
+static void nativeClearCursor(JNIEnv *env, jobject obj)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+    view->clearCursor();
+}
 
 static void nativeCreate(JNIEnv *env, jobject obj, int viewImpl,
                          jstring drawableDir, jboolean isHighEndGfx)
 {
     WTF::String dir = jstringToWtfString(env, drawableDir);
-    new WebView(env, obj, viewImpl, dir, isHighEndGfx);
+    WebView* webview = new WebView(env, obj, viewImpl, dir, isHighEndGfx);
     // NEED THIS OR SOMETHING LIKE IT!
     //Release(obj);
 }
 
+static jint nativeCursorFramePointer(JNIEnv *env, jobject obj)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+    if (!root)
+        return 0;
+    const CachedFrame* frame = 0;
+    (void) root->currentCursor(&frame);
+    return reinterpret_cast<int>(frame ? frame->framePointer() : 0);
+}
+
+static const CachedNode* getCursorNode(JNIEnv *env, jobject obj)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+    return root ? root->currentCursor() : 0;
+}
+
+static const CachedNode* getCursorNode(JNIEnv *env, jobject obj,
+    const CachedFrame** frame)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+    return root ? root->currentCursor(frame) : 0;
+}
+
+static const CachedNode* getFocusCandidate(JNIEnv *env, jobject obj,
+    const CachedFrame** frame)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+    if (!root)
+        return 0;
+    const CachedNode* cursor = root->currentCursor(frame);
+    if (cursor && cursor->wantsKeyEvents())
+        return cursor;
+    return root->currentFocus(frame);
+}
+
+static bool focusCandidateHasNextTextfield(JNIEnv *env, jobject obj)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+    if (!root)
+        return false;
+    const CachedNode* cursor = root->currentCursor();
+    if (!cursor || !cursor->isTextInput())
+        cursor = root->currentFocus();
+    if (!cursor || !cursor->isTextInput()) return false;
+    return root->nextTextField(cursor, 0);
+}
+
+static const CachedNode* getFocusNode(JNIEnv *env, jobject obj)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+    return root ? root->currentFocus() : 0;
+}
+
+static const CachedNode* getFocusNode(JNIEnv *env, jobject obj,
+    const CachedFrame** frame)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+    return root ? root->currentFocus(frame) : 0;
+}
+
+static const CachedInput* getInputCandidate(JNIEnv *env, jobject obj)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+    if (!root)
+        return 0;
+    const CachedFrame* frame;
+    const CachedNode* cursor = root->currentCursor(&frame);
+    if (!cursor || !cursor->wantsKeyEvents())
+        cursor = root->currentFocus(&frame);
+    return cursor ? frame->textInput(cursor) : 0;
+}
+
+static jboolean nativePageShouldHandleShiftAndArrows(JNIEnv *env, jobject obj)
+{
+    const CachedNode* focus = getFocusNode(env, obj);
+    if (!focus) return false;
+    // Plugins handle shift and arrows whether or not they have focus.
+    if (focus->isPlugin()) return true;
+    const CachedNode* cursor = getCursorNode(env, obj);
+    // ContentEditable nodes should only receive shift and arrows if they have
+    // both the cursor and the focus.
+    return cursor && cursor->nodePointer() == focus->nodePointer()
+            && cursor->isContentEditable();
+}
+
+static jobject nativeCursorNodeBounds(JNIEnv *env, jobject obj)
+{
+    const CachedFrame* frame;
+    const CachedNode* node = getCursorNode(env, obj, &frame);
+    WebCore::IntRect bounds = node ? node->bounds(frame)
+        : WebCore::IntRect(0, 0, 0, 0);
+    return createJavaRect(env, bounds.x(), bounds.y(),
+                          bounds.maxX(), bounds.maxY());
+}
+
+static jint nativeCursorNodePointer(JNIEnv *env, jobject obj)
+{
+    const CachedNode* node = getCursorNode(env, obj);
+    return reinterpret_cast<int>(node ? node->nodePointer() : 0);
+}
+
+static jobject nativeCursorPosition(JNIEnv *env, jobject obj)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    const CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+    WebCore::IntPoint pos = WebCore::IntPoint(0, 0);
+    if (root)
+        root->getSimulatedMousePosition(&pos);
+    jclass pointClass = env->FindClass("android/graphics/Point");
+    jmethodID init = env->GetMethodID(pointClass, "<init>", "(II)V");
+    jobject point = env->NewObject(pointClass, init, pos.x(), pos.y());
+    env->DeleteLocalRef(pointClass);
+    return point;
+}
+
 static WebCore::IntRect jrect_to_webrect(JNIEnv* env, jobject obj)
 {
     if (obj) {
@@ -872,67 +1825,88 @@
     return rect;
 }
 
-static void nativeDraw(JNIEnv *env, jobject obj, jobject canv,
-        jobject visible, jint color,
-        jint extras) {
-    SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv);
-    WebView* webView = GET_NATIVE_VIEW(env, obj);
-    SkRect visibleContentRect = jrectf_to_rect(env, visible);
-    webView->setVisibleContentRect(visibleContentRect);
-    webView->draw(canvas, color, static_cast<WebView::DrawExtras>(extras));
+static bool nativeCursorIntersects(JNIEnv *env, jobject obj, jobject visRect)
+{
+    const CachedFrame* frame;
+    const CachedNode* node = getCursorNode(env, obj, &frame);
+    return node ? node->bounds(frame).intersects(
+        jrect_to_webrect(env, visRect)) : false;
 }
 
-static jint nativeCreateDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView,
-                                       jobject jinvscreenrect, jobject jscreenrect,
-                                       jobject jvisiblecontentrect,
-                                       jfloat scale, jint extras) {
-    WebCore::IntRect invScreenRect = jrect_to_webrect(env, jinvscreenrect);
-    WebView *wvInstance = reinterpret_cast<WebView*>(nativeView);
-    SkRect visibleContentRect = jrectf_to_rect(env, jvisiblecontentrect);
-    wvInstance->setVisibleContentRect(visibleContentRect);
+static bool nativeCursorIsAnchor(JNIEnv *env, jobject obj)
+{
+    const CachedNode* node = getCursorNode(env, obj);
+    return node ? node->isAnchor() : false;
+}
 
-    GLDrawFunctor* functor = (GLDrawFunctor*) wvInstance->getFunctor();
-    if (!functor) {
-        functor = new GLDrawFunctor(wvInstance, &android::WebView::drawGL,
-                                    invScreenRect, scale, extras);
-        wvInstance->setFunctor((Functor*) functor);
-    } else {
-        functor->updateInvScreenRect(invScreenRect);
-        functor->updateScale(scale);
-        functor->updateExtras(extras);
-    }
+static bool nativeCursorIsTextInput(JNIEnv *env, jobject obj)
+{
+    const CachedNode* node = getCursorNode(env, obj);
+    return node ? node->isTextInput() : false;
+}
 
-    WebCore::IntRect rect = jrect_to_webrect(env, jscreenrect);
-    functor->updateScreenRect(rect);
+static jobject nativeCursorText(JNIEnv *env, jobject obj)
+{
+    const CachedNode* node = getCursorNode(env, obj);
+    if (!node)
+        return 0;
+    WTF::String value = node->getExport();
+    return wtfStringToJstring(env, value);
+}
+
+static void nativeDebugDump(JNIEnv *env, jobject obj)
+{
+#if DUMP_NAV_CACHE
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+    view->debugDump();
+#endif
+}
+
+static jint nativeDraw(JNIEnv *env, jobject obj, jobject canv,
+        jobject visible, jint color,
+        jint extras, jboolean split) {
+    SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv);
+    WebView* webView = GET_NATIVE_VIEW(env, obj);
+    SkRect visibleRect = jrectf_to_rect(env, visible);
+    webView->setVisibleRect(visibleRect);
+    PictureSet* pictureSet = webView->draw(canvas, color, extras, split);
+    return reinterpret_cast<jint>(pictureSet);
+}
+
+static jint nativeGetDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView,
+                                    jobject jrect, jobject jviewrect,
+                                    jobject jvisiblerect,
+                                    jfloat scale, jint extras) {
+    WebCore::IntRect viewRect = jrect_to_webrect(env, jrect);
+    WebView *wvInstance = (WebView*) nativeView;
+    SkRect visibleRect = jrectf_to_rect(env, jvisiblerect);
+    wvInstance->setVisibleRect(visibleRect);
+
+    GLDrawFunctor* functor = new GLDrawFunctor(wvInstance,
+            &android::WebView::drawGL, viewRect, scale, extras);
+    wvInstance->setFunctor((Functor*) functor);
+
+    WebCore::IntRect webViewRect = jrect_to_webrect(env, jviewrect);
+    functor->updateViewRect(webViewRect);
 
     return (jint)functor;
 }
 
-static jint nativeGetDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView) {
-    WebView *wvInstance = reinterpret_cast<WebView*>(nativeView);
-    if (!wvInstance)
-        return 0;
-
-    return (jint) wvInstance->getFunctor();
-}
-
-static void nativeUpdateDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView,
-                                       jobject jinvscreenrect, jobject jscreenrect,
-                                       jobject jvisiblecontentrect, jfloat scale) {
-    WebView *wvInstance = reinterpret_cast<WebView*>(nativeView);
+static void nativeUpdateDrawGLFunction(JNIEnv *env, jobject obj, jobject jrect,
+        jobject jviewrect, jobject jvisiblerect) {
+    WebView *wvInstance = GET_NATIVE_VIEW(env, obj);
     if (wvInstance) {
         GLDrawFunctor* functor = (GLDrawFunctor*) wvInstance->getFunctor();
         if (functor) {
-            WebCore::IntRect invScreenRect = jrect_to_webrect(env, jinvscreenrect);
-            functor->updateInvScreenRect(invScreenRect);
+            WebCore::IntRect viewRect = jrect_to_webrect(env, jrect);
+            functor->updateRect(viewRect);
 
-            SkRect visibleContentRect = jrectf_to_rect(env, jvisiblecontentrect);
-            wvInstance->setVisibleContentRect(visibleContentRect);
+            SkRect visibleRect = jrectf_to_rect(env, jvisiblerect);
+            wvInstance->setVisibleRect(visibleRect);
 
-            WebCore::IntRect screenRect = jrect_to_webrect(env, jscreenrect);
-            functor->updateScreenRect(screenRect);
-
-            functor->updateScale(scale);
+            WebCore::IntRect webViewRect = jrect_to_webrect(env, jviewrect);
+            functor->updateViewRect(webViewRect);
         }
     }
 }
@@ -941,29 +1915,56 @@
 {
     // only call in software rendering, initialize and evaluate animations
 #if USE(ACCELERATED_COMPOSITING)
-    BaseLayerAndroid* baseLayer = reinterpret_cast<WebView*>(nativeView)->getBaseLayer();
-    if (baseLayer) {
-        baseLayer->initAnimations();
-        return baseLayer->evaluateAnimations();
+    LayerAndroid* root = ((WebView*)nativeView)->compositeRoot();
+    if (root) {
+        root->initAnimations();
+        return root->evaluateAnimations();
     }
 #endif
     return false;
 }
 
-static bool nativeSetBaseLayer(JNIEnv *env, jobject obj, jint nativeView, jint layer,
-                               jboolean showVisualIndicator,
-                               jboolean isPictureAfterFirstLayout,
-                               jint scrollingLayer)
+static void nativeSetBaseLayer(JNIEnv *env, jobject obj, jint layer, jobject inval,
+                                jboolean showVisualIndicator,
+                                jboolean isPictureAfterFirstLayout,
+                                jboolean registerPageSwapCallback)
 {
     BaseLayerAndroid* layerImpl = reinterpret_cast<BaseLayerAndroid*>(layer);
-    return reinterpret_cast<WebView*>(nativeView)->setBaseLayer(layerImpl, showVisualIndicator,
-                                                                isPictureAfterFirstLayout,
-                                                                scrollingLayer);
+    SkRegion invalRegion;
+    if (inval)
+        invalRegion = *GraphicsJNI::getNativeRegion(env, inval);
+    GET_NATIVE_VIEW(env, obj)->setBaseLayer(layerImpl, invalRegion, showVisualIndicator,
+                                            isPictureAfterFirstLayout,
+                                            registerPageSwapCallback);
 }
 
-static BaseLayerAndroid* nativeGetBaseLayer(JNIEnv *env, jobject obj, jint nativeView)
+static void nativeGetTextSelectionRegion(JNIEnv *env, jobject obj, jint view,
+                                         jobject region)
 {
-    return reinterpret_cast<WebView*>(nativeView)->getBaseLayer();
+    if (!region)
+        return;
+    SkRegion* nregion = GraphicsJNI::getNativeRegion(env, region);
+    ((WebView*)view)->getTextSelectionRegion(nregion);
+}
+
+static void nativeGetSelectionHandles(JNIEnv *env, jobject obj, jint view,
+                                      jintArray arr)
+{
+    int handles[4];
+    ((WebView*)view)->getTextSelectionHandles(handles);
+    env->SetIntArrayRegion(arr, 0, 4, handles);
+    checkException(env);
+}
+
+static BaseLayerAndroid* nativeGetBaseLayer(JNIEnv *env, jobject obj)
+{
+    return GET_NATIVE_VIEW(env, obj)->getBaseLayer();
+}
+
+static void nativeReplaceBaseContent(JNIEnv *env, jobject obj, jint content)
+{
+    PictureSet* set = reinterpret_cast<PictureSet*>(content);
+    GET_NATIVE_VIEW(env, obj)->replaceBaseContent(set);
 }
 
 static void nativeCopyBaseContentToPicture(JNIEnv *env, jobject obj, jobject pict)
@@ -977,40 +1978,549 @@
     return GET_NATIVE_VIEW(env, obj)->hasContent();
 }
 
+static jobject nativeImageURI(JNIEnv *env, jobject obj, jint x, jint y)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+    WTF::String uri = view->imageURI(x, y);
+    return wtfStringToJstring(env, uri);
+}
+
+static jint nativeFocusCandidateFramePointer(JNIEnv *env, jobject obj)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+    if (!root)
+        return 0;
+    const CachedFrame* frame = 0;
+    const CachedNode* cursor = root->currentCursor(&frame);
+    if (!cursor || !cursor->wantsKeyEvents())
+        (void) root->currentFocus(&frame);
+    return reinterpret_cast<int>(frame ? frame->framePointer() : 0);
+}
+
+static bool nativeFocusCandidateIsPassword(JNIEnv *env, jobject obj)
+{
+    const CachedInput* input = getInputCandidate(env, obj);
+    return input && input->getType() == CachedInput::PASSWORD;
+}
+
+static bool nativeFocusCandidateIsRtlText(JNIEnv *env, jobject obj)
+{
+    const CachedInput* input = getInputCandidate(env, obj);
+    return input ? input->isRtlText() : false;
+}
+
+static bool nativeFocusCandidateIsTextInput(JNIEnv *env, jobject obj)
+{
+    const CachedNode* node = getFocusCandidate(env, obj, 0);
+    return node ? node->isTextInput() : false;
+}
+
+static jint nativeFocusCandidateMaxLength(JNIEnv *env, jobject obj)
+{
+    const CachedInput* input = getInputCandidate(env, obj);
+    return input ? input->maxLength() : false;
+}
+
+static jint nativeFocusCandidateIsAutoComplete(JNIEnv *env, jobject obj)
+{
+    const CachedInput* input = getInputCandidate(env, obj);
+    return input ? input->autoComplete() : false;
+}
+
+static jobject nativeFocusCandidateName(JNIEnv *env, jobject obj)
+{
+    const CachedInput* input = getInputCandidate(env, obj);
+    if (!input)
+        return 0;
+    const WTF::String& name = input->name();
+    return wtfStringToJstring(env, name);
+}
+
+static jobject nativeFocusCandidateNodeBounds(JNIEnv *env, jobject obj)
+{
+    const CachedFrame* frame;
+    const CachedNode* node = getFocusCandidate(env, obj, &frame);
+    WebCore::IntRect bounds = node ? node->originalAbsoluteBounds()
+        : WebCore::IntRect(0, 0, 0, 0);
+    // Inset the rect by 1 unit, so that the focus candidate's border can still
+    // be seen behind it.
+    return createJavaRect(env, bounds.x(), bounds.y(),
+                          bounds.maxX(), bounds.maxY());
+}
+
+static jobject nativeFocusCandidatePaddingRect(JNIEnv *env, jobject obj)
+{
+    const CachedInput* input = getInputCandidate(env, obj);
+    if (!input)
+        return 0;
+    // Note that the Java Rect is being used to pass four integers, rather than
+    // being used as an actual rectangle.
+    return createJavaRect(env, input->paddingLeft(), input->paddingTop(),
+            input->paddingRight(), input->paddingBottom());
+}
+
+static jint nativeFocusCandidatePointer(JNIEnv *env, jobject obj)
+{
+    const CachedNode* node = getFocusCandidate(env, obj, 0);
+    return reinterpret_cast<int>(node ? node->nodePointer() : 0);
+}
+
+static jint nativeFocusCandidateIsSpellcheck(JNIEnv *env, jobject obj)
+{
+    const CachedInput* input = getInputCandidate(env, obj);
+    return input ? input->spellcheck() : false;
+}
+
+static jobject nativeFocusCandidateText(JNIEnv *env, jobject obj)
+{
+    const CachedNode* node = getFocusCandidate(env, obj, 0);
+    if (!node)
+        return 0;
+    WTF::String value = node->getExport();
+    return wtfStringToJstring(env, value);
+}
+
+static int nativeFocusCandidateLineHeight(JNIEnv *env, jobject obj)
+{
+    const CachedInput* input = getInputCandidate(env, obj);
+    return input ? input->lineHeight() : 0;
+}
+
+static jfloat nativeFocusCandidateTextSize(JNIEnv *env, jobject obj)
+{
+    const CachedInput* input = getInputCandidate(env, obj);
+    return input ? input->textSize() : 0.f;
+}
+
+static int nativeFocusCandidateType(JNIEnv *env, jobject obj)
+{
+    const CachedInput* input = getInputCandidate(env, obj);
+    if (!input)
+        return CachedInput::NONE;
+
+    if (input->isTextArea())
+        return CachedInput::TEXT_AREA;
+
+    return input->getType();
+}
+
+static int nativeFocusCandidateLayerId(JNIEnv *env, jobject obj)
+{
+    const CachedFrame* frame = 0;
+    const CachedNode* node = getFocusNode(env, obj, &frame);
+    if (!node || !frame)
+        return -1;
+    const CachedLayer* layer = frame->layer(node);
+    if (!layer)
+        return -1;
+    return layer->uniqueId();
+}
+
+static bool nativeFocusIsPlugin(JNIEnv *env, jobject obj)
+{
+    const CachedNode* node = getFocusNode(env, obj);
+    return node ? node->isPlugin() : false;
+}
+
+static jobject nativeFocusNodeBounds(JNIEnv *env, jobject obj)
+{
+    const CachedFrame* frame;
+    const CachedNode* node = getFocusNode(env, obj, &frame);
+    WebCore::IntRect bounds = node ? node->bounds(frame)
+        : WebCore::IntRect(0, 0, 0, 0);
+    return createJavaRect(env, bounds.x(), bounds.y(),
+                          bounds.maxX(), bounds.maxY());
+}
+
+static jint nativeFocusNodePointer(JNIEnv *env, jobject obj)
+{
+    const CachedNode* node = getFocusNode(env, obj);
+    return node ? reinterpret_cast<int>(node->nodePointer()) : 0;
+}
+
+static bool nativeCursorWantsKeyEvents(JNIEnv* env, jobject jwebview) {
+    WebView* view = GET_NATIVE_VIEW(env, jwebview);
+    LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+    return view->cursorWantsKeyEvents();
+}
+
+static void nativeHideCursor(JNIEnv *env, jobject obj)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+    view->hideCursor();
+}
+
+static void nativeInstrumentReport(JNIEnv *env, jobject obj)
+{
+#ifdef ANDROID_INSTRUMENT
+    TimeCounter::reportNow();
+#endif
+}
+
+static void nativeSelectBestAt(JNIEnv *env, jobject obj, jobject jrect)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+    WebCore::IntRect rect = jrect_to_webrect(env, jrect);
+    view->selectBestAt(rect);
+}
+
+static void nativeSelectAt(JNIEnv *env, jobject obj, jint x, jint y)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+    WebCore::IntRect rect = IntRect(x, y , 1, 1);
+    view->selectBestAt(rect);
+    if (view->hasCursorNode())
+        view->showCursorUntimed();
+}
+
+static jobject nativeLayerBounds(JNIEnv* env, jobject obj, jint jlayer)
+{
+    SkRect r;
+#if USE(ACCELERATED_COMPOSITING)
+    LayerAndroid* layer = (LayerAndroid*) jlayer;
+    r = layer->bounds();
+#else
+    r.setEmpty();
+#endif
+    SkIRect irect;
+    r.round(&irect);
+    jclass rectClass = env->FindClass("android/graphics/Rect");
+    jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
+    jobject rect = env->NewObject(rectClass, init, irect.fLeft, irect.fTop,
+        irect.fRight, irect.fBottom);
+    env->DeleteLocalRef(rectClass);
+    return rect;
+}
+
+static jobject nativeSubtractLayers(JNIEnv* env, jobject obj, jobject jrect)
+{
+    SkIRect irect = jrect_to_webrect(env, jrect);
+#if USE(ACCELERATED_COMPOSITING)
+    LayerAndroid* root = GET_NATIVE_VIEW(env, obj)->compositeRoot();
+    if (root) {
+        SkRect rect;
+        rect.set(irect);
+        rect = root->subtractLayers(rect);
+        rect.round(&irect);
+    }
+#endif
+    jclass rectClass = env->FindClass("android/graphics/Rect");
+    jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
+    jobject rect = env->NewObject(rectClass, init, irect.fLeft, irect.fTop,
+        irect.fRight, irect.fBottom);
+    env->DeleteLocalRef(rectClass);
+    return rect;
+}
+
+static jint nativeTextGeneration(JNIEnv *env, jobject obj)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+    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)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+    return view->motionUp(x, y, slop);
+}
+
+static bool nativeHasCursorNode(JNIEnv *env, jobject obj)
+{
+    return GET_NATIVE_VIEW(env, obj)->hasCursorNode();
+}
+
+static bool nativeHasFocusNode(JNIEnv *env, jobject obj)
+{
+    return GET_NATIVE_VIEW(env, obj)->hasFocusNode();
+}
+
+static bool nativeMoveCursor(JNIEnv *env, jobject obj,
+    int key, int count, bool ignoreScroll)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    DBG_NAV_LOGD("env=%p obj=%p view=%p", env, obj, view);
+    LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+    return view->moveCursor(key, count, ignoreScroll);
+}
+
+static void nativeSetFindIsUp(JNIEnv *env, jobject obj, jboolean isUp)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+    view->setFindIsUp(isUp);
+}
+
+static void nativeSetFindIsEmpty(JNIEnv *env, jobject obj)
+{
+    GET_NATIVE_VIEW(env, obj)->setFindIsEmpty();
+}
+
+static void nativeShowCursorTimed(JNIEnv *env, jobject obj)
+{
+    GET_NATIVE_VIEW(env, obj)->showCursorTimed();
+}
+
 static void nativeSetHeightCanMeasure(JNIEnv *env, jobject obj, bool measure)
 {
     WebView* view = GET_NATIVE_VIEW(env, obj);
-    ALOG_ASSERT(view, "view not set in nativeSetHeightCanMeasure");
+    LOG_ASSERT(view, "view not set in nativeSetHeightCanMeasure");
     view->setHeightCanMeasure(measure);
 }
 
-static void nativeDestroy(JNIEnv *env, jobject obj, jint ptr)
+static jobject nativeGetCursorRingBounds(JNIEnv *env, jobject obj)
 {
-    WebView* view = reinterpret_cast<WebView*>(ptr);
-    ALOGD("nativeDestroy view: %p", view);
-    ALOG_ASSERT(view, "view not set in nativeDestroy");
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+    jclass rectClass = env->FindClass("android/graphics/Rect");
+    LOG_ASSERT(rectClass, "Could not find Rect class!");
+    jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
+    LOG_ASSERT(init, "Could not find constructor for Rect");
+    WebCore::IntRect webRect;
+    view->cursorRingBounds(&webRect);
+    jobject rect = env->NewObject(rectClass, init, webRect.x(),
+        webRect.y(), webRect.maxX(), webRect.maxY());
+    env->DeleteLocalRef(rectClass);
+    return rect;
+}
+
+static int nativeFindAll(JNIEnv *env, jobject obj, jstring findLower,
+        jstring findUpper, jboolean sameAsLastSearch)
+{
+    // If one or the other is null, do not search.
+    if (!(findLower && findUpper))
+        return 0;
+    // Obtain the characters for both the lower case string and the upper case
+    // string representing the same word.
+    const jchar* findLowerChars = env->GetStringChars(findLower, 0);
+    const jchar* findUpperChars = env->GetStringChars(findUpper, 0);
+    // If one or the other is null, do not search.
+    if (!(findLowerChars && findUpperChars)) {
+        if (findLowerChars)
+            env->ReleaseStringChars(findLower, findLowerChars);
+        if (findUpperChars)
+            env->ReleaseStringChars(findUpper, findUpperChars);
+        checkException(env);
+        return 0;
+    }
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(view, "view not set in nativeFindAll");
+    CachedRoot* root = view->getFrameCache(WebView::AllowNewer);
+    if (!root) {
+        env->ReleaseStringChars(findLower, findLowerChars);
+        env->ReleaseStringChars(findUpper, findUpperChars);
+        checkException(env);
+        return 0;
+    }
+    int length = env->GetStringLength(findLower);
+    // If the lengths of the strings do not match, then they are not the same
+    // word, so do not search.
+    if (!length || env->GetStringLength(findUpper) != length) {
+        env->ReleaseStringChars(findLower, findLowerChars);
+        env->ReleaseStringChars(findUpper, findUpperChars);
+        checkException(env);
+        return 0;
+    }
+    int width = root->documentWidth();
+    int height = root->documentHeight();
+    // Create a FindCanvas, which allows us to fake draw into it so we can
+    // figure out where our search string is rendered (and how many times).
+    FindCanvas canvas(width, height, (const UChar*) findLowerChars,
+            (const UChar*) findUpperChars, length << 1);
+    SkBitmap bitmap;
+    bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
+    canvas.setBitmapDevice(bitmap);
+    root->draw(canvas);
+    WTF::Vector<MatchInfo>* matches = canvas.detachMatches();
+    // With setMatches, the WebView takes ownership of matches
+    view->setMatches(matches, sameAsLastSearch);
+
+    env->ReleaseStringChars(findLower, findLowerChars);
+    env->ReleaseStringChars(findUpper, findUpperChars);
+    checkException(env);
+    return canvas.found();
+}
+
+static void nativeFindNext(JNIEnv *env, jobject obj, bool forward)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(view, "view not set in nativeFindNext");
+    view->findNext(forward);
+}
+
+static int nativeFindIndex(JNIEnv *env, jobject obj)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(view, "view not set in nativeFindIndex");
+    return view->currentMatchIndex();
+}
+
+static void nativeUpdateCachedTextfield(JNIEnv *env, jobject obj, jstring updatedText, jint generation)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(view, "view not set in nativeUpdateCachedTextfield");
+    CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+    if (!root)
+        return;
+    const CachedNode* cachedFocusNode = root->currentFocus();
+    if (!cachedFocusNode || !cachedFocusNode->isTextInput())
+        return;
+    WTF::String webcoreString = jstringToWtfString(env, updatedText);
+    (const_cast<CachedNode*>(cachedFocusNode))->setExport(webcoreString);
+    root->setTextGeneration(generation);
+    checkException(env);
+}
+
+static jint nativeGetBlockLeftEdge(JNIEnv *env, jobject obj, jint x, jint y,
+        jfloat scale)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+    if (!view)
+        return -1;
+    return view->getBlockLeftEdge(x, y, scale);
+}
+
+static void nativeDestroy(JNIEnv *env, jobject obj)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    LOGD("nativeDestroy view: %p", view);
+    LOG_ASSERT(view, "view not set in nativeDestroy");
     delete view;
 }
 
-static void nativeStopGL(JNIEnv *env, jobject obj, jint ptr)
+static void nativeStopGL(JNIEnv *env, jobject obj)
 {
-    if (ptr)
-        reinterpret_cast<WebView*>(ptr)->stopGL();
+    GET_NATIVE_VIEW(env, obj)->stopGL();
+}
+
+static bool nativeMoveCursorToNextTextInput(JNIEnv *env, jobject obj)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+    if (!root)
+        return false;
+    const CachedNode* current = root->currentCursor();
+    if (!current || !current->isTextInput())
+        current = root->currentFocus();
+    if (!current || !current->isTextInput())
+        return false;
+    const CachedFrame* frame;
+    const CachedNode* next = root->nextTextField(current, &frame);
+    if (!next)
+        return false;
+    const WebCore::IntRect& bounds = next->bounds(frame);
+    root->rootHistory()->setMouseBounds(bounds);
+    view->getWebViewCore()->updateCursorBounds(root, frame, next);
+    view->showCursorUntimed();
+    root->setCursor(const_cast<CachedFrame*>(frame),
+            const_cast<CachedNode*>(next));
+    view->sendMoveFocus(static_cast<WebCore::Frame*>(frame->framePointer()),
+            static_cast<WebCore::Node*>(next->nodePointer()));
+    if (!next->isInLayer())
+        view->scrollRectOnScreen(bounds);
+    view->getWebViewCore()->m_moveGeneration++;
+    return true;
+}
+
+static int nativeMoveGeneration(JNIEnv *env, jobject obj)
+{
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    if (!view)
+        return 0;
+    return view->moveGeneration();
+}
+
+static void nativeMoveSelection(JNIEnv *env, jobject obj, int x, int y)
+{
+    GET_NATIVE_VIEW(env, obj)->moveSelection(x, y);
+}
+
+static void nativeResetSelection(JNIEnv *env, jobject obj)
+{
+    return GET_NATIVE_VIEW(env, obj)->resetSelection();
+}
+
+static jobject nativeSelectableText(JNIEnv* env, jobject obj)
+{
+    IntPoint pos = GET_NATIVE_VIEW(env, obj)->selectableText();
+    jclass pointClass = env->FindClass("android/graphics/Point");
+    jmethodID init = env->GetMethodID(pointClass, "<init>", "(II)V");
+    jobject point = env->NewObject(pointClass, init, pos.x(), pos.y());
+    env->DeleteLocalRef(pointClass);
+    return point;
+}
+
+static void nativeSelectAll(JNIEnv* env, jobject obj)
+{
+    GET_NATIVE_VIEW(env, obj)->selectAll();
+}
+
+static void nativeSetExtendSelection(JNIEnv *env, jobject obj)
+{
+    GET_NATIVE_VIEW(env, obj)->setExtendSelection();
+}
+
+static jboolean nativeStartSelection(JNIEnv *env, jobject obj, int x, int y)
+{
+    return GET_NATIVE_VIEW(env, obj)->startSelection(x, y);
+}
+
+static jboolean nativeWordSelection(JNIEnv *env, jobject obj, int x, int y)
+{
+    return GET_NATIVE_VIEW(env, obj)->wordSelection(x, y);
+}
+
+static void nativeExtendSelection(JNIEnv *env, jobject obj, int x, int y)
+{
+    GET_NATIVE_VIEW(env, obj)->extendSelection(x, y);
 }
 
 static jobject nativeGetSelection(JNIEnv *env, jobject obj)
 {
     WebView* view = GET_NATIVE_VIEW(env, obj);
-    ALOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+    LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
     String selection = view->getSelection();
     return wtfStringToJstring(env, selection);
 }
 
-static void nativeDiscardAllTextures(JNIEnv *env, jobject obj)
+static jboolean nativeHitSelection(JNIEnv *env, jobject obj, int x, int y)
 {
-    //discard all textures for debugging/test purposes, but not gl backing memory
-    bool allTextures = true, deleteGLTextures = false;
-    TilesManager::instance()->discardTextures(allTextures, deleteGLTextures);
+    return GET_NATIVE_VIEW(env, obj)->hitSelection(x, y);
+}
+
+static jint nativeSelectionX(JNIEnv *env, jobject obj)
+{
+    return GET_NATIVE_VIEW(env, obj)->selectionX();
+}
+
+static jint nativeSelectionY(JNIEnv *env, jobject obj)
+{
+    return GET_NATIVE_VIEW(env, obj)->selectionY();
+}
+
+static void nativeSetSelectionPointer(JNIEnv *env, jobject obj, jint nativeView,
+                                      jboolean set, jfloat scale, jint x, jint y)
+{
+    ((WebView*)nativeView)->setSelectionPointer(set, scale, x, y);
+}
+
+static void nativeRegisterPageSwapCallback(JNIEnv *env, jobject obj)
+{
+    GET_NATIVE_VIEW(env, obj)->registerPageSwapCallback();
 }
 
 static void nativeTileProfilingStart(JNIEnv *env, jobject obj)
@@ -1071,14 +2581,15 @@
 }
 #endif
 
-// Return true to view invalidate WebView
 static bool nativeSetProperty(JNIEnv *env, jobject obj, jstring jkey, jstring jvalue)
 {
     WTF::String key = jstringToWtfString(env, jkey);
     WTF::String value = jstringToWtfString(env, jvalue);
     if (key == "inverted") {
-        bool shouldInvert = (value == "true");
-        TilesManager::instance()->setInvertedScreen(shouldInvert);
+        if (value == "true")
+            TilesManager::instance()->setInvertedScreen(true);
+        else
+            TilesManager::instance()->setInvertedScreen(false);
         return true;
     }
     else if (key == "inverted_contrast") {
@@ -1089,47 +2600,25 @@
     else if (key == "enable_cpu_upload_path") {
         TilesManager::instance()->transferQueue()->setTextureUploadType(
             value == "true" ? CpuUpload : GpuUpload);
+        return true;
     }
     else if (key == "use_minimal_memory") {
         TilesManager::instance()->setUseMinimalMemory(value == "true");
-    }
-    else if (key == "use_double_buffering") {
-        TilesManager::instance()->setUseDoubleBuffering(value == "true");
-    }
-    else if (key == "tree_updates") {
-        TilesManager::instance()->clearContentUpdates();
+        return true;
     }
     return false;
 }
 
-static jstring nativeGetProperty(JNIEnv *env, jobject obj, jstring jkey)
+static jstring nativeGetProperty(JNIEnv *env, jobject obj, jstring key)
 {
-    WTF::String key = jstringToWtfString(env, jkey);
-    if (key == "tree_updates") {
-        int updates = TilesManager::instance()->getContentUpdates();
-        WTF::String wtfUpdates = WTF::String::number(updates);
-        return wtfStringToJstring(env, wtfUpdates);
-    }
     return 0;
 }
 
 static void nativeOnTrimMemory(JNIEnv *env, jobject obj, jint level)
 {
     if (TilesManager::hardwareAccelerationEnabled()) {
-        // When we got TRIM_MEMORY_MODERATE or TRIM_MEMORY_COMPLETE, we should
-        // make sure the transfer queue is empty and then abandon the Surface
-        // Texture to avoid ANR b/c framework may destroy the EGL context.
-        // Refer to WindowManagerImpl.java for conditions we followed.
-        TilesManager* tilesManager = TilesManager::instance();
-        if ((level >= TRIM_MEMORY_MODERATE
-            && !tilesManager->highEndGfx())
-            || level >= TRIM_MEMORY_COMPLETE) {
-            ALOGD("OnTrimMemory with EGL Context %p", eglGetCurrentContext());
-            tilesManager->cleanupGLResources();
-        }
-
-        bool freeAllTextures = (level > TRIM_MEMORY_UI_HIDDEN), glTextures = true;
-        tilesManager->discardTextures(freeAllTextures, glTextures);
+        bool freeAllTextures = (level > TRIM_MEMORY_UI_HIDDEN);
+        TilesManager::instance()->deallocateTextures(freeAllTextures);
     }
 }
 
@@ -1137,7 +2626,7 @@
 {
 #ifdef ANDROID_DUMP_DISPLAY_TREE
     WebView* view = GET_NATIVE_VIEW(env, jwebview);
-    ALOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+    LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
 
     if (view && view->getWebViewCore()) {
         FILE* file = fopen(DISPLAY_TREE_LOG_FILE, "w");
@@ -1154,17 +2643,17 @@
             SkDumpCanvas canvas(&dumper);
             // this will playback the picture into the canvas, which will
             // spew its contents to the dumper
-            view->draw(&canvas, 0, WebView::DrawExtrasNone);
+            view->draw(&canvas, 0, 0, false);
             // we're done with the file now
             fwrite("\n", 1, 1, file);
             fclose(file);
         }
 #if USE(ACCELERATED_COMPOSITING)
-        const LayerAndroid* baseLayer = view->getBaseLayer();
-        if (baseLayer) {
+        const LayerAndroid* rootLayer = view->compositeRoot();
+        if (rootLayer) {
           FILE* file = fopen(LAYERS_TREE_LOG_FILE,"w");
           if (file) {
-              baseLayer->dumpLayers(file, 0);
+              rootLayer->dumpLayers(file, 0);
               fclose(file);
           }
         }
@@ -1173,13 +2662,13 @@
 #endif
 }
 
-static int nativeScrollableLayer(JNIEnv* env, jobject jwebview, jint nativeView,
-    jint x, jint y, jobject rect, jobject bounds)
+static int nativeScrollableLayer(JNIEnv* env, jobject jwebview, jint x, jint y,
+    jobject rect, jobject bounds)
 {
-    WebView* webview = reinterpret_cast<WebView*>(nativeView);
-    ALOG_ASSERT(webview, "webview not set in %s", __FUNCTION__);
+    WebView* view = GET_NATIVE_VIEW(env, jwebview);
+    LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
     SkIRect nativeRect, nativeBounds;
-    int id = webview->scrollableLayer(x, y, &nativeRect, &nativeBounds);
+    int id = view->scrollableLayer(x, y, &nativeRect, &nativeBounds);
     if (rect)
         GraphicsJNI::irect_to_jrect(nativeRect, env, rect);
     if (bounds)
@@ -1187,18 +2676,18 @@
     return id;
 }
 
-static bool nativeScrollLayer(JNIEnv* env, jobject obj,
-    jint nativeView, jint layerId, jint x, jint y)
+static bool nativeScrollLayer(JNIEnv* env, jobject obj, jint layerId, jint x,
+        jint y)
 {
 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
-    WebView* webview = reinterpret_cast<WebView*>(nativeView);
-    webview->scrollLayer(layerId, x, y);
+    WebView* view = GET_NATIVE_VIEW(env, obj);
+    view->scrollLayer(layerId, x, y);
 
     //TODO: the below only needed for the SW rendering path
-    LayerAndroid* baseLayer = webview->getBaseLayer();
-    if (!baseLayer)
+    LayerAndroid* root = view->compositeRoot();
+    if (!root)
         return false;
-    LayerAndroid* layer = baseLayer->findById(layerId);
+    LayerAndroid* layer = root->findById(layerId);
     if (!layer || !layer->contentIsScrollable())
         return false;
     return static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y);
@@ -1208,10 +2697,9 @@
 
 static void nativeSetIsScrolling(JNIEnv* env, jobject jwebview, jboolean isScrolling)
 {
-    // TODO: Pass in the native pointer instead
     WebView* view = GET_NATIVE_VIEW(env, jwebview);
-    if (view)
-        view->setIsScrolling(isScrolling);
+    LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+    view->setIsScrolling(isScrolling);
 }
 
 static void nativeUseHardwareAccelSkia(JNIEnv*, jobject, jboolean enabled)
@@ -1219,9 +2707,9 @@
     BaseRenderer::setCurrentRendererType(enabled ? BaseRenderer::Ganesh : BaseRenderer::Raster);
 }
 
-static int nativeGetBackgroundColor(JNIEnv* env, jobject obj, jint nativeView)
+static int nativeGetBackgroundColor(JNIEnv* env, jobject obj)
 {
-    WebView* view = reinterpret_cast<WebView*>(nativeView);
+    WebView* view = GET_NATIVE_VIEW(env, obj);
     BaseLayerAndroid* baseLayer = view->getBaseLayer();
     if (baseLayer) {
         WebCore::Color color = baseLayer->getBackgroundColor();
@@ -1235,93 +2723,179 @@
 static void nativeSetPauseDrawing(JNIEnv *env, jobject obj, jint nativeView,
                                       jboolean pause)
 {
-    reinterpret_cast<WebView*>(nativeView)->setDrawingPaused(pause);
-}
-
-static void nativeSetTextSelection(JNIEnv *env, jobject obj, jint nativeView,
-                                   jint selectionPtr)
-{
-    SelectText* selection = reinterpret_cast<SelectText*>(selectionPtr);
-    reinterpret_cast<WebView*>(nativeView)->setTextSelection(selection);
-}
-
-static jint nativeGetHandleLayerId(JNIEnv *env, jobject obj, jint nativeView,
-                                     jint handleIndex, jobject cursorPoint,
-                                     jobject textQuad)
-{
-    WebView* webview = reinterpret_cast<WebView*>(nativeView);
-    SkIPoint nativePoint;
-    FloatQuad nativeTextQuad;
-    int layerId = webview->getHandleLayerId((SelectText::HandleId) handleIndex,
-            nativePoint, nativeTextQuad);
-    if (cursorPoint)
-        GraphicsJNI::ipoint_to_jpoint(nativePoint, env, cursorPoint);
-    if (textQuad)
-        webview->floatQuadToQuadF(env, nativeTextQuad, textQuad);
-    return layerId;
-}
-
-static void nativeMapLayerRect(JNIEnv *env, jobject obj, jint nativeView,
-        jint layerId, jobject rect)
-{
-    WebView* webview = reinterpret_cast<WebView*>(nativeView);
-    SkIRect nativeRect;
-    GraphicsJNI::jrect_to_irect(env, rect, &nativeRect);
-    webview->mapLayerRect(layerId, nativeRect);
-    GraphicsJNI::irect_to_jrect(nativeRect, env, rect);
-}
-
-static jint nativeSetHwAccelerated(JNIEnv *env, jobject obj, jint nativeView,
-        jboolean hwAccelerated)
-{
-    WebView* webview = reinterpret_cast<WebView*>(nativeView);
-    return webview->setHwAccelerated(hwAccelerated);
-}
-
-static void nativeFindMaxVisibleRect(JNIEnv *env, jobject obj, jint nativeView,
-        jint movingLayerId, jobject visibleContentRect)
-{
-    WebView* webview = reinterpret_cast<WebView*>(nativeView);
-    SkIRect nativeRect;
-    GraphicsJNI::jrect_to_irect(env, visibleContentRect, &nativeRect);
-    webview->findMaxVisibleRect(movingLayerId, nativeRect);
-    GraphicsJNI::irect_to_jrect(nativeRect, env, visibleContentRect);
+    ((WebView*)nativeView)->m_isDrawingPaused = pause;
 }
 
 /*
  * JNI registration
  */
 static JNINativeMethod gJavaWebViewMethods[] = {
+    { "nativeCacheHitFramePointer", "()I",
+        (void*) nativeCacheHitFramePointer },
+    { "nativeCacheHitIsPlugin", "()Z",
+        (void*) nativeCacheHitIsPlugin },
+    { "nativeCacheHitNodeBounds", "()Landroid/graphics/Rect;",
+        (void*) nativeCacheHitNodeBounds },
+    { "nativeCacheHitNodePointer", "()I",
+        (void*) nativeCacheHitNodePointer },
+    { "nativeClearCursor", "()V",
+        (void*) nativeClearCursor },
     { "nativeCreate", "(ILjava/lang/String;Z)V",
         (void*) nativeCreate },
-    { "nativeDestroy", "(I)V",
+    { "nativeCursorFramePointer", "()I",
+        (void*) nativeCursorFramePointer },
+    { "nativePageShouldHandleShiftAndArrows", "()Z",
+        (void*) nativePageShouldHandleShiftAndArrows },
+    { "nativeCursorNodeBounds", "()Landroid/graphics/Rect;",
+        (void*) nativeCursorNodeBounds },
+    { "nativeCursorNodePointer", "()I",
+        (void*) nativeCursorNodePointer },
+    { "nativeCursorIntersects", "(Landroid/graphics/Rect;)Z",
+        (void*) nativeCursorIntersects },
+    { "nativeCursorIsAnchor", "()Z",
+        (void*) nativeCursorIsAnchor },
+    { "nativeCursorIsTextInput", "()Z",
+        (void*) nativeCursorIsTextInput },
+    { "nativeCursorPosition", "()Landroid/graphics/Point;",
+        (void*) nativeCursorPosition },
+    { "nativeCursorText", "()Ljava/lang/String;",
+        (void*) nativeCursorText },
+    { "nativeCursorWantsKeyEvents", "()Z",
+        (void*)nativeCursorWantsKeyEvents },
+    { "nativeDebugDump", "()V",
+        (void*) nativeDebugDump },
+    { "nativeDestroy", "()V",
         (void*) nativeDestroy },
-    { "nativeDraw", "(Landroid/graphics/Canvas;Landroid/graphics/RectF;II)V",
+    { "nativeDraw", "(Landroid/graphics/Canvas;Landroid/graphics/RectF;IIZ)I",
         (void*) nativeDraw },
-    { "nativeCreateDrawGLFunction", "(ILandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;FI)I",
-        (void*) nativeCreateDrawGLFunction },
-    { "nativeGetDrawGLFunction", "(I)I",
+    { "nativeGetDrawGLFunction", "(ILandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;FI)I",
         (void*) nativeGetDrawGLFunction },
-    { "nativeUpdateDrawGLFunction", "(ILandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;F)V",
+    { "nativeUpdateDrawGLFunction", "(Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;)V",
         (void*) nativeUpdateDrawGLFunction },
     { "nativeDumpDisplayTree", "(Ljava/lang/String;)V",
         (void*) nativeDumpDisplayTree },
     { "nativeEvaluateLayersAnimations", "(I)Z",
         (void*) nativeEvaluateLayersAnimations },
+    { "nativeExtendSelection", "(II)V",
+        (void*) nativeExtendSelection },
+    { "nativeFindAll", "(Ljava/lang/String;Ljava/lang/String;Z)I",
+        (void*) nativeFindAll },
+    { "nativeFindNext", "(Z)V",
+        (void*) nativeFindNext },
+    { "nativeFindIndex", "()I",
+        (void*) nativeFindIndex},
+    { "nativeFocusCandidateFramePointer", "()I",
+        (void*) nativeFocusCandidateFramePointer },
+    { "nativeFocusCandidateHasNextTextfield", "()Z",
+        (void*) focusCandidateHasNextTextfield },
+    { "nativeFocusCandidateIsPassword", "()Z",
+        (void*) nativeFocusCandidateIsPassword },
+    { "nativeFocusCandidateIsRtlText", "()Z",
+        (void*) nativeFocusCandidateIsRtlText },
+    { "nativeFocusCandidateIsTextInput", "()Z",
+        (void*) nativeFocusCandidateIsTextInput },
+    { "nativeFocusCandidateLineHeight", "()I",
+        (void*) nativeFocusCandidateLineHeight },
+    { "nativeFocusCandidateMaxLength", "()I",
+        (void*) nativeFocusCandidateMaxLength },
+    { "nativeFocusCandidateIsAutoComplete", "()Z",
+        (void*) nativeFocusCandidateIsAutoComplete },
+    { "nativeFocusCandidateIsSpellcheck", "()Z",
+        (void*) nativeFocusCandidateIsSpellcheck },
+    { "nativeFocusCandidateName", "()Ljava/lang/String;",
+        (void*) nativeFocusCandidateName },
+    { "nativeFocusCandidateNodeBounds", "()Landroid/graphics/Rect;",
+        (void*) nativeFocusCandidateNodeBounds },
+    { "nativeFocusCandidatePaddingRect", "()Landroid/graphics/Rect;",
+        (void*) nativeFocusCandidatePaddingRect },
+    { "nativeFocusCandidatePointer", "()I",
+        (void*) nativeFocusCandidatePointer },
+    { "nativeFocusCandidateText", "()Ljava/lang/String;",
+        (void*) nativeFocusCandidateText },
+    { "nativeFocusCandidateTextSize", "()F",
+        (void*) nativeFocusCandidateTextSize },
+    { "nativeFocusCandidateType", "()I",
+        (void*) nativeFocusCandidateType },
+    { "nativeFocusCandidateLayerId", "()I",
+        (void*) nativeFocusCandidateLayerId },
+    { "nativeFocusIsPlugin", "()Z",
+        (void*) nativeFocusIsPlugin },
+    { "nativeFocusNodeBounds", "()Landroid/graphics/Rect;",
+        (void*) nativeFocusNodeBounds },
+    { "nativeFocusNodePointer", "()I",
+        (void*) nativeFocusNodePointer },
+    { "nativeGetCursorRingBounds", "()Landroid/graphics/Rect;",
+        (void*) nativeGetCursorRingBounds },
     { "nativeGetSelection", "()Ljava/lang/String;",
         (void*) nativeGetSelection },
+    { "nativeHasCursorNode", "()Z",
+        (void*) nativeHasCursorNode },
+    { "nativeHasFocusNode", "()Z",
+        (void*) nativeHasFocusNode },
+    { "nativeHideCursor", "()V",
+        (void*) nativeHideCursor },
+    { "nativeHitSelection", "(II)Z",
+        (void*) nativeHitSelection },
+    { "nativeImageURI", "(II)Ljava/lang/String;",
+        (void*) nativeImageURI },
+    { "nativeInstrumentReport", "()V",
+        (void*) nativeInstrumentReport },
+    { "nativeLayerBounds", "(I)Landroid/graphics/Rect;",
+        (void*) nativeLayerBounds },
+    { "nativeMotionUp", "(III)Z",
+        (void*) nativeMotionUp },
+    { "nativeMoveCursor", "(IIZ)Z",
+        (void*) nativeMoveCursor },
+    { "nativeMoveCursorToNextTextInput", "()Z",
+        (void*) nativeMoveCursorToNextTextInput },
+    { "nativeMoveGeneration", "()I",
+        (void*) nativeMoveGeneration },
+    { "nativeMoveSelection", "(II)V",
+        (void*) nativeMoveSelection },
+    { "nativePointInNavCache", "(III)Z",
+        (void*) nativePointInNavCache },
+    { "nativeResetSelection", "()V",
+        (void*) nativeResetSelection },
+    { "nativeSelectableText", "()Landroid/graphics/Point;",
+        (void*) nativeSelectableText },
+    { "nativeSelectAll", "()V",
+        (void*) nativeSelectAll },
+    { "nativeSelectBestAt", "(Landroid/graphics/Rect;)V",
+        (void*) nativeSelectBestAt },
+    { "nativeSelectAt", "(II)V",
+        (void*) nativeSelectAt },
+    { "nativeSelectionX", "()I",
+        (void*) nativeSelectionX },
+    { "nativeSelectionY", "()I",
+        (void*) nativeSelectionY },
+    { "nativeSetExtendSelection", "()V",
+        (void*) nativeSetExtendSelection },
+    { "nativeSetFindIsEmpty", "()V",
+        (void*) nativeSetFindIsEmpty },
+    { "nativeSetFindIsUp", "(Z)V",
+        (void*) nativeSetFindIsUp },
     { "nativeSetHeightCanMeasure", "(Z)V",
         (void*) nativeSetHeightCanMeasure },
-    { "nativeSetBaseLayer", "(IIZZI)Z",
+    { "nativeSetBaseLayer", "(ILandroid/graphics/Region;ZZZ)V",
         (void*) nativeSetBaseLayer },
-    { "nativeGetBaseLayer", "(I)I",
+    { "nativeGetTextSelectionRegion", "(ILandroid/graphics/Region;)V",
+        (void*) nativeGetTextSelectionRegion },
+    { "nativeGetSelectionHandles", "(I[I)V",
+        (void*) nativeGetSelectionHandles },
+    { "nativeGetBaseLayer", "()I",
         (void*) nativeGetBaseLayer },
+    { "nativeReplaceBaseContent", "(I)V",
+        (void*) nativeReplaceBaseContent },
     { "nativeCopyBaseContentToPicture", "(Landroid/graphics/Picture;)V",
         (void*) nativeCopyBaseContentToPicture },
     { "nativeHasContent", "()Z",
         (void*) nativeHasContent },
-    { "nativeDiscardAllTextures", "()V",
-        (void*) nativeDiscardAllTextures },
+    { "nativeSetSelectionPointer", "(IZFII)V",
+        (void*) nativeSetSelectionPointer },
+    { "nativeShowCursorTimed", "()V",
+        (void*) nativeShowCursorTimed },
+    { "nativeRegisterPageSwapCallback", "()V",
+        (void*) nativeRegisterPageSwapCallback },
     { "nativeTileProfilingStart", "()V",
         (void*) nativeTileProfilingStart },
     { "nativeTileProfilingStop", "()F",
@@ -1336,17 +2910,29 @@
         (void*) nativeTileProfilingGetInt },
     { "nativeTileProfilingGetFloat", "(IILjava/lang/String;)F",
         (void*) nativeTileProfilingGetFloat },
-    { "nativeStopGL", "(I)V",
+    { "nativeStartSelection", "(II)Z",
+        (void*) nativeStartSelection },
+    { "nativeStopGL", "()V",
         (void*) nativeStopGL },
-    { "nativeScrollableLayer", "(IIILandroid/graphics/Rect;Landroid/graphics/Rect;)I",
+    { "nativeSubtractLayers", "(Landroid/graphics/Rect;)Landroid/graphics/Rect;",
+        (void*) nativeSubtractLayers },
+    { "nativeTextGeneration", "()I",
+        (void*) nativeTextGeneration },
+    { "nativeUpdateCachedTextfield", "(Ljava/lang/String;I)V",
+        (void*) nativeUpdateCachedTextfield },
+    {  "nativeWordSelection", "(II)Z",
+        (void*) nativeWordSelection },
+    { "nativeGetBlockLeftEdge", "(IIF)I",
+        (void*) nativeGetBlockLeftEdge },
+    { "nativeScrollableLayer", "(IILandroid/graphics/Rect;Landroid/graphics/Rect;)I",
         (void*) nativeScrollableLayer },
-    { "nativeScrollLayer", "(IIII)Z",
+    { "nativeScrollLayer", "(III)Z",
         (void*) nativeScrollLayer },
     { "nativeSetIsScrolling", "(Z)V",
         (void*) nativeSetIsScrolling },
     { "nativeUseHardwareAccelSkia", "(Z)V",
         (void*) nativeUseHardwareAccelSkia },
-    { "nativeGetBackgroundColor", "(I)I",
+    { "nativeGetBackgroundColor", "()I",
         (void*) nativeGetBackgroundColor },
     { "nativeSetProperty", "(Ljava/lang/String;Ljava/lang/String;)Z",
         (void*) nativeSetProperty },
@@ -1356,27 +2942,17 @@
         (void*) nativeOnTrimMemory },
     { "nativeSetPauseDrawing", "(IZ)V",
         (void*) nativeSetPauseDrawing },
-    { "nativeSetTextSelection", "(II)V",
-        (void*) nativeSetTextSelection },
-    { "nativeGetHandleLayerId", "(IILandroid/graphics/Point;Landroid/webkit/QuadF;)I",
-        (void*) nativeGetHandleLayerId },
-    { "nativeMapLayerRect", "(IILandroid/graphics/Rect;)V",
-        (void*) nativeMapLayerRect },
-    { "nativeSetHwAccelerated", "(IZ)I",
-        (void*) nativeSetHwAccelerated },
-    { "nativeFindMaxVisibleRect", "(IILandroid/graphics/Rect;)V",
-        (void*) nativeFindMaxVisibleRect },
 };
 
 int registerWebView(JNIEnv* env)
 {
-    jclass clazz = env->FindClass("android/webkit/WebViewClassic");
-    ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebViewClassic");
+    jclass clazz = env->FindClass("android/webkit/WebView");
+    LOG_ASSERT(clazz, "Unable to find class android/webkit/WebView");
     gWebViewField = env->GetFieldID(clazz, "mNativeClass", "I");
-    ALOG_ASSERT(gWebViewField, "Unable to find android/webkit/WebViewClassic.mNativeClass");
+    LOG_ASSERT(gWebViewField, "Unable to find android/webkit/WebView.mNativeClass");
     env->DeleteLocalRef(clazz);
 
-    return jniRegisterNativeMethods(env, "android/webkit/WebViewClassic", gJavaWebViewMethods, NELEM(gJavaWebViewMethods));
+    return jniRegisterNativeMethods(env, "android/webkit/WebView", gJavaWebViewMethods, NELEM(gJavaWebViewMethods));
 }
 
 } // namespace android
diff --git a/Source/WebKit/android/plugins/ANPSoundInterface.cpp b/Source/WebKit/android/plugins/ANPSoundInterface.cpp
index 9d19443..c238872 100644
--- a/Source/WebKit/android/plugins/ANPSoundInterface.cpp
+++ b/Source/WebKit/android/plugins/ANPSoundInterface.cpp
@@ -38,7 +38,7 @@
     android::AudioTrack* mTrack;
 };
 
-static ANPSampleFormat toANPFormat(audio_format_t fm) {
+static ANPSampleFormat toANPFormat(int fm) {
     switch (fm) {
         case AUDIO_FORMAT_PCM_16_BIT:
             return kPCM16Bit_ANPSampleFormat;
@@ -49,7 +49,7 @@
     }
 }
 
-static audio_format_t fromANPFormat(ANPSampleFormat fm) {
+static int fromANPFormat(ANPSampleFormat fm) {
     switch (fm) {
         case kPCM16Bit_ANPSampleFormat:
             return AUDIO_FORMAT_PCM_16_BIT;
@@ -71,7 +71,7 @@
             src = reinterpret_cast<android::AudioTrack::Buffer*>(info);
             dst.bufferData      = src->raw;
             dst.channelCount    = src->channelCount;
-            dst.format          = toANPFormat((audio_format_t) src->format);
+            dst.format          = toANPFormat(src->format);
             dst.size            = src->size;
             track->mProc(kMoreData_ANPAudioEvent, track->mUser, &dst);
             // return the updated size field
@@ -102,7 +102,7 @@
                                             fromANPFormat(format),
                                             (channelCount > 1) ? AUDIO_CHANNEL_OUT_STEREO : AUDIO_CHANNEL_OUT_MONO,
                                             0,  // frameCount
-                                            (audio_output_flags_t) 0, // AUDIO_OUTPUT_FLAG_NONE,
+                                            0,  // flags
                                             callbackProc,
                                             track,
                                             0);
diff --git a/Source/WebKit/android/plugins/ANPSurfaceInterface.cpp b/Source/WebKit/android/plugins/ANPSurfaceInterface.cpp
index 92dbbcd..4b99b31 100644
--- a/Source/WebKit/android/plugins/ANPSurfaceInterface.cpp
+++ b/Source/WebKit/android/plugins/ANPSurfaceInterface.cpp
@@ -32,7 +32,7 @@
 #include "SkANP.h"
 #include "android_graphics.h"
 #include <JNIUtility.h>
-#include <gui/Surface.h>
+#include <surfaceflinger/Surface.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
 #include <utils/RefBase.h>
@@ -47,7 +47,7 @@
     jfieldID    surfacePointer;
 } gSurfaceJavaGlue;
 
-static inline sp<android::Surface> getSurface(JNIEnv* env, jobject view) {
+static inline sp<Surface> getSurface(JNIEnv* env, jobject view) {
     if (!env || !view) {
         return NULL;
     }
@@ -80,7 +80,7 @@
     env->DeleteLocalRef(holder);
     env->DeleteLocalRef(surface);
 
-    return sp<android::Surface>((android::Surface*) surfacePointer);
+    return sp<Surface>((Surface*) surfacePointer);
 }
 
 static inline ANPBitmapFormat convertPixelFormat(PixelFormat format) {
@@ -96,9 +96,9 @@
         return false;
     }
 
-    sp<android::Surface> surface = getSurface(env, surfaceView);
+    sp<Surface> surface = getSurface(env, surfaceView);
 
-    if (!bitmap || !android::Surface::isValid(surface)) {
+    if (!bitmap || !Surface::isValid(surface)) {
             return false;
     }
 
@@ -112,7 +112,7 @@
         dirtyRegion.set(Rect(0x3FFF, 0x3FFF));
     }
 
-    android::Surface::SurfaceInfo info;
+    Surface::SurfaceInfo info;
     status_t err = surface->lock(&info, &dirtyRegion);
     if (err < 0) {
         return false;
@@ -150,9 +150,9 @@
         return;
     }
 
-    sp<android::Surface> surface = getSurface(env, surfaceView);
+    sp<Surface> surface = getSurface(env, surfaceView);
 
-    if (!android::Surface::isValid(surface)) {
+    if (!Surface::isValid(surface)) {
         return;
     }
 
diff --git a/Source/WebKit/android/plugins/PluginWidgetAndroid.cpp b/Source/WebKit/android/plugins/PluginWidgetAndroid.cpp
index 09bb24e..fc98837 100644
--- a/Source/WebKit/android/plugins/PluginWidgetAndroid.cpp
+++ b/Source/WebKit/android/plugins/PluginWidgetAndroid.cpp
@@ -160,8 +160,7 @@
 
     if (model == kOpenGL_ANPDrawingModel && m_layer == 0) {
         jobject webview = m_core->getWebViewJavaObject();
-        AutoJObject webViewCore = m_core->getJavaObject();
-        m_layer = new WebCore::MediaLayer(webview, webViewCore.get());
+        m_layer = new WebCore::MediaLayer(webview);
     }
     else if (model != kOpenGL_ANPDrawingModel && m_layer != 0) {
         m_layer->unref();
@@ -597,9 +596,9 @@
     android::WebViewCore* core = android::WebViewCore::getWebViewCore(scrollView);
 #if DEBUG_VISIBLE_RECTS
     PLUGIN_LOG("%s call scrollTo (%d,%d) to center (%d,%d)", __FUNCTION__,
-            scrollDocX, scrollDocY, rectCenterX, rectCenterY);
+            scrollDocX, scrollDocX, rectCenterX, rectCenterY);
 #endif
-    core->scrollTo(scrollDocX, scrollDocY, true);
+    core->scrollTo(scrollDocX, scrollDocX, true);
 }
 
 void PluginWidgetAndroid::requestFullScreen() {
diff --git a/Source/WebKit/android/smoke/MessageThread.cpp b/Source/WebKit/android/smoke/MessageThread.cpp
index 97ab18c..48f2222 100644
--- a/Source/WebKit/android/smoke/MessageThread.cpp
+++ b/Source/WebKit/android/smoke/MessageThread.cpp
@@ -79,7 +79,7 @@
     AutoMutex lock(m_mutex);
 
     double when = message->m_when;
-    ALOG_ASSERT(when > 0, "Message time may not be 0");
+    LOG_ASSERT(when > 0, "Message time may not be 0");
 
     list<Message*>::iterator it;
     for (it = m_messages.begin(); it != m_messages.end(); ++it) {
diff --git a/Source/WebKit/android/wds/Command.cpp b/Source/WebKit/android/wds/Command.cpp
index 1a365e5..bd8536f 100644
--- a/Source/WebKit/android/wds/Command.cpp
+++ b/Source/WebKit/android/wds/Command.cpp
@@ -95,7 +95,7 @@
     virtual ~InternalCommand() { delete m_connection; }
 
     void doCommand() const {
-        ALOGD("Executing command '%s' (%s)", m_name, m_description);
+        LOGD("Executing command '%s' (%s)", m_name, m_description);
         if (!m_dispatch(m_frame, m_connection))
             // XXX: Have useful failure messages
             m_connection->write("EPIC FAIL!\n", 11);
diff --git a/Source/WebKit/android/wds/Connection.cpp b/Source/WebKit/android/wds/Connection.cpp
index 52193e5..d7e55ac 100644
--- a/Source/WebKit/android/wds/Connection.cpp
+++ b/Source/WebKit/android/wds/Connection.cpp
@@ -35,7 +35,7 @@
 #if ENABLE(WDS)
 
 #define MAX_CONNECTION_QUEUE 5
-#define log_errno(x) ALOGE("%s: %d", x, strerror(errno))
+#define log_errno(x) LOGE("%s: %d", x, strerror(errno))
 
 namespace android {
 
diff --git a/Source/WebKit/android/wds/DebugServer.cpp b/Source/WebKit/android/wds/DebugServer.cpp
index 2fde6bd..f33a65b 100644
--- a/Source/WebKit/android/wds/DebugServer.cpp
+++ b/Source/WebKit/android/wds/DebugServer.cpp
@@ -42,7 +42,7 @@
 #if ENABLE(WDS)
 
 #define DEFAULT_PORT 9999
-#define log_errno(x) ALOGE("%s: %d", x, strerror(errno))
+#define log_errno(x) LOGE("%s: %d", x, strerror(errno))
 
 namespace android {
 
@@ -70,7 +70,7 @@
     char buf[PROPERTY_VALUE_MAX];
     int ret = property_get("webcore.wds.enable", buf, NULL);
     if (ret != -1 && strcmp(buf, "1") == 0) {
-        ALOGD("WDS Enabled");
+        LOGD("WDS Enabled");
         m_threadId = createThread(mainThread, this, "WDS");
     }
     // Initialize the available commands.
@@ -78,26 +78,26 @@
 }
 
 void DebugServer::start() {
-    ALOGD("DebugServer thread started");
+    LOGD("DebugServer thread started");
 
     ConnectionServer cs;
     if (!cs.connect(DEFAULT_PORT)) {
-        ALOGE("Failed to start the server socket connection");
+        LOGE("Failed to start the server socket connection");
         return;
     }
 
     while (true ) {
-        ALOGD("Waiting for incoming connections...");
+        LOGD("Waiting for incoming connections...");
         Connection* conn = cs.accept();
         if (!conn) {
             log_errno("Failed to accept new connections");
             return;
         }
-        ALOGD("...Connection established");
+        LOGD("...Connection established");
 
         Command* c = Command::Find(conn);
         if (!c) {
-            ALOGE("Could not find matching command");
+            LOGE("Could not find matching command");
             delete conn;
         } else {
             // Dispatch the command, it will handle cleaning up the connection
@@ -106,7 +106,7 @@
         }
     }
 
-    ALOGD("DebugServer thread finished");
+    LOGD("DebugServer thread finished");
 }
 
 } // end namespace WDS
diff --git a/Source/WebKit/android/wds/client/AdbConnection.cpp b/Source/WebKit/android/wds/client/AdbConnection.cpp
index 7d02ecc..465f9c3 100644
--- a/Source/WebKit/android/wds/client/AdbConnection.cpp
+++ b/Source/WebKit/android/wds/client/AdbConnection.cpp
@@ -78,7 +78,7 @@
 
 bool AdbConnection::sendRequest(const char* fmt, ...) const {
     if (m_fd == -1) {
-        ALOGE("Connection is closed");
+        LOGE("Connection is closed");
         return false;
     }
 
@@ -89,7 +89,7 @@
     int res = vsnprintf(buf, MAX_COMMAND_LENGTH, fmt, args);
     va_end(args);
 
-    ALOGV("Sending command: %04X%.*s", res, res, buf);
+    LOGV("Sending command: %04X%.*s", res, res, buf);
 
     // Construct the payload length
     char payloadLen[PAYLOAD_LENGTH + 1];
@@ -115,7 +115,7 @@
     // Grab the payload length
     char lenStr[PAYLOAD_LENGTH + 1];
     int payloadLen = recv(fd, lenStr, sizeof(lenStr) - 1, 0);
-    ALOG_ASSERT(payloadLen == PAYLOAD_LENGTH, "Incorrect payload size");
+    LOG_ASSERT(payloadLen == PAYLOAD_LENGTH, "Incorrect payload size");
     lenStr[PAYLOAD_LENGTH] = 0;
 
     // Parse the hex payload
@@ -130,13 +130,13 @@
         log_errno("Failure reading failure message from adb");
         return;
     } else if (res != payloadLen) {
-        ALOGE("Incorrect payload length %d - expected %d", res, payloadLen);
+        LOGE("Incorrect payload length %d - expected %d", res, payloadLen);
         return;
     }
     msg[res] = 0;
 
     // Tell somebody about it
-    ALOGE("Received failure from adb: %s", msg);
+    LOGE("Received failure from adb: %s", msg);
 
     // Cleanup
     delete[] msg;
@@ -145,7 +145,7 @@
 #define ADB_RESPONSE_LENGTH 4
 
 bool AdbConnection::checkOkayResponse() const {
-    ALOG_ASSERT(m_fd != -1, "Connection has been closed!");
+    LOG_ASSERT(m_fd != -1, "Connection has been closed!");
 
     char buf[ADB_RESPONSE_LENGTH];
     int res = recv(m_fd, buf, sizeof(buf), 0);
@@ -156,14 +156,14 @@
 
     // Check for a response other than OKAY/FAIL
     if ((res == ADB_RESPONSE_LENGTH) && (strncmp(buf, "OKAY", res) == 0)) {
-        ALOGV("Command OKAY");
+        LOGV("Command OKAY");
         return true;
     } else if (strncmp(buf, "FAIL", ADB_RESPONSE_LENGTH) == 0) {
         // Something happened, print out the reason for failure
         printFailureMessage(m_fd);
         return false;
     }
-    ALOGE("Incorrect response from adb - '%.*s'", res, buf);
+    LOGE("Incorrect response from adb - '%.*s'", res, buf);
     return false;
 }
 
@@ -178,13 +178,13 @@
     clearDevices();
 
     if (m_fd == -1) {
-        ALOGE("Connection is closed");
+        LOGE("Connection is closed");
         return m_devices;
     }
 
     // Try to send the device list request
     if (!sendRequest("host:devices")) {
-        ALOGE("Failed to get device list from adb");
+        LOGE("Failed to get device list from adb");
         return m_devices;
     }
 
@@ -210,7 +210,7 @@
         log_errno("Failure reading the device list");
         return m_devices;
     } else if (res != payloadLen) {
-        ALOGE("Incorrect payload length %d - expected %d", res, payloadLen);
+        LOGE("Incorrect payload length %d - expected %d", res, payloadLen);
         return m_devices;
     }
     msg[res] = 0;
@@ -224,7 +224,7 @@
         static const char emulator[] = "emulator-";
         if (strncmp(serial, emulator, sizeof(emulator) - 1) == 0)
             t = Device::EMULATOR;
-        ALOGV("Adding device %s (%s)", serial, state);
+        LOGV("Adding device %s (%s)", serial, state);
         m_devices.add(new Device(serial, t, this));
 
         // Reset for the next line
diff --git a/Source/WebKit/android/wds/client/ClientUtils.h b/Source/WebKit/android/wds/client/ClientUtils.h
index 7c4b9ce..7d0db30 100644
--- a/Source/WebKit/android/wds/client/ClientUtils.h
+++ b/Source/WebKit/android/wds/client/ClientUtils.h
@@ -37,7 +37,7 @@
 #endif
 
 // Callers need to include Log.h and errno.h to use this macro
-#define log_errno(str) ALOGE("%s: %s", str, strerror(errno))
+#define log_errno(str) LOGE("%s: %s", str, strerror(errno))
 
 // Fill in the sockaddr_in structure for binding to the localhost on the given
 // port
diff --git a/Source/WebKit/android/wds/client/main.cpp b/Source/WebKit/android/wds/client/main.cpp
index 276affe..1c7d856 100644
--- a/Source/WebKit/android/wds/client/main.cpp
+++ b/Source/WebKit/android/wds/client/main.cpp
@@ -74,7 +74,7 @@
     Device::DeviceType type = Device::NONE;
 
     if (argc <= 1) {
-        ALOGE("wdsclient takes at least 1 argument");
+        LOGE("wdsclient takes at least 1 argument");
         return 1;
     } else {
         // Parse the options, look for -e or -d to choose a device.
@@ -94,7 +94,7 @@
             }
         }
         if (optind == argc) {
-            ALOGE("No command specified");
+            LOGE("No command specified");
             return 1;
         }
     }
@@ -109,10 +109,10 @@
 
     // No device specified and more than one connected, bail
     if (type == Device::NONE && devices.size() > 1) {
-        ALOGE("More than one device/emulator, please specify with -e or -d");
+        LOGE("More than one device/emulator, please specify with -e or -d");
         return 1;
     } else if (devices.size() == 0) {
-        ALOGE("No devices connected");
+        LOGE("No devices connected");
         return 1;
     }
 
@@ -131,23 +131,23 @@
     }
 
     if (!device) {
-        ALOGE("No device found!");
+        LOGE("No device found!");
         return 1;
     }
 
     // Forward tcp:9999
     if (!device->sendRequest("forward:tcp:" PORT_STR ";tcp:" PORT_STR)) {
-        ALOGE("Failed to send forwarding request");
+        LOGE("Failed to send forwarding request");
         return 1;
     }
 
-    ALOGV("Connecting to localhost port " PORT_STR);
+    LOGV("Connecting to localhost port " PORT_STR);
 
     const char* command = argv[optind];
     int commandLen = strlen(command);
 #define WDS_COMMAND_LENGTH 4
     if (commandLen != WDS_COMMAND_LENGTH) {
-        ALOGE("Commands must be 4 characters '%s'", command);
+        LOGE("Commands must be 4 characters '%s'", command);
         return 1;
     }
 
diff --git a/Source/WebKit/chromium/public/WebRange.h b/Source/WebKit/chromium/public/WebRange.h
index 3da3d95..89fc8f6 100644
--- a/Source/WebKit/chromium/public/WebRange.h
+++ b/Source/WebKit/chromium/public/WebRange.h
@@ -37,10 +37,10 @@
 namespace WebCore { class Range; }
 namespace WTF { template <typename T> class PassRefPtr; }
 #endif
-namespace WebCore { class Node; }
 
 namespace WebKit {
 
+class WebNode;
 class WebRangePrivate;
 class WebString;
 
@@ -64,8 +64,8 @@
 
     WEBKIT_API int startOffset() const;
     WEBKIT_API int endOffset() const;
-    WEBKIT_API WebCore::Node* startContainer(int& exceptionCode) const;
-    WEBKIT_API WebCore::Node* endContainer(int& exceptionCode) const;
+    WEBKIT_API WebNode startContainer(int& exceptionCode) const;
+    WEBKIT_API WebNode endContainer(int& exceptionCode) const;
 
     WEBKIT_API WebString toHTMLText() const;
     WEBKIT_API WebString toPlainText() const;
diff --git a/Source/WebKit/chromium/public/android/WebDOMTextContentWalker.h b/Source/WebKit/chromium/public/android/WebDOMTextContentWalker.h
deleted file mode 100644
index 26ba589..0000000
--- a/Source/WebKit/chromium/public/android/WebDOMTextContentWalker.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef WebDOMTextContentWalker_h
-#define WebDOMTextContentWalker_h
-
-#include "../WebPrivateOwnPtr.h"
-#include "../WebRange.h"
-#include "../WebString.h"
-
-namespace WebCore {
-class DOMTextContentWalker;
-class Node;
-}
-
-namespace WebKit {
-
-class WebHitTestInfo;
-
-class WebDOMTextContentWalker {
-public:
-    WebDOMTextContentWalker();
-    ~WebDOMTextContentWalker();
-
-    // Creates a new text content walker centered in the position described by the hit test.
-    // The maximum length of the contents retrieved by the walker is defined by maxLength.
-    WEBKIT_API WebDOMTextContentWalker(const WebHitTestInfo&, size_t maxLength);
-
-    // Creates a new text content walker centered in the selected offset of the given text node.
-    // The maximum length of the contents retrieved by the walker is defined by maxLength.
-    WEBKIT_API WebDOMTextContentWalker(WebCore::Node* textNode, size_t offset, size_t maxLength);
-
-    // Text content retrieved by the walker.
-    WEBKIT_API WebString content() const;
-
-    // Position of the initial text node offset in the content string.
-    WEBKIT_API size_t hitOffsetInContent() const;
-
-    // Convert start/end positions in the content text string into a WebKit text range.
-    WEBKIT_API WebRange contentOffsetsToRange(size_t startInContent, size_t endInContent);
-
-protected:
-    WebPrivateOwnPtr<WebCore::DOMTextContentWalker> m_private;
-};
-
-} // namespace WebKit
-
-#endif
diff --git a/Source/WebKit/chromium/public/android/WebHitTestInfo.h b/Source/WebKit/chromium/public/android/WebHitTestInfo.h
deleted file mode 100644
index 79b354e..0000000
--- a/Source/WebKit/chromium/public/android/WebHitTestInfo.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-* Copyright (C) 2011 Google Inc. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-*
-* 1.  Redistributions of source code must retain the above copyright
-*     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef WebHitTestInfo_h
-#define WebHitTestInfo_h
-
-#include "../WebPoint.h"
-#include "../WebPrivateOwnPtr.h"
-#include "../WebURL.h"
-
-namespace WebCore {
-class HitTestResult;
-class Node;
-}
-
-namespace WebKit {
-
-// Properties of a hit test result, i.e. properties of the nodes at a given point
-// (the hit point) on the page. Both urls may be populated at the same time, for
-// example in the instance of an <img> inside an <a>.
-class WebHitTestInfo {
-public:
-    WebHitTestInfo();
-    WebHitTestInfo(const WebHitTestInfo&);
-    ~WebHitTestInfo();
-
-    // The absolute URL of the link returned by the hit test.
-    WEBKIT_API WebURL linkURL() const;
-
-    // The absolute URL of the image returned by the hit test.
-    WEBKIT_API WebURL imageURL() const;
-
-    // The node that got hit.
-    WEBKIT_API WebCore::Node* node() const;
-
-    // Point coordinates of the hit.
-    WEBKIT_API WebPoint point() const;
-
-    // True iff the hit was on an editable field or node.
-    WEBKIT_API bool isContentEditable() const;
-
-#if WEBKIT_IMPLEMENTATION
-    WebHitTestInfo(const WebCore::HitTestResult&);
-    WebHitTestInfo& operator=(const WebCore::HitTestResult&);
-    operator WebCore::HitTestResult() const;
-#endif
-
-protected:
-    WebPrivateOwnPtr<WebCore::HitTestResult> m_private;
-};
-
-} // namespace WebKit
-
-#endif
diff --git a/Source/WebKit/chromium/src/WebRange.cpp b/Source/WebKit/chromium/src/WebRange.cpp
index 5ea3990..3dd000d 100644
--- a/Source/WebKit/chromium/src/WebRange.cpp
+++ b/Source/WebKit/chromium/src/WebRange.cpp
@@ -32,6 +32,7 @@
 #include "WebRange.h"
 
 #include "Range.h"
+#include "WebNode.h"
 #include "WebString.h"
 #include <wtf/PassRefPtr.h>
 
@@ -65,14 +66,14 @@
     return m_private->endOffset();
 }
 
-Node* WebRange::startContainer(int& exceptionCode) const
+WebNode WebRange::startContainer(int& exceptionCode) const
 {
-    return m_private->startContainer(exceptionCode);
+    return PassRefPtr<Node>(m_private->startContainer(exceptionCode));
 }
 
-Node* WebRange::endContainer(int& exceptionCode) const
+WebNode WebRange::endContainer(int& exceptionCode) const
 {
-    return m_private->endContainer(exceptionCode);
+    return PassRefPtr<Node>(m_private->endContainer(exceptionCode));
 }
 
 WebString WebRange::toHTMLText() const
diff --git a/Source/WebKit/chromium/src/android/WebDOMTextContentWalker.cpp b/Source/WebKit/chromium/src/android/WebDOMTextContentWalker.cpp
deleted file mode 100644
index 80155fb..0000000
--- a/Source/WebKit/chromium/src/android/WebDOMTextContentWalker.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "android/WebDOMTextContentWalker.h"
-
-#include "DOMTextContentWalker.h"
-#include "Element.h"
-#include "Node.h"
-#include "Range.h"
-#include "RenderObject.h"
-#include "Text.h"
-#include "VisiblePosition.h"
-#include "android/WebHitTestInfo.h"
-
-using namespace WebCore;
-
-namespace WebKit {
-
-WebDOMTextContentWalker::WebDOMTextContentWalker()
-{
-}
-
-WebDOMTextContentWalker::~WebDOMTextContentWalker()
-{
-    m_private.reset(0);
-}
-
-WebDOMTextContentWalker::WebDOMTextContentWalker(const WebHitTestInfo& hitTestInfo, size_t maxLength)
-{
-    Node* node = hitTestInfo.node();
-    if (!node)
-        return;
-
-    Element* element = node->parentElement();
-    if (!node->inDocument() && element && element->inDocument())
-        node = element;
-    m_private.reset(new DOMTextContentWalker(node->renderer()->positionForPoint(hitTestInfo.point()), maxLength));
-}
-
-WebDOMTextContentWalker::WebDOMTextContentWalker(Node* node, size_t offset, size_t maxLength)
-{
-    if (!node || !node->isTextNode() || offset >= node->nodeValue().length())
-        return;
-
-    m_private.reset(new DOMTextContentWalker(VisiblePosition(Position(static_cast<Text*>(node), offset).parentAnchoredEquivalent(), DOWNSTREAM), maxLength));
-}
-
-WebString WebDOMTextContentWalker::content() const
-{
-    return m_private->content();
-}
-
-size_t WebDOMTextContentWalker::hitOffsetInContent() const
-{
-    return m_private->hitOffsetInContent();
-}
-
-WebRange WebDOMTextContentWalker::contentOffsetsToRange(size_t startInContent, size_t endInContent)
-{
-    return m_private->contentOffsetsToRange(startInContent, endInContent);
-}
-
-} // namespace WebKit
diff --git a/Source/WebKit/chromium/src/android/WebHitTestInfo.cpp b/Source/WebKit/chromium/src/android/WebHitTestInfo.cpp
deleted file mode 100644
index 948c6fb..0000000
--- a/Source/WebKit/chromium/src/android/WebHitTestInfo.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
-* Copyright (C) 2011 Google Inc. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-*
-* 1.  Redistributions of source code must retain the above copyright
-*     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "android/WebHitTestInfo.h"
-
-#include "Element.h"
-#include "HitTestResult.h"
-#include "KURL.h"
-#include "Node.h"
-#include "RenderObject.h"
-#include "VisiblePosition.h"
-
-using namespace WebCore;
-
-namespace WebKit {
-
-WebHitTestInfo::WebHitTestInfo()
-{
-}
-
-WebHitTestInfo::WebHitTestInfo(const WebHitTestInfo& testInfo)
-    : m_private(new HitTestResult(testInfo))
-{
-}
-
-WebURL WebHitTestInfo::linkURL() const
-{
-    return m_private->absoluteLinkURL();
-}
-
-WebHitTestInfo::~WebHitTestInfo()
-{
-    m_private.reset(0);
-}
-
-WebURL WebHitTestInfo::imageURL() const
-{
-    return m_private->absoluteImageURL();
-}
-
-Node* WebHitTestInfo::node() const
-{
-    return m_private->innerNode();
-}
-
-WebPoint WebHitTestInfo::point() const
-{
-    return WebPoint(m_private->localPoint());
-}
-
-bool WebHitTestInfo::isContentEditable() const
-{
-    return m_private->isContentEditable();
-}
-
-WebHitTestInfo::WebHitTestInfo(const HitTestResult& result)
-{
-    m_private.reset(new HitTestResult(result));
-}
-
-WebHitTestInfo& WebHitTestInfo::operator=(const HitTestResult& result)
-{
-    m_private.reset(new HitTestResult(result));
-    return *this;
-}
-
-WebHitTestInfo::operator HitTestResult() const
-{
-    return *m_private.get();
-}
-
-} // namespace WebKit
diff --git a/Source/WebKit/efl/WebCoreSupport/ChromeClientEfl.cpp b/Source/WebKit/efl/WebCoreSupport/ChromeClientEfl.cpp
index 6459887..ce2ac1b 100644
--- a/Source/WebKit/efl/WebCoreSupport/ChromeClientEfl.cpp
+++ b/Source/WebKit/efl/WebCoreSupport/ChromeClientEfl.cpp
@@ -360,7 +360,7 @@
         if (!url.isEmpty() && url != m_hoveredLinkURL) {
             const char* link[2];
             TextDirection dir;
-            CString urlStr = url.string().utf8();
+            CString urlStr = url.prettyURL().utf8();
             CString titleStr = hit.title(dir).utf8();
             link[0] = urlStr.data();
             link[1] = titleStr.data();
diff --git a/Source/WebKit/efl/WebCoreSupport/FrameLoaderClientEfl.cpp b/Source/WebKit/efl/WebCoreSupport/FrameLoaderClientEfl.cpp
index 021188a..9a409f2 100644
--- a/Source/WebKit/efl/WebCoreSupport/FrameLoaderClientEfl.cpp
+++ b/Source/WebKit/efl/WebCoreSupport/FrameLoaderClientEfl.cpp
@@ -209,7 +209,7 @@
 
 void FrameLoaderClientEfl::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& coreRequest, const ResourceResponse& coreResponse)
 {
-    CString url = coreRequest.url().string().utf8();
+    CString url = coreRequest.url().prettyURL().utf8();
     DBG("Resource url=%s", url.data());
 
     Ewk_Frame_Resource_Request request = { 0, identifier };
@@ -236,7 +236,7 @@
 
 void FrameLoaderClientEfl::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest& coreRequest)
 {
-    CString url = coreRequest.url().string().utf8();
+    CString url = coreRequest.url().prettyURL().utf8();
     DBG("Resource url=%s", url.data());
 
     Ewk_Frame_Resource_Request request = { 0, identifier };
@@ -309,7 +309,7 @@
     ASSERT(m_frame);
     // if not acceptNavigationRequest - look at Qt -> PolicyIgnore;
     // FIXME: do proper check and only reset forms when on PolicyIgnore
-    char* url = strdup(resourceRequest.url().string().utf8().data());
+    char* url = strdup(resourceRequest.url().prettyURL().utf8().data());
     Ewk_Frame_Resource_Request request = { url, 0 };
     Eina_Bool ret = ewk_view_navigation_policy_decision(m_view, &request);
     free(url);
@@ -764,7 +764,7 @@
     if (!m_view)
         return;
 
-    CString url = request.url().string().utf8();
+    CString url = request.url().prettyURL().utf8();
     Ewk_Download download;
 
     download.url = url.data();
@@ -784,7 +784,7 @@
 
 ResourceError FrameLoaderClientEfl::cancelledError(const ResourceRequest& request)
 {
-    ResourceError error("Error", -999, request.url().string(),
+    ResourceError error("Error", -999, request.url().prettyURL(),
                         "Request cancelled");
     error.setIsCancellation(true);
     return error;
@@ -792,7 +792,7 @@
 
 ResourceError FrameLoaderClientEfl::blockedError(const ResourceRequest& request)
 {
-    return ResourceError("Error", WebKitErrorCannotUseRestrictedPort, request.url().string(),
+    return ResourceError("Error", WebKitErrorCannotUseRestrictedPort, request.url().prettyURL(),
                          "Request blocked");
 }
 
diff --git a/Source/WebKit/efl/ewk/ewk_frame.cpp b/Source/WebKit/efl/ewk/ewk_frame.cpp
index e865d39..4e52b56 100644
--- a/Source/WebKit/efl/ewk/ewk_frame.cpp
+++ b/Source/WebKit/efl/ewk/ewk_frame.cpp
@@ -1162,7 +1162,7 @@
         hit_test->frame = kit(result.innerNonSharedNode()->document()->frame());
 
     hit_test->link.text = eina_stringshare_add(result.textContent().utf8().data());
-    hit_test->link.url = eina_stringshare_add(result.absoluteLinkURL().string().utf8().data());
+    hit_test->link.url = eina_stringshare_add(result.absoluteLinkURL().prettyURL().utf8().data());
     hit_test->link.title = eina_stringshare_add(result.titleDisplayString().utf8().data());
     hit_test->link.target_frame = kit(result.targetFrame());
 
@@ -2014,7 +2014,7 @@
 {
     EWK_FRAME_SD_GET_OR_RETURN(o, sd, EINA_FALSE);
     EINA_SAFETY_ON_NULL_RETURN_VAL(sd->frame, EINA_FALSE);
-    WTF::CString uri(sd->frame->document()->url().string().utf8());
+    WTF::CString uri(sd->frame->document()->url().prettyURL().utf8());
 
     INF("uri=%s", uri.data());
     if (!uri.data()) {
diff --git a/Source/WebKit/efl/ewk/ewk_view.cpp b/Source/WebKit/efl/ewk/ewk_view.cpp
index f830426..a6749de 100644
--- a/Source/WebKit/efl/ewk/ewk_view.cpp
+++ b/Source/WebKit/efl/ewk/ewk_view.cpp
@@ -577,7 +577,7 @@
     priv->page_settings->setUsesEncodingDetector(true);
 
     url = priv->page_settings->userStyleSheetLocation();
-    priv->settings.user_stylesheet = eina_stringshare_add(url.string().utf8().data());
+    priv->settings.user_stylesheet = eina_stringshare_add(url.prettyURL().utf8().data());
 
     priv->settings.encoding_default = eina_stringshare_add
         (priv->page_settings->defaultTextEncodingName().utf8().data());
@@ -4077,7 +4077,7 @@
 {
     DBG("o=%p, frame=%p, name=%s, ownerElement=%p, url=%s, referrer=%s",
         o, frame, name.utf8().data(), ownerElement,
-        url.string().utf8().data(), referrer.utf8().data());
+        url.prettyURL().utf8().data(), referrer.utf8().data());
 
     EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
     EWK_VIEW_PRIV_GET_OR_RETURN(sd, priv, 0);
@@ -4109,7 +4109,7 @@
 {
     DBG("o=%p, frame=%p, size=%dx%d, element=%p, url=%s, mimeType=%s",
         o, frame, pluginSize.width(), pluginSize.height(), element,
-        url.string().utf8().data(), mimeType.utf8().data());
+        url.prettyURL().utf8().data(), mimeType.utf8().data());
 
     EWK_VIEW_SD_GET_OR_RETURN(o, sd, 0);
     sd->changed.frame_rect = EINA_TRUE;
diff --git a/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp b/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp
index 4ee9c1a..9f21139 100644
--- a/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp
+++ b/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp
@@ -549,7 +549,7 @@
         if (!url.isEmpty() && url != m_hoveredLinkURL) {
             TextDirection dir;
             CString titleString = hit.title(dir).utf8();
-            CString urlString = url.string().utf8();
+            CString urlString = url.prettyURL().utf8();
             g_signal_emit_by_name(m_webView, "hovering-over-link", titleString.data(), urlString.data());
             m_hoveredLinkURL = url;
         }
diff --git a/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp b/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp
index de85a67..539675a 100644
--- a/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp
+++ b/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp
@@ -895,7 +895,7 @@
 {
     WebKitWebFramePrivate* priv = m_frame->priv;
     g_free(priv->uri);
-    priv->uri = g_strdup(core(m_frame)->document()->url().string().utf8().data());
+    priv->uri = g_strdup(core(m_frame)->document()->url().prettyURL().utf8().data());
     g_object_notify(G_OBJECT(m_frame), "uri");
     WebKitWebView* webView = getViewFromFrame(m_frame);
     if (m_frame == webkit_web_view_get_main_frame(webView))
@@ -986,7 +986,7 @@
 
     WebKitWebFramePrivate* priv = m_frame->priv;
     g_free(priv->uri);
-    priv->uri = g_strdup(core(m_frame)->loader()->activeDocumentLoader()->url().string().utf8().data());
+    priv->uri = g_strdup(core(m_frame)->loader()->activeDocumentLoader()->url().prettyURL().utf8().data());
     g_free(priv->title);
     priv->title = NULL;
     g_object_notify(G_OBJECT(m_frame), "uri");
diff --git a/Source/WebKit/gtk/webkit/webkitwebview.cpp b/Source/WebKit/gtk/webkit/webkitwebview.cpp
index 3b9ebe3..85ad904 100644
--- a/Source/WebKit/gtk/webkit/webkitwebview.cpp
+++ b/Source/WebKit/gtk/webkit/webkitwebview.cpp
@@ -5034,7 +5034,7 @@
 G_CONST_RETURN gchar* webkit_web_view_get_icon_uri(WebKitWebView* webView)
 {
     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
-    String iconURL = iconDatabase().synchronousIconURLForPageURL(core(webView)->mainFrame()->document()->url().string());
+    String iconURL = iconDatabase().synchronousIconURLForPageURL(core(webView)->mainFrame()->document()->url().prettyURL());
     webView->priv->iconURI = iconURL.utf8();
     return webView->priv->iconURI.data();
 }
diff --git a/Source/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp b/Source/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp
index f30e0f8..ea2c826 100644
--- a/Source/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp
+++ b/Source/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp
@@ -497,7 +497,7 @@
         lastHoverURL = result.absoluteLinkURL();
         lastHoverTitle = result.title(dir);
         lastHoverContent = result.textContent();
-        emit m_webPage->linkHovered(lastHoverURL.string(),
+        emit m_webPage->linkHovered(lastHoverURL.prettyURL(),
                 lastHoverTitle, lastHoverContent);
     }
 }
diff --git a/Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp b/Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp
index c35cf3b..d083f8f 100644
--- a/Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp
+++ b/Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp
@@ -797,7 +797,7 @@
     QWebHistoryInterface* history = QWebHistoryInterface::defaultInterface();
     WebCore::DocumentLoader* loader = m_frame->loader()->documentLoader();
     if (history)
-        history->addHistoryEntry(loader->urlForHistory().string());
+        history->addHistoryEntry(loader->urlForHistory().prettyURL());
 
     if (dumpHistoryCallbacks) {
         printf("WebView navigated to url \"%s\" with title \"%s\" with HTTP equivalent method \"%s\".  The navigation was %s and was %s%s.\n",
@@ -921,7 +921,7 @@
 
 WebCore::ResourceError FrameLoaderClientQt::cancelledError(const WebCore::ResourceRequest& request)
 {
-    ResourceError error = ResourceError("QtNetwork", QNetworkReply::OperationCanceledError, request.url().string(),
+    ResourceError error = ResourceError("QtNetwork", QNetworkReply::OperationCanceledError, request.url().prettyURL(),
             QCoreApplication::translate("QWebFrame", "Request cancelled", 0, QCoreApplication::UnicodeUTF8));
     error.setIsCancellation(true);
     return error;
@@ -941,7 +941,7 @@
 
 WebCore::ResourceError FrameLoaderClientQt::blockedError(const WebCore::ResourceRequest& request)
 {
-    return ResourceError("WebKitErrorDomain", WebKitErrorCannotUseRestrictedPort, request.url().string(),
+    return ResourceError("WebKitErrorDomain", WebKitErrorCannotUseRestrictedPort, request.url().prettyURL(),
             QCoreApplication::translate("QWebFrame", "Request blocked", 0, QCoreApplication::UnicodeUTF8));
 }
 
@@ -1345,7 +1345,7 @@
 
 ObjectContentType FrameLoaderClientQt::objectContentType(const KURL& url, const String& mimeTypeIn, bool shouldPreferPlugInsForImages)
 {
-    // qDebug()<<" ++++++++++++++++ url is "<<url.string()<<", mime = "<<mimeTypeIn;
+    // qDebug()<<" ++++++++++++++++ url is "<<url.prettyURL()<<", mime = "<<mimeTypeIn;
     QFileInfo fi(url.path());
     String extension = fi.suffix();
     if (mimeTypeIn == "application/x-qt-plugin" || mimeTypeIn == "application/x-qt-styled-widget")
@@ -1508,8 +1508,8 @@
 PassRefPtr<Widget> FrameLoaderClientQt::createPlugin(const IntSize& pluginSize, HTMLPlugInElement* element, const KURL& url, const Vector<String>& paramNames,
                                           const Vector<String>& paramValues, const String& mimeType, bool loadManually)
 {
-    // qDebug()<<"------ Creating plugin in FrameLoaderClientQt::createPlugin for "<<url.string() << mimeType;
-    // qDebug()<<"------\t url = "<<url.string();
+    // qDebug()<<"------ Creating plugin in FrameLoaderClientQt::createPlugin for "<<url.prettyURL() << mimeType;
+    // qDebug()<<"------\t url = "<<url.prettyURL();
 
     if (!m_webFrame)
         return 0;
diff --git a/Source/WebKit2/WebProcess/WebCoreSupport/qt/WebErrorsQt.cpp b/Source/WebKit2/WebProcess/WebCoreSupport/qt/WebErrorsQt.cpp
index ace9599..61c2a3a 100644
--- a/Source/WebKit2/WebProcess/WebCoreSupport/qt/WebErrorsQt.cpp
+++ b/Source/WebKit2/WebProcess/WebCoreSupport/qt/WebErrorsQt.cpp
@@ -51,7 +51,7 @@
 
 ResourceError cancelledError(const ResourceRequest& request)
 {
-    ResourceError error = ResourceError("QtNetwork", QNetworkReply::OperationCanceledError, request.url().string(),
+    ResourceError error = ResourceError("QtNetwork", QNetworkReply::OperationCanceledError, request.url().prettyURL(),
                                         QCoreApplication::translate("QWebFrame", "Request cancelled", 0, QCoreApplication::UnicodeUTF8));
     error.setIsCancellation(true);
     return error;    
@@ -59,7 +59,7 @@
 
 ResourceError blockedError(const ResourceRequest& request)
 {
-    return ResourceError("WebKit", WebKitErrorCannotUseRestrictedPort, request.url().string(),
+    return ResourceError("WebKit", WebKitErrorCannotUseRestrictedPort, request.url().prettyURL(),
                          QCoreApplication::translate("QWebFrame", "Request blocked", 0, QCoreApplication::UnicodeUTF8));
 }