Title: [218901] trunk
Revision
218901
Author
bfulg...@apple.com
Date
2017-06-28 16:21:11 -0700 (Wed, 28 Jun 2017)

Log Message

Teach ResourceLoadStatistics to recognize changes in the file system
https://bugs.webkit.org/show_bug.cgi?id=173800
<rdar://problem/32937842>

Reviewed by Chris Dumez.

Source/WebCore:

We want to support the case where multiple UI processes choose to share the same
statistics file. To support this, update the ResourceLoadStatistics logic to be aware
that the statistics data file might change underneath it, and to take appropriate
action when it does.

* WebCore.xcodeproj/project.pbxproj: Update for new sources.
* WebCore/CMakeLists.txt: Update for new FileMonitor source file.
* loader/ResourceLoadStatisticsStore.cpp:
(WebCore::ResourceLoadStatisticsStore::clearInMemoryAndPersistent): Use the new deletion
handler for the data file instead of writing out an empty file.
(WebCore::ResourceLoadStatisticsStore::setDeletePersistentStoreCallback): Added.
* loader/ResourceLoadStatisticsStore.h:
* platform/FileMonitor.cpp: Added.
(WebCore::FileMonitor::create):
(WebCore::FileMonitor::FileMonitor): Register handlers and begin monitoring file.
(WebCore::FileMonitor::~FileMonitor): Stop any active file monitoring.
(WebCore::FileMonitor::startMonitoringPath): Stub implementation.
(WebCore::FileMonitor::stopMonitoring): Ditto.
* platform/FileMonitor.h: Added.
* platform/FileSystem.h: Export files needed by WebKit2. Add support for O_EVTONLY
Darwin file handles.
* platform/Logging.h: Add 'ResourceLoadStatistics' category.
* platform/cocoa/FileMonitorCocoa.mm: Added.
(WebCore::FileMonitor::startMonitoringPath): Create a new VNODE type dispatch_source
to receive notifications when the specified file changes.
(WebCore::FileMonitor::stopMonitoring): Cancel the dispatch_source when we are done
monitoring the file.
* platform/posix/FileSystemPOSIX.cpp: Update 'openFile' to understand the O_EVTONLY
mode of file handles (Darwin-only). 

Source/WebKit2:

We want to support the case where multiple UI processes choose to share the same
statistics file. To support this, update the ResourceLoadStatistics logic to be aware
that the statistics data file might change underneath it, and to take appropriate
action when it does.

* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::setResourceLoadStatisticsEnabled): When we enable
the statistics, read in the data and then watch for changes.
(WebKit::WebResourceLoadStatisticsStore::registerSharedResourceLoadObserver): Add a
'delete data' handler to remove the file on disk, not just write an empty store.
(WebKit::WebResourceLoadStatisticsStore::readDataFromDiskIfNeeded): Use ASCIILiteral.
(WebKit::WebResourceLoadStatisticsStore::refreshFromDisk): Convenience function.
(WebKit::WebResourceLoadStatisticsStore::writeStoreToDisk): Sync with any on-disk
storage before writing out.
(WebKit::openAndLockFile): Convenience function.
(WebKit::closeAndUnlockFile): Ditto.
(WebKit::WebResourceLoadStatisticsStore::writeEncoderToDisk): Revise to lock file (on
platforms that support it) before writing to disk.
(WebKit::WebResourceLoadStatisticsStore::deleteStoreFromDisk): Added convenience function.
(WebKit::WebResourceLoadStatisticsStore::clearInMemoryData): Ditto.
(WebKit::WebResourceLoadStatisticsStore::startMonitoringStatisticsStorage): Create a
file system monitor to watch for file changes.
(WebKit::WebResourceLoadStatisticsStore::syncWithExistingStatisticsStorageIfNeeded): Added
convenience function.
(WebKit::WebResourceLoadStatisticsStore::createDecoderFromDisk): Revise to read data
directly so we can control file locking.
* UIProcess/WebResourceLoadStatisticsStore.h:

 2017-06-28  Wenson Hsieh  <wenson_hs...@apple.com>

Followup to r218885: adjust for further UIKit SPI changes
https://bugs.webkit.org/show_bug.cgi?id=173927
<rdar://problem/33020792>

Reviewed by Tim Horton.

On ToT, UIKit now invokes -_dragInteraction:item:shouldDelaySetDownAnimationWithCompletion: before the
completion block of -dragInteraction:willAnimateLiftWithAnimator:session: is called. This means we now need to
store the completion block in -shouldDelaySetDownAnimationWithCompletion: and wait until the UIDragAnimating
completion block in -willAnimateCancelWithAnimator: before invoking it.

* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView cleanUpDragSourceSessionState]):

Ensure that the set-down completion block is invoked when a drag session ends (e.g., if the web content process
crashes).

(-[WKContentView _dragInteraction:item:shouldDelaySetDownAnimationWithCompletion:]):
(-[WKContentView _api_dragInteraction:item:willAnimateCancelWithAnimator:]):

Source/WTF:

* wtf/DispatchPtr.h: Added (moved from WebKit2)
* wtf/Platform.h: Make sure USE_FILE_LOCK is enabled.

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebCore/FileMonitor.cpp: Added.
(TestWebKitAPI::FileMonitorTest::tempFilePath):
(TestWebKitAPI::handleFileModification):
(TestWebKitAPI::handleFileDeletion):
(TestWebKitAPI::resetTestState):
(TestWebKitAPI::TEST_F):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (218900 => 218901)


--- trunk/Source/WTF/ChangeLog	2017-06-28 23:04:38 UTC (rev 218900)
+++ trunk/Source/WTF/ChangeLog	2017-06-28 23:21:11 UTC (rev 218901)
@@ -1,3 +1,14 @@
+2017-06-28  Brent Fulgham  <bfulg...@apple.com>
+
+        Teach ResourceLoadStatistics to recognize changes in the file system
+        https://bugs.webkit.org/show_bug.cgi?id=173800
+        <rdar://problem/32937842>
+
+        Reviewed by Chris Dumez.
+
+        * wtf/DispatchPtr.h: Added (moved from WebKit2)
+        * wtf/Platform.h: Make sure USE_FILE_LOCK is enabled.
+
 2017-06-28  David Kilzer  <ddkil...@apple.com>
 
         Fix typo in comment: WordResult => WorkResult

Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (218900 => 218901)


--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2017-06-28 23:04:38 UTC (rev 218900)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2017-06-28 23:21:11 UTC (rev 218901)
@@ -382,6 +382,7 @@
 		A8A4727C151A825A004123FF /* DecimalNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DecimalNumber.h; sourceTree = "<group>"; };
 		A8A4727E151A825A004123FF /* Deque.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Deque.h; sourceTree = "<group>"; };
 		A8A4727F151A825A004123FF /* DisallowCType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisallowCType.h; sourceTree = "<group>"; };
+		A8A4727F151A825A004123FF /* DispatchPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DispatchPtr.h; sourceTree = "<group>"; };
 		A8A47280151A825A004123FF /* DoublyLinkedList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoublyLinkedList.h; sourceTree = "<group>"; };
 		A8A47282151A825A004123FF /* bignum-dtoa.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "bignum-dtoa.cc"; sourceTree = "<group>"; };
 		A8A47283151A825A004123FF /* bignum-dtoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "bignum-dtoa.h"; sourceTree = "<group>"; };
@@ -772,6 +773,7 @@
 				A561F30F1DF2642100FF675D /* DeprecatedOptional.h */,
 				A8A4727E151A825A004123FF /* Deque.h */,
 				A8A4727F151A825A004123FF /* DisallowCType.h */,
+                A8A4727F151A825A004123FF /* DispatchPtr.h */,
 				0F4570421BE5B58F0062A629 /* Dominators.h */,
 				A8A47280151A825A004123FF /* DoublyLinkedList.h */,
 				A8A47297151A825A004123FF /* dtoa.cpp */,

Added: trunk/Source/WTF/wtf/DispatchPtr.h (0 => 218901)


