Add SPI to set HSTS storage directory
https://bugs.webkit.org/show_bug.cgi?id=197259
Source/WebCore/PAL:

Patch by Alex Christensen <achristensen@webkit.org> on 2019-05-08
Reviewed by Brady Eidson.

* pal/spi/cf/CFNetworkSPI.h:

Source/WebKit:

<rdar://problem/48797895>

Patch by Alex Christensen <achristensen@webkit.org> on 2019-05-08
Reviewed by Brady Eidson.

It is with great sadness that I lament the design of this SPI, which is necessitated by the process-global nature of the SPI that
I must call and the time at which I must call it (before any networking calls have been made).
I'm also not thrilled about the fact that the unit test infrastructure I developed for this in r244594 cannot be used because
the SPI that I must call does not work on iOS simulator or Mac.  I have verified the SPI is being called and that when called on iOS,
and that CFNetwork does the right thing with it.

* NetworkProcess/NetworkProcessCreationParameters.cpp:
(WebKit::NetworkProcessCreationParameters::encode const):
(WebKit::NetworkProcessCreationParameters::decode):
* NetworkProcess/NetworkProcessCreationParameters.h:
* NetworkProcess/cocoa/NetworkProcessCocoa.mm:
(WebKit::NetworkProcess::platformInitializeNetworkProcessCocoa):
* UIProcess/API/APIProcessPoolConfiguration.cpp:
(API::ProcessPoolConfiguration::copy):
* UIProcess/API/APIProcessPoolConfiguration.h:
* UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h:
* UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm:
(-[_WKProcessPoolConfiguration setHSTSStorageDirectory:]):
(-[_WKProcessPoolConfiguration hstsStorageDirectory]):
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::ensureNetworkProcess):

Source/WTF:

Patch by Alex Christensen <achristensen@webkit.org> on 2019-05-08
Reviewed by Brady Eidson.

* wtf/Platform.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@245075 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WTF/ChangeLog b/Source/WTF/ChangeLog
index b92d057..6f263fe 100644
--- a/Source/WTF/ChangeLog
+++ b/Source/WTF/ChangeLog
@@ -1,3 +1,12 @@
+2019-05-08  Alex Christensen  <achristensen@webkit.org>
+
+        Add SPI to set HSTS storage directory
+        https://bugs.webkit.org/show_bug.cgi?id=197259
+
+        Reviewed by Brady Eidson.
+
+        * wtf/Platform.h:
+
 2019-05-08  Keith Miller  <keith_miller@apple.com>
 
         Remove Gigacage from arm64 and use PAC for arm64e instead
diff --git a/Source/WTF/wtf/Platform.h b/Source/WTF/wtf/Platform.h
index 84636ca..6e5e02f 100644
--- a/Source/WTF/wtf/Platform.h
+++ b/Source/WTF/wtf/Platform.h
@@ -1361,6 +1361,10 @@
 #define USE_SOURCE_APPLICATION_AUDIT_DATA 1
 #endif
 
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) || (PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000)
+#define HAVE_HSTS_STORAGE_PATH 1
+#endif
+
 #if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400) || PLATFORM(IOS) || PLATFORM(IOSMAC)
 #define HAVE_URL_FORMATTING 1
 #endif
diff --git a/Source/WebCore/PAL/ChangeLog b/Source/WebCore/PAL/ChangeLog
index a542ea5..3d9f182 100644
--- a/Source/WebCore/PAL/ChangeLog
+++ b/Source/WebCore/PAL/ChangeLog
@@ -1,3 +1,12 @@
+2019-05-08  Alex Christensen  <achristensen@webkit.org>
+
+        Add SPI to set HSTS storage directory
+        https://bugs.webkit.org/show_bug.cgi?id=197259
+
+        Reviewed by Brady Eidson.
+
+        * pal/spi/cf/CFNetworkSPI.h:
+
 2019-05-07  Eric Carlson  <eric.carlson@apple.com>
 
         Define media buffering policy
diff --git a/Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h b/Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h
index 8778bcc..897af04 100644
--- a/Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h
+++ b/Source/WebCore/PAL/pal/spi/cf/CFNetworkSPI.h
@@ -325,6 +325,10 @@
 CFMutableURLRequestRef _CFURLRequestCreateFromArchiveList(CFAllocatorRef, CFIndex version, CFTypeRef* objects, CFIndex objectCount, CFDictionaryRef protocolProperties);
 void CFURLRequestSetProxySettings(CFMutableURLRequestRef, CFDictionaryRef);
 
+#if HAVE(HSTS_STORAGE_PATH)
+void _CFNetworkSetHSTSStoragePath(CFStringRef);
+#endif
+
 #endif // !PLATFORM(WIN)
 
 CFN_EXPORT const CFStringRef kCFStreamPropertyCONNECTProxy;
diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog
index 4cc54e7..aa93f41 100644
--- a/Source/WebKit/ChangeLog
+++ b/Source/WebKit/ChangeLog
@@ -1,3 +1,33 @@
+2019-05-08  Alex Christensen  <achristensen@webkit.org>
+
+        Add SPI to set HSTS storage directory
+        https://bugs.webkit.org/show_bug.cgi?id=197259
+        <rdar://problem/48797895>
+
+        Reviewed by Brady Eidson.
+
+        It is with great sadness that I lament the design of this SPI, which is necessitated by the process-global nature of the SPI that
+        I must call and the time at which I must call it (before any networking calls have been made).
+        I'm also not thrilled about the fact that the unit test infrastructure I developed for this in r244594 cannot be used because
+        the SPI that I must call does not work on iOS simulator or Mac.  I have verified the SPI is being called and that when called on iOS,
+        and that CFNetwork does the right thing with it.
+
+        * NetworkProcess/NetworkProcessCreationParameters.cpp:
+        (WebKit::NetworkProcessCreationParameters::encode const):
+        (WebKit::NetworkProcessCreationParameters::decode):
+        * NetworkProcess/NetworkProcessCreationParameters.h:
+        * NetworkProcess/cocoa/NetworkProcessCocoa.mm:
+        (WebKit::NetworkProcess::platformInitializeNetworkProcessCocoa):
+        * UIProcess/API/APIProcessPoolConfiguration.cpp:
+        (API::ProcessPoolConfiguration::copy):
+        * UIProcess/API/APIProcessPoolConfiguration.h:
+        * UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h:
+        * UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm:
+        (-[_WKProcessPoolConfiguration setHSTSStorageDirectory:]):
+        (-[_WKProcessPoolConfiguration hstsStorageDirectory]):
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::WebProcessPool::ensureNetworkProcess):
+
 2019-05-08  Daniel Bates  <dabates@apple.com>
 
         Pass insertTextAsync options as a struct
diff --git a/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.cpp b/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.cpp
index 4059319..dc34806 100644
--- a/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.cpp
+++ b/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.cpp
@@ -92,6 +92,8 @@
     encoder << downloadMonitorSpeedMultiplier;
     encoder << isITPFirstPartyWebsiteDataRemovalEnabled;
     encoder << enableAdClickAttributionDebugMode;
+    encoder << hstsStorageDirectory;
+    encoder << hstsStorageDirectoryExtensionHandle;
 }
 
 bool NetworkProcessCreationParameters::decode(IPC::Decoder& decoder, NetworkProcessCreationParameters& result)
@@ -224,6 +226,12 @@
     if (!decoder.decode(result.enableAdClickAttributionDebugMode))
         return false;
 
+    if (!decoder.decode(result.hstsStorageDirectory))
+        return false;
+
+    if (!decoder.decode(result.hstsStorageDirectoryExtensionHandle))
+        return false;
+    
     return true;
 }
 
diff --git a/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h b/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h
index 203be69..9cdc45a 100644
--- a/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h
+++ b/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h
@@ -110,6 +110,8 @@
     bool isITPFirstPartyWebsiteDataRemovalEnabled { true };
     uint32_t downloadMonitorSpeedMultiplier { 1 };
     bool enableAdClickAttributionDebugMode { false };
+    String hstsStorageDirectory;
+    SandboxExtension::Handle hstsStorageDirectoryExtensionHandle;
 };
 
 } // namespace WebKit
diff --git a/Source/WebKit/NetworkProcess/cocoa/NetworkProcessCocoa.mm b/Source/WebKit/NetworkProcess/cocoa/NetworkProcessCocoa.mm
index 5aeae45..12c8aa9 100644
--- a/Source/WebKit/NetworkProcess/cocoa/NetworkProcessCocoa.mm
+++ b/Source/WebKit/NetworkProcess/cocoa/NetworkProcessCocoa.mm
@@ -72,6 +72,13 @@
     WebCore::setApplicationBundleIdentifier(parameters.uiProcessBundleIdentifier);
     WebCore::setApplicationSDKVersion(parameters.uiProcessSDKVersion);
 
+#if HAVE(HSTS_STORAGE_PATH)
+    if (!parameters.hstsStorageDirectory.isNull()) {
+        SandboxExtension::consumePermanently(parameters.hstsStorageDirectoryExtensionHandle);
+        _CFNetworkSetHSTSStoragePath(parameters.hstsStorageDirectory.createCFString().get());
+    }
+#endif
+
 #if PLATFORM(IOS_FAMILY)
     SandboxExtension::consumePermanently(parameters.cookieStorageDirectoryExtensionHandle);
     SandboxExtension::consumePermanently(parameters.containerCachesDirectoryExtensionHandle);
