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;