REGRESSION(r219530): ResourceLoadStatisticsPersistentStorage should be read-only...
authorbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Jan 2018 03:13:05 +0000 (03:13 +0000)
committerbfulgham@apple.com <bfulgham@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Jan 2018 03:13:05 +0000 (03:13 +0000)
https://bugs.webkit.org/show_bug.cgi?id=181136
<rdar://problem/36116604>

Reviewed by Chris Dumez.

Source/WebKit:

Some uses of WebKit involve running a UIProcess as an ephemeral session for the life of the process. In this
case, we do not initialize the data path for the set of load statistics triggering an assertion.

We actually intended ephemeral sessions to consume the existing resource load data (presumably captured during
non-ephemeral browsing). This would be a read-only mode, where it would not add new entries to the load
statistics, but would take advantage of existing observations. Currently that does not happen (for this type
of WebKit embed), which forces each run as an ephemeral session to build up in-memory browsing data until it has
enough observations to begin modifying loads.

We need to set the ResourceLoadStatisticsPersistentStorage object to a "read only" mode in this case, so
that it read (but does not write) from this database.

Tested by ephemeral website data TestWebKitAPI tests.

* UIProcess/ResourceLoadStatisticsPersistentStorage.cpp:
(WebKit::ResourceLoadStatisticsPersistentStorage::create): Added to allow creation of the right style of
Persistent Storage.
(WebKit::ResourceLoadStatisticsPersistentStorage::ResourceLoadStatisticsPersistentStorage): Initialize the
new data member.
(WebKit::ResourceLoadStatisticsPersistentStorage::asyncWriteTimerFired): RELEASE_ASSERT that we never run
this method when in "read only" mode.
(WebKit::ResourceLoadStatisticsPersistentStorage::writeMemoryStoreToDisk): Ditto.
(WebKit::ResourceLoadStatisticsPersistentStorage::scheduleOrWriteMemoryStore): Return early if asked to
schedule a write operation for a "read only" persistent store.
(WebKit::ResourceLoadStatisticsPersistentStorage::finishAllPendingWorkSynchronously): RELEASE_ASSERT if we
ever shut down in "read only" mode with an active write timer.
* UIProcess/ResourceLoadStatisticsPersistentStorage.h:
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore): Pass a flag indicating whether the
storage session is ephemeral or not.
* UIProcess/WebResourceLoadStatisticsStore.h:

Tools:

Add a new API test to confirm that ResourceLoadStatistics can be turned on safely for ephemeral
browsing sessions.

* Scripts/run-gtk-tests:
(GtkTestRunner): Unskip test now that it passes.
* TestWebKitAPI/Tests/WebKitCocoa/WebsiteDataStoreCustomPaths.mm:
(TEST): Add new WebsiteDataStoreEphemeral test.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@226838 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit/ChangeLog
Source/WebKit/UIProcess/ResourceLoadStatisticsPersistentStorage.cpp
Source/WebKit/UIProcess/ResourceLoadStatisticsPersistentStorage.h
Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.cpp
Source/WebKit/UIProcess/WebResourceLoadStatisticsStore.h
Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h
Tools/ChangeLog
Tools/Scripts/run-gtk-tests
Tools/TestWebKitAPI/Tests/WebKitCocoa/WebsiteDataStoreCustomPaths.mm