diff --git a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp
index 3db7056..54a4ab5 100644
--- a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp
+++ b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp
@@ -131,6 +131,7 @@
 #endif
     copy->m_customWebContentServiceBundleIdentifier = this->m_customWebContentServiceBundleIdentifier;
     copy->m_usesSingleWebProcess = m_usesSingleWebProcess;
+    copy->m_hstsStorageDirectory = m_hstsStorageDirectory;
 
     return copy;
 }
diff --git a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h
index f21af5f..872ceff 100644
--- a/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h
+++ b/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h
@@ -180,6 +180,9 @@
     const WTF::String& customWebContentServiceBundleIdentifier() const { return m_customWebContentServiceBundleIdentifier; }
     void setCustomWebContentServiceBundleIdentifier(const WTF::String& customWebContentServiceBundleIdentifier) { m_customWebContentServiceBundleIdentifier = customWebContentServiceBundleIdentifier; }
 
+    const WTF::String& hstsStorageDirectory() const { return m_hstsStorageDirectory; }
+    void setHSTSStorageDirectory(WTF::String&& directory) { m_hstsStorageDirectory = WTFMove(directory); }
+    
 #if PLATFORM(COCOA)
     bool suppressesConnectionTerminationOnSystemChange() const { return m_suppressesConnectionTerminationOnSystemChange; }
     void setSuppressesConnectionTerminationOnSystemChange(bool suppressesConnectionTerminationOnSystemChange) { m_suppressesConnectionTerminationOnSystemChange = suppressesConnectionTerminationOnSystemChange; }
@@ -227,6 +230,7 @@
     bool m_isJITEnabled { true };
     bool m_usesSingleWebProcess { false };
     uint32_t m_downloadMonitorSpeedMultiplier { 1 };
+    WTF::String m_hstsStorageDirectory;
 
 #if PLATFORM(IOS_FAMILY)
     WTF::String m_ctDataConnectionServiceType;
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h
index e188dd8..0f3a541 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h
+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.h
@@ -70,6 +70,7 @@
 @property (nonatomic) BOOL suppressesConnectionTerminationOnSystemChange WK_API_AVAILABLE(macos(10.14), ios(12.0));
 @property (nonatomic, getter=isJITEnabled) BOOL JITEnabled WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 @property (nonatomic) NSUInteger downloadMonitorSpeedMultiplierForTesting WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+@property (nonatomic, nullable, copy, setter=setHSTSStorageDirectory:) NSURL *hstsStorageDirectory WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 
 @end
 
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm
index 16c323b..dec574c 100644
--- a/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm
+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKProcessPoolConfiguration.mm
@@ -328,6 +328,20 @@
     return _processPoolConfiguration->downloadMonitorSpeedMultiplier();
 }
 
+- (void)setHSTSStorageDirectory:(NSURL *)directory
+{
+    if (directory && ![directory isFileURL])
+        [NSException raise:NSInvalidArgumentException format:@"%@ is not a file URL", directory];
+
+    // FIXME: Move this to _WKWebsiteDataStoreConfiguration once rdar://problem/50109631 is fixed.
+    _processPoolConfiguration->setHSTSStorageDirectory(directory.path);
+}
+
+- (NSURL *)hstsStorageDirectory
+{
+    return [NSURL fileURLWithPath:_processPoolConfiguration->hstsStorageDirectory() isDirectory:YES];
+}
+
 - (void)setDownloadMonitorSpeedMultiplierForTesting:(NSUInteger)multiplier
 {
     _processPoolConfiguration->setDownloadMonitorSpeedMultiplier(multiplier);
diff --git a/Source/WebKit/UIProcess/WebProcessPool.cpp b/Source/WebKit/UIProcess/WebProcessPool.cpp
index 3a6dacc..24fc797 100644
--- a/Source/WebKit/UIProcess/WebProcessPool.cpp
+++ b/Source/WebKit/UIProcess/WebProcessPool.cpp
@@ -535,6 +535,10 @@
 #endif
 #endif
 
+    parameters.hstsStorageDirectory = m_configuration->hstsStorageDirectory();
+    if (!parameters.hstsStorageDirectory.isNull())
+        SandboxExtension::createHandleForReadWriteDirectory(parameters.hstsStorageDirectory, parameters.hstsStorageDirectoryExtensionHandle);
+
     parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession;
 
     parameters.urlSchemesRegisteredAsSecure = copyToVector(m_schemesToRegisterAsSecure);