--- trunk/Source/WTF/wtf/DispatchPtr.h	                        (rev 0)
+++ trunk/Source/WTF/wtf/DispatchPtr.h	2017-06-28 23:21:11 UTC (rev 218901)
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015-2017 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.
+ */
+
+#pragma once
+
+#if PLATFORM(COCOA)
+
+#include <wtf/Assertions.h>
+#include <wtf/StdLibExtras.h>
+
+namespace WTF {
+
+template <typename T> class DispatchPtr;
+template <typename T> DispatchPtr<T> adoptDispatch(T dispatchObject);
+
+// FIXME: Use OSObjectPtr instead when it works with dispatch_data_t on all platforms.
+template<typename T> class DispatchPtr {
+public:
+    DispatchPtr()
+        : m_ptr(nullptr)
+    {
+    }
+    explicit DispatchPtr(T ptr)
+        : m_ptr(ptr)
+    {
+        if (m_ptr)
+            dispatch_retain(m_ptr);
+    }
+    DispatchPtr(const DispatchPtr& other)
+        : m_ptr(other.m_ptr)
+    {
+        if (m_ptr)
+            dispatch_retain(m_ptr);
+    }
+    ~DispatchPtr()
+    {
+        if (m_ptr)
+            dispatch_release(m_ptr);
+    }
+
+    DispatchPtr& operator=(const DispatchPtr& other)
+    {
+        auto copy = other;
+        std::swap(m_ptr, copy.m_ptr);
+        return *this;
+    }
+
+    DispatchPtr& operator=(std::nullptr_t)
+    {
+        auto ptr = std::exchange(m_ptr, nullptr);
+        if (LIKELY(ptr != nullptr))
+            dispatch_release(ptr);
+        return *this;
+    }
+
+    T get() const { return m_ptr; }
+    explicit operator bool() const { return m_ptr; }
+
+    friend DispatchPtr adoptDispatch<T>(T);
+
+private:
+    struct Adopt { };
+    DispatchPtr(Adopt, T data)
+        : m_ptr(data)
+    {
+    }
+
+    T m_ptr;
+};
+
+template <typename T> DispatchPtr<T> adoptDispatch(T dispatchObject)
+{
+    return DispatchPtr<T>(typename DispatchPtr<T>::Adopt { }, dispatchObject);
+}
+
+} // namespace WTF
+
+using WTF::DispatchPtr;
+using WTF::adoptDispatch;
+
+#endif

Modified: trunk/Source/WTF/wtf/Platform.h (218900 => 218901)


--- trunk/Source/WTF/wtf/Platform.h	2017-06-28 23:04:38 UTC (rev 218900)
+++ trunk/Source/WTF/wtf/Platform.h	2017-06-28 23:21:11 UTC (rev 218901)
@@ -545,6 +545,7 @@
 #define ENABLE_USER_MESSAGE_HANDLERS 1
 #define HAVE_OUT_OF_PROCESS_LAYER_HOSTING 1
 #define HAVE_DTRACE 0
+#define USE_FILE_LOCK 1
 
 #if !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
 #define ENABLE_DATA_DETECTION 1

Modified: trunk/Source/WebCore/CMakeLists.txt (218900 => 218901)


--- trunk/Source/WebCore/CMakeLists.txt	2017-06-28 23:04:38 UTC (rev 218900)
+++ trunk/Source/WebCore/CMakeLists.txt	2017-06-28 23:21:11 UTC (rev 218901)
@@ -2177,6 +2177,7 @@
     platform/EventTrackingRegions.cpp
     platform/FileChooser.cpp
     platform/FileHandle.cpp
+    platform/FileMonitor.cpp
     platform/FileStream.cpp
     platform/FileSystem.cpp
     platform/GenericTaskQueue.cpp

Modified: trunk/Source/WebCore/ChangeLog (218900 => 218901)


--- trunk/Source/WebCore/ChangeLog	2017-06-28 23:04:38 UTC (rev 218900)
+++ trunk/Source/WebCore/ChangeLog	2017-06-28 23:21:11 UTC (rev 218901)
@@ -1,3 +1,41 @@
+2017-06-28  Brent Fulgham  <bfulg...@apple.com>
+
+        Teach ResourceLoadStatistics to recognize changes in the file system
+        https://bugs.webkit.org/show_bug.cgi?id=173800
+        <rdar://problem/32937842>
+
+        Reviewed by Chris Dumez.
+
+        We want to support the case where multiple UI processes choose to share the same
+        statistics file. To support this, update the ResourceLoadStatistics logic to be aware
+        that the statistics data file might change underneath it, and to take appropriate
+        action when it does.
+
+        * WebCore.xcodeproj/project.pbxproj: Update for new sources.
+        * WebCore/CMakeLists.txt: Update for new FileMonitor source file.
+        * loader/ResourceLoadStatisticsStore.cpp:
+        (WebCore::ResourceLoadStatisticsStore::clearInMemoryAndPersistent): Use the new deletion
+        handler for the data file instead of writing out an empty file.
+        (WebCore::ResourceLoadStatisticsStore::setDeletePersistentStoreCallback): Added.
+        * loader/ResourceLoadStatisticsStore.h:
+        * platform/FileMonitor.cpp: Added.
+        (WebCore::FileMonitor::create):
+        (WebCore::FileMonitor::FileMonitor): Register handlers and begin monitoring file.
+        (WebCore::FileMonitor::~FileMonitor): Stop any active file monitoring.
+        (WebCore::FileMonitor::startMonitoringPath): Stub implementation.
+        (WebCore::FileMonitor::stopMonitoring): Ditto.
+        * platform/FileMonitor.h: Added.
+        * platform/FileSystem.h: Export files needed by WebKit2. Add support for O_EVTONLY
+        Darwin file handles.
+        * platform/Logging.h: Add 'ResourceLoadStatistics' category.
+        * platform/cocoa/FileMonitorCocoa.mm: Added.
+        (WebCore::FileMonitor::startMonitoringPath): Create a new VNODE type dispatch_source
+        to receive notifications when the specified file changes.
+        (WebCore::FileMonitor::stopMonitoring): Cancel the dispatch_source when we are done
+        monitoring the file.
+        * platform/posix/FileSystemPOSIX.cpp: Update 'openFile' to understand the O_EVTONLY
+        mode of file handles (Darwin-only). 
+
 2017-06-28  Brady Eidson  <beid...@apple.com>
 
         DocumentLoader should always notify the client if there are pending icon loads when the load is stopped.

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (218900 => 218901)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2017-06-28 23:04:38 UTC (rev 218900)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2017-06-28 23:21:11 UTC (rev 218901)
@@ -3066,6 +3066,7 @@
 		79AC9219109945C80021266E /* JSCompositionEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 79AC9217109945C80021266E /* JSCompositionEvent.h */; };
 		79F2F5A11091939A000D87CB /* CompositionEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79F2F59E1091939A000D87CB /* CompositionEvent.cpp */; };
 		79F2F5A21091939A000D87CB /* CompositionEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 79F2F59F1091939A000D87CB /* CompositionEvent.h */; };
+		7A09CEF11F02069B00E93BDB /* FileMonitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A09CEEC1F01CC9300E93BDB /* FileMonitor.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		7A0E770E10C00A8800A0276E /* InspectorFrontendHost.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A0E770B10C00A8800A0276E /* InspectorFrontendHost.cpp */; };
 		7A0E770F10C00A8800A0276E /* InspectorFrontendHost.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A0E770C10C00A8800A0276E /* InspectorFrontendHost.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		7A0E771E10C00DB100A0276E /* JSInspectorFrontendHost.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A0E771C10C00DB100A0276E /* JSInspectorFrontendHost.cpp */; };
@@ -3076,6 +3077,8 @@
 		7A24587C1021EAF4000A00AA /* InspectorDOMAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A24587A1021EAF4000A00AA /* InspectorDOMAgent.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		7A29BA6A187B7C1D00F29CEB /* TemporaryOpenGLSetting.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A29BA69187B781C00F29CEB /* TemporaryOpenGLSetting.cpp */; };
 		7A29F57218C69514004D0F81 /* OutOfBandTextTrackPrivateAVF.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A29F57118C69514004D0F81 /* OutOfBandTextTrackPrivateAVF.h */; };
+		7A32D7471F020EED00162C44 /* FileMonitorCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7A09CEF01F01D1F700E93BDB /* FileMonitorCocoa.mm */; };
+		7A32D7481F020EFF00162C44 /* FileMonitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A09CEEB1F01CC9300E93BDB /* FileMonitor.cpp */; };
 		7A45032F18DB717200377B34 /* BufferedLineReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A45032D18DB717200377B34 /* BufferedLineReader.cpp */; };
 		7A45033018DB717200377B34 /* BufferedLineReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A45032E18DB717200377B34 /* BufferedLineReader.h */; };
 		7A54857F14E02D51006AE05A /* InspectorHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A54857D14E02D51006AE05A /* InspectorHistory.cpp */; };
