OSDN Git Service

am 48a84519: (-s ours) am 31cf3287: Do not merge: Cherry-pick CL to help flash plugin...
authorNicolas Roard <nicolas@android.com>
Fri, 25 Feb 2011 00:34:26 +0000 (16:34 -0800)
committerAndroid Git Automerger <android-git-automerger@android.com>
Fri, 25 Feb 2011 00:34:26 +0000 (16:34 -0800)
* commit '48a84519fe5415339de288d11f43a71fb3ca6c28':
  Do not merge: Cherry-pick CL to help flash plugin performance

114 files changed:
ThirdPartyProject.prop
WebCore/ChangeLog
WebCore/bindings/v8/V8NPUtils.cpp
WebCore/config.h
WebCore/css/CSSFontFaceSource.cpp
WebCore/css/CSSFontFaceSource.h
WebCore/css/CSSMediaRule.cpp
WebCore/css/CSSRuleList.cpp
WebCore/css/CSSStyleSheet.cpp
WebCore/css/CSSStyleSheet.h
WebCore/css/WebKitCSSKeyframesRule.cpp
WebCore/dom/DeviceMotionController.cpp
WebCore/dom/DeviceMotionController.h
WebCore/dom/DeviceOrientationController.cpp
WebCore/dom/DeviceOrientationController.h
WebCore/dom/Document.cpp
WebCore/editing/SelectionController.cpp
WebCore/editing/TextIterator.cpp
WebCore/history/HistoryItem.cpp
WebCore/history/HistoryItem.h
WebCore/html/HTMLFormControlElement.cpp
WebCore/html/HTMLFormControlElement.h
WebCore/html/HTMLOptionElement.h
WebCore/html/canvas/DataView.h
WebCore/html/canvas/WebGLRenderingContext.cpp
WebCore/loader/HistoryController.cpp
WebCore/loader/HistoryController.h
WebCore/page/DOMWindow.cpp
WebCore/page/DOMWindow.h
WebCore/page/DOMWindow.idl
WebCore/page/FrameView.cpp
WebCore/page/FrameView.h
WebCore/page/History.cpp
WebCore/page/History.h
WebCore/page/History.idl
WebCore/page/animation/AnimationController.cpp
WebCore/platform/android/PlatformBridge.h
WebCore/platform/android/PopupMenuAndroid.cpp
WebCore/platform/android/PopupMenuAndroid.h
WebCore/platform/android/RenderThemeAndroid.cpp
WebCore/platform/graphics/android/BaseLayerAndroid.cpp
WebCore/platform/graphics/android/BaseLayerAndroid.h
WebCore/platform/graphics/android/BaseTile.cpp
WebCore/platform/graphics/android/FontCustomPlatformData.cpp
WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp
WebCore/platform/graphics/android/GLWebViewState.cpp
WebCore/platform/graphics/android/GLWebViewState.h
WebCore/platform/graphics/android/GradientAndroid.cpp
WebCore/platform/graphics/android/GraphicsContextAndroid.cpp
WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp
WebCore/platform/graphics/android/GraphicsLayerAndroid.h
WebCore/platform/graphics/android/LayerAndroid.cpp
WebCore/platform/graphics/android/LayerAndroid.h
WebCore/platform/graphics/android/MediaTexture.cpp
WebCore/platform/graphics/android/MediaTexture.h
WebCore/platform/graphics/android/PatternAndroid.cpp
WebCore/platform/graphics/android/ScrollableLayerAndroid.h
WebCore/platform/graphics/android/TilesManager.cpp
WebCore/platform/graphics/android/TilesManager.h
WebCore/platform/graphics/android/VideoListener.h [new file with mode: 0644]
WebCore/platform/graphics/android/android_graphics.cpp
WebCore/platform/graphics/android/android_graphics.h
WebCore/rendering/RenderBlock.cpp
WebCore/rendering/RenderBlock.h
WebCore/rendering/RenderBox.cpp
WebCore/rendering/RenderLayer.cpp
WebCore/rendering/RenderLayerBacking.cpp
WebCore/rendering/RenderLayerCompositor.cpp
WebCore/rendering/RenderTable.cpp
WebCore/rendering/RenderTextControlMultiLine.cpp
WebCore/rendering/RenderTheme.cpp
WebCore/rendering/RenderTheme.h
WebCore/svg/SVGDocumentExtensions.cpp
WebCore/svg/SVGFont.cpp
WebCore/svg/SVGFontFaceElement.cpp
WebCore/svg/SVGFontFaceElement.h
WebCore/xml/XSLStyleSheet.h
WebCore/xml/XSLStyleSheetLibxslt.cpp
WebCore/xml/XSLStyleSheetQt.cpp
WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h
WebKit/android/WebCoreSupport/PlatformBridge.cpp
WebKit/android/WebCoreSupport/ResourceLoaderAndroid.cpp
WebKit/android/WebCoreSupport/WebCookieJar.cpp
WebKit/android/WebCoreSupport/WebCookieJar.h
WebKit/android/WebCoreSupport/WebRequest.cpp
WebKit/android/WebCoreSupport/WebRequest.h
WebKit/android/WebCoreSupport/WebUrlLoader.cpp
WebKit/android/WebCoreSupport/WebUrlLoader.h
WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp
WebKit/android/WebCoreSupport/WebUrlLoaderClient.h
WebKit/android/jni/CookieManager.cpp
WebKit/android/jni/PictureSet.cpp
WebKit/android/jni/WebCoreFrameBridge.cpp
WebKit/android/jni/WebCoreFrameBridge.h
WebKit/android/jni/WebCoreJni.h
WebKit/android/jni/WebViewCore.cpp
WebKit/android/jni/WebViewCore.h
WebKit/android/nav/CacheBuilder.cpp
WebKit/android/nav/CacheBuilder.h
WebKit/android/nav/CachedFrame.cpp
WebKit/android/nav/CachedFrame.h
WebKit/android/nav/CachedLayer.cpp
WebKit/android/nav/CachedLayer.h
WebKit/android/nav/CachedNode.cpp
WebKit/android/nav/CachedNode.h
WebKit/android/nav/CachedRoot.cpp
WebKit/android/nav/CachedRoot.h
WebKit/android/nav/FindCanvas.cpp
WebKit/android/nav/SelectText.cpp
WebKit/android/nav/WebView.cpp
WebKit/android/plugins/ANPTypefaceInterface.cpp
WebKit/android/plugins/PluginWidgetAndroid.cpp

index 4efb8e4..7d97ec6 100644 (file)
@@ -11,4 +11,4 @@ homepage=http\://webkit.org/
 # Currently we track the Chromium 9.0.597 release branch:
 # http://trac.webkit.org/browser/branches/chromium/597
 # which is WebKit r72805 + stability cherry picks.
-webkit.chromiumRelease=http\://src.chromium.org/svn/releases/9.0.597.83/DEPS
+webkit.chromiumRelease=http\://src.chromium.org/svn/releases/9.0.597.106/DEPS
index ae5f73f..2749f26 100644 (file)
@@ -1,3 +1,234 @@
+2011-01-30  Kenichi Ishibashi  <bashi@google.com>
+
+        Reviewed by Kent Tamura.
+
+        Dangling form associated elements should not be registered on the document
+        https://bugs.webkit.org/show_bug.cgi?id=53223
+
+        Adds insertedIntoDocument() and remvoedFromDocument() to
+        FormAssociatedElement class to register the element on the document
+        if and only if it actually inserted into (removed from) the document.
+
+        Test: fast/forms/dangling-form-element-crash.html
+
+        * html/FormAssociatedElement.cpp:
+        (WebCore::FormAssociatedElement::insertedIntoDocument): Added.
+        (WebCore::FormAssociatedElement::removedFromDocument): Ditto.
+        (WebCore::FormAssociatedElement::insertedIntoTree): Don't register
+        the element to a document.
+        (WebCore::FormAssociatedElement::removedFromTree): Don't unregister
+        the element from a document.
+        * html/FormAssociatedElement.h:
+        * html/HTMLFormControlElement.cpp:
+        (WebCore::HTMLFormControlElement::insertedIntoDocument): Added.
+        (WebCore::HTMLFormControlElement::removedFromDocument): Ditto.
+        * html/HTMLFormControlElement.h:
+        * html/HTMLObjectElement.cpp:
+        (WebCore::HTMLObjectElement::insertedIntoDocument): Calls
+        FormAssociatedElement::insertedIntoDocument().
+        (WebCore::HTMLObjectElement::removedFromDocument): Calls
+        FormAssociatedElement::removedFromDocument().
+
+2011-02-08  Zhenyao Mo  <zmo@google.com>
+
+        Reviewed by Kenneth Russell.
+
+        drawElements should check if a buffer is bound to ELEMENT_ARRAY_BUFFER
+        https://bugs.webkit.org/show_bug.cgi?id=54017
+
+        * html/canvas/WebGLRenderingContext.cpp:
+        (WebCore::WebGLRenderingContext::drawElements):
+
+2011-02-02  Chris Evans  <cevans@chromium.org>
+
+        Reviewed by Darin Fisher.
+
+        window.find() can fail when switching case sensitivity
+        https://bugs.webkit.org/show_bug.cgi?id=53654
+
+        Reset the pattern to a safe one when done, to avoid usearch_reset()
+        indirectly touching the old, stale text pointer.
+
+        Test: fast/text/find-window.html
+
+        * editing/TextIterator.cpp:
+        (WebCore::SearchBuffer::~SearchBuffer): leave a safe pattern buffer when done.
+
+2011-02-03  Justin Schuh  <jschuh@chromium.org>
+
+        Reviewed by Dirk Schulze.
+
+        startAnimations should use a local, RefCounted Vector.
+        https://bugs.webkit.org/show_bug.cgi?id=53458
+
+        Test: svg/custom/use-animation-in-fill.html
+
+        * svg/SVGDocumentExtensions.cpp:
+        (WebCore::SVGDocumentExtensions::startAnimations):
+
+2011-02-03  Abhishek Arya  <inferno@chromium.org>
+
+        Reviewed by James Robinson.
+
+        Enforce more limits on root inline boxes height calculations.
+        https://bugs.webkit.org/show_bug.cgi?id=53729
+
+        Test: fast/overflow/overflow-height-float-not-removed-crash.html
+
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::removeFloatingObject): prevent logicalBottom to
+        become negative when logicalTop is INT_MAX.
+        (WebCore::RenderBlock::markLinesDirtyInBlockRange): when logicalBottom
+        is INT_MAX, we should dirty everything. So, we bail out to make
+        afterLowest equal to the lastRootBox() or lowestDirstLine.
+
+2011-01-26  Emil A Eklund  <eae@chromium.org>
+
+        Reviewed by Alexey Proskuryakov.
+
+        Remove cached document reference from CSSStyleSheet and XSLStyleSheet.
+        https://bugs.webkit.org/show_bug.cgi?id=52084
+
+        Test: fast/dom/css-delete-doc.html
+
+        * css/CSSMediaRule.cpp:
+        (WebCore::CSSMediaRule::insertRule):
+        (WebCore::CSSMediaRule::deleteRule):
+        * css/CSSStyleSheet.cpp:
+        (WebCore::CSSStyleSheet::CSSStyleSheet):
+        (WebCore::CSSStyleSheet::document):
+        * css/CSSStyleSheet.h:
+        * xml/XSLStyleSheet.h:
+        (WebCore::XSLStyleSheet::parentStyleSheet):
+        * xml/XSLStyleSheetLibxslt.cpp:
+        (WebCore::XSLStyleSheet::XSLStyleSheet):
+        (WebCore::XSLStyleSheet::cachedResourceLoader):
+        (WebCore::XSLStyleSheet::setParentStyleSheet):
+        (WebCore::XSLStyleSheet::ownerDocument):
+        * xml/XSLStyleSheetQt.cpp:
+        (WebCore::XSLStyleSheet::XSLStyleSheet):
+        (WebCore::XSLStyleSheet::cachedResourceLoader):
+        (WebCore::XSLStyleSheet::ownerDocument):
+
+2011-01-27  Abhishek Arya  <inferno@chromium.org>
+
+        Reviewed by Dave Hyatt.
+
+        If beforeChild is wrapped in an anonymous table section, we need to
+        go the parent to find it and use it before adding childs to table.
+        https://bugs.webkit.org/show_bug.cgi?id=53276
+
+        We need to make sure that beforeChild's parent is "this" before calling
+        RenderBox::addChild. The previous condition in while is too restrictive
+        and fails to calculate the right beforeChild value when its display
+        style is table caption.
+        Test: fast/table/before-child-non-table-section-add-table-crash.html
+
+        * rendering/RenderTable.cpp:
+        (WebCore::RenderTable::addChild):
+
+2011-02-01  Abhishek Arya  <inferno@chromium.org>
+
+        Reviewed by Dan Bernstein.
+
+        Do not add a node in the document's stylesheet candidate node list if the
+        node is already removed from document.
+        https://bugs.webkit.org/show_bug.cgi?id=53441
+
+        Test: fast/css/stylesheet-candidate-nodes-crash.xhtml
+
+        * dom/Document.cpp:
+        (WebCore::Document::addStyleSheetCandidateNode):
+
+2011-01-31  Abhishek Arya  <inferno@chromium.org>
+
+        Reviewed by Dimitri Glazkov.
+
+        Check the textarea node still exists in document before casting
+        it to HTMLTextAreaElement.
+        https://bugs.webkit.org/show_bug.cgi?id=53429
+
+        Test: fast/forms/textarea-node-removed-from-document-crash.html
+
+        * rendering/RenderTextControlMultiLine.cpp:
+        (WebCore::RenderTextControlMultiLine::~RenderTextControlMultiLine):
+
+2011-02-02  Jian Li  <jianli@chromium.org>
+
+        Reviewed by Kenneth Russell.
+
+        [V8] Accessing DataView with index of -1 returns 0, doesn't throw
+        https://bugs.webkit.org/show_bug.cgi?id=53559
+
+        Added test cases to cover this in fast/canvas/webgl/data-view-test.html.
+
+        * html/canvas/DataView.h:
+        (WebCore::DataView::beyondRange):
+
+2011-02-06  Andreas Kling  <kling@webkit.org>
+
+        Reviewed by Dirk Schulze.
+
+        Fix potential buffer overrun in SVGTextRunWalker::walk()
+        https://bugs.webkit.org/show_bug.cgi?id=53870
+
+        A new String was created from a UChar* with a 'length' argument
+        that could be greater than the number of UChars available.
+
+        * svg/SVGFont.cpp:
+        (WebCore::SVGTextRunWalker::walk):
+
+2011-02-02  Cris Neckar  <cdn@chromium.org>
+
+        Reviewed by James Robinson.
+
+        Refcount domwindows when dispatching device orientation events.
+        https://bugs.webkit.org/show_bug.cgi?id=53623
+
+        Test: fast/events/device-orientation-crash.html
+
+        * dom/DeviceMotionController.cpp:
+        (WebCore::DeviceMotionController::timerFired):
+        (WebCore::DeviceMotionController::didChangeDeviceMotion):
+        * dom/DeviceMotionController.h:
+        * dom/DeviceOrientationController.cpp:
+        (WebCore::DeviceOrientationController::timerFired):
+        (WebCore::DeviceOrientationController::didChangeDeviceOrientation):
+        * dom/DeviceOrientationController.h:
+
+2011-01-27  Abhishek Arya  <inferno@chromium.org>
+
+        Reviewed by Dan Bernstein.
+
+        Recalc table sections if needed before calculating the first line
+        box baseline.
+        https://bugs.webkit.org/show_bug.cgi?id=53265
+
+        When we try to calculate the baseline position of a table cell,
+        we recurse through all the child sibling boxes (when children are
+        non inline) and add their first linebox baseline values. If one of
+        the children is a table with pending section recalc, we will access
+        wrong table section values. We recalc table sections if it is needed.
+
+        Test: fast/table/recalc-section-first-body-crash-main.html
+
+        * rendering/RenderTable.cpp:
+        (WebCore::RenderTable::firstLineBoxBaseline):
+
+2011-01-27  Cris Neckar  <cdn@chromium.org>
+
+        Reviewed by Dimitri Glazkov.
+
+        Clear the parent on a css keyframe's m_style when removing it from the stylesheet.
+        https://bugs.webkit.org/show_bug.cgi?id=52320
+
+        Test: fast/css/css-keyframe-style-crash.html
+
+        * css/CSSRuleList.cpp:
+        (WebCore::CSSRuleList::deleteRule):
+        * css/WebKitCSSKeyframesRule.cpp:
+        (WebCore::WebKitCSSKeyframesRule::~WebKitCSSKeyframesRule):
+
 2011-01-20  Xiaomei Ji  <xji@chromium.org>
 
         Reviewed by Dan Bernstein.
index 8fa19d7..cb752be 100644 (file)
@@ -65,8 +65,10 @@ void convertV8ObjectToNPVariant(v8::Local<v8::Value> object, NPObject* owner, NP
         VOID_TO_NPVARIANT(*result);
     else if (object->IsString()) {
         v8::String::Utf8Value utf8(object);
-        char* utf8_chars = strdup(*utf8);
-        STRINGN_TO_NPVARIANT(utf8_chars, utf8.length(), *result);
+        int length = utf8.length() + 1;
+        char* utf8Chars = reinterpret_cast<char*>(malloc(length));
+        memcpy(utf8Chars, *utf8, length);
+        STRINGN_TO_NPVARIANT(utf8Chars, utf8.length(), *result);
     } else if (object->IsObject()) {
         DOMWindow* window = V8Proxy::retrieveWindow(V8Proxy::currentContext());
         NPObject* npobject = npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(object), window);
index 7174c4b..a74acd6 100644 (file)
 // 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
 
 // Converts ListBoxes to dropdown popup lists.
-#define ANDROID_LISTBOX_USES_MENU_LIST
+#define ENABLE_NO_LISTBOX_RENDERING 1
 
 #define ANDROID_MULTIPLE_WINDOWS
 #define ANDROID_CSS_RING
index 30a0072..d5dc6ec 100644 (file)
@@ -168,7 +168,7 @@ SimpleFontData* CSSFontFaceSource::getFontData(const FontDescription& fontDescri
 #if ENABLE(SVG_FONTS)
             // In-Document SVG Fonts
             if (m_svgFontFaceElement)
-                fontData.set(new SimpleFontData(adoptPtr(new SVGFontData(m_svgFontFaceElement)), fontDescription.computedPixelSize(), syntheticBold, syntheticItalic));
+                fontData.set(new SimpleFontData(adoptPtr(new SVGFontData(m_svgFontFaceElement.get())), fontDescription.computedPixelSize(), syntheticBold, syntheticItalic));
 #endif
         }
     } else {
@@ -190,6 +190,16 @@ SimpleFontData* CSSFontFaceSource::getFontData(const FontDescription& fontDescri
 }
 
 #if ENABLE(SVG_FONTS)
+SVGFontFaceElement* CSSFontFaceSource::svgFontFaceElement() const
+{
+    return m_svgFontFaceElement.get();
+}
+
+void CSSFontFaceSource::setSVGFontFaceElement(PassRefPtr<SVGFontFaceElement> element) 
+{ 
+    m_svgFontFaceElement = element;
+}
+
 bool CSSFontFaceSource::isSVGFontFaceSource() const
 {
     return m_svgFontFaceElement || (m_font && m_font->isSVGFont());
index e2057cc..a5c3e61 100644 (file)
@@ -63,8 +63,8 @@ public:
     void pruneTable();
 
 #if ENABLE(SVG_FONTS)
-    SVGFontFaceElement* svgFontFaceElement() const { return m_svgFontFaceElement; }
-    void setSVGFontFaceElement(SVGFontFaceElement* element) { m_svgFontFaceElement = element; }
+    SVGFontFaceElement* svgFontFaceElement() const;
+    void setSVGFontFaceElement(PassRefPtr<SVGFontFaceElement>);
     bool isSVGFontFaceSource() const;
 #endif
 
@@ -75,7 +75,7 @@ private:
     HashMap<unsigned, SimpleFontData*> m_fontDataTable; // The hash key is composed of size synthetic styles.
 
 #if ENABLE(SVG_FONTS)
-    SVGFontFaceElement* m_svgFontFaceElement;
+    RefPtr<SVGFontFaceElement> m_svgFontFaceElement;
     RefPtr<SVGFontElement> m_externalSVGFontElement;
 #endif
 };
index 6348762..46dc780 100644 (file)
@@ -88,8 +88,8 @@ unsigned CSSMediaRule::insertRule(const String& rule, unsigned index, ExceptionC
     newRule->setParent(this);
     unsigned returnedIndex = m_lstCSSRules->insertRule(newRule.get(), index);
 
-    // stylesheet() can only return 0 for computed style declarations.
-    stylesheet()->styleSheetChanged();
+    if (stylesheet())
+        stylesheet()->styleSheetChanged();
 
     return returnedIndex;
 }
@@ -105,8 +105,8 @@ void CSSMediaRule::deleteRule(unsigned index, ExceptionCode& ec)
 
     m_lstCSSRules->deleteRule(index);
 
-    // stylesheet() can only return 0 for computed style declarations.
-    stylesheet()->styleSheetChanged();
+    if (stylesheet())
+        stylesheet()->styleSheetChanged();
 }
 
 String CSSMediaRule::cssText() const
index 0a312af..da65632 100644 (file)
 #include "config.h"
 #include "CSSRuleList.h"
 
+#include "CSSMutableStyleDeclaration.h"
 #include "CSSRule.h"
 #include "StyleList.h"
+#include "WebKitCSSKeyframeRule.h"
 
 namespace WebCore {
 
@@ -76,6 +78,11 @@ void CSSRuleList::deleteRule(unsigned index)
         return;
     }
 
+    if (m_lstCSSRules[index]->isKeyframeRule()) {
+        if (CSSMutableStyleDeclaration* style = static_cast<WebKitCSSKeyframeRule*>(m_lstCSSRules[index].get())->style())
+            style->setParent(0);
+    }
+
     m_lstCSSRules[index]->setParent(0);
     m_lstCSSRules.remove(index);
 }
index d5487a1..16c2ba8 100644 (file)
@@ -53,7 +53,6 @@ static bool isAcceptableCSSStyleSheetParent(Node* parentNode)
 
 CSSStyleSheet::CSSStyleSheet(CSSStyleSheet* parentSheet, const String& href, const KURL& baseURL, const String& charset)
     : StyleSheet(parentSheet, href, baseURL)
-    , m_document(parentSheet ? parentSheet->document() : 0)
     , m_charset(charset)
     , m_loadCompleted(false)
     , m_strictParsing(!parentSheet || parentSheet->useStrictParsing())
