Permalink
Browse files

Crash in 3rd party WebKit apps that disable cache at a wrong time

https://bugs.webkit.org/show_bug.cgi?id=86027
<rdar://problem/10615880>

Reviewed by Antti Koivisto.

Source/WebCore:

Added an API test.

The fix is to use CachedResourceHandle throughout MemoryCache, which will certainly
keep the resource alive. Also removed earlier fixes.

* css/CSSImageSetValue.cpp: (WebCore::CSSImageSetValue::cachedImageSet):
* css/CSSImageValue.cpp: (WebCore::CSSImageValue::cachedImage):
* css/WebKitCSSShaderValue.cpp: (WebCore::WebKitCSSShaderValue::cachedShader):
* history/PageCache.cpp: (WebCore::PageCache::releaseAutoreleasedPagesNow):
* loader/ImageLoader.cpp: (WebCore::ImageLoader::updateFromElement):
* loader/TextTrackLoader.cpp: (WebCore::TextTrackLoader::load):
* loader/cache/CachedResourceLoader.cpp:
(WebCore::CachedResourceLoader::requestImage):
(WebCore::CachedResourceLoader::requestFont):
(WebCore::CachedResourceLoader::requestTextTrack):
(WebCore::CachedResourceLoader::requestShader):
(WebCore::CachedResourceLoader::requestCSSStyleSheet):
(WebCore::CachedResourceLoader::requestUserCSSStyleSheet):
(WebCore::CachedResourceLoader::requestScript):
(WebCore::CachedResourceLoader::requestXSLStyleSheet):
(WebCore::CachedResourceLoader::requestSVGDocument):
(WebCore::CachedResourceLoader::requestLinkResource):
(WebCore::CachedResourceLoader::requestRawResource):
(WebCore::CachedResourceLoader::requestResource):
(WebCore::CachedResourceLoader::revalidateResource):
(WebCore::CachedResourceLoader::loadResource):
(WebCore::CachedResourceLoader::requestPreload):
* loader/cache/CachedResourceLoader.h: (CachedResourceLoader):
* loader/cache/MemoryCache.h: (WebCore::MemoryCache::setPruneEnabled):

* loader/cache/CachedResourceHandle.h:
(WebCore::CachedResourceHandle::CachedResourceHandle):
(WebCore::CachedResourceHandle::operator=):
Teach CachedResourceHandle how to make CachedResourceHandle<CachedResource> from
a handle to subclass.

Tools:

Added a test that's very similar to MemoryCachePruneWithinResourceLoadDelegate,
but for disabling the cache instead of triggering a prune.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/mac/MemoryCacheDisableWithinResourceLoadDelegate.html: Added.
* TestWebKitAPI/Tests/mac/MemoryCacheDisableWithinResourceLoadDelegate.mm: Added.
(-[MemoryCacheDisableTestResourceLoadDelegate webView:identifierForInitialRequest:fromDataSource:]):
(-[MemoryCacheDisableTestResourceLoadDelegate webView:resource:willSendRequest:redirectResponse:fromDataSource:]):
(-[MemoryCacheDisableTestResourceLoadDelegate webView:resource:didFinishLoadingFromDataSource:]):
(-[MemoryCacheDisableTestResourceLoadDelegate webView:resource:didFailLoadingWithError:fromDataSource:]):
(TestWebKitAPI::TEST):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@116719 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information...
1 parent 6f2377d commit 6edc42b47be2a920302bcbfc6a4fcfcd227b63c3 ap@apple.com committed May 11, 2012
View
44 Source/WebCore/ChangeLog
@@ -1,3 +1,47 @@
+2012-05-10 Alexey Proskuryakov <ap@apple.com>
+
+ Crash in 3rd party WebKit apps that disable cache at a wrong time
+ https://bugs.webkit.org/show_bug.cgi?id=86027
+ <rdar://problem/10615880>
+
+ Reviewed by Antti Koivisto.
+
+ Added an API test.
+
+ The fix is to use CachedResourceHandle throughout MemoryCache, which will certainly
+ keep the resource alive. Also removed earlier fixes.
+
+ * css/CSSImageSetValue.cpp: (WebCore::CSSImageSetValue::cachedImageSet):
+ * css/CSSImageValue.cpp: (WebCore::CSSImageValue::cachedImage):
+ * css/WebKitCSSShaderValue.cpp: (WebCore::WebKitCSSShaderValue::cachedShader):
+ * history/PageCache.cpp: (WebCore::PageCache::releaseAutoreleasedPagesNow):
+ * loader/ImageLoader.cpp: (WebCore::ImageLoader::updateFromElement):
+ * loader/TextTrackLoader.cpp: (WebCore::TextTrackLoader::load):
+ * loader/cache/CachedResourceLoader.cpp:
+ (WebCore::CachedResourceLoader::requestImage):
+ (WebCore::CachedResourceLoader::requestFont):
+ (WebCore::CachedResourceLoader::requestTextTrack):
+ (WebCore::CachedResourceLoader::requestShader):
+ (WebCore::CachedResourceLoader::requestCSSStyleSheet):
+ (WebCore::CachedResourceLoader::requestUserCSSStyleSheet):
+ (WebCore::CachedResourceLoader::requestScript):
+ (WebCore::CachedResourceLoader::requestXSLStyleSheet):
+ (WebCore::CachedResourceLoader::requestSVGDocument):
+ (WebCore::CachedResourceLoader::requestLinkResource):
+ (WebCore::CachedResourceLoader::requestRawResource):
+ (WebCore::CachedResourceLoader::requestResource):
+ (WebCore::CachedResourceLoader::revalidateResource):
+ (WebCore::CachedResourceLoader::loadResource):
+ (WebCore::CachedResourceLoader::requestPreload):
+ * loader/cache/CachedResourceLoader.h: (CachedResourceLoader):
+ * loader/cache/MemoryCache.h: (WebCore::MemoryCache::setPruneEnabled):
+
+ * loader/cache/CachedResourceHandle.h:
+ (WebCore::CachedResourceHandle::CachedResourceHandle):
+ (WebCore::CachedResourceHandle::operator=):
+ Teach CachedResourceHandle how to make CachedResourceHandle<CachedResource> from
+ a handle to subclass.
+
2012-05-10 Tien-Ren Chen <trchen@chromium.org>
Eliminate duplicated code for culled line box in RenderInline
View
4 Source/WebCore/css/CSSImageSetValue.cpp
@@ -106,8 +106,8 @@ StyleCachedImageSet* CSSImageSetValue::cachedImageSet(CachedResourceLoader* load
// and any CSS transforms. https://bugs.webkit.org/show_bug.cgi?id=81698
ImageWithScale image = bestImageForScaleFactor();
ResourceRequest request(loader->document()->completeURL(image.imageURL));
- if (CachedImage* cachedImage = loader->requestImage(request)) {
- m_imageSet = StyleCachedImageSet::create(cachedImage, image.scaleFactor, this);
+ if (CachedResourceHandle<CachedImage> cachedImage = loader->requestImage(request)) {
+ m_imageSet = StyleCachedImageSet::create(cachedImage.get(), image.scaleFactor, this);
m_accessedBestFitImage = true;
}
}
View
4 Source/WebCore/css/CSSImageValue.cpp
@@ -82,8 +82,8 @@ StyleCachedImage* CSSImageValue::cachedImage(CachedResourceLoader* loader, const
m_accessedImage = true;
ResourceRequest request(loader->document()->completeURL(url));
- if (CachedImage* cachedImage = loader->requestImage(request))
- m_image = StyleCachedImage::create(cachedImage);
+ if (CachedResourceHandle<CachedImage> cachedImage = loader->requestImage(request))
+ m_image = StyleCachedImage::create(cachedImage.get());
}
return (m_image && m_image->isCachedImage()) ? static_cast<StyleCachedImage*>(m_image.get()) : 0;
View
4 Source/WebCore/css/WebKitCSSShaderValue.cpp
@@ -59,8 +59,8 @@ StyleCachedShader* WebKitCSSShaderValue::cachedShader(CachedResourceLoader* load
m_accessedShader = true;
ResourceRequest request(loader->document()->completeURL(m_url));
- if (CachedShader* cachedShader = loader->requestShader(request))
- m_shader = StyleCachedShader::create(cachedShader);
+ if (CachedResourceHandle<CachedShader> cachedShader = loader->requestShader(request))
+ m_shader = StyleCachedShader::create(cachedShader.get());
}
return (m_shader && m_shader->isCachedShader()) ? static_cast<StyleCachedShader*>(m_shader.get()) : 0;
View
7 Source/WebCore/history/PageCache.cpp
@@ -535,7 +535,6 @@ void PageCache::releaseAutoreleasedPagesNow()
m_autoreleaseTimer.stop();
// Postpone dead pruning until all our resources have gone dead.
- bool pruneWasEnabled = memoryCache()->pruneEnabled();
memoryCache()->setPruneEnabled(false);
CachedPageSet tmp;
@@ -546,10 +545,8 @@ void PageCache::releaseAutoreleasedPagesNow()
(*it)->destroy();
// Now do the prune.
- if (pruneWasEnabled) {
- memoryCache()->setPruneEnabled(true);
- memoryCache()->prune();
- }
+ memoryCache()->setPruneEnabled(true);
+ memoryCache()->prune();
}
void PageCache::autorelease(PassRefPtr<CachedPage> page)
View
4 Source/WebCore/loader/ImageLoader.cpp
@@ -154,7 +154,7 @@ void ImageLoader::updateFromElement()
// Do not load any image if the 'src' attribute is missing or if it is
// an empty string.
- CachedImage* newImage = 0;
+ CachedResourceHandle<CachedImage> newImage = 0;
if (!attr.isNull() && !stripLeadingAndTrailingHTMLSpaces(attr).isEmpty()) {
ResourceRequest request = ResourceRequest(document->completeURL(sourceURI(attr)));
@@ -170,7 +170,7 @@ void ImageLoader::updateFromElement()
newImage = new CachedImage(request);
newImage->setLoading(true);
newImage->setOwningCachedResourceLoader(document->cachedResourceLoader());
- document->cachedResourceLoader()->m_documentResources.set(newImage->url(), newImage);
+ document->cachedResourceLoader()->m_documentResources.set(newImage->url(), newImage.get());
document->cachedResourceLoader()->setAutoLoadImages(autoLoadOtherImages);
} else
newImage = document->cachedResourceLoader()->requestImage(request);
View
2 Source/WebCore/loader/TextTrackLoader.cpp
@@ -167,7 +167,7 @@ bool TextTrackLoader::load(const KURL& url, const String& crossOriginMode)
}
CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader();
- m_cachedCueData = static_cast<CachedTextTrack*>(cachedResourceLoader->requestTextTrack(cueRequest));
+ m_cachedCueData = cachedResourceLoader->requestTextTrack(cueRequest);
if (m_cachedCueData)
m_cachedCueData->addClient(this);
View
3 Source/WebCore/loader/cache/CachedResourceHandle.h
@@ -61,12 +61,15 @@ namespace WebCore {
CachedResourceHandle() { }
CachedResourceHandle(R* res) : CachedResourceHandleBase(res) { }
CachedResourceHandle(const CachedResourceHandle<R>& o) : CachedResourceHandleBase(o) { }
+ template<typename U> CachedResourceHandle(const CachedResourceHandle<U>& o) : CachedResourceHandleBase(o.get()) { }
R* get() const { return reinterpret_cast<R*>(CachedResourceHandleBase::get()); }
R* operator->() const { return get(); }
CachedResourceHandle& operator=(R* res) { setResource(res); return *this; }
CachedResourceHandle& operator=(const CachedResourceHandle& o) { setResource(o.get()); return *this; }
+ template<typename U> CachedResourceHandle& operator=(const CachedResourceHandle<U>& o) { setResource(o.get()); return *this; }
+
bool operator==(const CachedResourceHandleBase& o) const { return get() == o.get(); }
bool operator!=(const CachedResourceHandleBase& o) const { return get() != o.get(); }
};
View
105 Source/WebCore/loader/cache/CachedResourceLoader.cpp
@@ -151,7 +151,7 @@ Frame* CachedResourceLoader::frame() const
return m_document ? m_document->frame() : 0;
}
-CachedImage* CachedResourceLoader::requestImage(ResourceRequest& request)
+CachedResourceHandle<CachedImage> CachedResourceLoader::requestImage(ResourceRequest& request)
{
if (Frame* f = frame()) {
if (f->loader()->pageDismissalEventBeingDispatched() != FrameLoader::NoDismissal) {
@@ -161,37 +161,37 @@ CachedImage* CachedResourceLoader::requestImage(ResourceRequest& request)
return 0;
}
}
- CachedImage* resource = static_cast<CachedImage*>(requestResource(CachedResource::ImageResource, request, String(), defaultCachedResourceOptions()));
+ CachedResourceHandle<CachedImage> resource(static_cast<CachedImage*>(requestResource(CachedResource::ImageResource, request, String(), defaultCachedResourceOptions()).get()));
if (autoLoadImages() && resource && resource->stillNeedsLoad())
resource->load(this, defaultCachedResourceOptions());
return resource;
}
-CachedFont* CachedResourceLoader::requestFont(ResourceRequest& request)
+CachedResourceHandle<CachedFont> CachedResourceLoader::requestFont(ResourceRequest& request)
{
- return static_cast<CachedFont*>(requestResource(CachedResource::FontResource, request, String(), defaultCachedResourceOptions()));
+ return static_cast<CachedFont*>(requestResource(CachedResource::FontResource, request, String(), defaultCachedResourceOptions()).get());
}
#if ENABLE(VIDEO_TRACK)
-CachedTextTrack* CachedResourceLoader::requestTextTrack(ResourceRequest& request)
+CachedResourceHandle<CachedTextTrack> CachedResourceLoader::requestTextTrack(ResourceRequest& request)
{
- return static_cast<CachedTextTrack*>(requestResource(CachedResource::TextTrackResource, request, String(), defaultCachedResourceOptions()));
+ return static_cast<CachedTextTrack*>(requestResource(CachedResource::TextTrackResource, request, String(), defaultCachedResourceOptions()).get());
}
#endif
#if ENABLE(CSS_SHADERS)
-CachedShader* CachedResourceLoader::requestShader(ResourceRequest& request)
+CachedResourceHandle<CachedShader> CachedResourceLoader::requestShader(ResourceRequest& request)
{
- return static_cast<CachedShader*>(requestResource(CachedResource::ShaderResource, request, String(), defaultCachedResourceOptions()));
+ return static_cast<CachedShader*>(requestResource(CachedResource::ShaderResource, request, String(), defaultCachedResourceOptions()).get());
}
#endif
-CachedCSSStyleSheet* CachedResourceLoader::requestCSSStyleSheet(ResourceRequest& request, const String& charset, ResourceLoadPriority priority)
+CachedResourceHandle<CachedCSSStyleSheet> CachedResourceLoader::requestCSSStyleSheet(ResourceRequest& request, const String& charset, ResourceLoadPriority priority)
{
- return static_cast<CachedCSSStyleSheet*>(requestResource(CachedResource::CSSStyleSheet, request, charset, defaultCachedResourceOptions(), priority));
+ return static_cast<CachedCSSStyleSheet*>(requestResource(CachedResource::CSSStyleSheet, request, charset, defaultCachedResourceOptions(), priority).get());
}
-CachedCSSStyleSheet* CachedResourceLoader::requestUserCSSStyleSheet(ResourceRequest& request, const String& charset)
+CachedResourceHandle<CachedCSSStyleSheet> CachedResourceLoader::requestUserCSSStyleSheet(ResourceRequest& request, const String& charset)
{
KURL url = MemoryCache::removeFragmentIdentifierIfNeeded(request.url());
@@ -203,51 +203,47 @@ CachedCSSStyleSheet* CachedResourceLoader::requestUserCSSStyleSheet(ResourceRequ
if (url.string() != request.url())
request.setURL(url);
- CachedCSSStyleSheet* userSheet = new CachedCSSStyleSheet(request, charset);
-
- bool inCache = memoryCache()->add(userSheet);
- if (!inCache)
- userSheet->setInCache(true);
+ CachedResourceHandle<CachedCSSStyleSheet> userSheet = new CachedCSSStyleSheet(request, charset);
- userSheet->load(this, ResourceLoaderOptions(DoNotSendCallbacks, SniffContent, BufferData, AllowStoredCredentials, AskClientForCrossOriginCredentials, SkipSecurityCheck));
+ memoryCache()->add(userSheet.get());
+ // FIXME: loadResource calls setOwningCachedResourceLoader() if the resource couldn't be added to cache. Does this function need to call it, too?
- if (!inCache)
- userSheet->setInCache(false);
+ userSheet->load(this, ResourceLoaderOptions(DoNotSendCallbacks, SniffContent, BufferData, AllowStoredCredentials, AskClientForCrossOriginCredentials, SkipSecurityCheck));
return userSheet;
}
-CachedScript* CachedResourceLoader::requestScript(ResourceRequest& request, const String& charset)
+CachedResourceHandle<CachedScript> CachedResourceLoader::requestScript(ResourceRequest& request, const String& charset)
{
- return static_cast<CachedScript*>(requestResource(CachedResource::Script, request, charset, defaultCachedResourceOptions()));
+ return static_cast<CachedScript*>(requestResource(CachedResource::Script, request, charset, defaultCachedResourceOptions()).get());
}
#if ENABLE(XSLT)
-CachedXSLStyleSheet* CachedResourceLoader::requestXSLStyleSheet(ResourceRequest& request)
+CachedResourceHandle<CachedXSLStyleSheet> CachedResourceLoader::requestXSLStyleSheet(ResourceRequest& request)
{
- return static_cast<CachedXSLStyleSheet*>(requestResource(CachedResource::XSLStyleSheet, request, String(), defaultCachedResourceOptions()));
+ return static_cast<CachedXSLStyleSheet*>(requestResource(CachedResource::XSLStyleSheet, request, String(), defaultCachedResourceOptions()).get());
}
#endif
#if ENABLE(SVG)
-CachedSVGDocument* CachedResourceLoader::requestSVGDocument(ResourceRequest& request)
+CachedResourceHandle<CachedSVGDocument> CachedResourceLoader::requestSVGDocument(ResourceRequest& request)
{
- return static_cast<CachedSVGDocument*>(requestResource(CachedResource::SVGDocumentResource, request, request.url(), defaultCachedResourceOptions()));
+ return static_cast<CachedSVGDocument*>(requestResource(CachedResource::SVGDocumentResource, request, request.url(), defaultCachedResourceOptions()).get());
}
#endif
#if ENABLE(LINK_PREFETCH)
-CachedResource* CachedResourceLoader::requestLinkResource(CachedResource::Type type, ResourceRequest& request, ResourceLoadPriority priority)
+CachedResourceHandle<CachedResource> CachedResourceLoader::requestLinkResource(CachedResource::Type type, ResourceRequest& request, ResourceLoadPriority priority)
{
ASSERT(frame());
ASSERT(type == CachedResource::LinkPrefetch || type == CachedResource::LinkPrerender || type == CachedResource::LinkSubresource);
return requestResource(type, request, String(), defaultCachedResourceOptions(), priority);
}
#endif
-CachedRawResource* CachedResourceLoader::requestRawResource(ResourceRequest& request, const ResourceLoaderOptions& options)
+CachedResourceHandle<CachedRawResource> CachedResourceLoader::requestRawResource(ResourceRequest& request, const ResourceLoaderOptions& options)
{
- return static_cast<CachedRawResource*>(requestResource(CachedResource::RawResource, request, String(), options, ResourceLoadPriorityUnresolved, false));
+ return static_cast<CachedRawResource*>(requestResource(CachedResource::RawResource, request, String(), options, ResourceLoadPriorityUnresolved, false).get());
}
bool CachedResourceLoader::checkInsecureContent(CachedResource::Type type, const KURL& url) const
@@ -410,7 +406,7 @@ bool CachedResourceLoader::canRequest(CachedResource::Type type, const KURL& url
return true;
}
-CachedResource* CachedResourceLoader::requestResource(CachedResource::Type type, ResourceRequest& request, const String& charset, const ResourceLoaderOptions& options, ResourceLoadPriority priority, bool forPreload)
+CachedResourceHandle<CachedResource> CachedResourceLoader::requestResource(CachedResource::Type type, ResourceRequest& request, const String& charset, const ResourceLoaderOptions& options, ResourceLoadPriority priority, bool forPreload)
{
KURL url = request.url();
@@ -434,25 +430,25 @@ CachedResource* CachedResourceLoader::requestResource(CachedResource::Type type,
}
// See if we can use an existing resource from the cache.
- CachedResource* resource = memoryCache()->resourceForURL(url);
+ CachedResourceHandle<CachedResource> resource = memoryCache()->resourceForURL(url);
if (request.url() != url)
request.setURL(url);
- switch (determineRevalidationPolicy(type, request, forPreload, resource)) {
+ switch (determineRevalidationPolicy(type, request, forPreload, resource.get())) {
case Load:
resource = loadResource(type, request, charset, priority, options);
break;
case Reload:
- memoryCache()->remove(resource);
+ memoryCache()->remove(resource.get());
resource = loadResource(type, request, charset, priority, options);
break;
case Revalidate:
- resource = revalidateResource(resource, priority, options);
+ resource = revalidateResource(resource.get(), priority, options);
break;
case Use:
- memoryCache()->resourceAccessed(resource);
- notifyLoadedFromMemoryCache(resource);
+ memoryCache()->resourceAccessed(resource.get());
+ notifyLoadedFromMemoryCache(resource.get());
break;
}
@@ -463,8 +459,8 @@ CachedResource* CachedResourceLoader::requestResource(CachedResource::Type type,
m_documentResources.set(resource->url(), resource);
return resource;
}
-
-CachedResource* CachedResourceLoader::revalidateResource(CachedResource* resource, ResourceLoadPriority priority, const ResourceLoaderOptions& options)
+
+CachedResourceHandle<CachedResource> CachedResourceLoader::revalidateResource(CachedResource* resource, ResourceLoadPriority priority, const ResourceLoaderOptions& options)
{
ASSERT(resource);
ASSERT(resource->inCache());
@@ -475,13 +471,13 @@ CachedResource* CachedResourceLoader::revalidateResource(CachedResource* resourc
// Copy the URL out of the resource to be revalidated in case it gets deleted by the remove() call below.
String url = resource->url();
bool urlProtocolIsData = resource->url().protocolIsData();
- CachedResource* newResource = createResource(resource->type(), resource->resourceRequest(), resource->encoding());
+ CachedResourceHandle<CachedResource> newResource = createResource(resource->type(), resource->resourceRequest(), resource->encoding());
- LOG(ResourceLoading, "Resource %p created to revalidate %p", newResource, resource);
+ LOG(ResourceLoading, "Resource %p created to revalidate %p", newResource.get(), resource);
newResource->setResourceToRevalidate(resource);
memoryCache()->remove(resource);
- memoryCache()->add(newResource);
+ memoryCache()->add(newResource.get());
newResource->setLoadPriority(priority);
newResource->load(this, options);
@@ -491,39 +487,26 @@ CachedResource* CachedResourceLoader::revalidateResource(CachedResource* resourc
return newResource;
}
-CachedResource* CachedResourceLoader::loadResource(CachedResource::Type type, ResourceRequest& request, const String& charset, ResourceLoadPriority priority, const ResourceLoaderOptions& options)
+CachedResourceHandle<CachedResource> CachedResourceLoader::loadResource(CachedResource::Type type, ResourceRequest& request, const String& charset, ResourceLoadPriority priority, const ResourceLoaderOptions& options)
{
ASSERT(!memoryCache()->resourceForURL(request.url()));
LOG(ResourceLoading, "Loading CachedResource for '%s'.", request.url().string().latin1().data());
- CachedResource* resource = createResource(type, request, charset);
-
- bool inCache = memoryCache()->add(resource);
+ CachedResourceHandle<CachedResource> resource = createResource(type, request, charset);
- // Pretend the resource is in the cache, to prevent it from being deleted during the load() call.
- // FIXME: CachedResource should just use normal refcounting instead.
- if (!inCache)
- resource->setInCache(true);
+ bool inCache = memoryCache()->add(resource.get());
resource->setLoadPriority(priority);
-
- bool wasPruneEnabled = memoryCache()->pruneEnabled();
- memoryCache()->setPruneEnabled(false);
resource->load(this, options);
- memoryCache()->setPruneEnabled(wasPruneEnabled);
- if (!inCache) {
+ if (!inCache)
resource->setOwningCachedResourceLoader(this);
- resource->setInCache(false);
- }
// We don't support immediate loads, but we do support immediate failure.
if (resource->errorOccurred()) {
if (inCache)
- memoryCache()->remove(resource);
- else
- delete resource;
+ memoryCache()->remove(resource.get());
return 0;
}
@@ -781,14 +764,14 @@ void CachedResourceLoader::requestPreload(CachedResource::Type type, ResourceReq
if (type == CachedResource::Script || type == CachedResource::CSSStyleSheet)
encoding = charset.isEmpty() ? m_document->charset() : charset;
- CachedResource* resource = requestResource(type, request, encoding, defaultCachedResourceOptions(), ResourceLoadPriorityUnresolved, true);
- if (!resource || (m_preloads && m_preloads->contains(resource)))
+ CachedResourceHandle<CachedResource> resource = requestResource(type, request, encoding, defaultCachedResourceOptions(), ResourceLoadPriorityUnresolved, true);
+ if (!resource || (m_preloads && m_preloads->contains(resource.get())))
return;
resource->increasePreloadCount();
if (!m_preloads)
m_preloads = adoptPtr(new ListHashSet<CachedResource*>);
- m_preloads->add(resource);
+ m_preloads->add(resource.get());
#if PRELOAD_DEBUG
printf("PRELOADING %s\n", resource->url().latin1().data());
View
28 Source/WebCore/loader/cache/CachedResourceLoader.h
@@ -63,27 +63,27 @@ friend class ResourceCacheValidationSuppressor;
CachedResourceLoader(Document*);
~CachedResourceLoader();
- CachedImage* requestImage(ResourceRequest&);
- CachedCSSStyleSheet* requestCSSStyleSheet(ResourceRequest&, const String& charset, ResourceLoadPriority = ResourceLoadPriorityUnresolved);
- CachedCSSStyleSheet* requestUserCSSStyleSheet(ResourceRequest&, const String& charset);
- CachedScript* requestScript(ResourceRequest&, const String& charset);
- CachedFont* requestFont(ResourceRequest&);
- CachedRawResource* requestRawResource(ResourceRequest&, const ResourceLoaderOptions&);
+ CachedResourceHandle<CachedImage> requestImage(ResourceRequest&);
+ CachedResourceHandle<CachedCSSStyleSheet> requestCSSStyleSheet(ResourceRequest&, const String& charset, ResourceLoadPriority = ResourceLoadPriorityUnresolved);
+ CachedResourceHandle<CachedCSSStyleSheet> requestUserCSSStyleSheet(ResourceRequest&, const String& charset);
+ CachedResourceHandle<CachedScript> requestScript(ResourceRequest&, const String& charset);
+ CachedResourceHandle<CachedFont> requestFont(ResourceRequest&);
+ CachedResourceHandle<CachedRawResource> requestRawResource(ResourceRequest&, const ResourceLoaderOptions&);
#if ENABLE(SVG)
- CachedSVGDocument* requestSVGDocument(ResourceRequest&);
+ CachedResourceHandle<CachedSVGDocument> requestSVGDocument(ResourceRequest&);
#endif
#if ENABLE(XSLT)
- CachedXSLStyleSheet* requestXSLStyleSheet(ResourceRequest&);
+ CachedResourceHandle<CachedXSLStyleSheet> requestXSLStyleSheet(ResourceRequest&);
#endif
#if ENABLE(LINK_PREFETCH)
- CachedResource* requestLinkResource(CachedResource::Type, ResourceRequest&, ResourceLoadPriority = ResourceLoadPriorityUnresolved);
+ CachedResourceHandle<CachedResource> requestLinkResource(CachedResource::Type, ResourceRequest&, ResourceLoadPriority = ResourceLoadPriorityUnresolved);
#endif
#if ENABLE(VIDEO_TRACK)
- CachedTextTrack* requestTextTrack(ResourceRequest&);
+ CachedResourceHandle<CachedTextTrack> requestTextTrack(ResourceRequest&);
#endif
#if ENABLE(CSS_SHADERS)
- CachedShader* requestShader(ResourceRequest&);
+ CachedResourceHandle<CachedShader> requestShader(ResourceRequest&);
#endif
// Logs an access denied message to the console for the specified URL.
@@ -119,9 +119,9 @@ friend class ResourceCacheValidationSuppressor;
bool canRequest(CachedResource::Type, const KURL&, bool forPreload = false);
private:
- CachedResource* requestResource(CachedResource::Type, ResourceRequest&, const String& charset, const ResourceLoaderOptions&, ResourceLoadPriority = ResourceLoadPriorityUnresolved, bool isPreload = false);
- CachedResource* revalidateResource(CachedResource*, ResourceLoadPriority, const ResourceLoaderOptions&);
- CachedResource* loadResource(CachedResource::Type, ResourceRequest&, const String& charset, ResourceLoadPriority, const ResourceLoaderOptions&);
+ CachedResourceHandle<CachedResource> requestResource(CachedResource::Type, ResourceRequest&, const String& charset, const ResourceLoaderOptions&, ResourceLoadPriority = ResourceLoadPriorityUnresolved, bool isPreload = false);
+ CachedResourceHandle<CachedResource> revalidateResource(CachedResource*, ResourceLoadPriority, const ResourceLoaderOptions&);
+ CachedResourceHandle<CachedResource> loadResource(CachedResource::Type, ResourceRequest&, const String& charset, ResourceLoadPriority, const ResourceLoaderOptions&);
void requestPreload(CachedResource::Type, ResourceRequest&, const String& charset);
enum RevalidationPolicy { Use, Revalidate, Reload, Load };
View
1 Source/WebCore/loader/cache/MemoryCache.h
@@ -129,7 +129,6 @@ class MemoryCache {
void evictResources();
void setPruneEnabled(bool enabled) { m_pruneEnabled = enabled; }
- bool pruneEnabled() const { return m_pruneEnabled; }
void prune();
void pruneToPercentage(float targetPercentLive);
View
20 Tools/ChangeLog
@@ -1,3 +1,23 @@
+2012-05-10 Alexey Proskuryakov <ap@apple.com>
+
+ Crash in 3rd party WebKit apps that disable cache at a wrong time
+ https://bugs.webkit.org/show_bug.cgi?id=86027
+ <rdar://problem/10615880>
+
+ Reviewed by Antti Koivisto.
+
+ Added a test that's very similar to MemoryCachePruneWithinResourceLoadDelegate,
+ but for disabling the cache instead of triggering a prune.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/mac/MemoryCacheDisableWithinResourceLoadDelegate.html: Added.
+ * TestWebKitAPI/Tests/mac/MemoryCacheDisableWithinResourceLoadDelegate.mm: Added.
+ (-[MemoryCacheDisableTestResourceLoadDelegate webView:identifierForInitialRequest:fromDataSource:]):
+ (-[MemoryCacheDisableTestResourceLoadDelegate webView:resource:willSendRequest:redirectResponse:fromDataSource:]):
+ (-[MemoryCacheDisableTestResourceLoadDelegate webView:resource:didFinishLoadingFromDataSource:]):
+ (-[MemoryCacheDisableTestResourceLoadDelegate webView:resource:didFailLoadingWithError:fromDataSource:]):
+ (TestWebKitAPI::TEST):
+
2012-05-10 Anders Carlsson <andersca@apple.com>
WebKit2: Add a way to blacklist specific plug-ins/plug-in versions
View
10 Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
@@ -141,6 +141,8 @@
C507E8A714C6545B005D6B3B /* InspectorBar.mm in Sources */ = {isa = PBXBuildFile; fileRef = C507E8A614C6545B005D6B3B /* InspectorBar.mm */; };
C540F776152E4DA000A40C8C /* SimplifyMarkup.mm in Sources */ = {isa = PBXBuildFile; fileRef = C540F775152E4DA000A40C8C /* SimplifyMarkup.mm */; };
C540F784152E5A9A00A40C8C /* verboseMarkup.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = C540F783152E5A7800A40C8C /* verboseMarkup.html */; };
+ E1220DA0155B25480013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = E1220D9F155B25480013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.mm */; };
+ E1220DCA155B28AA0013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = E1220DC9155B287D0013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.html */; };
E490296814E2E3A4002BEDD1 /* TypingStyleCrash.mm in Sources */ = {isa = PBXBuildFile; fileRef = E490296714E2E3A4002BEDD1 /* TypingStyleCrash.mm */; };
F3FC3EE313678B7300126A65 /* libgtest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F3FC3EE213678B7300126A65 /* libgtest.a */; };
F6A6BFBB1558AC4800926107 /* simple-unload.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F6A6BFB91558ABF800926107 /* simple-unload.html */; };
@@ -182,6 +184,7 @@
B55F11B71517D03300915916 /* attributedStringCustomFont.html in Copy Resources */,
76E182DF154767E600F1FADD /* auto-submitting-form.html in Copy Resources */,
5142B2731517C8C800C32B19 /* ContextMenuCanCopyURL.html in Copy Resources */,
+ E1220DCA155B28AA0013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.html in Copy Resources */,
517E7E04151119C100D0B008 /* MemoryCachePruneWithinResourceLoadDelegate.html in Copy Resources */,
379028B914FAC24C007E6B43 /* acceptsFirstMouse.html in Copy Resources */,
33DC8912141955FE00747EF7 /* simple-iframe.html in Copy Resources */,
@@ -360,6 +363,8 @@
C507E8A614C6545B005D6B3B /* InspectorBar.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InspectorBar.mm; sourceTree = "<group>"; };
C540F775152E4DA000A40C8C /* SimplifyMarkup.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SimplifyMarkup.mm; sourceTree = "<group>"; };
C540F783152E5A7800A40C8C /* verboseMarkup.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = verboseMarkup.html; sourceTree = "<group>"; };
+ E1220D9F155B25480013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MemoryCacheDisableWithinResourceLoadDelegate.mm; sourceTree = "<group>"; };
+ E1220DC9155B287D0013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = MemoryCacheDisableWithinResourceLoadDelegate.html; sourceTree = "<group>"; };
E490296714E2E3A4002BEDD1 /* TypingStyleCrash.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TypingStyleCrash.mm; sourceTree = "<group>"; };
F3FC3EE213678B7300126A65 /* libgtest.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgtest.a; sourceTree = BUILT_PRODUCTS_DIR; };
F6A6BFB81558ABF800926107 /* simple-iframe-unload.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "simple-iframe-unload.html"; sourceTree = "<group>"; };
@@ -654,6 +659,7 @@
3776BC62150946BC0043A66D /* DeviceScaleFactorInDashboardRegions.mm */,
939BA91614103412001A01BD /* DeviceScaleFactorOnBack.mm */,
C507E8A614C6545B005D6B3B /* InspectorBar.mm */,
+ E1220D9F155B25480013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.mm */,
517E7DFB15110EA600D0B008 /* MemoryCachePruneWithinResourceLoadDelegate.mm */,
3722C8681461E03E00C45D00 /* RenderedImageFromDOMRange.mm */,
C540F775152E4DA000A40C8C /* SimplifyMarkup.mm */,
@@ -673,8 +679,9 @@
379028B814FABE49007E6B43 /* acceptsFirstMouse.html */,
5142B2721517C89100C32B19 /* ContextMenuCanCopyURL.html */,
37DC678F140D7D3A00ABCCDB /* DOMRangeOfString.html */,
- C07E6CB113FD738A0038B22B /* devicePixelRatio.html */,
+ E1220DC9155B287D0013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.html */,
517E7E031511187500D0B008 /* MemoryCachePruneWithinResourceLoadDelegate.html */,
+ C07E6CB113FD738A0038B22B /* devicePixelRatio.html */,
C540F783152E5A7800A40C8C /* verboseMarkup.html */,
);
name = Resources;
@@ -878,6 +885,7 @@
51FCF79A1534AC6D00104491 /* ShouldGoToBackForwardListItem.cpp in Sources */,
51393E201523944A005F39C5 /* DOMWindowExtensionBasic.cpp in Sources */,
76E182DA1547550100F1FADD /* WillSendSubmitEvent.cpp in Sources */,
+ E1220DA0155B25480013E2FC /* MemoryCacheDisableWithinResourceLoadDelegate.mm in Sources */,
F6F49C6915545C8E0007F39D /* DOMWindowExtensionNoCache.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
View
14 Tools/TestWebKitAPI/Tests/mac/MemoryCacheDisableWithinResourceLoadDelegate.html
@@ -0,0 +1,14 @@
+<script>
+
+function loaded()
+{
+ var request = new XMLHttpRequest();
+ request.open('GET', 'http://www.iana.org/domains/example/', true);
+ request.send(null);
+}
+
+</script>
+
+<body onload="loaded();">
+We will do some XHR'ing now!
+</body>
View
90 Tools/TestWebKitAPI/Tests/mac/MemoryCacheDisableWithinResourceLoadDelegate.mm
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#import "config.h"
+#import "PlatformUtilities.h"
+#import <WebKit/WebCache.h>
+#import <wtf/RetainPtr.h>
+
+@interface MemoryCacheDisableTestResourceLoadDelegate : NSObject {
+}
+@end
+
+static bool didFinishLoad;
+
+@implementation MemoryCacheDisableTestResourceLoadDelegate
+
+- (id)webView:(WebView *)sender identifierForInitialRequest:(NSURLRequest *)request fromDataSource:(WebDataSource *)dataSource
+{
+ [WebCache setDisabled:YES];
+ [WebCache setDisabled:NO];
+
+ return self;
+}
+
+- (NSURLRequest *)webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource
+{
+ [WebCache setDisabled:YES];
+ [WebCache setDisabled:NO];
+
+ return request;
+}
+
+- (void)webView:(WebView *)sender resource:(id)identifier didFinishLoadingFromDataSource:(WebDataSource *)dataSource
+{
+ [WebCache setDisabled:YES];
+ [WebCache setDisabled:NO];
+
+ didFinishLoad = YES;
+}
+
+- (void)webView:(WebView *)sender resource:(id)identifier didFailLoadingWithError:(NSError *)error fromDataSource:(WebDataSource *)dataSource
+{
+ [WebCache setDisabled:YES];
+ [WebCache setDisabled:NO];
+}
+
+@end
+
+namespace TestWebKitAPI {
+
+TEST(WebKit1, MemoryCacheDisableWithinResourceLoadDelegate)
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ RetainPtr<WebView> webView(AdoptNS, [[WebView alloc] initWithFrame:NSMakeRect(0, 0, 120, 200) frameName:nil groupName:nil]);
+
+ RetainPtr<MemoryCacheDisableTestResourceLoadDelegate> resourceLoadDelegate(AdoptNS, [[MemoryCacheDisableTestResourceLoadDelegate alloc] init]);
+ webView.get().resourceLoadDelegate = resourceLoadDelegate.get();
+
+ [[webView.get() mainFrame] loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"MemoryCacheDisableWithinResourceLoadDelegate" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]]];
+
+ Util::run(&didFinishLoad);
+
+ [pool drain];
+ // If we finished without crashing, the test passed.
+}
+
+} // namespace TestWebKitAPI

0 comments on commit 6edc42b

Please sign in to comment.