Merge from Chromium at DEPS revision 37.0.2062.34
This commit was generated by merge_to_master.py.
Change-Id: I9c446e400b5665e20eb2eca0150f1792eedd07e5
diff --git a/Source/core/css/SelectorChecker.cpp b/Source/core/css/SelectorChecker.cpp
index e7c4537..3c6755a 100644
--- a/Source/core/css/SelectorChecker.cpp
+++ b/Source/core/css/SelectorChecker.cpp
@@ -106,20 +106,13 @@
return true;
ASSERT(context.scope);
- // If behaviorAtBoundary is not ScopeIsShadowRoot, we can use "contains".
- if (!(context.behaviorAtBoundary & SelectorChecker::ScopeIsShadowRoot))
- return context.scope->contains(context.element);
-
- // If a given element is scope, i.e. shadow host, matches.
- if (context.element == context.scope->shadowHost() && (!context.previousElement || context.previousElement->isInDescendantTreeOf(context.element)))
+ if (context.scope->treeScope() == context.element->treeScope())
return true;
- ShadowRoot* root = context.element->containingShadowRoot();
- if (!root)
- return false;
-
- // If a host of the containing shadow root is scope, matches.
- return root == context.scope;
+ // Because Blink treats a shadow host's TreeScope as a separate one from its descendent shadow roots,
+ // if the last matched element is a shadow host, the condition above isn't met, even though it
+ // should be.
+ return context.element == context.scope->shadowHost() && (!context.previousElement || context.previousElement->isInDescendantTreeOf(context.element));
}
static inline bool nextSelectorExceedsScope(const SelectorChecker::SelectorCheckingContext& context)
@@ -167,8 +160,7 @@
}
// Prepare next selector
- const CSSSelector* historySelector = context.selector->tagHistory();
- if (!historySelector) {
+ if (context.selector->isLastInTagHistory()) {
if (scopeContainsLastMatchedElement(context)) {
if (result)
result->specificity += specificity;
diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp
index 2c719b4..a75add2 100644
--- a/Source/core/dom/Element.cpp
+++ b/Source/core/dom/Element.cpp
@@ -684,7 +684,7 @@
if (document().documentElement() != this) {
if (RenderBox* rend = renderBox())
- rend->setScrollLeft(roundf(newLeft * rend->style()->effectiveZoom()));
+ rend->setScrollLeft(LayoutUnit::fromFloatRound(newLeft * rend->style()->effectiveZoom()));
return;
}
@@ -730,7 +730,7 @@
if (document().documentElement() != this) {
if (RenderBox* rend = renderBox())
- rend->setScrollTop(roundf(newTop * rend->style()->effectiveZoom()));
+ rend->setScrollTop(LayoutUnit::fromFloatRound(newTop * rend->style()->effectiveZoom()));
return;
}
diff --git a/Source/core/dom/Range.cpp b/Source/core/dom/Range.cpp
index 10e4029..af875e7 100644
--- a/Source/core/dom/Range.cpp
+++ b/Source/core/dom/Range.cpp
@@ -954,7 +954,7 @@
// FIXME: As with innerText, we'd like this to work even if there are no render objects.
m_start.container()->document().updateLayout();
- return plainText(this);
+ return plainText(this, TextIteratorEmitsObjectReplacementCharacter);
}
PassRefPtrWillBeRawPtr<DocumentFragment> Range::createContextualFragment(const String& markup, ExceptionState& exceptionState)
diff --git a/Source/core/dom/SelectorQuery.cpp b/Source/core/dom/SelectorQuery.cpp
index 97c71df..9ed695d 100644
--- a/Source/core/dom/SelectorQuery.cpp
+++ b/Source/core/dom/SelectorQuery.cpp
@@ -121,6 +121,8 @@
SelectorChecker::SelectorCheckingContext selectorCheckingContext(selector, &element, SelectorChecker::VisitedMatchDisabled);
selectorCheckingContext.behaviorAtBoundary = SelectorChecker::StaysWithinTreeScope;
selectorCheckingContext.scope = !rootNode.isDocumentNode() ? &rootNode : 0;
+ if (selectorCheckingContext.scope)
+ selectorCheckingContext.behaviorAtBoundary = static_cast<SelectorChecker::BehaviorAtBoundary>(SelectorChecker::StaysWithinTreeScope | SelectorChecker::ScopeContainsLastMatchedElement);
return selectorChecker.match(selectorCheckingContext, DOMSiblingTraversalStrategy()) == SelectorChecker::SelectorMatches;
}
diff --git a/Source/core/editing/InputMethodController.cpp b/Source/core/editing/InputMethodController.cpp
index 47a27e6..3e6b85e 100644
--- a/Source/core/editing/InputMethodController.cpp
+++ b/Source/core/editing/InputMethodController.cpp
@@ -317,7 +317,7 @@
void InputMethodController::setCompositionFromExistingText(const Vector<CompositionUnderline>& underlines, unsigned compositionStart, unsigned compositionEnd)
{
- Node* editable = m_frame.selection().rootEditableElement();
+ Element* editable = m_frame.selection().rootEditableElement();
Position base = m_frame.selection().base().downstream();
Node* baseNode = base.anchorNode();
if (editable->firstChild() == baseNode && editable->lastChild() == baseNode && baseNode->isTextNode()) {
@@ -330,13 +330,14 @@
return;
m_compositionNode = toText(baseNode);
- m_compositionStart = compositionStart;
- m_compositionEnd = compositionEnd;
+ RefPtrWillBeRawPtr<Range> range = PlainTextRange(compositionStart, compositionEnd).createRange(*editable);
+ m_compositionStart = range->startOffset();
+ m_compositionEnd = range->endOffset();
m_customCompositionUnderlines = underlines;
size_t numUnderlines = m_customCompositionUnderlines.size();
for (size_t i = 0; i < numUnderlines; ++i) {
- m_customCompositionUnderlines[i].startOffset += compositionStart;
- m_customCompositionUnderlines[i].endOffset += compositionStart;
+ m_customCompositionUnderlines[i].startOffset += m_compositionStart;
+ m_customCompositionUnderlines[i].endOffset += m_compositionStart;
}
if (baseNode->renderer())
baseNode->renderer()->paintInvalidationForWholeRenderer();
@@ -379,7 +380,7 @@
if (!rootEditableElement)
return false;
- RefPtrWillBeRawPtr<Range> range = selectionOffsets.createRangeForInputMethod(*rootEditableElement);
+ RefPtrWillBeRawPtr<Range> range = selectionOffsets.createRange(*rootEditableElement);
if (!range)
return false;
diff --git a/Source/core/editing/PlainTextRange.cpp b/Source/core/editing/PlainTextRange.cpp
index 1ebc8f4..ff63a5e 100644
--- a/Source/core/editing/PlainTextRange.cpp
+++ b/Source/core/editing/PlainTextRange.cpp
@@ -67,11 +67,6 @@
return createRangeFor(scope, ForSelection);
}
-PassRefPtrWillBeRawPtr<Range> PlainTextRange::createRangeForInputMethod(const ContainerNode& scope) const
-{
- return createRangeFor(scope, ForInputMethod);
-}
-
PassRefPtrWillBeRawPtr<Range> PlainTextRange::createRangeFor(const ContainerNode& scope, GetRangeFor getRangeFor) const
{
ASSERT(isNotNull());
@@ -83,11 +78,9 @@
RefPtrWillBeRawPtr<Range> textRunRange = nullptr;
- TextIteratorBehavior behaviorFlags = TextIteratorDefaultBehavior;
+ TextIteratorBehaviorFlags behaviorFlags = TextIteratorEmitsObjectReplacementCharacter;
if (getRangeFor == ForSelection)
- behaviorFlags = TextIteratorEmitsCharactersBetweenAllVisiblePositions;
- else if (getRangeFor == ForInputMethod)
- behaviorFlags = TextIteratorEmitsObjectReplacementCharacter;
+ behaviorFlags |= TextIteratorEmitsCharactersBetweenAllVisiblePositions;
TextIterator it(rangeOfContents(const_cast<ContainerNode*>(&scope)).get(), behaviorFlags);
// FIXME: the atEnd() check shouldn't be necessary, workaround for <http://bugs.webkit.org/show_bug.cgi?id=6289>.
diff --git a/Source/core/editing/PlainTextRange.h b/Source/core/editing/PlainTextRange.h
index ba583ce..d3e2617 100644
--- a/Source/core/editing/PlainTextRange.h
+++ b/Source/core/editing/PlainTextRange.h
@@ -51,14 +51,13 @@
PassRefPtrWillBeRawPtr<Range> createRange(const ContainerNode& scope) const;
PassRefPtrWillBeRawPtr<Range> createRangeForSelection(const ContainerNode& scope) const;
- PassRefPtrWillBeRawPtr<Range> createRangeForInputMethod(const ContainerNode& scope) const;
static PlainTextRange create(const Node& scope, const Range&);
private:
PlainTextRange& operator=(const PlainTextRange&) WTF_DELETED_FUNCTION;
- enum GetRangeFor { ForGeneric, ForSelection, ForInputMethod };
+ enum GetRangeFor { ForGeneric, ForSelection };
PassRefPtrWillBeRawPtr<Range> createRangeFor(const ContainerNode& scope, GetRangeFor) const;
const size_t m_start;
diff --git a/Source/core/editing/TextIterator.cpp b/Source/core/editing/TextIterator.cpp
index 45a5f21..b1c9e13 100644
--- a/Source/core/editing/TextIterator.cpp
+++ b/Source/core/editing/TextIterator.cpp
@@ -2043,7 +2043,10 @@
int TextIterator::rangeLength(const Range* r, bool forSelectionPreservation)
{
int length = 0;
- for (TextIterator it(r, forSelectionPreservation ? TextIteratorEmitsCharactersBetweenAllVisiblePositions : TextIteratorDefaultBehavior); !it.atEnd(); it.advance())
+ TextIteratorBehaviorFlags behaviorFlags = TextIteratorEmitsObjectReplacementCharacter;
+ if (forSelectionPreservation)
+ behaviorFlags |= TextIteratorEmitsCharactersBetweenAllVisiblePositions;
+ for (TextIterator it(r, behaviorFlags); !it.atEnd(); it.advance())
length += it.length();
return length;
diff --git a/Source/core/editing/TextIterator.h b/Source/core/editing/TextIterator.h
index 7e9afc3..08a91ed 100644
--- a/Source/core/editing/TextIterator.h
+++ b/Source/core/editing/TextIterator.h
@@ -109,7 +109,12 @@
PassRefPtrWillBeRawPtr<Range> range() const;
Node* node() const;
- static int rangeLength(const Range*, bool spacesForReplacedElements = false);
+ // Computes the length of the given range using a text iterator. The default
+ // iteration behavior is to always emit object replacement characters for
+ // replaced elements. When |forSelectionPreservation| is set to true, it
+ // also emits spaces for other non-text nodes using the
+ // |TextIteratorEmitsCharactersBetweenAllVisiblePosition| mode.
+ static int rangeLength(const Range*, bool forSelectionPreservation = false);
static PassRefPtrWillBeRawPtr<Range> subrange(Range* entireRange, int characterOffset, int characterCount);
private:
diff --git a/Source/core/editing/TextIteratorTest.cpp b/Source/core/editing/TextIteratorTest.cpp
index 082444e..63a7f40 100644
--- a/Source/core/editing/TextIteratorTest.cpp
+++ b/Source/core/editing/TextIteratorTest.cpp
@@ -539,4 +539,17 @@
EXPECT_EQ(expectedTextChunks, iterate(TextIteratorEmitsObjectReplacementCharacter));
}
+TEST_F(TextIteratorTest, RangeLengthWithReplacedElements)
+{
+ static const char* bodyContent =
+ "<div id=\"div\" contenteditable=\"true\">1<img src=\"foo.png\">3</div>";
+ setBodyInnerHTML(bodyContent);
+ document().view()->updateLayoutAndStyleIfNeededRecursive();
+
+ Node* divNode = document().getElementById("div");
+ RefPtrWillBeRawPtr<Range> range = Range::create(document(), divNode, 0, divNode, 3);
+
+ EXPECT_EQ(3, TextIterator::rangeLength(range.get()));
+}
+
}
diff --git a/Source/core/html/HTMLFormElement.cpp b/Source/core/html/HTMLFormElement.cpp
index 9878763..18ef044 100644
--- a/Source/core/html/HTMLFormElement.cpp
+++ b/Source/core/html/HTMLFormElement.cpp
@@ -487,10 +487,10 @@
void HTMLFormElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
if (name == actionAttr) {
- m_attributes.parseAction(document(), value);
+ m_attributes.parseAction(value);
// If the new action attribute is pointing to insecure "action" location from a secure page
// it is marked as "passive" mixed content.
- KURL actionURL = m_attributes.action().isEmpty() ? document().url() : m_attributes.action();
+ KURL actionURL = document().completeURL(m_attributes.action().isEmpty() ? document().url().string() : m_attributes.action());
if (MixedContentChecker::isMixedContent(document().securityOrigin(), actionURL))
document().frame()->loader().mixedContentChecker()->canSubmitToInsecureForm(document().securityOrigin(), actionURL);
} else if (name == targetAttr)
diff --git a/Source/core/html/HTMLLIElement.cpp b/Source/core/html/HTMLLIElement.cpp
index c9e8c10..c74defe 100644
--- a/Source/core/html/HTMLLIElement.cpp
+++ b/Source/core/html/HTMLLIElement.cpp
@@ -98,10 +98,8 @@
// If we are not in a list, tell the renderer so it can position us inside.
// We don't want to change our style to say "inside" since that would affect nested nodes.
- if (!listNode) {
+ if (!listNode)
listItemRenderer->setNotInList(true);
- listItemRenderer->updateMarkerLocation();
- }
parseValue(fastGetAttribute(valueAttr));
}
diff --git a/Source/core/html/canvas/CanvasRenderingContext2D.cpp b/Source/core/html/canvas/CanvasRenderingContext2D.cpp
index a615334..ccca4dd 100644
--- a/Source/core/html/canvas/CanvasRenderingContext2D.cpp
+++ b/Source/core/html/canvas/CanvasRenderingContext2D.cpp
@@ -1740,12 +1740,15 @@
if (dirtyRect.isEmpty())
return;
- // If we are drawing to hardware and we have a composited layer, just invalidate layer.
- if (isAccelerated() && platformLayer()) {
- platformLayer()->invalidateRect(dirtyRect);
- canvas()->clearCopiedImage();
- canvas()->notifyObserversCanvasChanged(dirtyRect);
- return;
+ // If we are drawing to hardware and we have a composited layer, just call contentChanged().
+ if (isAccelerated()) {
+ RenderBox* renderBox = canvas()->renderBox();
+ if (renderBox && renderBox->hasAcceleratedCompositing()) {
+ renderBox->contentChanged(CanvasPixelsChanged);
+ canvas()->clearCopiedImage();
+ canvas()->notifyObserversCanvasChanged(dirtyRect);
+ return;
+ }
}
canvas()->didDraw(dirtyRect);
diff --git a/Source/core/loader/FormSubmission.cpp b/Source/core/loader/FormSubmission.cpp
index 8b6c22b..b6503ab 100644
--- a/Source/core/loader/FormSubmission.cpp
+++ b/Source/core/loader/FormSubmission.cpp
@@ -83,9 +83,10 @@
url.setQuery(query.toString());
}
-void FormSubmission::Attributes::parseAction(const Document& document, const String& action)
+void FormSubmission::Attributes::parseAction(const String& action)
{
- m_action = action.isEmpty() ? KURL() : document.completeURL(stripLeadingAndTrailingHTMLSpaces(action));
+ // m_action cannot be converted to KURL (bug https://crbug.com/388664)
+ m_action = stripLeadingAndTrailingHTMLSpaces(action);
}
AtomicString FormSubmission::Attributes::parseEncodingType(const String& type)
@@ -179,7 +180,7 @@
if (submitButton) {
AtomicString attributeValue;
if (!(attributeValue = submitButton->fastGetAttribute(formactionAttr)).isNull())
- copiedAttributes.parseAction(form->document(), attributeValue);
+ copiedAttributes.parseAction(attributeValue);
if (!(attributeValue = submitButton->fastGetAttribute(formenctypeAttr)).isNull())
copiedAttributes.updateEncodingType(attributeValue);
if (!(attributeValue = submitButton->fastGetAttribute(formmethodAttr)).isNull())
@@ -195,7 +196,7 @@
}
Document& document = form->document();
- KURL actionURL = copiedAttributes.action().isEmpty() ? document.url() : copiedAttributes.action();
+ KURL actionURL = document.completeURL(copiedAttributes.action().isEmpty() ? document.url().string() : copiedAttributes.action());
bool isMailtoForm = actionURL.protocolIs("mailto");
bool isMultiPartForm = false;
AtomicString encodingType = copiedAttributes.encodingType();
diff --git a/Source/core/loader/FormSubmission.h b/Source/core/loader/FormSubmission.h
index b57c732..956c2b0 100644
--- a/Source/core/loader/FormSubmission.h
+++ b/Source/core/loader/FormSubmission.h
@@ -67,8 +67,8 @@
void updateMethodType(const String&);
static String methodString(Method);
- const KURL& action() const { return m_action; }
- void parseAction(const Document&, const String&);
+ const String& action() const { return m_action; }
+ void parseAction(const String&);
const AtomicString& target() const { return m_target; }
void setTarget(const AtomicString& target) { m_target = target; }
@@ -87,7 +87,7 @@
Method m_method;
bool m_isMultiPartForm;
- KURL m_action;
+ String m_action;
AtomicString m_target;
AtomicString m_encodingType;
String m_acceptCharset;
diff --git a/Source/core/page/EventHandler.cpp b/Source/core/page/EventHandler.cpp
index 293359d..bad7363 100644
--- a/Source/core/page/EventHandler.cpp
+++ b/Source/core/page/EventHandler.cpp
@@ -3538,14 +3538,19 @@
touchTarget = m_targetForTouchID.get(point.id());
}
- LocalFrame* targetFrame;
- bool knownTarget;
+ LocalFrame* targetFrame = 0;
+ bool knownTarget = false;
if (touchTarget) {
Document& doc = touchTarget->toNode()->document();
- ASSERT(&doc == m_touchSequenceDocument.get());
- targetFrame = doc.frame();
- knownTarget = true;
- } else {
+ // If the target node has moved to a new document while it was being touched,
+ // we can't send events to the new document because that could leak nodes
+ // from one document to another. See http://crbug.com/394339.
+ if (&doc == m_touchSequenceDocument.get()) {
+ targetFrame = doc.frame();
+ knownTarget = true;
+ }
+ }
+ if (!knownTarget) {
// If we don't have a target registered for the point it means we've
// missed our opportunity to do a hit test for it (due to some
// optimization that prevented blink from ever seeing the
@@ -3563,7 +3568,6 @@
// is on-heap.
touchTarget = m_touchSequenceDocument.get();
targetFrame = m_touchSequenceDocument->frame();
- knownTarget = false;
}
ASSERT(targetFrame);
diff --git a/Source/core/rendering/RenderBoxModelObject.h b/Source/core/rendering/RenderBoxModelObject.h
index 6d223d8..f308aec 100644
--- a/Source/core/rendering/RenderBoxModelObject.h
+++ b/Source/core/rendering/RenderBoxModelObject.h
@@ -46,6 +46,7 @@
enum ContentChangeType {
ImageChanged,
CanvasChanged,
+ CanvasPixelsChanged,
CanvasContextChanged
};
diff --git a/Source/core/rendering/RenderListItem.cpp b/Source/core/rendering/RenderListItem.cpp
index 17c0cfc..54d3d2d 100644
--- a/Source/core/rendering/RenderListItem.cpp
+++ b/Source/core/rendering/RenderListItem.cpp
@@ -269,64 +269,70 @@
return result;
}
-void RenderListItem::updateMarkerLocation()
+void RenderListItem::updateMarkerLocationAndInvalidateWidth()
{
- // Sanity check the location of our marker.
- if (m_marker) {
- RenderObject* markerParent = m_marker->parent();
- RenderObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker);
- if (!lineBoxParent) {
- // If the marker is currently contained inside an anonymous box,
- // then we are the only item in that anonymous box (since no line box
- // parent was found). It's ok to just leave the marker where it is
- // in this case.
- if (markerParent && markerParent->isAnonymousBlock())
- lineBoxParent = markerParent;
- else
- lineBoxParent = this;
- }
+ ASSERT(m_marker);
- if (markerParent != lineBoxParent || m_marker->preferredLogicalWidthsDirty()) {
- // FIXME: We should not modify the structure of the render tree
- // during layout. crbug.com/370461
- DeprecatedDisableModifyRenderTreeStructureAsserts disabler;
-
- // Removing and adding the marker can trigger repainting in
- // containers other than ourselves, so we need to disable LayoutState.
- ForceHorriblySlowRectMapping slowRectMapping(*this);
- updateFirstLetter();
- m_marker->remove();
- if (markerParent)
- markerParent->dirtyLinesFromChangedChild(m_marker);
- if (!lineBoxParent)
- lineBoxParent = this;
- lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent));
- m_marker->updateMarginsAndContent();
- // If markerParent is an anonymous block that has lost all its children, destroy it.
- if (markerParent && markerParent->isAnonymousBlock() && !toRenderBlock(markerParent)->firstChild() && !toRenderBlock(markerParent)->continuation())
- markerParent->destroy();
-
- // If the marker is inside we need to redo the preferred width calculations
- // as the size of the item now includes the size of the list marker.
- if (m_marker->isInside())
- containingBlock()->updateLogicalWidth();
- }
+ // FIXME: We should not modify the structure of the render tree
+ // during layout. crbug.com/370461
+ DeprecatedDisableModifyRenderTreeStructureAsserts disabler;
+ // Removing and adding the marker can trigger repainting in
+ // containers other than ourselves, so we need to disable LayoutState.
+ ForceHorriblySlowRectMapping slowRectMapping(*this);
+ if (updateMarkerLocation()) {
+ // If the marker is inside we need to redo the preferred width calculations
+ // as the size of the item now includes the size of the list marker.
+ if (m_marker->isInside())
+ containingBlock()->updateLogicalWidth();
}
}
+bool RenderListItem::updateMarkerLocation()
+{
+ ASSERT(m_marker);
+ RenderObject* markerParent = m_marker->parent();
+ RenderObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker);
+ if (!lineBoxParent) {
+ // If the marker is currently contained inside an anonymous box, then we
+ // are the only item in that anonymous box (since no line box parent was
+ // found). It's ok to just leave the marker where it is in this case.
+ if (markerParent && markerParent->isAnonymousBlock())
+ lineBoxParent = markerParent;
+ else
+ lineBoxParent = this;
+ }
+
+ if (markerParent != lineBoxParent) {
+ updateFirstLetter();
+ m_marker->remove();
+ // FIXME(crbug.com/391009): Investigate whether this call is needed.
+ if (markerParent)
+ markerParent->dirtyLinesFromChangedChild(m_marker);
+ lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent));
+ m_marker->updateMarginsAndContent();
+ // If markerParent is an anonymous block with no children, destroy it.
+ if (markerParent && markerParent->isAnonymousBlock() && !toRenderBlock(markerParent)->firstChild() && !toRenderBlock(markerParent)->continuation())
+ markerParent->destroy();
+ return true;
+ }
+
+ return false;
+}
+
void RenderListItem::layout()
{
ASSERT(needsLayout());
- // The marker must be autosized before calling updateMarkerLocation.
- // It cannot be done in the parent's beginLayout because it is not yet in the render tree.
if (m_marker) {
- FastTextAutosizer* textAutosizer = document().fastTextAutosizer();
- if (textAutosizer)
+ // The marker must be autosized before calling
+ // updateMarkerLocationAndInvalidateWidth. It cannot be done in the
+ // parent's beginLayout because it is not yet in the render tree.
+ if (FastTextAutosizer* textAutosizer = document().fastTextAutosizer())
textAutosizer->inflateListItem(this, m_marker);
+
+ updateMarkerLocationAndInvalidateWidth();
}
- updateMarkerLocation();
RenderBlockFlow::layout();
}
@@ -477,6 +483,13 @@
explicitValueChanged();
}
+void RenderListItem::setNotInList(bool notInList)
+{
+ m_notInList = notInList;
+ if (m_marker)
+ updateMarkerLocation();
+}
+
static RenderListItem* previousOrNextItem(bool isListReversed, Node* list, RenderListItem* item)
{
return isListReversed ? previousListItem(list, item) : nextListItem(list, item);
diff --git a/Source/core/rendering/RenderListItem.h b/Source/core/rendering/RenderListItem.h
index 3d6edc5..ca46d46 100644
--- a/Source/core/rendering/RenderListItem.h
+++ b/Source/core/rendering/RenderListItem.h
@@ -42,13 +42,12 @@
void setExplicitValue(int value);
void clearExplicitValue();
- void setNotInList(bool notInList) { m_notInList = notInList; }
+ void setNotInList(bool);
bool notInList() const { return m_notInList; }
const String& markerText() const;
void updateListMarkerNumbers();
- void updateMarkerLocation();
static void updateItemValuesForOrderedList(const HTMLOListElement*);
static unsigned itemCountForOrderedList(const HTMLOListElement*);
@@ -69,6 +68,10 @@
virtual void layout() OVERRIDE;
+ // Returns true if we re-attached and updated the location of the marker.
+ bool updateMarkerLocation();
+ void updateMarkerLocationAndInvalidateWidth();
+
void positionListMarker();
virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
diff --git a/Source/core/rendering/compositing/CompositedLayerMapping.cpp b/Source/core/rendering/compositing/CompositedLayerMapping.cpp
index 2e5cdbe..0b01a05 100644
--- a/Source/core/rendering/compositing/CompositedLayerMapping.cpp
+++ b/Source/core/rendering/compositing/CompositedLayerMapping.cpp
@@ -1713,7 +1713,7 @@
return;
}
- if (changeType == CanvasChanged && isAcceleratedCanvas(renderer())) {
+ if ((changeType == CanvasChanged || changeType == CanvasPixelsChanged) && isAcceleratedCanvas(renderer())) {
m_graphicsLayer->setContentsNeedsDisplay();
return;
}
diff --git a/Source/devtools/front_end/elements/StylesSidebarPane.js b/Source/devtools/front_end/elements/StylesSidebarPane.js
index e5459e7..51f5dda 100644
--- a/Source/devtools/front_end/elements/StylesSidebarPane.js
+++ b/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -1156,7 +1156,7 @@
if (!this.rule || !this.rule.styleSheetId)
return;
if (this.rule !== editedRule)
- this.rule.sourceStyleSheetEdited(this.rule.styleSheetId, oldRange, newRange);
+ this.rule.sourceStyleSheetEdited(editedRule.styleSheetId, oldRange, newRange);
this._updateMediaList();
this._updateRuleOrigin();
},
diff --git a/Source/platform/blink_platform.gypi b/Source/platform/blink_platform.gypi
index c741e2b..39466a4 100644
--- a/Source/platform/blink_platform.gypi
+++ b/Source/platform/blink_platform.gypi
@@ -915,6 +915,7 @@
'testing/TreeTestHelpers.cpp',
'testing/TreeTestHelpers.h',
'transforms/TransformOperationsTest.cpp',
+ 'transforms/TransformationMatrixTest.cpp',
'text/BidiResolverTest.cpp',
'text/DateTimeFormatTest.cpp',
'text/SegmentedStringTest.cpp',
diff --git a/Source/platform/fonts/FontFallbackList.cpp b/Source/platform/fonts/FontFallbackList.cpp
index fee749f..e7dfc6e 100644
--- a/Source/platform/fonts/FontFallbackList.cpp
+++ b/Source/platform/fonts/FontFallbackList.cpp
@@ -126,10 +126,12 @@
if (!fontData) {
// All fonts are custom fonts and are loading. Return the first FontData.
fontData = fontDataAt(fontDescription, 0);
- if (!fontData)
- fontData = FontCache::fontCache()->getLastResortFallbackFont(fontDescription).get();
- ASSERT(fontData);
- return fontData;
+ if (fontData)
+ return fontData->fontDataForCharacter(' ');
+
+ SimpleFontData* lastResortFallback = FontCache::fontCache()->getLastResortFallbackFont(fontDescription).get();
+ ASSERT(lastResortFallback);
+ return lastResortFallback;
}
if (fontData->isSegmented() && !toSegmentedFontData(fontData)->containsCharacter(' '))
diff --git a/Source/platform/transforms/TransformationMatrix.cpp b/Source/platform/transforms/TransformationMatrix.cpp
index 4403d3e..172d0bf 100644
--- a/Source/platform/transforms/TransformationMatrix.cpp
+++ b/Source/platform/transforms/TransformationMatrix.cpp
@@ -1364,8 +1364,11 @@
// decompose
DecomposedType fromDecomp;
DecomposedType toDecomp;
- from.decompose(fromDecomp);
- decompose(toDecomp);
+ if (!from.decompose(fromDecomp) || !decompose(toDecomp)) {
+ if (progress < 0.5)
+ *this = from;
+ return;
+ }
// interpolate
blendFloat(fromDecomp.scaleX, toDecomp.scaleX, progress);
diff --git a/Source/platform/transforms/TransformationMatrixTest.cpp b/Source/platform/transforms/TransformationMatrixTest.cpp
new file mode 100644
index 0000000..64c533c
--- /dev/null
+++ b/Source/platform/transforms/TransformationMatrixTest.cpp
@@ -0,0 +1,28 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "platform/transforms/TransformationMatrix.h"
+
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+namespace {
+
+TEST(TransformationMatrixTest, NonInvertableBlendTest)
+{
+ TransformationMatrix from;
+ TransformationMatrix to(2.7133590938, 0.0, 0.0, 0.0, 0.0, 2.4645137761, 0.0, 0.0, 0.0, 0.0, 0.00, 0.01, 0.02, 0.03, 0.04, 0.05);
+ TransformationMatrix result;
+
+ result = to;
+ result.blend(from, 0.25);
+ EXPECT_TRUE(result == from);
+
+ result = to;
+ result.blend(from, 0.75);
+ EXPECT_TRUE(result == to);
+}
+
+} // namespace
diff --git a/Source/web/WebViewImpl.cpp b/Source/web/WebViewImpl.cpp
index 80ff79a..df666ab 100644
--- a/Source/web/WebViewImpl.cpp
+++ b/Source/web/WebViewImpl.cpp
@@ -2124,7 +2124,9 @@
if (!focused->editor().canEdit())
return info;
- info.value = plainText(rangeOfContents(node).get());
+ // Emits an object replacement character for each replaced element so that
+ // it is exposed to IME and thus could be deleted by IME on android.
+ info.value = plainText(rangeOfContents(node).get(), TextIteratorEmitsObjectReplacementCharacter);
if (info.value.isEmpty())
return info;
diff --git a/Source/web/tests/WebViewTest.cpp b/Source/web/tests/WebViewTest.cpp
index 1d479d5..4d6dd81 100644
--- a/Source/web/tests/WebViewTest.cpp
+++ b/Source/web/tests/WebViewTest.cpp
@@ -512,6 +512,17 @@
testInputMode(WebString("verbatim"), "input_mode_textarea_verbatim.html");
}
+TEST_F(WebViewTest, TextInputInfoWithReplacedElements)
+{
+ std::string url = m_baseURL + "div_with_image.html";
+ URLTestHelpers::registerMockedURLLoad(toKURL(url), "div_with_image.html");
+ WebView* webView = m_webViewHelper.initializeAndLoad(url);
+ webView->setInitialFocus(false);
+ WebTextInputInfo info = webView->textInputInfo();
+
+ EXPECT_EQ("foo\xef\xbf\xbc", info.value.utf8());
+}
+
TEST_F(WebViewTest, SetEditableSelectionOffsetsAndTextInputInfo)
{
URLTestHelpers::registerMockedURLFromBaseURL(WebString::fromUTF8(m_baseURL.c_str()), WebString::fromUTF8("input_field_populated.html"));
diff --git a/Source/web/tests/data/div_with_image.html b/Source/web/tests/data/div_with_image.html
new file mode 100644
index 0000000..0a2af6c
--- /dev/null
+++ b/Source/web/tests/data/div_with_image.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<div id="outer" contentEditable=true>foo<img src="foo.png"></div>
+