Factor pending CSS resources into a struct
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 Jun 2016 23:01:42 +0000 (23:01 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 Jun 2016 23:01:42 +0000 (23:01 +0000)
https://bugs.webkit.org/show_bug.cgi?id=159268

Reviewed by Andreas Kling.

To fix resource loading related re-entrancy issues in StyleResolver we should move the triggering of
resource loads outside the style resolver. The first step for that is to capture pending resources to a struct.

* CMakeLists.txt:
* WebCore.xcodeproj/project.pbxproj:
* css/CSSCursorImageValue.cpp:
(WebCore::CSSCursorImageValue::cachedImage):
(WebCore::CSSCursorImageValue::cachedOrPendingImage):
* css/CSSCursorImageValue.h:
* css/CSSGradientValue.cpp:
(WebCore::GradientStop::GradientStop):
(WebCore::CSSGradientValue::gradientWithStylesResolved):
* css/CSSGradientValue.h:
(WebCore::CSSGradientValue::loadSubimages):
(WebCore::CSSGradientValue::CSSGradientValue):
* css/CSSImageSetValue.cpp:
(WebCore::CSSImageSetValue::cachedImageSet):
(WebCore::CSSImageSetValue::cachedOrPendingImageSet):
* css/CSSImageSetValue.h:
* css/StyleResolver.cpp:
(WebCore::StyleResolver::State::clear):
(WebCore::StyleResolver::State::setParentStyle):
(WebCore::StyleResolver::State::ensurePendingResources):
(WebCore::isAtShadowBoundary):
(WebCore::StyleResolver::cachedOrPendingFromValue):
(WebCore::StyleResolver::generatedOrPendingFromValue):
(WebCore::StyleResolver::setOrPendingFromValue):
(WebCore::StyleResolver::cursorOrPendingFromValue):
(WebCore::filterOperationForType):
(WebCore::StyleResolver::createFilterOperations):
(WebCore::StyleResolver::loadPendingResources):
(WebCore::StyleResolver::MatchedProperties::MatchedProperties):
(WebCore::StyleResolver::loadPendingSVGDocuments): Deleted.
(WebCore::StyleResolver::loadPendingImage): Deleted.
(WebCore::StyleResolver::loadPendingShapeImage): Deleted.
(WebCore::StyleResolver::loadPendingImages): Deleted.
* css/StyleResolver.h:
(WebCore::StyleResolver::rootElementStyle):
(WebCore::StyleResolver::element):
(WebCore::StyleResolver::document):
(WebCore::StyleResolver::documentSettings):
(WebCore::StyleResolver::State::setApplyPropertyToVisitedLinkStyle):
(WebCore::StyleResolver::State::applyPropertyToRegularStyle):
(WebCore::StyleResolver::State::applyPropertyToVisitedLinkStyle):
(WebCore::StyleResolver::State::setFontDirty):
(WebCore::StyleResolver::State::fontDirty):
(WebCore::StyleResolver::State::useSVGZoomRules):
(WebCore::StyleResolver::State::takePendingResources):
(WebCore::StyleResolver::State::cssToLengthConversionData):
(WebCore::StyleResolver::State::cascadeLevel):
(WebCore::StyleResolver::State::setCascadeLevel):
(WebCore::StyleResolver::state):
(WebCore::StyleResolver::State::pendingImageProperties): Deleted.
(WebCore::StyleResolver::State::filtersWithPendingSVGDocuments): Deleted.
* style/StylePendingResources.cpp: Added.
(WebCore::Style::loadPendingImage):
(WebCore::Style::loadPendingImages):
(WebCore::Style::loadPendingSVGFilters):
(WebCore::Style::loadPendingResources):

    Move the functions for triggering the resource loads from StyleResolver.

* style/StylePendingResources.h: Added.

    Add struct for pending resources.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@202656 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSCursorImageValue.cpp
Source/WebCore/css/CSSCursorImageValue.h
Source/WebCore/css/CSSGradientValue.cpp
Source/WebCore/css/CSSGradientValue.h
Source/WebCore/css/CSSImageSetValue.cpp
Source/WebCore/css/CSSImageSetValue.h
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/css/StyleResolver.h
Source/WebCore/style/StylePendingResources.cpp [new file with mode: 0644]
Source/WebCore/style/StylePendingResources.h [new file with mode: 0644]

index 2f778f2..95eb9c8 100644 (file)
@@ -2649,6 +2649,7 @@ set(WebCore_SOURCES
     style/RenderTreeUpdater.cpp
     style/StyleChange.cpp
     style/StyleFontSizeFunctions.cpp
+    style/StylePendingResources.cpp
     style/StyleRelations.cpp
     style/StyleResolveForDocument.cpp
     style/StyleSharingResolver.cpp
index 0bea3ad..660dfa2 100644 (file)
@@ -1,3 +1,76 @@
+2016-06-29  Antti Koivisto  <antti@apple.com>
+
+        Factor pending CSS resources into a struct
+        https://bugs.webkit.org/show_bug.cgi?id=159268
+
+        Reviewed by Andreas Kling.
+
+        To fix resource loading related re-entrancy issues in StyleResolver we should move the triggering of
+        resource loads outside the style resolver. The first step for that is to capture pending resources to a struct.
+
+        * CMakeLists.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/CSSCursorImageValue.cpp:
+        (WebCore::CSSCursorImageValue::cachedImage):
+        (WebCore::CSSCursorImageValue::cachedOrPendingImage):
+        * css/CSSCursorImageValue.h:
+        * css/CSSGradientValue.cpp:
+        (WebCore::GradientStop::GradientStop):
+        (WebCore::CSSGradientValue::gradientWithStylesResolved):
+        * css/CSSGradientValue.h:
+        (WebCore::CSSGradientValue::loadSubimages):
+        (WebCore::CSSGradientValue::CSSGradientValue):
+        * css/CSSImageSetValue.cpp:
+        (WebCore::CSSImageSetValue::cachedImageSet):
+        (WebCore::CSSImageSetValue::cachedOrPendingImageSet):
+        * css/CSSImageSetValue.h:
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::State::clear):
+        (WebCore::StyleResolver::State::setParentStyle):
+        (WebCore::StyleResolver::State::ensurePendingResources):
+        (WebCore::isAtShadowBoundary):
+        (WebCore::StyleResolver::cachedOrPendingFromValue):
+        (WebCore::StyleResolver::generatedOrPendingFromValue):
+        (WebCore::StyleResolver::setOrPendingFromValue):
+        (WebCore::StyleResolver::cursorOrPendingFromValue):
+        (WebCore::filterOperationForType):
+        (WebCore::StyleResolver::createFilterOperations):
+        (WebCore::StyleResolver::loadPendingResources):
+        (WebCore::StyleResolver::MatchedProperties::MatchedProperties):
+        (WebCore::StyleResolver::loadPendingSVGDocuments): Deleted.
+        (WebCore::StyleResolver::loadPendingImage): Deleted.
+        (WebCore::StyleResolver::loadPendingShapeImage): Deleted.
+        (WebCore::StyleResolver::loadPendingImages): Deleted.
+        * css/StyleResolver.h:
+        (WebCore::StyleResolver::rootElementStyle):
+        (WebCore::StyleResolver::element):
+        (WebCore::StyleResolver::document):
+        (WebCore::StyleResolver::documentSettings):
+        (WebCore::StyleResolver::State::setApplyPropertyToVisitedLinkStyle):
+        (WebCore::StyleResolver::State::applyPropertyToRegularStyle):
+        (WebCore::StyleResolver::State::applyPropertyToVisitedLinkStyle):
+        (WebCore::StyleResolver::State::setFontDirty):
+        (WebCore::StyleResolver::State::fontDirty):
+        (WebCore::StyleResolver::State::useSVGZoomRules):
+        (WebCore::StyleResolver::State::takePendingResources):
+        (WebCore::StyleResolver::State::cssToLengthConversionData):
+        (WebCore::StyleResolver::State::cascadeLevel):
+        (WebCore::StyleResolver::State::setCascadeLevel):
+        (WebCore::StyleResolver::state):
+        (WebCore::StyleResolver::State::pendingImageProperties): Deleted.
+        (WebCore::StyleResolver::State::filtersWithPendingSVGDocuments): Deleted.
+        * style/StylePendingResources.cpp: Added.
+        (WebCore::Style::loadPendingImage):
+        (WebCore::Style::loadPendingImages):
+        (WebCore::Style::loadPendingSVGFilters):
+        (WebCore::Style::loadPendingResources):
+
+            Move the functions for triggering the resource loads from StyleResolver.
+
+        * style/StylePendingResources.h: Added.
+
+            Add struct for pending resources.
+
 2016-06-29  Anders Carlsson  <andersca@apple.com>
 
         Add "type" and "paymentPass" properties in PaymentMethod
index 685d433..d523c2f 100644 (file)
                E4D58EBB17B8F12800CBDCA8 /* ElementTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D58EBA17B8F12800CBDCA8 /* ElementTraversal.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E4D988B417BFD1F60084FB88 /* TextNodeTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = E4D988B317BFD1F60084FB88 /* TextNodeTraversal.h */; };
                E4D988B617BFEB210084FB88 /* TextNodeTraversal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4D988B517BFEB210084FB88 /* TextNodeTraversal.cpp */; };
