Merge from Chromium at DEPS revision 261286

This commit was generated by merge_to_master.py.

Change-Id: I756d37445fd7f470b1689ad81318e715d4244987
diff --git a/Source/core/dom/ContainerNode.cpp b/Source/core/dom/ContainerNode.cpp
index 6184479..69cc8be 100644
--- a/Source/core/dom/ContainerNode.cpp
+++ b/Source/core/dom/ContainerNode.cpp
@@ -654,7 +654,7 @@
     if (!changedByParser && childCountDelta)
         document().updateRangesAfterChildrenChanged(this);
     invalidateNodeListCachesInAncestors();
-    if (childCountDelta > 0 && inActiveDocument()) {
+    if (childCountDelta > 0 && !childNeedsStyleRecalc()) {
         setChildNeedsStyleRecalc();
         markAncestorsWithChildNeedsStyleRecalc();
     }
diff --git a/Source/core/dom/Document.cpp b/Source/core/dom/Document.cpp
index e9e7627..7289c58 100644
--- a/Source/core/dom/Document.cpp
+++ b/Source/core/dom/Document.cpp
@@ -1204,6 +1204,26 @@
     return String();
 }
 
+void Document::setMimeType(const AtomicString& mimeType)
+{
+    m_mimeType = mimeType;
+}
+
+AtomicString Document::contentType() const
+{
+    if (!m_mimeType.isEmpty())
+        return m_mimeType;
+
+    if (DocumentLoader* documentLoader = loader())
+        return documentLoader->mimeType();
+
+    String mimeType = suggestedMIMEType();
+    if (!mimeType.isEmpty())
+        return AtomicString(mimeType);
+
+    return AtomicString("application/xml");
+}
+
 Element* Document::elementFromPoint(int x, int y) const
 {
     if (!renderView())
@@ -1590,7 +1610,7 @@
     TRACE_EVENT0("webkit", "Document::computeNeedsStyleRecalcState");
     ASSERT(styleResolver());
 
-    StyleInvalidator(*this).invalidate();
+    styleResolver()->ruleFeatureSet().styleInvalidator().invalidate(*this);
 }
 
 void Document::updateDistributionForNodeIfNeeded(Node* node)
@@ -2070,6 +2090,10 @@
 
     ContainerNode::attach(context);
 
+    // FastTextAutosizer can't update render view info while the Document is detached, so update now in case anything changed.
+    if (FastTextAutosizer* textAutosizer = fastTextAutosizer())
+        textAutosizer->updatePageInfo();
+
     m_lifecycle.advanceTo(DocumentLifecycle::StyleClean);
 }
 
