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();