@@ -11129,6 +11132,9 @@
 		79F2F59E1091939A000D87CB /* CompositionEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompositionEvent.cpp; sourceTree = "<group>"; };
 		79F2F59F1091939A000D87CB /* CompositionEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompositionEvent.h; sourceTree = "<group>"; };
 		79F2F5A01091939A000D87CB /* CompositionEvent.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CompositionEvent.idl; sourceTree = "<group>"; };
+		7A09CEEB1F01CC9300E93BDB /* FileMonitor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FileMonitor.cpp; sourceTree = "<group>"; };
+		7A09CEEC1F01CC9300E93BDB /* FileMonitor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FileMonitor.h; sourceTree = "<group>"; };
+		7A09CEF01F01D1F700E93BDB /* FileMonitorCocoa.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FileMonitorCocoa.mm; sourceTree = "<group>"; };
 		7A0E770B10C00A8800A0276E /* InspectorFrontendHost.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorFrontendHost.cpp; sourceTree = "<group>"; };
 		7A0E770C10C00A8800A0276E /* InspectorFrontendHost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorFrontendHost.h; sourceTree = "<group>"; };
 		7A0E770D10C00A8800A0276E /* InspectorFrontendHost.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = InspectorFrontendHost.idl; sourceTree = "<group>"; };
@@ -21260,6 +21266,7 @@
 				CD7D33461C7A16BF00041293 /* CoreVideoSoftLink.h */,
 				7C7941E31C56C29300A4C58E /* DataDetectorsCoreSoftLink.h */,
 				7C7941E21C56C29300A4C58E /* DataDetectorsCoreSoftLink.mm */,
+				7A09CEF01F01D1F700E93BDB /* FileMonitorCocoa.mm */,
 				514B3F750C722055000530DF /* FileSystemCocoa.mm */,
 				A5C974CF11485FF10066F2AB /* KeyEventCocoa.h */,
 				A5C974D011485FF10066F2AB /* KeyEventCocoa.mm */,
@@ -24138,6 +24145,8 @@
 				5351D4AE1DF916AC008010CD /* FileHandle.cpp */,
 				5351D4AF1DF916AC008010CD /* FileHandle.h */,
 				4689F1AE1267BAE100E8D380 /* FileMetadata.h */,
+				7A09CEEB1F01CC9300E93BDB /* FileMonitor.cpp */,
+				7A09CEEC1F01CC9300E93BDB /* FileMonitor.h */,
 				2EF1BFE8121C9F4200C27627 /* FileStream.cpp */,
 				2EF1BFE9121C9F4200C27627 /* FileStream.h */,
 				2EF1BFF8121CB0CE00C27627 /* FileStreamClient.h */,
@@ -26563,6 +26572,7 @@
 				07B0113F1032242200FBDC33 /* AccessibilityMediaControls.h in Headers */,
 				76CDD2F31103DA6600680521 /* AccessibilityMenuList.h in Headers */,
 				76CDD2F71103DA6600680521 /* AccessibilityMenuListOption.h in Headers */,
+				7A09CEF11F02069B00E93BDB /* FileMonitor.h in Headers */,
 				76CDD2F51103DA6600680521 /* AccessibilityMenuListPopup.h in Headers */,
 				29ACB212143E7128006BCA5F /* AccessibilityMockObject.h in Headers */,
 				29A812360FBB9C1D00510293 /* AccessibilityObject.h in Headers */,
@@ -30846,6 +30856,7 @@
 				070363E3181A1CDC00C074A5 /* AVCaptureDeviceManager.mm in Sources */,
 				0719427F1D088F21002AA51D /* AVFoundationMIMETypeCache.mm in Sources */,
 				070363E5181A1CDC00C074A5 /* AVMediaCaptureSource.mm in Sources */,
+				7A32D7481F020EFF00162C44 /* FileMonitor.cpp in Sources */,
 				CD336F6117F9F64700DDDCD0 /* AVTrackPrivateAVFObjCImpl.mm in Sources */,
 				070363E7181A1CDC00C074A5 /* AVVideoCaptureSource.mm in Sources */,
 				F45C231D1995B73B00A6E2E3 /* AxisScrollSnapOffsets.cpp in Sources */,
@@ -33961,6 +33972,7 @@
 				498391580F1E776900C23782 /* WebKitCSSMatrix.cpp in Sources */,
 				8AA61CFF144D595B00F37350 /* WebKitCSSRegionRule.cpp in Sources */,
 				3FFFF9A8159D9A550020BBD5 /* WebKitCSSViewportRule.cpp in Sources */,
+				7A32D7471F020EED00162C44 /* FileMonitorCocoa.mm in Sources */,
 				1A1414B513A0F0500019996C /* WebKitFontFamilyNames.cpp in Sources */,
 				2D0621441DA639B600A7FB26 /* WebKitMediaKeyMessageEvent.cpp in Sources */,
 				2D0621521DA63AA200A7FB26 /* WebKitMediaKeyNeededEvent.cpp in Sources */,

Modified: trunk/Source/WebCore/loader/ResourceLoadStatisticsStore.cpp (218900 => 218901)


--- trunk/Source/WebCore/loader/ResourceLoadStatisticsStore.cpp	2017-06-28 23:04:38 UTC (rev 218900)
+++ trunk/Source/WebCore/loader/ResourceLoadStatisticsStore.cpp	2017-06-28 23:21:11 UTC (rev 218901)
@@ -158,8 +158,8 @@
 {
     ASSERT(!isMainThread());
     clearInMemory();
-    if (m_writePersistentStoreHandler)
-        m_writePersistentStoreHandler();
+    if (m_deletePersistentStoreHandler)
+        m_deletePersistentStoreHandler();
     if (m_grandfatherExistingWebsiteDataHandler)
         m_grandfatherExistingWebsiteDataHandler();
 }
@@ -222,6 +222,11 @@
     m_grandfatherExistingWebsiteDataHandler = WTFMove(handler);
 }
 