@@ -3031,6 +3055,10 @@
 
 void Document::setViewportDescription(const ViewportDescription& viewportDescription)
 {
+    // The UA-defined min-width is used by the processing of legacy meta tags.
+    if (!viewportDescription.isSpecifiedByAuthor())
+        m_viewportDefaultMinWidth = viewportDescription.minWidth;
+
     if (viewportDescription.isLegacyViewportType()) {
         if (settings() && !settings()->viewportMetaEnabled())
             return;
@@ -3260,6 +3288,7 @@
     setEncodingData(other.m_encodingData);
     setContextFeatures(other.contextFeatures());
     setSecurityOrigin(other.securityOrigin()->isolatedCopy());
+    setMimeType(other.contentType());
 }
 
 StyleSheetList* Document::styleSheets()
@@ -5444,10 +5473,11 @@
     Page* page = this->page();
     if (!page)
         return false;
-    if (!page->focusController().isActive() || !page->focusController().isFocused() || !page->focusController().focusedFrame()->isLocalFrame())
+    if (!page->focusController().isActive() || !page->focusController().isFocused())
         return false;
-    if (LocalFrame* focusedFrame = toLocalFrame(page->focusController().focusedFrame())) {
-        if (focusedFrame->tree().isDescendantOf(frame()))
+    Frame* focusedFrame = page->focusController().focusedFrame();
+    if (focusedFrame && focusedFrame->isLocalFrame()) {
+        if (toLocalFrame(focusedFrame)->tree().isDescendantOf(frame()))
             return true;
     }
     return false;
diff --git a/Source/core/dom/Document.h b/Source/core/dom/Document.h
index 0cfd671..3a6f68c 100644
--- a/Source/core/dom/Document.h
+++ b/Source/core/dom/Document.h
@@ -50,6 +50,7 @@
 #include "core/page/PageVisibilityState.h"
 #include "core/rendering/HitTestRequest.h"
 #include "heap/Handle.h"
+#include "platform/Length.h"
 #include "platform/Timer.h"
 #include "platform/weborigin/KURL.h"
 #include "platform/weborigin/ReferrerPolicy.h"
@@ -282,6 +283,8 @@
     bool shouldOverrideLegacyDescription(ViewportDescription::Type);
     void setViewportDescription(const ViewportDescription&);
     const ViewportDescription& viewportDescription() const { return m_viewportDescription; }
+    Length viewportDefaultMinWidth() const { return m_viewportDefaultMinWidth; }
+
 #ifndef NDEBUG
     bool didDispatchViewportPropertiesChanged() const { return m_didDispatchViewportPropertiesChanged; }
 #endif
@@ -353,6 +356,8 @@
     void setContent(const String&);
 
     String suggestedMIMEType() const;
+    void setMimeType(const AtomicString&);
+    AtomicString contentType() const; // DOM 4 document.contentType
 
     const AtomicString& contentLanguage() const { return m_contentLanguage; }
     void setContentLanguage(const AtomicString&);
@@ -648,6 +653,7 @@
 
     void scheduleRenderTreeUpdate();
     bool hasPendingForcedStyleRecalc() const;
+    bool hasPendingStyleRecalc() const { return m_lifecycle.state() == DocumentLifecycle::StyleRecalcPending; }
 
     void registerNodeList(LiveNodeListBase*);
     void unregisterNodeList(LiveNodeListBase*);
@@ -1117,8 +1123,6 @@
     void updateFocusAppearanceTimerFired(Timer<Document>*);
     void updateBaseURL();
 
-    bool hasPendingStyleRecalc() const { return m_lifecycle.state() == DocumentLifecycle::StyleRecalcPending; }
-
     void executeScriptsWaitingForResourcesIfNeeded();
 
     PassRefPtr<NodeList> handleZeroPadding(const HitTestRequest&, HitTestResult&) const;
@@ -1185,6 +1189,9 @@
 
     AtomicString m_baseTarget;
 
+    // Mime-type of the document in case it was cloned or created by XHR.
+    AtomicString m_mimeType;
+
     RefPtr<DocumentType> m_docType;
     OwnPtr<DOMImplementation> m_implementation;
 
@@ -1309,6 +1316,7 @@
 
     ViewportDescription m_viewportDescription;
     ViewportDescription m_legacyViewportDescription;
+    Length m_viewportDefaultMinWidth;
 
     bool m_didSetReferrerPolicy;
     ReferrerPolicy m_referrerPolicy;
diff --git a/Source/core/dom/Document.idl b/Source/core/dom/Document.idl
index e61390b..fe3d996 100644
--- a/Source/core/dom/Document.idl
+++ b/Source/core/dom/Document.idl
@@ -89,6 +89,9 @@
      CSSStyleDeclaration getOverrideStyle([Default=Undefined] optional Element element,
                                                         [Default=Undefined] optional DOMString pseudoElement);
 
+    // DOM 4
+    readonly attribute DOMString contentType;
+
     // Common extensions
     [CustomElementCallbacks]
     boolean            execCommand([Default=Undefined] optional DOMString command,
diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp
index b9b4bc3..46a6053 100644
--- a/Source/core/dom/Element.cpp
+++ b/Source/core/dom/Element.cpp
@@ -1084,11 +1084,11 @@
         elementData()->setClass(newClassString, shouldFoldCase);
         const SpaceSplitString& newClasses = elementData()->classNames();
         if (testShouldInvalidateStyle)
-            styleResolver->ensureUpdatedRuleFeatureSet().scheduleStyleInvalidationForClassChange(oldClasses, newClasses, this);
+            styleResolver->ensureUpdatedRuleFeatureSet().scheduleStyleInvalidationForClassChange(oldClasses, newClasses, *this);
     } else {
         const SpaceSplitString& oldClasses = elementData()->classNames();
         if (testShouldInvalidateStyle)
-            styleResolver->ensureUpdatedRuleFeatureSet().scheduleStyleInvalidationForClassChange(oldClasses, this);
+            styleResolver->ensureUpdatedRuleFeatureSet().scheduleStyleInvalidationForClassChange(oldClasses, *this);
         elementData()->clearClass();
     }
 
@@ -2875,7 +2875,7 @@
 
     if (oldValue != newValue) {
         if (inActiveDocument())
-            document().ensureStyleResolver().ensureUpdatedRuleFeatureSet().scheduleStyleInvalidationForAttributeChange(name, this);
+            document().ensureStyleResolver().ensureUpdatedRuleFeatureSet().scheduleStyleInvalidationForAttributeChange(name, *this);
 
         if (isUpgradedCustomElement())
             CustomElement::attributeDidChange(this, name.localName(), oldValue, newValue);
diff --git a/Source/core/dom/Node.cpp b/Source/core/dom/Node.cpp
index d99a120..e2e7961 100644
--- a/Source/core/dom/Node.cpp
+++ b/Source/core/dom/Node.cpp
@@ -744,6 +744,9 @@
     for (ContainerNode* p = parentOrShadowHostNode(); p && !p->childNeedsStyleRecalc(); p = p->parentOrShadowHostNode())
         p->setChildNeedsStyleRecalc();
 
+    if (document().hasPendingStyleRecalc())
+        return;
+
     if (document().needsStyleRecalc() || document().childNeedsStyleRecalc())
         document().scheduleRenderTreeUpdate();
 }
@@ -1004,7 +1007,7 @@
     setChildNeedsStyleRecalc();
 
     if (StyleResolver* resolver = document().styleResolver())
-        resolver->ruleFeatureSet().clearStyleInvalidation(this);
+        resolver->ruleFeatureSet().styleInvalidator().clearInvalidation(*this);
 
 #ifndef NDEBUG
     detachingNode = 0;
diff --git a/Source/core/dom/StyleElement.cpp b/Source/core/dom/StyleElement.cpp
index fb172ed..cbe3765 100644
--- a/Source/core/dom/StyleElement.cpp
+++ b/Source/core/dom/StyleElement.cpp
@@ -60,6 +60,7 @@
 {
     TRACE_EVENT0("webkit", "StyleElement::processStyleSheet");
     ASSERT(element);
+    ASSERT(element->inDocument());
 
     m_registeredAsCandidate = true;
     document.styleEngine()->addStyleSheetCandidateNode(element, m_createdByParser);
@@ -78,20 +79,17 @@
 {
     ASSERT(element);
 
-    if (!m_registeredAsCandidate) {
-        ASSERT(!m_sheet);
-        return;
+    if (m_registeredAsCandidate) {
+        document.styleEngine()->removeStyleSheetCandidateNode(element, scopingNode, treeScope);
+        m_registeredAsCandidate = false;
     }
 
-    document.styleEngine()->removeStyleSheetCandidateNode(element, scopingNode, treeScope);
-    m_registeredAsCandidate = false;
-
     RefPtrWillBeRawPtr<StyleSheet> removedSheet = m_sheet.get();
 
     if (m_sheet)
         clearSheet(element);
-
-    document.removedStyleSheet(removedSheet.get(), RecalcStyleDeferred, AnalyzedStyleUpdate);
+    if (removedSheet)
+        document.removedStyleSheet(removedSheet.get(), RecalcStyleDeferred, AnalyzedStyleUpdate);
 }
 
 void StyleElement::clearDocumentData(Document& document, Element* element)
diff --git a/Source/core/dom/ViewportDescription.cpp b/Source/core/dom/ViewportDescription.cpp
index 7f63c6a..5e928bd 100644
--- a/Source/core/dom/ViewportDescription.cpp
+++ b/Source/core/dom/ViewportDescription.cpp
@@ -70,11 +70,29 @@
     return ViewportDescription::ValueAuto;
 }
 
-PageScaleConstraints ViewportDescription::resolve(const FloatSize& initialViewportSize) const
+PageScaleConstraints ViewportDescription::resolve(const FloatSize& initialViewportSize, Length legacyFallbackWidth) const
 {
     float resultWidth = ValueAuto;
-    float resultMaxWidth = resolveViewportLength(maxWidth, initialViewportSize, Horizontal);
-    float resultMinWidth = resolveViewportLength(minWidth, initialViewportSize, Horizontal);
+
+    Length copyMaxWidth = maxWidth;
+    Length copyMinWidth = minWidth;
+    // In case the width (used for min- and max-width) is undefined.
+    if (isLegacyViewportType() && maxWidth.isAuto()) {
+        // The width viewport META property is translated into 'width' descriptors, setting
+        // the 'min' value to 'extend-to-zoom' and the 'max' value to the intended length.
+        // In case the UA-defines a min-width, use that as length.
+        if (zoom == ViewportDescription::ValueAuto) {
+            copyMinWidth = Length(ExtendToZoom);
+            copyMaxWidth = legacyFallbackWidth;
+        } else if (maxHeight.isAuto()) {
+            copyMinWidth = Length(ExtendToZoom);
+            copyMaxWidth = Length(ExtendToZoom);
+        }
+    }
+
+    float resultMaxWidth = resolveViewportLength(copyMaxWidth, initialViewportSize, Horizontal);
+    float resultMinWidth = resolveViewportLength(copyMinWidth, initialViewportSize, Horizontal);
+
     float resultHeight = ValueAuto;
     float resultMaxHeight = resolveViewportLength(maxHeight, initialViewportSize, Vertical);
     float resultMinHeight = resolveViewportLength(minHeight, initialViewportSize, Vertical);
diff --git a/Source/core/dom/ViewportDescription.h b/Source/core/dom/ViewportDescription.h
index 53eed26..2f4b13f 100644
--- a/Source/core/dom/ViewportDescription.h
+++ b/Source/core/dom/ViewportDescription.h
@@ -70,7 +70,7 @@
     }
 
     // All arguments are in CSS units.
-    PageScaleConstraints resolve(const FloatSize& initialViewportSize) const;
+    PageScaleConstraints resolve(const FloatSize& initialViewportSize, Length legacyFallbackWidth) const;
 
     Length minWidth;
     Length maxWidth;
diff --git a/Source/core/dom/custom/CustomElement.cpp b/Source/core/dom/custom/CustomElement.cpp
index 4810925..432b7f5 100644
--- a/Source/core/dom/custom/CustomElement.cpp
+++ b/Source/core/dom/custom/CustomElement.cpp
@@ -98,7 +98,7 @@
 
     case Element::WaitingForUpgrade:
         element->setCustomElementDefinition(definition);
-        CustomElementScheduler::scheduleCreatedCallback(definition->callbacks(), element);
+        CustomElementScheduler::scheduleCallback(definition->callbacks(), element, CustomElementLifecycleCallbacks::Created);
         break;
     }
 }
@@ -114,7 +114,7 @@
     ASSERT(element->customElementState() == Element::Upgraded);
     if (!document.domWindow())
         return;
-    CustomElementScheduler::scheduleAttachedCallback(element->customElementDefinition()->callbacks(), element);
+    CustomElementScheduler::scheduleCallback(element->customElementDefinition()->callbacks(), element, CustomElementLifecycleCallbacks::Attached);
 }
 
 void CustomElement::didLeaveDocument(Element* element, const Document& document)