+               E4DACE6A1D12E10B0075980F /* StylePendingResources.h in Headers */ = {isa = PBXBuildFile; fileRef = E4DACE691D12E10B0075980F /* StylePendingResources.h */; };
+               E4DACE6C1D12E1160075980F /* StylePendingResources.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4DACE6B1D12E1160075980F /* StylePendingResources.cpp */; };
                E4DEAA1717A93DC3000E0430 /* StyleTreeResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4DEAA1517A93DC3000E0430 /* StyleTreeResolver.cpp */; };
                E4DEAA1817A93DC3000E0430 /* StyleTreeResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = E4DEAA1617A93DC3000E0430 /* StyleTreeResolver.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E4E39AFB1330EFA8003AB274 /* LegacyTileLayerPool.h in Headers */ = {isa = PBXBuildFile; fileRef = E4E39AFA1330EFA8003AB274 /* LegacyTileLayerPool.h */; };
                E4D58EBA17B8F12800CBDCA8 /* ElementTraversal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementTraversal.h; sourceTree = "<group>"; };
                E4D988B317BFD1F60084FB88 /* TextNodeTraversal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextNodeTraversal.h; sourceTree = "<group>"; };
                E4D988B517BFEB210084FB88 /* TextNodeTraversal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextNodeTraversal.cpp; sourceTree = "<group>"; };
+               E4DACE691D12E10B0075980F /* StylePendingResources.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StylePendingResources.h; sourceTree = "<group>"; };
+               E4DACE6B1D12E1160075980F /* StylePendingResources.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StylePendingResources.cpp; sourceTree = "<group>"; };
                E4DEAA1517A93DC3000E0430 /* StyleTreeResolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleTreeResolver.cpp; sourceTree = "<group>"; };
                E4DEAA1617A93DC3000E0430 /* StyleTreeResolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleTreeResolver.h; sourceTree = "<group>"; };
                E4E39AFA1330EFA8003AB274 /* LegacyTileLayerPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LegacyTileLayerPool.h; sourceTree = "<group>"; };
                                E401E0A31C3C0B8300F34D10 /* StyleChange.h */,
                                E4D58EB617B4ED8900CBDCA8 /* StyleFontSizeFunctions.cpp */,
                                E4D58EB717B4ED8900CBDCA8 /* StyleFontSizeFunctions.h */,