+void ResourceLoadStatisticsStore::setDeletePersistentStoreCallback(WTF::Function<void()>&& handler)
+{
+    m_deletePersistentStoreHandler = WTFMove(handler);
+}
+
 void ResourceLoadStatisticsStore::setFireTelemetryCallback(WTF::Function<void()>&& handler)
 {
     m_fireTelemetryHandler = WTFMove(handler);

Modified: trunk/Source/WebCore/loader/ResourceLoadStatisticsStore.h (218900 => 218901)


--- trunk/Source/WebCore/loader/ResourceLoadStatisticsStore.h	2017-06-28 23:04:38 UTC (rev 218900)
+++ trunk/Source/WebCore/loader/ResourceLoadStatisticsStore.h	2017-06-28 23:21:11 UTC (rev 218901)
@@ -84,6 +84,7 @@
     WEBCORE_EXPORT void setNotificationCallback(WTF::Function<void()>&&);
     WEBCORE_EXPORT void setShouldPartitionCookiesCallback(WTF::Function<void(const Vector<String>& domainsToRemove, const Vector<String>& domainsToAdd, bool clearFirst)>&&);
     WEBCORE_EXPORT void setWritePersistentStoreCallback(WTF::Function<void()>&&);
+    WEBCORE_EXPORT void setDeletePersistentStoreCallback(WTF::Function<void()>&&);
     WEBCORE_EXPORT void setGrandfatherExistingWebsiteDataCallback(WTF::Function<void()>&&);
     WEBCORE_EXPORT void setFireTelemetryCallback(WTF::Function<void()>&& handler);
 
@@ -119,6 +120,7 @@
     WTF::Function<void(const Vector<String>&, const Vector<String>&, bool clearFirst)> m_shouldPartitionCookiesForDomainsHandler;
     WTF::Function<void()> m_writePersistentStoreHandler;
     WTF::Function<void()> m_grandfatherExistingWebsiteDataHandler;
+    WTF::Function<void()> m_deletePersistentStoreHandler;
     WTF::Function<void()> m_fireTelemetryHandler;
 
     WallTime m_endOfGrandfatheringTimestamp;

Added: trunk/Source/WebCore/platform/FileMonitor.cpp (0 => 218901)


--- trunk/Source/WebCore/platform/FileMonitor.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/FileMonitor.cpp	2017-06-28 23:21:11 UTC (rev 218901)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 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 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 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.
+ */
+
+#include "config.h"
+#include "FileMonitor.h"
+
+namespace WebCore {
+
+Ref<FileMonitor> FileMonitor::create(const String& path, Ref<WorkQueue>&& handlerQueue, WTF::Function<void(FileChangeType)>&& modificationHandler)
+{
+    return adoptRef(*new FileMonitor(path, WTFMove(handlerQueue), WTFMove(modificationHandler)));
+}
+    
+FileMonitor::FileMonitor(const String& path, Ref<WorkQueue>&& handlerQueue, WTF::Function<void(FileChangeType)>&& modificationHandler)
+    : m_path(path)
+    , m_modificationHandler(WTFMove(modificationHandler))
+    , m_handlerQueue(WTFMove(handlerQueue))
+{
+}
+    
+FileMonitor::~FileMonitor()
+{
+    stopMonitoring();
+}
+    
+#if !PLATFORM(COCOA)
+void FileMonitor::startMonitoring()
+{
+    // Do Nothing
+}
+    
+void FileMonitor::stopMonitoring()
+{
+    // Do Nothing
+}
+
+#endif
+
+} // namespace WebCore

Added: trunk/Source/WebCore/platform/FileMonitor.h (0 => 218901)


--- trunk/Source/WebCore/platform/FileMonitor.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/FileMonitor.h	2017-06-28 23:21:11 UTC (rev 218901)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017 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. ``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
+ * 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.
+ */
+
+#pragma once
+
+#include <wtf/Function.h>
+#include <wtf/ThreadSafeRefCounted.h>
+#include <wtf/WorkQueue.h>
+#include <wtf/text/WTFString.h>
+
+#if USE(COCOA_EVENT_LOOP)
+#include <dispatch/dispatch.h>
+#include <wtf/DispatchPtr.h>
+#endif
+
+namespace WebCore {
+
+class FileMonitor : public ThreadSafeRefCounted<FileMonitor> {
+public:
+    enum class FileChangeType {
+        Modification,
+        Removal
+    };
+
+    WEBCORE_EXPORT static Ref<FileMonitor> create(const String&, Ref<WorkQueue>&& handlerQueue, WTF::Function<void(FileChangeType)>&& modificationHandler);
+    WEBCORE_EXPORT ~FileMonitor();
+
+    WEBCORE_EXPORT void startMonitoring();
+    WEBCORE_EXPORT void stopMonitoring();
+
+private:
+    FileMonitor(const String&, Ref<WorkQueue>&& handlerQueue, WTF::Function<void(FileChangeType)>&& modificationHandler);
+
+    String m_path;
+    WTF::Function<void(FileChangeType)> m_modificationHandler;
+    Ref<WTF::WorkQueue> m_handlerQueue;
+
+#if USE(COCOA_EVENT_LOOP)
+    DispatchPtr<dispatch_source_t> m_platformMonitor;
+#endif
+};
+
+} // namespace WebCore
+

Modified: trunk/Source/WebCore/platform/FileSystem.h (218900 => 218901)


--- trunk/Source/WebCore/platform/FileSystem.h	2017-06-28 23:04:38 UTC (rev 218900)
+++ trunk/Source/WebCore/platform/FileSystem.h	2017-06-28 23:21:11 UTC (rev 218901)
@@ -28,8 +28,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef FileSystem_h
-#define FileSystem_h
+#pragma once
 
 #include <time.h>
 #include <utility>
@@ -71,7 +70,10 @@
 
 enum FileOpenMode {
     OpenForRead = 0,
-    OpenForWrite
+    OpenForWrite,
+#if OS(DARWIN)
+    OpenForEventsOnly
+#endif
 };
 
 enum FileSeekOrigin {
@@ -131,7 +133,7 @@
 // Returns number of bytes actually read if successful, -1 otherwise.
 WEBCORE_EXPORT int writeToFile(PlatformFileHandle, const char* data, int length);
 // Returns number of bytes actually written if successful, -1 otherwise.
-int readFromFile(PlatformFileHandle, char* data, int length);
+WEBCORE_EXPORT int readFromFile(PlatformFileHandle, char* data, int length);
 
 // Appends the contents of the file found at 'path' to the open PlatformFileHandle.
 // Returns true if the write was successful, false if it was not.
@@ -141,8 +143,8 @@
 bool hardLinkOrCopyFile(const String& source, const String& destination);
 
 #if USE(FILE_LOCK)
-bool lockFile(PlatformFileHandle, FileLockMode);
-bool unlockFile(PlatformFileHandle);
+WEBCORE_EXPORT bool lockFile(PlatformFileHandle, FileLockMode);
+WEBCORE_EXPORT bool unlockFile(PlatformFileHandle);
 #endif
 
 // Encode a string for use within a file name.
@@ -198,4 +200,3 @@
 
 } // namespace WebCore
 
-#endif // FileSystem_h

Modified: trunk/Source/WebCore/platform/Logging.h (218900 => 218901)


--- trunk/Source/WebCore/platform/Logging.h	2017-06-28 23:04:38 UTC (rev 218900)
+++ trunk/Source/WebCore/platform/Logging.h	2017-06-28 23:21:11 UTC (rev 218901)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003, 2006, 2013, 2015, 2016 Apple Inc.  All rights reserved.
+ * Copyright (C) 2003-2017 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -76,6 +76,7 @@
     M(RemoteInspector) \
     M(ResourceLoading) \
     M(ResourceLoadObserver) \
+    M(ResourceLoadStatistics) \
     M(Scrolling) \
     M(Services) \
     M(SpellingAndGrammar) \

Added: trunk/Source/WebCore/platform/cocoa/FileMonitorCocoa.mm (0 => 218901)


--- trunk/Source/WebCore/platform/cocoa/FileMonitorCocoa.mm	                        (rev 0)
+++ trunk/Source/WebCore/platform/cocoa/FileMonitorCocoa.mm	2017-06-28 23:21:11 UTC (rev 218901)
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 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. ``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
+ * 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 "FileMonitor.h"
+
+#import "FileSystem.h"
+#import "Logging.h"
+#import <dispatch/dispatch.h>
+#import <wtf/DispatchPtr.h>
+
+namespace WebCore {
+    
+constexpr unsigned monitorMask = DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_EXTEND | DISPATCH_VNODE_RENAME | DISPATCH_VNODE_REVOKE;
+    
+void FileMonitor::startMonitoring()
+{
+    if (m_platformMonitor)
+        return;
+
+    if (m_path.isEmpty())
+        return;
+
+    if (!m_modificationHandler)
+        return;
+
+    auto handle = openFile(m_path, OpenForEventsOnly);
+    if (handle == invalidPlatformFileHandle) {
+        RELEASE_LOG_ERROR(ResourceLoadStatistics, "Failed to open statistics file for monitoring: %s", m_path.utf8().data());
+        return;
+    }
+
+    m_platformMonitor = adoptDispatch(dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, handle, monitorMask, m_handlerQueue->dispatchQueue()));
+    
+    dispatch_source_set_event_handler(m_platformMonitor.get(), [this, protectedThis = makeRefPtr(this), fileMonitor = m_platformMonitor.get()] () mutable {
+        // If this is getting called after the monitor was cancelled, just drop the notification.
+        if (dispatch_source_testcancel(fileMonitor))
+            return;
+
+        unsigned flag = dispatch_source_get_data(fileMonitor);
+        if (flag & DISPATCH_VNODE_DELETE) {
+            m_modificationHandler(FileChangeType::Removal);
+            dispatch_source_cancel(fileMonitor);
+        } else
+            m_modificationHandler(FileChangeType::Modification);
+    });
+    
+    dispatch_source_set_cancel_handler(m_platformMonitor.get(), [fileMonitor = m_platformMonitor.get()] {
+        auto handle = static_cast<PlatformFileHandle>(dispatch_source_get_handle(fileMonitor));
+        closeFile(handle);
+    });
+    
+    dispatch_resume(m_platformMonitor.get());
+}
+    
+void FileMonitor::stopMonitoring()
+{
+    if (!m_platformMonitor)
+        return;
+    
+    dispatch_source_cancel(m_platformMonitor.get());
+    m_platformMonitor = nullptr;
+}
+
+} // namespace WebCore

Modified: trunk/Source/WebCore/platform/posix/FileSystemPOSIX.cpp (218900 => 218901)


--- trunk/Source/WebCore/platform/posix/FileSystemPOSIX.cpp	2017-06-28 23:04:38 UTC (rev 218900)
+++ trunk/Source/WebCore/platform/posix/FileSystemPOSIX.cpp	2017-06-28 23:21:11 UTC (rev 218901)
@@ -83,6 +83,11 @@
         platformFlag |= O_RDONLY;
     else if (mode == OpenForWrite)
         platformFlag |= (O_WRONLY | O_CREAT | O_TRUNC);
+#if OS(DARWIN)
+    else if (mode == OpenForEventsOnly)
+        platformFlag |= O_EVTONLY;
+#endif
+
     return open(fsRep.data(), platformFlag, 0666);
 }
 

Modified: trunk/Source/WebKit2/ChangeLog (218900 => 218901)


