Title: [184315] trunk
Revision
184315
Author
[email protected]
Date
2015-05-13 16:09:13 -0700 (Wed, 13 May 2015)

Log Message

Cached CSS image resources don't show up after reloading <http://nightly.webkit.org/start/>
https://bugs.webkit.org/show_bug.cgi?id=144952
Source/WebCore:

rdar://problem/13387307

Reviewed by Oliver Hunt.

This is a symptom of a general problem that we don't revalidate subresources of cached parsed stylesheets.

Fix by tightening the check we perform when choosing to used the cached sheet. If there are expired subresources
we reparse the sheet.

Test: http/tests/cache/stylesheet-sharing.html

* css/CSSCrossfadeValue.cpp:
(WebCore::CSSCrossfadeValue::traverseSubresources):
(WebCore::CSSCrossfadeValue::hasFailedOrCanceledSubresources): Deleted.

    Replace hasFailedOrCanceledSubresources with general purpose subresource traversal functions.

* css/CSSCrossfadeValue.h:
* css/CSSFilterImageValue.cpp:
(WebCore::CSSFilterImageValue::traverseSubresources):
(WebCore::CSSFilterImageValue::hasFailedOrCanceledSubresources): Deleted.
* css/CSSFilterImageValue.h:
* css/CSSFontFaceSrcValue.cpp:
(WebCore::CSSFontFaceSrcValue::traverseSubresources):
(WebCore::CSSFontFaceSrcValue::hasFailedOrCanceledSubresources): Deleted.
* css/CSSFontFaceSrcValue.h:
* css/CSSImageSetValue.cpp:
(WebCore::CSSImageSetValue::traverseSubresources):
(WebCore::CSSImageSetValue::hasFailedOrCanceledSubresources): Deleted.
* css/CSSImageSetValue.h:
* css/CSSImageValue.cpp:
(WebCore::CSSImageValue::traverseSubresources):
(WebCore::CSSImageValue::hasFailedOrCanceledSubresources): Deleted.
* css/CSSImageValue.h:
* css/CSSValue.cpp:
(WebCore::CSSValue::traverseSubresources):
(WebCore::CSSValue::hasFailedOrCanceledSubresources): Deleted.
* css/CSSValue.h:
* css/CSSValueList.cpp:
(WebCore::CSSValueList::traverseSubresources):
(WebCore::CSSValueList::hasFailedOrCanceledSubresources): Deleted.
* css/CSSValueList.h:
* css/StyleProperties.cpp:
(WebCore::StyleProperties::traverseSubresources):
(WebCore::StyleProperties::hasFailedOrCanceledSubresources): Deleted.
* css/StyleProperties.h:
* css/StyleSheetContents.cpp:
(WebCore::traverseSubresourcesInRules):
(WebCore::StyleSheetContents::traverseSubresources):
(WebCore::StyleSheetContents::subresourcesAllowReuse):

    Disallow reuse if there are expired subresources.

(WebCore::StyleSheetContents::isLoadingSubresources):

    Testing support.