+                               E4DACE6B1D12E1160075980F /* StylePendingResources.cpp */,
+                               E4DACE691D12E10B0075980F /* StylePendingResources.h */,
                                E461802E1C8DD4D20026C02C /* StyleRelations.cpp */,
                                E461802C1C8DD2900026C02C /* StyleRelations.h */,
                                E4D58EB217B4DBDC00CBDCA8 /* StyleResolveForDocument.cpp */,
                                E1C416120F6562FD0092D2FB /* CrossOriginAccessControl.h in Headers */,
                                41ABE67B1D0580DB006D862D /* CrossOriginPreflightChecker.h in Headers */,
                                E1C415DA0F655D6F0092D2FB /* CrossOriginPreflightResultCache.h in Headers */,
+                               E4DACE6A1D12E10B0075980F /* StylePendingResources.h in Headers */,
                                E169803D1133542D00894115 /* CRuntimeObject.h in Headers */,
                                975CA28B130365F800E99AD9 /* Crypto.h in Headers */,
                                E172AF6E180F24C600FBADB9 /* CryptoAlgorithm.h in Headers */,
                                E1284BB210449FFA00EAEB52 /* JSPageTransitionEvent.cpp in Sources */,
                                FDA15EB112B03EE1003A583A /* JSPannerNode.cpp in Sources */,
                                FD8AA63E169514A700D2EA68 /* JSPannerNodeCustom.cpp in Sources */,
+                               E4DACE6C1D12E1160075980F /* StylePendingResources.cpp in Sources */,
                                E51A81DF17298D7700BFCA61 /* JSPerformance.cpp in Sources */,
                                CB38FD511CCF938900592A3F /* JSPerformanceEntry.cpp in Sources */,
                                CB38FD571CD21E2A00592A3F /* JSPerformanceEntryCustom.cpp in Sources */,
index ec6760a..bca7cb3 100644 (file)
@@ -150,7 +150,7 @@ StyleImage* CSSCursorImageValue::cachedImage(CachedResourceLoader& loader, const
     return nullptr;
 }
 