--- trunk/Source/WebKit2/ChangeLog	2017-06-28 23:04:38 UTC (rev 218900)
+++ trunk/Source/WebKit2/ChangeLog	2017-06-28 23:21:11 UTC (rev 218901)
@@ -1,3 +1,39 @@
+2017-06-28  Brent Fulgham  <bfulg...@apple.com>
+
+        Teach ResourceLoadStatistics to recognize changes in the file system
+        https://bugs.webkit.org/show_bug.cgi?id=173800
+        <rdar://problem/32937842>
+
+        Reviewed by Chris Dumez.
+
+        We want to support the case where multiple UI processes choose to share the same
+        statistics file. To support this, update the ResourceLoadStatistics logic to be aware
+        that the statistics data file might change underneath it, and to take appropriate
+        action when it does.
+
+        * UIProcess/WebResourceLoadStatisticsStore.cpp:
+        (WebKit::WebResourceLoadStatisticsStore::setResourceLoadStatisticsEnabled): When we enable
+        the statistics, read in the data and then watch for changes.
+        (WebKit::WebResourceLoadStatisticsStore::registerSharedResourceLoadObserver): Add a
+        'delete data' handler to remove the file on disk, not just write an empty store.
+        (WebKit::WebResourceLoadStatisticsStore::readDataFromDiskIfNeeded): Use ASCIILiteral.
+        (WebKit::WebResourceLoadStatisticsStore::refreshFromDisk): Convenience function.
+        (WebKit::WebResourceLoadStatisticsStore::writeStoreToDisk): Sync with any on-disk
+        storage before writing out.
+        (WebKit::openAndLockFile): Convenience function.
+        (WebKit::closeAndUnlockFile): Ditto.
+        (WebKit::WebResourceLoadStatisticsStore::writeEncoderToDisk): Revise to lock file (on
+        platforms that support it) before writing to disk.
+        (WebKit::WebResourceLoadStatisticsStore::deleteStoreFromDisk): Added convenience function.
+        (WebKit::WebResourceLoadStatisticsStore::clearInMemoryData): Ditto.
+        (WebKit::WebResourceLoadStatisticsStore::startMonitoringStatisticsStorage): Create a
+        file system monitor to watch for file changes.
+        (WebKit::WebResourceLoadStatisticsStore::syncWithExistingStatisticsStorageIfNeeded): Added
+        convenience function.
+        (WebKit::WebResourceLoadStatisticsStore::createDecoderFromDisk): Revise to read data
+        directly so we can control file locking.
+        * UIProcess/WebResourceLoadStatisticsStore.h:
+
  2017-06-28  Wenson Hsieh  <wenson_hs...@apple.com>
 
         Followup to r218885: adjust for further UIKit SPI changes

Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheData.h (218900 => 218901)


--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheData.h	2017-06-28 23:04:38 UTC (rev 218900)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheData.h	2017-06-28 23:21:11 UTC (rev 218901)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,6 +33,10 @@
 #include <wtf/ThreadSafeRefCounted.h>
 #include <wtf/text/WTFString.h>
 
+#if PLATFORM(COCOA)
+#include <wtf/DispatchPtr.h>
+#endif
+
 #if USE(SOUP)
 #include <WebCore/GRefPtrSoup.h>
 #endif
@@ -43,63 +47,6 @@
 
 namespace NetworkCache {
 
-#if PLATFORM(COCOA)
-template <typename T> class DispatchPtr;
-template <typename T> DispatchPtr<T> adoptDispatch(T dispatchObject);
-
-// FIXME: Use OSObjectPtr instead when it works with dispatch_data_t on all platforms.
-template<typename T> class DispatchPtr {
-public:
-    DispatchPtr()
-        : m_ptr(nullptr)
-    {
-    }
-    explicit DispatchPtr(T ptr)
-        : m_ptr(ptr)
-    {
-        if (m_ptr)
-            dispatch_retain(m_ptr);
-    }
-    DispatchPtr(const DispatchPtr& other)
-        : m_ptr(other.m_ptr)
-    {
-        if (m_ptr)
-            dispatch_retain(m_ptr);
-    }
-    ~DispatchPtr()
-    {
-        if (m_ptr)
-            dispatch_release(m_ptr);
-    }
-
-    DispatchPtr& operator=(const DispatchPtr& other)
-    {
-        auto copy = other;
-        std::swap(m_ptr, copy.m_ptr);
-        return *this;
-    }
-
-    T get() const { return m_ptr; }
-    explicit operator bool() const { return m_ptr; }
-
-    friend DispatchPtr adoptDispatch<T>(T);
-
-private:
-    struct Adopt { };
-    DispatchPtr(Adopt, T data)
-        : m_ptr(data)
-    {
-    }
-
-    T m_ptr;
-};
-
-template <typename T> DispatchPtr<T> adoptDispatch(T dispatchObject)
-{
-    return DispatchPtr<T>(typename DispatchPtr<T>::Adopt { }, dispatchObject);
-}
-#endif
-
 class Data {
 public:
     Data() { }

Modified: trunk/Source/WebKit2/UIProcess/WebResourceLoadStatisticsStore.cpp (218900 => 218901)


--- trunk/Source/WebKit2/UIProcess/WebResourceLoadStatisticsStore.cpp	2017-06-28 23:04:38 UTC (rev 218900)
+++ trunk/Source/WebKit2/UIProcess/WebResourceLoadStatisticsStore.cpp	2017-06-28 23:21:11 UTC (rev 218901)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "WebResourceLoadStatisticsStore.h"
 
+#include "Logging.h"
 #include "WebProcessMessages.h"
 #include "WebProcessPool.h"
 #include "WebProcessProxy.h"
@@ -33,6 +34,8 @@
 #include "WebResourceLoadStatisticsStoreMessages.h"
 #include "WebsiteDataFetchOption.h"
 #include "WebsiteDataType.h"
+#include <WebCore/FileMonitor.h>
+#include <WebCore/FileSystem.h>
 #include <WebCore/KeyedCoding.h>
 #include <WebCore/ResourceLoadObserver.h>
 #include <WebCore/ResourceLoadStatistics.h>
@@ -43,6 +46,10 @@
 #include <wtf/Seconds.h>
 #include <wtf/threads/BinarySemaphore.h>
 
+#if PLATFORM(COCOA)
+#define ENABLE_MULTIPROCESS_ACCESS_TO_STATISTICS_STORE 1
+#endif
+
 using namespace WebCore;
 
 namespace WebKit {
@@ -150,8 +157,12 @@
                 WebProcessProxy::notifyPageStatisticsAndDataRecordsProcessed();
             });
         }
-            
+
+        stopMonitoringStatisticsStorage();
+
         writeStoreToDisk();
+
+        startMonitoringStatisticsStorage();
     });
 }
 
@@ -166,12 +177,20 @@
 
 void WebResourceLoadStatisticsStore::setResourceLoadStatisticsEnabled(bool enabled)
 {
+    ASSERT(RunLoop::isMain());
+
     if (enabled == m_resourceLoadStatisticsEnabled)
         return;
 
     m_resourceLoadStatisticsEnabled = enabled;
 
-    readDataFromDiskIfNeeded();
+    if (m_resourceLoadStatisticsEnabled) {
+        readDataFromDiskIfNeeded();
+        m_statisticsQueue->dispatch([this, protectedThis = makeRef(*this)] () {
+            startMonitoringStatisticsStorage();
+        });
+    } else
+        m_statisticsQueue->dispatch([statisticsStorageMonitor = WTFMove(m_statisticsStorageMonitor)]  { });
 }
 
 bool WebResourceLoadStatisticsStore::resourceLoadStatisticsEnabled() const
@@ -198,6 +217,11 @@
     m_resourceLoadStatisticsStore->setGrandfatherExistingWebsiteDataCallback([this, protectedThis = makeRef(*this)]() {
         grandfatherExistingWebsiteData();
     });
