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
+