1/* 2 * Copyright (C) 2006 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#import "WebCache.h" 27 28#import "WebNSObjectExtras.h" 29#import "WebPreferences.h" 30#import "WebSystemInterface.h" 31#import "WebView.h" 32#import "WebViewInternal.h" 33#import <WebCore/ApplicationCacheStorage.h> 34#import <WebCore/CrossOriginPreflightResultCache.h> 35#import <WebCore/MemoryCache.h> 36#import <runtime/InitializeThreading.h> 37#import <wtf/MainThread.h> 38#import <wtf/RunLoop.h> 39 40#if PLATFORM(IOS) 41#import "MemoryMeasure.h" 42#import "WebFrameInternal.h" 43#import <WebCore/CachedImage.h> 44#import <WebCore/CredentialStorage.h> 45#import <WebCore/Frame.h> 46#import <WebCore/PageCache.h> 47#import <WebCore/WebCoreThreadRun.h> 48#endif 49 50#if ENABLE(CACHE_PARTITIONING) 51#import <WebCore/Document.h> 52#endif 53 54@implementation WebCache 55 56+ (void)initialize 57{ 58#if !PLATFORM(IOS) 59 JSC::initializeThreading(); 60 WTF::initializeMainThreadToProcessMainThread(); 61 RunLoop::initializeMainRunLoop(); 62#endif 63 InitWebCoreSystemInterface(); 64} 65 66+ (NSArray *)statistics 67{ 68 WebCore::MemoryCache::Statistics s = WebCore::memoryCache()->getStatistics(); 69 70 return [NSArray arrayWithObjects: 71 [NSDictionary dictionaryWithObjectsAndKeys: 72 [NSNumber numberWithInt:s.images.count], @"Images", 73 [NSNumber numberWithInt:s.cssStyleSheets.count], @"CSS", 74#if ENABLE(XSLT) 75 [NSNumber numberWithInt:s.xslStyleSheets.count], @"XSL", 76#else 77 [NSNumber numberWithInt:0], @"XSL", 78#endif 79 [NSNumber numberWithInt:s.scripts.count], @"JavaScript", 80 nil], 81 [NSDictionary dictionaryWithObjectsAndKeys: 82 [NSNumber numberWithInt:s.images.size], @"Images", 83 [NSNumber numberWithInt:s.cssStyleSheets.size] ,@"CSS", 84#if ENABLE(XSLT) 85 [NSNumber numberWithInt:s.xslStyleSheets.size], @"XSL", 86#else 87 [NSNumber numberWithInt:0], @"XSL", 88#endif 89 [NSNumber numberWithInt:s.scripts.size], @"JavaScript", 90 nil], 91 [NSDictionary dictionaryWithObjectsAndKeys: 92 [NSNumber numberWithInt:s.images.liveSize], @"Images", 93 [NSNumber numberWithInt:s.cssStyleSheets.liveSize] ,@"CSS", 94#if ENABLE(XSLT) 95 [NSNumber numberWithInt:s.xslStyleSheets.liveSize], @"XSL", 96#else 97 [NSNumber numberWithInt:0], @"XSL", 98#endif 99 [NSNumber numberWithInt:s.scripts.liveSize], @"JavaScript", 100 nil], 101 [NSDictionary dictionaryWithObjectsAndKeys: 102 [NSNumber numberWithInt:s.images.decodedSize], @"Images", 103 [NSNumber numberWithInt:s.cssStyleSheets.decodedSize] ,@"CSS", 104#if ENABLE(XSLT) 105 [NSNumber numberWithInt:s.xslStyleSheets.decodedSize], @"XSL", 106#else 107 [NSNumber numberWithInt:0], @"XSL", 108#endif 109 [NSNumber numberWithInt:s.scripts.decodedSize], @"JavaScript", 110 nil], 111 [NSDictionary dictionaryWithObjectsAndKeys: 112 [NSNumber numberWithInt:s.images.purgeableSize], @"Images", 113 [NSNumber numberWithInt:s.cssStyleSheets.purgeableSize] ,@"CSS", 114#if ENABLE(XSLT) 115 [NSNumber numberWithInt:s.xslStyleSheets.purgeableSize], @"XSL", 116#else 117 [NSNumber numberWithInt:0], @"XSL", 118#endif 119 [NSNumber numberWithInt:s.scripts.purgeableSize], @"JavaScript", 120 nil], 121 [NSDictionary dictionaryWithObjectsAndKeys: 122 [NSNumber numberWithInt:s.images.purgedSize], @"Images", 123 [NSNumber numberWithInt:s.cssStyleSheets.purgedSize] ,@"CSS", 124#if ENABLE(XSLT) 125 [NSNumber numberWithInt:s.xslStyleSheets.purgedSize], @"XSL", 126#else 127 [NSNumber numberWithInt:0], @"XSL", 128#endif 129 [NSNumber numberWithInt:s.scripts.purgedSize], @"JavaScript", 130 nil], 131#if ENABLE(DISK_IMAGE_CACHE) && PLATFORM(IOS) 132 [NSDictionary dictionaryWithObjectsAndKeys: 133 [NSNumber numberWithInt:s.images.mappedSize], @"Images", 134 [NSNumber numberWithInt:s.cssStyleSheets.mappedSize] ,@"CSS", 135#if ENABLE(XSLT) 136 [NSNumber numberWithInt:s.xslStyleSheets.mappedSize], @"XSL", 137#else 138 [NSNumber numberWithInt:0], @"XSL", 139#endif 140 [NSNumber numberWithInt:s.scripts.mappedSize], @"JavaScript", 141 nil], 142#endif // ENABLE(DISK_IMAGE_CACHE) && PLATFORM(IOS) 143 nil]; 144} 145 146+ (void)empty 147{ 148 // Toggling the cache model like this forces the cache to evict all its in-memory resources. 149 WebCacheModel cacheModel = [WebView _cacheModel]; 150 [WebView _setCacheModel:WebCacheModelDocumentViewer]; 151 [WebView _setCacheModel:cacheModel]; 152 153 // Empty the application cache. 154 WebCore::cacheStorage().empty(); 155 156 // Empty the Cross-Origin Preflight cache 157 WebCore::CrossOriginPreflightResultCache::shared().empty(); 158} 159 160#if PLATFORM(IOS) 161+ (void)emptyInMemoryResources 162{ 163 // This method gets called from MobileSafari after it calls [WebView 164 // _close]. [WebView _close] schedules its work on the WebThread. So we 165 // schedule this method on the WebThread as well so as to pick up all the 166 // dead resources left behind after closing the WebViews 167 WebThreadRun(^{ 168 WebKit::MemoryMeasure measurer("[WebCache emptyInMemoryResources]"); 169 170 // Toggling the cache model like this forces the cache to evict all its in-memory resources. 171 WebCacheModel cacheModel = [WebView _cacheModel]; 172 [WebView _setCacheModel:WebCacheModelDocumentViewer]; 173 [WebView _setCacheModel:cacheModel]; 174 175 WebCore::memoryCache()->pruneLiveResources(true); 176 }); 177} 178 179+ (void)sizeOfDeadResources:(int *)resources 180{ 181 WebCore::MemoryCache::Statistics stats = WebCore::memoryCache()->getStatistics(); 182 if (resources) { 183 *resources = (stats.images.size - stats.images.liveSize) 184 + (stats.cssStyleSheets.size - stats.cssStyleSheets.liveSize) 185#if ENABLE(XSLT) 186 + (stats.xslStyleSheets.size - stats.xslStyleSheets.liveSize) 187#endif 188 + (stats.scripts.size - stats.scripts.liveSize); 189 } 190} 191 192+ (void)clearCachedCredentials 193{ 194 WebCore::CredentialStorage::clearCredentials(); 195} 196 197+ (bool)addImageToCache:(CGImageRef)image forURL:(NSURL *)url 198{ 199 return [WebCache addImageToCache:image forURL:url forFrame:nil]; 200} 201 202+ (bool)addImageToCache:(CGImageRef)image forURL:(NSURL *)url forFrame:(WebFrame *)frame 203{ 204 if (!image || !url || ![[url absoluteString] length]) 205 return false; 206 WebCore::SecurityOrigin* topOrigin = nullptr; 207#if ENABLE(CACHE_PARTITIONING) 208 if (frame) 209 topOrigin = core(frame)->document()->topOrigin(); 210#endif 211 return WebCore::memoryCache()->addImageToCache(image, url, topOrigin ? topOrigin->cachePartition() : emptyString()); 212} 213 214+ (void)removeImageFromCacheForURL:(NSURL *)url 215{ 216 [WebCache removeImageFromCacheForURL:url forFrame:nil]; 217} 218 219+ (void)removeImageFromCacheForURL:(NSURL *)url forFrame:(WebFrame *)frame 220{ 221 if (!url) 222 return; 223 WebCore::SecurityOrigin* topOrigin = nullptr; 224#if ENABLE(CACHE_PARTITIONING) 225 if (frame) 226 topOrigin = core(frame)->document()->topOrigin(); 227#endif 228 WebCore::memoryCache()->removeImageFromCache(url, topOrigin ? topOrigin->cachePartition() : emptyString()); 229} 230 231+ (CGImageRef)imageForURL:(NSURL *)url 232{ 233 if (!url) 234 return nullptr; 235 236 WebCore::CachedResource* cachedResource = WebCore::memoryCache()->resourceForURL(url); 237 if (!cachedResource || !cachedResource->isImage()) 238 return nullptr; 239 WebCore::CachedImage* cachedImage = WebCore::toCachedImage(cachedResource); 240 if (!cachedImage || !cachedImage->hasImage()) 241 return nullptr; 242 return cachedImage->image()->getCGImageRef(); 243} 244 245#endif // PLATFORM(IOS) 246 247+ (void)setDisabled:(BOOL)disabled 248{ 249 if (!pthread_main_np()) 250 return [[self _webkit_invokeOnMainThread] setDisabled:disabled]; 251 252 WebCore::memoryCache()->setDisabled(disabled); 253} 254 255+ (BOOL)isDisabled 256{ 257 return WebCore::memoryCache()->disabled(); 258} 259 260@end 261