Merge from Chromium at DEPS revision 33.0.1750.70

This commit was generated by merge_to_master.py.

Change-Id: I4594a61403de213df4bb408f52c6ca5333d4f244
diff --git a/Source/core/animation/css/CSSAnimations.cpp b/Source/core/animation/css/CSSAnimations.cpp
index cdcff2e..fc0f0f8 100644
--- a/Source/core/animation/css/CSSAnimations.cpp
+++ b/Source/core/animation/css/CSSAnimations.cpp
@@ -92,11 +92,13 @@
     return chainedTimingFunction;
 }
 
-static void resolveKeyframes(StyleResolver* resolver, Element* element, const RenderStyle& style, RenderStyle* parentStyle, const AtomicString& name, TimingFunction* defaultTimingFunction,
+static void resolveKeyframes(StyleResolver* resolver, Element* element, const Element& parentElement, const RenderStyle& style, RenderStyle* parentStyle, const AtomicString& name, TimingFunction* defaultTimingFunction,
     Vector<std::pair<KeyframeAnimationEffect::KeyframeVector, RefPtr<TimingFunction> > >& keyframesAndTimingFunctions)
 {
     ASSERT(RuntimeEnabledFeatures::webAnimationsCSSEnabled());
-    const StyleRuleKeyframes* keyframesRule = CSSAnimations::matchScopedKeyframesRule(resolver, element, name.impl());
+    // When the element is null, use its parent for scoping purposes.
+    const Element* elementForScoping = element ? element : &parentElement;
+    const StyleRuleKeyframes* keyframesRule = CSSAnimations::matchScopedKeyframesRule(resolver, elementForScoping, name.impl());
     if (!keyframesRule)
         return;
 
@@ -110,6 +112,7 @@
     HashMap<double, RefPtr<TimingFunction> > perKeyframeTimingFunctions;
     for (size_t i = 0; i < styleKeyframes.size(); ++i) {
         const StyleKeyframe* styleKeyframe = styleKeyframes[i].get();
+        // It's OK to pass a null element here.
         RefPtr<RenderStyle> keyframeStyle = resolver->styleForKeyframe(element, style, parentStyle, styleKeyframe, name);
         RefPtr<Keyframe> keyframe = Keyframe::create();
         const Vector<double>& offsets = styleKeyframe->keys();
@@ -344,21 +347,22 @@
     return 0;
 }
 
-PassOwnPtr<CSSAnimationUpdate> CSSAnimations::calculateUpdate(Element* element, const RenderStyle& style, RenderStyle* parentStyle, StyleResolver* resolver)
+PassOwnPtr<CSSAnimationUpdate> CSSAnimations::calculateUpdate(Element* element, const Element& parentElement, const RenderStyle& style, RenderStyle* parentStyle, StyleResolver* resolver)
 {
     ASSERT(RuntimeEnabledFeatures::webAnimationsCSSEnabled());
     OwnPtr<CSSAnimationUpdate> update = adoptPtr(new CSSAnimationUpdate());
-    calculateAnimationUpdate(update.get(), element, style, parentStyle, resolver);
+    calculateAnimationUpdate(update.get(), element, parentElement, style, parentStyle, resolver);
     calculateAnimationCompositableValues(update.get(), element);
     calculateTransitionUpdate(update.get(), element, style);
     calculateTransitionCompositableValues(update.get(), element);
     return update->isEmpty() ? nullptr : update.release();
 }
 
-void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, Element* element, const RenderStyle& style, RenderStyle* parentStyle, StyleResolver* resolver)
+void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, Element* element, const Element& parentElement, const RenderStyle& style, RenderStyle* parentStyle, StyleResolver* resolver)
 {
+    const ActiveAnimations* activeAnimations = element ? element->activeAnimations() : 0;
     const CSSAnimationDataList* animationDataList = style.animations();
-    const CSSAnimations* cssAnimations = element->activeAnimations() ? &element->activeAnimations()->cssAnimations() : 0;
+    const CSSAnimations* cssAnimations = activeAnimations ? &activeAnimations->cssAnimations() : 0;
 
     HashSet<AtomicString> inactive;
     if (cssAnimations)
@@ -397,7 +401,7 @@
             bool isPaused;
             RefPtr<TimingFunction> defaultTimingFunction = timingFromAnimationData(animationData, timing, isPaused);
             Vector<std::pair<KeyframeAnimationEffect::KeyframeVector, RefPtr<TimingFunction> > > keyframesAndTimingFunctions;
-            resolveKeyframes(resolver, element, style, parentStyle, animationName, defaultTimingFunction.get(), keyframesAndTimingFunctions);
+            resolveKeyframes(resolver, element, parentElement, style, parentStyle, animationName, defaultTimingFunction.get(), keyframesAndTimingFunctions);
             if (!keyframesAndTimingFunctions.isEmpty()) {
                 HashSet<RefPtr<InertAnimation> > animations;
                 for (size_t j = 0; j < keyframesAndTimingFunctions.size(); ++j) {
@@ -572,6 +576,9 @@
 
 void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate* update, const Element* element, const RenderStyle& style)
 {
+    if (!element)
+        return;
+
     ActiveAnimations* activeAnimations = element->activeAnimations();
     const TransitionMap* activeTransitions = activeAnimations ? &activeAnimations->cssAnimations().m_transitions : 0;
 
@@ -651,7 +658,7 @@
 
 void CSSAnimations::calculateAnimationCompositableValues(CSSAnimationUpdate* update, const Element* element)
 {
-    ActiveAnimations* activeAnimations = element->activeAnimations();
+    ActiveAnimations* activeAnimations = element ? element->activeAnimations() : 0;
     AnimationStack* animationStack = activeAnimations ? &activeAnimations->defaultStack() : 0;
 
     if (update->newAnimations().isEmpty() && update->cancelledAnimationPlayers().isEmpty()) {
@@ -672,7 +679,7 @@
 
 void CSSAnimations::calculateTransitionCompositableValues(CSSAnimationUpdate* update, const Element* element)
 {
-    ActiveAnimations* activeAnimations = element->activeAnimations();
+    ActiveAnimations* activeAnimations = element ? element->activeAnimations() : 0;
     AnimationStack* animationStack = activeAnimations ? &activeAnimations->defaultStack() : 0;
 
     AnimationEffect::CompositableValueMap compositableValuesForTransitions;
diff --git a/Source/core/animation/css/CSSAnimations.h b/Source/core/animation/css/CSSAnimations.h
index 6a8ddb2..fb553d9 100644
--- a/Source/core/animation/css/CSSAnimations.h
+++ b/Source/core/animation/css/CSSAnimations.h
@@ -149,7 +149,7 @@
     static const StylePropertyShorthand& animatableProperties();
     // FIXME: This should take a const ScopedStyleTree instead of a StyleResolver.
     // We should also change the Element* to a const Element*
-    static PassOwnPtr<CSSAnimationUpdate> calculateUpdate(Element*, const RenderStyle&, RenderStyle* parentStyle, StyleResolver*);
+    static PassOwnPtr<CSSAnimationUpdate> calculateUpdate(Element*, const Element& parentElement, const RenderStyle&, RenderStyle* parentStyle, StyleResolver*);
 
     void setPendingUpdate(PassOwnPtr<CSSAnimationUpdate> update) { m_pendingUpdate = update; }
     void maybeApplyPendingUpdate(Element*);
@@ -174,7 +174,7 @@
 
     AnimationEffect::CompositableValueMap m_previousCompositableValuesForAnimations;
 
-    static void calculateAnimationUpdate(CSSAnimationUpdate*, Element*, const RenderStyle&, RenderStyle* parentStyle, StyleResolver*);
+    static void calculateAnimationUpdate(CSSAnimationUpdate*, Element*, const Element& parentElement, const RenderStyle&, RenderStyle* parentStyle, StyleResolver*);
     static void calculateTransitionUpdate(CSSAnimationUpdate*, const Element*, const RenderStyle&);
     static void calculateTransitionUpdateForProperty(CSSPropertyID, const CSSAnimationData*, const RenderStyle& oldStyle, const RenderStyle&, const TransitionMap* activeTransitions, CSSAnimationUpdate*, const Element*);
 
diff --git a/Source/core/css/resolver/StyleResolver.cpp b/Source/core/css/resolver/StyleResolver.cpp
index c761d72..bc5cbda 100644
--- a/Source/core/css/resolver/StyleResolver.cpp
+++ b/Source/core/css/resolver/StyleResolver.cpp
@@ -883,15 +883,39 @@
     return KeyframeAnimationEffect::create(keyframes);
 }
 
-PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* element, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle)
+PassRefPtr<PseudoElement> StyleResolver::createPseudoElementIfNeeded(Element& element, PseudoId pseudoId)
+{
+    RenderObject* renderer = element.renderer();
+    if (!renderer)
+        return 0;
+
+    if (pseudoId < FIRST_INTERNAL_PSEUDOID && !renderer->style()->hasPseudoStyle(pseudoId))
+        return 0;
+
+    RenderStyle* parentStyle = renderer->style();
+    StyleResolverState state(document(), &element, parentStyle);
+    if (!pseudoStyleForElementInternal(element, pseudoId, parentStyle, state))
+        return 0;
+    RefPtr<RenderStyle> style = state.takeStyle();
+    ASSERT(style);
+
+    if (!element.needsPseudoElement(pseudoId, *style))
+        return 0;
+
+    renderer->style()->addCachedPseudoStyle(style.release());
+    RefPtr<PseudoElement> pseudo = PseudoElement::create(&element, pseudoId);
+
+    setAnimationUpdateIfNeeded(state, *pseudo);
+    if (ActiveAnimations* activeAnimations = pseudo->activeAnimations())
+        activeAnimations->cssAnimations().maybeApplyPendingUpdate(pseudo.get());
+    return pseudo.release();
+}
+
+bool StyleResolver::pseudoStyleForElementInternal(Element& element, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle, StyleResolverState& state)
 {
     ASSERT(document().frame());
     ASSERT(documentSettings());
-    ASSERT(parentStyle);
-    if (!element)
-        return 0;
-
-    StyleResolverState state(document(), element, parentStyle);
+    ASSERT(pseudoStyleRequest.pseudoId != FIRST_LINE_INHERITED);
 
     if (pseudoStyleRequest.allowsInheritance(state.parentStyle())) {
         state.setStyle(RenderStyle::create());
@@ -915,7 +939,7 @@
         matchAuthorRules(state.element(), collector, false);
 
         if (collector.matchedResult().matchedProperties.isEmpty())
-            return 0;
+            return false;
 
         state.style()->setStyleType(pseudoStyleRequest.pseudoId);
 
@@ -933,10 +957,23 @@
     // FIXME: The CSSWG wants to specify that the effects of animations are applied before
     // important rules, but this currently happens here as we require adjustment to have happened
     // before deciding which properties to transition.
-    applyAnimatedProperties(state, element->pseudoElement(pseudoStyleRequest.pseudoId));
+    applyAnimatedProperties(state, element.pseudoElement(pseudoStyleRequest.pseudoId));
 
     didAccess();
 
+    return true;
+}
+
+PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* element, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle)
+{
+    ASSERT(parentStyle);
+    if (!element)
+        return 0;
+
+    StyleResolverState state(document(), element, parentStyle);
+    if (!pseudoStyleForElementInternal(*element, pseudoStyleRequest, parentStyle, state))
+        return 0;
+
     if (PseudoElement* pseudoElement = element->pseudoElement(pseudoStyleRequest.pseudoId))
         setAnimationUpdateIfNeeded(state, *pseudoElement);
 
@@ -1090,19 +1127,26 @@
 
 void StyleResolver::applyAnimatedProperties(StyleResolverState& state, Element* animatingElement)
 {
-    // animatingElement may be null, for example if we're calculating the
-    // style for a potential pseudo element that has yet to be created.
-    if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled() || !animatingElement)
+    if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled())
         return;
 
-    if (!animatingElement->hasActiveAnimations()
+    const Element* element = state.element();
+    ASSERT(element);
+
+    // The animating element may be this element, or its pseudo element. It is
+    // null when calculating the style for a potential pseudo element that has
+    // yet to be created.
+    ASSERT(animatingElement == element || !animatingElement || animatingElement->parentOrShadowHostElement() == element);
+
+    if (!(animatingElement && animatingElement->hasActiveAnimations())
         && !(state.style()->transitions() && !state.style()->transitions()->isEmpty())
         && !(state.style()->animations() && !state.style()->animations()->isEmpty()))
         return;
 
-    state.setAnimationUpdate(CSSAnimations::calculateUpdate(animatingElement, *state.style(), state.parentStyle(), this));
+    state.setAnimationUpdate(CSSAnimations::calculateUpdate(animatingElement, *element, *state.style(), state.parentStyle(), this));
     if (!state.animationUpdate())
         return;
+
     const AnimationEffect::CompositableValueMap& compositableValuesForAnimations = state.animationUpdate()->compositableValuesForAnimations();
     const AnimationEffect::CompositableValueMap& compositableValuesForTransitions = state.animationUpdate()->compositableValuesForTransitions();
     applyAnimatedProperties<HighPriorityProperties>(state, compositableValuesForAnimations);
diff --git a/Source/core/css/resolver/StyleResolver.h b/Source/core/css/resolver/StyleResolver.h
index 96a0ac1..f1dae0b 100644
--- a/Source/core/css/resolver/StyleResolver.h
+++ b/Source/core/css/resolver/StyleResolver.h
@@ -229,6 +229,8 @@
     unsigned accessCount() const { return m_accessCount; }
     void didAccess() { ++m_accessCount; }
 
+    PassRefPtr<PseudoElement> createPseudoElementIfNeeded(Element&, PseudoId);
+
 private:
     // FontSelectorClient implementation.
     virtual void fontsNeedUpdate(FontSelector*);
@@ -284,6 +286,8 @@
     bool isFirstPage(int pageIndex) const;
     String pageName(int pageIndex) const;
 
+    bool pseudoStyleForElementInternal(Element&, const PseudoStyleRequest&, RenderStyle* parentStyle, StyleResolverState&);
+
     // FIXME: This likely belongs on RuleSet.
     typedef HashMap<StringImpl*, RefPtr<StyleRuleKeyframes> > KeyframesRuleMap;
     KeyframesRuleMap m_keyframesRuleMap;
diff --git a/Source/core/dom/Element.cpp b/Source/core/dom/Element.cpp
index 1dec7bd..60502e8 100644
--- a/Source/core/dom/Element.cpp
+++ b/Source/core/dom/Element.cpp
@@ -2739,28 +2739,26 @@
         createPseudoElementIfNeeded(pseudoId);
 }
 
-void Element::createPseudoElementIfNeeded(PseudoId pseudoId)
-{
-    if (needsPseudoElement(pseudoId))
-        createPseudoElement(pseudoId);
-}
-
-bool Element::needsPseudoElement(PseudoId pseudoId) const
+bool Element::needsPseudoElement(PseudoId pseudoId, const RenderStyle& style) const
 {
     if (pseudoId == BACKDROP && !isInTopLayer())
         return false;
-    if (!renderer() || !pseudoElementRendererIsNeeded(renderer()->getCachedPseudoStyle(pseudoId)))
+    if (!renderer() || !pseudoElementRendererIsNeeded(&style))
         return false;
     if (!renderer()->canHaveGeneratedChildren())
         return false;
     return true;
 }
 
-void Element::createPseudoElement(PseudoId pseudoId)
+void Element::createPseudoElementIfNeeded(PseudoId pseudoId)
 {
-    ASSERT(needsPseudoElement(pseudoId));
-    ASSERT(!isPseudoElement());
-    RefPtr<PseudoElement> element = PseudoElement::create(this, pseudoId);
+    if (isPseudoElement())
+        return;
+
+    RefPtr<PseudoElement> element = document().ensureStyleResolver().createPseudoElementIfNeeded(*this, pseudoId);
+    if (!element)
+        return;
+
     if (pseudoId == BACKDROP)
         document().addToTopLayer(element.get(), this);
     element->insertedInto(this);
diff --git a/Source/core/dom/Element.h b/Source/core/dom/Element.h
index eca5712..370d7d6 100644
--- a/Source/core/dom/Element.h
+++ b/Source/core/dom/Element.h
@@ -522,6 +522,8 @@
 
     void synchronizeAttribute(const AtomicString& localName) const;
 
+    bool needsPseudoElement(PseudoId, const RenderStyle&) const;
+
 protected:
     Element(const QualifiedName& tagName, Document* document, ConstructionType type)
         : ContainerNode(document, type)
@@ -591,8 +593,6 @@
     void updatePseudoElement(PseudoId, StyleRecalcChange);
 
     inline void createPseudoElementIfNeeded(PseudoId);
-    inline bool needsPseudoElement(PseudoId) const;
-    void createPseudoElement(PseudoId);
 
     // FIXME: Everyone should allow author shadows.
     virtual bool areAuthorShadowsAllowed() const { return true; }
diff --git a/Source/core/fetch/ResourceFetcher.cpp b/Source/core/fetch/ResourceFetcher.cpp
index ea42382..6418dc9 100644
--- a/Source/core/fetch/ResourceFetcher.cpp
+++ b/Source/core/fetch/ResourceFetcher.cpp
@@ -164,16 +164,21 @@
     return resource;
 }
 
-static void reportResourceTiming(ResourceTimingInfo* info, Resource* resource, double finishTime, Document* initiatorDocument, bool clearLoadTimings)
+static void populateResourceTiming(ResourceTimingInfo* info, Resource* resource, bool clearLoadTimings)
 {
-    if (resource->type() == Resource::MainResource)
-        initiatorDocument = initiatorDocument->parentDocument();
-    ASSERT(initiatorDocument);
     info->setInitialRequest(resource->resourceRequest());
     info->setFinalResponse(resource->response());
     if (clearLoadTimings)
         info->clearLoadTimings();
-    info->setLoadFinishTime(finishTime);
+    info->setLoadFinishTime(resource->loadFinishTime());
+}
+
+static void reportResourceTiming(ResourceTimingInfo* info, Document* initiatorDocument, bool isMainResource)
+{
+    if (initiatorDocument && isMainResource)
+        initiatorDocument = initiatorDocument->parentDocument();
+    if (!initiatorDocument)
+        return;
     if (DOMWindow* initiatorWindow = initiatorDocument->domWindow()) {
         if (Performance* performance = initiatorWindow->performance())
             performance->addResourceTiming(*info, initiatorDocument);
@@ -219,6 +224,7 @@
     , m_documentLoader(documentLoader)
     , m_requestCount(0)
     , m_garbageCollectDocumentResourcesTimer(this, &ResourceFetcher::garbageCollectDocumentResourcesTimerFired)
+    , m_resourceTimingReportTimer(this, &ResourceFetcher::resourceTimingReportTimerFired)
     , m_autoLoadImages(true)
     , m_imagesEnabled(true)
     , m_allowStaleResources(false)
@@ -673,7 +679,10 @@
         if (policy == Use && !m_validatedURLs.contains(request.resourceRequest().url())) {
             // Resources loaded from memory cache should be reported the first time they're used.
             RefPtr<ResourceTimingInfo> info = ResourceTimingInfo::create(request.options().initiatorInfo.name, monotonicallyIncreasingTime());
-            reportResourceTiming(info.get(), resource.get(), monotonicallyIncreasingTime(), document(), true);
+            populateResourceTiming(info.get(), resource.get(), true);
+            m_scheduledResourceTimingReports.add(info, resource->type() == Resource::MainResource);
+            if (!m_resourceTimingReportTimer.isActive())
+                m_resourceTimingReportTimer.startOneShot(0);
         }
 
         m_validatedURLs.add(request.resourceRequest().url());
@@ -684,6 +693,19 @@
     return resource;
 }
 
+void ResourceFetcher::resourceTimingReportTimerFired(Timer<ResourceFetcher>* timer)
+{
+    ASSERT_UNUSED(timer, timer == &m_resourceTimingReportTimer);
+    HashMap<RefPtr<ResourceTimingInfo>, bool> timingReports;
+    timingReports.swap(m_scheduledResourceTimingReports);
+    HashMap<RefPtr<ResourceTimingInfo>, bool>::iterator end = timingReports.end();
+    for (HashMap<RefPtr<ResourceTimingInfo>, bool>::iterator it = timingReports.begin(); it != end; ++it) {
+        RefPtr<ResourceTimingInfo> info = it->key;
+        bool isMainResource = it->value;
+        reportResourceTiming(info.get(), document(), isMainResource);
+    }
+}
+
 void ResourceFetcher::determineTargetType(ResourceRequest& request, Resource::Type type)
 {
     ResourceRequest::TargetType targetType = requestTargetType(this, request, type);
@@ -983,7 +1005,8 @@
         if (it != m_resourceTimingInfoMap.end()) {
             RefPtr<ResourceTimingInfo> info = it->value;
             m_resourceTimingInfoMap.remove(it);
-            reportResourceTiming(info.get(), resource, resource->loadFinishTime(), document(), false);
+            populateResourceTiming(info.get(), resource, false);
+            reportResourceTiming(info.get(), document(), resource->type() == Resource::MainResource);
         }
     }
 
diff --git a/Source/core/fetch/ResourceFetcher.h b/Source/core/fetch/ResourceFetcher.h
index 318e6ff..bb1995e 100644
--- a/Source/core/fetch/ResourceFetcher.h
+++ b/Source/core/fetch/ResourceFetcher.h
@@ -190,6 +190,9 @@
     void notifyLoadedFromMemoryCache(Resource*);
 
     void garbageCollectDocumentResourcesTimerFired(Timer<ResourceFetcher>*);
+
+    void resourceTimingReportTimerFired(Timer<ResourceFetcher>*);
+
     void performPostLoadActions();
 
     bool clientDefersImage(const KURL&) const;
@@ -211,10 +214,13 @@
     Deque<PendingPreload> m_pendingPreloads;
 
     Timer<ResourceFetcher> m_garbageCollectDocumentResourcesTimer;
+    Timer<ResourceFetcher> m_resourceTimingReportTimer;
 
     typedef HashMap<Resource*, RefPtr<ResourceTimingInfo> > ResourceTimingInfoMap;
     ResourceTimingInfoMap m_resourceTimingInfoMap;
 
+    HashMap<RefPtr<ResourceTimingInfo>, bool> m_scheduledResourceTimingReports;
+
     OwnPtr<ResourceLoaderSet> m_loaders;
     OwnPtr<ResourceLoaderSet> m_multipartLoaders;