There should only be one way to get the system memory size.
[WebKit-https.git] / Source / WebKit2 / NetworkProcess / cocoa / NetworkProcessCocoa.mm
1 /*
2  * Copyright (C) 2014, 2015 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "NetworkProcess.h"
28
29 #if ENABLE(NETWORK_PROCESS)
30
31 #import "NetworkCache.h"
32 #import "NetworkProcessCreationParameters.h"
33 #import "NetworkResourceLoader.h"
34 #import "SandboxExtension.h"
35 #import <WebCore/CFNetworkSPI.h>
36 #import <wtf/RAMSize.h>
37
38 namespace WebKit {
39
40 void NetworkProcess::platformLowMemoryHandler(bool)
41 {
42     CFURLConnectionInvalidateConnectionCache();
43     _CFURLCachePurgeMemoryCache(adoptCF(CFURLCacheCopySharedURLCache()).get());
44 }
45
46 void NetworkProcess::platformInitializeNetworkProcessCocoa(const NetworkProcessCreationParameters& parameters)
47 {
48 #if PLATFORM(IOS)
49     SandboxExtension::consumePermanently(parameters.cookieStorageDirectoryExtensionHandle);
50     SandboxExtension::consumePermanently(parameters.containerCachesDirectoryExtensionHandle);
51     SandboxExtension::consumePermanently(parameters.parentBundleDirectoryExtensionHandle);
52 #endif
53     m_diskCacheDirectory = parameters.diskCacheDirectory;
54
55 #if (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 90000) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
56     _CFNetworkSetATSContext(parameters.networkATSContext.get());
57 #endif
58
59     // FIXME: Most of what this function does for cache size gets immediately overridden by setCacheModel().
60     // - memory cache size passed from UI process is always ignored;
61     // - disk cache size passed from UI process is effectively a minimum size.
62     // One non-obvious constraint is that we need to use -setSharedURLCache: even in testing mode, to prevent creating a default one on disk later, when some other code touches the cache.
63
64     ASSERT(!m_diskCacheIsDisabledForTesting || !parameters.nsURLCacheDiskCapacity);
65
66     if (!m_diskCacheDirectory.isNull()) {
67         SandboxExtension::consumePermanently(parameters.diskCacheDirectoryExtensionHandle);
68 #if ENABLE(NETWORK_CACHE)
69         if (parameters.shouldEnableNetworkCache && NetworkCache::singleton().initialize(m_diskCacheDirectory, parameters.shouldEnableNetworkCacheEfficacyLogging)) {
70             RetainPtr<NSURLCache> urlCache(adoptNS([[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil]));
71             [NSURLCache setSharedURLCache:urlCache.get()];
72             return;
73         }
74 #endif
75 #if PLATFORM(IOS)
76         [NSURLCache setSharedURLCache:adoptNS([[NSURLCache alloc]
77             _initWithMemoryCapacity:parameters.nsURLCacheMemoryCapacity
78             diskCapacity:parameters.nsURLCacheDiskCapacity
79             relativePath:parameters.uiProcessBundleIdentifier]).get()];
80 #else
81         [NSURLCache setSharedURLCache:adoptNS([[NSURLCache alloc]
82             initWithMemoryCapacity:parameters.nsURLCacheMemoryCapacity
83             diskCapacity:parameters.nsURLCacheDiskCapacity
84             diskPath:parameters.diskCacheDirectory]).get()];
85 #endif
86     }
87
88     RetainPtr<CFURLCacheRef> cache = adoptCF(CFURLCacheCopySharedURLCache());
89     if (!cache)
90         return;
91
92     _CFURLCacheSetMinSizeForVMCachedResource(cache.get(), NetworkResourceLoader::fileBackedResourceMinimumSize());
93 }
94
95 static uint64_t volumeFreeSize(const String& path)
96 {
97     NSDictionary *fileSystemAttributesDictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:(NSString *)path error:NULL];
98     return [[fileSystemAttributesDictionary objectForKey:NSFileSystemFreeSize] unsignedLongLongValue];
99 }
100
101 void NetworkProcess::platformSetCacheModel(CacheModel cacheModel)
102 {
103     uint64_t memSize = ramSize() / 1024 / 1024;
104
105     // As a fudge factor, use 1000 instead of 1024, in case the reported byte
106     // count doesn't align exactly to a megabyte boundary.
107     uint64_t diskFreeSize = volumeFreeSize(m_diskCacheDirectory) / 1024 / 1000;
108
109     unsigned cacheTotalCapacity = 0;
110     unsigned cacheMinDeadCapacity = 0;
111     unsigned cacheMaxDeadCapacity = 0;
112     auto deadDecodedDataDeletionInterval = std::chrono::seconds { 0 };
113     unsigned pageCacheCapacity = 0;
114     unsigned long urlCacheMemoryCapacity = 0;
115     unsigned long urlCacheDiskCapacity = 0;
116
117     calculateCacheSizes(cacheModel, memSize, diskFreeSize,
118         cacheTotalCapacity, cacheMinDeadCapacity, cacheMaxDeadCapacity, deadDecodedDataDeletionInterval,
119         pageCacheCapacity, urlCacheMemoryCapacity, urlCacheDiskCapacity);
120
121     if (m_diskCacheSizeOverride >= 0)
122         urlCacheDiskCapacity = m_diskCacheSizeOverride;
123
124 #if ENABLE(NETWORK_CACHE)
125     auto& networkCache = NetworkCache::singleton();
126     if (networkCache.isEnabled()) {
127         networkCache.setCapacity(urlCacheDiskCapacity);
128         return;
129     }
130 #endif
131     NSURLCache *nsurlCache = [NSURLCache sharedURLCache];
132     [nsurlCache setMemoryCapacity:urlCacheMemoryCapacity];
133     if (!m_diskCacheIsDisabledForTesting)
134         [nsurlCache setDiskCapacity:std::max<unsigned long>(urlCacheDiskCapacity, [nsurlCache diskCapacity])]; // Don't shrink a big disk cache, since that would cause churn.
135 }
136
137 void NetworkProcess::clearDiskCache(std::chrono::system_clock::time_point modifiedSince, std::function<void ()> completionHandler)
138 {
139 #if ENABLE(NETWORK_CACHE)
140     NetworkCache::singleton().clear();
141 #endif
142
143     if (!m_clearCacheDispatchGroup)
144         m_clearCacheDispatchGroup = dispatch_group_create();
145
146     dispatch_group_async(m_clearCacheDispatchGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), [modifiedSince, completionHandler] {
147         NSURLCache *cache = [NSURLCache sharedURLCache];
148
149 #if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
150         NSTimeInterval timeInterval = std::chrono::duration_cast<std::chrono::duration<double>>(modifiedSince.time_since_epoch()).count();
151         NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeInterval];
152         [cache removeCachedResponsesSinceDate:date];
153 #else
154         [cache removeAllCachedResponses];
155 #endif
156         dispatch_async(dispatch_get_main_queue(), [completionHandler] {
157             completionHandler();
158         });
159     });
160 }
161
162 }
163
164 #endif