index ab68c8a..bc7bcce 100644 (file)
@@ -1,3 +1,43 @@
+2018-01-11  Brent Fulgham  <bfulgham@apple.com>
+
+        REGRESSION(r219530): ResourceLoadStatisticsPersistentStorage should be read-only in ephemeral sessions
+        https://bugs.webkit.org/show_bug.cgi?id=181136
+        <rdar://problem/36116604>
+
+        Reviewed by Chris Dumez.
+
+        Some uses of WebKit involve running a UIProcess as an ephemeral session for the life of the process. In this
+        case, we do not initialize the data path for the set of load statistics triggering an assertion.
+
+        We actually intended ephemeral sessions to consume the existing resource load data (presumably captured during
+        non-ephemeral browsing). This would be a read-only mode, where it would not add new entries to the load
+        statistics, but would take advantage of existing observations. Currently that does not happen (for this type
+        of WebKit embed), which forces each run as an ephemeral session to build up in-memory browsing data until it has
+        enough observations to begin modifying loads.
+
+        We need to set the ResourceLoadStatisticsPersistentStorage object to a "read only" mode in this case, so
+        that it read (but does not write) from this database.
+
+        Tested by ephemeral website data TestWebKitAPI tests.
+
+        * UIProcess/ResourceLoadStatisticsPersistentStorage.cpp:
+        (WebKit::ResourceLoadStatisticsPersistentStorage::create): Added to allow creation of the right style of
+        Persistent Storage.
+        (WebKit::ResourceLoadStatisticsPersistentStorage::ResourceLoadStatisticsPersistentStorage): Initialize the
+        new data member.
+        (WebKit::ResourceLoadStatisticsPersistentStorage::asyncWriteTimerFired): RELEASE_ASSERT that we never run
+        this method when in "read only" mode.
+        (WebKit::ResourceLoadStatisticsPersistentStorage::writeMemoryStoreToDisk): Ditto.
+        (WebKit::ResourceLoadStatisticsPersistentStorage::scheduleOrWriteMemoryStore): Return early if asked to
+        schedule a write operation for a "read only" persistent store.
+        (WebKit::ResourceLoadStatisticsPersistentStorage::finishAllPendingWorkSynchronously): RELEASE_ASSERT if we
+        ever shut down in "read only" mode with an active write timer.
+        * UIProcess/ResourceLoadStatisticsPersistentStorage.h:
+        * UIProcess/WebResourceLoadStatisticsStore.cpp:
+        (WebKit::WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore): Pass a flag indicating whether the
+        storage session is ephemeral or not.
+        * UIProcess/WebResourceLoadStatisticsStore.h:
+
 2018-01-11  Keith Rollin  <krollin@apple.com>
 
         Add optional logging of ITP-related user interaction information
index 3571404..9d99bca 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -82,10 +82,11 @@ static std::unique_ptr<KeyedDecoder> createDecoderForFile(const String& path)
     return KeyedDecoder::decoder(reinterpret_cast<const uint8_t*>(buffer.data()), buffer.size());
 }
 
-ResourceLoadStatisticsPersistentStorage::ResourceLoadStatisticsPersistentStorage(WebResourceLoadStatisticsStore& store, const String& storageDirectoryPath)
+ResourceLoadStatisticsPersistentStorage::ResourceLoadStatisticsPersistentStorage(WebResourceLoadStatisticsStore& store, const String& storageDirectoryPath, IsReadOnly isReadOnly)
     : m_memoryStore(store)
     , m_storageDirectoryPath(storageDirectoryPath)
     , m_asyncWriteTimer(RunLoop::main(), this, &ResourceLoadStatisticsPersistentStorage::asyncWriteTimerFired)
+    , m_isReadOnly(isReadOnly)
 {
 }
 
