/* static */ void EffectCompositor::ComposeAnimationRule(dom::Element* aElement, nsCSSPseudoElements::Type aPseudoType, CascadeLevel aCascadeLevel, bool& aStyleChanging) { EffectSet* effects = EffectSet::GetEffectSet(aElement, aPseudoType); if (!effects) { return; } // The caller is responsible for calling MaybeUpdateCascadeResults first. MOZ_ASSERT(!effects->CascadeNeedsUpdate(), "Animation cascade out of date when composing animation rule"); // Get a list of effects for the current level sorted by composite order. nsTArray<KeyframeEffectReadOnly*> sortedEffectList; for (KeyframeEffectReadOnly* effect : *effects) { MOZ_ASSERT(effect->GetAnimation()); if (effect->GetAnimation()->CascadeLevel() == aCascadeLevel) { sortedEffectList.AppendElement(effect); } } sortedEffectList.Sort(EffectCompositeOrderComparator()); RefPtr<AnimValuesStyleRule>& animationRule = effects->AnimationRule(aCascadeLevel); animationRule = nullptr; // We'll set aStyleChanging to true below if necessary. aStyleChanging = false; // If multiple animations specify behavior for the same property the // animation with the *highest* composite order wins. // As a result, we iterate from last animation to first and, if a // property has already been set, we don't change it. nsCSSPropertySet properties; for (KeyframeEffectReadOnly* effect : Reversed(sortedEffectList)) { effect->GetAnimation()->ComposeStyle(animationRule, properties, aStyleChanging); } }
void Matrix::Reverse() { *this = Reversed(); }
void ContentBlockingLog::ReportLog() { MOZ_ASSERT(NS_IsMainThread()); if (!IsReportingEnabled()) { return; } LOG("ContentBlockingLog::ReportLog [this=%p]", this); const bool testMode = StaticPrefs::telemetry_origin_telemetry_test_mode_enabled(); OriginMetricID metricId = testMode ? OriginMetricID::ContentBlocking_Blocked_TestOnly : OriginMetricID::ContentBlocking_Blocked; ReportOriginSingleHash(metricId, kDummyOriginHash); nsTArray<HashNumber> lookupTable; for (const auto& originEntry : mLog) { if (!originEntry.mData) { continue; } for (const auto& logEntry : Reversed(originEntry.mData->mLogs)) { if (logEntry.mType != nsIWebProgressListener::STATE_COOKIES_BLOCKED_TRACKER || logEntry.mTrackingFullHashes.IsEmpty()) { continue; } const bool isBlocked = logEntry.mBlocked; Maybe<StorageAccessGrantedReason> reason = logEntry.mReason; metricId = testMode ? OriginMetricID::ContentBlocking_Blocked_TestOnly : OriginMetricID::ContentBlocking_Blocked; if (!isBlocked) { MOZ_ASSERT(reason.isSome()); switch (reason.value()) { case StorageAccessGrantedReason::eStorageAccessAPI: metricId = testMode ? OriginMetricID:: ContentBlocking_StorageAccessAPIExempt_TestOnly : OriginMetricID::ContentBlocking_StorageAccessAPIExempt; break; case StorageAccessGrantedReason::eOpenerAfterUserInteraction: metricId = testMode ? OriginMetricID:: ContentBlocking_OpenerAfterUserInteractionExempt_TestOnly : OriginMetricID:: ContentBlocking_OpenerAfterUserInteractionExempt; break; case StorageAccessGrantedReason::eOpener: metricId = testMode ? OriginMetricID::ContentBlocking_OpenerExempt_TestOnly : OriginMetricID::ContentBlocking_OpenerExempt; break; default: MOZ_ASSERT_UNREACHABLE("Unknown StorageAccessGrantedReason"); } } for (const auto& hash : logEntry.mTrackingFullHashes) { HashNumber key = AddToHash(HashString(hash.get(), hash.Length()), static_cast<uint32_t>(metricId)); if (lookupTable.Contains(key)) { continue; } lookupTable.AppendElement(key); ReportOriginSingleHash(metricId, hash); } break; } } }
/* static */ void EffectCompositor::UpdateCascadeResults(EffectSet& aEffectSet, Element* aElement, nsCSSPseudoElements::Type aPseudoType, nsStyleContext* aStyleContext) { MOZ_ASSERT(EffectSet::GetEffectSet(aElement, aPseudoType) == &aEffectSet, "Effect set should correspond to the specified (pseudo-)element"); if (aEffectSet.IsEmpty()) { aEffectSet.MarkCascadeUpdated(); return; } // Get a list of effects sorted by composite order. nsTArray<KeyframeEffectReadOnly*> sortedEffectList; for (KeyframeEffectReadOnly* effect : aEffectSet) { sortedEffectList.AppendElement(effect); } sortedEffectList.Sort(EffectCompositeOrderComparator()); // Get properties that override the *animations* level of the cascade. // // We only do this for properties that we can animate on the compositor // since we will apply other properties on the main thread where the usual // cascade applies. nsCSSPropertySet overriddenProperties; if (aStyleContext) { GetOverriddenProperties(aStyleContext, aEffectSet, overriddenProperties); } bool changed = false; nsCSSPropertySet animatedProperties; // Iterate from highest to lowest composite order. for (KeyframeEffectReadOnly* effect : Reversed(sortedEffectList)) { MOZ_ASSERT(effect->GetAnimation(), "Effects on a target element should have an Animation"); bool inEffect = effect->IsInEffect(); for (AnimationProperty& prop : effect->Properties()) { bool winsInCascade = !animatedProperties.HasProperty(prop.mProperty) && inEffect; // If this property wins in the cascade, add it to the set of animated // properties. We need to do this even if the property is overridden // (in which case we set winsInCascade to false below) since we don't // want to fire transitions on these properties. if (winsInCascade) { animatedProperties.AddProperty(prop.mProperty); } // For effects that will be applied to the animations level of the // cascade, we need to check that the property isn't being set by // something with higher priority in the cascade. // // We only do this, however, for properties that can be animated on // the compositor. For properties animated on the main thread the usual // cascade ensures these animations will be correctly overridden. if (winsInCascade && effect->GetAnimation()->CascadeLevel() == CascadeLevel::Animations && overriddenProperties.HasProperty(prop.mProperty)) { winsInCascade = false; } if (winsInCascade != prop.mWinsInCascade) { changed = true; } prop.mWinsInCascade = winsInCascade; } } aEffectSet.MarkCascadeUpdated(); // If there is any change in the cascade result, update animations on // layers with the winning animations. nsPresContext* presContext = GetPresContext(aElement); if (changed && presContext) { // We currently unconditionally update both animations and transitions // even if we could, for example, get away with only updating animations. // This is a temporary measure until we unify all animation style updating // under EffectCompositor. AnimationCollection* animations = presContext->AnimationManager()->GetAnimationCollection(aElement, aPseudoType, false); /* don't create */ if (animations) { animations->RequestRestyle(AnimationCollection::RestyleType::Layer); } AnimationCollection* transitions = presContext->TransitionManager()->GetAnimationCollection(aElement, aPseudoType, false); /* don't create */ if (transitions) { transitions->RequestRestyle(AnimationCollection::RestyleType::Layer); } } }