@@ -64,7 +63,6 @@ CSSStyleSheet::CSSStyleSheet(CSSStyleSheet* parentSheet, const String& href, con
 
 CSSStyleSheet::CSSStyleSheet(Node* parentNode, const String& href, const KURL& baseURL, const String& charset)
     : StyleSheet(parentNode, href, baseURL)
-    , m_document(parentNode->document())
     , m_charset(charset)
     , m_loadCompleted(false)
     , m_strictParsing(false)
@@ -82,7 +80,6 @@ CSSStyleSheet::CSSStyleSheet(CSSRule* ownerRule, const String& href, const KURL&
     , m_hasSyntacticallyValidCSSHeader(true)
 {
     CSSStyleSheet* parentSheet = ownerRule ? ownerRule->parentStyleSheet() : 0;
-    m_document = parentSheet ? parentSheet->document() : 0;
     m_isUserStyleSheet = parentSheet ? parentSheet->isUserStyleSheet() : false;
 }
 
@@ -233,6 +230,24 @@ void CSSStyleSheet::checkLoaded()
     m_loadCompleted = ownerNode() ? ownerNode()->sheetLoaded() : true;
 }
 
+Document* CSSStyleSheet::document()
+{
+    StyleBase* styleObject = this;
+    while (styleObject) {
+        if (styleObject->isCSSStyleSheet()) {
+            Node* ownerNode = static_cast<CSSStyleSheet*>(styleObject)->ownerNode();
+            if (ownerNode)
+                return ownerNode->document();
+        }
+        if (styleObject->isRule())
+            styleObject = static_cast<CSSRule*>(styleObject)->parentStyleSheet();
+        else
+            styleObject = styleObject->parent();
+    }
+
+    return 0;
+}
+
 void CSSStyleSheet::styleSheetChanged()
 {
     StyleBase* root = this;
index 725518f..062886a 100644 (file)
@@ -87,7 +87,7 @@ public:
 
     virtual void checkLoaded();
 
-    Document* document() { return m_document; }
+    Document* document();
 
     const String& charset() const { return m_charset; }
 
@@ -112,7 +112,6 @@ private:
     virtual bool isCSSStyleSheet() const { return true; }
     virtual String type() const { return "text/css"; }
 
-    Document* m_document;
     OwnPtr<CSSNamespace> m_namespaces;
     String m_charset;
     bool m_loadCompleted : 1;
index 23f9f34..bf0c463 100644 (file)
  */
 
 #include "config.h"
+#include "WebKitCSSKeyframesRule.h"
 
+#include "CSSMutableStyleDeclaration.h"
 #include "CSSParser.h"
-#include "WebKitCSSKeyframesRule.h"
-#include "WebKitCSSKeyframeRule.h"
 #include "CSSRuleList.h"
 #include "StyleSheet.h"
+#include "WebKitCSSKeyframeRule.h"
 
 namespace WebCore {
 
@@ -45,8 +46,13 @@ WebKitCSSKeyframesRule::~WebKitCSSKeyframesRule()
     if (length == 0)
         return;
         
-    for (int i = 0; i < length; i++)
+    for (int i = 0; i < length; i++) {
+        if (m_lstCSSRules->item(i)->isKeyframeRule()) {
+            if (CSSMutableStyleDeclaration* style = static_cast<WebKitCSSKeyframeRule*>(m_lstCSSRules->item(i))->style())
+                style->setParent(0);
+        }
         m_lstCSSRules->item(i)->setParent(0);
+    }
 }
 
 String WebKitCSSKeyframesRule::name() const
index 3385167..28e201e 100644 (file)
@@ -54,7 +54,7 @@ void DeviceMotionController::timerFired(Timer<DeviceMotionController>* timer)
     RefPtr<DeviceMotionData> deviceMotionData = m_client ? m_client->currentDeviceMotion() : DeviceMotionData::create();
     RefPtr<DeviceMotionEvent> event = DeviceMotionEvent::create(eventNames().devicemotionEvent, deviceMotionData.get());
  
-    Vector<DOMWindow*> listenersVector;
+    Vector<RefPtr<DOMWindow> > listenersVector;
     copyToVector(m_newListeners, listenersVector);
     m_newListeners.clear();
     for (size_t i = 0; i < listenersVector.size(); ++i)
@@ -100,7 +100,7 @@ void DeviceMotionController::removeAllListeners(DOMWindow* window)
 void DeviceMotionController::didChangeDeviceMotion(DeviceMotionData* deviceMotionData)
 {
     RefPtr<DeviceMotionEvent> event = DeviceMotionEvent::create(eventNames().devicemotionEvent, deviceMotionData);
-    Vector<DOMWindow*> listenersVector;
+    Vector<RefPtr<DOMWindow> > listenersVector;
     copyToVector(m_listeners, listenersVector);
     for (size_t i = 0; i < listenersVector.size(); ++i)
         listenersVector[i]->dispatchEvent(event);
index 70c948e..80c9d94 100644 (file)
@@ -52,9 +52,9 @@ private:
     void timerFired(Timer<DeviceMotionController>*);
     
     DeviceMotionClient* m_client;
-    typedef HashCountedSet<DOMWindow*> ListenersCountedSet;
+    typedef HashCountedSet<RefPtr<DOMWindow> > ListenersCountedSet;
     ListenersCountedSet m_listeners;
-    typedef HashSet<DOMWindow*> ListenersSet;
+    typedef HashSet<RefPtr<DOMWindow> > ListenersSet;
     ListenersSet m_newListeners;
     Timer<DeviceMotionController> m_timer;
 };
index 60fcf13..da42bec 100644 (file)
@@ -54,7 +54,7 @@ void DeviceOrientationController::timerFired(Timer<DeviceOrientationController>*
     RefPtr<DeviceOrientation> orientation = m_client->lastOrientation();
     RefPtr<DeviceOrientationEvent> event = DeviceOrientationEvent::create(eventNames().deviceorientationEvent, orientation.get());
 
-    Vector<DOMWindow*> listenersVector;
+    Vector<RefPtr<DOMWindow> > listenersVector;
     copyToVector(m_newListeners, listenersVector);
     m_newListeners.clear();
     for (size_t i = 0; i < listenersVector.size(); ++i)
@@ -102,7 +102,7 @@ void DeviceOrientationController::removeAllListeners(DOMWindow* window)
 void DeviceOrientationController::didChangeDeviceOrientation(DeviceOrientation* orientation)
 {
     RefPtr<DeviceOrientationEvent> event = DeviceOrientationEvent::create(eventNames().deviceorientationEvent, orientation);
-    Vector<DOMWindow*> listenersVector;
+    Vector<RefPtr<DOMWindow> > listenersVector;
     copyToVector(m_listeners, listenersVector);
     for (size_t i = 0; i < listenersVector.size(); ++i)
         listenersVector[i]->dispatchEvent(event);
index 4fa9006..5e06771 100644 (file)
@@ -55,9 +55,9 @@ private:
 
     Page* m_page;
     DeviceOrientationClient* m_client;
-    typedef HashCountedSet<DOMWindow*> ListenersCountedSet;
+    typedef HashCountedSet<RefPtr<DOMWindow> > ListenersCountedSet;
     ListenersCountedSet m_listeners;
-    typedef HashSet<DOMWindow*> ListenersSet;
+    typedef HashSet<RefPtr<DOMWindow> > ListenersSet;
     ListenersSet m_newListeners;
     Timer<DeviceOrientationController> m_timer;
 };
index 400d917..f01ae32 100644 (file)
@@ -2990,6 +2990,9 @@ void Document::styleSelectorChanged(StyleSelectorUpdateFlag updateFlag)
 
 void Document::addStyleSheetCandidateNode(Node* node, bool createdByParser)
 {
+    if (!node->inDocument())
+        return;
+    
     // Until the <body> exists, we have no choice but to compare document positions,
     // since styles outside of the body and head continue to be shunted into the head
     // (and thus can shift to end up before dynamically added DOM content that is also
index bc6ef24..42802ca 100644 (file)
@@ -58,6 +58,9 @@
 #include "TypingCommand.h"
 #include "htmlediting.h"
 #include "visible_units.h"
+#ifdef ANDROID_ALLOW_TURNING_OFF_CARET
+#include "WebViewCore.h"
+#endif
 #include <stdio.h>
 #include <wtf/text/CString.h>
 
@@ -1079,6 +1082,10 @@ void SelectionController::invalidateCaretRect()
 
 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;
index 2ea16fb..182742e 100644 (file)
@@ -1869,6 +1869,11 @@ inline SearchBuffer::SearchBuffer(const String& target, bool isCaseSensitive)
 
 inline SearchBuffer::~SearchBuffer()
 {
+    // Leave the static object pointing to a valid string.
+    UErrorCode status = U_ZERO_ERROR;
+    usearch_setPattern(WebCore::searcher(), &newlineCharacter, 1, &status);
+    ASSERT(status == U_ZERO_ERROR);
+
     unlockSearcher();
 }
 
index 34b54a1..2c1ffb3 100644 (file)
@@ -60,6 +60,8 @@ HistoryItem::HistoryItem()
     , m_visitCount(0)
     , m_itemSequenceNumber(generateSequenceNumber())
     , m_documentSequenceNumber(generateSequenceNumber())
+    , m_next(0)
+    , m_prev(0)
 {
 }
 
@@ -74,6 +76,8 @@ HistoryItem::HistoryItem(const String& urlString, const String& title, double ti
     , m_visitCount(0)
     , m_itemSequenceNumber(generateSequenceNumber())
     , m_documentSequenceNumber(generateSequenceNumber())
+    , m_next(0)
+    , m_prev(0)
 {    
     iconDatabase()->retainIconForPageURL(m_urlString);
 }
@@ -90,6 +94,8 @@ HistoryItem::HistoryItem(const String& urlString, const String& title, const Str
     , m_visitCount(0)
     , m_itemSequenceNumber(generateSequenceNumber())
     , m_documentSequenceNumber(generateSequenceNumber())
+    , m_next(0)
+    , m_prev(0)
 {
     iconDatabase()->retainIconForPageURL(m_urlString);
 }
@@ -107,6 +113,8 @@ HistoryItem::HistoryItem(const KURL& url, const String& target, const String& pa
     , m_visitCount(0)
     , m_itemSequenceNumber(generateSequenceNumber())
     , m_documentSequenceNumber(generateSequenceNumber())
+    , m_next(0)
+    , m_prev(0)
 {    
     iconDatabase()->retainIconForPageURL(m_urlString);
 }
@@ -159,6 +167,38 @@ PassRefPtr<HistoryItem> HistoryItem::copy() const
     return adoptRef(new HistoryItem(*this));
 }
 
+void HistoryItem::reset()
+{
+    iconDatabase()->releaseIconForPageURL(m_urlString);
+
+    m_urlString = String();
+    m_originalURLString = String();
+    m_referrer = String();
+    m_target = String();
+    m_parent = String();
+    m_title = String();
+    m_displayTitle = String();
+
+    m_lastVisitedTime = 0;
+    m_lastVisitWasHTTPNonGet = false;
+
+    m_lastVisitWasFailure = false;
+    m_isTargetItem = false;
+    m_visitCount = 0;
+    m_dailyVisitCounts.clear();
+    m_weeklyVisitCounts.clear();
+
+    m_redirectURLs.clear();
+
+    m_itemSequenceNumber = generateSequenceNumber();
+
+    m_stateObject = 0;
+    m_documentSequenceNumber = generateSequenceNumber();
+
+    m_formData = 0;
+    m_formContentType = String();
+}
+
 const String& HistoryItem::urlString() const
 {
     return m_urlString;
index ef9ac23..285f3d7 100644 (file)
@@ -88,6 +88,9 @@ public:
     
     PassRefPtr<HistoryItem> copy() const;
     
+    // Resets the HistoryItem to its initial state, as returned by create().
+    void reset();
+    
     const String& originalURLString() const;
     const String& urlString() const;
     const String& title() const;
@@ -141,7 +144,7 @@ public:
 
     void setDocumentSequenceNumber(long long number) { m_documentSequenceNumber = number; }
     long long documentSequenceNumber() const { return m_documentSequenceNumber; }
-    
+
     void setFormInfoFromRequest(const ResourceRequest&);
     void setFormData(PassRefPtr<FormData>);
     void setFormContentType(const String&);
@@ -251,11 +254,19 @@ private:
 
     OwnPtr<Vector<String> > m_redirectURLs;
 
+    // If two HistoryItems have the same item sequence number, then they are
+    // clones of one another.  Traversing history from one such HistoryItem to
+    // another is a no-op.  HistoryItem clones are created for parent and
+    // sibling frames when only a subframe navigates.
     long long m_itemSequenceNumber;
 
+    // If two HistoryItems have the same document sequence number, then they
+    // refer to the same instance of a document.  Traversing history from one
+    // such HistoryItem to another preserves the document.
+    long long m_documentSequenceNumber;
+
     // Support for HTML5 History
     RefPtr<SerializedScriptValue> m_stateObject;
-    long long m_documentSequenceNumber;
     
     // info used to repost form data
     RefPtr<FormData> m_formData;
index daf4b93..88b47ac 100644 (file)
@@ -162,7 +162,6 @@ void HTMLFormControlElement::willMoveToNewOwnerDocument()
 void HTMLFormControlElement::insertedIntoTree(bool deep)
 {
     if (fastHasAttribute(formAttr)) {
-        document()->registerFormElementWithFormAttribute(this);
         Element* element = document()->getElementById(fastGetAttribute(formAttr));
         if (element && element->hasTagName(formTag)) {
             if (m_form)
@@ -196,9 +195,6 @@ static inline Node* findRoot(Node* n)
 
 void HTMLFormControlElement::removedFromTree(bool deep)
 {
-    if (fastHasAttribute(formAttr))
-        document()->unregisterFormElementWithFormAttribute(this);
-
     // If the form and element are both in the same tree, preserve the connection to the form.
     // Otherwise, null out our form and remove ourselves from the form's list of elements.
     if (m_form && findRoot(this) != findRoot(m_form)) {
@@ -209,6 +205,20 @@ void HTMLFormControlElement::removedFromTree(bool deep)
     HTMLElement::removedFromTree(deep);
 }
 
+void HTMLFormControlElement::insertedIntoDocument()
+{
+    if (fastHasAttribute(formAttr))
+        document()->registerFormElementWithFormAttribute(this);
+    HTMLElement::insertedIntoDocument();
+}
+
+void HTMLFormControlElement::removedFromDocument()
+{
+    if (fastHasAttribute(formAttr))
+        document()->unregisterFormElementWithFormAttribute(this);
+    HTMLElement::removedFromDocument();
+}
+
 const AtomicString& HTMLFormControlElement::formControlName() const
 {
     const AtomicString& name = fastGetAttribute(nameAttr);
index c5ed013..f006e65 100644 (file)
@@ -109,6 +109,8 @@ protected:
     virtual void attach();
     virtual void insertedIntoTree(bool deep);
     virtual void removedFromTree(bool deep);
+    virtual void insertedIntoDocument();
+    virtual void removedFromDocument();
     virtual void willMoveToNewOwnerDocument();
 
     virtual bool isKeyboardFocusable(KeyboardEvent*) const;
index deac66a..c1791d7 100644 (file)
 #include "HTMLFormControlElement.h"
 #include "OptionElement.h"
 
-#if PLATFORM(ANDROID)
-namespace android {
-class WebViewCore;
-class ListBoxReply;
-};
-#endif
-
 namespace WebCore {
 
 class HTMLSelectElement;
@@ -41,11 +34,6 @@ class HTMLSelectElement;
 class HTMLOptionElement : public HTMLFormControlElement, public OptionElement {
     friend class HTMLSelectElement;
     friend class RenderMenuList;
-#if PLATFORM(ANDROID)
-    friend class RenderThemeAndroid;
-    friend class android::WebViewCore;
-    friend class android::ListBoxReply;
-#endif
 
 public:
     static PassRefPtr<HTMLOptionElement> create(Document*, HTMLFormElement*);
index 0681341..1c76c28 100755 (executable)
@@ -75,7 +75,7 @@ private:
     DataView(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned byteLength);
 
     template<typename T>
-    inline bool beyondRange(unsigned byteOffset) const { return byteOffset + sizeof(T) > m_byteLength; }
+    inline bool beyondRange(unsigned byteOffset) const { return byteOffset >= m_byteLength || byteOffset + sizeof(T) > m_byteLength; }
 
     template<typename T>
     T getData(unsigned byteOffset, bool littleEndian, ExceptionCode&) const;
index 3dd1453..237d80c 100644 (file)
@@ -1146,6 +1146,11 @@ void WebGLRenderingContext::drawElements(unsigned long mode, long count, unsigne
     if (!count)
         return;
 
+    if (!m_boundElementArrayBuffer) {
+        m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+        return;
+    }
+
     long numElements = 0;
     if (!isErrorGeneratedOnOutOfBoundsAccesses()) {
         // Ensure we have a valid rendering state
index ff733a9..0919a59 100644 (file)
@@ -248,6 +248,10 @@ void HistoryController::updateForBackForwardNavigation()
     // Must grab the current scroll position before disturbing it
     if (!m_frameLoadComplete)
         saveScrollPositionAndViewStateToItem(m_previousItem.get());
+
+    // When traversing history, we may end up redirecting to a different URL
+    // this time (e.g., due to cookies).  See http://webkit.org/b/49654.
+    updateCurrentItem();
 }
 
 void HistoryController::updateForReload()
@@ -262,11 +266,11 @@ void HistoryController::updateForReload()
     
         if (m_frame->loader()->loadType() == FrameLoadTypeReload || m_frame->loader()->loadType() == FrameLoadTypeReloadFromOrigin)
             saveScrollPositionAndViewStateToItem(m_currentItem.get());
-    
-        // Sometimes loading a page again leads to a different result because of cookies. Bugzilla 4072
-        if (m_frame->loader()->documentLoader()->unreachableURL().isEmpty())
-            m_currentItem->setURL(m_frame->loader()->documentLoader()->requestURL());
     }
+
+    // When reloading the page, we may end up redirecting to a different URL
+    // this time (e.g., due to cookies).  See http://webkit.org/b/4072.
+    updateCurrentItem();
 }
 
 // There are 3 things you might think of as "history", all of which are handled by these functions.
@@ -298,9 +302,9 @@ void HistoryController::updateForStandardLoad(HistoryUpdateType updateType)
             if (Page* page = m_frame->page())
                 page->setGlobalHistoryItem(needPrivacy ? 0 : page->backForward()->currentItem());
         }
-    } else if (frameLoader->documentLoader()->unreachableURL().isEmpty() && m_currentItem) {
-        m_currentItem->setURL(frameLoader->documentLoader()->url());
-        m_currentItem->setFormInfoFromRequest(frameLoader->documentLoader()->request());
+    } else {
+        // The client redirect replaces the current history item.
+        updateCurrentItem();
     }
 
     if (!historyURL.isEmpty() && !needPrivacy) {
@@ -337,14 +341,12 @@ void HistoryController::updateForRedirectWithLockedBackForwardList()
                     page->setGlobalHistoryItem(needPrivacy ? 0 : page->backForward()->currentItem());
             }
         }
-        if (m_currentItem) {
-            m_currentItem->setURL(m_frame->loader()->documentLoader()->url());
-            m_currentItem->setFormInfoFromRequest(m_frame->loader()->documentLoader()->request());
-        }
+        // The client redirect replaces the current history item.
+        updateCurrentItem();
     } else {
         Frame* parentFrame = m_frame->tree()->parent();
         if (parentFrame && parentFrame->loader()->history()->m_currentItem)
-            parentFrame->loader()->history()->m_currentItem->setChildItem(createItem(true));
+            parentFrame->loader()->history()->m_currentItem->setChildItem(createItem());
     }
 
     if (!historyURL.isEmpty() && !needPrivacy) {
@@ -453,12 +455,13 @@ void HistoryController::setProvisionalItem(HistoryItem* item)
     m_provisionalItem = item;
 }
 
-PassRefPtr<HistoryItem> HistoryController::createItem(bool useOriginal)
+void HistoryController::initializeItem(HistoryItem* item)
 {
     DocumentLoader* documentLoader = m_frame->loader()->documentLoader();
-    
-    KURL unreachableURL = documentLoader ? documentLoader->unreachableURL() : KURL();
-    
+    ASSERT(documentLoader);
+
+    KURL unreachableURL = documentLoader->unreachableURL();
+
     KURL url;
     KURL originalURL;
 
@@ -466,15 +469,10 @@ PassRefPtr<HistoryItem> HistoryController::createItem(bool useOriginal)
         url = unreachableURL;
         originalURL = unreachableURL;
     } else {
-        originalURL = documentLoader ? documentLoader->originalURL() : KURL();
-        if (useOriginal)
-            url = originalURL;
-        else if (documentLoader)
-            url = documentLoader->requestURL();
+        url = documentLoader->url();
+        originalURL = documentLoader->originalURL();
     }
 
-    LOG(History, "WebCoreHistory: Creating item for %s", url.string().ascii().data());
-    
     // Frames that have never successfully loaded any content
     // may have no URL at all. Currently our history code can't
     // deal with such things, so we nip that in the bud here.
@@ -487,21 +485,25 @@ PassRefPtr<HistoryItem> HistoryController::createItem(bool useOriginal)
     
     Frame* parentFrame = m_frame->tree()->parent();
     String parent = parentFrame ? parentFrame->tree()->uniqueName() : "";
-    String title = documentLoader ? documentLoader->title() : "";
+    String title = documentLoader->title();
 
-    RefPtr<HistoryItem> item = HistoryItem::create(url, m_frame->tree()->uniqueName(), parent, title);
+    item->setURL(url);
+    item->setTarget(m_frame->tree()->uniqueName());
+    item->setParent(parent);
+    item->setTitle(title);
     item->setOriginalURLString(originalURL.string());
 
-    if (!unreachableURL.isEmpty() || !documentLoader || documentLoader->response().httpStatusCode() >= 400)
+    if (!unreachableURL.isEmpty() || documentLoader->response().httpStatusCode() >= 400)
         item->setLastVisitWasFailure(true);
 
     // Save form state if this is a POST
-    if (documentLoader) {
-        if (useOriginal)
-            item->setFormInfoFromRequest(documentLoader->originalRequest());
-        else
-            item->setFormInfoFromRequest(documentLoader->request());
-    }
+    item->setFormInfoFromRequest(documentLoader->request());
+}
+
+PassRefPtr<HistoryItem> HistoryController::createItem()
+{
+    RefPtr<HistoryItem> item = HistoryItem::create();
+    initializeItem(item.get());
     
     // Set the item for which we will save document state
     m_frameLoadComplete = false;
@@ -513,7 +515,7 @@ PassRefPtr<HistoryItem> HistoryController::createItem(bool useOriginal)
 
 PassRefPtr<HistoryItem> HistoryController::createItemTree(Frame* targetFrame, bool clipAtTarget)
 {
-    RefPtr<HistoryItem> bfItem = createItem(m_frame->tree()->parent() ? true : false);
+    RefPtr<HistoryItem> bfItem = createItem();
     if (!m_frameLoadComplete)
         saveScrollPositionAndViewStateToItem(m_previousItem.get());
 
@@ -647,6 +649,31 @@ void HistoryController::updateBackForwardListClippedAtTarget(bool doClip)
     page->backForward()->addItem(topItem.release());
 }
 
+void HistoryController::updateCurrentItem()
+{
+    if (!m_currentItem)
+        return;
+
+    DocumentLoader* documentLoader = m_frame->loader()->documentLoader();
+
+    if (!documentLoader->unreachableURL().isEmpty())
+        return;
+
+    if (m_currentItem->url() != documentLoader->url()) {
+        // We ended up on a completely different URL this time, so the HistoryItem
+        // needs to be re-initialized.  Preserve the isTargetItem flag as it is a
+        // property of how this HistoryItem was originally created and is not
+        // dependent on the document.
+        bool isTargetItem = m_currentItem->isTargetItem();
+        m_currentItem->reset();
+        initializeItem(m_currentItem.get());
+        m_currentItem->setIsTargetItem(isTargetItem);
+    } else {
+        // Even if the final URL didn't change, the form data may have changed.
+        m_currentItem->setFormInfoFromRequest(documentLoader->request());
+    }
+}
+
 void HistoryController::pushState(PassRefPtr<SerializedScriptValue> stateObject, const String& title, const String& urlString)
 {
     if (!m_currentItem)
index 1bf5072..01f093c 100644 (file)
@@ -84,12 +84,14 @@ public:
     void replaceState(PassRefPtr<SerializedScriptValue>, const String& title, const String& url);
 
 private:
-    PassRefPtr<HistoryItem> createItem(bool useOriginal);
+    void initializeItem(HistoryItem*);
+    PassRefPtr<HistoryItem> createItem();
     PassRefPtr<HistoryItem> createItemTree(Frame* targetFrame, bool clipAtTarget);
 
     void recursiveGoToItem(HistoryItem*, HistoryItem*, FrameLoadType);
     bool currentFramesMatchItem(HistoryItem*) const;
     void updateBackForwardListClippedAtTarget(bool doClip);
+    void updateCurrentItem();
 
     Frame* m_frame;
 
index 22e1355..17b4c3d 100644 (file)
@@ -867,7 +867,7 @@ void DOMWindow::blur()
     page->chrome()->unfocus();
 }
 
-void DOMWindow::close()
+void DOMWindow::close(ScriptExecutionContext* context)
 {
     if (!m_frame)
         return;
@@ -879,6 +879,16 @@ void DOMWindow::close()
     if (m_frame != page->mainFrame())
         return;
 
+    if (context) {
+        ASSERT(WTF::isMainThread());
+        Frame* activeFrame = static_cast<Document*>(context)->frame();
+        if (!activeFrame)
+            return;
+
+        if (!activeFrame->loader()->shouldAllowNavigation(m_frame))
+            return;
+    }
+
     Settings* settings = m_frame->settings();
     bool allowScriptsToCloseWindows = settings && settings->allowScriptsToCloseWindows();
 
index 68b21ff..d0a6cce 100644 (file)
@@ -147,7 +147,7 @@ namespace WebCore {
 
         void focus();
         void blur();
-        void close();
+        void close(ScriptExecutionContext* = 0);
         void print();
         void stop();
 
index 602289b..fe12287 100644 (file)
@@ -65,7 +65,7 @@ module window {
 
         [DoNotCheckDomainSecurity] void focus();
         [DoNotCheckDomainSecurity] void blur();
-        [DoNotCheckDomainSecurity] void close();
+        [DoNotCheckDomainSecurity, CallWith=ScriptExecutionContext] void close();
 
         void print();
         void stop();
index 5314a32..1f03599 100644 (file)
@@ -1067,6 +1067,29 @@ void FrameView::removeFixedObject()
         updateCanBlitOnScrollRecursively();
 }
 
+#if PLATFORM(ANDROID)
+// When the screen size change, fixed positioned element should be updated.
+void FrameView::updatePositionedObjects()
+{
+    RenderBlock::PositionedObjectsListHashSet* positionedObjects = 0;
+    if (RenderView* root = m_frame->contentRenderer())
+        positionedObjects = root->positionedObjects();
+
+    if (!positionedObjects || positionedObjects->isEmpty())
+        return;
+
+    RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
+    for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
+        RenderBox* renderBox = *it;
+        if (renderBox->style()->position() != FixedPosition)
+            continue;
+
+        renderBox->computeLogicalWidth();
+        renderBox->computeLogicalHeight();
+    }
+}
+#endif
+
 bool FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
 {
     const size_t fixedObjectThreshold = 5;
index 1b5b322..4135045 100644 (file)
@@ -97,6 +97,10 @@ public:
 
     bool needsFullRepaint() const { return m_doFullRepaint; }
 
+#if PLATFORM(ANDROID)
+    void updatePositionedObjects();
+#endif
+
 #if USE(ACCELERATED_COMPOSITING)
     void updateCompositingLayers();
 
index 95b1350..f0a75fe 100644 (file)
@@ -27,6 +27,7 @@
 #include "History.h"
 
 #include "BackForwardController.h"
+#include "Document.h"
 #include "ExceptionCode.h"
 #include "Frame.h"
 #include "FrameLoader.h"
@@ -62,22 +63,44 @@ unsigned History::length() const
 
 void History::back()
 {
-    if (!m_frame)
-        return;
-    m_frame->navigationScheduler()->scheduleHistoryNavigation(-1);
+    go(-1);
+}
+
+void History::back(ScriptExecutionContext* context)
+{
+    go(context, -1);
 }
 
 void History::forward()
 {
+    go(1);
+}
+
+void History::forward(ScriptExecutionContext* context)
+{
+    go(context, 1);
+}
+
+void History::go(int distance)
+{
     if (!m_frame)
         return;
-    m_frame->navigationScheduler()->scheduleHistoryNavigation(1);
+    m_frame->navigationScheduler()->scheduleHistoryNavigation(distance);
 }
 
-void History::go(int distance)
+void History::go(ScriptExecutionContext* context, int distance)
 {
     if (!m_frame)
         return;
+
+    ASSERT(WTF::isMainThread());
+    Frame* activeFrame = static_cast<Document*>(context)->frame();
+    if (!activeFrame)
+        return;
+
+    if (!activeFrame->loader()->shouldAllowNavigation(m_frame))
+        return;
+
     m_frame->navigationScheduler()->scheduleHistoryNavigation(distance);
 }
 
index e885847..9ec1914 100644 (file)
@@ -34,6 +34,7 @@
 namespace WebCore {
 
 class Frame;
+class ScriptExecutionContext;
 class SerializedScriptValue;
 typedef int ExceptionCode;
 
@@ -49,6 +50,10 @@ public:
     void forward();
     void go(int distance);
 
+    void back(ScriptExecutionContext*);
+    void forward(ScriptExecutionContext*);
+    void go(ScriptExecutionContext*, int distance);
+
     enum StateObjectType {
         StateObjectPush,
         StateObjectReplace
index d1be5ae..d8eac60 100644 (file)
@@ -37,9 +37,9 @@ module window {
     ] History {
         readonly attribute unsigned long length;
 
-        [DoNotCheckDomainSecurity] void back();
-        [DoNotCheckDomainSecurity] void forward();
-        [DoNotCheckDomainSecurity] void go(in long distance);
+        [DoNotCheckDomainSecurity, CallWith=ScriptExecutionContext] void back();
+        [DoNotCheckDomainSecurity, CallWith=ScriptExecutionContext] void forward();
+        [DoNotCheckDomainSecurity, CallWith=ScriptExecutionContext] void go(in long distance);
         
         [Custom, EnabledAtRuntime] void pushState(in any data, in DOMString title, in optional DOMString url)
             raises(DOMException);
index e8e990c..613aee6 100644 (file)
@@ -145,16 +145,16 @@ void AnimationControllerPrivate::fireEventsAndUpdateStyle()
     bool updateStyle = !m_eventsToDispatch.isEmpty() || !m_nodeChangesToDispatch.isEmpty();
     
     // fire all the events
-    Vector<EventToDispatch>::const_iterator eventsToDispatchEnd = m_eventsToDispatch.end();
-    for (Vector<EventToDispatch>::const_iterator it = m_eventsToDispatch.begin(); it != eventsToDispatchEnd; ++it) {
+    Vector<EventToDispatch> eventsToDispatch = m_eventsToDispatch;
+    m_eventsToDispatch.clear();
+    Vector<EventToDispatch>::const_iterator eventsToDispatchEnd = eventsToDispatch.end();
+    for (Vector<EventToDispatch>::const_iterator it = eventsToDispatch.begin(); it != eventsToDispatchEnd; ++it) {
         if (it->eventType == eventNames().webkitTransitionEndEvent)
             it->element->dispatchEvent(WebKitTransitionEvent::create(it->eventType, it->name, it->elapsedTime));
         else
             it->element->dispatchEvent(WebKitAnimationEvent::create(it->eventType, it->name, it->elapsedTime));
     }
     
-    m_eventsToDispatch.clear();
-    
     // call setChanged on all the elements
     Vector<RefPtr<Node> >::const_iterator nodeChangesToDispatchEnd = m_nodeChangesToDispatch.end();
     for (Vector<RefPtr<Node> >::const_iterator it = m_nodeChangesToDispatch.begin(); it != nodeChangesToDispatchEnd; ++it)
index 3f559d5..faa823e 100644 (file)
@@ -149,8 +149,8 @@ public:
     static int memoryUsageMB();
     static int actualMemoryUsageMB();
 
-    static int visibleScreenWidth(const FrameView*);
-    static int visibleScreenHeight(const FrameView*);
+    static int screenWidthInDocCoord(const FrameView*);
+    static int screenHeightInDocCoord(const FrameView*);
 };
 
 }
index 2bae724..f4c351f 100644 (file)
@@ -31,7 +31,7 @@
 
 class PopupReply : public android::WebCoreReply {
 public:
-    PopupReply(const IntRect& rect, android::WebViewCore* view, PopupMenuClient* client)
+    PopupReply(const IntRect& rect, android::WebViewCore* view, ListPopupMenuClient* client)
         : m_rect(rect)
         , m_viewImpl(view)
         , m_popupClient(client)
@@ -53,9 +53,23 @@ public:
             m_viewImpl->contentInvalidate(m_rect);
     }
 
-    virtual void replyIntArray(const int*, int) {
-        // Should never be called.
-        SkASSERT(false);
+    virtual void replyIntArray(const int* values, int count)
+    {
+        if (m_popupClient) {
+            m_popupClient->popupDidHide();
+            if (0 == count) {
+                m_popupClient->valueChanged(-1, true);
+            } else {
+                for (int i = 0; i < count; i++) {
+                    m_popupClient->listBoxSelectItem(values[i],
+                        i != 0 /* allowMultiplySelection */,
+                        false /* shift */,
+                        i == count - 1 /* fireOnChangeNow */);
+                }
+            }
+        }
+        if (m_viewImpl)
+            m_viewImpl->contentInvalidate(m_rect);
     }
 
     void disconnectClient()
@@ -67,12 +81,12 @@ private:
     IntRect m_rect;
     // FIXME: Do not need this if we handle ChromeClientAndroid::formStateDidChange
     android::WebViewCore* m_viewImpl;
-    PopupMenuClient* m_popupClient;
+    ListPopupMenuClient* m_popupClient;
 };
 
 namespace WebCore {
 
-PopupMenuAndroid::PopupMenuAndroid(PopupMenuClient* menuList)
+PopupMenuAndroid::PopupMenuAndroid(ListPopupMenuClient* menuList)
     : m_popupClient(menuList)
     , m_reply(0)
 {
@@ -91,8 +105,7 @@ void PopupMenuAndroid::disconnectClient()
         m_reply = 0;
     }
 }
-// Copied from WebViewCore.cpp.  Once we move ListBox handling to this class,
-// we can remove the one in WebViewCore.cpp.
+
 // Convert a WTF::String into an array of characters where the first
 // character represents the length, for easy conversion to java.
 static uint16_t* stringConverter(const WTF::String& text)
@@ -122,9 +135,7 @@ void PopupMenuAndroid::show(const IntRect& rect, FrameView* frameView, int)
     SkTDArray<int> enabledArray;
     SkTDArray<int> selectedArray;
     int size = m_popupClient->listSize();
-    // If we use this for ListBoxes in addition to MenuLists, we will need to
-    // account for 'multiple'
-    bool multiple = false;
+    bool multiple = m_popupClient->multiple();
     for (int i = 0; i < size; i++) {
         *names.append() = stringConverter(m_popupClient->itemText(i));
         if (m_popupClient->itemIsSeparator(i)) {
index 48bce44..6c2c015 100644 (file)
@@ -34,18 +34,18 @@ class PopupReply;
 namespace WebCore {
 
 class FrameView;
-class PopupMenuClient;
+class ListPopupMenuClient;
 
 class PopupMenuAndroid : public PopupMenu {
 public:
-    PopupMenuAndroid(PopupMenuClient*);
+    PopupMenuAndroid(ListPopupMenuClient*);
     virtual ~PopupMenuAndroid();
     virtual void show(const IntRect&, FrameView*, int);
     virtual void hide() { }
     virtual void updateFromElement() { }
     virtual void disconnectClient();
 private:
-    PopupMenuClient* m_popupClient;
+    ListPopupMenuClient* m_popupClient;
     PopupReply* m_reply;
 };
 
index 87e7a6d..66f034d 100644 (file)
@@ -52,9 +52,15 @@ namespace WebCore {
 // dropdowns, we want a much smaller height, which encompasses the text.
 const int listboxPadding = 5;
 
-// This is the color of selection in a textfield.  It was obtained by checking
-// the color of selection in TextViews in the system.
-const RGBA32 selectionColor = makeRGB(255, 146, 0);
+// This is the color of selection in a textfield.  It was computed from
+// frameworks/base/core/res/res/values/colors.xml, which uses #9983CC39
+// (decimal a = 153, r = 131, g = 204, b = 57)
+// for all four highlighted text values. Blending this with white yields:
+// R = (131 * 153 + 255 * (255 - 153)) / 255  -> 180.6
+// G = (204 * 153 + 255 * (255 - 153)) / 255  -> 224.4
+// B = ( 57 * 153 + 255 * (255 - 153)) / 255  -> 136.2
+
+const RGBA32 selectionColor = makeRGB(181, 224, 136);
 
 static SkCanvas* getCanvasFromInfo(const PaintInfo& info)
 {
@@ -351,57 +357,9 @@ void RenderThemeAndroid::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle* sty
 
 bool RenderThemeAndroid::paintTextArea(RenderObject* obj, const PaintInfo& info, const IntRect& rect)
 {
-    if (!obj->isListBox())
-        return true;
-
-    paintCombo(obj, info, rect);
-    RenderStyle* style = obj->style();
-    if (style)
-        style->setColor(Color::transparent);
-    Node* node = obj->node();
-    if (!node || !node->hasTagName(HTMLNames::selectTag))
-        return true;
-
-    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node);
-    // The first item may be visible.  Make sure it does not draw.
-    // If it has a style, it overrides the RenderListBox's style, so we
-    // need to make sure both are set to transparent.
-    node = select->item(0);
-    if (node) {
-        RenderObject* renderer = node->renderer();
-        if (renderer) {
-            RenderStyle* renderStyle = renderer->style();
-            if (renderStyle)
-                renderStyle->setColor(Color::transparent);
-        }
-    }
-    // Find the first selected option, and draw its text.
-    // FIXME: In a later change, if there is more than one item selected,
-    // draw a string that says "X items" like iPhone Safari does
-    int index = select->selectedIndex();
-    node = select->item(index);
-    if (!node || !node->hasTagName(HTMLNames::optionTag))
-        return true;
-
-    HTMLOptionElement* option = static_cast<HTMLOptionElement*>(node);
-    String label = option->textIndentedToRespectGroupLabel();
-    SkRect r(rect);
-
-    SkPaint paint;
-    paint.setAntiAlias(true);
-    paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
-    // Values for text size and positioning determined by trial and error
-    paint.setTextSize(r.height() - SkIntToScalar(6));
-
-    SkCanvas* canvas = getCanvasFromInfo(info);
-    int saveCount = canvas->save();
-    r.fRight -= SkIntToScalar(RenderSkinCombo::extraWidth());
-    canvas->clipRect(r);
-    canvas->drawText(label.characters(), label.length() << 1,
-             r.fLeft + SkIntToScalar(5), r.fBottom - SkIntToScalar(5), paint);
-    canvas->restoreToCount(saveCount);
-
-    return true;    
+    if (obj->isMenuList())
+        paintCombo(obj, info, rect);
+    return true;
 }
 
 void RenderThemeAndroid::adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
@@ -414,16 +372,7 @@ bool RenderThemeAndroid::paintSearchField(RenderObject*, const PaintInfo&, const
     return true;    
 }
 
-void RenderThemeAndroid::adjustListboxStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
-{
-    style->setPaddingRight(Length(RenderSkinCombo::extraWidth(), Fixed));
-    style->setMaxHeight(Length(style->fontSize() + listboxPadding, Fixed));
-    // Make webkit draw invisible, since it will simply draw the first element
-    style->setColor(Color::transparent);
-    addIntrinsicMargins(style);
-}
-
-static void adjustMenuListStyleCommon(RenderStyle* style, Element* e)
+static void adjustMenuListStyleCommon(RenderStyle* style)
 {
     // Added to make room for our arrow and make the touch target less cramped.
     style->setPaddingLeft(Length(RenderSkinCombo::padding(), Fixed));
@@ -432,9 +381,14 @@ static void adjustMenuListStyleCommon(RenderStyle* style, Element* e)
     style->setPaddingRight(Length(RenderSkinCombo::extraWidth(), Fixed));
 }
 
+void RenderThemeAndroid::adjustListboxStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+    adjustMenuListButtonStyle(0, style, 0);
+}
+
 void RenderThemeAndroid::adjustMenuListStyle(CSSStyleSelector*, RenderStyle* style, Element* e) const
 {
-    adjustMenuListStyleCommon(style, e);
+    adjustMenuListStyleCommon(style);
     addIntrinsicMargins(style);
 }
 
@@ -450,7 +404,8 @@ bool RenderThemeAndroid::paintMenuList(RenderObject* obj, const PaintInfo& info,
     return paintCombo(obj, info, rect);
 }
 
-void RenderThemeAndroid::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* style, Element* e) const
+void RenderThemeAndroid::adjustMenuListButtonStyle(CSSStyleSelector*,
+        RenderStyle* style, Element*) const
 {
     // Copied from RenderThemeSafari.
     const float baseFontSize = 11.0f;
@@ -468,7 +423,7 @@ void RenderThemeAndroid::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyl
     const int padding = 4;
     style->setPaddingTop(Length(padding, Fixed));
     style->setPaddingLeft(Length(padding, Fixed));
-    adjustMenuListStyleCommon(style, e);
+    adjustMenuListStyleCommon(style);
 }
 
 bool RenderThemeAndroid::paintMenuListButton(RenderObject* obj, const PaintInfo& info, const IntRect& rect) 
index dcefa9b..2166e9d 100644 (file)
@@ -116,12 +116,11 @@ void BaseLayerAndroid::drawCanvas(SkCanvas* canvas)
 }
 
 #if USE(ACCELERATED_COMPOSITING)
-bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale)
+bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale, double currentTime)
 {
     if (!m_glWebViewState)
         return false;
 
-    double currentTime = WTF::currentTime();
     bool goingDown = m_previousVisible.fTop - viewport.fTop <= 0;
     bool goingLeft = m_previousVisible.fLeft - viewport.fLeft >= 0;
 
@@ -282,7 +281,8 @@ bool BaseLayerAndroid::drawGL(IntRect& viewRect, SkRect& visibleRect,
     shader->setViewport(visibleRect);
     shader->resetBlending();
 
-    ret = drawBasePictureInGL(visibleRect, scale);
+    double currentTime = WTF::currentTime();
+    ret = drawBasePictureInGL(visibleRect, scale, currentTime);
 
     if (countChildren() >= 1) {
         LayerAndroid* compositedRoot = static_cast<LayerAndroid*>(getChild(0));
@@ -311,7 +311,7 @@ bool BaseLayerAndroid::drawGL(IntRect& viewRect, SkRect& visibleRect,
             scale = m_glWebViewState->futureScale();
         }
         compositedRoot->setScale(scale);
-        compositedRoot->computeTextureSize();
+        compositedRoot->computeTextureSize(currentTime);
         compositedRoot->reserveGLTextures();
 
 #ifdef DEBUG
@@ -338,12 +338,6 @@ bool BaseLayerAndroid::drawGL(IntRect& viewRect, SkRect& visibleRect,
     glBindBuffer(GL_ARRAY_BUFFER, 0);
     m_previousVisible = visibleRect;
 
-#ifdef DEBUG_COUNT
-    XLOG("GLWebViewState(%d) DoubleBufferedTexture(%d) BaseTile(%d) TileSet(%d) TiledPage(%d)",
-         GLWebViewState::count(), DoubleBufferedTexture::count(),
-         BaseTile::count(), TileSet::count(), TiledPage::count());
-#endif // DEBUG_COUNT
-
 #endif // USE(ACCELERATED_COMPOSITING)
 #ifdef DEBUG
     ClassTracker::instance()->show();
index c57b13d..cb1caef 100644 (file)
@@ -59,7 +59,7 @@ public:
     void swapExtra(BaseLayerAndroid* base) { m_extra.swap(base->m_extra); }
 private:
 #if USE(ACCELERATED_COMPOSITING)
-    bool drawBasePictureInGL(SkRect& viewport, float scale);
+    bool drawBasePictureInGL(SkRect& viewport, float scale, double currentTime);
 
     GLWebViewState* m_glWebViewState;
     android::Mutex m_drawLock;
index acb500d..9499870 100644 (file)
@@ -254,7 +254,27 @@ void BaseTile::paintBitmap()
     float w = tileWidth * invScale;
     float h = tileHeight * invScale;
 
-    SkCanvas* canvas = texture->canvas();
+    SkCanvas* canvas;
+
+#ifdef USE_SKIA_GPU
+    GLuint fboId;
+    glGenFramebuffersEXT(1, &fboId);
+    glBindFramebuffer(GL_FRAMEBUFFER, fboId);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureInfo->m_textureId, 0);
+    glCheckFramebufferStatus(GL_FRAMEBUFFER)); // should return GL_FRAMEBUFFER_COMPLETE
+
+    //Do I need to assign a width/height/format?
+
+    GrContext* context = gr_get_global_ctx();
+    context->resetContext();
+    GrRenderTarget* target = context->createPlatformRenderTarget(fboId, tileWidth, tileHeight);
+    SkCanvas tmpCanvas;
+    SkDevice* device = new SkGpuDevice(context, bm, target);
+    tmpCanvas.setDevice(device)->unref();
+    canvas = &tmpCanvas;
+#else
+    canvas = texture->canvas();
+#endif
 
     canvas->save();
     canvas->drawColor(tiledPage->glWebViewState()->getBackgroundColor());
@@ -265,21 +285,32 @@ void BaseTile::paintBitmap()
 
     canvas->restore();
 
-#ifdef DEBUG
-    SkPaint paint;
-    paint.setARGB(128, 255, 0, 0);
-    paint.setStrokeWidth(3);
-    canvas->drawLine(0, 0, tileWidth, tileHeight, paint);
-    paint.setARGB(128, 0, 255, 0);
-    canvas->drawLine(0, tileHeight, tileWidth, 0, paint);
-    paint.setARGB(128, 0, 0, 255);
-    canvas->drawLine(0, 0, tileWidth, 0, paint);
-    canvas->drawLine(tileWidth, 0, tileWidth, tileHeight, paint);
-    drawTileInfo(canvas, texture, x, y, scale);
-#endif
+    if (TilesManager::instance()->getShowVisualIndicator()) {
+        SkPaint paint;
+        paint.setARGB(128, 255, 0, 0);
+        paint.setStrokeWidth(3);
+        canvas->drawLine(0, 0, tileWidth, tileHeight, paint);
+        paint.setARGB(128, 0, 255, 0);
+        canvas->drawLine(0, tileHeight, tileWidth, 0, paint);
+        paint.setARGB(128, 0, 0, 255);
+        canvas->drawLine(0, 0, tileWidth, 0, paint);
+        canvas->drawLine(tileWidth, 0, tileWidth, tileHeight, paint);
+        drawTileInfo(canvas, texture, x, y, scale);
+    }
 
     texture->setTile(x, y);
+
+#ifdef USE_SKIA_GPU
+    // set the texture info w/h/format
+    textureInfo->m_width = tileWidth;
+    textureInfo->m_height = tileHeight;
+    texture->producerReleaseAndSwap();
+
+    glBindFramebuffer(GL_FRAMEBUFFER, 0); // rebind the standard FBO
+    glDeleteFramebuffers(1, &fboId);
+#else
     texture->producerUpdate(textureInfo);
+#endif
 
     m_atomicSync.lock();
     m_lastPaintedPicture = pictureCount;
index e17e532..4795d9e 100644 (file)
@@ -35,13 +35,13 @@ namespace WebCore {
 
 FontCustomPlatformData::FontCustomPlatformData(SkTypeface* face)
 {
-    face->safeRef();
+    SkSafeRef(face);
     m_typeface = face;
 }
 
 FontCustomPlatformData::~FontCustomPlatformData()
 {
-    m_typeface->safeUnref();
+    SkSafeUnref(m_typeface);
     // the unref is enough to release the font data...
 }
 
index 974b828..194bc62 100644 (file)
@@ -83,7 +83,7 @@ FontPlatformData::FontPlatformData()
 FontPlatformData::FontPlatformData(const FontPlatformData& src)
 {
     if (hashTableDeletedFontValue() != src.mTypeface) {
-        src.mTypeface->safeRef();
+        SkSafeRef(src.mTypeface);
     }
 
     mTypeface   = src.mTypeface;
@@ -101,7 +101,7 @@ FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold
     : mTypeface(tf), mTextSize(textSize), mFakeBold(fakeBold), mFakeItalic(fakeItalic)
 {
     if (hashTableDeletedFontValue() != mTypeface) {
-        mTypeface->safeRef();
+        SkSafeRef(mTypeface);
     }
 
     inc_count();
@@ -113,7 +113,7 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize)
       m_harfbuzzFace(src.m_harfbuzzFace)
 {
     if (hashTableDeletedFontValue() != mTypeface) {
-        mTypeface->safeRef();
+        SkSafeRef(mTypeface);
     }
 
     inc_count();
@@ -135,17 +135,17 @@ FontPlatformData::~FontPlatformData()
 #endif
 
     if (hashTableDeletedFontValue() != mTypeface) {
-        mTypeface->safeUnref();
+        SkSafeUnref(mTypeface);
     }
 }
 
 FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src)
 {
     if (hashTableDeletedFontValue() != src.mTypeface) {
-        src.mTypeface->safeRef();
+        SkSafeRef(src.mTypeface);
     }
     if (hashTableDeletedFontValue() != mTypeface) {
-        mTypeface->safeUnref();
+        SkSafeUnref(mTypeface);
     }
 
     mTypeface   = src.mTypeface;
index eef32e8..b3c5b02 100644 (file)
@@ -85,7 +85,7 @@ GLWebViewState::GLWebViewState(android::Mutex* buttonMutex)
 
 GLWebViewState::~GLWebViewState()
 {
-    m_currentBaseLayer->safeUnref();
+    SkSafeUnref(m_currentBaseLayer);
     delete m_tiledPageA;
     delete m_tiledPageB;
 #ifdef DEBUG_COUNT
@@ -93,7 +93,8 @@ GLWebViewState::~GLWebViewState()
 #endif
 }
 
-void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const IntRect& rect)
+void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const IntRect& rect,
+                                  bool showVisualIndicator)
 {
     android::Mutex::Autolock lock(m_baseLayerLock);
     if (!layer) {
@@ -109,18 +110,20 @@ void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const IntRect& rect)
     // We only update the layers if we are not currently
     // waiting for a tiledPage to be painted
     if (m_baseLayerUpdate) {
-        layer->safeRef();
-        m_currentBaseLayer->safeUnref();
+        SkSafeRef(layer);
+        SkSafeUnref(m_currentBaseLayer);
         m_currentBaseLayer = layer;
     }
     inval(rect);
+
+    TilesManager::instance()->setShowVisualIndicator(showVisualIndicator);
 }
 
 void GLWebViewState::unlockBaseLayerUpdate() {
     m_baseLayerUpdate = true;
     android::Mutex::Autolock lock(m_baseLayerLock);
-    m_baseLayer->safeRef();
-    m_currentBaseLayer->safeUnref();
+    SkSafeRef(m_baseLayer);
+    SkSafeUnref(m_currentBaseLayer);
     m_currentBaseLayer = m_baseLayer;
     inval(m_invalidateRect);
     IntRect empty;
@@ -128,7 +131,7 @@ void GLWebViewState::unlockBaseLayerUpdate() {
 }
 
 void GLWebViewState::setExtra(BaseLayerAndroid* layer, SkPicture& picture,
-    const IntRect& rect)
+    const IntRect& rect, bool allowSame)
 {
     android::Mutex::Autolock lock(m_baseLayerLock);
     if (!m_baseLayerUpdate)
@@ -136,7 +139,7 @@ void GLWebViewState::setExtra(BaseLayerAndroid* layer, SkPicture& picture,
 
     layer->setExtra(picture);
 
-    if (m_lastInval == rect)
+    if (!allowSame && m_lastInval == rect)
         return;
 
     if (!rect.isEmpty())
@@ -300,12 +303,12 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, float scale, SkColo
 {
     m_baseLayerLock.lock();
     BaseLayerAndroid* baseLayer = m_currentBaseLayer;
-    baseLayer->safeRef();
+    SkSafeRef(baseLayer);
     m_baseLayerLock.unlock();
     if (!baseLayer)
         return false;
     bool ret = baseLayer->drawGL(rect, viewport, scale, color);
-    baseLayer->safeUnref();
+    SkSafeUnref(baseLayer);
     return ret;
 }
 
index 4b71d86..d265b41 100644 (file)
@@ -168,8 +168,8 @@ public:
     void resetTransitionTime() { m_transitionTime = -1; }
 
     unsigned int paintBaseLayerContent(SkCanvas* canvas);
-    void setBaseLayer(BaseLayerAndroid* layer, const IntRect& rect);
-    void setExtra(BaseLayerAndroid*, SkPicture&, const IntRect&);
+    void setBaseLayer(BaseLayerAndroid* layer, const IntRect& rect, bool showVisualIndicator);
+    void setExtra(BaseLayerAndroid*, SkPicture&, const IntRect&, bool allowSame);
     void scheduleUpdate(const double& currentTime, const SkIRect& viewport, float scale);
 
     TiledPage* sibling(TiledPage* page);
@@ -205,12 +205,12 @@ public:
         return false;
     }
 
-    void setBackgroundColor(SkColor color) { m_backgroundColor = color; }
-    SkColor getBackgroundColor() { return m_backgroundColor; }
-
     bool drawGL(IntRect& rect, SkRect& viewport,
                 float scale, SkColor color = SK_ColorWHITE);
 
+    void setBackgroundColor(SkColor color) { m_backgroundColor = color; }
+    SkColor getBackgroundColor() { return m_backgroundColor; }
+
 private:
     void inval(const IntRect& rect); // caller must hold m_baseLayerLock
 
index 72ae336..b8dc9dd 100644 (file)
@@ -38,7 +38,7 @@
 class PlatformGradientRec {
 public:
     PlatformGradientRec() : m_shader(NULL) {}
-    ~PlatformGradientRec() { m_shader->safeUnref(); }
+    ~PlatformGradientRec() { SkSafeUnref(m_shader); }
 
     SkShader*           m_shader;
     SkShader::TileMode  m_tileMode;
@@ -102,7 +102,7 @@ SkShader* Gradient::getShader(SkShader::TileMode mode)
         s = new SkColorShader(0);
 
     // zap our previous shader, if present
-    m_gradient->m_shader->safeUnref();
+    SkSafeUnref(m_gradient->m_shader);
     m_gradient->m_shader = s;
     m_gradient->m_tileMode = mode;
     SkMatrix matrix = m_gradientSpaceTransformation;
index 06a53b1..dce7b27 100644 (file)
@@ -128,13 +128,13 @@ public:
             , useAA(other.useAA)
         {
             path = deepCopyPtr<SkPath>(other.path);
-            pathEffect->safeRef();
+            SkSafeRef(pathEffect);
         }
 
         ~State()
         {
             delete path;
-            pathEffect->safeUnref();
+            SkSafeUnref(pathEffect);
         }
 
         void setShadow(int radius, int dx, int dy, SkColor c)
@@ -1043,7 +1043,7 @@ void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
     for (unsigned int i = 0; i < count; i++)
         intervals[i] = SkFloatToScalar(dashes[i % dashLength]);
     SkPathEffect **effectPtr = &m_data->getState()->pathEffect;
-    (*effectPtr)->safeUnref();
+    SkSafeUnref(*effectPtr);
     *effectPtr = new SkDashPathEffect(intervals, count, SkFloatToScalar(dashOffset));
 
     delete[] intervals;
index e887964..48badf8 100644 (file)
@@ -122,8 +122,8 @@ GraphicsLayerAndroid::GraphicsLayerAndroid(GraphicsLayerClient* client) :
     m_foregroundLayer(0),
     m_foregroundClipLayer(0)
 {
-    m_contentLayer = new LayerAndroid(true);
     RenderLayer* renderLayer = renderLayerFromClient(m_client);
+    m_contentLayer = new LayerAndroid(renderLayer, true);
     if (renderLayer) {
         m_contentLayer->setIsRootLayer(renderLayer->isRootLayer()
             && !(renderLayer->renderer()->frame()->ownerElement()));
@@ -227,6 +227,9 @@ void GraphicsLayerAndroid::updateFixedPosition()
     RenderLayer* renderLayer = renderLayerFromClient(m_client);
     RenderView* view = static_cast<RenderView*>(renderLayer->renderer());
 
+    // We will need the Iframe flag in the LayerAndroid tree for fixed position
+    if (view && view->isRenderIFrame())
+        m_contentLayer->setIsIframe(true);
     // If we are a fixed position layer, just set it
     if (view->isPositioned() && view->style()->position() == FixedPosition) {
         // We need to get the passed CSS properties for the element
@@ -271,15 +274,24 @@ void GraphicsLayerAndroid::setPosition(const FloatPoint& point)
     if (point == m_position)
         return;
 
-    GraphicsLayer::setPosition(point);
+    FloatPoint pos(point);
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+    // Add the scroll position back in. When scrolling a layer, all the children
+    // are positioned based on the content scroll. Adding the scroll position
+    // back in allows the children to draw based on 0,0.
+    RenderLayer* layer = renderLayerFromClient(m_client);
+    if (layer && layer->parent() && layer->parent()->hasOverflowScroll())
+        pos += layer->parent()->scrolledContentOffset();
+#endif
+
+    GraphicsLayer::setPosition(pos);
 
 #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
-    updateFixedPosition();
-    m_contentLayer->setPosition(point.x(), point.y());
+    m_contentLayer->setPosition(pos.x(), pos.y());
     askForSync();
 }
 
@@ -310,7 +322,6 @@ void GraphicsLayerAndroid::setSize(const FloatSize& size)
     MLOG("(%x) setSize (%.2f,%.2f)", this, size.width(), size.height());
     GraphicsLayer::setSize(size);
     m_contentLayer->setSize(size.width(), size.height());
-    updateFixedPosition();
     askForSync();
 }
 
@@ -368,31 +379,6 @@ void GraphicsLayerAndroid::setDrawsContent(bool drawsContent)
     if (m_contentLayer->isRootLayer())
         return;
     if (m_drawsContent) {
-#if ENABLE(ANDROID_OVERFLOW_SCROLL)
-        RenderLayer* layer = renderLayerFromClient(m_client);
-        if (layer) {
-            if (layer->hasOverflowScroll() && !m_foregroundLayer) {
-                m_foregroundLayer = new ScrollableLayerAndroid();
-                m_foregroundClipLayer = new LayerAndroid(false);
-                m_foregroundClipLayer->setMasksToBounds(true);
-
-                m_foregroundClipLayer->addChild(m_foregroundLayer);
-                m_contentLayer->addChild(m_foregroundClipLayer);
-            } else if (layer->isRootLayer()
-                       && layer->renderer()->frame()->ownerRenderer()) {
-                // We have to do another check for scrollable content since an
-                // iframe might be compositing for other reasons.
-                FrameView* view = layer->renderer()->frame()->view();
-                if (view->hasOverflowScroll()) {
-                    // Replace the content layer with a scrollable layer.
-                    LayerAndroid* layer = new ScrollableLayerAndroid(*m_contentLayer);
-                    m_contentLayer->unref();
-                    m_contentLayer = layer;
-                }
-            }
-        }
-#endif
-
         m_haveContents = true;
         setNeedsDisplay();
     }
@@ -478,6 +464,77 @@ private:
     GraphicsLayerPaintingPhase m_originalPhase;
 };
 
+void GraphicsLayerAndroid::updateScrollingLayers()
+{
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+    RenderLayer* layer = renderLayerFromClient(m_client);
+    if (!layer || !m_haveContents)
+        return;
+    bool hasOverflowScroll = m_foregroundLayer || m_contentLayer->contentIsScrollable();
+    bool layerNeedsOverflow = layer->hasOverflowScroll();
+    bool iframeNeedsOverflow = layer->isRootLayer() &&
+        layer->renderer()->frame()->ownerRenderer() &&
+        layer->renderer()->frame()->view()->hasOverflowScroll();
+
+    if (hasOverflowScroll && (layerNeedsOverflow || iframeNeedsOverflow)) {
+        // Already has overflow layers.
+        return;
+    }
+    if (!hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow) {
+        // Does not need overflow layers.
+        return;
+    }
+    if (layerNeedsOverflow || iframeNeedsOverflow) {
+        ASSERT(!hasOverflowScroll);
+        if (layerNeedsOverflow) {
+            ASSERT(!m_foregroundLayer && !m_foregroundClipLayer);
+            m_foregroundLayer = new ScrollableLayerAndroid(layer);
+            m_foregroundClipLayer = new LayerAndroid(layer, false);
+            m_foregroundClipLayer->setMasksToBounds(true);
+            m_foregroundClipLayer->addChild(m_foregroundLayer);
+            m_contentLayer->addChild(m_foregroundClipLayer);
+        } else {
+            ASSERT(iframeNeedsOverflow && !m_contentLayer->contentIsScrollable());
+            // 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 ScrollableLayerAndroid(*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;
+            }
+        }
+        // Need to rebuild our children based on the new structure.
+        m_needsSyncChildren = true;
+    } else {
+        ASSERT(hasOverflowScroll && !layerNeedsOverflow && !iframeNeedsOverflow);
+        ASSERT(m_contentLayer);
+        // Remove the foreground layers.
+        if (m_foregroundLayer) {
+            m_foregroundLayer->unref();
+            m_foregroundLayer = 0;
+            m_foregroundClipLayer->unref();
+            m_foregroundClipLayer = 0;
+        }
+        // No need to copy over children.
+        m_contentLayer->removeChildren();
+        LayerAndroid* layer = new LayerAndroid(*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;
+    }
+#endif
+}
+
 bool GraphicsLayerAndroid::repaint()
 {
     LOG("(%x) repaint(), gPaused(%d) m_needsRepaint(%d) m_haveContents(%d) ",
@@ -506,8 +563,13 @@ bool GraphicsLayerAndroid::repaint()
             m_foregroundLayer->setSize(contentsRect.width(), contentsRect.height());
             // Paint everything else into the main recording canvas.
             phase.clear(GraphicsLayerPaintBackground);
-            if (!paintContext(m_foregroundLayer->recordContext(), contentsRect))
-                return false;
+
+            // Paint at 0,0.
+            IntSize scroll = layer->scrolledContentOffset();
+            layer->scrollToOffset(0, 0, true, false);
+            // At this point, it doesn't matter if painting failed.
+            (void) paintContext(m_foregroundLayer->recordContext(), contentsRect);
+            layer->scrollToOffset(scroll.width(), scroll.height(), true, false);
 
             // Construct the clip layer for masking the contents.
             IntRect clip = layer->renderer()->absoluteBoundingBoxRect();
@@ -830,10 +892,16 @@ void GraphicsLayerAndroid::syncChildren()
 {
     if (m_needsSyncChildren) {
         m_contentLayer->removeChildren();
-        if (m_foregroundClipLayer)
+        LayerAndroid* layer = m_contentLayer;
+        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++)
-            m_contentLayer->addChild(m_children[i]->platformLayer());
+            layer->addChild(m_children[i]->platformLayer());
         m_needsSyncChildren = false;
     }
 }
@@ -857,6 +925,8 @@ void GraphicsLayerAndroid::syncCompositingState()
     for (unsigned int i = 0; i < m_children.size(); i++)
         m_children[i]->syncCompositingState();
 
+    updateScrollingLayers();
+    updateFixedPosition();
     syncChildren();
     syncMask();
 
index ce6bac1..da247ca 100644 (file)
@@ -127,6 +127,7 @@ private:
     void syncMask();
 
     void updateFixedPosition();
+    void updateScrollingLayers();
 
     // with SkPicture, we always repaint the entire layer's content.
     bool repaint();
index 7e998c1..3706d20 100644 (file)
@@ -61,10 +61,11 @@ class OpacityDrawFilter : public SkDrawFilter {
 
 ///////////////////////////////////////////////////////////////////////////////
 
-LayerAndroid::LayerAndroid(bool isRootLayer) : SkLayer(),
+LayerAndroid::LayerAndroid(RenderLayer* owner, bool isRootLayer) : SkLayer(),
     m_isRootLayer(isRootLayer),
     m_haveClip(false),
     m_isFixed(false),
+    m_isIframe(false),
     m_preserves3D(false),
     m_anchorPointZ(0),
     m_recordingPicture(0),
@@ -75,13 +76,15 @@ LayerAndroid::LayerAndroid(bool isRootLayer) : SkLayer(),
     m_reservedTexture(0),
     m_pictureUsed(0),
     m_requestSent(false),
-    m_scale(1)
+    m_scale(1),
+    m_lastComputeTextureSize(0),
+    m_owningLayer(owner)
 {
     m_backgroundColor = 0;
 
     m_preserves3D = false;
     m_dirty = false;
-
+    m_iframeOffset.set(0,0);
 #ifdef DEBUG_COUNT
     ClassTracker::instance()->increment("LayerAndroid");
 #endif
@@ -90,15 +93,17 @@ LayerAndroid::LayerAndroid(bool isRootLayer) : SkLayer(),
 LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer),
     m_isRootLayer(layer.m_isRootLayer),
     m_haveClip(layer.m_haveClip),
+    m_isIframe(layer.m_isIframe),
     m_extra(0), // deliberately not copied
     m_uniqueId(layer.m_uniqueId),
     m_drawingTexture(0),
     m_reservedTexture(0),
-    m_requestSent(false)
+    m_requestSent(false),
+    m_owningLayer(layer.m_owningLayer)
 {
     m_isFixed = layer.m_isFixed;
     m_contentsImage = layer.m_contentsImage;
-    m_contentsImage->safeRef();
+    SkSafeRef(m_contentsImage);
     m_renderLayerPos = layer.m_renderLayerPos;
     m_transform = layer.m_transform;
     m_backgroundColor = layer.m_backgroundColor;
@@ -112,7 +117,7 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer),
     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);
 
@@ -123,6 +128,7 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer),
     m_dirty = layer.m_dirty;
     m_pictureUsed = layer.m_pictureUsed;
     m_scale = layer.m_scale;
+    m_lastComputeTextureSize = 0;
 
     for (int i = 0; i < layer.countChildren(); i++)
         addChild(layer.getChild(i)->copy())->unref();
@@ -140,6 +146,7 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(),
     m_isRootLayer(true),
     m_haveClip(false),
     m_isFixed(false),
+    m_isIframe(false),
     m_recordingPicture(picture),
     m_contentsImage(0),
     m_extra(0),
@@ -147,11 +154,14 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(),
     m_drawingTexture(0),
     m_reservedTexture(0),
     m_requestSent(false),
-    m_scale(1)
+    m_scale(1),
+    m_lastComputeTextureSize(0),
+    m_owningLayer(0)
 {
     m_backgroundColor = 0;
     m_dirty = false;
     SkSafeRef(m_recordingPicture);
+    m_iframeOffset.set(0,0);
 #ifdef DEBUG_COUNT
     ClassTracker::instance()->increment("LayerAndroid");
 #endif
@@ -189,8 +199,8 @@ LayerAndroid::~LayerAndroid()
     removeTexture(0);
     removeChildren();
     delete m_extra;
-    m_contentsImage->safeUnref();
-    m_recordingPicture->safeUnref();
+    SkSafeUnref(m_contentsImage);
+    SkSafeUnref(m_recordingPicture);
     m_animations.clear();
 #ifdef DEBUG_COUNT
     ClassTracker::instance()->decrement("LayerAndroid");
@@ -460,9 +470,31 @@ const LayerAndroid* LayerAndroid::find(int* xPtr, int* yPtr, SkPicture* root) co
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void LayerAndroid::updateFixedLayersPositions(const SkRect& viewport)
+void LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* parentIframeLayer)
 {
+    // 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) {
+        // 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;
@@ -494,7 +526,7 @@ void LayerAndroid::updateFixedLayersPositions(const SkRect& viewport)
 
     int count = this->countChildren();
     for (int i = 0; i < count; i++)
-        this->getChild(i)->updateFixedLayersPositions(viewport);
+        this->getChild(i)->updateFixedLayersPositions(viewport, parentIframeLayer);
 }
 
 void LayerAndroid::updatePositions()
@@ -651,8 +683,12 @@ static inline bool compareLayerFullSize(const LayerAndroid* a, const LayerAndroi
     return sizeA > sizeB;
 }
 
-void LayerAndroid::computeTextureSize()
+void LayerAndroid::computeTextureSize(double time)
 {
+   if (m_lastComputeTextureSize + s_computeTextureDelay > time)
+       return;
+   m_lastComputeTextureSize = time;
+
    // First, we collect the layers, computing m_layerTextureRect
    // as being clipped against the viewport
    Vector <LayerAndroid*> layers;
@@ -985,25 +1021,25 @@ void LayerAndroid::contentDraw(SkCanvas* canvas)
         canvas->drawPicture(*m_extra);
     m_atomicSync.unlock();
 
-#ifdef LAYER_DEBUG
-    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);
+    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);
+        }
     }
-#endif
 }
 
 void LayerAndroid::onDraw(SkCanvas* canvas, SkScalar opacity)
@@ -1045,11 +1081,11 @@ bool LayerAndroid::prepareContext(bool force)
             || (m_recordingPicture
                 && ((m_recordingPicture->width() != (int) getSize().width())
                    || (m_recordingPicture->height() != (int) getSize().height())))) {
-            m_recordingPicture->safeUnref();
+            SkSafeUnref(m_recordingPicture);
             m_recordingPicture = new SkPicture();
         }
     } else if (m_recordingPicture) {
-        m_recordingPicture->safeUnref();
+        SkSafeUnref(m_recordingPicture);
         m_recordingPicture = 0;
     }
 
@@ -1197,6 +1233,8 @@ void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const
     writeIntVal(file, indentLevel + 1, "haveClip", m_haveClip);
     writeIntVal(file, indentLevel + 1, "isRootLayer", m_isRootLayer);
     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());
index 2cb56c1..c315488 100644 (file)
@@ -83,12 +83,13 @@ namespace WebCore {
 class AndroidAnimation;
 class BackedDoubleBufferedTexture;
 class LayerAndroidFindState;
+class RenderLayer;
 class TiledPage;
 
 class LayerAndroid : public SkLayer, public TextureOwner {
 
 public:
-    LayerAndroid(bool isRootLayer);
+    LayerAndroid(RenderLayer* owner, bool isRootLayer);
     LayerAndroid(const LayerAndroid& layer);
     LayerAndroid(SkPicture*);
     virtual ~LayerAndroid();
@@ -111,7 +112,7 @@ public:
     void showLayers(int indent = 0);
 
     // Texture size functions
-    void computeTextureSize();
+    void computeTextureSize(double time);
     void collect(Vector<LayerAndroid*>& layers,
                  int& size);
     int clippedTextureSize() const;
@@ -201,7 +202,7 @@ public:
         This call is recursive, so it should be called on the root of the
         hierarchy.
     */
-    void updateFixedLayersPositions(const SkRect& viewPort);
+    void updateFixedLayersPositions(SkRect viewPort, LayerAndroid* parentIframeLayer = 0);
 
     /** Call this to update the position attribute, so that later calls
         like bounds() will report the corrected position.
@@ -245,6 +246,10 @@ public:
 
     virtual bool isMedia() const { return false; }
 
+    RenderLayer* owningLayer() const { return m_owningLayer; }
+
+    void setIsIframe(bool isIframe) { m_isIframe = isIframe; }
+
 protected:
     virtual void onDraw(SkCanvas*, SkScalar opacity);
 
@@ -263,6 +268,7 @@ private:
     bool m_haveClip;
     bool m_isFixed;
     bool m_backgroundColorSet;
+    bool m_isIframe;
 
     SkLength m_fixedLeft;
     SkLength m_fixedTop;
@@ -274,6 +280,7 @@ private:
     SkLength m_fixedMarginBottom;
     SkRect m_fixedRect;
 
+    SkPoint m_iframeOffset;
     // When fixed element is undefined or auto, the render layer's position
     // is needed for offset computation
     IntPoint m_renderLayerPos;
@@ -325,11 +332,17 @@ private:
 
     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;
+
     typedef SkLayer INHERITED;
 };
 
index a92b570..9e04e96 100644 (file)
@@ -17,6 +17,7 @@
 #include "MediaTexture.h"
 #include "TilesManager.h"
 #include "GLUtils.h"
+#include "VideoListener.h"
 
 #if USE(ACCELERATED_COMPOSITING)
 
 
 namespace WebCore {
 
-class VideoListener : public android::SurfaceTexture::FrameAvailableListener {
-
-public:
-    VideoListener(jobject weakWebViewRef)
-        : m_weakWebViewRef(weakWebViewRef)
-        , m_postInvalMethod(0)
-    {
-        if (!m_weakWebViewRef)
-            return;
-
-        JNIEnv* env = JSC::Bindings::getJNIEnv();
-        jobject localWebViewRef = env->NewLocalRef(m_weakWebViewRef);
-        if (localWebViewRef) {
-            jclass wvClass = env->GetObjectClass(localWebViewRef);
-            m_postInvalMethod = env->GetMethodID(wvClass, "postInvalidate", "()V");
-            env->DeleteLocalRef(wvClass);
-            env->DeleteLocalRef(localWebViewRef);
-        }
-        checkException(env);
-    }
-
-    virtual void onFrameAvailable()
-    {
-        JNIEnv* env = JSC::Bindings::getJNIEnv();
-        jobject localWebViewRef = env->NewLocalRef(m_weakWebViewRef);
-        if (localWebViewRef) {
-            env->CallVoidMethod(localWebViewRef, m_postInvalMethod);
-            env->DeleteLocalRef(localWebViewRef);
-        }
-        checkException(env);
-    }
-
-private:
-    jobject m_weakWebViewRef;
-    jmethodID m_postInvalMethod;
-};
-
 VideoTexture::VideoTexture(jobject weakWebViewRef) : android::LightRefBase<VideoTexture>()
 {
     m_weakWebViewRef = weakWebViewRef;
@@ -91,6 +55,7 @@ VideoTexture::VideoTexture(jobject weakWebViewRef) : android::LightRefBase<Video
     m_dimensions.setEmpty();
     m_newWindowRequest = false;
     m_newWindowReady = false;
+    m_videoListener = new VideoListener(m_weakWebViewRef);
 }
 
 VideoTexture::~VideoTexture()
@@ -119,8 +84,8 @@ void VideoTexture::initNativeWindowIfNeeded()
     m_surfaceTextureClient = new android::SurfaceTextureClient(m_surfaceTexture);
 
     //setup callback
-    sp<VideoListener> listener = new VideoListener(m_weakWebViewRef);
-    m_surfaceTexture->setFrameAvailableListener(listener);
+    m_videoListener->resetFrameAvailable();
+    m_surfaceTexture->setFrameAvailableListener(m_videoListener);
 
     m_newWindowRequest = false;
     m_newWindowReady = true;
@@ -131,7 +96,8 @@ void VideoTexture::drawVideo(const TransformationMatrix& matrix)
 {
     android::Mutex::Autolock lock(m_videoLock);
 
-    if(!m_surfaceTexture.get() || m_dimensions.isEmpty())
+    if(!m_surfaceTexture.get() || m_dimensions.isEmpty()
+            || !m_videoListener->isFrameAvailable())
         return;
 
     m_surfaceTexture->updateTexImage();
index 189905c..b3e1d07 100644 (file)
@@ -31,6 +31,8 @@ namespace android {
 
 namespace WebCore {
 
+class VideoListener;
+
 class MediaTexture : public DoubleBufferedTexture,
                      public android::LightRefBase<MediaTexture> {
 
@@ -57,6 +59,7 @@ private:
     GLuint m_textureId;
     sp<android::SurfaceTexture> m_surfaceTexture;
     sp<ANativeWindow> m_surfaceTextureClient;
+    sp<VideoListener> m_videoListener;
     SkRect m_dimensions;
     bool m_newWindowRequest;
     bool m_newWindowReady;
index 5a3fd8f..568036c 100644 (file)
@@ -42,7 +42,7 @@ static SkShader::TileMode toTileMode(bool doRepeat) {
 
 void Pattern::platformDestroy()
 {
-    m_pattern->safeUnref();
+    SkSafeUnref(m_pattern);
     m_pattern = 0;
 }
 
index 697fe74..68fba77 100644 (file)
@@ -26,8 +26,8 @@ namespace WebCore {
 class ScrollableLayerAndroid : public LayerAndroid {
 
 public:
-    ScrollableLayerAndroid()
-        : LayerAndroid(false) {}
+    ScrollableLayerAndroid(RenderLayer* owner)
+        : LayerAndroid(owner, false) {}
     ScrollableLayerAndroid(const ScrollableLayerAndroid& layer)
         : LayerAndroid(layer)
         , m_scrollLimits(layer.m_scrollLimits) {}
index 8bea60c..16fb782 100644 (file)
@@ -89,6 +89,7 @@ TilesManager::TilesManager()
     , m_maxTextureCount(0)
     , m_expandedTileBounds(false)
     , m_generatorReady(false)
+    , m_showVisualIndicator(false)
 {
     XLOG("TilesManager ctor");
     m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
index 29b7fc1..107b121 100644 (file)
@@ -108,6 +108,14 @@ public:
         m_expandedTileBounds = enabled;
     }
 
+    bool getShowVisualIndicator() {
+        return m_showVisualIndicator;
+    }
+
+    void setShowVisualIndicator(bool showVisualIndicator) {
+        m_showVisualIndicator = showVisualIndicator;
+    }
+
 private:
 
     TilesManager();
@@ -129,6 +137,8 @@ private:
 
     bool m_generatorReady;
 
+    bool m_showVisualIndicator;
+
     sp<TexturesGenerator> m_pixmapsGenerationThread;
 
     android::Mutex m_texturesLock;
diff --git a/WebCore/platform/graphics/android/VideoListener.h b/WebCore/platform/graphics/android/VideoListener.h
new file mode 100644 (file)
index 0000000..7cac6d6
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 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 VideoListener_h
+#define VideoListener_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include <gui/SurfaceTexture.h>
+#include <jni.h>
+#include <JNIUtility.h>
+#include "WebCoreJni.h"
+
+#ifdef DEBUG
+
+#include <cutils/log.h>
+#include <wtf/text/CString.h>
+
+#undef XLOG
+#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "VideoListener", __VA_ARGS__)
+
+#else
+
+#undef XLOG
+#define XLOG(...)
+
+#endif // DEBUG
+
+namespace WebCore {
+
+class VideoListener : public android::SurfaceTexture::FrameAvailableListener {
+
+public:
+    VideoListener(jobject weakWebViewRef)
+        : m_weakWebViewRef(weakWebViewRef)
+        , m_postInvalMethod(0)
+        , m_frameAvailable(false)
+    {
+        if (!m_weakWebViewRef)
+            return;
+
+        JNIEnv* env = JSC::Bindings::getJNIEnv();
+        jobject localWebViewRef = env->NewLocalRef(m_weakWebViewRef);
+        if (localWebViewRef) {
+            jclass wvClass = env->GetObjectClass(localWebViewRef);
+            m_postInvalMethod = env->GetMethodID(wvClass, "postInvalidate", "()V");
+            env->DeleteLocalRef(wvClass);
+            env->DeleteLocalRef(localWebViewRef);
+        }
+        checkException(env);
+    }
+
+    virtual void onFrameAvailable()
+    {
+        JNIEnv* env = JSC::Bindings::getJNIEnv();
+        jobject localWebViewRef = env->NewLocalRef(m_weakWebViewRef);
+        if (localWebViewRef) {
+            env->CallVoidMethod(localWebViewRef, m_postInvalMethod);
+            env->DeleteLocalRef(localWebViewRef);
+        }
+        checkException(env);
+        if (!m_frameAvailable) {
+            m_frameAvailable = true;
+        }
+    }
+
+    void resetFrameAvailable() { m_frameAvailable = false; }
+    bool isFrameAvailable() { return m_frameAvailable; }
+
+private:
+    jobject m_weakWebViewRef;
+    jmethodID m_postInvalMethod;
+    bool m_frameAvailable;
+};
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
+#endif  // VideoListener_h
index c046858..e50cfec 100644 (file)
@@ -109,14 +109,8 @@ void CursorRing::draw(SkCanvas* canvas, LayerAndroid* layer, IntRect* inval)
     inval->unite(m_lastBounds);
 }
 
-bool CursorRing::setup()
+void CursorRing::setIsButton(const CachedNode* node)
 {
-    m_node->localCursorRings(m_frame, &m_rings);
-    if (!m_rings.size()) {
-        DBG_NAV_LOG("!rings.size()");
-        m_viewImpl->m_hasCursorBounds = false;
-        return false;
-    }
     m_isButton = false;
     m_viewImpl->gButtonMutex.lock();
     // If this is a button drawn by us (rather than webkit) do not draw the
@@ -124,7 +118,7 @@ bool CursorRing::setup()
     // Should be in sync with recordButtons, since that will be called
     // before this.
     if (m_viewImpl->m_buttons.size() > 0) {
-        WebCore::Node* cursorPointer = (WebCore::Node*) m_node->nodePointer();
+        WebCore::Node* cursorPointer = (WebCore::Node*) node->nodePointer();
         Container* end = m_viewImpl->m_buttons.end();
         for (Container* ptr = m_viewImpl->m_buttons.begin(); ptr != end; ptr++) {
             if (ptr->matches(cursorPointer)) {
@@ -134,6 +128,17 @@ bool CursorRing::setup()
         }
     }
     m_viewImpl->gButtonMutex.unlock();
+}
+
+bool CursorRing::setup()
+{
+    m_node->localCursorRings(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->localBounds(m_frame);
     m_viewImpl->updateCursorBounds(m_root, m_frame, m_node);
 
index 9f52a27..be309a6 100644 (file)
@@ -54,6 +54,7 @@ public:
     CursorRing(WebViewCore* core) : m_viewImpl(core) {}
     virtual ~CursorRing() {}
     virtual void draw(SkCanvas* , LayerAndroid* , IntRect* );
+    void setIsButton(const CachedNode* );
     bool setup();
 private:
     friend class WebView;
index 4609f1b..22e8afb 100644 (file)
@@ -117,6 +117,7 @@ RenderBlock::RenderBlock(Node* node)
       , m_continuation(0)
       , m_rareData(0)
       , m_lineHeight(-1)
+      , m_beingDestroyed(false)
 {
     setChildrenInline(true);
 }
@@ -151,6 +152,9 @@ RenderBlock::~RenderBlock()
 
 void RenderBlock::destroy()
 {
+    // Mark as being destroyed to avoid trouble with merges in removeChild().
+    m_beingDestroyed = true;
+
     // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will
     // properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise.
     children()->destroyLeftoverChildren();
@@ -930,8 +934,8 @@ static bool canMergeContiguousAnonymousBlocks(RenderObject* oldChild, RenderObje
     if (oldChild->documentBeingDestroyed() || oldChild->isInline() || oldChild->virtualContinuation())
         return false;
 
-    if ((prev && (!prev->isAnonymousBlock() || toRenderBlock(prev)->continuation()))
-        || (next && (!next->isAnonymousBlock() || toRenderBlock(next)->continuation())))
+    if ((prev && (!prev->isAnonymousBlock() || toRenderBlock(prev)->continuation() || toRenderBlock(prev)->beingDestroyed()))
+        || (next && (!next->isAnonymousBlock() || toRenderBlock(next)->continuation() || toRenderBlock(next)->beingDestroyed())))
         return false;
 
     // FIXME: This check isn't required when inline run-ins can't be split into continuations.
@@ -1007,10 +1011,6 @@ void RenderBlock::removeChild(RenderObject* oldChild)
             nextBlock->deleteLineBoxTree();
             nextBlock->destroy();
             next = 0;
-
-            // FIXME: Revert the continuation change done above.
-            if (oldChildBlock)
-                oldChildBlock->setContinuation(0);
         }
     }
 
@@ -3033,7 +3033,7 @@ void RenderBlock::removeFloatingObject(RenderBox* o)
                     // Special-case zero- and less-than-zero-height floats: those don't touch
                     // the line that they're on, but it still needs to be dirtied. This is
                     // accomplished by pretending they have a height of 1.
-                    logicalBottom = max(logicalBottom, logicalTop + 1);
+                    logicalBottom = max(logicalBottom, logicalTop == numeric_limits<int>::max() ? logicalTop : logicalTop + 1);
                     markLinesDirtyInBlockRange(0, logicalBottom);
                 }
                 m_floatingObjects->removeRef(it.current());
@@ -3807,7 +3807,7 @@ void RenderBlock::markLinesDirtyInBlockRange(int logicalTop, int logicalBottom,
 
     RootInlineBox* lowestDirtyLine = lastRootBox();
     RootInlineBox* afterLowest = lowestDirtyLine;
-    while (lowestDirtyLine && lowestDirtyLine->blockLogicalHeight() >= logicalBottom) {
+    while (lowestDirtyLine && lowestDirtyLine->blockLogicalHeight() >= logicalBottom && logicalBottom < numeric_limits<int>::max()) {
         afterLowest = lowestDirtyLine;
         lowestDirtyLine = lowestDirtyLine->prevRootBox();
     }
index 5153218..cc06954 100644 (file)
@@ -55,6 +55,7 @@ public:
     RenderObjectChildList* children() { return &m_children; }
 
     virtual void destroy();
+    bool beingDestroyed() const { return m_beingDestroyed; }
 
     // These two functions are overridden for inline-block.
     virtual int lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
@@ -717,7 +718,8 @@ private:
     RenderObjectChildList m_children;
     RenderLineBoxList m_lineBoxes;   // All of the root line boxes created for this block flow.  For example, <div>Hello<br>world.</div> will have two total lines for the <div>.
 
-    mutable int m_lineHeight;
+    mutable int m_lineHeight : 31;
+    bool m_beingDestroyed : 1;
 
     // RenderRubyBase objects need to be able to split and merge, moving their children around
     // (calling moveChildTo, moveAllChildrenTo, and makeChildrenNonInline).
index fe78fd5..140d326 100644 (file)
@@ -39,7 +39,9 @@
 #include "FloatQuad.h"
 #include "Frame.h"
 #include "Page.h"
+#if PLATFORM(ANDROID)
 #include "PlatformBridge.h"
+#endif
 #include "RenderArena.h"
 #include "RenderFlexibleBox.h"
 #include "RenderInline.h"
@@ -225,26 +227,30 @@ void RenderBox::removeFloatingOrPositionedChildFromBlockLists()
         return;
 
     if (isFloating()) {
-        RenderBlock* outermostBlock = containingBlock();
-        for (RenderBlock* p = outermostBlock; p && !p->isRenderView(); p = p->containingBlock()) {
-            if (p->containsFloat(this))
-                outermostBlock = p;
+        RenderBlock* parentBlock = 0;
+        for (RenderObject* curr = parent(); curr && !curr->isRenderView(); curr = curr->parent()) {
+            if (curr->isRenderBlock()) {
+                RenderBlock* currBlock = toRenderBlock(curr);
+                if (currBlock->containsFloat(this))
+                    parentBlock = currBlock;
+                else
+                    break;
+            }
         }
 
-        if (outermostBlock) {
-            RenderObject* parent = outermostBlock->parent();
+        if (parentBlock) {
+            RenderObject* parent = parentBlock->parent();
             if (parent && parent->isFlexibleBox())
-                outermostBlock = toRenderBlock(parent);
+                parentBlock = toRenderBlock(parent);
 
-            outermostBlock->markAllDescendantsWithFloatsForLayout(this, false);
+            parentBlock->markAllDescendantsWithFloatsForLayout(this, false);
         }
     }
 
     if (isPositioned()) {
-        RenderObject* p;
-        for (p = parent(); p; p = p->parent()) {
-            if (p->isRenderBlock())
-                toRenderBlock(p)->removePositionedObject(this);
+        for (RenderObject* curr = parent(); curr; curr = curr->parent()) {
+            if (curr->isRenderBlock())
+                toRenderBlock(curr)->removePositionedObject(this);
         }
     }
 }
@@ -2078,13 +2084,14 @@ void RenderBox::computeBlockDirectionMargins(RenderBlock* containingBlock)
 
 int RenderBox::containingBlockWidthForPositioned(const RenderBoxModelObject* containingBlock) const
 {
+#if PLATFORM(ANDROID)
     // Fixed element's position should be decided by the visible screen size.
     // That is in the doc coordindate.
     if (style()->position() == FixedPosition && containingBlock->isRenderView()) {
         const RenderView* view = toRenderView(containingBlock);
-        return PlatformBridge::visibleScreenWidth(view->frameView());
+        return PlatformBridge::screenWidthInDocCoord(view->frameView());
     }
-
+#endif
     if (containingBlock->isBox()) {
         const RenderBox* containingBlockBox = toRenderBox(containingBlock);
         return containingBlockBox->width() - containingBlockBox->borderLeft() - containingBlockBox->borderRight() - containingBlockBox->verticalScrollbarWidth();
@@ -2114,14 +2121,15 @@ int RenderBox::containingBlockWidthForPositioned(const RenderBoxModelObject* con
 }
 
 int RenderBox::containingBlockHeightForPositioned(const RenderBoxModelObject* containingBlock) const
-{   
+{
+#if PLATFORM(ANDROID)
     // Fixed element's position should be decided by the visible screen size.
     // That is in the doc coordindate.
     if (style()->position() == FixedPosition && containingBlock->isRenderView()) {
         const RenderView* view = toRenderView(containingBlock);
-        return PlatformBridge::visibleScreenHeight(view->frameView());
+        return PlatformBridge::screenHeightInDocCoord(view->frameView());
     }
-
+#endif
     int heightResult = 0;
     if (containingBlock->isBox())
          heightResult = toRenderBox(containingBlock)->height();
index b850ba3..559f25c 100644 (file)
@@ -1159,14 +1159,6 @@ RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, i
         return;
 
     EPosition position = renderer()->style()->position();
-#if PLATFORM(ANDROID)
-    if (position == FixedPosition) {
-        if (renderer() && renderer()->isBox()) {
-            (toRenderBox(renderer()))->computeLogicalWidth();
-            (toRenderBox(renderer()))->computeLogicalHeight();
-        }
-    }
-#endif
     if (position == FixedPosition && (!ancestorLayer || ancestorLayer == renderer()->view()->layer())) {
         // If the fixed layer's container is the root, just add in the offset of the view. We can obtain this by calling
         // localToAbsolute() on the RenderView.
index 48aa3ec..0d39f7a 100644 (file)
@@ -1021,14 +1021,6 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*
     bool selectionOnly  = paintBehavior & PaintBehaviorSelectionOnly;
 
     if (shouldPaint && (paintingPhase & GraphicsLayerPaintForeground)) {
-#if ENABLE(ANDROID_OVERFLOW_SCROLL)
-        // Scroll to 0,0 and paint the entire contents, then scroll back the
-        // the original offset.
-        int x = m_owningLayer->scrollXOffset();
-        int y = m_owningLayer->scrollYOffset();
-        if (m_owningLayer->hasOverflowScroll())
-            m_owningLayer->scrollToOffset(0, 0, false, false);
-#endif
         // Set up the clip used when painting our children.
         setClip(context, paintDirtyRect, clipRectToApply);
         PaintInfo paintInfo(context, clipRectToApply, 
@@ -1067,10 +1059,6 @@ void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext*
 
         // Now walk the sorted list of children with positive z-indices.
         m_owningLayer->paintList(m_owningLayer->posZOrderList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, 0, 0);
-#if ENABLE(ANDROID_OVERFLOW_SCROLL)
-        if (m_owningLayer->hasOverflowScroll())
-            m_owningLayer->scrollToOffset(x, y, false, false);
-#endif
     }
     
     if (shouldPaint && (paintingPhase & GraphicsLayerPaintMask)) {
index f31ab9d..6578d1d 100644 (file)
@@ -1193,27 +1193,10 @@ bool RenderLayerCompositor::requiresCompositingForAndroidLayers(const RenderLaye
         return true;
 #endif
 #if ENABLE(COMPOSITED_FIXED_ELEMENTS)
-    // First, check if we are in an iframe, and if so bail out
-    if (m_renderView->document()->frame()->tree()->parent())
-        return false;
 
-    // For the moment, we want to only enable fixed composited layers on mobile websites.
     // Enable composited layers (for fixed elements)
-    // We can consider a website as being a 'mobile' site if all the
-    // following checks are true:
-    // 1) - the viewport width is either undefined (-1) or equal to device-width (0), and
-    // 2) - no scaling is allowed
-    if (!layer->isFixed())
-        return false;
-
-    Settings* settings = m_renderView->document()->settings();
-    if (!settings)
-        return false;
-
-    if ((settings->viewportWidth() == -1 || settings->viewportWidth() == 0) &&
-        !settings->viewportUserScalable())
+    if (layer->isFixed())
         return true;
-
 #endif
     return false;
 }
@@ -1288,6 +1271,10 @@ bool RenderLayerCompositor::clippedByAncestor(RenderLayer* layer) const
 // into the hierarchy between this layer and its children in the z-order hierarchy.
 bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer) const
 {
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+    if (layer->hasOverflowScroll())
+        return false;
+#endif
     return layer->hasCompositingDescendant() &&
            (layer->renderer()->hasOverflowClip() || layer->renderer()->hasClip());
 }
index 43b6b03..521dea1 100644 (file)
@@ -167,7 +167,7 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
 
     if (!wrapInAnonymousSection) {
         // If the next renderer is actually wrapped in an anonymous table section, we need to go up and find that.
-        while (beforeChild && !beforeChild->isTableSection() && !beforeChild->isTableCol() && beforeChild->style()->display() != TABLE_CAPTION)
+        while (beforeChild && beforeChild->parent() != this)
             beforeChild = beforeChild->parent();
 
         RenderBox::addChild(child, beforeChild);
@@ -1172,6 +1172,8 @@ int RenderTable::firstLineBoxBaseline() const
     if (isWritingModeRoot())
         return -1;
 
+    recalcSectionsIfNeeded();
+
     RenderTableSection* firstNonEmptySection = m_head ? m_head : (m_firstBody ? m_firstBody : m_foot);
     if (firstNonEmptySection && !firstNonEmptySection->numRows())
         firstNonEmptySection = sectionBelow(firstNonEmptySection, true);
index eaa7eca..1a7ba36 100644 (file)
@@ -41,7 +41,7 @@ RenderTextControlMultiLine::RenderTextControlMultiLine(Node* node, bool placehol
 
 RenderTextControlMultiLine::~RenderTextControlMultiLine()
 {
-    if (node())
+    if (node() && node()->inDocument())
         static_cast<HTMLTextAreaElement*>(node())->rendererWillBeDestroyed();
 }
 
index 522bd4d..538b6c6 100644 (file)
@@ -198,7 +198,7 @@ void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, El
             return adjustTextFieldStyle(selector, style, e);
         case TextAreaPart:
             return adjustTextAreaStyle(selector, style, e);
-#ifdef ANDROID_LISTBOX_USES_MENU_LIST
+#if ENABLE(NO_LISTBOX_RENDERING)
         case ListboxPart:
             return adjustListboxStyle(selector, style, e);
 #endif
index aedb8eb..13c69e6 100644 (file)
@@ -236,7 +236,7 @@ protected:
     virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
     virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
 
-#ifdef ANDROID_LISTBOX_USES_MENU_LIST
+#if ENABLE(NO_LISTBOX_RENDERING)
     virtual void adjustListboxStyle(CSSStyleSelector*, RenderStyle*, Element*) const {}
 #endif
     virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
index 3fd9761..7f7ba67 100644 (file)
@@ -93,8 +93,12 @@ void SVGDocumentExtensions::startAnimations()
     // FIXME: Eventually every "Time Container" will need a way to latch on to some global timer
     // starting animations for a document will do this "latching"
 #if ENABLE(SVG_ANIMATION)    
-    HashSet<SVGSVGElement*>::iterator end = m_timeContainers.end();
-    for (HashSet<SVGSVGElement*>::iterator itr = m_timeContainers.begin(); itr != end; ++itr)
+    // FIXME: We hold a ref pointers to prevent a shadow tree from getting removed out from underneath us.
+    // In the future we should refactor the use-element to avoid this. See https://webkit.org/b/53704
+    Vector<RefPtr<SVGSVGElement> > timeContainers;
+    timeContainers.appendRange(m_timeContainers.begin(), m_timeContainers.end());
+    Vector<RefPtr<SVGSVGElement> >::iterator end = timeContainers.end();
+    for (Vector<RefPtr<SVGSVGElement> >::iterator itr = timeContainers.begin(); itr != end; ++itr)
         (*itr)->timeContainer()->begin();
 #endif
 }
index 898c259..25dbbe3 100644 (file)
@@ -241,7 +241,7 @@ struct SVGTextRunWalker {
     {
         ASSERT(0 <= from && from <= to && to - from <= run.length());
 
-        const String text = Font::normalizeSpaces(String(run.data(from), run.length()));
+        const String text = Font::normalizeSpaces(String(run.data(from), to - from));
         Vector<SVGGlyphIdentifier::ArabicForm> chars(charactersWithArabicForm(text, run.rtl()));
 
         SVGGlyphIdentifier identifier;
index 515ce04..97f457d 100644 (file)
@@ -262,6 +262,11 @@ String SVGFontFaceElement::fontFamily() const
     return m_styleDeclaration->getPropertyValue(CSSPropertyFontFamily);
 }
 
+SVGFontElement* SVGFontFaceElement::associatedFontElement() const
+{
+    return m_fontElement.get();
+}
+
 void SVGFontFaceElement::rebuildFontFace()
 {
     ASSERT(inDocument());
index 3ee71d8..ead2e1f 100644 (file)
@@ -47,7 +47,7 @@ namespace WebCore {
         int descent() const;
         String fontFamily() const;
 
-        SVGFontElement* associatedFontElement() const { return m_fontElement; }
+        SVGFontElement* associatedFontElement() const;
         void rebuildFontFace();
         void removeFromMappedElementSheet();
 
@@ -63,7 +63,7 @@ namespace WebCore {
         RefPtr<CSSFontFaceRule> m_fontFaceRule;
         RefPtr<CSSMutableStyleDeclaration> m_styleDeclaration;
 
-        SVGFontElement* m_fontElement;
+        RefPtr<SVGFontElement> m_fontElement;
     };
 
 } // namespace WebCore
index 4312771..b36ac1d 100644 (file)
@@ -79,7 +79,8 @@ public:
 
     CachedResourceLoader* cachedResourceLoader();
 
-    Document* ownerDocument() { return m_ownerDocument; }
+    Document* ownerDocument();
+    XSLStyleSheet* parentStyleSheet() const { return m_parentStyleSheet; }
     void setParentStyleSheet(XSLStyleSheet* parent);
 
 #if USE(QXMLQUERY)
index 3fb9eb5..447ba1e 100644 (file)
@@ -57,7 +57,6 @@ namespace WebCore {
 
 XSLStyleSheet::XSLStyleSheet(XSLImportRule* parentRule, const String& originalURL, const KURL& finalURL)
     : StyleSheet(parentRule, originalURL, finalURL)
-    , m_ownerDocument(0)
     , m_embedded(false)
     , m_processed(false) // Child sheets get marked as processed when the libxslt engine has finally seen them.
     , m_stylesheetDoc(0)
@@ -68,7 +67,6 @@ XSLStyleSheet::XSLStyleSheet(XSLImportRule* parentRule, const String& originalUR
 
 XSLStyleSheet::XSLStyleSheet(Node* parentNode, const String& originalURL, const KURL& finalURL,  bool embedded)
     : StyleSheet(parentNode, originalURL, finalURL)
-    , m_ownerDocument(parentNode->document())
     , m_embedded(embedded)
     , m_processed(true) // The root sheet starts off processed.
     , m_stylesheetDoc(0)
@@ -130,9 +128,10 @@ void XSLStyleSheet::clearDocuments()
 
 CachedResourceLoader* XSLStyleSheet::cachedResourceLoader()
 {
-    if (!m_ownerDocument)
+    Document* document = ownerDocument();
+    if (!document)
         return 0;
-    return m_ownerDocument->cachedResourceLoader();
+    return document->cachedResourceLoader();
 }
 
 bool XSLStyleSheet::parseString(const String& string, bool)
@@ -258,8 +257,16 @@ xsltStylesheetPtr XSLStyleSheet::compileStyleSheet()
 void XSLStyleSheet::setParentStyleSheet(XSLStyleSheet* parent)
 {
     m_parentStyleSheet = parent;
-    if (parent)
-        m_ownerDocument = parent->ownerDocument();
+}
+
+Document* XSLStyleSheet::ownerDocument()
+{
+    for (XSLStyleSheet* styleSheet = this; styleSheet; styleSheet = styleSheet->parentStyleSheet()) {
+        Node* node = styleSheet->ownerNode();
+        if (node)
+            return node->document();
+    }
+    return 0;
 }
 
 xmlDocPtr XSLStyleSheet::locateStylesheetSubResource(xmlDocPtr parentDoc, const xmlChar* uri)
index 0523560..0d41d1f 100644 (file)
@@ -35,7 +35,6 @@ namespace WebCore {
 
 XSLStyleSheet::XSLStyleSheet(Node* parentNode, const String& originalURL, const KURL& finalURL,  bool embedded)
     : StyleSheet(parentNode, originalURL, finalURL)
-    , m_ownerDocument(parentNode->document())
     , m_embedded(embedded)
 {
 }
@@ -63,9 +62,10 @@ void XSLStyleSheet::clearDocuments()
 
 CachedResourceLoader* XSLStyleSheet::cachedResourceLoader()
 {
-    if (!m_ownerDocument)
+    Document* document = ownerDocument();
+    if (!document)
         return 0;
-    return m_ownerDocument->cachedResourceLoader();
+    return document->cachedResourceLoader();
 }
 
 bool XSLStyleSheet::parseString(const String& string, bool)
@@ -88,6 +88,12 @@ void XSLStyleSheet::loadChildSheet(const String&)
     notImplemented();
 }
 
+Document* XSLStyleSheet::ownerDocument()
+{
+    Node* node = ownerNode();
+    return node ? node->document() : 0;
+}
+
 void XSLStyleSheet::setParentStyleSheet(XSLStyleSheet*)
 {
     notImplemented();
index f0958d9..980c03e 100644 (file)
@@ -87,8 +87,6 @@ void ChromeClientAndroid::attachRootGraphicsLayer(WebCore::Frame*, WebCore::Grap
 {
     // frame is not used in Android as we should only get root graphics layer for the main frame
     m_rootGraphicsLayer = layer;
-    if (!layer)
-        return;
     scheduleCompositingLayerSync();
 }
 
@@ -536,7 +534,7 @@ bool ChromeClientAndroid::selectItemWritingDirectionIsNatural()
 
 PassRefPtr<PopupMenu> ChromeClientAndroid::createPopupMenu(PopupMenuClient* client) const
 {
-    return adoptRef(new PopupMenuAndroid(client));
+    return adoptRef(new PopupMenuAndroid(static_cast<ListPopupMenuClient*>(client)));
 }
 
 PassRefPtr<SearchPopupMenu> ChromeClientAndroid::createSearchPopupMenu(PopupMenuClient*) const
index cc21dad..535c0da 100644 (file)
@@ -577,6 +577,12 @@ void FrameLoaderClientAndroid::dispatchWillSubmitForm(FramePolicyFunction func,
     (m_frame->loader()->policyChecker()->*func)(PolicyUse);
 }
 
+void FrameLoaderClientAndroid::dispatchWillSendSubmitEvent(HTMLFormElement* form)
+{
+    if (m_webFrame->shouldSaveFormData())
+        m_webFrame->saveFormData(form);
+}
+
 void FrameLoaderClientAndroid::dispatchDidLoadMainResource(DocumentLoader*) {
     notImplemented();
 }
index 964ac6e..034333e 100644 (file)
@@ -223,7 +223,7 @@ namespace android {
         void enableOnDemandPlugins() { m_onDemandPluginsEnabled = true; }
 
         void dispatchDidChangeIcons();
-        void dispatchWillSendSubmitEvent(HTMLFormElement*) { }
+        void dispatchWillSendSubmitEvent(HTMLFormElement*);
     private:
         CacheBuilder        m_cacheBuilder;
         Frame*              m_frame;
index b34ff8c..8d8d809 100644 (file)
@@ -160,16 +160,16 @@ FloatRect PlatformBridge::screenRect()
 }
 
 // The visible size on screen in document coordinate
-int PlatformBridge::visibleScreenWidth(const WebCore::FrameView* frameView)
+int PlatformBridge::screenWidthInDocCoord(const WebCore::FrameView* frameView)
 {
     android::WebViewCore* webViewCore = android::WebViewCore::getWebViewCore(frameView);
-    return webViewCore->visibleScreenWidth();
+    return webViewCore->screenWidth();
 }
 
-int PlatformBridge::visibleScreenHeight(const WebCore::FrameView* frameView)
+int PlatformBridge::screenHeightInDocCoord(const WebCore::FrameView* frameView)
 {
     android::WebViewCore* webViewCore = android::WebViewCore::getWebViewCore(frameView);
-    return webViewCore->visibleScreenHeight();
+    return webViewCore->screenHeight();
 }
 
 String PlatformBridge::computeDefaultLanguage()
index 3f2d9ee..7f54810 100644 (file)
@@ -44,7 +44,8 @@ PassRefPtr<ResourceLoaderAndroid> ResourceLoaderAndroid::start(
     FrameLoaderClientAndroid* clientAndroid = static_cast<FrameLoaderClientAndroid*>(client);
 #if USE(CHROME_NETWORK_STACK)
     WebViewCore* webViewCore = WebViewCore::getWebViewCore(clientAndroid->getFrame()->view());
-    return WebUrlLoader::start(client, handle, request, isMainResource, isSync, webViewCore->webRequestContext());
+    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
index d290b5a..99de67e 100644 (file)
 #include "WebRequestContext.h"
 #include "WebUrlLoaderClient.h"
 
-
+#include <cutils/log.h>
 #include <dirent.h>
 
+#undef ASSERT
+#define ASSERT(assertion, ...) do \
+    if (!(assertion)) { \
+        android_printLog(ANDROID_LOG_ERROR, __FILE__, __VA_ARGS__); \
+    } \
+while (0)
+
 namespace android {
 
 static WTF::Mutex instanceMutex;
+static bool isFirstInstanceCreated = false;
+static bool fileSchemeCookiesEnabled = false;
 
 static const std::string& databaseDirectory()
 {
@@ -99,6 +108,9 @@ scoped_refptr<WebCookieJar>* instance(bool isPrivateBrowsing)
 WebCookieJar* WebCookieJar::get(bool isPrivateBrowsing)
 {
     MutexLocker lock(instanceMutex);
+    if (!isFirstInstanceCreated && fileSchemeCookiesEnabled)
+        net::CookieMonster::EnableFileScheme();
+    isFirstInstanceCreated = true;
     scoped_refptr<WebCookieJar>* instancePtr = instance(isPrivateBrowsing);
     if (!instancePtr->get())
         *instancePtr = new WebCookieJar(databaseDirectory(isPrivateBrowsing));
@@ -117,9 +129,6 @@ void WebCookieJar::cleanup(bool isPrivateBrowsing)
 WebCookieJar::WebCookieJar(const std::string& databaseFilePath)
     : m_allowCookies(true)
 {
-    // This is needed for the page cycler. See http://b/2944150
-    net::CookieMonster::EnableFileScheme();
-
     // Setup the permissions for the file
     const char* cDatabasePath = databaseFilePath.c_str();
     mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
@@ -130,6 +139,7 @@ WebCookieJar::WebCookieJar(const std::string& databaseFilePath)
         if (fd >= 0)
             close(fd);
     }
+
     FilePath cookiePath(databaseFilePath.c_str());
     m_cookieDb = new SQLitePersistentCookieStore(cookiePath);
     m_cookieStore = new net::CookieMonster(m_cookieDb.get(), 0);
@@ -190,16 +200,21 @@ public:
             Task* callback = NewRunnableMethod(this, &FlushSemaphore::Callback);
             ioThread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
                 monster, &net::CookieMonster::FlushStore, callback));
+        } else {
+            Callback();
         }
     }
 
     // Block until the given number of callbacks has been made.
     void Wait(int numCallbacks) {
         AutoLock al(m_lock);
+        int lastCount = m_count;
         while (m_count < numCallbacks) {
             // TODO(husky): Maybe use TimedWait() here? But it's not obvious what
             // to do if the flush fails. Might be okay just to let the OS kill us.
             m_condition.Wait();
+            ASSERT(lastCount != m_count, "Wait finished without incrementing m_count %d %d", m_count, lastCount);
+            lastCount = m_count;
         }
         m_count -= numCallbacks;
     }
@@ -227,4 +242,22 @@ void WebCookieJar::flush()
     semaphore->Wait(2);
 }
 
+bool WebCookieJar::acceptFileSchemeCookies()
+{
+    MutexLocker lock(instanceMutex);
+    return fileSchemeCookiesEnabled;
+}
+
+void WebCookieJar::setAcceptFileSchemeCookies(bool accept)
+{
+    // The Chromium HTTP stack only reflects changes to this flag when creating
+    // a new CookieMonster instance. While we could track whether any
+    // CookieMonster instances currently exist, this would be complicated and is
+    // not required, so we only allow this flag to be changed before the first
+    // instance is created.
+    MutexLocker lock(instanceMutex);
+    if (!isFirstInstanceCreated)
+        fileSchemeCookiesEnabled = accept;
+}
+
 }
index 2f32e1a..1f4266c 100644 (file)
@@ -49,6 +49,12 @@ public:
     bool allowCookies();
     void setAllowCookies(bool allow);
 
+    // Getter and setter for whether we accept cookies for file scheme URLS.
+    // Defaults to false. Note that calls to the setter are ignored once the
+    // first instance of this class has been created.
+    static bool acceptFileSchemeCookies();
+    static void setAcceptFileSchemeCookies(bool);
+
     // 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() { return m_cookieStore.get(); }
index fd6bbe2..a14036f 100644 (file)
@@ -116,10 +116,28 @@ const std::string& WebRequest::getUserAgent() const
     return m_userAgent;
 }
 
+#ifdef LOG_REQUESTS
+namespace {
+int remaining = 0;
+}
+#endif
+
 void WebRequest::finish(bool success)
 {
     m_runnableFactory.RevokeAll();
-    ASSERT(m_loadState < Finished, "called finish on an already finished WebRequest (%d)", m_loadState);
+    ASSERT(m_loadState < Finished, "(%p) called finish on an already finished WebRequest (%d) (%s)", this, m_loadState, m_url.c_str());
+    if (m_loadState >= Finished)
+        return;
+#ifdef LOG_REQUESTS
+    time_t finish;
+    time(&finish);
+    finish = finish - m_startTime;
+    struct tm * timeinfo;
+    char buffer[80];
+    timeinfo = localtime(&finish);
+    strftime(buffer, 80, "Time: %M:%S",timeinfo);
+    android_printLog(ANDROID_LOG_DEBUG, "KM", "(%p) finish (%d) (%s) (%d) (%s)", this, --remaining, buffer, success, m_url.c_str());
+#endif
 
     // Make sure WebUrlLoaderClient doesn't delete us in the middle of this method.
     scoped_refptr<WebRequest> guard(this);
@@ -183,6 +201,10 @@ void WebRequest::updateLoadFlags(int& loadFlags)
 void WebRequest::start()
 {
     ASSERT(m_loadState == Created, "Start called on a WebRequest not in CREATED state: (%s)", m_url.c_str());
+#ifdef LOG_REQUESTS
+    android_printLog(ANDROID_LOG_DEBUG, "KM", "(%p) start (%d) (%s)", this, ++remaining, m_url.c_str());
+    time(&m_startTime);
+#endif
 
     m_loadState = Started;
 
index ae386fd..dba7559 100644 (file)
@@ -113,6 +113,9 @@ private:
     ScopedRunnableMethodFactory<WebRequest> m_runnableFactory;
     bool m_wantToPause;
     bool m_isPaused;
+#ifdef LOG_REQUESTS
+    time_t m_startTime;
+#endif
 };
 
 } // namespace android
index 531619a..0c90bc5 100644 (file)
@@ -45,7 +45,7 @@ WebUrlLoader::~WebUrlLoader()
 }
 
 PassRefPtr<WebUrlLoader> WebUrlLoader::start(FrameLoaderClient* client, WebCore::ResourceHandle* resourceHandle,
-        const WebCore::ResourceRequest& resourceRequest, bool isMainResource, bool isSync, WebRequestContext* context)
+        const WebCore::ResourceRequest& resourceRequest, bool isMainResource, bool isMainFrame, bool isSync, WebRequestContext* context)
 {
     FrameLoaderClientAndroid* androidClient = static_cast<FrameLoaderClientAndroid*>(client);
     WebFrame* webFrame = androidClient->webFrame();
@@ -58,7 +58,7 @@ PassRefPtr<WebUrlLoader> WebUrlLoader::start(FrameLoaderClient* client, WebCore:
     webFrame->maybeSavePassword(androidClient->getFrame(), resourceRequest);
 
     RefPtr<WebUrlLoader> loader = WebUrlLoader::create(webFrame, resourceHandle, resourceRequest);
-    loader->m_loaderClient->start(isMainResource, isSync, context);
+    loader->m_loaderClient->start(isMainResource, isMainFrame, isSync, context);
 
     return loader.release();
 }
index 73c022a..dd88e73 100644 (file)
@@ -39,7 +39,7 @@ class WebRequestContext;
 class WebUrlLoader : public ResourceLoaderAndroid {
 public:
     virtual ~WebUrlLoader();
-    static PassRefPtr<WebUrlLoader> start(FrameLoaderClient* client, WebCore::ResourceHandle*, const WebCore::ResourceRequest&, bool isMainResource, bool sync, WebRequestContext*);
+    static PassRefPtr<WebUrlLoader> start(FrameLoaderClient* client, WebCore::ResourceHandle*, const WebCore::ResourceRequest&, bool isMainResource, bool isMainFrame, bool sync, WebRequestContext*);
 
     virtual void cancel();
     virtual void downloadFile();
index 5c54000..05e728b 100644 (file)
@@ -38,7 +38,6 @@
 #include "WebResourceRequest.h"
 
 #include <wtf/text/CString.h>
-#include <sstream>
 
 namespace android {
 
@@ -88,6 +87,8 @@ bool WebUrlLoaderClient::isActive() const
 {
     if (m_cancelling)
         return false;
+    if (!m_resourceHandle)
+        return false;
     if (!m_resourceHandle->client())
         return false;
     if (m_finished)
@@ -100,6 +101,7 @@ WebUrlLoaderClient::WebUrlLoaderClient(WebFrame* webFrame, WebCore::ResourceHand
     : m_webFrame(webFrame)
     , m_resourceHandle(resourceHandle)
     , m_isMainResource(false)
+    , m_isMainFrame(false)
     , m_isCertMimeType(false)
     , m_cancelling(false)
     , m_sync(false)
@@ -161,7 +163,7 @@ WebUrlLoaderClient::WebUrlLoaderClient(WebFrame* webFrame, WebCore::ResourceHand
     }
 }
 
-bool WebUrlLoaderClient::start(bool isMainResource, bool sync, WebRequestContext* context)
+bool WebUrlLoaderClient::start(bool isMainResource, bool isMainFrame, bool sync, WebRequestContext* context)
 {
     base::Thread* thread = ioThread();
     if (!thread) {
@@ -169,6 +171,7 @@ bool WebUrlLoaderClient::start(bool isMainResource, bool sync, WebRequestContext
     }
 
     m_isMainResource = isMainResource;
+    m_isMainFrame = isMainFrame;
     m_sync = sync;
     if (m_sync) {
         AutoLock autoLock(*syncLock());
@@ -221,7 +224,7 @@ void WebUrlLoaderClient::downloadFile()
     if (m_response) {
         std::string contentDisposition;
         m_response->getHeader("content-disposition", &contentDisposition);
-        m_webFrame->downloadStart(m_request->getUrl(), m_request->getUserAgent(), contentDisposition, m_response->getMimeType(), m_response->getExpectedSize());
+        m_webFrame->downloadStart(m_response->getUrl(), m_request->getUserAgent(), contentDisposition, m_response->getMimeType(), m_response->getExpectedSize());
 
         m_isCertMimeType = isMimeTypeForCert(m_response->getMimeType());
         // Currently, only certificate mime type needs to receive the data.
@@ -344,30 +347,6 @@ void WebUrlLoaderClient::maybeCallOnMainThread(Task* task)
     }
 }
 
-namespace {
-// Convert a CertPrincipal into string readable by Java code.
-// The expected format is "CN=xxx, O=xxx, OU=xxx" (see SslCertificate.DName).
-// If there are multiple organization names, we print them all.
-static std::string certPrincipalToString(const net::CertPrincipal& cp)
-{
-    std::string result;
-    if (!cp.common_name.empty()) {
-        result += "CN=";
-        result += cp.common_name;
-    }
-    std::vector<std::string>::const_iterator i;
-    for (i = cp.organization_names.begin(); i != cp.organization_names.end(); ++i) {
-        result += result.empty() ? "O=" : ", O=";
-        result += *i;
-    }
-    for (i = cp.organization_unit_names.begin(); i != cp.organization_unit_names.end(); ++i) {
-        result += result.empty() ? "OU=" : ", OU=";
-        result += *i;
-    }
-    return result;
-}
-}
-
 // Response methods
 void WebUrlLoaderClient::didReceiveResponse(PassOwnPtr<WebResponse> webResponse)
 {
@@ -377,15 +356,13 @@ void WebUrlLoaderClient::didReceiveResponse(PassOwnPtr<WebResponse> webResponse)
     m_response = webResponse;
     m_resourceHandle->client()->didReceiveResponse(m_resourceHandle.get(), m_response->createResourceResponse());
 
-    if (m_isMainResource) {
-        // If we got an SSL certificate, tell the WebView about it.
-        const net::SSLInfo& ssl = m_response->getSslInfo();
-        if (ssl.cert) {
-            m_webFrame->setCertificate(
-                    certPrincipalToString(ssl.cert->subject()),
-                    certPrincipalToString(ssl.cert->issuer()),
-                    1000L * ssl.cert->valid_start().ToDoubleT(),
-                    1000L * ssl.cert->valid_expiry().ToDoubleT());
+    // Set the main page's certificate to WebView.
+    if (m_isMainResource && m_isMainFrame) {
+        const net::SSLInfo& ssl_info = m_response->getSslInfo();
+        if (ssl_info.is_valid()) {
+            std::vector<std::string> chain_bytes;
+            ssl_info.cert->GetChainDEREncodedBytes(&chain_bytes);
+            m_webFrame->setCertificate(chain_bytes[0]);
         }
     }
 }
index 59ec28b..dc101db 100644 (file)
@@ -66,7 +66,7 @@ public:
     WebUrlLoaderClient(WebFrame*, WebCore::ResourceHandle*, const WebCore::ResourceRequest&);
 
     // Called from WebCore, will be forwarded to the IO thread
-    bool start(bool isMainResource, bool sync, WebRequestContext*);
+    bool start(bool isMainResource, bool isMainFrame, bool sync, WebRequestContext*);
     void cancel();
     void downloadFile();
     void pauseLoad(bool pause);
@@ -104,6 +104,7 @@ private:
     WebFrame* m_webFrame;
     RefPtr<WebCore::ResourceHandle> m_resourceHandle;
     bool m_isMainResource;
+    bool m_isMainFrame;
     bool m_isCertMimeType;
     bool m_cancelling;
     bool m_sync;
index 87c7fa8..a9c68fd 100644 (file)
@@ -155,6 +155,25 @@ static void flushCookieStore(JNIEnv*, jobject)
 #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[] = {
     { "nativeAcceptCookie", "()Z", (void*) acceptCookie },
     { "nativeGetCookie", "(Ljava/lang/String;)Ljava/lang/String;", (void*) getCookie },
@@ -165,6 +184,8 @@ static JNINativeMethod gCookieManagerMethods[] = {
     { "nativeSetAcceptCookie", "(Z)V", (void*) setAcceptCookie },
     { "nativeSetCookie", "(Ljava/lang/String;Ljava/lang/String;)V", (void*) setCookie },
     { "nativeFlushCookieStore", "()V", (void*) flushCookieStore },
+    { "nativeAcceptFileSchemeCookies", "()Z", (void*) acceptFileSchemeCookies },
+    { "nativeSetAcceptFileSchemeCookies", "(Z)V", (void*) setAcceptFileSchemeCookies },
 };
 
 int registerCookieManager(JNIEnv* env)
index 98cda23..6dafd26 100644 (file)
@@ -68,7 +68,7 @@ PictureSet::~PictureSet()
 void PictureSet::add(const Pictures* temp)
 {
     Pictures pictureAndBounds = *temp;
-    pictureAndBounds.mPicture->safeRef();
+    SkSafeRef(pictureAndBounds.mPicture);
     pictureAndBounds.mWroteElapsed = false;
     mPictures.append(pictureAndBounds);
 }
@@ -80,7 +80,7 @@ void PictureSet::add(const SkRegion& area, SkPicture* picture,
         area.getBounds().fLeft, area.getBounds().fTop,
         area.getBounds().fRight, area.getBounds().fBottom, picture,
         elapsed, split);
-    picture->safeRef();
+    SkSafeRef(picture);
     /* if nothing is drawn beneath part of the new picture, mark it as a base */
     SkRegion diff = SkRegion(area);
     Pictures* last = mPictures.end();
@@ -150,7 +150,7 @@ bool PictureSet::build()
             }
         }
         if (tossPicture) {
-            working->mPicture->safeUnref();
+            SkSafeUnref(working->mPicture);
             working->mPicture = NULL; // mark to redraw
         }
         if (working->mPicture == NULL) // may have been set to null elsewhere
@@ -211,7 +211,7 @@ void PictureSet::clear()
     Pictures* last = mPictures.end();
     for (Pictures* working = mPictures.begin(); working != last; working++) {
         working->mArea.setEmpty();
-        working->mPicture->safeUnref();
+        SkSafeUnref(working->mPicture);
     }
     mPictures.clear();
     mWidth = mHeight = 0;
@@ -362,7 +362,7 @@ public:
         return true;
     }
 
-    virtual void commonDrawBitmap(const SkBitmap& bitmap,
+    virtual void commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* rect,
             const SkMatrix& , const SkPaint& ) {
         if (bitmap.width() <= 1 || bitmap.height() <= 1)
             return;
@@ -476,7 +476,7 @@ bool PictureSet::reuseSubdivided(const SkRegion& inval)
         if ((working->mSplit == false || invalBounds != working->mUnsplit) &&
                 inval.contains(working->mArea) == false)
             continue;
-        working->mPicture->safeUnref();
+        SkSafeUnref(working->mPicture);
         working->mPicture = NULL;
     }
     return true;
@@ -526,7 +526,7 @@ void PictureSet::setDrawTimes(const PictureSet& src)
 
 void PictureSet::setPicture(size_t i, SkPicture* p)
 {
-    mPictures[i].mPicture->safeUnref();
+    SkSafeUnref(mPictures[i].mPicture);
     mPictures[i].mPicture = p;
     mPictures[i].mEmpty = emptyPicture(p);
 }
index 9780d2d..c187d92 100644 (file)
@@ -44,7 +44,6 @@
 #include "Element.h"
 #include "FocusController.h"
 #include "Font.h"
-#include "FormState.h"
 #include "Frame.h"
 #include "FrameLoader.h"
 #include "FrameLoaderClientAndroid.h"
@@ -220,6 +219,8 @@ struct WebFrame::JavaBrowserFrame
     jmethodID   mDidReceiveData;
     jmethodID   mDidFinishLoading;
     jmethodID   mSetCertificate;
+    jmethodID   mShouldSaveFormData;
+    jmethodID   mSaveFormData;
     AutoJObject frame(JNIEnv* env) {
         return getRealObject(env, mObj);
     }
@@ -290,8 +291,9 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page*
             "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V");
     mJavaFrame->mDidReceiveData = env->GetMethodID(clazz, "didReceiveData", "([BI)V");
     mJavaFrame->mDidFinishLoading = env->GetMethodID(clazz, "didFinishLoading", "()V");
-    mJavaFrame->mSetCertificate = env->GetMethodID(clazz, "setCertificate",
-            "(Ljava/lang/String;Ljava/lang/String;JJ)V");
+    mJavaFrame->mSetCertificate = env->GetMethodID(clazz, "setCertificate", "([B)V");
+    mJavaFrame->mShouldSaveFormData = env->GetMethodID(clazz, "shouldSaveFormData", "()Z");
+    mJavaFrame->mSaveFormData = env->GetMethodID(clazz, "saveFormData", "(Ljava/util/HashMap;)V");
     env->DeleteLocalRef(clazz);
 
     LOG_ASSERT(mJavaFrame->mStartLoadingResource, "Could not find method startLoadingResource");
@@ -322,6 +324,8 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page*
     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");
 
     mUserAgent = WTF::String();
     mUserInitiatedAction = false;
@@ -782,6 +786,16 @@ WebFrame::canHandleRequest(const WebCore::ResourceRequest& request)
     return (ret == 0);
 }
 
+bool
+WebFrame::shouldSaveFormData()
+{
+    JNIEnv* env = getJNIEnv();
+    jboolean ret = env->CallBooleanMethod(mJavaFrame->frame(env).get(),
+            mJavaFrame->mShouldSaveFormData);
+    checkException(env);
+    return ret;
+}
+
 WebCore::Frame*
 WebFrame::createWindow(bool dialog, bool userGesture)
 {
@@ -950,20 +964,21 @@ WebFrame::didFinishLoading() {
 #endif
 
 #if USE(CHROME_NETWORK_STACK)
-void WebFrame::setCertificate(const std::string& issuedTo, const std::string& issuedBy, long long validNotBeforeMillis, long long validNotAfterMillis)
+void WebFrame::setCertificate(const std::string& cert)
 {
 #ifdef ANDROID_INSTRUMENT
     TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter);
 #endif
     JNIEnv* env = getJNIEnv();
-    jstring jIssuedTo = stdStringToJstring(env, issuedTo, true);
-    jstring jIssuedBy = stdStringToJstring(env, issuedBy, true);
 
-    env->CallVoidMethod(mJavaFrame->frame(env).get(),
-            mJavaFrame->mSetCertificate, jIssuedTo, jIssuedBy, validNotBeforeMillis, validNotAfterMillis);
+    int len = cert.length();
+    jbyteArray jCert = env->NewByteArray(len);
+    jbyte* bytes = env->GetByteArrayElements(jCert, NULL);
+    cert.copy(reinterpret_cast<char*>(bytes), len);
+
+    env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mSetCertificate, jCert);
 
-    env->DeleteLocalRef(jIssuedTo);
-    env->DeleteLocalRef(jIssuedBy);
+    env->DeleteLocalRef(jCert);
     checkException(env);
 }
 #endif
@@ -1876,62 +1891,46 @@ static void SetUsernamePassword(JNIEnv *env, jobject obj,
     }
 }
 
-static jobject GetFormTextData(JNIEnv *env, jobject obj)
+void
+WebFrame::saveFormData(HTMLFormElement* form)
 {
-#ifdef ANDROID_INSTRUMENT
-    TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter);
-#endif
-    WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj);
-    LOG_ASSERT(pFrame, "GetFormTextData must take a valid frame pointer!");
-    jobject hashMap = NULL;
-
-    WTF::PassRefPtr<WebCore::HTMLCollection> collection = pFrame->document()->forms();
-    if (collection->length() > 0) {
+    if (form->autoComplete()) {
+        JNIEnv* env = getJNIEnv();
         jclass mapClass = env->FindClass("java/util/HashMap");
         LOG_ASSERT(mapClass, "Could not find HashMap class!");
         jmethodID init = env->GetMethodID(mapClass, "<init>", "(I)V");
         LOG_ASSERT(init, "Could not find constructor for HashMap");
-        hashMap = env->NewObject(mapClass, init, 1);
+        jobject hashMap = env->NewObject(mapClass, init, 1);
         LOG_ASSERT(hashMap, "Could not create a new HashMap");
         jmethodID put = env->GetMethodID(mapClass, "put",
                 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
         LOG_ASSERT(put, "Could not find put method on HashMap");
-
-        WebCore::HTMLFormElement* form;
-        WebCore::HTMLInputElement* input;
-        for (WebCore::Node* node = collection->firstItem();
-             node && !node->namespaceURI().isNull() && !node->namespaceURI().isEmpty();
-             node = collection->nextItem()) {
-            form = static_cast<WebCore::HTMLFormElement*>(node);
-            if (form->autoComplete()) {
-                WTF::Vector<WebCore::HTMLFormControlElement*> elements = form->associatedElements();
-                size_t size = elements.size();
-                for (size_t i = 0; i < size; i++) {
-                    WebCore::HTMLFormControlElement* e = elements[i];
-                    if (e->hasTagName(WebCore::HTMLNames::inputTag)) {
-                        input = static_cast<WebCore::HTMLInputElement*>(e);
-                        if (input->isTextField() && !input->isPasswordField()
-                                && input->autoComplete()) {
-                            WTF::String value = input->value();
-                            int len = value.length();
-                            if (len) {
-                                const WTF::AtomicString& name = input->name();
-                                jstring key = wtfStringToJstring(env, name);
-                                jstring val = wtfStringToJstring(env, value);
-                                LOG_ASSERT(key && val, "name or value not set");
-                                env->CallObjectMethod(hashMap, put, key, val);
-                                env->DeleteLocalRef(key);
-                                env->DeleteLocalRef(val);
-                            }
-                        }
+        WTF::Vector<WebCore::HTMLFormControlElement*> elements = form->associatedElements();
+        size_t size = elements.size();
+        for (size_t i = 0; i < size; i++) {
+            WebCore::HTMLFormControlElement* e = elements[i];
+            if (e->hasTagName(WebCore::HTMLNames::inputTag)) {
+                WebCore::HTMLInputElement* input = static_cast<WebCore::HTMLInputElement*>(e);
+                if (input->isTextField() && !input->isPasswordField()
+                        && input->autoComplete()) {
+                    WTF::String value = input->value();
+                    int len = value.length();
+                    if (len) {
+                        const WTF::AtomicString& name = input->name();
+                        jstring key = wtfStringToJstring(env, name);
+                        jstring val = wtfStringToJstring(env, value);
+                        LOG_ASSERT(key && val, "name or value not set");
+                        env->CallObjectMethod(hashMap, put, key, val);
+                        env->DeleteLocalRef(key);
+                        env->DeleteLocalRef(val);
                     }
                 }
             }
         }
+        env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mSaveFormData, hashMap);
+        env->DeleteLocalRef(hashMap);
         env->DeleteLocalRef(mapClass);
-
     }
-    return hashMap;
 }
 
 static void OrientationChanged(JNIEnv *env, jobject obj, int orientation)
@@ -2048,8 +2047,6 @@ static JNINativeMethod gBrowserFrameNativeMethods[] = {
         (void*) GetUsernamePassword },
     { "setUsernamePassword", "(Ljava/lang/String;Ljava/lang/String;)V",
         (void*) SetUsernamePassword },
-    { "getFormTextData", "()Ljava/util/HashMap;",
-        (void*) GetFormTextData },
     { "nativeOrientationChanged", "(I)V",
         (void*) OrientationChanged },
     { "nativeAuthenticationProceed", "(ILjava/lang/String;Ljava/lang/String;)V",
index ae62835..af7be60 100644 (file)
@@ -37,6 +37,7 @@
 #include <wtf/RefCounted.h>
 
 namespace WebCore {
+    class HTMLFormElement;
     class Frame;
     class HistoryItem;
     class Image;
@@ -125,18 +126,15 @@ class WebFrame : public WebCoreRefObject {
 
     void maybeSavePassword(WebCore::Frame* frame, const WebCore::ResourceRequest& request);
 
-    void setCertificate(const std::string& issuedTo, const std::string& issuedBy, long long validNotBeforeMillis, long long validNotAfterMillis);
+    void setCertificate(const std::string& cert);
 
     /**
-     * When the user initiates an action (via trackball, key-press, or touch),
-     * 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.
+     * 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; }
 
-    bool userInitiatedAction() { return mUserInitiatedAction; }
-    
     WebCore::Page* page() const { return mPage; }
 
     // Currently used only by the chrome net stack.  A similar field is used by
@@ -151,6 +149,8 @@ class WebFrame : public WebCoreRefObject {
     bool getUsernamePasswordFromDom(WebCore::Frame* frame, WTF::String& username, WTF::String& password);
     jbyteArray getPostData(const WebCore::ResourceRequest& request);
 
+    bool shouldSaveFormData();
+    void saveFormData(WebCore::HTMLFormElement*);
 private:
     struct JavaBrowserFrame;
     JavaBrowserFrame* mJavaFrame;
index 6e6a486..ec25c8f 100644 (file)
@@ -36,6 +36,9 @@ namespace android {
 // returned from getRealObject.
 class AutoJObject {
 public:
+    AutoJObject(const AutoJObject& other)
+        : m_env(other.m_env)
+        , m_obj(other.m_obj ? other.m_env->NewLocalRef(other.m_obj) : NULL) {}
     ~AutoJObject() {
         if (m_obj)
             m_env->DeleteLocalRef(m_obj);
@@ -54,6 +57,7 @@ public:
         return m_env;
     }
 private:
+    AutoJObject(); // Not permitted.
     AutoJObject(JNIEnv* env, jobject obj)
         : m_env(env)
         , m_obj(obj) {}
index b329e3b..4d36741 100644 (file)
@@ -35,6 +35,8 @@
 #include "Chrome.h"
 #include "ChromeClientAndroid.h"
 #include "ChromiumIncludes.h"
+#include "ClientRect.h"
+#include "ClientRectList.h"
 #include "Color.h"
 #include "CSSPropertyNames.h"
 #include "CSSValueKeywords.h"
@@ -250,9 +252,7 @@ struct WebViewCoreFields {
 
 struct WebViewCore::JavaGlue {
     jweak       m_obj;
-    jmethodID   m_spawnScrollTo;
     jmethodID   m_scrollTo;
-    jmethodID   m_scrollBy;
     jmethodID   m_contentDraw;
     jmethodID   m_layersDraw;
     jmethodID   m_requestListBox;
@@ -343,15 +343,14 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
     m_isPaused = false;
     m_screenOnCounter = 0;
     m_onlyScrollIfImeIsShowing = false;
+    m_shouldPaintCaret = true;
 
     LOG_ASSERT(m_mainFrame, "Uh oh, somehow a frameview was made without an initial frame!");
 
     jclass clazz = env->GetObjectClass(javaWebViewCore);
     m_javaGlue = new JavaGlue;
     m_javaGlue->m_obj = env->NewWeakGlobalRef(javaWebViewCore);
-    m_javaGlue->m_spawnScrollTo = GetJMethod(env, clazz, "contentSpawnScrollTo", "(II)V");
-    m_javaGlue->m_scrollTo = GetJMethod(env, clazz, "contentScrollTo", "(IIZ)V");
-    m_javaGlue->m_scrollBy = GetJMethod(env, clazz, "contentScrollBy", "(IIZ)V");
+    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");
@@ -487,8 +486,6 @@ void WebViewCore::reset(bool fromConstructor)
     m_scrollOffsetY = 0;
     m_screenWidth = 0;
     m_screenHeight = 0;
-    m_visibleScreenWidth = 0;
-    m_visibleScreenHeight = 0;
     m_groupForVisitedLinks = NULL;
     m_currentNodeDomNavigationAxis = 0;
 }
@@ -674,7 +671,7 @@ void WebViewCore::recordPictureSet(PictureSet* content)
         DBG_SET_LOGD("{%d,%d,w=%d,h=%d}", inval.fLeft,
             inval.fTop, inval.width(), inval.height());
         content->add(m_addInval, picture, 0, false);
-        picture->safeUnref();
+        SkSafeUnref(picture);
     }
     // Remove any pictures already in the set that are obscured by the new one,
     // and check to see if any already split pieces need to be redrawn.
@@ -948,11 +945,8 @@ void WebViewCore::scrollTo(int x, int y, bool animate)
 //    LOGD("WebViewCore::scrollTo(%d %d)\n", x, y);
 
     JNIEnv* env = JSC::Bindings::getJNIEnv();
-    if (animate)
-        env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_spawnScrollTo, x, y);
-    else
-        env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_scrollTo,
-                x, y, m_onlyScrollIfImeIsShowing);
+    env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_scrollTo,
+            x, y, animate, m_onlyScrollIfImeIsShowing);
     checkException(env);
 }
 
@@ -974,16 +968,6 @@ void WebViewCore::viewInvalidate(const WebCore::IntRect& rect)
     checkException(env);
 }
 
-void WebViewCore::scrollBy(int dx, int dy, bool animate)
-{
-    if (!(dx | dy))
-        return;
-    JNIEnv* env = JSC::Bindings::getJNIEnv();
-    env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_scrollBy,
-        dx, dy, animate);
-    checkException(env);
-}
-
 void WebViewCore::contentDraw()
 {
     JNIEnv* env = JSC::Bindings::getJNIEnv();
@@ -1154,13 +1138,14 @@ void WebViewCore::doMaxScroll(CacheBuilder::Direction dir)
     default:
         LOG_ASSERT(0, "unexpected focus selector");
     }
-    this->scrollBy(dx, dy, true);
+    WebCore::FrameView* view = m_mainFrame->view();
+    this->scrollTo(view->scrollX() + dx, view->scrollY() + dy, true);
 }
 
-void WebViewCore::setScrollOffset(int moveGeneration, int userScrolled, int dx, int dy)
+void WebViewCore::setScrollOffset(int moveGeneration, bool sendScrollEvent, int dx, int dy)
 {
-    DBG_NAV_LOGD("{%d,%d} m_scrollOffset=(%d,%d), userScrolled=%d", dx, dy,
-        m_scrollOffsetX, m_scrollOffsetY, userScrolled);
+    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;
@@ -1169,24 +1154,25 @@ void WebViewCore::setScrollOffset(int moveGeneration, int userScrolled, int dx,
         // testing work correctly.
         m_mainFrame->view()->platformWidget()->setLocation(m_scrollOffsetX,
                 m_scrollOffsetY);
-        if (userScrolled) {
+        if (sendScrollEvent) {
             m_mainFrame->eventHandler()->sendScrollEvent();
-        }
 
-        // Update history item to reflect the new scroll position.
-        // This also helps save the history information when the browser goes to
-        // background, so scroll position will be restored if browser gets
-        // killed while in background.
-        WebCore::HistoryController* history = m_mainFrame->loader()->history();
-        // Because the history item saving could be heavy for large sites and
-        // scrolling can generate lots of small scroll offset, the following code
-        // reduces the saving frequency.
-        static const int MIN_SCROLL_DIFF = 32;
-        if (history->currentItem()) {
-            WebCore::IntPoint currentPoint = history->currentItem()->scrollPoint();
-            if (std::abs(currentPoint.x() - dx) >= MIN_SCROLL_DIFF ||
-                std::abs(currentPoint.y() - dy) >= MIN_SCROLL_DIFF) {
-                history->saveScrollPositionAndViewStateToItem(history->currentItem());
+            // Only update history position if it's user scrolled.
+            // Update history item to reflect the new scroll position.
+            // This also helps save the history information when the browser goes to
+            // background, so scroll position will be restored if browser gets
+            // killed while in background.
+            WebCore::HistoryController* history = m_mainFrame->loader()->history();
+            // Because the history item saving could be heavy for large sites and
+            // scrolling can generate lots of small scroll offset, the following code
+            // reduces the saving frequency.
+            static const int MIN_SCROLL_DIFF = 32;
+            if (history->currentItem()) {
+                WebCore::IntPoint currentPoint = history->currentItem()->scrollPoint();
+                if (std::abs(currentPoint.x() - dx) >= MIN_SCROLL_DIFF ||
+                    std::abs(currentPoint.y() - dy) >= MIN_SCROLL_DIFF) {
+                    history->saveScrollPositionAndViewStateToItem(history->currentItem());
+                }
             }
         }
 
@@ -1232,6 +1218,12 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
     // Don't reflow if the diff is small.
     const bool reflow = otw && textWrapWidth &&
         ((float) abs(otw - textWrapWidth) / textWrapWidth) >= 0.01f;
+
+    // When the screen size change, fixed positioned element should be updated.
+    // This is supposed to be light weighted operation without a full layout.
+    if (osh != screenHeight || osw != screenWidth)
+        m_mainFrame->view()->updatePositionedObjects();
+
     if (ow != width || (!ignoreHeight && oh != height) || reflow) {
         WebCore::RenderObject *r = m_mainFrame->contentRenderer();
         DBG_NAV_LOGD("renderer=%p view=(w=%d,h=%d)", r,
@@ -2090,18 +2082,18 @@ String WebViewCore::modifySelection(const int direction, const int axis)
     if (selection->rangeCount() > 1)
         selection->removeAllRanges();
     switch (axis) {
-    case AXIS_CHARACTER:
-    case AXIS_WORD:
-    case AXIS_SENTENCE:
-        return modifySelectionTextNavigationAxis(selection, direction, axis);
-    case AXIS_HEADING:
-    case AXIS_SIBLING:
-    case AXIS_PARENT_FIRST_CHILD:
-    case AXIS_DOCUMENT:
-        return modifySelectionDomNavigationAxis(selection, direction, axis);
-    default:
-        LOGE("Invalid navigation axis: %d", axis);
-        return String();
+        case AXIS_CHARACTER:
+        case AXIS_WORD:
+        case AXIS_SENTENCE:
+            return modifySelectionTextNavigationAxis(selection, direction, axis);
+        case AXIS_HEADING:
+        case AXIS_SIBLING:
+        case AXIS_PARENT_FIRST_CHILD:
+        case AXIS_DOCUMENT:
+            return modifySelectionDomNavigationAxis(selection, direction, axis);
+        default:
+            LOGE("Invalid navigation axis: %d", axis);
+            return String();
     }
 }
 
@@ -2129,10 +2121,10 @@ void WebViewCore::scrollNodeIntoView(Frame* frame, Node* node)
 
 String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, int direction, int axis)
 {
-    // TODO: Add support of IFrames.
-    HTMLElement* body = m_mainFrame->document()->body();
+    Node* body = m_mainFrame->document()->body();
 
     ExceptionCode ec = 0;
+    String markup;
 
     // initialize the selection if necessary
     if (selection->rangeCount() == 0) {
@@ -2157,14 +2149,13 @@ String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, i
             if (ec)
                 return String();
             selection->addRange(rangeRef.get());
-        } else if (direction == DIRECTION_FORWARD) {
-            selection->setPosition(body->firstDescendant(), 0, ec);
         } else {
-            selection->setPosition(body->lastDescendant(), 0, ec);
+            selection->setPosition(body, 0, ec);
         }
         if (ec)
             return String();
     }
+
     // collapse the selection
     if (direction == DIRECTION_FORWARD)
         selection->collapseToEnd(ec);
@@ -2173,126 +2164,52 @@ String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, i
     if (ec)
         return String();
 
-    Node* oldAnchorNode = selection->anchorNode();
-    if (!oldAnchorNode)
-        return String();
-
     // Make sure the anchor node is a text node since we are generating
     // the markup of the selection which includes the anchor, the focus,
     // and any crossed nodes. Forcing the condition that the selection
     // starts and ends on text nodes guarantees symmetric selection markup.
+    // Also this way the text content, rather its container, is highlighted.
     Node* anchorNode = selection->anchorNode();
     if (anchorNode->isElementNode()) {
-        int anchorOffset = rangeCompliantChildOffset(anchorNode,
-            selection->anchorOffset());
-        anchorNode = selection->anchorNode()->childNodes()->item(anchorOffset);
-        Node* nextAnchorNode = traverseVisibleNonEmptyNonWhitespaceTextNode(
-            anchorNode, body, direction);
-        if (!nextAnchorNode)
+        // Collapsed selection while moving forward points to the
+        // next unvisited node and while moving backward to the
+        // last visited node.
+        if (direction == DIRECTION_FORWARD)
+            advanceAnchorNode(selection, direction, markup, false, ec);
+        else
+            advanceAnchorNode(selection, direction, markup, true, ec);
+        if (ec)
             return String();
-        if (direction == DIRECTION_FORWARD) {
-            Node* skippedControl = getFirstIntermediaryInputOrButton(anchorNode,
-                nextAnchorNode);
-            if (skippedControl) {
-                IntRect bounds = static_cast<Element*>(
-                    skippedControl)->boundsInWindowSpace();
-                selectAt(bounds.center().x(), bounds.center().y());
-                selection->setBaseAndExtent(skippedControl,
-                    caretMinOffset(skippedControl), skippedControl,
-                    caretMaxOffset(skippedControl), ec);
-                if (ec)
-                    return String();
-                return formatMarkup(selection).stripWhiteSpace();
-            } else {
-                selection->setPosition(nextAnchorNode, 0, ec);
-                if (ec)
-                    return String();
-            }
-        } else {
-            Node* skippedControl = getFirstIntermediaryInputOrButton(
-                nextAnchorNode, anchorNode);
-            if (skippedControl) {
-                IntRect bounds = static_cast<Element*>(
-                    skippedControl)->boundsInWindowSpace();
-                selectAt(bounds.center().x(), bounds.center().y());
-                selection->setBaseAndExtent(skippedControl,
-                    caretMaxOffset(skippedControl), skippedControl,
-                    caretMinOffset(skippedControl), ec);
-                if (ec)
-                    return String();
-                return formatMarkup(selection).stripWhiteSpace();
-            } else {
-                selection->setPosition(nextAnchorNode,
-                    caretMaxOffset(nextAnchorNode), ec);
-                if (ec)
-                    return String();
-            }
-        }
+        if (!markup.isEmpty())
+            return markup;
     }
 
     // If the selection is at the end of a non white space text move
     // it to the next visible text node with non white space content.
     // This is a workaround for the selection getting stuck.
     anchorNode = selection->anchorNode();
-    if (!anchorNode)
-        return String();
     if (anchorNode->isTextNode()) {
         if (direction == DIRECTION_FORWARD) {
             String suffix = anchorNode->textContent().substring(
-                selection->anchorOffset(), caretMaxOffset(anchorNode));
+                    selection->anchorOffset(), caretMaxOffset(anchorNode));
+            // If at the end of non white space text we advance the
+            // anchor node to either an input element or non empty text.
             if (suffix.stripWhiteSpace().isEmpty()) {
-                Node* nextAnchorNode =
-                    traverseVisibleNonEmptyNonWhitespaceTextNode(anchorNode,
-                        body, direction);
-                if (!nextAnchorNode)
-                    return String();
-                Node* skippedControl = getFirstIntermediaryInputOrButton(
-                    anchorNode, nextAnchorNode);
-                if (skippedControl) {
-                    IntRect bounds = static_cast<Element*>(
-                        skippedControl)->boundsInWindowSpace();
-                    selectAt(bounds.center().x(), bounds.center().y());
-                    selection->setBaseAndExtent(skippedControl,
-                        caretMinOffset(skippedControl), skippedControl,
-                        caretMaxOffset(skippedControl), ec);
-                    if (ec)
-                        return String();
-                    return formatMarkup(selection).stripWhiteSpace();
-                } else {
-                    selection->setPosition(nextAnchorNode, 0, ec);
-                    if (ec)
-                        return String();
-                }
+                advanceAnchorNode(selection, direction, markup, true, ec);
             }
         } else {
             String prefix = anchorNode->textContent().substring(0,
-                selection->anchorOffset());
+                    selection->anchorOffset());
+            // If at the end of non white space text we advance the
+            // anchor node to either an input element or non empty text.
             if (prefix.stripWhiteSpace().isEmpty()) {
-                Node* nextAnchorNode =
-                    traverseVisibleNonEmptyNonWhitespaceTextNode(anchorNode,
-                        body, direction);
-                if (!nextAnchorNode)
-                    return String();
-                Node* skippedControl = getFirstIntermediaryInputOrButton(
-                    nextAnchorNode, anchorNode);
-                if (skippedControl) {
-                    IntRect bounds = static_cast<Element*>(
-                        skippedControl)->boundsInWindowSpace();
-                    selectAt(bounds.center().x(), bounds.center().y());
-                    selection->setBaseAndExtent(skippedControl,
-                        caretMaxOffset(skippedControl), skippedControl,
-                        caretMinOffset(skippedControl), ec);
-                    if (ec)
-                        return String();
-                    return formatMarkup(selection).stripWhiteSpace();
-                } else {
-                    selection->setPosition(nextAnchorNode,
-                        caretMaxOffset(nextAnchorNode), ec);
-                    if (ec)
-                        return String();
-                }
+                advanceAnchorNode(selection, direction, markup, true, ec);
             }
         }
+        if (ec)
+            return String();
+        if (!markup.isEmpty())
+            return markup;
     }
 
     // extend the selection
@@ -2314,176 +2231,111 @@ String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, i
 
     // Make sure the focus node is a text node in order to have the
     // selection generate symmetric markup because the latter
-    // includes all nodes crossed by the selection.
+    // includes all nodes crossed by the selection.  Also this way
+    // the text content, rather its container, is highlighted.
     Node* focusNode = selection->focusNode();
     if (focusNode->isElementNode()) {
-        int focusOffset = rangeCompliantChildOffset(focusNode,
-            selection->focusOffset());
+        focusNode = getImplicitBoundaryNode(selection->focusNode(),
+                selection->focusOffset(), direction);
+        if (!focusNode)
+            return String();
         if (direction == DIRECTION_FORWARD) {
-            focusNode =
-                focusNode->childNodes()->item(focusOffset)->lastDescendant();
-            if (!isVisibleNonEmptyNonWhitespaceTextNode(focusNode)) {
-                focusNode = traverseVisibleNonEmptyNonWhitespaceTextNode(
-                    focusNode, body, DIRECTION_BACKWARD);
-                if (!focusNode)
+            focusNode = focusNode->traversePreviousSiblingPostOrder(body);
+            if (focusNode && !isContentTextNode(focusNode)) {
+                Node* textNode = traverseNextContentTextNode(focusNode,
+                        anchorNode, DIRECTION_BACKWARD);
+                if (textNode)
+                    anchorNode = textNode;
+            }
+            if (focusNode && isContentTextNode(focusNode)) {
+                selection->extend(focusNode, caretMaxOffset(focusNode), ec);
+                if (ec)
                     return String();
             }
-            selection->extend(focusNode, caretMaxOffset(focusNode), ec);
-            if (ec)
-                return String();
         } else {
-            focusNode =
-                focusNode->childNodes()->item(focusOffset)->firstDescendant();
-            if (!isVisibleNonEmptyNonWhitespaceTextNode(focusNode)) {
-                focusNode = traverseVisibleNonEmptyNonWhitespaceTextNode(
-                    focusNode, body, DIRECTION_FORWARD);
-                if (!focusNode)
+            focusNode = focusNode->traverseNextSibling();
+            if (focusNode && !isContentTextNode(focusNode)) {
+                Node* textNode = traverseNextContentTextNode(focusNode,
+                        anchorNode, DIRECTION_FORWARD);
+                if (textNode)
+                    anchorNode = textNode;
+            }
+            if (anchorNode && isContentTextNode(anchorNode)) {
+                selection->extend(focusNode, 0, ec);
+                if (ec)
                     return String();
             }
-            selection->extend(focusNode, 0, ec);
-            if (ec)
-                return String();
         }
     }
 
     // Enforce that the selection does not cross anchor boundaries. This is
     // a workaround for the asymmetric behavior of WebKit while crossing
     // anchors.
-    // NOTE: The code is asymmetric since the logic is based off the common
-    // ancestor in both directions - backward and forward.
-    // TODO: Factor out common code repeated below.
-    anchorNode = selection->anchorNode();
-    focusNode = selection->focusNode();
-    if (anchorNode != focusNode
-            && anchorNode->isTextNode()
-            && focusNode->isTextNode()) {
-        Node* commonAncestor = Range::commonAncestorContainer(anchorNode,
-            focusNode);
-        Node* currentNode = 0;
-        bool selectionAdjusted = false;
-        if (direction == DIRECTION_FORWARD) {
-            // catch if the anchor is in a link but the focus is not
-            if (!commonAncestor->hasTagName(WebCore::HTMLNames::aTag)) {
-                currentNode = anchorNode;
-                while (currentNode != commonAncestor) {
-                    if (isVisible(currentNode) && isInputControl(currentNode)) {
-                        focusNode = currentNode->lastDescendant();
-                        if (!isVisibleNonEmptyNonWhitespaceTextNode(focusNode)) {
-                            focusNode =
-                                traverseVisibleNonEmptyNonWhitespaceTextNode(
-                                    focusNode, commonAncestor,
-                                    DIRECTION_BACKWARD);
-                            if (!focusNode)
-                                return String();
-                        }
-                        selection->extend(focusNode, caretMaxOffset(focusNode),
-                            ec);
-                        if (ec)
-                            return String();
-                        selectionAdjusted = true;
-                        break;
-                    }
-                    currentNode = currentNode->parentNode();
+    anchorNode = getImplicitBoundaryNode(selection->anchorNode(),
+            selection->anchorOffset(), direction);
+    focusNode = getImplicitBoundaryNode(selection->focusNode(),
+            selection->focusOffset(), direction);
+    if (anchorNode && focusNode && anchorNode != focusNode) {
+        Node* inputControl = getIntermediaryInputElement(anchorNode, focusNode,
+                direction);
+        if (inputControl) {
+            if (direction == DIRECTION_FORWARD) {
+                if (isDescendantOf(inputControl, anchorNode)) {
+                    focusNode = inputControl;
+                } else {
+                    focusNode = inputControl->traversePreviousSiblingPostOrder(
+                            body);
+                    if (!focusNode)
+                        focusNode = inputControl;
                 }
-                // catch if there is a link between the anchor and focus
-                if (!selectionAdjusted) {
-                    currentNode = anchorNode;
-                    while (currentNode != focusNode) {
-                        if (isVisible(currentNode)
-                                && isInputControl(currentNode)) {
-                            focusNode = currentNode;
-                            if (!isVisibleNonEmptyNonWhitespaceTextNode(focusNode)) {
-                                focusNode =
-                                    traverseVisibleNonEmptyNonWhitespaceTextNode(
-                                        focusNode, commonAncestor,
-                                        DIRECTION_BACKWARD);
-                                if (!focusNode)
-                                   return String();
-                            }
-                            selection->extend(focusNode,
-                                caretMaxOffset(focusNode), ec);
-                            if (ec)
-                                return String();
-                            break;
-                        }
-                        currentNode = currentNode->traverseNextNode();
-                    }
+                // We prefer a text node contained in the input element.
+                if (!isContentTextNode(focusNode)) {
+                    Node* textNode = traverseNextContentTextNode(focusNode,
+                        anchorNode, DIRECTION_BACKWARD);
+                    if (textNode)
+                        focusNode = textNode;
                 }
-            }
-        } else {
-            // catch if the anchor is in a link but the focus is not
-            // NOTE: There is not such case in forward direction because
-            //       it is implicitly covered the second case. Also the
-            //       base position used for computing the the common
-            //       ancestor which is asymmteric.
-            if (!commonAncestor->hasTagName(WebCore::HTMLNames::aTag)) {
-                currentNode = anchorNode;
-                while (currentNode != commonAncestor) {
-                    if (isVisible(currentNode) && isInputControl(currentNode)) {
-                        focusNode = currentNode->firstDescendant();
-                        if (!isVisibleNonEmptyNonWhitespaceTextNode(focusNode)) {
-                            focusNode =
-                                traverseVisibleNonEmptyNonWhitespaceTextNode(
-                                    focusNode, commonAncestor,
-                                    DIRECTION_FORWARD);
-                             if (!focusNode)
-                                 return String();
-                        }
-                        selection->extend(focusNode, 0, ec);
-                        if (ec)
-                            return String();
-                        selectionAdjusted = true;
-                        break;
-                    }
-                    currentNode = currentNode->parentNode();
+                // If we found text in the input select it.
+                // Otherwise, select the input element itself.
+                if (isContentTextNode(focusNode)) {
+                    selection->extend(focusNode, caretMaxOffset(focusNode), ec);
+                } else if (anchorNode != focusNode) {
+                    // Note that the focusNode always has parent and that
+                    // the offset can be one more that the index of the last
+                    // element - this is how WebKit selects such elements.
+                    selection->extend(focusNode->parentNode(),
+                            focusNode->nodeIndex() + 1, ec);
                 }
-                // catch if there is a link between the anchor and focus
-                if (!selectionAdjusted) {
-                    currentNode = anchorNode;
-                    while (currentNode != focusNode) {
-                        if (isVisible(currentNode)
-                                && isInputControl(currentNode)) {
-                            focusNode = currentNode->traverseNextSibling();
-                            if (!isVisibleNonEmptyNonWhitespaceTextNode(focusNode)) {
-                                focusNode =
-                                    traverseVisibleNonEmptyNonWhitespaceTextNode(
-                                        focusNode, commonAncestor,
-                                        DIRECTION_FORWARD);
-                                if (!focusNode)
-                                    return String();
-                            }
-                            selection->extend(focusNode, 0, ec);
-                            if (ec)
-                                return String();
-                            selectionAdjusted = true;
-                            break;
-                        }
-                        currentNode = currentNode->traversePreviousNode();
-                    }
+                if (ec)
+                    return String();
+            } else {
+                if (isDescendantOf(inputControl, anchorNode)) {
+                    focusNode = inputControl;
+                } else {
+                    focusNode = inputControl->traverseNextSibling();
+                    if (!focusNode)
+                        focusNode = inputControl;
                 }
-                // catch if the focus is in a link but the anchor is not
-                if (!selectionAdjusted) {
-                    currentNode = focusNode;
-                    while (currentNode != commonAncestor) {
-                        if (isVisible(currentNode)
-                                && isInputControl(currentNode)) {
-                            focusNode = currentNode->traverseNextSibling();
-                            if (!isVisibleNonEmptyNonWhitespaceTextNode(focusNode)) {
-                                focusNode =
-                                    traverseVisibleNonEmptyNonWhitespaceTextNode(
-                                        focusNode, commonAncestor,
-                                        DIRECTION_FORWARD);
-                                if (!focusNode)
-                                    return String();
-                            }
-                            selection->extend(focusNode, 0, ec);
-                            if (ec)
-                                return String();
-                            break;
-                        }
-                        currentNode = currentNode->parentNode();
-                    }
+                // We prefer a text node contained in the input element.
+                if (!isContentTextNode(focusNode)) {
+                    Node* textNode = traverseNextContentTextNode(focusNode,
+                            anchorNode, DIRECTION_FORWARD);
+                    if (textNode)
+                        focusNode = textNode;
+                }
+                // If we found text in the input select it.
+                // Otherwise, select the input element itself.
+                if (isContentTextNode(focusNode)) {
+                    selection->extend(focusNode, caretMinOffset(focusNode), ec);
+                } else if (anchorNode != focusNode) {
+                    // Note that the focusNode always has parent and that
+                    // the offset can be one more that the index of the last
+                    // element - this is how WebKit selects such elements.
+                    selection->extend(focusNode->parentNode(),
+                            focusNode->nodeIndex() + 1, ec);
                 }
+                if (ec)
+                   return String();
             }
         }
     }
@@ -2500,30 +2352,136 @@ String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, i
         return String();
     IntRect bounds = range->boundingBox();
     selectAt(bounds.center().x(), bounds.center().y());
-    String markup = formatMarkup(selection).stripWhiteSpace();
+    markup = formatMarkup(selection);
     LOGV("Selection markup: %s", markup.utf8().data());
 
     return markup;
 }
 
-bool WebViewCore::isInputControl(Node* node)
+Node* WebViewCore::getImplicitBoundaryNode(Node* node, unsigned offset, int direction)
+{
+    if (node->offsetInCharacters())
+        return node;
+    if (!node->hasChildNodes())
+        return node;
+    if (offset < node->childNodeCount())
+        return node->childNode(offset);
+    else
+        if (direction == DIRECTION_FORWARD)
+            return node->traverseNextSibling();
+        else
+            return node->traversePreviousNodePostOrder(
+                    node->document()->body());
+}
+
+Node* WebViewCore::getNextAnchorNode(Node* anchorNode, bool ignoreFirstNode, int direction)
 {
-  return (node->hasTagName(WebCore::HTMLNames::aTag)
-      || node->hasTagName(WebCore::HTMLNames::inputTag)
-      || node->hasTagName(WebCore::HTMLNames::buttonTag));
+    Node* body = 0;
+    Node* currentNode = 0;
+    if (direction == DIRECTION_FORWARD) {
+        if (ignoreFirstNode)
+            currentNode = anchorNode->traverseNextNode(body);
+        else
+            currentNode = anchorNode;
+    } else {
+        body = anchorNode->document()->body();
+        if (ignoreFirstNode)
+            currentNode = anchorNode->traversePreviousSiblingPostOrder(body);
+        else
+            currentNode = anchorNode;
+    }
+    while (currentNode) {
+        if (isContentTextNode(currentNode)
+                || isContentInputElement(currentNode))
+            return currentNode;
+        if (direction == DIRECTION_FORWARD)
+            currentNode = currentNode->traverseNextNode();
+        else
+            currentNode = currentNode->traversePreviousNodePostOrder(body);
+    }
+    return 0;
 }
 
-int WebViewCore::rangeCompliantChildOffset(Node* parent, int offset)
+void WebViewCore::advanceAnchorNode(DOMSelection* selection, int direction,
+        String& markup, bool ignoreFirstNode, ExceptionCode& ec)
 {
-    if (offset < 0)
-        return 0;
-    int lastChildIndex = parent->childNodes()->length() - 1;
-    if (offset > lastChildIndex)
-        return lastChildIndex;
-    return offset;
+    Node* anchorNode = getImplicitBoundaryNode(selection->anchorNode(),
+            selection->anchorOffset(), direction);
+    if (!anchorNode) {
+        ec = NOT_FOUND_ERR;
+        return;
+    }
+    // If the anchor offset is invalid i.e. the anchor node has no
+    // child with that index getImplicitAnchorNode returns the next
+    // logical node in the current direction. In such a case our
+    // position in the DOM tree was has already been advanced,
+    // therefore we there is no need to do that again.
+    if (selection->anchorNode()->isElementNode()) {
+        unsigned anchorOffset = selection->anchorOffset();
+        unsigned childNodeCount = selection->anchorNode()->childNodeCount();
+        if (anchorOffset >= childNodeCount)
+            ignoreFirstNode = false;
+    }
+    // Find the next anchor node given our position in the DOM and
+    // whether we want the current node to be considered as well.
+    Node* nextAnchorNode = getNextAnchorNode(anchorNode, ignoreFirstNode,
+            direction);
+    if (!nextAnchorNode) {
+        ec = NOT_FOUND_ERR;
+        return;
+    }
+    if (nextAnchorNode->isElementNode()) {
+        // If this is an input element tell the WebView thread
+        // to set the cursor to that control.
+        if (isContentInputElement(nextAnchorNode)) {
+            IntRect bounds = nextAnchorNode->getRect();
+            selectAt(bounds.center().x(), bounds.center().y());
+        }
+        Node* textNode = 0;
+        // Treat the text content of links as any other text but
+        // for the rest input elements select the control itself.
+        if (nextAnchorNode->hasTagName(WebCore::HTMLNames::aTag))
+            textNode = traverseNextContentTextNode(nextAnchorNode,
+                    nextAnchorNode, direction);
+        // We prefer to select the text content of the link if such,
+        // otherwise just select the element itself.
+        if (textNode) {
+            nextAnchorNode = textNode;
+        } else {
+            if (direction == DIRECTION_FORWARD) {
+                selection->setBaseAndExtent(nextAnchorNode,
+                        caretMinOffset(nextAnchorNode), nextAnchorNode,
+                        caretMaxOffset(nextAnchorNode), ec);
+            } else {
+                selection->setBaseAndExtent(nextAnchorNode,
+                        caretMaxOffset(nextAnchorNode), nextAnchorNode,
+                        caretMinOffset(nextAnchorNode), ec);
+            }
+            if (!ec)
+                markup = formatMarkup(selection);
+            // make sure the selection is visible
+            scrollNodeIntoView(selection->frame(), nextAnchorNode);
+            return;
+        }
+    }
+    if (direction == DIRECTION_FORWARD)
+        selection->setPosition(nextAnchorNode,
+                caretMinOffset(nextAnchorNode), ec);
+    else
+        selection->setPosition(nextAnchorNode,
+                caretMaxOffset(nextAnchorNode), ec);
 }
 
-bool WebViewCore::isVisibleNonEmptyNonWhitespaceTextNode(Node* node)
+bool WebViewCore::isContentInputElement(Node* node)
+{
+  return (isVisible(node)
+          && (node->hasTagName(WebCore::HTMLNames::selectTag)
+          || node->hasTagName(WebCore::HTMLNames::aTag)
+          || node->hasTagName(WebCore::HTMLNames::inputTag)
+          || node->hasTagName(WebCore::HTMLNames::buttonTag)));
+}
+
+bool WebViewCore::isContentTextNode(Node* node)
 {
    if (!node || !node->isTextNode())
        return false;
@@ -2532,21 +2490,66 @@ bool WebViewCore::isVisibleNonEmptyNonWhitespaceTextNode(Node* node)
        && !textNode->containsOnlyWhitespace());
 }
 
-Text* WebViewCore::traverseVisibleNonEmptyNonWhitespaceTextNode(Node* fromNode, Node* toNode, int direction)
+Text* WebViewCore::traverseNextContentTextNode(Node* fromNode, Node* toNode, int direction)
 {
     Node* currentNode = fromNode;
     do {
         if (direction == DIRECTION_FORWARD)
             currentNode = currentNode->traverseNextNode(toNode);
         else
-            currentNode = currentNode->traversePreviousNode(toNode);
-    } while (currentNode && !isVisibleNonEmptyNonWhitespaceTextNode(currentNode));
+            currentNode = currentNode->traversePreviousNodePostOrder(toNode);
+    } while (currentNode && !isContentTextNode(currentNode));
     return static_cast<Text*>(currentNode);
 }
 
+Node* WebViewCore::getIntermediaryInputElement(Node* fromNode, Node* toNode, int direction)
+{
+    if (fromNode == toNode)
+        return 0;
+    if (direction == DIRECTION_FORWARD) {
+        Node* currentNode = fromNode;
+        while (currentNode && currentNode != toNode) {
+            if (isContentInputElement(currentNode))
+                return currentNode;
+            currentNode = currentNode->traverseNextNodePostOrder();
+        }
+        currentNode = fromNode;
+        while (currentNode && currentNode != toNode) {
+            if (isContentInputElement(currentNode))
+                return currentNode;
+            currentNode = currentNode->traverseNextNode();
+        }
+    } else {
+        Node* currentNode = fromNode->traversePreviousNode();
+        while (currentNode && currentNode != toNode) {
+            if (isContentInputElement(currentNode))
+                return currentNode;
+            currentNode = currentNode->traversePreviousNode();
+        }
+        currentNode = fromNode->traversePreviousNodePostOrder();
+        while (currentNode && currentNode != toNode) {
+            if (isContentInputElement(currentNode))
+                return currentNode;
+            currentNode = currentNode->traversePreviousNodePostOrder();
+        }
+    }
+    return 0;
+}
+
+bool WebViewCore::isDescendantOf(Node* parent, Node* node)
+{
+    Node* currentNode = node;
+    while (currentNode) {
+        if (currentNode == parent) {
+            return true;
+        }
+        currentNode = currentNode->parentNode();
+    }
+    return false;
+}
+
 String WebViewCore::modifySelectionDomNavigationAxis(DOMSelection* selection, int direction, int axis)
 {
-    // TODO: Add support of IFrames.
     HTMLElement* body = m_mainFrame->document()->body();
     if (!m_currentNodeDomNavigationAxis && selection->focusNode()) {
         m_currentNodeDomNavigationAxis = selection->focusNode();
@@ -2639,12 +2642,27 @@ bool WebViewCore::isHeading(Node* node)
 
 bool WebViewCore::isVisible(Node* node)
 {
-    // TODO: Use DOMWindow#getComputedStyle instead.
+    // start off an element
+    Element* element = 0;
+    if (node->isElementNode())
+        element = static_cast<Element*>(node);
+    else
+        element = node->parentElement();
+    // check renderer
+    if (!element->renderer()) {
+        return false;
+    }
+    // check size
+    if (element->offsetHeight() == 0 || element->offsetWidth() == 0) {
+        return false;
+    }
+    // check style
     Node* body = m_mainFrame->document()->body();
-    Node* currentNode = node;
+    Node* currentNode = element;
     while (currentNode && currentNode != body) {
         RenderStyle* style = currentNode->computedStyle();
-        if (style->display() == NONE || style->visibility() == HIDDEN) {
+        if (style &&
+                (style->display() == NONE || style->visibility() == HIDDEN)) {
             return false;
         }
         currentNode = currentNode->parentNode();
@@ -2656,52 +2674,48 @@ String WebViewCore::formatMarkup(DOMSelection* selection)
 {
     ExceptionCode ec = 0;
     String markup = String();
-
     PassRefPtr<Range> wholeRange = selection->getRangeAt(0, ec);
     if (ec)
-        return markup;
-
+        return String();
     if (!wholeRange->startContainer() || !wholeRange->startContainer())
-        return markup;
-
+        return String();
     // Since formatted markup contains invisible nodes it
     // is created from the concatenation of the visible fragments.
     Node* firstNode = wholeRange->firstNode();
     Node* pastLastNode = wholeRange->pastLastNode();
     Node* currentNode = firstNode;
     PassRefPtr<Range> currentRange;
+
     while (currentNode != pastLastNode) {
         Node* nextNode = currentNode->traverseNextNode();
         if (!isVisible(currentNode)) {
             if (currentRange) {
-                markup = markup + stripAppleSpanFromMarkup(
-                    currentRange->toHTML()).utf8().data();
+                markup = markup + currentRange->toHTML().utf8().data();
                 currentRange = 0;
             }
         } else {
             if (!currentRange) {
                 currentRange = selection->frame()->document()->createRange();
                 if (ec)
-                    return markup;
+                    break;
                 if (currentNode == firstNode) {
                     currentRange->setStart(wholeRange->startContainer(),
                         wholeRange->startOffset(), ec);
                     if (ec)
-                        return markup;
+                        break;
                 } else {
                     currentRange->setStart(currentNode->parentNode(),
                         currentNode->nodeIndex(), ec);
                     if (ec)
-                       return markup;
+                       break;
                 }
             }
             if (nextNode == pastLastNode) {
                 currentRange->setEnd(wholeRange->endContainer(),
                     wholeRange->endOffset(), ec);
                 if (ec)
-                    return markup;
-                markup = markup + stripAppleSpanFromMarkup(
-                    currentRange->toHTML()).utf8().data();
+                    break;
+                markup = markup + currentRange->toHTML().utf8().data();
             } else {
                 if (currentNode->offsetInCharacters())
                     currentRange->setEnd(currentNode,
@@ -2710,24 +2724,12 @@ String WebViewCore::formatMarkup(DOMSelection* selection)
                     currentRange->setEnd(currentNode->parentNode(),
                             currentNode->nodeIndex() + 1, ec);
                 if (ec)
-                    return markup;
+                    break;
             }
         }
         currentNode = nextNode;
     }
-    return markup;
-}
-
-String WebViewCore::stripAppleSpanFromMarkup(String markup)
-{
-  int fromIdx = markup.find("<span class=\"Apple-style-span\"");
-  while (fromIdx > -1) {
-      int toIdx = markup.find(">");
-      markup = markup.replace(fromIdx, toIdx - fromIdx + 1, "");
-      markup = markup.replace("</span>", "");
-      fromIdx = markup.find("<span class=\"Apple-style-span\"");
-  }
-  return markup;
+    return markup.stripWhiteSpace();
 }
 
 void WebViewCore::selectAt(int x, int y)
@@ -2738,32 +2740,6 @@ void WebViewCore::selectAt(int x, int y)
     checkException(env);
 }
 
-Node* WebViewCore::getFirstIntermediaryInputOrButton(Node* fromNode, Node* toNode)
-{
-    // do bidirectional traversal to catch the case in which
-    // the toNode is a descendant of a control but the fromNode
-    // is not and the other way around
-    Node* currentNode = fromNode->traverseNextNode();
-    while (currentNode && currentNode != toNode) {
-        if (isVisible(currentNode)
-            && (currentNode->hasTagName(WebCore::HTMLNames::inputTag)
-            || currentNode->hasTagName(WebCore::HTMLNames::buttonTag))) {
-          return currentNode;
-        }
-        currentNode = currentNode->traverseNextNode();
-    }
-    currentNode = fromNode->traverseNextNodePostOrder();
-    while (currentNode && currentNode != toNode) {
-        if (isVisible(currentNode)
-                && (currentNode->hasTagName(WebCore::HTMLNames::inputTag)
-                || currentNode->hasTagName(WebCore::HTMLNames::buttonTag))) {
-            return currentNode;
-        }
-        currentNode = currentNode->traverseNextNodePostOrder();
-    }
-    return 0;
-}
-
 void WebViewCore::deleteSelection(int start, int end, int textGeneration)
 {
     setSelection(start, end);
@@ -2783,6 +2759,7 @@ void WebViewCore::deleteSelection(int start, int end, int textGeneration)
     key(up);
     client->setUiGeneratedSelectionChange(false);
     m_textGeneration = textGeneration;
+    m_shouldPaintCaret = true;
 }
 
 void WebViewCore::replaceTextfieldText(int oldStart,
@@ -2804,6 +2781,7 @@ void WebViewCore::replaceTextfieldText(int oldStart,
     // 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,
@@ -2843,6 +2821,7 @@ void WebViewCore::passToJs(int generation, const WTF::String& current,
     }
     // Now that the selection has settled down, send it.
     updateTextSelection();
+    m_shouldPaintCaret = true;
 }
 
 void WebViewCore::scrollFocusedTextInput(float xPercent, int y)
@@ -2888,94 +2867,6 @@ void WebViewCore::saveDocumentState(WebCore::Frame* frame)
     }
 }
 
-// Convert a WTF::String into an array of characters where the first
-// character represents the length, for easy conversion to java.
-static uint16_t* stringConverter(const WTF::String& text)
-{
-    size_t length = text.length();
-    uint16_t* itemName = new uint16_t[length+1];
-    itemName[0] = (uint16_t)length;
-    uint16_t* firstChar = &(itemName[1]);
-    memcpy((void*)firstChar, text.characters(), sizeof(UChar)*length);
-    return itemName;
-}
-
-// Response to dropdown created for a listbox.
-class ListBoxReply : public WebCoreReply {
-public:
-    ListBoxReply(WebCore::HTMLSelectElement* select, WebCore::Frame* frame, WebViewCore* view)
-        : m_select(select)
-        , m_frame(frame)
-        , m_viewImpl(view)
-    {}
-
-    // Response used for a multiple selection listbox if the user did not change
-    // anything, in which case -2 is used.
-    // Also used by a listbox which has single selection but a size is set.
-    virtual void replyInt(int index)
-    {
-        if (-2 == index) {
-            // Special value for cancel. Do nothing.
-            return;
-        }
-        // If the select element no longer exists, due to a page change, etc,
-        // silently return.
-        if (!m_select || !CacheBuilder::validNode(m_viewImpl->m_mainFrame,
-                m_frame, m_select))
-            return;
-        // Use a pointer to HTMLSelectElement's superclass, where
-        // listToOptionIndex is public
-        SelectElement* selectElement = m_select;
-        int optionIndex = selectElement->listToOptionIndex(index);
-        m_select->setSelectedIndex(optionIndex, true);
-        m_select->dispatchFormControlChangeEvent();
-        m_viewImpl->contentInvalidate(m_select->getRect());
-    }
-
-    // Response if the listbox allows multiple selection.  array stores the listIndices
-    // of selected positions.
-    virtual void replyIntArray(const int* array, int count)
-    {
-        // If the select element no longer exists, due to a page change, etc,
-        // silently return.
-        if (!m_select || !CacheBuilder::validNode(m_viewImpl->m_mainFrame,
-                m_frame, m_select))
-            return;
-
-        const WTF::Vector<Element*>& items = m_select->listItems();
-        int totalItems = static_cast<int>(items.size());
-        // Keep track of the position of the value we are comparing against.
-        int arrayIndex = 0;
-        // The value we are comparing against.
-        int selection = array[arrayIndex];
-        WebCore::HTMLOptionElement* option;
-        for (int listIndex = 0; listIndex < totalItems; listIndex++) {
-            if (items[listIndex]->hasLocalName(WebCore::HTMLNames::optionTag)) {
-                option = static_cast<WebCore::HTMLOptionElement*>(
-                        items[listIndex]);
-                if (listIndex == selection) {
-                    option->setSelectedState(true);
-                    arrayIndex++;
-                    if (arrayIndex == count)
-                        selection = -1;
-                    else
-                        selection = array[arrayIndex];
-                } else
-                    option->setSelectedState(false);
-            }
-        }
-        m_select->dispatchFormControlChangeEvent();
-        m_viewImpl->contentInvalidate(m_select->getRect());
-    }
-private:
-    // The select element associated with this listbox.
-    WebCore::HTMLSelectElement* m_select;
-    // The frame of this select element, to verify that it is valid.
-    WebCore::Frame* m_frame;
-    // For calling invalidate and checking the select element's validity
-    WebViewCore* m_viewImpl;
-};
-
 // Create an array of java Strings.
 static jobjectArray makeLabelArray(JNIEnv* env, const uint16_t** labels, size_t count)
 {
@@ -3226,51 +3117,6 @@ void WebViewCore::touchUp(int touchGeneration,
     handleMouseClick(frame, node, false);
 }
 
-// Return the RenderLayer for the given RenderObject only if the layer is
-// composited and it contains a scrollable content layer.
-static WebCore::RenderLayer* getScrollingLayerFromRenderer(
-        WebCore::RenderObject* renderer)
-{
-#if ENABLE(ANDROID_OVERFLOW_SCROLL)
-    if (!renderer)
-        return 0;
-    WebCore::RenderLayer* layer = renderer->enclosingSelfPaintingLayer();
-    if (!layer)
-        return 0;
-    // Find the layer that actually has overflow scroll in case this renderer is
-    // inside a child layer.
-    while (layer && !layer->hasOverflowScroll())
-        layer = layer->parent();
-    return layer;
-#endif
-    return 0;
-}
-
-// Scroll the RenderLayer associated with a scrollable div element.  This is
-// done so that the node is visible when it is clicked.
-static void scrollLayer(WebCore::RenderObject* renderer, WebCore::IntPoint* pos)
-{
-    WebCore::RenderLayer* layer = getScrollingLayerFromRenderer(renderer);
-    if (!layer)
-        return;
-    // The cache uses absolute coordinates when clicking on nodes and it assumes
-    // the layer is not scrolled.
-    layer->scrollToOffset(0, 0, true, false);
-
-    WebCore::IntRect absBounds = renderer->absoluteBoundingBoxRect();
-    // Do not include the outline when moving the node's bounds.
-    WebCore::IntRect layerBounds = layer->renderer()->absoluteBoundingBoxRect();
-
-    // Move the node's bounds into the layer's coordinates.
-    absBounds.move(-layerBounds.x(), -layerBounds.y());
-
-    // Scroll the layer to the node's position.
-    layer->scrollToOffset(absBounds.x(), absBounds.y(), true, true);
-
-    // Update the mouse position to the layer offset.
-    pos->move(-layer->scrollXOffset(), -layer->scrollYOffset());
-}
-
 // 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
@@ -3289,47 +3135,6 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node
             DBG_NAV_LOG("area");
             return true;
         }
-
-        WebCore::RenderObject* renderer = nodePtr->renderer();
-        if (renderer && renderer->isListBox()) {
-            WebCore::HTMLSelectElement* select = static_cast<WebCore::HTMLSelectElement*>(nodePtr);
-            const WTF::Vector<WebCore::Element*>& listItems = select->listItems();
-            SkTDArray<const uint16_t*> names;
-            // Possible values for enabledArray.  Keep in Sync with values in
-            // InvokeListBox.Container in WebView.java
-            enum OptionStatus {
-                OPTGROUP = -1,
-                OPTION_DISABLED = 0,
-                OPTION_ENABLED = 1,
-            };
-            SkTDArray<int> enabledArray;
-            SkTDArray<int> selectedArray;
-            int size = listItems.size();
-            bool multiple = select->multiple();
-            for (int i = 0; i < size; i++) {
-                if (listItems[i]->hasTagName(WebCore::HTMLNames::optionTag)) {
-                    WebCore::HTMLOptionElement* option = static_cast<WebCore::HTMLOptionElement*>(listItems[i]);
-                    *names.append() = stringConverter(option->textIndentedToRespectGroupLabel());
-                    *enabledArray.append() = option->disabled() ? OPTION_DISABLED : OPTION_ENABLED;
-                    if (multiple && option->selected())
-                        *selectedArray.append() = i;
-                } else if (listItems[i]->hasTagName(WebCore::HTMLNames::optgroupTag)) {
-                    WebCore::HTMLOptGroupElement* optGroup = static_cast<WebCore::HTMLOptGroupElement*>(listItems[i]);
-                    *names.append() = stringConverter(optGroup->groupLabelText());
-                    *enabledArray.append() = OPTGROUP;
-                }
-            }
-            WebCoreReply* reply = new ListBoxReply(select, select->document()->frame(), this);
-            // Use a pointer to HTMLSelectElement's superclass, where
-            // optionToListIndex is public.
-            SelectElement* selectElement = select;
-            listBoxRequest(reply, names.begin(), size, enabledArray.begin(), enabledArray.count(),
-                    multiple, selectedArray.begin(), multiple ? selectedArray.count() :
-                    selectElement->optionToListIndex(select->selectedIndex()));
-            DBG_NAV_LOG("list box");
-            return true;
-        }
-        scrollLayer(renderer, &m_mousePos);
     }
     if (!valid || !framePtr)
         framePtr = m_mainFrame;
@@ -3418,15 +3223,15 @@ void WebViewCore::formDidBlur(const WebCore::Node* node)
 
 void WebViewCore::focusNodeChanged(const WebCore::Node* newFocus)
 {
-    if (!m_blurringNodePointer)
-        return;
-    if (!isTextInput(newFocus)) {
+    if (isTextInput(newFocus))
+        m_shouldPaintCaret = true;
+    else if (m_blurringNodePointer) {
         JNIEnv* env = JSC::Bindings::getJNIEnv();
         env->CallVoidMethod(m_javaGlue->object(env).get(),
                 m_javaGlue->m_formDidBlur, m_blurringNodePointer);
         checkException(env);
+        m_blurringNodePointer = 0;
     }
-    m_blurringNodePointer = 0;
 }
 
 void WebViewCore::addMessageToConsole(const WTF::String& message, unsigned int lineNumber, const WTF::String& sourceID, int msgLevel) {
@@ -3537,13 +3342,13 @@ bool WebViewCore::jsConfirm(const WTF::String& url, const WTF::String& text)
 bool WebViewCore::jsPrompt(const WTF::String& url, const WTF::String& text, const WTF::String& defaultValue, WTF::String& result)
 {
     JNIEnv* env = JSC::Bindings::getJNIEnv();
+    jstring jUrlStr = wtfStringToJstring(env, url);
     jstring jInputStr = wtfStringToJstring(env, text);
     jstring jDefaultStr = wtfStringToJstring(env, defaultValue);
-    jstring jUrlStr = wtfStringToJstring(env, url);
     jstring returnVal = static_cast<jstring>(env->CallObjectMethod(m_javaGlue->object(env).get(), m_javaGlue->m_jsPrompt, jUrlStr, jInputStr, jDefaultStr));
+    env->DeleteLocalRef(jUrlStr);
     env->DeleteLocalRef(jInputStr);
     env->DeleteLocalRef(jDefaultStr);
-    env->DeleteLocalRef(jUrlStr);
     checkException(env);
 
     // If returnVal is null, it means that the user cancelled the dialog.
@@ -3551,6 +3356,7 @@ bool WebViewCore::jsPrompt(const WTF::String& url, const WTF::String& text, cons
         return false;
 
     result = jstringToWtfString(env, returnVal);
+    env->DeleteLocalRef(returnVal);
     return true;
 }
 
@@ -3795,10 +3601,12 @@ void WebViewCore::notifyWebAppCanBeInstalled()
 
 void WebViewCore::setWebTextViewAutoFillable(int queryId, const string16& previewSummary)
 {
+#if ENABLE(WEB_AUTOFILL)
     JNIEnv* env = JSC::Bindings::getJNIEnv();
     jstring preview = env->NewString(previewSummary.data(), previewSummary.length());
     env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_setWebTextViewAutoFillable, queryId, preview);
     env->DeleteLocalRef(preview);
+#endif
 }
 
 bool WebViewCore::drawIsPaused() const
@@ -3838,6 +3646,27 @@ WebRequestContext* WebViewCore::webRequestContext()
 }
 #endif
 
+void WebViewCore::scrollRenderLayer(int layer, const SkRect& rect)
+{
+#if USE(ACCELERATED_COMPOSITING)
+    GraphicsLayerAndroid* root = graphicsRootLayer();
+    if (!root)
+        return;
+
+    LayerAndroid* layerAndroid = root->platformLayer();
+    if (!layerAndroid)
+        return;
+
+    LayerAndroid* target = layerAndroid->findById(layer);
+    if (!target)
+        return;
+
+    RenderLayer* owner = target->owningLayer();
+    if (owner)
+        owner->scrollToOffset(rect.fLeft, rect.fTop, true, false);
+#endif
+}
+
 //----------------------------------------------------------------------
 // Native JNI methods
 //----------------------------------------------------------------------
@@ -3881,7 +3710,7 @@ static void SetSize(JNIEnv *env, jobject obj, jint width, jint height,
             screenWidth, screenHeight, anchorX, anchorY, ignoreHeight);
 }
 
-static void SetScrollOffset(JNIEnv *env, jobject obj, jint gen, jint userScrolled, jint x, jint y)
+static void SetScrollOffset(JNIEnv *env, jobject obj, jint gen, jboolean sendScrollEvent, jint x, jint y)
 {
 #ifdef ANDROID_INSTRUMENT
     TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
@@ -3889,7 +3718,7 @@ static void SetScrollOffset(JNIEnv *env, jobject obj, jint gen, jint userScrolle
     WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
     LOG_ASSERT(viewImpl, "need viewImpl");
 
-    viewImpl->setScrollOffset(gen, userScrolled, x, y);
+    viewImpl->setScrollOffset(gen, sendScrollEvent, x, y);
 }
 
 static void SetGlobalBounds(JNIEnv *env, jobject obj, jint x, jint y, jint h,
@@ -4192,6 +4021,11 @@ static jstring RetrieveImageSource(JNIEnv *env, jobject obj, jint x, jint y)
     return !result.isEmpty() ? wtfStringToJstring(env, result) : 0;
 }
 
+static void StopPaintingCaret(JNIEnv *env, jobject obj)
+{
+    GET_NATIVE_VIEW(env, obj)->setShouldPaintCaret(false);
+}
+
 static void MoveFocus(JNIEnv *env, jobject obj, jint framePtr, jint nodePtr)
 {
 #ifdef ANDROID_INSTRUMENT
@@ -4519,6 +4353,13 @@ static void AutoFillForm(JNIEnv* env, jobject obj, jint queryId)
 #endif
 }
 
+static void ScrollRenderLayer(JNIEnv* env, jobject obj, jint layer, jobject jRect)
+{
+    SkRect rect;
+    GraphicsJNI::jrect_to_rect(env, jRect, &rect);
+    GET_NATIVE_VIEW(env, obj)->scrollRenderLayer(layer, rect);
+}
+
 // ----------------------------------------------------------------------------
 
 /*
@@ -4541,7 +4382,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
         (void*) SendListBoxChoice },
     { "nativeSetSize", "(IIIFIIIIZ)V",
         (void*) SetSize },
-    { "nativeSetScrollOffset", "(IIII)V",
+    { "nativeSetScrollOffset", "(IZII)V",
         (void*) SetScrollOffset },
     { "nativeSetGlobalBounds", "(IIII)V",
         (void*) SetGlobalBounds },
@@ -4579,6 +4420,8 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
         (void*) RetrieveAnchorText },
     { "nativeRetrieveImageSource", "(II)Ljava/lang/String;",
         (void*) RetrieveImageSource },
+    { "nativeStopPaintingCaret", "()V",
+        (void*) StopPaintingCaret },
     { "nativeUpdateFrameCache", "()V",
         (void*) UpdateFrameCache },
     { "nativeGetContentMinPrefWidth", "()I",
@@ -4626,6 +4469,8 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
         (void*) GetTouchHighlightRects },
     { "nativeAutoFillForm", "(I)V",
         (void*) AutoFillForm },
+    { "nativeScrollLayer", "(ILandroid/graphics/Rect;)V",
+        (void*) ScrollRenderLayer },
 };
 
 int registerWebViewCore(JNIEnv* env)
index 5820dc5..be8de94 100644 (file)
@@ -149,14 +149,6 @@ namespace android {
         void scrollTo(int x, int y, bool animate = false);
 
         /**
-         * Scroll to the point x,y relative to the current position.
-         * @param x The relative x position.
-         * @param y The relative y position.
-         * @param animate If it is true, animate to the new scroll position
-         */
-        void scrollBy(int x, int y, bool animate);
-
-        /**
          * Record the invalid rectangle
          */
         void contentInvalidate(const WebCore::IntRect &rect);
@@ -311,7 +303,7 @@ namespace android {
             WebCore::Frame* frame, int x, int y);
 
         // set the scroll amount that webview.java is currently showing
-        void setScrollOffset(int moveGeneration, int userScrolled, int dx, int dy);
+        void setScrollOffset(int moveGeneration, bool sendScrollEvent, int dx, int dy);
 
         void setGlobalBounds(int x, int y, int h, int v);
 
@@ -554,6 +546,8 @@ namespace android {
         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; }
 
         // these members are shared with webview.cpp
         static Mutex gFrameCacheMutex;
@@ -579,15 +573,19 @@ namespace android {
         bool isPaused() const { return m_isPaused; }
         void setIsPaused(bool isPaused) { m_isPaused = isPaused; }
         bool drawIsPaused() const;
-        int  visibleScreenWidth() const { return m_visibleScreenWidth; }
-        int  visibleScreenHeight() const { return m_visibleScreenHeight; }
-        void  setVisibleScreenWidth(int w) {  m_visibleScreenWidth = w; }
-        void  setVisibleScreenHeight(int h) {  m_visibleScreenHeight = h; }
+        // 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);
+
         // end of shared members
 
         // internal functions
@@ -638,11 +636,6 @@ namespace android {
         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
-        // The m_screenHeight is not equal to the visibleRect from WebView,
-        // using m_visibleScreenHeight to store that info.
-        // After we can fix the m_screenHeight in java side, we can merge them.
-        int m_visibleScreenWidth;
-        int m_visibleScreenHeight;
         int m_textWrapWidth;
         float m_scale;
         unsigned m_domtree_version;
@@ -650,6 +643,7 @@ namespace android {
         PageGroup* m_groupForVisitedLinks;
         bool m_isPaused;
         int m_cacheMode;
+        bool m_shouldPaintCaret;
 
         SkTDArray<PluginWidgetAndroid*> m_plugins;
         WebCore::Timer<WebViewCore> m_pluginInvalTimer;
@@ -677,18 +671,20 @@ namespace android {
         // below are members responsible for accessibility support
         String modifySelectionTextNavigationAxis(DOMSelection* selection, int direction, int granularity);
         String modifySelectionDomNavigationAxis(DOMSelection* selection, int direction, int granularity);
-        Text* traverseVisibleNonEmptyNonWhitespaceTextNode(Node* fromNode, Node* toNode ,int direction);
+        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);
         Node* m_currentNodeDomNavigationAxis;
         void scrollNodeIntoView(Frame* frame, Node* node);
-        bool isVisibleNonEmptyNonWhitespaceTextNode(Node* node);
-        String stripAppleSpanFromMarkup(String markup);
-        int rangeCompliantChildOffset(Node* parent, int offset);
-        Node* getFirstIntermediaryInputOrButton(Node* fromNode, Node* toNode);
-        bool isInputControl(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);
 
 #if ENABLE(TOUCH_EVENTS)
         bool m_forwardingTouchEvents;
index 56bce1e..d2ae0a4 100644 (file)
@@ -547,6 +547,7 @@ void CacheBuilder::Debug::groups() {
             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, 
@@ -556,7 +557,7 @@ void CacheBuilder::Debug::groups() {
             } else {
                 IntRect nodeBounds = node->getRect();
                 if (CacheBuilder::ConstructPartRects(node, nodeBounds, rectPtr, 
-                        globalOffsetX, globalOffsetY, &rects) == false)
+                        globalOffsetX, globalOffsetY, &rects, &imageCount) == false)
                     continue;
             }
             unsigned arraySize = rects.size();
@@ -592,8 +593,8 @@ void CacheBuilder::Debug::groups() {
                         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 ", 
-                            baseline, ++rectIndex);
+                        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();
@@ -1129,6 +1130,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
         bool isFocus = node == focused;
         bool takesFocus = false;
         int columnGap = 0;
+        int imageCount = 0;
         TextDirection direction = LTR;
         String exported;
         CachedNodeType type = NORMAL_CACHEDNODETYPE;
@@ -1328,7 +1330,8 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
             cachedNode.setBounds(bounds);
             cachedNode.mCursorRing.append(bounds);
         } else if (ConstructPartRects(node, bounds, &cachedNode.mBounds,
-                globalOffsetX, globalOffsetY, &cachedNode.mCursorRing) == false)
+                globalOffsetX, globalOffsetY, &cachedNode.mCursorRing,
+                &imageCount) == false)
             continue;
     keepTextNode:
         if (nodeRenderer) { // area tags' node->renderer() == 0
@@ -1412,6 +1415,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
         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) {
@@ -3024,7 +3028,8 @@ bool CacheBuilder::AddPartRect(IntRect& bounds, int x, int y,
 }
 
 bool CacheBuilder::ConstructPartRects(Node* node, const IntRect& bounds, 
-    IntRect* focusBounds, int x, int y, WTF::Vector<IntRect>* result)
+    IntRect* focusBounds, int x, int y, WTF::Vector<IntRect>* result,
+    int* imageCountPtr)
 {
     WTF::Vector<ClipColumnTracker> clipTracker(1);
     ClipColumnTracker* baseTracker = clipTracker.data(); // sentinel
@@ -3075,6 +3080,7 @@ bool CacheBuilder::ConstructPartRects(Node* node, const IntRect& bounds,
                 bounds.intersect(clipBounds);
                 if (AddPartRect(bounds, x, y, result, focusBounds) == false)
                     return false;
+                *imageCountPtr += 1;
                 continue;
             } 
             if (hasClip == false) {
index d229df0..d48a045 100644 (file)
@@ -83,7 +83,8 @@ public:
     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);
+        IntRect* focusBounds, int x, int y, WTF::Vector<IntRect>* result,
+        int* imageCountPtr);
     Node* currentFocus() const;
     void disallowAddressDetection() { mAllowableTypes = (CachedNodeBits) (
         mAllowableTypes & ~ADDRESS_CACHEDNODE_BIT); }
index b25ad7d..b26e24b 100644 (file)
@@ -65,24 +65,6 @@ WebCore::IntRect CachedFrame::adjustBounds(const CachedNode* node,
     return rect;
 }
 
-// This is for nodes inside a layer.  It takes an IntRect that has been
-// adjusted by the layer's position and removes the adjustment made by the
-// layer.
-WebCore::IntRect CachedFrame::unadjustBounds(const CachedNode* node,
-    const WebCore::IntRect& rect) const
-{
-#if USE(ACCELERATED_COMPOSITING)
-    if (node->isInLayer()) {
-        const CachedLayer* cachedLayer = layer(node);
-        const WebCore::LayerAndroid* rootLayer = mRoot->rootLayer();
-        const LayerAndroid* aLayer = cachedLayer->layer(rootLayer);
-        if (aLayer)
-            return cachedLayer->unadjustBounds(rootLayer, rect);
-    }
-#endif
-    return rect;
-}
-
 bool CachedFrame::CheckBetween(Direction direction, const WebCore::IntRect& bestRect,
         const WebCore::IntRect& prior, WebCore::IntRect* result)
 {
@@ -153,11 +135,9 @@ bool CachedFrame::checkBetween(BestData* best, Direction direction)
 }
 
 bool CachedFrame::checkRings(const CachedNode* node,
-        const WTF::Vector<WebCore::IntRect>& rings,
-        const WebCore::IntRect& nodeBounds,
         const WebCore::IntRect& testBounds) const
 {
-    return mRoot->checkRings(picture(node), rings, nodeBounds, testBounds);
+    return mRoot->checkRings(picture(node), node, testBounds);
 }
 
 bool CachedFrame::checkVisited(const CachedNode* node, Direction direction) const
@@ -437,7 +417,6 @@ const CachedNode* CachedFrame::findBestAt(const WebCore::IntRect& rect,
                         *directHit = test;
                         *directHitFramePtr = this;
                         IntRect r(center, IntSize(0, 0));
-                        r = unadjustBounds(test, r);
                         *x = r.x();
                         *y = r.y();
                     } else {
@@ -482,7 +461,6 @@ const CachedNode* CachedFrame::findBestAt(const WebCore::IntRect& rect,
                     *inside = testInside;
                     result = test;
                     *framePtr = this;
-                    both = unadjustBounds(test, both);
                     *x = both.x() + (both.width() >> 1);
                     *y = both.y() + (both.height() >> 1);
                 }
@@ -554,7 +532,6 @@ const CachedNode* CachedFrame::findBestHitAt(const WebCore::IntRect& rect,
             if (cursorRect.intersects(rect)) {
                 WebCore::IntRect intersection(cursorRect);
                 intersection.intersect(rect);
-                intersection = unadjustBounds(test, intersection);
                 *x = intersection.x() + (intersection.width() >> 1);
                 *y = intersection.y() + (intersection.height() >> 1);
                 *framePtr = this;
index 8ca73cf..039a0ee 100644 (file)
@@ -80,11 +80,7 @@ public:
     void addFrame(CachedFrame& child) { mCachedFrames.append(child); }
     WebCore::IntRect adjustBounds(const CachedNode* ,
         const WebCore::IntRect& ) const;
-    WebCore::IntRect unadjustBounds(const CachedNode*,
-        const WebCore::IntRect& ) const;
     bool checkRings(const CachedNode* node,
-        const WTF::Vector<WebCore::IntRect>& rings,
-        const WebCore::IntRect& nodeBounds,
         const WebCore::IntRect& testBounds) const;
     bool checkVisited(const CachedNode* , CachedFrame::Direction ) const;
     size_t childCount() { return mCachedFrames.size(); }
index c8220b3..299f2d1 100644 (file)
@@ -55,9 +55,36 @@ IntRect CachedLayer::adjustBounds(const LayerAndroid* root,
     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]"
@@ -72,38 +99,6 @@ IntRect CachedLayer::adjustBounds(const LayerAndroid* root,
     return result;
 }
 
-IntRect CachedLayer::unadjustBounds(const LayerAndroid* root,
-    const IntRect& bounds) const
-{
-    const LayerAndroid* aLayer = layer(root);
-    if (!aLayer)
-        return bounds;
-
-    IntRect temp = bounds;
-    // Remove the new position (i.e. fixed position elements).
-    FloatPoint position = getGlobalPosition(aLayer);
-
-    temp.move(-position.x(), -position.y());
-
-    // Remove any layer translation.
-    const FloatPoint& translation = aLayer->translation();
-    temp.move(-translation.x(), -translation.y());
-
-    // Move it back to the original offset.
-    temp.move(mOffset.x(), mOffset.y());
-
-    DBG_NAV_LOGD("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(),
-        temp.x(), temp.y(), temp.width(), temp.height());
-    return temp;
-}
-
 FloatPoint CachedLayer::getGlobalPosition(const LayerAndroid* aLayer) const
 {
     SkPoint result = aLayer->getPosition();
@@ -177,7 +172,6 @@ void CachedLayer::Debug::print() const
 {
     CachedLayer* b = base();
     DUMP_NAV_LOGD("    // int mCachedNodeIndex=%d;\n", b->mCachedNodeIndex);
-    DUMP_NAV_LOGD("    // LayerAndroid* mLayer=%p;\n", b->mLayer);
     DUMP_NAV_LOGD("    // int mOffset=(%d, %d);\n",
         b->mOffset.x(), b->mOffset.y());
     DUMP_NAV_LOGD("    // int mUniqueId=%p;\n", b->mUniqueId);
index 0a382fd..3d963e0 100644 (file)
@@ -48,10 +48,6 @@ public:
     }
     // FIXME: adjustBounds should be renamed globalBounds or toGlobal
     IntRect adjustBounds(const LayerAndroid* root, const IntRect& bounds) const;
-    // Moves the bounds by the layer's position.  Assumes the incoming
-    // bounds have been adjusted by adjustBounds.
-    IntRect unadjustBounds(const LayerAndroid* root,
-                           const IntRect& bounds) const;
     int cachedNodeIndex() const { return mCachedNodeIndex; }
     FloatPoint getGlobalPosition(const LayerAndroid* ) const;
     const LayerAndroid* layer(const LayerAndroid* root) const;
index 4ba7b48..e3ba34d 100644 (file)
@@ -110,7 +110,7 @@ void CachedNode::fixUpCursorRects(const CachedFrame* frame)
     mFixedUpCursorRects = true;
     // if the hit-test rect doesn't intersect any other rect, use it
     if (mHitBounds != mBounds && mHitBounds.contains(mBounds) &&
-            frame->checkRings(this, mCursorRing, mBounds, mHitBounds)) {
+            frame->checkRings(this, mHitBounds)) {
         DBG_NAV_LOGD("use mHitBounds (%d,%d,%d,%d)", mHitBounds.x(),
             mHitBounds.y(), mHitBounds.width(), mHitBounds.height());
         mUseHitBounds = true;
@@ -122,7 +122,7 @@ void CachedNode::fixUpCursorRects(const CachedFrame* frame)
     // any other cursor ring bounds, use it
     IntRect sloppyBounds = mBounds;
     sloppyBounds.inflate(2); // give it a couple of extra pixels
-    if (frame->checkRings(this, mCursorRing, mBounds, sloppyBounds)) {
+    if (frame->checkRings(this, sloppyBounds)) {
         DBG_NAV_LOGD("use mBounds (%d,%d,%d,%d)", mBounds.x(),
             mBounds.y(), mBounds.width(), mBounds.height());
         mUseBounds = true;
@@ -424,6 +424,7 @@ void CachedNode::Debug::print() const
     DEBUG_PRINT_BOOL(mLast);
     DEBUG_PRINT_BOOL(mUseBounds);
     DEBUG_PRINT_BOOL(mUseHitBounds);
+    DEBUG_PRINT_BOOL(mSingleImage);
 }
 
 #endif
index 961018b..f9bcbed 100644 (file)
@@ -145,8 +145,10 @@ public:
     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; }
@@ -170,9 +172,11 @@ public:
     void setNavableRects() { mNavableRects = mCursorRing.size(); }
     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]; }
@@ -210,6 +214,7 @@ private:
     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
index 2f0e74d..6083296 100644 (file)
@@ -131,104 +131,6 @@ public:
 #define kMargin 16
 #define kSlop 2
 
-class BoundsCheck : public CommonCheck {
-public:
-    BoundsCheck() {
-        mAllDrawnIn.setEmpty();
-        mLastAll.setEmpty();
-        mLastOver.setEmpty();
-    }
-
-    static int Area(SkIRect test) {
-        return test.width() * test.height();
-    }
-
-   void checkLast() {
-        if (mAllDrawnIn.isEmpty())
-            return;
-        if (mLastAll.isEmpty() || Area(mLastAll) < Area(mAllDrawnIn)) {
-            mLastAll = mAllDrawnIn;
-            mDrawnOver.setEmpty();
-        }
-        mAllDrawnIn.setEmpty();
-    }
-
-    bool hidden() {
-        return (mLastAll.isEmpty() && mLastOver.isEmpty()) ||
-            mDrawnOver.contains(mBounds);
-    }
-
-    virtual bool onIRect(const SkIRect& rect) {
-        if (joinGlyphs(rect))
-            return false;
-        bool interestingType = mType == kDrawBitmap_Type
-            || mType == kDrawSprite_Type
-            || mType == kDrawRect_Type || isTextType(mType);
-        if (SkIRect::Intersects(mBounds, rect) == false) {
-            DBG_NAV_LOGD("BoundsCheck (no intersect) rect={%d,%d,%d,%d}"
-                " mType=%s", rect.fLeft, rect.fTop, rect.fRight, rect.fBottom,
-                TypeNames[mType]);
-            if (interestingType)
-                checkLast();
-            return false;
-        }
-        if (interestingType == false)
-            return false;
-        if (!mDrawnOver.contains(rect) && (mBoundsSlop.contains(rect) ||
-                (mBounds.fLeft == rect.fLeft && mBounds.fRight == rect.fRight &&
-                mBounds.fTop >= rect.fTop && mBounds.fBottom <= rect.fBottom) ||
-                (mBounds.fTop == rect.fTop && mBounds.fBottom == rect.fBottom &&
-                mBounds.fLeft >= rect.fLeft && mBounds.fRight <= rect.fRight))) {
-            mDrawnOver.setEmpty();
-            mAllDrawnIn.join(rect);
-            DBG_NAV_LOGD("BoundsCheck (contains) rect={%d,%d,%d,%d}"
-                " mAllDrawnIn={%d,%d,%d,%d} mType=%s",
-                rect.fLeft, rect.fTop, rect.fRight, rect.fBottom,
-                mAllDrawnIn.fLeft, mAllDrawnIn.fTop, mAllDrawnIn.fRight,
-                mAllDrawnIn.fBottom, TypeNames[mType]);
-       } else {
-            checkLast();
-            if (!isTextType(mType)) {
-                if (
-#if 0
-// should the opaqueness of the bitmap disallow its ability to draw over?
-// not sure that this test is needed
-                (mType != kDrawBitmap_Type ||
-                        (mIsOpaque && mAllOpaque)) &&
-#endif
-                        mLastAll.isEmpty() == false)
-                    mDrawnOver.op(rect, SkRegion::kUnion_Op);
-            } else {
-// FIXME
-// sometimes the text is not drawn entirely inside the cursor area, even though
-// it is the correct text. Until I figure out why, I allow text drawn at the
-// end that is not covered up by something else to represent the link
-// example that triggers this that should be figured out:
-// http://cdn.labpixies.com/campaigns/blackjack/blackjack.html?lang=en&country=US&libs=assets/feature/core
-// ( http://tinyurl.com/ywsyzb )
-                mLastOver = rect;
-            }
-#if DEBUG_NAV_UI
-        const SkIRect& drawnOver = mDrawnOver.getBounds();
-        DBG_NAV_LOGD("(overlaps) rect={%d,%d,%d,%d}"
-            " mDrawnOver={%d,%d,%d,%d} mType=%s mIsOpaque=%s mAllOpaque=%s",
-            rect.fLeft, rect.fTop, rect.fRight, rect.fBottom,
-            drawnOver.fLeft, drawnOver.fTop, drawnOver.fRight, drawnOver.fBottom,
-            TypeNames[mType], mIsOpaque ? "true" : "false",
-            mAllOpaque ? "true" : "false");
-#endif
-        }
-        return false;
-    }
-
-    SkIRect mBounds;
-    SkIRect mBoundsSlop;
-    SkRegion mDrawnOver;
-    SkIRect mLastOver;
-    SkIRect mAllDrawnIn;
-    SkIRect mLastAll;
-};
-
 class BoundsCanvas : public ParseCanvas {
 public:
 
@@ -258,11 +160,11 @@ public:
         INHERITED::drawPath(path, paint);
     }
 
-    virtual void commonDrawBitmap(const SkBitmap& bitmap,
+    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, matrix, paint);
+        INHERITED::commonDrawBitmap(bitmap, rect, matrix, paint);
     }
 
     virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
@@ -606,7 +508,7 @@ 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,
+    virtual void commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* rect,
                               const SkMatrix& , const SkPaint& ) {
         SkPixelRef* pixelRef = bitmap.pixelRef();
         if (pixelRef != NULL) {
@@ -675,10 +577,12 @@ public:
 class RingCheck : public CommonCheck {
 public:
     RingCheck(const WTF::Vector<WebCore::IntRect>& rings,
-        const WebCore::IntRect& bitBounds, const WebCore::IntRect& testBounds)
+        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++) {
@@ -910,7 +814,7 @@ protected:
                 && mType != kDrawSprite_Type && mType != kDrawBitmap_Type)
             return false;
         if (mLayerTypes.isEmpty() || mLayerTypes.last() != mType
-            || !mAppendLikeTypes || mPushPop
+            || !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
@@ -1054,6 +958,7 @@ private:
     char mCh;
     bool mAppendLikeTypes;
     bool mPushPop;
+    bool mSingleImage;
 };
 
 class RingCanvas : public BoundsCanvas {
@@ -1205,16 +1110,16 @@ void CachedRoot::checkForJiggle(int* xDeltaPtr) const
     *xDeltaPtr = jiggleCheck.jiggle();
 }
 
-bool CachedRoot::checkRings(SkPicture* picture,
-        const WTF::Vector<WebCore::IntRect>& rings,
-        const WebCore::IntRect& nodeBounds,
+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);
+    RingCheck ringCheck(rings, bitBounds, testBounds, node->singleImage());
     RingCanvas checker(&ringCheck);
     SkBitmap bitmap;
     bitmap.setConfig(SkBitmap::kARGB_8888_Config, bitBounds.width(),
@@ -1474,9 +1379,7 @@ void CachedRoot::innerMove(const CachedNode* node, BestData* bestData,
     if (bestData->mNode != NULL) {
         mHistory->addToVisited(bestData->mNode, direction);
         mHistory->mNavBounds = bestData->bounds();
-        mHistory->mMouseBounds =
-                bestData->mFrame->unadjustBounds(bestData->mNode,
-                                            bestData->mouseBounds());
+        mHistory->mMouseBounds = bestData->mouseBounds();
     } else if (scroll->x() != 0 || scroll->y() != 0) {
         WebCore::IntRect newBounds = mHistory->mNavBounds;
         int offsetX = scroll->x();
@@ -1576,7 +1479,7 @@ bool CachedRoot::maskIfHidden(BestData* best) const
     const WebCore::IntRect& bounds = bestNode->bounds(frame);
     IntRect bitBounds;
     calcBitBounds(bounds, &bitBounds);
-    RingCheck ringCheck(rings, bitBounds, bounds);
+    RingCheck ringCheck(rings, bitBounds, bounds, bestNode->singleImage());
     RingCanvas checker(&ringCheck);
     SkBitmap bitmap;
     bitmap.setConfig(SkBitmap::kARGB_8888_Config, bitBounds.width(),
index a09e4fb..1f8b851 100644 (file)
@@ -52,8 +52,7 @@ public:
     void calcBitBounds(const IntRect& , IntRect* ) const;
     int checkForCenter(int x, int y) const;
     void checkForJiggle(int* ) const;
-    bool checkRings(SkPicture* , const WTF::Vector<WebCore::IntRect>& rings,
-        const WebCore::IntRect& nodeBounds,
+    bool checkRings(SkPicture* , const CachedNode* ,
         const WebCore::IntRect& testBounds) const;
     WebCore::IntPoint cursorLocation() const;
     int documentHeight() { return mContents.height(); }
index e1bfd82..2d310b3 100644 (file)
@@ -49,18 +49,18 @@ MatchInfo::MatchInfo() {
 }
 
 MatchInfo::~MatchInfo() {
-    m_picture->safeUnref();
+    SkSafeUnref(m_picture);
 }
 
 MatchInfo::MatchInfo(const MatchInfo& src) {
     m_layerId = src.m_layerId;
     m_location = src.m_location;
     m_picture = src.m_picture;
-    m_picture->safeRef();
+    SkSafeRef(m_picture);
 }
 
 void MatchInfo::set(const SkRegion& region, SkPicture* pic, int layerId) {
-    m_picture->safeUnref();
+    SkSafeUnref(m_picture);
     m_layerId = layerId;
     m_location = region;
     m_picture = pic;
@@ -161,7 +161,7 @@ FindCanvas::~FindCanvas() {
     setBounder(NULL);
     /* Just in case getAndClear was not called. */
     delete mMatches;
-    mWorkingPicture->safeUnref();
+    SkSafeUnref(mWorkingPicture);
 }
 
 // Each version of addMatch returns a rectangle for a match.
index a07fa8c..1524058 100644 (file)
@@ -141,40 +141,6 @@ void ReverseBidi(UChar* chars, int len) {
 
 namespace android {
 
-/* SpaceBounds and SpaceCanvas are used to measure the left and right side
- * bearings of two consecutive glyphs to help determine if the glyphs were
- * originally laid out with a space character between the glyphs.
- */
-class SpaceBounds : public SkBounder {
-public:
-    virtual bool onIRectGlyph(const SkIRect& , const SkBounder::GlyphRec& rec)
-    {
-        mFirstGlyph = mLastGlyph;
-        mLastGlyph = rec;
-        return false;
-    }
-
-    SkBounder::GlyphRec mFirstGlyph;
-    SkBounder::GlyphRec mLastGlyph;
-};
-
-class SpaceCanvas : public ParseCanvas {
-public:
-    SpaceCanvas()
-    {
-        setBounder(&mBounder);
-        SkBitmap bitmap;
-        // Configure a very large bitmap so the pair of glyphs can be anywhere
-        // on the page. Skia constrains the bitmap to be 2^31-1 bytes. The
-        // bitmap is never allocated, but this constraint avoids triggering
-        // a failure when the configuration is checked.
-        bitmap.setConfig(SkBitmap::kA1_Config, 16383, 1048576);
-        setBitmapDevice(bitmap);
-    }
-
-    SpaceBounds mBounder;
-};
-
 #define HYPHEN_MINUS 0x2D // ASCII hyphen
 #define SOLIDUS 0x2F // ASCII slash
 #define REVERSE_SOLIDUS 0x5C // ASCII backslash
@@ -194,6 +160,7 @@ public:
         reset();
     }
 
+    /* called only while the picture is parsed */
     int base() {
         if (mBase == INT_MAX) {
             SkPoint result;
@@ -202,7 +169,8 @@ public:
         }
         return mBase;
     }
-    
+
+    /* called only while the picture is parsed */
      int bottom() {
         if (mBottom == INT_MAX) {
             SkPoint result;
@@ -245,12 +213,14 @@ public:
     {
         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;
@@ -266,8 +236,7 @@ public:
         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)"
-            " mMinSpaceWidth=%g mLastUni=0x%04x '%c'",
+            " rec=((%g, %g),(%g, %g), %d) mLastUni=0x%04x '%c'",
             SkFixedToScalar(mLastGlyph.fLSB.fX),
             SkFixedToScalar(mLastGlyph.fLSB.fY),
             SkFixedToScalar(mLastGlyph.fRSB.fX),
@@ -275,7 +244,6 @@ public:
             SkFixedToScalar(rec.fLSB.fX), SkFixedToScalar(rec.fLSB.fY),
             SkFixedToScalar(rec.fRSB.fX), SkFixedToScalar(rec.fRSB.fY),
             rec.fGlyphID,
-            SkFixedToScalar(mMinSpaceWidth),
             mLastUni, mLastUni && mLastUni < 0x7f ? mLastUni : '?');
         bool newBaseLine = mLastGlyph.fLSB.fY != rec.fLSB.fY;
         if (newBaseLine)
@@ -284,45 +252,36 @@ public:
         SkFixed gapTwo = rec.fLSB.fX - mLastGlyph.fRSB.fX;
         if (gapOne < 0 && gapTwo < 0)
             return false; // overlaps
-        uint16_t test[2];
-        test[0] = mLastGlyph.fGlyphID;
-        test[1] = rec.fGlyphID;
-        SpaceCanvas spaceChecker;
-        spaceChecker.drawText(test, sizeof(test),
-            SkFixedToScalar(mLastGlyph.fLSB.fX),
-            SkFixedToScalar(mLastGlyph.fLSB.fY), mPaint);
-        const SkBounder::GlyphRec& g1 = spaceChecker.mBounder.mFirstGlyph;
-        const SkBounder::GlyphRec& g2 = spaceChecker.mBounder.mLastGlyph;
-        DBG_NAV_LOGD("g1=(%g, %g, %g, %g) g2=(%g, %g, %g, %g)",
-            SkFixedToScalar(g1.fLSB.fX), SkFixedToScalar(g1.fLSB.fY),
-            SkFixedToScalar(g1.fRSB.fX), SkFixedToScalar(g1.fRSB.fY),
-            SkFixedToScalar(g2.fLSB.fX), SkFixedToScalar(g2.fLSB.fY),
-            SkFixedToScalar(g2.fRSB.fX), SkFixedToScalar(g2.fRSB.fY));
-        gapOne = SkFixedAbs(gapOne);
-        gapTwo = SkFixedAbs(gapTwo);
-        SkFixed gap = gapOne < gapTwo ? gapOne : gapTwo;
-        SkFixed overlap = g2.fLSB.fX - g1.fRSB.fX;
-        if (overlap < 0)
-            gap -= overlap;
-        DBG_NAV_LOGD("gap=%g overlap=%g gapOne=%g gapTwo=%g minSpaceWidth()=%g",
-            SkFixedToScalar(gap), SkFixedToScalar(overlap),
-            SkFixedToScalar(gapOne), SkFixedToScalar(gapTwo),
-            SkFixedToScalar(minSpaceWidth()));
-        // FIXME: the -1/8 below takes care of slop beween the computed gap
-        // and the actual space width -- it's a rounding error from
-        // moving from fixed to float and back and could be much smaller.
-        spaceChecker.setBounder(0);
-        return gap >= minSpaceWidth() - SK_Fixed1 / 8;
-    }
-
-    SkFixed minSpaceWidth()
+        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 = mPaint.getTextEncoding();
-            mPaint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
-            SkScalar width = mPaint.measureText(" ", 1);
+            SkPaint::TextEncoding save = paint.getTextEncoding();
+            paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
+            SkScalar width = paint.measureText(" ", 1);
             mMinSpaceWidth = SkScalarToFixed(width * mMatrix.getScaleX());
-            mPaint.setTextEncoding(save);
+            paint.setTextEncoding(save);
             DBG_NAV_LOGV("width=%g matrix sx/sy=(%g, %g) tx/ty=(%g, %g)"
                 " mMinSpaceWidth=%g", width,
                 mMatrix.getScaleX(), mMatrix.getScaleY(),
@@ -336,6 +295,7 @@ public:
     {
         mLastCandidate = rec;
         mLastUniCandidate = getUniChar(rec);
+        mLastPaintCandidate = mPaint;
     }
 
     void reset()
@@ -349,7 +309,7 @@ public:
         mLastGlyph = check.mLastGlyph;
         mLastUni = check.mLastUni;
         mMatrix = check.mMatrix;
-        mPaint = check.mPaint;
+        mLastPaint = check.mLastPaint;
         reset();
     }
 
@@ -357,6 +317,7 @@ public:
     {
         mLastGlyph = check.mLastGlyph;
         mLastUni = check.mLastUni;
+        mLastPaint = check.mLastPaint;
     }
 
     void setUp(const SkPaint& paint, const SkMatrix& matrix, SkScalar y,
@@ -369,6 +330,7 @@ public:
         reset();
     }
 
+    /* called only while the picture is parsed */
     int top() {
         if (mTop == INT_MAX) {
             SkPoint result;
@@ -392,10 +354,12 @@ 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;
+    SkPaint mPaint; // only set up while the picture is parsed
     const uint16_t* mText;
     SkScalar mY;
 private:
@@ -493,7 +457,7 @@ public:
         // 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()
+            || bounds.fLeft > mLast.fRight + minSpaceWidth(mPaint)
             || bounds.fLeft < mLast.fLeft) {
             processLine();
             mLast = bounds;
@@ -524,7 +488,6 @@ protected:
     SkIRect mLast;
     SkTDArray<SkIRect> mParagraphs;
     SkTDArray<SkIRect> mSelected;
-    SkTDArray<SkIRect> mInColumn;
     bool mInBetween;
 private:
     typedef CommonCheck INHERITED;
@@ -698,7 +661,7 @@ public:
         , mLast(area)
         , mLeft(left)
     {
-        mLast.set(last);
+        mLast.set(last); // CommonCheck::set()
         setGlyph(last);
     }
 
@@ -753,7 +716,7 @@ public:
             mFocusX, mLeft ? "true" : "false", bounds.fLeft, bounds.fRight);
         reset();
         mFocusX = mLeft ? bounds.fLeft : bounds.fRight;
-        mLast.set(*this);
+        mLast.set(*this); // CommonCheck::set()
     }
 
 protected:
@@ -891,7 +854,7 @@ protected:
             mEndExtra.join(full);
             return mLastIntersects;
         }
-        int spaceGap = SkFixedRound(minSpaceWidth() * 3);
+        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)"
@@ -1255,7 +1218,7 @@ public:
     virtual void drawPath(const SkPath& path, const SkPaint& paint) {
     }
 
-    virtual void commonDrawBitmap(const SkBitmap& bitmap,
+    virtual void commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* rect,
                               const SkMatrix& matrix, const SkPaint& paint) {
     }
 
@@ -1433,13 +1396,13 @@ SelectText::SelectText()
     paint.setShader(dropGradient);
     canvas->drawRect(endDropRect, paint);
     m_endControl.endRecording();
-    fillGradient->safeUnref();
-    dropGradient->safeUnref();
+    SkSafeUnref(fillGradient);
+    SkSafeUnref(dropGradient);
 }
 
 SelectText::~SelectText()
 {
-    m_picture->safeUnref();
+    SkSafeUnref(m_picture);
 }
 
 void SelectText::draw(SkCanvas* canvas, LayerAndroid* layer, IntRect* inval)
@@ -1447,9 +1410,9 @@ void SelectText::draw(SkCanvas* canvas, LayerAndroid* layer, IntRect* inval)
     if (m_layerId != layer->uniqueId())
         return;
     // reset m_picture to match m_layerId
-    m_picture->safeUnref();
+    SkSafeUnref(m_picture);
     m_picture = layer->picture();
-    m_picture->safeRef();
+    SkSafeRef(m_picture);
     DBG_NAV_LOGD("m_extendSelection=%d m_drawPointer=%d layer [%d]",
         m_extendSelection, m_drawPointer, layer->uniqueId());
     if (m_extendSelection)
@@ -1846,7 +1809,7 @@ void SelectText::reset()
     m_lastEnd.setEmpty();
     m_extendSelection = false;
     m_startSelection = false;
-    m_picture->safeUnref();
+    SkSafeUnref(m_picture);
     m_picture = 0;
     m_layerId = 0;
 }
@@ -1905,7 +1868,7 @@ bool SelectText::startSelection(const CachedRoot* root, const IntRect& vis,
     m_wordSelection = false;
     m_startOffset.set(x, y);
     DBG_NAV_LOGD("x/y=(%d,%d)", x, y);
-    m_picture->safeUnref();
+    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);
index 38d0ccb..4031439 100644 (file)
@@ -148,7 +148,7 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) :
     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", "(Z)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");
@@ -210,7 +210,7 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) :
 #endif
     delete m_frameCacheUI;
     delete m_navPictureUI;
-    m_baseLayer->safeUnref();
+    SkSafeUnref(m_baseLayer);
     delete m_glDrawFunctor;
 }
 
@@ -303,10 +303,8 @@ void nativeRecordButtons(bool hasFocus, bool pressed, bool invalidate)
                 if (hasFocus) {
                     if (pressed || m_ring.m_isPressed)
                         state = RenderSkinAndroid::kPressed;
-                    else if (SkTime::GetMSecs() < m_ringAnimationEnd
-                        && m_ringAnimationEnd != UINT_MAX) {
+                    else if (SkTime::GetMSecs() < m_ringAnimationEnd)
                         state = RenderSkinAndroid::kFocused;
-                    }
                 }
             }
             ptr->updateFocusState(state);
@@ -390,6 +388,7 @@ bool drawCursorPreamble(CachedRoot* root)
         resetCursorRing();
         return false;
     }
+    m_ring.setIsButton(node);
     if (node->isHidden()) {
         DBG_NAV_LOG("node->isHidden()");
         m_viewImpl->m_hasCursorBounds = false;
@@ -439,7 +438,7 @@ bool drawGL(WebCore::IntRect& viewRect, float scale, int extras)
         m_glWebViewState = new GLWebViewState(&m_viewImpl->gButtonMutex);
         if (m_baseLayer->content()) {
             IntRect rect(0, 0, m_baseLayer->content()->width(), m_baseLayer->content()->height());
-            m_glWebViewState->setBaseLayer(m_baseLayer, rect);
+            m_glWebViewState->setBaseLayer(m_baseLayer, rect, false);
         }
     }
 
@@ -473,6 +472,7 @@ bool drawGL(WebCore::IntRect& viewRect, float scale, int extras)
 
     SkPicture picture;
     IntRect rect(0, 0, 0, 0);
+    bool allowSame = false;
     if (extra) {
         LayerAndroid mainPicture(m_navPictureUI);
         PictureSet* content = m_baseLayer->content();
@@ -480,8 +480,15 @@ bool drawGL(WebCore::IntRect& viewRect, float scale, int extras)
             content->height());
         extra->draw(canvas, &mainPicture, &rect);
         picture.endRecording();
+    } else if (extras == DrawExtrasCursorRing && m_ring.m_isButton) {
+        const CachedFrame* cachedFrame;
+        const CachedNode* cachedCursor = root->currentCursor(&cachedFrame);
+        if (cachedCursor) {
+            rect = cachedCursor->bounds(cachedFrame);
+            allowSame = true;
+        }
     }
-    m_glWebViewState->setExtra(m_baseLayer, picture, rect);
+    m_glWebViewState->setExtra(m_baseLayer, picture, rect, allowSame);
 
     LayerAndroid* compositeLayer = compositeRoot();
     if (compositeLayer)
@@ -489,12 +496,7 @@ bool drawGL(WebCore::IntRect& viewRect, float scale, int extras)
 
     SkRect visibleRect;
     calcOurContentVisibleRect(&visibleRect);
-
-    m_viewImpl->setVisibleScreenWidth(visibleRect.width());
-    m_viewImpl->setVisibleScreenHeight(visibleRect.height());
-
     bool ret = m_glWebViewState->drawGL(viewRect, visibleRect, scale);
-
     if (ret || m_glWebViewState->currentPictureCounter() != pic)
         return true;
 #endif
@@ -556,8 +558,6 @@ PictureSet* draw(SkCanvas* canvas, SkColor bgColor, int extras, bool split)
     compositeLayer->setExtra(extra);
     SkRect visible;
     calcOurContentVisibleRect(&visible);
-    m_viewImpl->setVisibleScreenWidth(visible.width());
-    m_viewImpl->setVisibleScreenHeight(visible.height());
     // call this to be sure we've adjusted for any scrolling or animations
     // before we actually draw
     compositeLayer->updateFixedLayersPositions(visible);
@@ -686,7 +686,7 @@ CachedRoot* getFrameCache(FrameCachePermission allowNewer)
     }
     m_viewImpl->gFrameCacheMutex.lock();
     delete m_frameCacheUI;
-    m_navPictureUI->safeUnref();
+    SkSafeUnref(m_navPictureUI);
     m_viewImpl->m_updatedFrameCache = false;
     m_frameCacheUI = m_viewImpl->m_frameCacheKit;
     m_navPictureUI = m_viewImpl->m_navPictureKit;
@@ -866,7 +866,9 @@ bool moveCursor(int keyCode, int count, bool ignoreScroll)
         const CachedNode* focus = root->currentFocus();
         bool clearTextEntry = cachedNode != focus && focus
                 && cachedNode->nodePointer() != focus->nodePointer() && focus->isTextInput();
-        sendMoveMouseIfLatest(clearTextEntry);
+        // 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();
@@ -936,13 +938,13 @@ void selectBestAt(const WebCore::IntRect& rect)
     } else {
         DBG_NAV_LOGD("CachedNode:%p (%d)", node, node->index());
         WebCore::IntRect bounds = node->bounds(frame);
-        root->rootHistory()->setMouseBounds(frame->unadjustBounds(node, bounds));
+        root->rootHistory()->setMouseBounds(bounds);
         m_viewImpl->updateCursorBounds(root, frame, node);
         showCursorTimed();
         root->setCursor(const_cast<CachedFrame*>(frame),
                 const_cast<CachedNode*>(node));
     }
-    sendMoveMouseIfLatest(false);
+    sendMoveMouseIfLatest(false, false);
     if (!node)
         return;
 }
@@ -988,8 +990,6 @@ bool motionUp(int x, int y, int slop)
     }
     DBG_NAV_LOGD("CachedNode:%p (%d) x=%d y=%d rx=%d ry=%d", result,
         result->index(), x, y, rx, ry);
-    // No need to call unadjustBounds below.  rx and ry are already adjusted to
-    // the absolute position of the node.
     WebCore::IntRect navBounds = WebCore::IntRect(rx, ry, 1, 1);
     history->setNavBounds(navBounds);
     history->setMouseBounds(navBounds);
@@ -1210,12 +1210,12 @@ void sendMoveMouse(WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int
     checkException(env);
 }
 
-void sendMoveMouseIfLatest(bool clearTextEntry)
+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();
     env->CallVoidMethod(m_javaGlue.object(env).get(),
-            m_javaGlue.m_sendMoveMouseIfLatest, clearTextEntry);
+            m_javaGlue.m_sendMoveMouseIfLatest, clearTextEntry, stopPaintingCaret);
     checkException(env);
 }
 
@@ -1383,11 +1383,11 @@ static void copyScrollPositionRecursive(const LayerAndroid* from,
 }
 #endif
 
-void setBaseLayer(BaseLayerAndroid* layer, WebCore::IntRect& rect)
+void setBaseLayer(BaseLayerAndroid* layer, WebCore::IntRect& rect, bool showVisualIndicator)
 {
 #if USE(ACCELERATED_COMPOSITING)
     if (m_glWebViewState)
-        m_glWebViewState->setBaseLayer(layer, rect);
+        m_glWebViewState->setBaseLayer(layer, rect, showVisualIndicator);
 #endif
 
 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
@@ -1396,7 +1396,7 @@ void setBaseLayer(BaseLayerAndroid* layer, WebCore::IntRect& rect)
         copyScrollPositionRecursive(compositeRoot(), newCompositeRoot);
     }
 #endif
-    m_baseLayer->safeUnref();
+    SkSafeUnref(m_baseLayer);
     m_baseLayer = layer;
     CachedRoot* root = getFrameCache(DontAllowNewer);
     if (!root)
@@ -1770,11 +1770,12 @@ static bool nativeEvaluateLayersAnimations(JNIEnv *env, jobject obj)
     return false;
 }
 
-static void nativeSetBaseLayer(JNIEnv *env, jobject obj, jint layer, jobject jrect)
+static void nativeSetBaseLayer(JNIEnv *env, jobject obj, jint layer, jobject jrect,
+                                jboolean showVisualIndicator)
 {
     BaseLayerAndroid* layerImpl = reinterpret_cast<BaseLayerAndroid*>(layer);
     WebCore::IntRect rect = jrect_to_webrect(env, jrect);
-    GET_NATIVE_VIEW(env, obj)->setBaseLayer(layerImpl, rect);
+    GET_NATIVE_VIEW(env, obj)->setBaseLayer(layerImpl, rect, showVisualIndicator);
 }
 
 static void nativeReplaceBaseContent(JNIEnv *env, jobject obj, jint content)
@@ -2239,7 +2240,7 @@ static bool nativeMoveCursorToNextTextInput(JNIEnv *env, jobject obj)
     if (!next)
         return false;
     const WebCore::IntRect& bounds = next->bounds(frame);
-    root->rootHistory()->setMouseBounds(frame->unadjustBounds(next, bounds));
+    root->rootHistory()->setMouseBounds(bounds);
     view->getWebViewCore()->updateCursorBounds(root, frame, next);
     view->showCursorUntimed();
     root->setCursor(const_cast<CachedFrame*>(frame),
@@ -2566,7 +2567,7 @@ static JNINativeMethod gJavaWebViewMethods[] = {
         (void*) nativeSetFindIsUp },
     { "nativeSetHeightCanMeasure", "(Z)V",
         (void*) nativeSetHeightCanMeasure },
-    { "nativeSetBaseLayer", "(ILandroid/graphics/Rect;)V",
+    { "nativeSetBaseLayer", "(ILandroid/graphics/Rect;Z)V",
         (void*) nativeSetBaseLayer },
     { "nativeReplaceBaseContent", "(I)V",
         (void*) nativeReplaceBaseContent },
index 4b2dda2..99734a7 100644 (file)
@@ -46,11 +46,11 @@ static int32_t anp_getRefCount(const ANPTypeface* tf) {
 }
 
 static void anp_ref(ANPTypeface* tf) {
-    tf->safeRef();
+    SkSafeRef(tf);
 }
 
 static void anp_unref(ANPTypeface* tf) {
-    tf->safeUnref();
+    SkSafeUnref(tf);
 }
 
 static ANPTypefaceStyle anp_getStyle(const ANPTypeface* tf) {
index 7f6948c..d7d4fa7 100644 (file)
@@ -95,7 +95,7 @@ PluginWidgetAndroid::~PluginWidgetAndroid() {
         env->DeleteGlobalRef(m_embeddedView);
     }
 
-    m_flipPixelRef->safeUnref();
+    SkSafeUnref(m_flipPixelRef);
 
     if (m_layer)
         m_layer->unref();
@@ -148,7 +148,7 @@ void PluginWidgetAndroid::setWindow(NPWindow* window, bool isTransparent) {
     layoutSurface(boundsChanged);
 
     if (m_drawingModel != kSurface_ANPDrawingModel) {
-        m_flipPixelRef->safeUnref();
+        SkSafeUnref(m_flipPixelRef);
         m_flipPixelRef = new SkFlipPixelRef(computeConfig(isTransparent),
                                             window->width, window->height);
     }
@@ -589,7 +589,7 @@ void PluginWidgetAndroid::scrollToVisiblePluginRect() {
 #if DEBUG_VISIBLE_RECTS
     PLUGIN_LOG("%s call scrollBy (%d,%d)", __FUNCTION__, deltaX, deltaY);
 #endif
-    core->scrollBy(deltaX, deltaY, true);
+    core->scrollTo(rectCenterX, rectCenterY, true);
 }
 
 void PluginWidgetAndroid::requestFullScreen() {