+    m_resourceLoadStatisticsStore->setDeletePersistentStoreCallback([this, protectedThis = makeRef(*this)] {
+        m_statisticsQueue->dispatch([this, protectedThis = protectedThis.copyRef()] {
+            deleteStoreFromDisk();
+        });
+    });
     m_resourceLoadStatisticsStore->setFireTelemetryCallback([this, protectedThis = makeRef(*this)]() {
         // This cancels the one shot timer and is only intended for testing purposes.
         m_telemetryOneShotTimer.startOneShot(100_ms);
@@ -239,7 +263,7 @@
         return;
 
     m_statisticsQueue->dispatch([this, protectedThis = makeRef(*this)] {
-        auto decoder = createDecoderFromDisk("full_browsing_session");
+        auto decoder = createDecoderFromDisk(ASCIILiteral("full_browsing_session"));
         if (!decoder) {
             grandfatherExistingWebsiteData();
             return;
@@ -253,7 +277,18 @@
             grandfatherExistingWebsiteData();
     });
 }
+    
+void WebResourceLoadStatisticsStore::refreshFromDisk()
+{
+    ASSERT(!RunLoop::isMain());
+    auto decoder = createDecoderFromDisk(ASCIILiteral("full_browsing_session"));
+    if (!decoder)
+        return;
 
+    auto locker = holdLock(coreStore().statisticsLock());
+    coreStore().readDataFromDecoder(*decoder);
+}
+    
 void WebResourceLoadStatisticsStore::processWillOpenConnection(WebProcessProxy&, IPC::Connection& connection)
 {
     connection.addWorkQueueMessageReceiver(Messages::WebResourceLoadStatisticsStore::messageReceiverName(), m_statisticsQueue.get(), this);
@@ -287,10 +322,37 @@
 {
     ASSERT(!RunLoop::isMain());
     
+    syncWithExistingStatisticsStorageIfNeeded();
+
     auto encoder = coreStore().createEncoderFromData();
     writeEncoderToDisk(*encoder.get(), "full_browsing_session");
 }
 
+static PlatformFileHandle openAndLockFile(const String& path, FileOpenMode mode)
+{
+    ASSERT(!RunLoop::isMain());
+    auto handle = openFile(path, mode);
+    if (handle == invalidPlatformFileHandle)
+        return invalidPlatformFileHandle;
+
+#if ENABLE(MULTIPROCESS_ACCESS_TO_STATISTICS_STORE)
+    bool locked = lockFile(handle, WebCore::LockExclusive);
+    ASSERT_UNUSED(locked, locked);
+#endif
+
+    return handle;
+}
+
+static void closeAndUnlockFile(PlatformFileHandle handle)
+{
+    ASSERT(!RunLoop::isMain());
+#if ENABLE(MULTIPROCESS_ACCESS_TO_STATISTICS_STORE)
+    bool unlocked = unlockFile(handle);
+    ASSERT_UNUSED(unlocked, unlocked);
+#endif
+    closeFile(handle);
+}
+
 void WebResourceLoadStatisticsStore::writeEncoderToDisk(KeyedEncoder& encoder, const String& label) const
 {
     ASSERT(!RunLoop::isMain());
@@ -308,17 +370,83 @@
         platformExcludeFromBackup();
     }
 
-    auto handle = openFile(resourceLog, OpenForWrite);
-    if (!handle)
+    auto handle = openAndLockFile(resourceLog, OpenForWrite);
+    if (handle == invalidPlatformFileHandle)
         return;
     
     int64_t writtenBytes = writeToFile(handle, rawData->data(), rawData->size());
-    closeFile(handle);
+    closeAndUnlockFile(handle);
 
     if (writtenBytes != static_cast<int64_t>(rawData->size()))
-        WTFLogAlways("WebResourceLoadStatisticsStore: We only wrote %d out of %d bytes to disk", static_cast<unsigned>(writtenBytes), rawData->size());
+        RELEASE_LOG_ERROR(ResourceLoadStatistics, "WebResourceLoadStatisticsStore: We only wrote %d out of %d bytes to disk", static_cast<unsigned>(writtenBytes), rawData->size());
 }
 
+void WebResourceLoadStatisticsStore::deleteStoreFromDisk()
+{
+    ASSERT(!RunLoop::isMain());
+    String resourceLogPath = persistentStoragePath(ASCIILiteral("full_browsing_session"));
+    if (resourceLogPath.isEmpty())
+        return;
+
+    stopMonitoringStatisticsStorage();
+
+    if (!deleteFile(resourceLogPath))
+        RELEASE_LOG_ERROR(ResourceLoadStatistics, "Unable to delete statistics file: %s", resourceLogPath.utf8().data());
+}
+
+void WebResourceLoadStatisticsStore::clearInMemoryData()
+{
+    auto locker = holdLock(coreStore().statisticsLock());
+    coreStore().clearInMemory();
+}
+
+void WebResourceLoadStatisticsStore::startMonitoringStatisticsStorage()
+{
+    ASSERT(!RunLoop::isMain());
+    if (m_statisticsStorageMonitor)
+        return;
+    
+    String resourceLogPath = persistentStoragePath(ASCIILiteral("full_browsing_session"));
+    if (resourceLogPath.isEmpty())
+        return;
+    
+    m_statisticsStorageMonitor = FileMonitor::create(resourceLogPath, m_statisticsQueue.copyRef(), [this] (FileMonitor::FileChangeType type) {
+        ASSERT(!RunLoop::isMain());
+        switch (type) {
+        case FileMonitor::FileChangeType::Modification:
+            refreshFromDisk();
+            break;
+        case FileMonitor::FileChangeType::Removal:
+            clearInMemoryData();
+            m_statisticsStorageMonitor = nullptr;
+            break;
+        }
+    });
+
+    m_statisticsStorageMonitor->startMonitoring();
+}
+
+void WebResourceLoadStatisticsStore::stopMonitoringStatisticsStorage()
+{
+    ASSERT(!RunLoop::isMain());
+    if (!m_statisticsStorageMonitor)
+        return;
+
+    m_statisticsStorageMonitor = nullptr;
+}
+
+void WebResourceLoadStatisticsStore::syncWithExistingStatisticsStorageIfNeeded()
+{
+    ASSERT(!RunLoop::isMain());
+    if (m_statisticsStorageMonitor)
+        return;
+    
+    refreshFromDisk();
+    
+    startMonitoringStatisticsStorage();
+}
+    
+    
 #if !PLATFORM(COCOA)
 void WebResourceLoadStatisticsStore::platformExcludeFromBackup() const
 {
@@ -328,15 +456,36 @@
 
 std::unique_ptr<KeyedDecoder> WebResourceLoadStatisticsStore::createDecoderFromDisk(const String& label) const
 {
+    ASSERT(!RunLoop::isMain());
     String resourceLog = persistentStoragePath(label);
     if (resourceLog.isEmpty())
         return nullptr;
 
-    RefPtr<SharedBuffer> rawData = SharedBuffer::createWithContentsOfFile(resourceLog);
-    if (!rawData)
+    auto handle = openAndLockFile(resourceLog, OpenForRead);
+    if (handle == invalidPlatformFileHandle)
         return nullptr;
+    
+    long long fileSize = 0;
+    if (!getFileSize(handle, fileSize)) {
+        closeAndUnlockFile(handle);
+        return nullptr;
+    }
+    
+    size_t bytesToRead;
+    if (!WTF::convertSafely(fileSize, bytesToRead)) {
+        closeAndUnlockFile(handle);
+        return nullptr;
+    }
 
-    return KeyedDecoder::decoder(reinterpret_cast<const uint8_t*>(rawData->data()), rawData->size());
+    Vector<char> buffer(bytesToRead);
+    size_t totalBytesRead = readFromFile(handle, buffer.data(), buffer.size());
+
+    closeAndUnlockFile(handle);
+
+    if (totalBytesRead != bytesToRead)
+        return nullptr;
+
+    return KeyedDecoder::decoder(reinterpret_cast<const uint8_t*>(buffer.data()), buffer.size());
 }
 
 void WebResourceLoadStatisticsStore::telemetryTimerFired()

Modified: trunk/Source/WebKit2/UIProcess/WebResourceLoadStatisticsStore.h (218900 => 218901)


--- trunk/Source/WebKit2/UIProcess/WebResourceLoadStatisticsStore.h	2017-06-28 23:04:38 UTC (rev 218900)
+++ trunk/Source/WebKit2/UIProcess/WebResourceLoadStatisticsStore.h	2017-06-28 23:21:11 UTC (rev 218901)
@@ -46,6 +46,7 @@
 namespace WebCore {
 class KeyedDecoder;
 class KeyedEncoder;
+class FileMonitor;
 struct ResourceLoadStatistics;
 }
 
@@ -85,6 +86,8 @@
 
     void classifyResource(WebCore::ResourceLoadStatistics&);
     void removeDataRecords();
+    void startMonitoringStatisticsStorage();
+    void stopMonitoringStatisticsStorage();
 
     String persistentStoragePath(const String& label) const;
 
@@ -97,7 +100,10 @@
     void writeEncoderToDisk(WebCore::KeyedEncoder&, const String& label) const;
     std::unique_ptr<WebCore::KeyedDecoder> createDecoderFromDisk(const String& label) const;
     void platformExcludeFromBackup() const;
-    
+    void deleteStoreFromDisk();
+    void clearInMemoryData();
+    void syncWithExistingStatisticsStorageIfNeeded();
+    void refreshFromDisk();
     void telemetryTimerFired();
 
     Ref<WebCore::ResourceLoadStatisticsStore> m_resourceLoadStatisticsStore;
@@ -107,6 +113,7 @@
     ResourceLoadStatisticsClassifier m_resourceLoadStatisticsClassifier;
 #endif
     Ref<WTF::WorkQueue> m_statisticsQueue;
+    RefPtr<WebCore::FileMonitor> m_statisticsStorageMonitor;
     String m_statisticsStoragePath;
     bool m_resourceLoadStatisticsEnabled { false };
     RunLoop::Timer<WebResourceLoadStatisticsStore> m_telemetryOneShotTimer;

Modified: trunk/Tools/ChangeLog (218900 => 218901)


--- trunk/Tools/ChangeLog	2017-06-28 23:04:38 UTC (rev 218900)
+++ trunk/Tools/ChangeLog	2017-06-28 23:21:11 UTC (rev 218901)
@@ -1,3 +1,19 @@
+2017-06-28  Brent Fulgham  <bfulg...@apple.com>
+
+        Teach ResourceLoadStatistics to recognize changes in the file system
+        https://bugs.webkit.org/show_bug.cgi?id=173800
+        <rdar://problem/32937842>
+
+        Reviewed by Chris Dumez.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebCore/FileMonitor.cpp: Added.
+        (TestWebKitAPI::FileMonitorTest::tempFilePath):
+        (TestWebKitAPI::handleFileModification):
+        (TestWebKitAPI::handleFileDeletion):
+        (TestWebKitAPI::resetTestState):
+        (TestWebKitAPI::TEST_F):
+
 2017-06-28  Brady Eidson  <beid...@apple.com>
 
         DocumentLoader should always notify the client if there are pending icon loads when the load is stopped.

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (218900 => 218901)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-06-28 23:04:38 UTC (rev 218900)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-06-28 23:21:11 UTC (rev 218901)
@@ -231,6 +231,7 @@
 		7A010BCB1D877C0500EDE72A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A010BCA1D877C0500EDE72A /* CoreGraphics.framework */; };
 		7A010BCD1D877C0D00EDE72A /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A010BCC1D877C0D00EDE72A /* QuartzCore.framework */; };
 		7A1458FC1AD5C07000E06772 /* mouse-button-listener.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 7A1458FB1AD5C03500E06772 /* mouse-button-listener.html */; };