@@ -239,6 +240,7 @@ void ResourceLoadStatisticsPersistentStorage::populateMemoryStoreFromDisk()
 void ResourceLoadStatisticsPersistentStorage::asyncWriteTimerFired()
 {
     ASSERT(RunLoop::isMain());
+    RELEASE_ASSERT(m_isReadOnly != IsReadOnly::Yes);
     m_memoryStore.statisticsQueue().dispatch([this] () mutable {
         writeMemoryStoreToDisk();
     });
@@ -247,6 +249,7 @@ void ResourceLoadStatisticsPersistentStorage::asyncWriteTimerFired()
 void ResourceLoadStatisticsPersistentStorage::writeMemoryStoreToDisk()
 {
     ASSERT(!RunLoop::isMain());
+    RELEASE_ASSERT(m_isReadOnly != IsReadOnly::Yes);
 
     m_hasPendingWrite = false;
     stopMonitoringDisk();
@@ -281,6 +284,8 @@ void ResourceLoadStatisticsPersistentStorage::writeMemoryStoreToDisk()
 void ResourceLoadStatisticsPersistentStorage::scheduleOrWriteMemoryStore(ForceImmediateWrite forceImmediateWrite)
 {
     ASSERT(!RunLoop::isMain());
+    if (m_isReadOnly == IsReadOnly::Yes)
+        return;
 
     auto timeSinceLastWrite = MonotonicTime::now() - m_lastStatisticsWriteTime;
     if (forceImmediateWrite != ForceImmediateWrite::Yes && timeSinceLastWrite < minimumWriteInterval) {
@@ -312,6 +317,11 @@ void ResourceLoadStatisticsPersistentStorage::clear()
 
 void ResourceLoadStatisticsPersistentStorage::finishAllPendingWorkSynchronously()
 {
+    if (m_isReadOnly == IsReadOnly::Yes) {
+        RELEASE_ASSERT(!m_asyncWriteTimer.isActive());
+        return;
+    }
+
     m_asyncWriteTimer.stop();
 
     BinarySemaphore semaphore;
index c5d2ed4..b8d12f1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -41,7 +41,8 @@ class WebResourceLoadStatisticsStore;
 
 class ResourceLoadStatisticsPersistentStorage {
 public:
-    ResourceLoadStatisticsPersistentStorage(WebResourceLoadStatisticsStore&, const String& storageDirectoryPath);
+    enum class IsReadOnly { No, Yes };
+    ResourceLoadStatisticsPersistentStorage(WebResourceLoadStatisticsStore&, const String& storageDirectoryPath, IsReadOnly);
     ~ResourceLoadStatisticsPersistentStorage();
 
     void initialize();
@@ -78,6 +79,7 @@ private:
     std::unique_ptr<WebCore::FileMonitor> m_fileMonitor;
     WallTime m_lastStatisticsFileSyncTime;
     MonotonicTime m_lastStatisticsWriteTime;
+    IsReadOnly m_isReadOnly { IsReadOnly::No };
     bool m_hasPendingWrite { false };
 };
 
index e4493ef..91effdc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -147,9 +147,9 @@ static Vector<OperatingDate> mergeOperatingDates(const Vector<OperatingDate>& ex
     return mergedDates;
 }
 
-WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore(const String& resourceLoadStatisticsDirectory, Function<void(const String&)>&& testingCallback, UpdatePrevalentDomainsToPartitionOrBlockCookiesHandler&& updatePrevalentDomainsToPartitionOrBlockCookiesHandler, HasStorageAccessForFrameHandler&& hasStorageAccessForFrameHandler, GrantStorageAccessForFrameHandler&& grantStorageAccessForFrameHandler, RemovePrevalentDomainsHandler&& removeDomainsHandler)
+WebResourceLoadStatisticsStore::WebResourceLoadStatisticsStore(const String& resourceLoadStatisticsDirectory, Function<void(const String&)>&& testingCallback, bool isEphemeral, UpdatePrevalentDomainsToPartitionOrBlockCookiesHandler&& updatePrevalentDomainsToPartitionOrBlockCookiesHandler, HasStorageAccessForFrameHandler&& hasStorageAccessForFrameHandler, GrantStorageAccessForFrameHandler&& grantStorageAccessForFrameHandler, RemovePrevalentDomainsHandler&& removeDomainsHandler)
     : m_statisticsQueue(WorkQueue::create("WebResourceLoadStatisticsStore Process Data Queue", WorkQueue::Type::Serial, WorkQueue::QOS::Utility))
-    , m_persistentStorage(*this, resourceLoadStatisticsDirectory)
+    , m_persistentStorage(*this, resourceLoadStatisticsDirectory, isEphemeral ? ResourceLoadStatisticsPersistentStorage::IsReadOnly::Yes : ResourceLoadStatisticsPersistentStorage::IsReadOnly::No)
     , m_updatePrevalentDomainsToPartitionOrBlockCookiesHandler(WTFMove(updatePrevalentDomainsToPartitionOrBlockCookiesHandler))
     , m_hasStorageAccessForFrameHandler(WTFMove(hasStorageAccessForFrameHandler))
     , m_grantStorageAccessForFrameHandler(WTFMove(grantStorageAccessForFrameHandler))
index 22041d2..a1061dd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -65,9 +65,9 @@ public:
     using HasStorageAccessForFrameHandler = WTF::Function<void(const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, WTF::Function<void(bool hasAccess)>&& callback)>;
     using GrantStorageAccessForFrameHandler = WTF::Function<void(const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, WTF::Function<void(bool wasGranted)>&& callback)>;
     using RemovePrevalentDomainsHandler = WTF::Function<void (const Vector<String>&)>;
-    static Ref<WebResourceLoadStatisticsStore> create(const String& resourceLoadStatisticsDirectory, Function<void (const String&)>&& testingCallback, UpdatePrevalentDomainsToPartitionOrBlockCookiesHandler&& updatePrevalentDomainsToPartitionOrBlockCookiesHandler = [](const Vector<String>&, const Vector<String>&, const Vector<String>&, ShouldClearFirst) { }, HasStorageAccessForFrameHandler&& hasStorageAccessForFrameHandler = [](const String&, const String&, uint64_t, uint64_t, WTF::Function<void(bool)>&&) { }, GrantStorageAccessForFrameHandler&& grantStorageAccessForFrameHandler = [](const String&, const String&, uint64_t, uint64_t, WTF::Function<void(bool)>&&) { }, RemovePrevalentDomainsHandler&& removeDomainsHandler = [] (const Vector<String>&) { })
+    static Ref<WebResourceLoadStatisticsStore> create(const String& resourceLoadStatisticsDirectory, Function<void (const String&)>&& testingCallback, bool isEphemeral, UpdatePrevalentDomainsToPartitionOrBlockCookiesHandler&& updatePrevalentDomainsToPartitionOrBlockCookiesHandler = [](const Vector<String>&, const Vector<String>&, const Vector<String>&, ShouldClearFirst) { }, HasStorageAccessForFrameHandler&& hasStorageAccessForFrameHandler = [](const String&, const String&, uint64_t, uint64_t, WTF::Function<void(bool)>&&) { }, GrantStorageAccessForFrameHandler&& grantStorageAccessForFrameHandler = [](const String&, const String&, uint64_t, uint64_t, WTF::Function<void(bool)>&&) { }, RemovePrevalentDomainsHandler&& removeDomainsHandler = [] (const Vector<String>&) { })
     {
-        return adoptRef(*new WebResourceLoadStatisticsStore(resourceLoadStatisticsDirectory, WTFMove(testingCallback), WTFMove(updatePrevalentDomainsToPartitionOrBlockCookiesHandler), WTFMove(hasStorageAccessForFrameHandler), WTFMove(grantStorageAccessForFrameHandler), WTFMove(removeDomainsHandler)));
+        return adoptRef(*new WebResourceLoadStatisticsStore(resourceLoadStatisticsDirectory, WTFMove(testingCallback), isEphemeral, WTFMove(updatePrevalentDomainsToPartitionOrBlockCookiesHandler), WTFMove(hasStorageAccessForFrameHandler), WTFMove(grantStorageAccessForFrameHandler), WTFMove(removeDomainsHandler)));
     }
 
     ~WebResourceLoadStatisticsStore();
@@ -143,7 +143,7 @@ public:
     void logTestingEvent(const String&);
 
 private:
-    WebResourceLoadStatisticsStore(const String&, Function<void(const String&)>&& testingCallback, UpdatePrevalentDomainsToPartitionOrBlockCookiesHandler&&, HasStorageAccessForFrameHandler&&, GrantStorageAccessForFrameHandler&&, RemovePrevalentDomainsHandler&&);
+    WebResourceLoadStatisticsStore(const String&, Function<void(const String&)>&& testingCallback, bool isEphemeral, UpdatePrevalentDomainsToPartitionOrBlockCookiesHandler&&, HasStorageAccessForFrameHandler&&, GrantStorageAccessForFrameHandler&&, RemovePrevalentDomainsHandler&&);
 
     void removeDataRecords();
 
index 2b50367..353065a 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "APIProcessPoolConfiguration.h"
 #include "APIWebsiteDataRecord.h"
+#include "APIWebsiteDataStore.h"
 #include "NetworkProcessMessages.h"
 #include "StorageManager.h"
 #include "StorageProcessCreationParameters.h"
@@ -78,6 +79,11 @@ Ref<WebsiteDataStore> WebsiteDataStore::create(Configuration configuration, PAL:
     return adoptRef(*new WebsiteDataStore(WTFMove(configuration), sessionID));
 }
 
+WebsiteDataStore::Configuration::Configuration()
+    : resourceLoadStatisticsDirectory(API::WebsiteDataStore::defaultResourceLoadStatisticsDirectory())
+{
+}
+
 WebsiteDataStore::WebsiteDataStore(Configuration configuration, PAL::SessionID sessionID)
     : m_sessionID(sessionID)
     , m_configuration(WTFMove(configuration))
@@ -1401,7 +1407,7 @@ void WebsiteDataStore::enableResourceLoadStatisticsAndSetTestingCallback(Functio
     }
 
 #if HAVE(CFNETWORK_STORAGE_PARTITIONING)
-    m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(m_configuration.resourceLoadStatisticsDirectory, WTFMove(callback), [this, protectedThis = makeRef(*this)] (const Vector<String>& domainsToPartition, const Vector<String>& domainsToBlock, const Vector<String>& domainsToNeitherPartitionNorBlock, ShouldClearFirst shouldClearFirst) {
+    m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(m_configuration.resourceLoadStatisticsDirectory, WTFMove(callback), m_sessionID.isEphemeral(), [this, protectedThis = makeRef(*this)] (const Vector<String>& domainsToPartition, const Vector<String>& domainsToBlock, const Vector<String>& domainsToNeitherPartitionNorBlock, ShouldClearFirst shouldClearFirst) {
         updatePrevalentDomainsToPartitionOrBlockCookies(domainsToPartition, domainsToBlock, domainsToNeitherPartitionNorBlock, shouldClearFirst);
     }, [this, protectedThis = makeRef(*this)] (const String& resourceDomain, const String& firstPartyDomain, uint64_t frameID, uint64_t pageID, WTF::CompletionHandler<void(bool hasAccess)>&& callback) {
         hasStorageAccessForFrameHandler(resourceDomain, firstPartyDomain, frameID, pageID, WTFMove(callback));
@@ -1411,7 +1417,7 @@ void WebsiteDataStore::enableResourceLoadStatisticsAndSetTestingCallback(Functio
         removePrevalentDomains(domainsToRemove);
     });
 #else
-    m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(m_configuration.resourceLoadStatisticsDirectory, WTFMove(callback));
+    m_resourceLoadStatistics = WebResourceLoadStatisticsStore::create(m_configuration.resourceLoadStatisticsDirectory, WTFMove(callback), m_sessionID.isEphemeral());
 #endif
 
     for (auto& processPool : processPools())
index ac2218b..7cc2b13 100644 (file)
@@ -86,6 +86,8 @@ public:
         String resourceLoadStatisticsDirectory;
         String javaScriptConfigurationDirectory;
         String cookieStorageFile;
+
+        explicit Configuration();
     };
     static Ref<WebsiteDataStore> createNonPersistent();
     static Ref<WebsiteDataStore> create(Configuration, PAL::SessionID);
index e67a82f..bfc6e12 100644 (file)
@@ -1,3 +1,19 @@
+2018-01-11  Brent Fulgham  <bfulgham@apple.com>
+
+        REGRESSION(r219530): ResourceLoadStatisticsPersistentStorage should be read-only in ephemeral sessions
+        https://bugs.webkit.org/show_bug.cgi?id=181136
+        <rdar://problem/36116604>
+
+        Reviewed by Chris Dumez.
+
+        Add a new API test to confirm that ResourceLoadStatistics can be turned on safely for ephemeral
+        browsing sessions.
+
+        * Scripts/run-gtk-tests:
+        (GtkTestRunner): Unskip test now that it passes.
+        * TestWebKitAPI/Tests/WebKitCocoa/WebsiteDataStoreCustomPaths.mm:
+        (TEST): Add new WebsiteDataStoreEphemeral test.
+
 2018-01-11  Ryan Haddad  <ryanhaddad@apple.com>
 
         Unreviewed, rolling out r226816.
index e6325e6..9e5e4b5 100755 (executable)
@@ -43,7 +43,6 @@ class GtkTestRunner(TestRunner):
         SkippedTest("WebKit2Gtk/TestWebViewEditor", "/webkit2/WebKitWebView/editable/editable", "Test hits an assertion in Debug builds", 151654, "Debug"),
         SkippedTest("WebKit2Gtk/TestWebExtensions", "/webkit2/WebKitWebView/install-missing-plugins-permission-request", "Test times out", 147822),
         SkippedTest("WebKit2Gtk/TestWebsiteData", "/webkit2/WebKitWebsiteData/databases", "Test fails to clear database data", 181251),
-        SkippedTest("WebKit2Gtk/TestWebsiteData", "/webkit2/WebKitWebsiteData/ephemeral", "Test hits an assertion in Debug builds", 181136, "Debug"),
         SkippedTest("WebKit/TestWebKit", "WebKit.MouseMoveAfterCrash", "Test is flaky", 85066),
         SkippedTest("WebKit/TestWebKit", "WebKit.NewFirstVisuallyNonEmptyLayoutForImages", "Test is flaky", 85066),
         SkippedTest("WebKit/TestWebKit", "WebKit.NewFirstVisuallyNonEmptyLayoutFrames", "Test fails", 85037),
index d03d905..5a06808 100644 (file)
@@ -219,4 +219,46 @@ TEST(WebKit, WebsiteDataStoreCustomPaths)
     EXPECT_FALSE([WKWebsiteDataStore _defaultDataStoreExists]);
 }
 
+TEST(WebKit, WebsiteDataStoreEphemeral)
+{
+    RetainPtr<WebsiteDataStoreCustomPathsMessageHandler> handler = adoptNS([[WebsiteDataStoreCustomPathsMessageHandler alloc] init]);
+    RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
+
+    NSURL *defaultResourceLoadStatisticsPath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/WebsiteData/ResourceLoadStatistics/" stringByExpandingTildeInPath] isDirectory:YES];
+
+    [[NSFileManager defaultManager] removeItemAtURL:defaultResourceLoadStatisticsPath error:nil];
+
+    EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:defaultResourceLoadStatisticsPath.path]);
+
+    configuration.get().websiteDataStore = [WKWebsiteDataStore nonPersistentDataStore];
+    [configuration.get().websiteDataStore _setResourceLoadStatisticsEnabled:YES];
+
+    // We expect the directory to be created by starting up the data store machinery, but not the data file.
+    EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:defaultResourceLoadStatisticsPath.path]);
+
+    NSURL *defaultResourceLoadStatisticsFilePath = [NSURL fileURLWithPath:[@"~/Library/WebKit/TestWebKitAPI/WebsiteData/ResourceLoadStatistics/full_browsing_session_resourceLog.plist" stringByExpandingTildeInPath] isDirectory:NO];
+    EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:defaultResourceLoadStatisticsFilePath.path]);
+
+    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+
+    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"WebsiteDataStoreCustomPaths" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
+    [webView loadRequest:request];
+
+    [[[webView configuration] processPool] _syncNetworkProcessCookies];
+
+    // Forcibly shut down everything of WebKit that we can.
+    [[[webView configuration] processPool] _terminateStorageProcess];
+    auto pid = [webView _webProcessIdentifier];
+    if (pid)
+        kill(pid, SIGKILL);
+
+    webView = nil;
+    handler = nil;
+    configuration = nil;
+
+    EXPECT_TRUE([[NSFileManager defaultManager] fileExistsAtPath:defaultResourceLoadStatisticsPath.path]);
+    EXPECT_FALSE([[NSFileManager defaultManager] fileExistsAtPath:defaultResourceLoadStatisticsFilePath.path]);
+}
+
 #endif