@@ -122,7 +122,7 @@
     ASSERT(element->customElementState() == Element::Upgraded);
     if (!document.domWindow())
         return;
-    CustomElementScheduler::scheduleDetachedCallback(element->customElementDefinition()->callbacks(), element);
+    CustomElementScheduler::scheduleCallback(element->customElementDefinition()->callbacks(), element, CustomElementLifecycleCallbacks::Detached);
 }
 
 void CustomElement::wasDestroyed(Element* element)
diff --git a/Source/core/dom/custom/CustomElementCallbackInvocation.cpp b/Source/core/dom/custom/CustomElementCallbackInvocation.cpp
index b7eb8e4..a3afe31 100644
--- a/Source/core/dom/custom/CustomElementCallbackInvocation.cpp
+++ b/Source/core/dom/custom/CustomElementCallbackInvocation.cpp
@@ -107,7 +107,7 @@
 void CreatedInvocation::dispatch(Element* element)
 {
     if (element->inDocument() && element->document().domWindow())
-        CustomElementScheduler::scheduleAttachedCallback(callbacks(), element);
+        CustomElementScheduler::scheduleCallback(callbacks(), element, CustomElementLifecycleCallbacks::Attached);
     callbacks()->created(element);
 }
 
diff --git a/Source/core/dom/custom/CustomElementLifecycleCallbacks.h b/Source/core/dom/custom/CustomElementLifecycleCallbacks.h
index aa182e6..a713815 100644
--- a/Source/core/dom/custom/CustomElementLifecycleCallbacks.h
+++ b/Source/core/dom/custom/CustomElementLifecycleCallbacks.h
@@ -42,18 +42,6 @@
 public:
     virtual ~CustomElementLifecycleCallbacks() { }
 