+		7A32D74A1F02151500162C44 /* FileMonitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A32D7491F02151500162C44 /* FileMonitor.cpp */; };
 		7A66BDB61EAF14EF00CCC924 /* LimitTitleSize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A66BDB51EAF14D000CCC924 /* LimitTitleSize.cpp */; };
 		7A66BDB81EAF18D500CCC924 /* set-long-title.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 7A66BDB71EAF150100CCC924 /* set-long-title.html */; };
 		7A6A2C701DCCFA8C00C0D085 /* LocalStorageQuirkTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7A6A2C6F1DCCF87B00C0D085 /* LocalStorageQuirkTest.mm */; };
@@ -1260,6 +1261,7 @@
 		7A010BCA1D877C0500EDE72A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
 		7A010BCC1D877C0D00EDE72A /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
 		7A1458FB1AD5C03500E06772 /* mouse-button-listener.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "mouse-button-listener.html"; sourceTree = "<group>"; };
+		7A32D7491F02151500162C44 /* FileMonitor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FileMonitor.cpp; sourceTree = "<group>"; };
 		7A38D7E51C752D5F004F157D /* HashCountedSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HashCountedSet.cpp; sourceTree = "<group>"; };
 		7A5623101AD5AF3E0096B920 /* MenuTypesForMouseEvents.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MenuTypesForMouseEvents.cpp; sourceTree = "<group>"; };
 		7A66BDB51EAF14D000CCC924 /* LimitTitleSize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LimitTitleSize.cpp; sourceTree = "<group>"; };
@@ -1929,6 +1931,7 @@
 				260BA57A1B1D2EE2004FA07C /* DFAHelpers.h */,
 				26F6E1EF1ADC749B00DE696B /* DFAMinimizer.cpp */,
 				3151180F1DB1ADD500176304 /* ExtendedColor.cpp */,
+				7A32D7491F02151500162C44 /* FileMonitor.cpp */,
 				41973B5A1AF2286A006C7B36 /* FileSystem.cpp */,
 				7A909A701D877475007E10F8 /* FloatPoint.cpp */,
 				7A909A711D877475007E10F8 /* FloatRect.cpp */,
@@ -3024,6 +3027,7 @@
 				7CCE7EF71A411AE600447C4C /* FrameMIMETypePNG.cpp in Sources */,
 				CD78E11D1DB7EA660014A2DE /* FullscreenDelegate.mm in Sources */,
 				7C83E0BD1D0A650C00FEBCF3 /* FullscreenTopContentInset.mm in Sources */,
+				7A32D74A1F02151500162C44 /* FileMonitor.cpp in Sources */,
 				CDBFCC451A9FF45300A7B691 /* FullscreenZoomInitialFrame.mm in Sources */,
 				7CCE7EF81A411AE600447C4C /* Geolocation.cpp in Sources */,
 				631EFFF61E7B5E8D00D2EBB8 /* Geolocation.mm in Sources */,

Added: trunk/Tools/TestWebKitAPI/Tests/WebCore/FileMonitor.cpp (0 => 218901)