(WebCore::childRulesHaveFailedOrCanceledSubresources): Deleted.
(WebCore::StyleSheetContents::hasFailedOrCanceledSubresources): Deleted.
* css/StyleSheetContents.h:
(WebCore::StyleSheetContents::loadCompleted):
* html/HTMLLinkElement.cpp:
(WebCore::HTMLLinkElement::setCSSStyleSheet):
* loader/cache/CachedCSSStyleSheet.cpp:
(WebCore::CachedCSSStyleSheet::restoreParsedStyleSheet):
* loader/cache/CachedCSSStyleSheet.h:
* loader/cache/CachedImage.cpp:
(WebCore::CachedImage::makeRevalidationDecision):
(WebCore::CachedImage::mustRevalidateDueToCacheHeaders): Deleted.

    Move the logging code out from this function (it requires frame access this function doesn't otherwise need)
    and refactor to return a decision enum.

* loader/cache/CachedImage.h:
* loader/cache/CachedResource.cpp:
(WebCore::CachedResource::makeRevalidationDecision):
(WebCore::logResourceRevalidationReason): Deleted.
(WebCore::CachedResource::mustRevalidateDueToCacheHeaders): Deleted.
* loader/cache/CachedResource.h:
(WebCore::CachedResource::loadFailedOrCanceled):
* loader/cache/CachedResourceLoader.cpp:
(WebCore::logRevalidation):
(WebCore::logResourceRevalidationDecision):
(WebCore::CachedResourceLoader::determineRevalidationPolicy):

    Move logging here.

* testing/Internals.cpp:
(WebCore::Internals::isSharingStyleSheetContents):
(WebCore::Internals::isStyleSheetLoadingSubresources):
* testing/Internals.h:
* testing/Internals.idl:

LayoutTests:

Reviewed by Oliver Hunt.

* http/tests/cache/resources/non-shareable.css: Added.
(#foo):
(#bar):
(#test1):
(#test2):
* http/tests/cache/resources/shareable.css: Added.
(#foo):
(#bar):
(#test1):
(#test2):
* http/tests/cache/resources/stylesheet-html.php: Added.
* http/tests/cache/stylesheet-sharing-expected.txt: Added.
* http/tests/cache/stylesheet-sharing.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (184314 => 184315)


--- trunk/LayoutTests/ChangeLog	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/LayoutTests/ChangeLog	2015-05-13 23:09:13 UTC (rev 184315)
@@ -1,3 +1,24 @@
+2015-05-13  Antti Koivisto  <[email protected]>
+
+        Cached CSS image resources don't show up after reloading <http://nightly.webkit.org/start/>
+        https://bugs.webkit.org/show_bug.cgi?id=144952
+
+        Reviewed by Oliver Hunt.
+
+        * http/tests/cache/resources/non-shareable.css: Added.
+        (#foo):
+        (#bar):
+        (#test1):
+        (#test2):
+        * http/tests/cache/resources/shareable.css: Added.
+        (#foo):
+        (#bar):
+        (#test1):
+        (#test2):
+        * http/tests/cache/resources/stylesheet-html.php: Added.
+        * http/tests/cache/stylesheet-sharing-expected.txt: Added.
+        * http/tests/cache/stylesheet-sharing.html: Added.
+
 2015-05-13  Ryosuke Niwa  <[email protected]>
 
         REGRESSION(r183770): Crash inside WebEditorClient::shouldApplyStyle when applying underline

Added: trunk/LayoutTests/http/tests/cache/resources/non-shareable.css (0 => 184315)


--- trunk/LayoutTests/http/tests/cache/resources/non-shareable.css	                        (rev 0)
+++ trunk/LayoutTests/http/tests/cache/resources/non-shareable.css	2015-05-13 23:09:13 UTC (rev 184315)
@@ -0,0 +1,4 @@
+#foo { color: red }
+#bar { color: blue }
+#test1 { background-image:url(/resources/square100.png) }
+#test2 { background-image:url(../disk-cache/resources/generate-response.cgi?Content-Type=image/png&Cache-Control=max-age=0) }

Added: trunk/LayoutTests/http/tests/cache/resources/shareable.css (0 => 184315)


--- trunk/LayoutTests/http/tests/cache/resources/shareable.css	                        (rev 0)
+++ trunk/LayoutTests/http/tests/cache/resources/shareable.css	2015-05-13 23:09:13 UTC (rev 184315)
@@ -0,0 +1,4 @@
+#foo { color: red }
+#bar { color: blue }
+#test1 { background-image:url(/resources/square100.png) }
+#test2 { background-image:url(../disk-cache/resources/generate-response.cgi?Content-Type=image/png&Cache-Control=max-age=100) }

Added: trunk/LayoutTests/http/tests/cache/resources/stylesheet-html.php (0 => 184315)


--- trunk/LayoutTests/http/tests/cache/resources/stylesheet-html.php	                        (rev 0)
+++ trunk/LayoutTests/http/tests/cache/resources/stylesheet-html.php	2015-05-13 23:09:13 UTC (rev 184315)
@@ -0,0 +1,5 @@
+<?php
+echo "<link rel=stylesheet href="" . $_GET['sheet'] . ">";
+?>
+<div id=test1></div>
+<div id=test2></div>

Added: trunk/LayoutTests/http/tests/cache/stylesheet-sharing-expected.txt (0 => 184315)


--- trunk/LayoutTests/http/tests/cache/stylesheet-sharing-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/cache/stylesheet-sharing-expected.txt	2015-05-13 23:09:13 UTC (rev 184315)
@@ -0,0 +1,8 @@
+shareable.css
+PASS styleSheetContentsShared is true
+non-shareable.css
+PASS styleSheetContentsShared is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+  

Added: trunk/LayoutTests/http/tests/cache/stylesheet-sharing.html (0 => 184315)


--- trunk/LayoutTests/http/tests/cache/stylesheet-sharing.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/cache/stylesheet-sharing.html	2015-05-13 23:09:13 UTC (rev 184315)
@@ -0,0 +1,50 @@
+<script src=""
+<body>
+<script>
+jsTestIsAsync = true;
+
+function waitForStylesheet(iframe, completionHandler)
+{
+    var link = iframe.contentDocument.getElementsByTagName('link')[0];
+    if (internals.isStyleSheetLoadingSubresources(link)) {
+        setTimeout(function () { waitForStylesheet(iframe, completionHandler) }, 10);
+        return;
+    }
+    completionHandler(link);
+}
+
+function load(src, completionHandler)
+{
+    var iframe = document.createElement("iframe");
+    iframe.src = "" + src;
+    iframe._onload_ = function () {
+        iframe.contentDocument.body.offsetWidth;
+        waitForStylesheet(iframe, completionHandler);
+    };
+    document.body.appendChild(iframe);
+}
+
+function testSharing(src, expected, completionHandler)
+{
+    load(src, function (linkA) {
+        load(src, function (linkB) {
+            styleSheetContentsShared = internals.isSharingStyleSheetContents(linkA, linkB);
+            debug(src);
+            if (expected)
+                shouldBeTrue("styleSheetContentsShared");
+            else
+                shouldBeFalse("styleSheetContentsShared");
+            completionHandler();
+        });
+    });
+}
+
+testSharing("shareable.css", true, function () {
+    testSharing("non-shareable.css", false, function () {
+        finishJSTest();
+    });
+});
+
+</script>
+
+<script src=""

Modified: trunk/Source/WebCore/ChangeLog (184314 => 184315)


--- trunk/Source/WebCore/ChangeLog	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/ChangeLog	2015-05-13 23:09:13 UTC (rev 184315)
@@ -1,3 +1,100 @@
+2015-05-13  Antti Koivisto  <[email protected]>
+
+        Cached CSS image resources don't show up after reloading <http://nightly.webkit.org/start/>
+        https://bugs.webkit.org/show_bug.cgi?id=144952
+        rdar://problem/13387307
+
+        Reviewed by Oliver Hunt.
+
+        This is a symptom of a general problem that we don't revalidate subresources of cached parsed stylesheets.
+
+        Fix by tightening the check we perform when choosing to used the cached sheet. If there are expired subresources
+        we reparse the sheet.
+
+        Test: http/tests/cache/stylesheet-sharing.html
+
+        * css/CSSCrossfadeValue.cpp:
+        (WebCore::CSSCrossfadeValue::traverseSubresources):
+        (WebCore::CSSCrossfadeValue::hasFailedOrCanceledSubresources): Deleted.
+
+            Replace hasFailedOrCanceledSubresources with general purpose subresource traversal functions.
+
+        * css/CSSCrossfadeValue.h:
+        * css/CSSFilterImageValue.cpp:
+        (WebCore::CSSFilterImageValue::traverseSubresources):
+        (WebCore::CSSFilterImageValue::hasFailedOrCanceledSubresources): Deleted.
+        * css/CSSFilterImageValue.h:
+        * css/CSSFontFaceSrcValue.cpp:
+        (WebCore::CSSFontFaceSrcValue::traverseSubresources):
+        (WebCore::CSSFontFaceSrcValue::hasFailedOrCanceledSubresources): Deleted.
+        * css/CSSFontFaceSrcValue.h:
+        * css/CSSImageSetValue.cpp:
+        (WebCore::CSSImageSetValue::traverseSubresources):
+        (WebCore::CSSImageSetValue::hasFailedOrCanceledSubresources): Deleted.
+        * css/CSSImageSetValue.h:
+        * css/CSSImageValue.cpp:
+        (WebCore::CSSImageValue::traverseSubresources):
+        (WebCore::CSSImageValue::hasFailedOrCanceledSubresources): Deleted.
+        * css/CSSImageValue.h:
+        * css/CSSValue.cpp:
+        (WebCore::CSSValue::traverseSubresources):
+        (WebCore::CSSValue::hasFailedOrCanceledSubresources): Deleted.
+        * css/CSSValue.h:
+        * css/CSSValueList.cpp:
+        (WebCore::CSSValueList::traverseSubresources):
+        (WebCore::CSSValueList::hasFailedOrCanceledSubresources): Deleted.
+        * css/CSSValueList.h:
+        * css/StyleProperties.cpp:
+        (WebCore::StyleProperties::traverseSubresources):
+        (WebCore::StyleProperties::hasFailedOrCanceledSubresources): Deleted.
+        * css/StyleProperties.h:
+        * css/StyleSheetContents.cpp:
+        (WebCore::traverseSubresourcesInRules):
+        (WebCore::StyleSheetContents::traverseSubresources):
+        (WebCore::StyleSheetContents::subresourcesAllowReuse):
+
+            Disallow reuse if there are expired subresources.
+
+        (WebCore::StyleSheetContents::isLoadingSubresources):
+
+            Testing support.
+
+        (WebCore::childRulesHaveFailedOrCanceledSubresources): Deleted.
+        (WebCore::StyleSheetContents::hasFailedOrCanceledSubresources): Deleted.
+        * css/StyleSheetContents.h:
+        (WebCore::StyleSheetContents::loadCompleted):
+        * html/HTMLLinkElement.cpp:
+        (WebCore::HTMLLinkElement::setCSSStyleSheet):
+        * loader/cache/CachedCSSStyleSheet.cpp:
+        (WebCore::CachedCSSStyleSheet::restoreParsedStyleSheet):
+        * loader/cache/CachedCSSStyleSheet.h:
+        * loader/cache/CachedImage.cpp:
+        (WebCore::CachedImage::makeRevalidationDecision):
+        (WebCore::CachedImage::mustRevalidateDueToCacheHeaders): Deleted.
+
+            Move the logging code out from this function (it requires frame access this function doesn't otherwise need)
+            and refactor to return a decision enum.
+
+        * loader/cache/CachedImage.h:
+        * loader/cache/CachedResource.cpp:
+        (WebCore::CachedResource::makeRevalidationDecision):
+        (WebCore::logResourceRevalidationReason): Deleted.
+        (WebCore::CachedResource::mustRevalidateDueToCacheHeaders): Deleted.
+        * loader/cache/CachedResource.h:
+        (WebCore::CachedResource::loadFailedOrCanceled):
+        * loader/cache/CachedResourceLoader.cpp:
+        (WebCore::logRevalidation):
+        (WebCore::logResourceRevalidationDecision):
+        (WebCore::CachedResourceLoader::determineRevalidationPolicy):
+
+            Move logging here.
+
+        * testing/Internals.cpp:
+        (WebCore::Internals::isSharingStyleSheetContents):
+        (WebCore::Internals::isStyleSheetLoadingSubresources):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
 2015-05-13  Ryuan Choi  <[email protected]>
 
         [CoordinatedGraphics] Remove scaleFactor from SurfaceUpdateInfo

Modified: trunk/Source/WebCore/css/CSSCrossfadeValue.cpp (184314 => 184315)


--- trunk/Source/WebCore/css/CSSCrossfadeValue.cpp	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/CSSCrossfadeValue.cpp	2015-05-13 23:09:13 UTC (rev 184315)
@@ -174,11 +174,11 @@
         m_ownerValue->crossfadeChanged(*rect);
 }
 
-bool CSSCrossfadeValue::hasFailedOrCanceledSubresources() const
+bool CSSCrossfadeValue::traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const
 {
-    if (m_cachedFromImage && m_cachedFromImage->loadFailedOrCanceled())
+    if (m_cachedFromImage && handler(*m_cachedFromImage))
         return true;
-    if (m_cachedToImage && m_cachedToImage->loadFailedOrCanceled())
+    if (m_cachedToImage && handler(*m_cachedToImage))
         return true;
     return false;
 }

Modified: trunk/Source/WebCore/css/CSSCrossfadeValue.h (184314 => 184315)


--- trunk/Source/WebCore/css/CSSCrossfadeValue.h	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/CSSCrossfadeValue.h	2015-05-13 23:09:13 UTC (rev 184315)
@@ -63,7 +63,7 @@
 
     void setPercentage(PassRefPtr<CSSPrimitiveValue> percentageValue) { m_percentageValue = percentageValue; }
 
-    bool hasFailedOrCanceledSubresources() const;
+    bool traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const;
 
     PassRefPtr<CSSCrossfadeValue> blend(const CSSCrossfadeValue&, double) const;
 

Modified: trunk/Source/WebCore/css/CSSFilterImageValue.cpp (184314 => 184315)


--- trunk/Source/WebCore/css/CSSFilterImageValue.cpp	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/CSSFilterImageValue.cpp	2015-05-13 23:09:13 UTC (rev 184315)
@@ -149,11 +149,11 @@
         m_ownerValue->filterImageChanged(*rect);
 }
 
-bool CSSFilterImageValue::hasFailedOrCanceledSubresources() const
+bool CSSFilterImageValue::traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const
 {
-    if (m_cachedImage && m_cachedImage->loadFailedOrCanceled())
-        return true;
-    return false;
+    if (!m_cachedImage)
+        return false;
+    return handler(*m_cachedImage);
 }
 
 bool CSSFilterImageValue::equals(const CSSFilterImageValue& other) const

Modified: trunk/Source/WebCore/css/CSSFilterImageValue.h (184314 => 184315)


--- trunk/Source/WebCore/css/CSSFilterImageValue.h	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/CSSFilterImageValue.h	2015-05-13 23:09:13 UTC (rev 184315)
@@ -64,7 +64,7 @@
 
     void loadSubimages(CachedResourceLoader&);
 
-    bool hasFailedOrCanceledSubresources() const;
+    bool traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const;
 
     bool equals(const CSSFilterImageValue&) const;
 

Modified: trunk/Source/WebCore/css/CSSFontFaceSrcValue.cpp (184314 => 184315)


--- trunk/Source/WebCore/css/CSSFontFaceSrcValue.cpp	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/CSSFontFaceSrcValue.cpp	2015-05-13 23:09:13 UTC (rev 184315)
@@ -91,11 +91,11 @@
         addSubresourceURL(urls, styleSheet->completeURL(m_resource));
 }
 
-bool CSSFontFaceSrcValue::hasFailedOrCanceledSubresources() const
+bool CSSFontFaceSrcValue::traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const
 {
     if (!m_cachedFont)
         return false;
-    return m_cachedFont->loadFailedOrCanceled();
+    return handler(*m_cachedFont);
 }
 
 CachedFont* CSSFontFaceSrcValue::cachedFont(Document* document, bool isSVG)

Modified: trunk/Source/WebCore/css/CSSFontFaceSrcValue.h (184314 => 184315)


--- trunk/Source/WebCore/css/CSSFontFaceSrcValue.h	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/CSSFontFaceSrcValue.h	2015-05-13 23:09:13 UTC (rev 184315)
@@ -68,7 +68,7 @@
 
     void addSubresourceStyleURLs(ListHashSet<URL>&, const StyleSheetContents*) const;
 
-    bool hasFailedOrCanceledSubresources() const;
+    bool traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const;
 
     CachedFont* cachedFont(Document*, bool isSVG);
 

Modified: trunk/Source/WebCore/css/CSSImageSetValue.cpp (184314 => 184315)


--- trunk/Source/WebCore/css/CSSImageSetValue.cpp	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/CSSImageSetValue.cpp	2015-05-13 23:09:13 UTC (rev 184315)
@@ -184,14 +184,13 @@
     return result.toString();
 }
 
-bool CSSImageSetValue::hasFailedOrCanceledSubresources() const
+bool CSSImageSetValue::traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const
 {
     if (!is<StyleCachedImageSet>(m_imageSet.get()))
         return false;
     CachedImage* cachedResource = downcast<StyleCachedImageSet>(*m_imageSet).cachedImage();
-    if (!cachedResource)
-        return true;
-    return cachedResource->loadFailedOrCanceled();
+    ASSERT(cachedResource);
+    return handler(*cachedResource);
 }
 
 CSSImageSetValue::CSSImageSetValue(const CSSImageSetValue& cloneFrom)

Modified: trunk/Source/WebCore/css/CSSImageSetValue.h (184314 => 184315)


--- trunk/Source/WebCore/css/CSSImageSetValue.h	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/CSSImageSetValue.h	2015-05-13 23:09:13 UTC (rev 184315)
@@ -62,7 +62,7 @@
         float scaleFactor;
     };
 
-    bool hasFailedOrCanceledSubresources() const;
+    bool traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const;
 
     PassRefPtr<CSSImageSetValue> cloneForCSSOM() const;
 

Modified: trunk/Source/WebCore/css/CSSImageValue.cpp (184314 => 184315)


--- trunk/Source/WebCore/css/CSSImageValue.cpp	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/CSSImageValue.cpp	2015-05-13 23:09:13 UTC (rev 184315)
@@ -99,14 +99,13 @@
     return cachedImage(loader, CachedResourceLoader::defaultCachedResourceOptions());
 }
 
-bool CSSImageValue::hasFailedOrCanceledSubresources() const
+bool CSSImageValue::traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const
 {
     if (!is<StyleCachedImage>(m_image.get()))
         return false;
     CachedResource* cachedResource = downcast<StyleCachedImage>(*m_image).cachedImage();
-    if (!cachedResource)
-        return true;
-    return cachedResource->loadFailedOrCanceled();
+    ASSERT(cachedResource);
+    return handler(*cachedResource);
 }
 
 bool CSSImageValue::equals(const CSSImageValue& other) const

Modified: trunk/Source/WebCore/css/CSSImageValue.h (184314 => 184315)


--- trunk/Source/WebCore/css/CSSImageValue.h	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/CSSImageValue.h	2015-05-13 23:09:13 UTC (rev 184315)
@@ -50,7 +50,7 @@
 
     PassRefPtr<CSSValue> cloneForCSSOM() const;
 
-    bool hasFailedOrCanceledSubresources() const;
+    bool traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const;
 
     bool equals(const CSSImageValue&) const;
 

Modified: trunk/Source/WebCore/css/CSSValue.cpp (184314 => 184315)


--- trunk/Source/WebCore/css/CSSValue.cpp	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/CSSValue.cpp	2015-05-13 23:09:13 UTC (rev 184315)
@@ -125,24 +125,24 @@
         downcast<CSSReflectValue>(*this).addSubresourceStyleURLs(urls, styleSheet);
 }
 
-bool CSSValue::hasFailedOrCanceledSubresources() const
+bool CSSValue::traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const
 {
     // This should get called for internal instances only.
     ASSERT(!isCSSOMSafe());
 
     if (is<CSSValueList>(*this))
-        return downcast<CSSValueList>(*this).hasFailedOrCanceledSubresources();
+        return downcast<CSSValueList>(*this).traverseSubresources(handler);
     if (is<CSSFontFaceSrcValue>(*this))
-        return downcast<CSSFontFaceSrcValue>(*this).hasFailedOrCanceledSubresources();
+        return downcast<CSSFontFaceSrcValue>(*this).traverseSubresources(handler);
     if (is<CSSImageValue>(*this))
-        return downcast<CSSImageValue>(*this).hasFailedOrCanceledSubresources();
+        return downcast<CSSImageValue>(*this).traverseSubresources(handler);
     if (is<CSSCrossfadeValue>(*this))
-        return downcast<CSSCrossfadeValue>(*this).hasFailedOrCanceledSubresources();
+        return downcast<CSSCrossfadeValue>(*this).traverseSubresources(handler);
     if (is<CSSFilterImageValue>(*this))
-        return downcast<CSSFilterImageValue>(*this).hasFailedOrCanceledSubresources();
+        return downcast<CSSFilterImageValue>(*this).traverseSubresources(handler);
 #if ENABLE(CSS_IMAGE_SET)
     if (is<CSSImageSetValue>(*this))
-        return downcast<CSSImageSetValue>(*this).hasFailedOrCanceledSubresources();
+        return downcast<CSSImageSetValue>(*this).traverseSubresources(handler);
 #endif
     return false;
 }

Modified: trunk/Source/WebCore/css/CSSValue.h (184314 => 184315)


--- trunk/Source/WebCore/css/CSSValue.h	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/CSSValue.h	2015-05-13 23:09:13 UTC (rev 184315)
@@ -30,6 +30,7 @@
 
 namespace WebCore {
 
+class CachedResource;
 class StyleSheetContents;
     
 // FIXME: The current CSSValue and subclasses should be turned into internal types (StyleValue).
@@ -122,7 +123,7 @@
 
     void addSubresourceStyleURLs(ListHashSet<URL>&, const StyleSheetContents*) const;
 
-    bool hasFailedOrCanceledSubresources() const;
+    bool traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const;
 
     bool equals(const CSSValue&) const;
 

Modified: trunk/Source/WebCore/css/CSSValueList.cpp (184314 => 184315)


--- trunk/Source/WebCore/css/CSSValueList.cpp	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/CSSValueList.cpp	2015-05-13 23:09:13 UTC (rev 184315)
@@ -151,10 +151,10 @@
         m_values[i].get().addSubresourceStyleURLs(urls, styleSheet);
 }
 
-bool CSSValueList::hasFailedOrCanceledSubresources() const
+bool CSSValueList::traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const
 {
     for (unsigned i = 0; i < m_values.size(); ++i) {
-        if (m_values[i].get().hasFailedOrCanceledSubresources())
+        if (m_values[i].get().traverseSubresources(handler))
             return true;
     }
     return false;

Modified: trunk/Source/WebCore/css/CSSValueList.h (184314 => 184315)


--- trunk/Source/WebCore/css/CSSValueList.h	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/CSSValueList.h	2015-05-13 23:09:13 UTC (rev 184315)
@@ -74,7 +74,7 @@
 
     void addSubresourceStyleURLs(ListHashSet<URL>&, const StyleSheetContents*) const;
 
-    bool hasFailedOrCanceledSubresources() const;
+    bool traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const;
     
     PassRefPtr<CSSValueList> cloneForCSSOM() const;
 

Modified: trunk/Source/WebCore/css/StyleProperties.cpp (184314 => 184315)


--- trunk/Source/WebCore/css/StyleProperties.cpp	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/StyleProperties.cpp	2015-05-13 23:09:13 UTC (rev 184315)
@@ -1074,11 +1074,11 @@
         propertyAt(i).value()->addSubresourceStyleURLs(urls, contextStyleSheet);
 }
 
-bool StyleProperties::hasFailedOrCanceledSubresources() const
+bool StyleProperties::traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const
 {
     unsigned size = propertyCount();
     for (unsigned i = 0; i < size; ++i) {
-        if (propertyAt(i).value()->hasFailedOrCanceledSubresources())
+        if (propertyAt(i).value()->traverseSubresources(handler))
             return true;
     }
     return false;

Modified: trunk/Source/WebCore/css/StyleProperties.h (184314 => 184315)


--- trunk/Source/WebCore/css/StyleProperties.h	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/StyleProperties.h	2015-05-13 23:09:13 UTC (rev 184315)
@@ -37,6 +37,7 @@
 namespace WebCore {
 
 class CSSStyleDeclaration;
+class CachedResource;
 class ImmutableStyleProperties;
 class URL;
 class MutableStyleProperties;
@@ -107,7 +108,7 @@
     bool isMutable() const { return m_isMutable; }
     bool hasCSSOMWrapper() const;
 
-    bool hasFailedOrCanceledSubresources() const;
+    bool traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const;
 
     static unsigned averageSizeInBytes();
 

Modified: trunk/Source/WebCore/css/StyleSheetContents.cpp (184314 => 184315)


--- trunk/Source/WebCore/css/StyleSheetContents.cpp	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/StyleSheetContents.cpp	2015-05-13 23:09:13 UTC (rev 184315)
@@ -423,24 +423,24 @@
     }
 }
 
-static bool childRulesHaveFailedOrCanceledSubresources(const Vector<RefPtr<StyleRuleBase>>& rules)
+static bool traverseSubresourcesInRules(const Vector<RefPtr<StyleRuleBase>>& rules, const std::function<bool (const CachedResource&)>& handler)
 {
     for (auto& rule : rules) {
         switch (rule->type()) {
         case StyleRuleBase::Style:
-            if (downcast<StyleRule>(*rule).properties().hasFailedOrCanceledSubresources())
+            if (downcast<StyleRule>(*rule).properties().traverseSubresources(handler))
                 return true;
             break;
         case StyleRuleBase::FontFace:
-            if (downcast<StyleRuleFontFace>(*rule).properties().hasFailedOrCanceledSubresources())
+            if (downcast<StyleRuleFontFace>(*rule).properties().traverseSubresources(handler))
                 return true;
             break;
         case StyleRuleBase::Media:
-            if (childRulesHaveFailedOrCanceledSubresources(downcast<StyleRuleMedia>(*rule).childRules()))
+            if (traverseSubresourcesInRules(downcast<StyleRuleMedia>(*rule).childRules(), handler))
                 return true;
             break;
         case StyleRuleBase::Region:
-            if (childRulesHaveFailedOrCanceledSubresources(downcast<StyleRuleRegion>(*rule).childRules()))
+            if (traverseSubresourcesInRules(downcast<StyleRuleRegion>(*rule).childRules(), handler))
                 return true;
             break;
         case StyleRuleBase::Import:
@@ -463,12 +463,37 @@
     return false;
 }
 
-bool StyleSheetContents::hasFailedOrCanceledSubresources() const
+bool StyleSheetContents::traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const
 {
-    ASSERT(isCacheable());
-    return childRulesHaveFailedOrCanceledSubresources(m_childRules);
+    for (auto& importRule : m_importRules) {
+        if (!importRule->styleSheet())
+            continue;
+        if (traverseSubresourcesInRules(importRule->styleSheet()->m_childRules, handler))
+            return true;
+    }
+    return traverseSubresourcesInRules(m_childRules, handler);
 }
 
+bool StyleSheetContents::subresourcesAllowReuse(CachePolicy cachePolicy) const
+{
+    bool hasFailedOrExpiredResources = traverseSubresources([cachePolicy](const CachedResource& resource) {
+        if (resource.loadFailedOrCanceled())
+            return true;
+        // We can't revalidate subresources individually so don't use reuse the parsed sheet if they need revalidation.
+        if (resource.makeRevalidationDecision(cachePolicy) != CachedResource::RevalidationDecision::No)
+            return true;
+        return false;
+    });
+    return !hasFailedOrExpiredResources;
+}
+
+bool StyleSheetContents::isLoadingSubresources() const
+{
+    return traverseSubresources([](const CachedResource& resource) {
+        return resource.isLoading();
+    });
+}
+
 StyleSheetContents* StyleSheetContents::parentStyleSheet() const
 {
     return m_ownerRule ? m_ownerRule->parentStyleSheet() : 0;

Modified: trunk/Source/WebCore/css/StyleSheetContents.h (184314 => 184315)


--- trunk/Source/WebCore/css/StyleSheetContents.h	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/css/StyleSheetContents.h	2015-05-13 23:09:13 UTC (rev 184315)
@@ -22,6 +22,7 @@
 #define StyleSheetContents_h
 
 #include "CSSParserMode.h"
+#include "CachePolicy.h"
 #include "URL.h"
 #include <wtf/HashMap.h>
 #include <wtf/ListHashSet.h>
@@ -34,6 +35,7 @@
 
 class CSSStyleSheet;
 class CachedCSSStyleSheet;
+class CachedResource;
 class Document;
 class Node;
 class StyleRuleBase;
@@ -67,6 +69,8 @@
     bool isCacheable() const;
 
     bool isLoading() const;
+    bool subresourcesAllowReuse(CachePolicy) const;
+    WEBCORE_EXPORT bool isLoadingSubresources() const;
 
     void checkLoaded();
     void startLoadingDynamicSheet();
@@ -78,10 +82,10 @@
     const String& charset() const { return m_parserContext.charset; }
 
     bool loadCompleted() const { return m_loadCompleted; }
-    bool hasFailedOrCanceledSubresources() const;
 
     URL completeURL(const String& url) const;
     void addSubresourceStyleURLs(ListHashSet<URL>&);
+    bool traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const;
 
     void setIsUserStyleSheet(bool b) { m_isUserStyleSheet = b; }
     bool isUserStyleSheet() const { return m_isUserStyleSheet; }

Modified: trunk/Source/WebCore/html/HTMLLinkElement.cpp (184314 => 184315)


--- trunk/Source/WebCore/html/HTMLLinkElement.cpp	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/html/HTMLLinkElement.cpp	2015-05-13 23:09:13 UTC (rev 184315)
@@ -321,8 +321,9 @@
     Ref<HTMLLinkElement> protect(*this);
 
     CSSParserContext parserContext(document(), baseURL, charset);
+    auto cachePolicy = document().frame()->loader().subresourceCachePolicy();
 
-    if (RefPtr<StyleSheetContents> restoredSheet = const_cast<CachedCSSStyleSheet*>(cachedStyleSheet)->restoreParsedStyleSheet(parserContext)) {
+    if (RefPtr<StyleSheetContents> restoredSheet = const_cast<CachedCSSStyleSheet*>(cachedStyleSheet)->restoreParsedStyleSheet(parserContext, cachePolicy)) {
         ASSERT(restoredSheet->isCacheable());
         ASSERT(!restoredSheet->isLoading());
 

Modified: trunk/Source/WebCore/loader/cache/CachedCSSStyleSheet.cpp (184314 => 184315)


--- trunk/Source/WebCore/loader/cache/CachedCSSStyleSheet.cpp	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/loader/cache/CachedCSSStyleSheet.cpp	2015-05-13 23:09:13 UTC (rev 184315)
@@ -143,11 +143,11 @@
     setDecodedSize(0);
 }
 
-PassRefPtr<StyleSheetContents> CachedCSSStyleSheet::restoreParsedStyleSheet(const CSSParserContext& context)
+PassRefPtr<StyleSheetContents> CachedCSSStyleSheet::restoreParsedStyleSheet(const CSSParserContext& context, CachePolicy cachePolicy)
 {
     if (!m_parsedStyleSheetCache)
         return 0;
-    if (m_parsedStyleSheetCache->hasFailedOrCanceledSubresources()) {
+    if (!m_parsedStyleSheetCache->subresourcesAllowReuse(cachePolicy)) {
         m_parsedStyleSheetCache->removedFromMemoryCache();
         m_parsedStyleSheetCache.clear();
         return 0;

Modified: trunk/Source/WebCore/loader/cache/CachedCSSStyleSheet.h (184314 => 184315)


--- trunk/Source/WebCore/loader/cache/CachedCSSStyleSheet.h	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/loader/cache/CachedCSSStyleSheet.h	2015-05-13 23:09:13 UTC (rev 184315)
@@ -43,7 +43,7 @@
 
         const String sheetText(bool* hasValidMIMEType = nullptr) const;
 
-        PassRefPtr<StyleSheetContents> restoreParsedStyleSheet(const CSSParserContext&);
+        PassRefPtr<StyleSheetContents> restoreParsedStyleSheet(const CSSParserContext&, CachePolicy);
         void saveParsedStyleSheet(Ref<StyleSheetContents>&&);
 
     private:

Modified: trunk/Source/WebCore/loader/cache/CachedImage.cpp (184314 => 184315)


--- trunk/Source/WebCore/loader/cache/CachedImage.cpp	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/loader/cache/CachedImage.cpp	2015-05-13 23:09:13 UTC (rev 184315)
@@ -515,7 +515,7 @@
     return !securityOrigin->taintsCanvas(response().url());
 }
 
-bool CachedImage::mustRevalidateDueToCacheHeaders(const CachedResourceLoader& cachedResourceLoader, CachePolicy policy) const
+CachedResource::RevalidationDecision CachedImage::makeRevalidationDecision(CachePolicy cachePolicy) const
 {
     if (UNLIKELY(isManuallyCached())) {
         // Do not revalidate manually cached images. This mechanism is used as a
@@ -523,9 +523,9 @@
         // the URL for that image may not represent a resource that can be
         // retrieved by standard means. If the manual caching SPI is used, it is
         // incumbent on the client to only use valid resources.
-        return false;
+        return RevalidationDecision::No;
     }
-    return CachedResource::mustRevalidateDueToCacheHeaders(cachedResourceLoader, policy);
+    return CachedResource::makeRevalidationDecision(cachePolicy);
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/loader/cache/CachedImage.h (184314 => 184315)


--- trunk/Source/WebCore/loader/cache/CachedImage.h	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/loader/cache/CachedImage.h	2015-05-13 23:09:13 UTC (rev 184315)
@@ -84,7 +84,7 @@
     void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio);
 
     bool isManuallyCached() const { return m_isManuallyCached; }
-    virtual bool mustRevalidateDueToCacheHeaders(const CachedResourceLoader&, CachePolicy) const override;
+    RevalidationDecision makeRevalidationDecision(CachePolicy) const override;
     virtual void load(CachedResourceLoader&, const ResourceLoaderOptions&) override;
 
     bool isOriginClean(SecurityOrigin*);

Modified: trunk/Source/WebCore/loader/cache/CachedResource.cpp (184314 => 184315)


--- trunk/Source/WebCore/loader/cache/CachedResource.cpp	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/loader/cache/CachedResource.cpp	2015-05-13 23:09:13 UTC (rev 184315)
@@ -680,39 +680,30 @@
     return m_response.hasCacheValidatorFields();
 }
 
-static inline void logResourceRevalidationReason(Frame* frame, const String& reason)
-{
-    if (frame)
-        frame->mainFrame().diagnosticLoggingClient().logDiagnosticMessageWithValue(DiagnosticLoggingKeys::cachedResourceRevalidationKey(), DiagnosticLoggingKeys::reasonKey(), reason, ShouldSample::Yes);
-}
-
-bool CachedResource::mustRevalidateDueToCacheHeaders(const CachedResourceLoader& cachedResourceLoader, CachePolicy cachePolicy) const
+CachedResource::RevalidationDecision CachedResource::makeRevalidationDecision(CachePolicy cachePolicy) const
 {    
-    ASSERT(cachePolicy == CachePolicyRevalidate || cachePolicy == CachePolicyVerify);
+    switch (cachePolicy) {
+    case CachePolicyHistoryBuffer:
+        return RevalidationDecision::No;
 
-    if (cachePolicy == CachePolicyRevalidate) {
-        logResourceRevalidationReason(cachedResourceLoader.frame(), DiagnosticLoggingKeys::reloadKey());
-        return true;
-    }
+    case CachePolicyReload:
+    case CachePolicyRevalidate:
+        return RevalidationDecision::YesDueToCachePolicy;
 
-    if (m_response.cacheControlContainsNoCache() || m_response.cacheControlContainsNoStore()) {
-        LOG(ResourceLoading, "CachedResource %p mustRevalidate because of m_response.cacheControlContainsNoCache() || m_response.cacheControlContainsNoStore()\n", this);
+    case CachePolicyVerify:
+        if (m_response.cacheControlContainsNoCache())
+            return RevalidationDecision::YesDueToNoCache;
+        // FIXME: Cache-Control:no-store should prevent storing, not reuse.
         if (m_response.cacheControlContainsNoStore())
-            logResourceRevalidationReason(cachedResourceLoader.frame(), DiagnosticLoggingKeys::noStoreKey());
-        else
-            logResourceRevalidationReason(cachedResourceLoader.frame(), DiagnosticLoggingKeys::noCacheKey());
+            return RevalidationDecision::YesDueToNoStore;
 
-        return true;
-    }
+        if (isExpired())
+            return RevalidationDecision::YesDueToExpired;
 
-    // CachePolicyVerify
-    if (isExpired()) {
-        LOG(ResourceLoading, "CachedResource %p mustRevalidate because of isExpired()\n", this);
-        logResourceRevalidationReason(cachedResourceLoader.frame(), DiagnosticLoggingKeys::isExpiredKey());
-        return true;
-    }
-
-    return false;
+        return RevalidationDecision::No;
+    };
+    ASSERT_NOT_REACHED();
+    return RevalidationDecision::No;
 }
 
 bool CachedResource::redirectChainAllowsReuse(ReuseExpiredRedirectionOrNot reuseExpiredRedirection) const

Modified: trunk/Source/WebCore/loader/cache/CachedResource.h (184314 => 184315)


--- trunk/Source/WebCore/loader/cache/CachedResource.h	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/loader/cache/CachedResource.h	2015-05-13 23:09:13 UTC (rev 184315)
@@ -211,7 +211,7 @@
     void cancelLoad();
     bool wasCanceled() const { return m_error.isCancellation(); }
     bool errorOccurred() const { return m_status == LoadError || m_status == DecodeError; }
-    bool loadFailedOrCanceled() { return !m_error.isNull(); }
+    bool loadFailedOrCanceled() const { return !m_error.isNull(); }
 
     bool shouldSendResourceLoadCallbacks() const { return m_options.sendLoadCallbacks() == SendCallbacks; }
     DataBufferingPolicy dataBufferingPolicy() const { return m_options.dataBufferingPolicy(); }
@@ -229,7 +229,8 @@
     
     bool canUseCacheValidator() const;
 
-    virtual bool mustRevalidateDueToCacheHeaders(const CachedResourceLoader&, CachePolicy) const;
+    enum class RevalidationDecision { No, YesDueToCachePolicy, YesDueToNoStore, YesDueToNoCache, YesDueToExpired };
+    virtual RevalidationDecision makeRevalidationDecision(CachePolicy) const;
     bool redirectChainAllowsReuse(ReuseExpiredRedirectionOrNot) const;
 
     bool isCacheValidator() const { return m_resourceToRevalidate; }

Modified: trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp (184314 => 184315)


--- trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp	2015-05-13 23:09:13 UTC (rev 184315)
@@ -646,6 +646,34 @@
 }
 #endif // ENABLE(RESOURCE_TIMING)
 
+static void logRevalidation(const String& reason, DiagnosticLoggingClient& logClient)
+{
+    logClient.logDiagnosticMessageWithValue(DiagnosticLoggingKeys::cachedResourceRevalidationKey(), DiagnosticLoggingKeys::reasonKey(), reason, ShouldSample::Yes);
+}
+
+static void logResourceRevalidationDecision(CachedResource::RevalidationDecision reason, const Frame* frame)
+{
+    if (!frame)
+        return;
+    auto& logClient = frame->mainFrame().diagnosticLoggingClient();
+    switch (reason) {
+    case CachedResource::RevalidationDecision::No:
+        break;
+    case CachedResource::RevalidationDecision::YesDueToExpired:
+        logRevalidation(DiagnosticLoggingKeys::isExpiredKey(), logClient);
+        break;
+    case CachedResource::RevalidationDecision::YesDueToNoStore:
+        logRevalidation(DiagnosticLoggingKeys::noStoreKey(), logClient);
+        break;
+    case CachedResource::RevalidationDecision::YesDueToNoCache:
+        logRevalidation(DiagnosticLoggingKeys::noCacheKey(), logClient);
+        break;
+    case CachedResource::RevalidationDecision::YesDueToCachePolicy:
+        logRevalidation(DiagnosticLoggingKeys::reloadKey(), logClient);
+        break;
+    }
+}
+
 CachedResourceLoader::RevalidationPolicy CachedResourceLoader::determineRevalidationPolicy(CachedResource::Type type, ResourceRequest& request, bool forPreload, CachedResource* existingResource, CachedResourceRequest::DeferOption defer) const
 {
     if (!existingResource)
@@ -738,8 +766,11 @@
     if (existingResource->isLoading())
         return Use;
 
+    auto revalidationDecision = existingResource->makeRevalidationDecision(cachePolicy(type));
+    logResourceRevalidationDecision(revalidationDecision, frame());
+
     // Check if the cache headers requires us to revalidate (cache expiration for example).
-    if (existingResource->mustRevalidateDueToCacheHeaders(*this, cachePolicy(type))) {
+    if (revalidationDecision != CachedResource::RevalidationDecision::No) {
         // See if the resource has usable ETag or Last-modified headers.
         if (existingResource->canUseCacheValidator())
             return Revalidate;

Modified: trunk/Source/WebCore/testing/Internals.cpp (184314 => 184315)


--- trunk/Source/WebCore/testing/Internals.cpp	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/testing/Internals.cpp	2015-05-13 23:09:13 UTC (rev 184315)
@@ -56,6 +56,7 @@
 #include "HTMLIFrameElement.h"
 #include "HTMLImageElement.h"
 #include "HTMLInputElement.h"
+#include "HTMLLinkElement.h"
 #include "HTMLNames.h"
 #include "HTMLPlugInElement.h"
 #include "HTMLPreloadScanner.h"
@@ -441,6 +442,25 @@
     return "Error";
 }
 
+bool Internals::isSharingStyleSheetContents(Element* a, Element* b)
+{
+    if (!is<HTMLLinkElement>(a) || !is<HTMLLinkElement>(b))
+        return false;
+    auto& aLink = downcast<HTMLLinkElement>(*a);
+    auto& bLink = downcast<HTMLLinkElement>(*b);
+    if (!aLink.sheet() || !bLink.sheet())
+        return false;
+    return &aLink.sheet()->contents() == &bLink.sheet()->contents();
+}
+
+bool Internals::isStyleSheetLoadingSubresources(Element* link)
+{
+    if (!is<HTMLLinkElement>(link))
+        return false;
+    auto& linkElement = downcast<HTMLLinkElement>(*link);
+    return linkElement.sheet() && linkElement.sheet()->contents().isLoadingSubresources();
+}
+
 static ResourceRequestCachePolicy stringToResourceRequestCachePolicy(const String& policy)
 {
     if (policy == "UseProtocolCachePolicy")

Modified: trunk/Source/WebCore/testing/Internals.h (184314 => 184315)


--- trunk/Source/WebCore/testing/Internals.h	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/testing/Internals.h	2015-05-13 23:09:13 UTC (rev 184315)
@@ -91,6 +91,8 @@
     bool isPreloaded(const String& url);
     bool isLoadingFromMemoryCache(const String& url);
     String xhrResponseSource(XMLHttpRequest*);
+    bool isSharingStyleSheetContents(Element* linkA, Element* linkB);
+    bool isStyleSheetLoadingSubresources(Element* link);
     void setOverrideCachePolicy(const String&);
     void setOverrideResourceLoadPriority(const String&);
 

Modified: trunk/Source/WebCore/testing/Internals.idl (184314 => 184315)


--- trunk/Source/WebCore/testing/Internals.idl	2015-05-13 22:27:37 UTC (rev 184314)
+++ trunk/Source/WebCore/testing/Internals.idl	2015-05-13 23:09:13 UTC (rev 184315)
@@ -59,6 +59,8 @@
     boolean isPreloaded(DOMString url);
     boolean isLoadingFromMemoryCache(DOMString url);
     DOMString xhrResponseSource(XMLHttpRequest xhr);
+    boolean isSharingStyleSheetContents(Element linkA, Element linkB);
+    boolean isStyleSheetLoadingSubresources(Element link);
     void clearMemoryCache();
     void pruneMemoryCacheToSize(long size);
     long memoryCacheSize();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to