-StyleImage* CSSCursorImageValue::cachedOrPendingImage(Document& document)
+StyleImage* CSSCursorImageValue::cachedOrPendingImage(const Document& document)
 {
 #if ENABLE(CSS_IMAGE_SET)
     // Need to delegate completely so that changes in device scale factor can be handled appropriately.
index 36a30be..1e3b5bd 100644 (file)
@@ -54,7 +54,7 @@ public:
 
     SVGCursorElement* updateCursorElement(const Document&);
     StyleImage* cachedImage(CachedResourceLoader&, const ResourceLoaderOptions&);
-    StyleImage* cachedOrPendingImage(Document&);
+    StyleImage* cachedOrPendingImage(const Document&);
 
     void removeReferencedElement(SVGElement*);
 
index 568857e..292f464 100644 (file)
@@ -104,7 +104,7 @@ struct GradientStop {
     { }
 };
 
-RefPtr<CSSGradientValue> CSSGradientValue::gradientWithStylesResolved(StyleResolver* styleResolver)
+RefPtr<CSSGradientValue> CSSGradientValue::gradientWithStylesResolved(const StyleResolver* styleResolver)
 {
     bool derived = false;
     for (auto& stop : m_stops) {
index b39a44c..5630027 100644 (file)
@@ -85,7 +85,7 @@ public:
     bool knownToBeOpaque(const RenderElement*) const;
 
     void loadSubimages(CachedResourceLoader&, const ResourceLoaderOptions&) { }
-    RefPtr<CSSGradientValue> gradientWithStylesResolved(StyleResolver*);
+    RefPtr<CSSGradientValue> gradientWithStylesResolved(const StyleResolver*);
 
 protected:
     CSSGradientValue(ClassType classType, CSSGradientRepeat repeat, CSSGradientType gradientType)
index 849d80f..c244d7b 100644 (file)
@@ -130,7 +130,7 @@ StyleCachedImageSet* CSSImageSetValue::cachedImageSet(CachedResourceLoader& load
     return is<StyleCachedImageSet>(m_imageSet.get()) ? downcast<StyleCachedImageSet>(m_imageSet.get()) : nullptr;
 }
 
-StyleImage* CSSImageSetValue::cachedOrPendingImageSet(Document& document)
+StyleImage* CSSImageSetValue::cachedOrPendingImageSet(const Document& document)
 {
     if (!m_imageSet)
         m_imageSet = StylePendingImage::create(this);
index 6d9f0a7..19f6cb2 100644 (file)
@@ -50,7 +50,7 @@ public:
     StyleCachedImageSet* cachedImageSet(CachedResourceLoader&, const ResourceLoaderOptions&);
 
     // Returns a StyleCachedImageSet if the best fit image has been cached already, otherwise a StylePendingImage.
-    StyleImage* cachedOrPendingImageSet(Document&);
+    StyleImage* cachedOrPendingImageSet(const Document&);
 
     String customCSSText() const;
 
index ab6df27..40535ef 100644 (file)
@@ -194,8 +194,7 @@ inline void StyleResolver::State::clear()
     m_parentStyle = nullptr;
     m_ownedParentStyle = nullptr;
     m_regionForStyling = nullptr;
-    m_pendingImageProperties.clear();
-    m_filtersWithPendingSVGDocuments.clear();
+    m_pendingResources = nullptr;
     m_cssToLengthConversionData = CSSToLengthConversionData();
 }
 
@@ -384,6 +383,13 @@ void StyleResolver::State::setParentStyle(std::unique_ptr<RenderStyle> parentSty
     m_parentStyle = m_ownedParentStyle.get();
 }
 
+Style::PendingResources& StyleResolver::State::ensurePendingResources()
+{
+    if (!m_pendingResources)
+        m_pendingResources = std::make_unique<Style::PendingResources>();
+    return *m_pendingResources;
+}
+
 static inline bool isAtShadowBoundary(const Element& element)
 {
     auto* parentNode = element.parentNode();
@@ -1725,7 +1731,7 @@ Ref<StyleImage> StyleResolver::cachedOrPendingFromValue(CSSPropertyID property,
 {
     Ref<StyleImage> image = value.cachedOrPendingImage();
     if (image->isPendingImage())
-        m_state.pendingImageProperties().set(property, &value);
+        m_state.ensurePendingResources().pendingImages.set(property, &value);
     return image;
 }
 
@@ -1737,7 +1743,7 @@ Ref<StyleImage> StyleResolver::generatedOrPendingFromValue(CSSPropertyID propert
     }
 
     if (value.isPending()) {
-        m_state.pendingImageProperties().set(property, &value);
+        m_state.ensurePendingResources().pendingImages.set(property, &value);
         return StylePendingImage::create(&value);
     }
     return StyleGeneratedImage::create(value);
@@ -1748,7 +1754,7 @@ RefPtr<StyleImage> StyleResolver::setOrPendingFromValue(CSSPropertyID property,
 {
     RefPtr<StyleImage> image = value.cachedOrPendingImageSet(document());
     if (image && image->isPendingImage())
-        m_state.pendingImageProperties().set(property, &value);
+        m_state.ensurePendingResources().pendingImages.set(property, &value);
     return image;
 }
 #endif
@@ -1757,7 +1763,7 @@ RefPtr<StyleImage> StyleResolver::cursorOrPendingFromValue(CSSPropertyID propert
 {
     RefPtr<StyleImage> image = value.cachedOrPendingImage(document());
     if (image && image->isPendingImage())
-        m_state.pendingImageProperties().set(property, &value);
+        m_state.ensurePendingResources().pendingImages.set(property, &value);
     return image;
 }
 
@@ -1960,28 +1966,6 @@ static FilterOperation::OperationType filterOperationForType(WebKitCSSFilterValu
     return FilterOperation::NONE;
 }
 
-void StyleResolver::loadPendingSVGDocuments()
-{
-    State& state = m_state;
-
-    // Crash reports indicate that we've seen calls to this function when our
-    // style is NULL. We don't know exactly why this happens. Our guess is
-    // reentering styleForElement().
-    ASSERT(state.style());
-    if (!state.style() || !state.style()->hasFilter() || state.filtersWithPendingSVGDocuments().isEmpty())
-        return;
-
-    ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
-    options.setContentSecurityPolicyImposition(m_state.element() && m_state.element()->isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);
-
-    CachedResourceLoader& cachedResourceLoader = state.document().cachedResourceLoader();
-    
-    for (auto& filterOperation : state.filtersWithPendingSVGDocuments())
-        filterOperation->getOrCreateCachedSVGDocumentReference()->load(cachedResourceLoader, options);
-
-    state.filtersWithPendingSVGDocuments().clear();
-}
-
 bool StyleResolver::createFilterOperations(const CSSValue& inValue, FilterOperations& outOperations)
 {
     State& state = m_state;
@@ -2018,7 +2002,7 @@ bool StyleResolver::createFilterOperations(const CSSValue& inValue, FilterOperat
 
             RefPtr<ReferenceFilterOperation> operation = ReferenceFilterOperation::create(cssUrl, url.fragmentIdentifier());
             if (SVGURIReference::isExternalURIReference(cssUrl, m_state.document()))
-                state.filtersWithPendingSVGDocuments().append(operation);
+                state.ensurePendingResources().pendingSVGFilters.append(operation);
 
             operations.operations().append(operation);
             continue;
@@ -2118,177 +2102,17 @@ bool StyleResolver::createFilterOperations(const CSSValue& inValue, FilterOperat
     return true;
 }
 
-RefPtr<StyleImage> StyleResolver::loadPendingImage(const StylePendingImage& pendingImage, const ResourceLoaderOptions& options)
-{
-    if (auto imageValue = pendingImage.cssImageValue())
-        return imageValue->cachedImage(m_state.document().cachedResourceLoader(), options);
-
-    if (auto imageGeneratorValue = pendingImage.cssImageGeneratorValue()) {
-        imageGeneratorValue->loadSubimages(m_state.document().cachedResourceLoader(), options);
-        return StyleGeneratedImage::create(*imageGeneratorValue);
-    }
-
-    if (auto cursorImageValue = pendingImage.cssCursorImageValue())
-        return cursorImageValue->cachedImage(m_state.document().cachedResourceLoader(), options);
-
-#if ENABLE(CSS_IMAGE_SET)
-    if (auto imageSetValue = pendingImage.cssImageSetValue())
-        return imageSetValue->cachedImageSet(m_state.document().cachedResourceLoader(), options);
-#endif
-
-    return nullptr;
-}
-
-RefPtr<StyleImage> StyleResolver::loadPendingImage(const StylePendingImage& pendingImage)
-{
-    ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
-    options.setContentSecurityPolicyImposition(m_state.element() && m_state.element()->isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);
-    return loadPendingImage(pendingImage, options);
-}
-
-#if ENABLE(CSS_SHAPES)
-void StyleResolver::loadPendingShapeImage(ShapeValue* shapeValue)
-{
-    if (!shapeValue)
-        return;
-
-    StyleImage* image = shapeValue->image();
-    if (!is<StylePendingImage>(image))
-        return;
-
-    auto& pendingImage = downcast<StylePendingImage>(*image);
-
-    ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
-    options.setRequestOriginPolicy(PotentiallyCrossOriginEnabled);
-    options.setAllowCredentials(DoNotAllowStoredCredentials);
-    options.setContentSecurityPolicyImposition(m_state.element() && m_state.element()->isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);
-
-    shapeValue->setImage(loadPendingImage(pendingImage, options));
-}
-#endif
-
-void StyleResolver::loadPendingImages()
-{
-    RELEASE_ASSERT(!m_inLoadPendingImages);
-    TemporaryChange<bool> changeInLoadPendingImages(m_inLoadPendingImages, true);
-
-    if (m_state.pendingImageProperties().isEmpty())
-        return;
-
-    auto end = m_state.pendingImageProperties().end().keys();
-    for (auto it = m_state.pendingImageProperties().begin().keys(); it != end; ++it) {
-        CSSPropertyID currentProperty = *it;
-
-        switch (currentProperty) {
-        case CSSPropertyBackgroundImage: {
-            for (FillLayer* backgroundLayer = &m_state.style()->ensureBackgroundLayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) {
-                auto* styleImage = backgroundLayer->image();
-                if (is<StylePendingImage>(styleImage))
-                    backgroundLayer->setImage(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
-            }
-            break;
-        }
-        case CSSPropertyContent: {
-            for (ContentData* contentData = const_cast<ContentData*>(m_state.style()->contentData()); contentData; contentData = contentData->next()) {
-                if (is<ImageContentData>(*contentData)) {
-                    auto& styleImage = downcast<ImageContentData>(*contentData).image();
-                    if (is<StylePendingImage>(styleImage)) {
-                        if (auto loadedImage = loadPendingImage(downcast<StylePendingImage>(styleImage)))
-                            downcast<ImageContentData>(*contentData).setImage(WTFMove(loadedImage));
-                    }
-                }
-            }
-            break;
-        }
-        case CSSPropertyCursor: {
-            if (CursorList* cursorList = m_state.style()->cursors()) {
-                for (size_t i = 0; i < cursorList->size(); ++i) {
-                    CursorData& currentCursor = cursorList->at(i);
-                    auto* styleImage = currentCursor.image();
-                    if (is<StylePendingImage>(styleImage))
-                        currentCursor.setImage(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
-                }
-            }
-            break;
-        }
-        case CSSPropertyListStyleImage: {
-            auto* styleImage = m_state.style()->listStyleImage();
-            if (is<StylePendingImage>(styleImage))
-                m_state.style()->setListStyleImage(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
-            break;
-        }
-        case CSSPropertyBorderImageSource: {
-            auto* styleImage = m_state.style()->borderImageSource();
-            if (is<StylePendingImage>(styleImage))
-                m_state.style()->setBorderImageSource(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
-            break;
-        }
-        case CSSPropertyWebkitBoxReflect: {
-            if (StyleReflection* reflection = m_state.style()->boxReflect()) {
-                const NinePieceImage& maskImage = reflection->mask();
-                auto* styleImage = maskImage.image();
-                if (is<StylePendingImage>(styleImage)) {
-                    auto loadedImage = loadPendingImage(downcast<StylePendingImage>(*styleImage));
-                    reflection->setMask(NinePieceImage(WTFMove(loadedImage), maskImage.imageSlices(), maskImage.fill(), maskImage.borderSlices(), maskImage.outset(), maskImage.horizontalRule(), maskImage.verticalRule()));
-                }
-            }
-            break;
-        }
-        case CSSPropertyWebkitMaskBoxImageSource: {
-            auto* styleImage = m_state.style()->maskBoxImageSource();
-            if (is<StylePendingImage>(styleImage))
-                m_state.style()->setMaskBoxImageSource(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
-            break;
-        }
-        case CSSPropertyWebkitMaskImage: {
-            for (FillLayer* maskLayer = &m_state.style()->ensureMaskLayers(); maskLayer; maskLayer = maskLayer->next()) {
-                auto* styleImage = maskLayer->image();
-                if (is<StylePendingImage>(styleImage))
-                    maskLayer->setImage(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
-            }
-            break;
-        }
-#if ENABLE(CSS_SHAPES)
-        case CSSPropertyWebkitShapeOutside:
-            loadPendingShapeImage(m_state.style()->shapeOutside());
-            break;
-#endif
-        default:
-            ASSERT_NOT_REACHED();
-        }
-    }
-
-    m_state.pendingImageProperties().clear();
-}
-
-#ifndef NDEBUG
-static bool inLoadPendingResources = false;
-#endif
-
 void StyleResolver::loadPendingResources()
 {
-    // We've seen crashes in all three of the functions below. Some of them
-    // indicate that style() is NULL. This NULL check will cut down on total
-    // crashes, while the ASSERT will help us find the cause in debug builds.
     ASSERT(style());
     if (!style())
         return;
 
-#ifndef NDEBUG
-    // Re-entering this function will probably mean trouble. Catch it in debug builds.
-    ASSERT(!inLoadPendingResources);
-    inLoadPendingResources = true;
-#endif
-
-    // Start loading images referenced by this style.
-    loadPendingImages();
-
-    // Start loading the SVG Documents referenced by this style.
-    loadPendingSVGDocuments();
+    RELEASE_ASSERT(!m_inLoadPendingImages);
+    TemporaryChange<bool> changeInLoadPendingImages(m_inLoadPendingImages, true);
 
-#ifndef NDEBUG
-    inLoadPendingResources = false;
-#endif
+    if (auto pendingResources = state().takePendingResources())
+        Style::loadPendingResources(*pendingResources, document(), *style(), m_state.element());
 }
 
 inline StyleResolver::MatchedProperties::MatchedProperties()
index 63a6d8d..c81f29a 100644 (file)
@@ -30,6 +30,7 @@
 #include "RuleFeature.h"
 #include "RuleSet.h"
 #include "SelectorChecker.h"
+#include "StylePendingResources.h"
 #include <bitset>
 #include <memory>
 #include <wtf/HashMap.h>
@@ -148,6 +149,7 @@ public:
     const RenderStyle* rootElementStyle() const { return m_state.rootElementStyle(); }
     const Element* element() { return m_state.element(); }
     Document& document() { return m_document; }
+    const Document& document() const { return m_document; }
     Settings* documentSettings() { return m_document.settings(); }
 
     void appendAuthorStyleSheets(const Vector<RefPtr<CSSStyleSheet>>&);
@@ -381,9 +383,6 @@ public:
         void setApplyPropertyToVisitedLinkStyle(bool isApply) { m_applyPropertyToVisitedLinkStyle = isApply; }
         bool applyPropertyToRegularStyle() const { return m_applyPropertyToRegularStyle; }
         bool applyPropertyToVisitedLinkStyle() const { return m_applyPropertyToVisitedLinkStyle; }
-        PendingImagePropertyMap& pendingImageProperties() { return m_pendingImageProperties; }
-        
-        Vector<RefPtr<ReferenceFilterOperation>>& filtersWithPendingSVGDocuments() { return m_filtersWithPendingSVGDocuments; }
 
         void setFontDirty(bool isDirty) { m_fontDirty = isDirty; }
         bool fontDirty() const { return m_fontDirty; }
@@ -406,7 +405,10 @@ public:
 
         bool useSVGZoomRules() const { return m_element && m_element->isSVGElement(); }
 
-        CSSToLengthConversionData cssToLengthConversionData() const { return m_cssToLengthConversionData; }
+        Style::PendingResources& ensurePendingResources();
+        std::unique_ptr<Style::PendingResources> takePendingResources() { return WTFMove(m_pendingResources); }
+
+        const CSSToLengthConversionData& cssToLengthConversionData() const { return m_cssToLengthConversionData; }
 
         CascadeLevel cascadeLevel() const { return m_cascadeLevel; }
         void setCascadeLevel(CascadeLevel level) { m_cascadeLevel = level; }
@@ -442,8 +444,7 @@ public:
         FillLayer m_backgroundData { BackgroundFillLayer };
         Color m_backgroundColor;
 
-        PendingImagePropertyMap m_pendingImageProperties;
-        Vector<RefPtr<ReferenceFilterOperation>> m_filtersWithPendingSVGDocuments;
+        std::unique_ptr<Style::PendingResources> m_pendingResources;
         CSSToLengthConversionData m_cssToLengthConversionData;
         
         CascadeLevel m_cascadeLevel { UserAgentLevel };
@@ -454,6 +455,7 @@ public:
     };
 
     State& state() { return m_state; }
+    const State& state() const { return m_state; }
 
     RefPtr<StyleImage> styleImage(CSSPropertyID, CSSValue&);
     Ref<StyleImage> cachedOrPendingFromValue(CSSPropertyID, CSSImageValue&);
@@ -489,12 +491,7 @@ private:
 
     void applySVGProperty(CSSPropertyID, CSSValue*);
 
-    RefPtr<StyleImage> loadPendingImage(const StylePendingImage&, const ResourceLoaderOptions&);
-    RefPtr<StyleImage> loadPendingImage(const StylePendingImage&);
     void loadPendingImages();
-#if ENABLE(CSS_SHAPES)
-    void loadPendingShapeImage(ShapeValue*);
-#endif
 
     static unsigned computeMatchedPropertiesHash(const MatchedProperties*, unsigned size);
     struct MatchedPropertiesCacheItem {
diff --git a/Source/WebCore/style/StylePendingResources.cpp b/Source/WebCore/style/StylePendingResources.cpp
new file mode 100644 (file)
index 0000000..e19b375
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "StylePendingResources.h"
+
+#include "CachedResourceLoader.h"
+#include "CachedSVGDocumentReference.h"
+#include "ContentData.h"
+#include "CursorData.h"
+#include "CursorList.h"
+#include "Document.h"
+#include "RenderStyle.h"
+#include "SVGURIReference.h"
+#include "StyleCachedImage.h"
+#include "StyleCachedImageSet.h"
+#include "StyleGeneratedImage.h"
+#include "StylePendingImage.h"
+#include "TransformFunctions.h"
+
+namespace WebCore {
+namespace Style {
+
+enum class LoadPolicy { Normal, ShapeOutside };
+static RefPtr<StyleImage> loadPendingImage(Document& document, const StyleImage& image, const Element* element, LoadPolicy loadPolicy = LoadPolicy::Normal)
+{
+    auto& pendingImage = downcast<StylePendingImage>(image);
+    ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
+    options.setContentSecurityPolicyImposition(element && element->isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);
+
+    // FIXME: Why does shape-outside have different policy than other properties?
+    if (loadPolicy == LoadPolicy::ShapeOutside) {
+        options.setRequestOriginPolicy(PotentiallyCrossOriginEnabled);
+        options.setAllowCredentials(DoNotAllowStoredCredentials);
+    }
+
+    if (auto imageValue = pendingImage.cssImageValue())
+        return imageValue->cachedImage(document.cachedResourceLoader(), options);
+
+    if (auto imageGeneratorValue = pendingImage.cssImageGeneratorValue()) {
+        imageGeneratorValue->loadSubimages(document.cachedResourceLoader(), options);
+        return StyleGeneratedImage::create(*imageGeneratorValue);
+    }
+
+    if (auto cursorImageValue = pendingImage.cssCursorImageValue())
+        return cursorImageValue->cachedImage(document.cachedResourceLoader(), options);
+
+#if ENABLE(CSS_IMAGE_SET)
+    if (auto imageSetValue = pendingImage.cssImageSetValue())
+        return imageSetValue->cachedImageSet(document.cachedResourceLoader(), options);
+#endif
+
+    return nullptr;
+}
+
+static void loadPendingImages(const PendingResources& pendingResources, Document& document, RenderStyle& style, const Element* element)
+{
+    for (auto currentProperty : pendingResources.pendingImages.keys()) {
+        switch (currentProperty) {
+        case CSSPropertyBackgroundImage: {
+            for (FillLayer* backgroundLayer = &style.ensureBackgroundLayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) {
+                auto* styleImage = backgroundLayer->image();
+                if (is<StylePendingImage>(styleImage))
+                    backgroundLayer->setImage(loadPendingImage(document, *styleImage, element));
+            }
+            break;
+        }
+        case CSSPropertyContent: {
+            for (ContentData* contentData = const_cast<ContentData*>(style.contentData()); contentData; contentData = contentData->next()) {
+                if (is<ImageContentData>(*contentData)) {
+                    auto& styleImage = downcast<ImageContentData>(*contentData).image();
+                    if (is<StylePendingImage>(styleImage)) {
+                        if (auto loadedImage = loadPendingImage(document, styleImage, element))
+                            downcast<ImageContentData>(*contentData).setImage(WTFMove(loadedImage));
+                    }
+                }
+            }
+            break;
+        }
+        case CSSPropertyCursor: {
+            if (CursorList* cursorList = style.cursors()) {
+                for (size_t i = 0; i < cursorList->size(); ++i) {
+                    CursorData& currentCursor = cursorList->at(i);
+                    auto* styleImage = currentCursor.image();
+                    if (is<StylePendingImage>(styleImage))
+                        currentCursor.setImage(loadPendingImage(document, *styleImage, element));
+                }
+            }
+            break;
+        }
+        case CSSPropertyListStyleImage: {
+            auto* styleImage = style.listStyleImage();
+            if (is<StylePendingImage>(styleImage))
+                style.setListStyleImage(loadPendingImage(document, *styleImage, element));
+            break;
+        }
+        case CSSPropertyBorderImageSource: {
+            auto* styleImage = style.borderImageSource();
+            if (is<StylePendingImage>(styleImage))
+                style.setBorderImageSource(loadPendingImage(document, *styleImage, element));
+            break;
+        }
+        case CSSPropertyWebkitBoxReflect: {
+            if (StyleReflection* reflection = style.boxReflect()) {
+                const NinePieceImage& maskImage = reflection->mask();
+                auto* styleImage = maskImage.image();
+                if (is<StylePendingImage>(styleImage)) {
+                    auto loadedImage = loadPendingImage(document, *styleImage, element);
+                    reflection->setMask(NinePieceImage(WTFMove(loadedImage), maskImage.imageSlices(), maskImage.fill(), maskImage.borderSlices(), maskImage.outset(), maskImage.horizontalRule(), maskImage.verticalRule()));
+                }
+            }
+            break;
+        }
+        case CSSPropertyWebkitMaskBoxImageSource: {
+            auto* styleImage = style.maskBoxImageSource();
+            if (is<StylePendingImage>(styleImage))
+                style.setMaskBoxImageSource(loadPendingImage(document, *styleImage, element));
+            break;
+        }
+        case CSSPropertyWebkitMaskImage: {
+            for (FillLayer* maskLayer = &style.ensureMaskLayers(); maskLayer; maskLayer = maskLayer->next()) {
+                auto* styleImage = maskLayer->image();
+                if (is<StylePendingImage>(styleImage))
+                    maskLayer->setImage(loadPendingImage(document, *styleImage, element));
+            }
+            break;
+        }
+#if ENABLE(CSS_SHAPES)
+        case CSSPropertyWebkitShapeOutside: {
+            if (!style.shapeOutside())
+                return;
+
+            StyleImage* image = style.shapeOutside()->image();
+            if (is<StylePendingImage>(image))
+                style.shapeOutside()->setImage(loadPendingImage(document, *image, element, LoadPolicy::ShapeOutside));
+
+            break;
+        }
+#endif
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+}
+
+static void loadPendingSVGFilters(const PendingResources& pendingResources, Document& document, const Element* element)
+{
+    if (pendingResources.pendingSVGFilters.isEmpty())
+        return;
+
+    ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
+    options.setContentSecurityPolicyImposition(element && element->isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);
+
+    for (auto& filterOperation : pendingResources.pendingSVGFilters)
+        filterOperation->getOrCreateCachedSVGDocumentReference()->load(document.cachedResourceLoader(), options);
+}
+
+void loadPendingResources(const PendingResources& pendingResources, Document& document, RenderStyle& style, const Element* element)
+{
+    loadPendingImages(pendingResources, document, style, element);
+    loadPendingSVGFilters(pendingResources, document, element);
+}
+
+}
+}
diff --git a/Source/WebCore/style/StylePendingResources.h b/Source/WebCore/style/StylePendingResources.h
new file mode 100644 (file)
index 0000000..68bc1fd
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "CSSPropertyNames.h"
+#include "FilterOperations.h"
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+class CSSValue;
+class Document;
+class Element;
+class RenderStyle;
+
+namespace Style {
+
+struct PendingResources {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    HashMap<CSSPropertyID, RefPtr<CSSValue>> pendingImages;
+    Vector<RefPtr<ReferenceFilterOperation>> pendingSVGFilters;
+};
+
+void loadPendingResources(const PendingResources&, Document&, RenderStyle&, const Element*);
+
+}
+}