--- trunk/Tools/TestWebKitAPI/Tests/WebCore/FileMonitor.cpp	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/FileMonitor.cpp	2017-06-28 23:21:11 UTC (rev 218901)
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2017 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 "Test.h"
+#import "WTFStringUtilities.h"
+#import <WebCore/FileMonitor.h>
+#import <WebCore/FileSystem.h>
+#import <WebCore/ScopeGuard.h>
+#import <wtf/MainThread.h>
+#import <wtf/RunLoop.h>
+#import <wtf/StringExtras.h>
+#import <wtf/WorkQueue.h>
+#import <wtf/text/StringBuffer.h>
+
+// Note: Currently, only a Cocoa implementation exists. This could probably be supported under GTK using g_file_monitor_file
+#if PLATFORM(COCOA)
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+    
+const String FileMonitorTestData("This is a test");
+const String FileMonitorRevisedData("This is some changed text for the test");
+const String FileMonitorSecondRevisedData("This is some changed text for the test");
+
+class FileMonitorTest : public testing::Test {
+public:
+    void SetUp() override
+    {
+        RunLoop::initializeMainRunLoop();
+        
+        // create temp file
+        PlatformFileHandle handle;
+        m_tempFilePath = openTemporaryFile("tempTestFile", handle);
+        ASSERT_NE(handle, invalidPlatformFileHandle);
+        
+        int rc = writeToFile(handle, FileMonitorTestData.utf8().data(), FileMonitorTestData.length());
+        ASSERT_NE(rc, -1);
+        
+        closeFile(handle);
+    }
+    
+    void TearDown() override
+    {
+        deleteFile(m_tempFilePath);
+    }
+    
+    const String& tempFilePath() { return m_tempFilePath; }
+    
+private:
+    String m_tempFilePath;
+};
+    
+static bool observedFileModification = false;
+static bool observedFileDeletion = false;
+static bool didFinish = false;
+    
+static void handleFileModification()
+{
+    observedFileModification = true;
+    didFinish = true;
+}
+    
+static void handleFileDeletion()
+{
+    observedFileDeletion = true;
+    didFinish = true;
+}
+    
+static void resetTestState()
+{
+    observedFileModification = false;
+    observedFileDeletion = false;
+    didFinish = false;
+}
+
+static String createCommand(const String& path, const String& payload)
+{
+    StringBuilder command;
+    command.appendLiteral("echo \"");
+    command.append(payload);
+    command.appendLiteral("\" > ");
+    command.append(path);
+
+    return command.toString();
+}
+
+static String readContentsOfFile(const String& path)
+{
+    constexpr int bufferSize = 1024;
+
+    auto source = openFile(path, OpenForRead);
+    if (!isHandleValid(source))
+        return emptyString();
+
+    StringBuffer<LChar> buffer(bufferSize);
+
+    ScopeGuard fileCloser([source]() {
+        PlatformFileHandle handle = source;
+        closeFile(handle);
+    });
+
+    // Since we control the test files, we know we only need one read
+    int readBytes = readFromFile(source, reinterpret_cast<char*>(buffer.characters()), bufferSize);
+    if (readBytes < 0)
+        return emptyString();
+
+    // Strip the trailing carriage return from the file:
+    if (readBytes > 1) {
+        int lastByte = readBytes - 1;
+        if (buffer[lastByte] == '\n')
+            buffer.shrink(lastByte);
+    }
+    ASSERT(readBytes < bufferSize);
+    return String::adopt(WTFMove(buffer));
+}
+
+TEST_F(FileMonitorTest, DetectChange)
+{
+    EXPECT_TRUE(fileExists(tempFilePath()));
+
+    RunLoop::initializeMainRunLoop();
+
+    auto testQueue = WorkQueue::create("Test Work Queue");
+
+    auto monitor = WebCore::FileMonitor::create(tempFilePath(), testQueue.copyRef(), [this] (WebCore::FileMonitor::FileChangeType type) {
+        ASSERT(!RunLoop::isMain());
+        switch (type) {
+        case FileMonitor::FileChangeType::Modification:
+            handleFileModification();
+            break;
+        case FileMonitor::FileChangeType::Removal:
+            handleFileDeletion();
+            break;
+        }
+    });
+    monitor->startMonitoring();
+
+    testQueue->dispatch([this] () mutable {
+        String fileContents = readContentsOfFile(tempFilePath());
+        EXPECT_STREQ(FileMonitorTestData.utf8().data(), fileContents.utf8().data());
+
+        auto command = createCommand(tempFilePath(), FileMonitorRevisedData);
+        auto rc = system(command.utf8().data());
+        ASSERT_NE(rc, -1);
+        if (rc == -1)
+            didFinish = true;
+    });
+
+    Util::run(&didFinish);
+
+    EXPECT_TRUE(observedFileModification);
+    EXPECT_FALSE(observedFileDeletion);
+
+    String revisedFileContents = readContentsOfFile(tempFilePath());
+    EXPECT_STREQ(FileMonitorRevisedData.utf8().data(), revisedFileContents.utf8().data());
+
+    resetTestState();
+}
+
+TEST_F(FileMonitorTest, DetectMultipleChanges)
+{
+    EXPECT_TRUE(fileExists(tempFilePath()));
+
+    RunLoop::initializeMainRunLoop();
+
+    auto testQueue = WorkQueue::create("Test Work Queue");
+
+    auto monitor = WebCore::FileMonitor::create(tempFilePath(), testQueue.copyRef(), [this] (WebCore::FileMonitor::FileChangeType type) {
+        ASSERT(!RunLoop::isMain());
+        switch (type) {
+        case FileMonitor::FileChangeType::Modification:
+            handleFileModification();
+            break;
+        case FileMonitor::FileChangeType::Removal:
+            handleFileDeletion();
+            break;
+        }
+    });
+    monitor->startMonitoring();
+    
+    testQueue->dispatch([this] () mutable {
+        String fileContents = readContentsOfFile(tempFilePath());
+        EXPECT_STREQ(FileMonitorTestData.utf8().data(), fileContents.utf8().data());
+
+        auto firstCommand = createCommand(tempFilePath(), FileMonitorRevisedData);
+        auto rc = system(firstCommand.utf8().data());
+        ASSERT_NE(rc, -1);
+        if (rc == -1)
+            didFinish = true;
+    });
+
+    Util::run(&didFinish);
+
+    EXPECT_TRUE(observedFileModification);
+    EXPECT_FALSE(observedFileDeletion);
+
+    String revisedFileContents = readContentsOfFile(tempFilePath());
+    EXPECT_STREQ(FileMonitorRevisedData.utf8().data(), revisedFileContents.utf8().data());
+
+    resetTestState();
+
+    testQueue->dispatch([this] () mutable {
+        auto secondCommand = createCommand(tempFilePath(), FileMonitorSecondRevisedData);
+        auto rc = system(secondCommand.utf8().data());
+        ASSERT_NE(rc, -1);
+        if (rc == -1)
+            didFinish = true;
+    });
+
+    Util::run(&didFinish);
+
+    EXPECT_TRUE(observedFileModification);
+    EXPECT_FALSE(observedFileDeletion);
+
+    String secondRevisedfileContents = readContentsOfFile(tempFilePath());
+    EXPECT_STREQ(FileMonitorSecondRevisedData.utf8().data(), secondRevisedfileContents.utf8().data());
+
+    resetTestState();
+}
+
+TEST_F(FileMonitorTest, DetectDeletion)
+{
+    EXPECT_TRUE(fileExists(tempFilePath()));
+
+    RunLoop::initializeMainRunLoop();
+
+    auto testQueue = WorkQueue::create("Test Work Queue");
+
+    auto monitor = WebCore::FileMonitor::create(tempFilePath(), testQueue.copyRef(), [this] (WebCore::FileMonitor::FileChangeType type) {
+        ASSERT(!RunLoop::isMain());
+        switch (type) {
+        case FileMonitor::FileChangeType::Modification:
+            handleFileModification();
+            break;
+        case FileMonitor::FileChangeType::Removal:
+            handleFileDeletion();
+            break;
+        }
+    });
+    monitor->startMonitoring();
+
+    testQueue->dispatch([this] () mutable {
+        StringBuilder command;
+        command.appendLiteral("rm -f ");
+        command.append(tempFilePath());
+
+        auto rc = system(command.toString().utf8().data());
+        ASSERT_NE(rc, -1);
+        if (rc == -1)
+            didFinish = true;
+    });
+
+    Util::run(&didFinish);
+
+    EXPECT_FALSE(observedFileModification);
+    EXPECT_TRUE(observedFileDeletion);
+
+    resetTestState();
+}
+
+TEST_F(FileMonitorTest, DetectChangeAndThenDelete)
+{
+    EXPECT_TRUE(fileExists(tempFilePath()));
+
+    RunLoop::initializeMainRunLoop();
+
+    auto testQueue = WorkQueue::create("Test Work Queue");
+
+    auto monitor = WebCore::FileMonitor::create(tempFilePath(), testQueue.copyRef(), [this] (WebCore::FileMonitor::FileChangeType type) {
+        ASSERT(!RunLoop::isMain());
+        switch (type) {
+            case FileMonitor::FileChangeType::Modification:
+                handleFileModification();
+                break;
+            case FileMonitor::FileChangeType::Removal:
+                handleFileDeletion();
+                break;
+        }
+    });
+    monitor->startMonitoring();
+
+    testQueue->dispatch([this] () mutable {
+        String fileContents = readContentsOfFile(tempFilePath());
+        EXPECT_STREQ(FileMonitorTestData.utf8().data(), fileContents.utf8().data());
+
+        auto firstCommand = createCommand(tempFilePath(), FileMonitorRevisedData);
+        auto rc = system(firstCommand.utf8().data());
+        ASSERT_NE(rc, -1);
+        if (rc == -1)
+            didFinish = true;
+    });
+
+    Util::run(&didFinish);
+
+    EXPECT_TRUE(observedFileModification);
+    EXPECT_FALSE(observedFileDeletion);
+
+    resetTestState();
+
+    testQueue->dispatch([this] () mutable {
+        StringBuilder command;
+        command.appendLiteral("rm -f ");
+        command.append(tempFilePath());
+
+        auto rc = system(command.toString().utf8().data());
+        ASSERT_NE(rc, -1);
+        if (rc == -1)
+            didFinish = true;
+    });
+
+    Util::run(&didFinish);
+
+    EXPECT_FALSE(observedFileModification);
+    EXPECT_TRUE(observedFileDeletion);
+
+    resetTestState();
+}
+
+TEST_F(FileMonitorTest, DetectDeleteButNotSubsequentChange)
+{
+    EXPECT_TRUE(fileExists(tempFilePath()));
+
+    RunLoop::initializeMainRunLoop();
+
+    auto testQueue = WorkQueue::create("Test Work Queue");
+
+    auto monitor = WebCore::FileMonitor::create(tempFilePath(), testQueue.copyRef(), [this] (WebCore::FileMonitor::FileChangeType type) {
+        ASSERT(!RunLoop::isMain());
+        switch (type) {
+            case FileMonitor::FileChangeType::Modification:
+                handleFileModification();
+                break;
+            case FileMonitor::FileChangeType::Removal:
+                handleFileDeletion();
+                break;
+        }
+    });
+    monitor->startMonitoring();
+
+    testQueue->dispatch([this] () mutable {
+        StringBuilder command;
+        command.appendLiteral("rm -f ");
+        command.append(tempFilePath());
+
+        auto rc = system(command.toString().utf8().data());
+        ASSERT_NE(rc, -1);
+        if (rc == -1)
+            didFinish = true;
+    });
+
+    Util::run(&didFinish);
+
+    EXPECT_FALSE(observedFileModification);
+    EXPECT_TRUE(observedFileDeletion);
+
+    resetTestState();
+
+    testQueue->dispatch([this] () mutable {
+        EXPECT_FALSE(fileExists(tempFilePath()));
+
+        auto handle = openFile(tempFilePath(), OpenForWrite);
+        ASSERT_NE(handle, invalidPlatformFileHandle);
+
+        int rc = writeToFile(handle, FileMonitorTestData.utf8().data(), FileMonitorTestData.length());
+        ASSERT_NE(rc, -1);
+
+        auto firstCommand = createCommand(tempFilePath(), FileMonitorRevisedData);
+        rc = system(firstCommand.utf8().data());
+        ASSERT_NE(rc, -1);
+        if (rc == -1)
+            didFinish = true;
+    });
+
+    // Set a timer to end the test, since we do not expect the file modification
+    // to be observed.
+    testQueue->dispatchAfter(500_ms, [&](void) {
+        EXPECT_FALSE(observedFileModification);
+        EXPECT_FALSE(observedFileDeletion);
+        didFinish = true;
+    });
+
+    Util::run(&didFinish);
+
+    EXPECT_FALSE(observedFileModification);
+    EXPECT_FALSE(observedFileDeletion);
+
+    resetTestState();
+}
+
+}
+
+#endif
+
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to