-    bool hasCreatedCallback() const { return m_which & Created; }
-    virtual void created(Element*) = 0;
-
-    bool hasAttachedCallback() const { return m_which & Attached; }
-    virtual void attached(Element*) = 0;
-
-    bool hasDetachedCallback() const { return m_which & Detached; }
-    virtual void detached(Element*) = 0;
-
-    bool hasAttributeChangedCallback() const { return m_which & AttributeChanged; }
-    virtual void attributeChanged(Element*, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue) = 0;
-
     enum CallbackType {
         None             = 0,
         Created          = 1 << 0,
@@ -62,6 +50,13 @@
         AttributeChanged = 1 << 3
     };
 
+    bool hasCallback(CallbackType type) const { return m_which & type; }
+
+    virtual void created(Element*) = 0;
+    virtual void attached(Element*) = 0;
+    virtual void detached(Element*) = 0;
+    virtual void attributeChanged(Element*, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue) = 0;
+
 protected:
     CustomElementLifecycleCallbacks(CallbackType which) : m_which(which) { }
 
diff --git a/Source/core/dom/custom/CustomElementScheduler.cpp b/Source/core/dom/custom/CustomElementScheduler.cpp
index 7743156..6878cae 100644
--- a/Source/core/dom/custom/CustomElementScheduler.cpp
+++ b/Source/core/dom/custom/CustomElementScheduler.cpp
@@ -46,39 +46,26 @@
 
 class HTMLImport;
 
-void CustomElementScheduler::scheduleCreatedCallback(PassRefPtr<CustomElementLifecycleCallbacks> callbacks, PassRefPtr<Element> element)
+void CustomElementScheduler::scheduleCallback(PassRefPtr<CustomElementLifecycleCallbacks> callbacks, PassRefPtr<Element> element, CustomElementLifecycleCallbacks::CallbackType type)
 {
+    ASSERT(type != CustomElementLifecycleCallbacks::AttributeChanged);
+
+    if (!callbacks->hasCallback(type))
+        return;
+
     CustomElementCallbackQueue& queue = instance().schedule(element);
-    queue.append(CustomElementCallbackInvocation::createInvocation(callbacks, CustomElementLifecycleCallbacks::Created));
+    queue.append(CustomElementCallbackInvocation::createInvocation(callbacks, type));
 }
 
 void CustomElementScheduler::scheduleAttributeChangedCallback(PassRefPtr<CustomElementLifecycleCallbacks> callbacks, PassRefPtr<Element> element, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue)
 {
-    if (!callbacks->hasAttributeChangedCallback())
+    if (!callbacks->hasCallback(CustomElementLifecycleCallbacks::AttributeChanged))
         return;
 
     CustomElementCallbackQueue& queue = instance().schedule(element);
     queue.append(CustomElementCallbackInvocation::createAttributeChangedInvocation(callbacks, name, oldValue, newValue));
 }
 
-void CustomElementScheduler::scheduleAttachedCallback(PassRefPtr<CustomElementLifecycleCallbacks> callbacks, PassRefPtr<Element> element)
-{
-    if (!callbacks->hasAttachedCallback())
-        return;
-
-    CustomElementCallbackQueue& queue = instance().schedule(element);
-    queue.append(CustomElementCallbackInvocation::createInvocation(callbacks, CustomElementLifecycleCallbacks::Attached));
-}
-
-void CustomElementScheduler::scheduleDetachedCallback(PassRefPtr<CustomElementLifecycleCallbacks> callbacks, PassRefPtr<Element> element)
-{
-    if (!callbacks->hasDetachedCallback())
-        return;
-
-    CustomElementCallbackQueue& queue = instance().schedule(element);
-    queue.append(CustomElementCallbackInvocation::createInvocation(callbacks, CustomElementLifecycleCallbacks::Detached));
-}
-
 void CustomElementScheduler::resolveOrScheduleResolution(PassRefPtr<CustomElementRegistrationContext> context, PassRefPtr<Element> element, const CustomElementDescriptor& descriptor)
 {
     if (CustomElementCallbackDispatcher::inCallbackDeliveryScope()) {
diff --git a/Source/core/dom/custom/CustomElementScheduler.h b/Source/core/dom/custom/CustomElementScheduler.h
index ee8c870..b17b875 100644
--- a/Source/core/dom/custom/CustomElementScheduler.h
+++ b/Source/core/dom/custom/CustomElementScheduler.h
@@ -32,6 +32,7 @@
 #define CustomElementScheduler_h
 
 #include "core/dom/custom/CustomElementCallbackQueue.h"
+#include "core/dom/custom/CustomElementLifecycleCallbacks.h"
 #include "wtf/HashMap.h"
 #include "wtf/OwnPtr.h"
 #include "wtf/PassRefPtr.h"
@@ -40,17 +41,14 @@
 namespace WebCore {
 
 class CustomElementDescriptor;
-class CustomElementLifecycleCallbacks;
 class CustomElementMicrotaskImportStep;
 class Element;
 class HTMLImportChild;
 
 class CustomElementScheduler {
 public:
-    static void scheduleCreatedCallback(PassRefPtr<CustomElementLifecycleCallbacks>, PassRefPtr<Element>);
+    static void scheduleCallback(PassRefPtr<CustomElementLifecycleCallbacks>, PassRefPtr<Element>, CustomElementLifecycleCallbacks::CallbackType);
     static void scheduleAttributeChangedCallback(PassRefPtr<CustomElementLifecycleCallbacks>, PassRefPtr<Element>, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue);
-    static void scheduleAttachedCallback(PassRefPtr<CustomElementLifecycleCallbacks>, PassRefPtr<Element>);
-    static void scheduleDetachedCallback(PassRefPtr<CustomElementLifecycleCallbacks>, PassRefPtr<Element>);
 
     static void resolveOrScheduleResolution(PassRefPtr<CustomElementRegistrationContext>, PassRefPtr<Element>, const CustomElementDescriptor&);
     static CustomElementMicrotaskImportStep* scheduleImport(HTMLImportChild*);
diff --git a/Source/core/dom/shadow/ShadowRoot.idl b/Source/core/dom/shadow/ShadowRoot.idl
index 8c69807..24bc69b 100644
--- a/Source/core/dom/shadow/ShadowRoot.idl
+++ b/Source/core/dom/shadow/ShadowRoot.idl
@@ -24,9 +24,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-[
-    NoInterfaceObject
-] interface ShadowRoot : DocumentFragment {
+interface ShadowRoot : DocumentFragment {
     readonly attribute Element activeElement;
 
     [ImplementedAs=olderShadowRootForBindings] readonly attribute ShadowRoot olderShadowRoot;