Title: [282632] trunk
Revision
282632
Author
[email protected]
Date
2021-09-16 21:18:09 -0700 (Thu, 16 Sep 2021)

Log Message

WebKit::WebProcessPool should use a weak observer with CFNotificationCenter
<https://webkit.org/b/230227>
<rdar://problem/83067708>

Reviewed by Darin Adler.

Source/WebKit:

To fix the bug, implement an Objective-C class named
WKProcessPoolWeakObserver which contains an instance variable
holding a WeakPtr<WebProcessPool>, and tell CFNotificationCenter
to hold a weak reference to WKProcessPoolWeakObserver.

Since WKProcessPoolWeakObserver is self-contained within the
source file, it uses the NS_DIRECT_MEMBERS attribute since it
does not require the overhead of dynamic Objective-C method
dispatch.

* UIProcess/Cocoa/WebProcessPoolCocoa.mm:
(-[WKProcessPoolWeakObserver initWithWeakPtr:]): Add.
(-[WKProcessPoolWeakObserver pool]): Add.
- Implement WKProcessPoolWeakObserver class.
- Note that init methods can never be marked as NS_DIRECT, and
  @property statements can't use NS_DIRECT in their declaration,
  so the @property is declared in a category which uses
  NS_DIRECT_MEMBERS.
(WebKit::extractWebProcessPool): Add.
- Static helper method for extracting RefPtr<WebProcessPool>
  from type-punned WKProcessPoolWeakObserver.
(WebKit::WebProcessPool::backlightLevelDidChangeCallback):
(WebKit::WebProcessPool::accessibilityPreferencesChangedCallback):
(WebKit::WebProcessPool::mediaAccessibilityPreferencesChangedCallback):
(WebKit::WebProcessPool::colorPreferencesDidChangeCallback):
(WebKit::WebProcessPool::remoteWebInspectorEnabledCallback):
- Clean up function parameter list.
- Use extractWebProcessPool() helper method to get a
  RefPtr<WebProcessPool> from `observer`.
(WebKit::WebProcessPool::addCFNotificationObserver): Add.
(WebKit::WebProcessPool::removeCFNotificationObserver): Add.
- Private helper methods to reduce duplicate code.
- Use m_weakObserver for CFNotificationCenter observer and
  include _CFNotificationObserverIsObjC to fix the bug.
(WebKit::WebProcessPool::registerNotificationObservers):
- Make use of new addCFNotificationObserver() helper method.
- Fixes use of static_cast<CFStringRef> to make code ready for
  ARC by using a __bridge cast or removing the static_cast when
  CFSTR() is used.
(WebKit::WebProcessPool::unregisterNotificationObservers):
- Make use of new removeCFNotificationObserver() helper method.

* UIProcess/WebProcessPool.h:
- Add m_weakObserver instance variable to hold the
  WKProcessPoolWeakObserver object.
(WebKit::WebProcessPool::addCFNotificationObserver): Add.
(WebKit::WebProcessPool::removeCFNotificationObserver): Add.
- Add declarations for new helper methods.
(WebKit::WebProcessPool::backlightLevelDidChangeCallback):
(WebKit::WebProcessPool::accessibilityPreferencesChangedCallback):
(WebKit::WebProcessPool::mediaAccessibilityPreferencesChangedCallback):
(WebKit::WebProcessPool::colorPreferencesDidChangeCallback):
(WebKit::WebProcessPool::remoteWebInspectorEnabledCallback):
- Clean up function parameter list.

Source/WTF:

Tests (API):
    TestWTF.TypeCastsNS.checked_ns_cast
    TestWTF.TypeCastsNS.dynamic_ns_cast
    TestWTF.TypeCastsNS.dynamic_ns_cast_RetainPtr

* WTF.xcodeproj/project.pbxproj:
* wtf/PlatformMac.cmake:
- Add new header files to the project.

* wtf/cocoa/TypeCastsNS.h: Add.
(WTF::checked_ns_cast):
(WTF::dynamic_ns_cast):
- Add casts for NS objects similar to TypeCastsCF.h.

* wtf/PlatformHave.h:
(HAVE_NS_DIRECT_SUPPORT): Add.
- Note that clang for macOS 11 Big Sur claims to know about the
  attributes, but will fail to compile if they are actually
  used.

* wtf/spi/cocoa/NSObjCRuntimeSPI.h: Add.
(NS_DIRECT):
(NS_DIRECT_MEMBERS):
- Define compiler attributes for direct dispatch of Objective-C
  methods.

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
- Add TypeCastsNS.mm to the project.
* TestWebKitAPI/Tests/WTF/cocoa/TypeCastsNS.mm: Add.
(TestWebKitAPI::TEST): Add tests for <wtf/TypeCastsNS.h>.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (282631 => 282632)


--- trunk/Source/WTF/ChangeLog	2021-09-17 03:12:11 UTC (rev 282631)
+++ trunk/Source/WTF/ChangeLog	2021-09-17 04:18:09 UTC (rev 282632)
@@ -1,3 +1,37 @@
+2021-09-16  David Kilzer  <[email protected]>
+
+        WebKit::WebProcessPool should use a weak observer with CFNotificationCenter
+        <https://webkit.org/b/230227>
+        <rdar://problem/83067708>
+
+        Reviewed by Darin Adler.
+
+        Tests (API):
+            TestWTF.TypeCastsNS.checked_ns_cast
+            TestWTF.TypeCastsNS.dynamic_ns_cast
+            TestWTF.TypeCastsNS.dynamic_ns_cast_RetainPtr
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/PlatformMac.cmake:
+        - Add new header files to the project.
+
+        * wtf/cocoa/TypeCastsNS.h: Add.
+        (WTF::checked_ns_cast):
+        (WTF::dynamic_ns_cast):
+        - Add casts for NS objects similar to TypeCastsCF.h.
+
+        * wtf/PlatformHave.h:
+        (HAVE_NS_DIRECT_SUPPORT): Add.
+        - Note that clang for macOS 11 Big Sur claims to know about the
+          attributes, but will fail to compile if they are actually
+          used.
+
+        * wtf/spi/cocoa/NSObjCRuntimeSPI.h: Add.
+        (NS_DIRECT):
+        (NS_DIRECT_MEMBERS):
+        - Define compiler attributes for direct dispatch of Objective-C
+          methods.
+
 2021-09-16  Philip Chimento  <[email protected]>
 
         Fixes for build-webkit --minimal

Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (282631 => 282632)


--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2021-09-17 03:12:11 UTC (rev 282631)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2021-09-17 04:18:09 UTC (rev 282632)
@@ -389,7 +389,9 @@
 		413FE8F51F8D2EAB00F6D7D7 /* CallbackAggregator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallbackAggregator.h; sourceTree = "<group>"; };
 		430B47871AAAAC1A001223DA /* StringCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringCommon.h; sourceTree = "<group>"; };
 		4427C5A921F6D6C300A612A4 /* ASCIICType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ASCIICType.cpp; sourceTree = "<group>"; };
+		44309D4026EFC14A00402A67 /* NSObjCRuntimeSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSObjCRuntimeSPI.h; sourceTree = "<group>"; };
 		4468567225094FE8008CCA05 /* ThreadSanitizerSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadSanitizerSupport.h; sourceTree = "<group>"; };
+		44CDE4D226EE6CDA009F6ACB /* TypeCastsNS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeCastsNS.h; sourceTree = "<group>"; };
 		46209A27266D543A007F8F4A /* CancellableTask.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CancellableTask.h; sourceTree = "<group>"; };
 		46BA9EAB1F4CD61E009A2BBC /* CompletionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompletionHandler.h; sourceTree = "<group>"; };
 		46BEB6E922FFDDD500269867 /* RefCounted.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RefCounted.cpp; sourceTree = "<group>"; };
@@ -1535,6 +1537,7 @@
 				CEA072A7236FFA160018839C /* CrashReporterClientSPI.h */,
 				E31BDE2822E913CC0029B105 /* MachVMSPI.h */,
 				1C503BE423AADEEA0072E66B /* NSLocaleSPI.h */,
+				44309D4026EFC14A00402A67 /* NSObjCRuntimeSPI.h */,
 				93D191CF20CAECE800C51B8E /* objcSPI.h */,
 				2DA442FC24904CA000C9C59D /* OSLogSPI.h */,
 				A5098B011C16A4F900087797 /* SecuritySPI.h */,
@@ -1615,6 +1618,7 @@
 				A30D412C1F0DE0BA00B71954 /* SoftLinking.h */,
 				BC3FEB5E267FCD460054006A /* SpanCocoa.h */,
 				EB61EDC62409CCC0001EFE36 /* SystemTracingCocoa.cpp */,
+				44CDE4D226EE6CDA009F6ACB /* TypeCastsNS.h */,
 				5CC0EE862162BC2200A1A842 /* URLCocoa.mm */,
 				93241657243BC2E50032FAAE /* VectorCocoa.h */,
 				E4A0AD3C1A96253C00536DF6 /* WorkQueueCocoa.cpp */,

Modified: trunk/Source/WTF/wtf/PlatformHave.h (282631 => 282632)


--- trunk/Source/WTF/wtf/PlatformHave.h	2021-09-17 03:12:11 UTC (rev 282631)
+++ trunk/Source/WTF/wtf/PlatformHave.h	2021-09-17 04:18:09 UTC (rev 282632)
@@ -846,6 +846,14 @@
 #endif
 #endif
 
+#if COMPILER(GCC_COMPATIBLE) && defined(__has_attribute)
+#if __has_attribute(objc_direct) && (!PLATFORM(MAC) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 120000)
+#if !defined(HAVE_NS_DIRECT_SUPPORT)
+#define HAVE_NS_DIRECT_SUPPORT 1
+#endif
+#endif
+#endif
+
 #if PLATFORM(COCOA)
 #if !defined(HAVE_CG_CONTEXT_DRAW_PATH_DIRECT)
 #define HAVE_CG_CONTEXT_DRAW_PATH_DIRECT 1

Modified: trunk/Source/WTF/wtf/PlatformMac.cmake (282631 => 282632)


--- trunk/Source/WTF/wtf/PlatformMac.cmake	2021-09-17 03:12:11 UTC (rev 282631)
+++ trunk/Source/WTF/wtf/PlatformMac.cmake	2021-09-17 04:18:09 UTC (rev 282632)
@@ -20,6 +20,7 @@
     cocoa/RuntimeApplicationChecksCocoa.h
     cocoa/SoftLinking.h
     cocoa/SpanCocoa.h
+    cocoa/TypeCastsNS.h
     cocoa/VectorCocoa.h
 
     darwin/WeakLinking.h
@@ -31,6 +32,7 @@
     spi/cocoa/CrashReporterClientSPI.h
     spi/cocoa/MachVMSPI.h
     spi/cocoa/NSLocaleSPI.h
+    spi/cocoa/NSObjCRuntimeSPI.h
     spi/cocoa/SecuritySPI.h
     spi/cocoa/objcSPI.h
 

Added: trunk/Source/WTF/wtf/cocoa/TypeCastsNS.h (0 => 282632)


--- trunk/Source/WTF/wtf/cocoa/TypeCastsNS.h	                        (rev 0)
+++ trunk/Source/WTF/wtf/cocoa/TypeCastsNS.h	2021-09-17 04:18:09 UTC (rev 282632)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2014-2021 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
+
+#include <wtf/Assertions.h>
+#include <wtf/RetainPtr.h>
+
+namespace WTF {
+
+// Use checked_ns_cast<> instead of dynamic_ns_cast<> when a specific NS type is required.
+
+template<typename T> T* checked_ns_cast(id object)
+{
+    using ValueType = std::remove_pointer_t<T>;
+    using PtrType = ValueType*;
+
+    if (!object)
+        return nullptr;
+
+    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION([object isKindOfClass:[ValueType class]]);
+
+    return reinterpret_cast<PtrType>(object);
+}
+
+// Use dynamic_ns_cast<> instead of checked_ns_cast<> when actively checking NS types,
+// similar to dynamic_cast<> in C++. Be sure to include a nil check.
+
+template<typename T> T* dynamic_ns_cast(id object)
+{
+    using ValueType = std::remove_pointer_t<T>;
+    using PtrType = ValueType*;
+
+    if (![object isKindOfClass:[ValueType class]])
+        return nullptr;
+
+    return reinterpret_cast<PtrType>(object);
+}
+
+template<typename T, typename U> RetainPtr<T> dynamic_ns_cast(RetainPtr<U>&& object)
+{
+    if (![object isKindOfClass:[T class]])
+        return nullptr;
+
+    return WTFMove(object);
+}
+
+} // namespace WTF
+
+using WTF::checked_ns_cast;
+using WTF::dynamic_ns_cast;

Added: trunk/Source/WTF/wtf/spi/cocoa/NSObjCRuntimeSPI.h (0 => 282632)


--- trunk/Source/WTF/wtf/spi/cocoa/NSObjCRuntimeSPI.h	                        (rev 0)
+++ trunk/Source/WTF/wtf/spi/cocoa/NSObjCRuntimeSPI.h	2021-09-17 04:18:09 UTC (rev 282632)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 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 USE(APPLE_INTERNAL_SDK)
+
+#include <Foundation/NSObjCRuntime_Private.h>
+
+#else
+
+#include <wtf/Platform.h>
+
+// Apply this to a specific method in the @interface or @implementation.
+#ifndef NS_DIRECT
+#if HAVE(NS_DIRECT_SUPPORT)
+#define NS_DIRECT __attribute__((objc_direct))
+#else
+#define NS_DIRECT
+#endif
+#endif
+
+// Apply this to the @interface or @implementation of a class.
+#ifndef NS_DIRECT_MEMBERS
+#if HAVE(NS_DIRECT_SUPPORT)
+#define NS_DIRECT_MEMBERS __attribute__((objc_direct_members))
+#else
+#define NS_DIRECT_MEMBERS
+#endif
+#endif
+
+#endif

Modified: trunk/Source/WebKit/ChangeLog (282631 => 282632)


--- trunk/Source/WebKit/ChangeLog	2021-09-17 03:12:11 UTC (rev 282631)
+++ trunk/Source/WebKit/ChangeLog	2021-09-17 04:18:09 UTC (rev 282632)
@@ -1,3 +1,66 @@
+2021-09-16  David Kilzer  <[email protected]>
+
+        WebKit::WebProcessPool should use a weak observer with CFNotificationCenter
+        <https://webkit.org/b/230227>
+        <rdar://problem/83067708>
+
+        Reviewed by Darin Adler.
+
+        To fix the bug, implement an Objective-C class named
+        WKProcessPoolWeakObserver which contains an instance variable
+        holding a WeakPtr<WebProcessPool>, and tell CFNotificationCenter
+        to hold a weak reference to WKProcessPoolWeakObserver.
+
+        Since WKProcessPoolWeakObserver is self-contained within the
+        source file, it uses the NS_DIRECT_MEMBERS attribute since it
+        does not require the overhead of dynamic Objective-C method
+        dispatch.
+
+        * UIProcess/Cocoa/WebProcessPoolCocoa.mm:
+        (-[WKProcessPoolWeakObserver initWithWeakPtr:]): Add.
+        (-[WKProcessPoolWeakObserver pool]): Add.
+        - Implement WKProcessPoolWeakObserver class.
+        - Note that init methods can never be marked as NS_DIRECT, and
+          @property statements can't use NS_DIRECT in their declaration,
+          so the @property is declared in a category which uses
+          NS_DIRECT_MEMBERS.
+        (WebKit::extractWebProcessPool): Add.
+        - Static helper method for extracting RefPtr<WebProcessPool>
+          from type-punned WKProcessPoolWeakObserver.
+        (WebKit::WebProcessPool::backlightLevelDidChangeCallback):
+        (WebKit::WebProcessPool::accessibilityPreferencesChangedCallback):
+        (WebKit::WebProcessPool::mediaAccessibilityPreferencesChangedCallback):
+        (WebKit::WebProcessPool::colorPreferencesDidChangeCallback):
+        (WebKit::WebProcessPool::remoteWebInspectorEnabledCallback):
+        - Clean up function parameter list.
+        - Use extractWebProcessPool() helper method to get a
+          RefPtr<WebProcessPool> from `observer`.
+        (WebKit::WebProcessPool::addCFNotificationObserver): Add.
+        (WebKit::WebProcessPool::removeCFNotificationObserver): Add.
+        - Private helper methods to reduce duplicate code.
+        - Use m_weakObserver for CFNotificationCenter observer and
+          include _CFNotificationObserverIsObjC to fix the bug.
+        (WebKit::WebProcessPool::registerNotificationObservers):
+        - Make use of new addCFNotificationObserver() helper method.
+        - Fixes use of static_cast<CFStringRef> to make code ready for
+          ARC by using a __bridge cast or removing the static_cast when
+          CFSTR() is used.
+        (WebKit::WebProcessPool::unregisterNotificationObservers):
+        - Make use of new removeCFNotificationObserver() helper method.
+
+        * UIProcess/WebProcessPool.h:
+        - Add m_weakObserver instance variable to hold the
+          WKProcessPoolWeakObserver object.
+        (WebKit::WebProcessPool::addCFNotificationObserver): Add.
+        (WebKit::WebProcessPool::removeCFNotificationObserver): Add.
+        - Add declarations for new helper methods.
+        (WebKit::WebProcessPool::backlightLevelDidChangeCallback):
+        (WebKit::WebProcessPool::accessibilityPreferencesChangedCallback):
+        (WebKit::WebProcessPool::mediaAccessibilityPreferencesChangedCallback):
+        (WebKit::WebProcessPool::colorPreferencesDidChangeCallback):
+        (WebKit::WebProcessPool::remoteWebInspectorEnabledCallback):
+        - Clean up function parameter list.
+
 2021-09-16  Cameron McCormack  <[email protected]>
 
         Support patterns with a wide gamut source painting into a display-p3 canvas

Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm (282631 => 282632)


--- trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm	2021-09-17 03:12:11 UTC (rev 282631)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebProcessPoolCocoa.mm	2021-09-17 04:18:09 UTC (rev 282632)
@@ -65,6 +65,7 @@
 #import <WebCore/VersionChecks.h>
 #import <objc/runtime.h>
 #import <pal/spi/cf/CFNetworkSPI.h>
+#import <pal/spi/cf/CFNotificationCenterSPI.h>
 #import <sys/param.h>
 #import <wtf/FileSystem.h>
 #import <wtf/ProcessPrivilege.h>
@@ -71,6 +72,8 @@
 #import <wtf/SoftLinking.h>
 #import <wtf/cocoa/Entitlements.h>
 #import <wtf/cocoa/RuntimeApplicationChecksCocoa.h>
+#import <wtf/cocoa/TypeCastsNS.h>
+#import <wtf/spi/cocoa/NSObjCRuntimeSPI.h>
 #import <wtf/spi/darwin/SandboxSPI.h>
 #import <wtf/spi/darwin/dyldSPI.h>
 #import <wtf/text/TextStream.h>
@@ -131,6 +134,35 @@
 
 #define WEBPROCESSPOOL_RELEASE_LOG(channel, fmt, ...) RELEASE_LOG(channel, "%p - WebProcessPool::" fmt, this, ##__VA_ARGS__)
 
+@interface WKProcessPoolWeakObserver : NSObject {
+    WeakPtr<WebKit::WebProcessPool> m_weakPtr;
+}
+- (instancetype)init NS_UNAVAILABLE;
+- (instancetype)initWithWeakPtr:(WeakPtr<WebKit::WebProcessPool>&&)weakPtr NS_DESIGNATED_INITIALIZER;
+@end
+
+NS_DIRECT_MEMBERS
+@interface WKProcessPoolWeakObserver (Direct)
+@property (nonatomic, readonly) RefPtr<WebKit::WebProcessPool> pool;
+@end
+
+@implementation WKProcessPoolWeakObserver
+- (instancetype)initWithWeakPtr:(WeakPtr<WebKit::WebProcessPool>&&)weakPtr
+{
+    if ((self = [super init]))
+        m_weakPtr = WTFMove(weakPtr);
+    return self;
+}
+@end
+
+NS_DIRECT_MEMBERS
+@implementation WKProcessPoolWeakObserver (Direct)
+- (RefPtr<WebKit::WebProcessPool>)pool
+{
+    return makeRefPtr(m_weakPtr.get());
+}
+@end
+
 namespace WebKit {
 using namespace WebCore;
 
@@ -603,29 +635,43 @@
     return !m_userObservablePageCounter.value() && !m_processSuppressionDisabledForPageCounter.value();
 }
 
+static inline RefPtr<WebProcessPool> extractWebProcessPool(void* observer)
+{
+    RetainPtr strongObserver { dynamic_ns_cast<WKProcessPoolWeakObserver>(reinterpret_cast<id>(observer)) };
+    if (!strongObserver)
+        return nullptr;
+    return [strongObserver pool];
+}
+
 #if PLATFORM(IOS_FAMILY) && !PLATFORM(MACCATALYST)
 float WebProcessPool::displayBrightness()
 {
     return BKSDisplayBrightnessGetCurrent();
 }
-    
-void WebProcessPool::backlightLevelDidChangeCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
+
+void WebProcessPool::backlightLevelDidChangeCallback(CFNotificationCenterRef, void* observer, CFStringRef, const void*, CFDictionaryRef)
 {
-    auto* pool = reinterpret_cast<WebProcessPool*>(observer);
+    auto pool = extractWebProcessPool(observer);
+    if (!pool)
+        return;
     pool->sendToAllProcesses(Messages::WebProcess::BacklightLevelDidChange(BKSDisplayBrightnessGetCurrent()));
 }
 #endif
 
-void WebProcessPool::accessibilityPreferencesChangedCallback(CFNotificationCenterRef, void *observer, CFStringRef name, const void *, CFDictionaryRef userInfo)
+void WebProcessPool::accessibilityPreferencesChangedCallback(CFNotificationCenterRef, void* observer, CFStringRef, const void*, CFDictionaryRef)
 {
-    auto* pool = reinterpret_cast<WebProcessPool*>(observer);
+    auto pool = extractWebProcessPool(observer);
+    if (!pool)
+        return;
     pool->sendToAllProcesses(Messages::WebProcess::AccessibilityPreferencesDidChange(accessibilityPreferences()));
 }
 
 #if HAVE(MEDIA_ACCESSIBILITY_FRAMEWORK)
-void WebProcessPool::mediaAccessibilityPreferencesChangedCallback(CFNotificationCenterRef, void *observer, CFStringRef name, const void *, CFDictionaryRef userInfo)
+void WebProcessPool::mediaAccessibilityPreferencesChangedCallback(CFNotificationCenterRef, void* observer, CFStringRef, const void*, CFDictionaryRef)
 {
-    auto* pool = reinterpret_cast<WebProcessPool*>(observer);
+    auto pool = extractWebProcessPool(observer);
+    if (!pool)
+        return;
     auto captionDisplayMode = WebCore::CaptionUserPreferencesMediaAF::platformCaptionDisplayMode();
     auto preferredLanguages = WebCore::CaptionUserPreferencesMediaAF::platformPreferredLanguages();
     pool->sendToAllProcesses(Messages::WebProcess::SetMediaAccessibilityPreferences(captionDisplayMode, preferredLanguages));
@@ -633,17 +679,21 @@
 #endif
 
 #if PLATFORM(MAC)
-void WebProcessPool::colorPreferencesDidChangeCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
+void WebProcessPool::colorPreferencesDidChangeCallback(CFNotificationCenterRef, void* observer, CFStringRef, const void*, CFDictionaryRef)
 {
-    auto* pool = reinterpret_cast<WebProcessPool*>(observer);
+    auto pool = extractWebProcessPool(observer);
+    if (!pool)
+        return;
     pool->sendToAllProcesses(Messages::WebProcess::ColorPreferencesDidChange());
 }
 #endif
 
 #if ENABLE(REMOTE_INSPECTOR) && PLATFORM(IOS_FAMILY) && !PLATFORM(MACCATALYST)
-void WebProcessPool::remoteWebInspectorEnabledCallback(CFNotificationCenterRef, void *observer, CFStringRef name, const void *, CFDictionaryRef userInfo)
+void WebProcessPool::remoteWebInspectorEnabledCallback(CFNotificationCenterRef, void* observer, CFStringRef, const void*, CFDictionaryRef)
 {
-    auto* pool = reinterpret_cast<WebProcessPool*>(observer);
+    auto pool = extractWebProcessPool(observer);
+    if (!pool)
+        return;
     for (auto& process : pool->m_processes)
         process->enableRemoteInspectorIfNeeded();
 }
@@ -662,6 +712,17 @@
 }
 #endif
 
+void WebProcessPool::addCFNotificationObserver(CFNotificationCallback callback, CFStringRef name, CFNotificationCenterRef center)
+{
+    auto coalesceBehavior = static_cast<CFNotificationSuspensionBehavior>(CFNotificationSuspensionBehaviorCoalesce | _CFNotificationObserverIsObjC);
+    CFNotificationCenterAddObserver(center, (__bridge const void*)m_weakObserver.get(), callback, name, nullptr, coalesceBehavior);
+}
+
+void WebProcessPool::removeCFNotificationObserver(CFStringRef name, CFNotificationCenterRef center)
+{
+    CFNotificationCenterRemoveObserver(center, (__bridge const void*)m_weakObserver.get(), name, nullptr);
+}
+
 void WebProcessPool::registerNotificationObservers()
 {
 #if !PLATFORM(IOS_FAMILY)
@@ -721,12 +782,14 @@
         setApplicationIsActive(false);
     }];
     
-    CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), this, colorPreferencesDidChangeCallback, AppleColorPreferencesChangedNotification, nullptr, CFNotificationSuspensionBehaviorCoalesce);
+    m_weakObserver = adoptNS([[WKProcessPoolWeakObserver alloc] initWithWeakPtr:makeWeakPtr(*this)]);
+
+    addCFNotificationObserver(colorPreferencesDidChangeCallback, AppleColorPreferencesChangedNotification, CFNotificationCenterGetDistributedCenter());
 #elif !PLATFORM(MACCATALYST)
-    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, backlightLevelDidChangeCallback, static_cast<CFStringRef>(UIBacklightLevelChangedNotification), nullptr, CFNotificationSuspensionBehaviorCoalesce);
+    addCFNotificationObserver(backlightLevelDidChangeCallback, (__bridge CFStringRef)UIBacklightLevelChangedNotification);
 #if PLATFORM(IOS)
 #if ENABLE(REMOTE_INSPECTOR)
-    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, remoteWebInspectorEnabledCallback, static_cast<CFStringRef>(CFSTR(WIRServiceEnabledNotification)), nullptr, CFNotificationSuspensionBehaviorCoalesce);
+    addCFNotificationObserver(remoteWebInspectorEnabledCallback, CFSTR(WIRServiceEnabledNotification));
 #endif
 #endif // PLATFORM(IOS)
 #endif // !PLATFORM(IOS_FAMILY)
@@ -762,14 +825,14 @@
     });
 
 #if HAVE(PER_APP_ACCESSIBILITY_PREFERENCES)
-    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, accessibilityPreferencesChangedCallback, kAXSReduceMotionChangedNotification, nullptr, CFNotificationSuspensionBehaviorCoalesce);
-    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, accessibilityPreferencesChangedCallback, kAXSIncreaseButtonLegibilityNotification, nullptr, CFNotificationSuspensionBehaviorCoalesce);
-    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, accessibilityPreferencesChangedCallback, kAXSEnhanceTextLegibilityChangedNotification, nullptr, CFNotificationSuspensionBehaviorCoalesce);
-    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, accessibilityPreferencesChangedCallback, kAXSDarkenSystemColorsEnabledNotification, nullptr, CFNotificationSuspensionBehaviorCoalesce);
-    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, accessibilityPreferencesChangedCallback, kAXSInvertColorsEnabledNotification, nullptr, CFNotificationSuspensionBehaviorCoalesce);
+    addCFNotificationObserver(accessibilityPreferencesChangedCallback, kAXSReduceMotionChangedNotification);
+    addCFNotificationObserver(accessibilityPreferencesChangedCallback, kAXSIncreaseButtonLegibilityNotification);
+    addCFNotificationObserver(accessibilityPreferencesChangedCallback, kAXSEnhanceTextLegibilityChangedNotification);
+    addCFNotificationObserver(accessibilityPreferencesChangedCallback, kAXSDarkenSystemColorsEnabledNotification);
+    addCFNotificationObserver(accessibilityPreferencesChangedCallback, kAXSInvertColorsEnabledNotification);
 #endif
 #if HAVE(MEDIA_ACCESSIBILITY_FRAMEWORK)
-    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, mediaAccessibilityPreferencesChangedCallback, kMAXCaptionAppearanceSettingsChangedNotification, nullptr, CFNotificationSuspensionBehaviorCoalesce);
+    addCFNotificationObserver(mediaAccessibilityPreferencesChangedCallback, kMAXCaptionAppearanceSettingsChangedNotification);
 #endif
 }
 
@@ -786,12 +849,12 @@
     [[NSWorkspace.sharedWorkspace notificationCenter] removeObserver:m_accessibilityDisplayOptionsNotificationObserver.get()];
     [[NSNotificationCenter defaultCenter] removeObserver:m_scrollerStyleNotificationObserver.get()];
     [[NSNotificationCenter defaultCenter] removeObserver:m_deactivationObserver.get()];
-    CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), this, AppleColorPreferencesChangedNotification, nullptr);
+    removeCFNotificationObserver(AppleColorPreferencesChangedNotification, CFNotificationCenterGetDistributedCenter());
 #elif !PLATFORM(MACCATALYST)
-    CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, static_cast<CFStringRef>(UIBacklightLevelChangedNotification) , nullptr);
+    removeCFNotificationObserver((__bridge CFStringRef)UIBacklightLevelChangedNotification);
 #if PLATFORM(IOS)
 #if ENABLE(REMOTE_INSPECTOR)
-    CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, CFSTR(WIRServiceEnabledNotification), nullptr);
+    removeCFNotificationObserver(CFSTR(WIRServiceEnabledNotification));
 #endif
 #endif // PLATFORM(IOS)
 #endif // !PLATFORM(IOS_FAMILY)
@@ -806,15 +869,17 @@
     m_powerSourceNotifier = nullptr;
 
 #if HAVE(PER_APP_ACCESSIBILITY_PREFERENCES)
-    CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, kAXSReduceMotionChangedNotification, nullptr);
-    CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, kAXSIncreaseButtonLegibilityNotification, nullptr);
-    CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, kAXSEnhanceTextLegibilityChangedNotification, nullptr);
-    CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, kAXSDarkenSystemColorsEnabledNotification, nullptr);
-    CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, kAXSInvertColorsEnabledNotification, nullptr);
+    removeCFNotificationObserver(kAXSReduceMotionChangedNotification);
+    removeCFNotificationObserver(kAXSIncreaseButtonLegibilityNotification);
+    removeCFNotificationObserver(kAXSEnhanceTextLegibilityChangedNotification);
+    removeCFNotificationObserver(kAXSDarkenSystemColorsEnabledNotification);
+    removeCFNotificationObserver(kAXSInvertColorsEnabledNotification);
 #endif
 #if HAVE(MEDIA_ACCESSIBILITY_FRAMEWORK)
-    CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), this, kMAXCaptionAppearanceSettingsChangedNotification, nullptr);
+    removeCFNotificationObserver(kMAXCaptionAppearanceSettingsChangedNotification);
 #endif
+
+    m_weakObserver = nil;
 }
 
 bool WebProcessPool::isURLKnownHSTSHost(const String& urlString) const

Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.h (282631 => 282632)


--- trunk/Source/WebKit/UIProcess/WebProcessPool.h	2021-09-17 03:12:11 UTC (rev 282631)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.h	2021-09-17 04:18:09 UTC (rev 282632)
@@ -64,6 +64,7 @@
 OBJC_CLASS NSSet;
 OBJC_CLASS NSString;
 OBJC_CLASS WKPreferenceObserver;
+OBJC_CLASS WKProcessPoolWeakObserver;
 #if PLATFORM(MAC)
 OBJC_CLASS WKWebInspectorPreferenceObserver;
 #endif
@@ -549,6 +550,9 @@
     bool usesSingleWebProcess() const { return m_configuration->usesSingleWebProcess(); }
 
 #if PLATFORM(COCOA)
+    void addCFNotificationObserver(CFNotificationCallback, CFStringRef name, CFNotificationCenterRef = CFNotificationCenterGetDarwinNotifyCenter());
+    void removeCFNotificationObserver(CFStringRef name, CFNotificationCenterRef = CFNotificationCenterGetDarwinNotifyCenter());
+
     void registerNotificationObservers();
     void unregisterNotificationObservers();
 #endif
@@ -567,22 +571,22 @@
 
 #if PLATFORM(IOS_FAMILY) && !PLATFORM(MACCATALYST)
     static float displayBrightness();
-    static void backlightLevelDidChangeCallback(CFNotificationCenterRef, void *observer, CFStringRef name, const void *, CFDictionaryRef userInfo);    
+    static void backlightLevelDidChangeCallback(CFNotificationCenterRef, void* observer, CFStringRef name, const void* postingObject, CFDictionaryRef userInfo);
 #if ENABLE(REMOTE_INSPECTOR)
-    static void remoteWebInspectorEnabledCallback(CFNotificationCenterRef, void *observer, CFStringRef name, const void *, CFDictionaryRef userInfo);
+    static void remoteWebInspectorEnabledCallback(CFNotificationCenterRef, void* observer, CFStringRef name, const void* postingObject, CFDictionaryRef userInfo);
 #endif
 #endif
 
 #if PLATFORM(COCOA)
-    static void accessibilityPreferencesChangedCallback(CFNotificationCenterRef, void *observer, CFStringRef name, const void *, CFDictionaryRef userInfo);
+    static void accessibilityPreferencesChangedCallback(CFNotificationCenterRef, void* observer, CFStringRef name, const void* postingObject, CFDictionaryRef userInfo);
 #endif
 
 #if HAVE(MEDIA_ACCESSIBILITY_FRAMEWORK)
-    static void mediaAccessibilityPreferencesChangedCallback(CFNotificationCenterRef, void *observer, CFStringRef name, const void *, CFDictionaryRef userInfo);
+    static void mediaAccessibilityPreferencesChangedCallback(CFNotificationCenterRef, void* observer, CFStringRef name, const void* postingObject, CFDictionaryRef userInfo);
 #endif
 
 #if PLATFORM(MAC)
-    static void colorPreferencesDidChangeCallback(CFNotificationCenterRef, void *observer, CFStringRef name, const void *, CFDictionaryRef userInfo);
+    static void colorPreferencesDidChangeCallback(CFNotificationCenterRef, void* observer, CFStringRef name, const void* postingObject, CFDictionaryRef userInfo);
 #endif
     
 #if ENABLE(CFPREFS_DIRECT_MODE)
@@ -689,6 +693,8 @@
     RetainPtr<NSObject> m_activationObserver;
     RetainPtr<NSObject> m_accessibilityEnabledObserver;
     RetainPtr<NSObject> m_applicationLaunchObserver;
+
+    RetainPtr<WKProcessPoolWeakObserver> m_weakObserver;
 #endif
 
     bool m_processTerminationEnabled { true };

Modified: trunk/Tools/ChangeLog (282631 => 282632)


--- trunk/Tools/ChangeLog	2021-09-17 03:12:11 UTC (rev 282631)
+++ trunk/Tools/ChangeLog	2021-09-17 04:18:09 UTC (rev 282632)
@@ -1,3 +1,16 @@
+2021-09-16  David Kilzer  <[email protected]>
+
+        WebKit::WebProcessPool should use a weak observer with CFNotificationCenter
+        <https://webkit.org/b/230227>
+        <rdar://problem/83067708>
+
+        Reviewed by Darin Adler.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        - Add TypeCastsNS.mm to the project.
+        * TestWebKitAPI/Tests/WTF/cocoa/TypeCastsNS.mm: Add.
+        (TestWebKitAPI::TEST): Add tests for <wtf/TypeCastsNS.h>.
+
 2021-09-16  Philip Chimento  <[email protected]>
 
         Fixes for build-webkit --minimal

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (282631 => 282632)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2021-09-17 03:12:11 UTC (rev 282631)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2021-09-17 04:18:09 UTC (rev 282632)
@@ -267,6 +267,7 @@
 		448D7E471EA6C55500ECC756 /* EnvironmentUtilitiesTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 448D7E451EA6C55500ECC756 /* EnvironmentUtilitiesTest.cpp */; };
 		44AC8BC621D0245A00CAFB34 /* RetainPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC029B161486AD6400817DA9 /* RetainPtr.cpp */; };
 		44C2FBE225E7592C00ABC72F /* WKAppHighlights.mm in Sources */ = {isa = PBXBuildFile; fileRef = 44C2FBE125E7592C00ABC72F /* WKAppHighlights.mm */; };
+		44CDE4D426EE6E4A009F6ACB /* TypeCastsNS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 44CDE4D326EE6E41009F6ACB /* TypeCastsNS.mm */; };
 		44CF31FD249941E8009CB6CB /* ContextMenuAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 44CF31FB24993F66009CB6CB /* ContextMenuAction.cpp */; };
 		4612C2B9210A6ACE00B788A6 /* LoadFileThenReload.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4612C2B8210A6ABF00B788A6 /* LoadFileThenReload.mm */; };
 		4628C8E92367ABD100B073F0 /* WKSecurityOrigin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4628C8E82367ABBC00B073F0 /* WKSecurityOrigin.cpp */; };
@@ -2099,6 +2100,7 @@
 		448D7E451EA6C55500ECC756 /* EnvironmentUtilitiesTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EnvironmentUtilitiesTest.cpp; sourceTree = "<group>"; };
 		44A622C114A0E2B60048515B /* WTFStringUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WTFStringUtilities.h; sourceTree = "<group>"; };
 		44C2FBE125E7592C00ABC72F /* WKAppHighlights.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKAppHighlights.mm; sourceTree = "<group>"; };
+		44CDE4D326EE6E41009F6ACB /* TypeCastsNS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TypeCastsNS.mm; sourceTree = "<group>"; };
 		44CF31FB24993F66009CB6CB /* ContextMenuAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContextMenuAction.cpp; sourceTree = "<group>"; };
 		4612C2B8210A6ABF00B788A6 /* LoadFileThenReload.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LoadFileThenReload.mm; sourceTree = "<group>"; };
 		4628C8E82367ABBC00B073F0 /* WKSecurityOrigin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKSecurityOrigin.cpp; sourceTree = "<group>"; };
@@ -4983,6 +4985,7 @@
 				BC3FEB63267FCF740054006A /* SpanCocoa.mm */,
 				1C4616A626BB172F00F8C9F6 /* TextStreamCocoa.cpp */,
 				1C46169E26BA510700F8C9F6 /* TextStreamCocoa.mm */,
+				44CDE4D326EE6E41009F6ACB /* TypeCastsNS.mm */,
 				E3C21A7B21B25CA2003B31A3 /* URLExtras.mm */,
 			);
 			path = cocoa;
@@ -5356,6 +5359,7 @@
 				E38A0D351FD50CC300E98C8B /* Threading.cpp in Sources */,
 				5311BD5E1EA9490E00525281 /* ThreadMessages.cpp in Sources */,
 				0F2C20B81DCD545000542D9E /* Time.cpp in Sources */,
+				44CDE4D426EE6E4A009F6ACB /* TypeCastsNS.mm in Sources */,
 				E324A6F02041C82000A76593 /* UniqueArray.cpp in Sources */,
 				E3A1E78221B25B7A008C6007 /* URL.cpp in Sources */,
 				E3C21A7C21B25CA2003B31A3 /* URLExtras.mm in Sources */,

Added: trunk/Tools/TestWebKitAPI/Tests/WTF/cocoa/TypeCastsNS.mm (0 => 282632)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/cocoa/TypeCastsNS.mm	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/cocoa/TypeCastsNS.mm	2021-09-17 04:18:09 UTC (rev 282632)
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2021 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 <wtf/cocoa/TypeCastsNS.h>
+
+#import <wtf/StdLibExtras.h>
+
+@interface MyObjectSubtype : NSObject
+@end
+
+@implementation MyObjectSubtype
+@end
+
+namespace TestWebKitAPI {
+
+using namespace WTF;
+
+TEST(TypeCastsNS, checked_ns_cast)
+{
+    EXPECT_EQ(nil, checked_ns_cast<NSString>(nil));
+
+    {
+        auto object = adoptNS(reinterpret_cast<id>([[NSString alloc] initWithFormat:@"%s", "Hello world"]));
+        EXPECT_EQ(object.get(), checked_ns_cast<NSString>(object.get()));
+        EXPECT_EQ(object.get(), checked_ns_cast<NSObject>(object.get()));
+    }
+
+    {
+        auto object = adoptNS(reinterpret_cast<NSObject *>([[NSString alloc] initWithFormat:@"%s", "Hello world"]));
+        EXPECT_EQ(object.get(), checked_ns_cast<NSString>(object.get()));
+    }
+
+    {
+        auto object = adoptNS([[NSString alloc] initWithFormat:@"%s", "Hello world"]);
+        EXPECT_EQ(object.get(), checked_ns_cast<NSObject>(object.get()));
+    }
+}
+
+TEST(TypeCastsNS, dynamic_ns_cast)
+{
+    EXPECT_EQ(nil, dynamic_ns_cast<NSString>(nil));
+
+    {
+        auto object = adoptNS(reinterpret_cast<id>([[NSString alloc] initWithFormat:@"%s", "Hello world"]));
+        EXPECT_EQ(object.get(), dynamic_ns_cast<NSString>(object.get()));
+        EXPECT_EQ(object.get(), dynamic_ns_cast<NSObject>(object.get()));
+        EXPECT_EQ(nil, dynamic_ns_cast<NSArray>(object.get()));
+    }
+
+    {
+        auto object = adoptNS(reinterpret_cast<NSObject *>([[NSString alloc] initWithFormat:@"%s", "Hello world"]));
+        EXPECT_EQ(object.get(), dynamic_ns_cast<NSString>(object.get()));
+        EXPECT_EQ(nil, dynamic_ns_cast<NSArray>(object.get()));
+    }
+
+    {
+        auto object = adoptNS([[NSString alloc] initWithFormat:@"%s", "Hello world"]);
+        EXPECT_EQ(object.get(), dynamic_ns_cast<NSObject>(object.get()));
+        EXPECT_EQ(nil, dynamic_ns_cast<NSArray>(object.get()));
+    }
+
+    {
+        auto object = adoptNS(reinterpret_cast<id>([[NSObject alloc] init]));
+        EXPECT_EQ(object.get(), dynamic_ns_cast<NSObject>(object.get()));
+        EXPECT_EQ(nil, dynamic_ns_cast<MyObjectSubtype>(object.get()));
+    }
+
+    {
+        auto object = adoptNS([[NSObject alloc] init]);
+        EXPECT_EQ(nil, dynamic_ns_cast<MyObjectSubtype>(object.get()));
+    }
+}
+
+TEST(TypeCastsNS, dynamic_ns_cast_RetainPtr)
+{
+    {
+        RetainPtr<NSString> object;
+        auto objectCast = dynamic_ns_cast<NSString>(WTFMove(object));
+        EXPECT_EQ(nil, object.get());
+        EXPECT_EQ(nil, objectCast.get());
+    }
+
+    {
+        auto object = adoptNS(reinterpret_cast<id>([[NSString alloc] initWithFormat:@"%s", "Hello world"]));
+        id objectPtr = object.get();
+        auto objectCast = dynamic_ns_cast<NSString>(WTFMove(object));
+        EXPECT_EQ(nil, object.get());
+        EXPECT_EQ(objectPtr, objectCast.get());
+        objectPtr = nil; // For ARC.
+        EXPECT_EQ(1U, [objectCast retainCount]);
+
+        object = adoptNS(reinterpret_cast<id>([[NSString alloc] initWithFormat:@"%s", "Hello world"]));
+        objectPtr = object.get();
+        auto objectCast2 = dynamic_ns_cast<NSObject>(WTFMove(object));
+        EXPECT_EQ(nil, object.get());
+        EXPECT_EQ(objectPtr, objectCast2.get());
+        objectPtr = nil; // For ARC.
+        EXPECT_EQ(1U, [objectCast2 retainCount]);
+
+        object = adoptNS(reinterpret_cast<id>([[NSString alloc] initWithFormat:@"%s", "Hello world"]));
+        objectPtr = object.get();
+        auto objectCast3 = dynamic_ns_cast<NSArray>(WTFMove(object));
+        EXPECT_EQ(objectPtr, object.get());
+        EXPECT_EQ(nil, objectCast3.get());
+        objectPtr = nil; // For ARC.
+        EXPECT_EQ(1U, [object retainCount]);
+    }
+
+    {
+        auto object = adoptNS(reinterpret_cast<NSObject *>([[NSString alloc] initWithFormat:@"%s", "Hello world"]));
+        id objectPtr = object.get();
+        auto objectCast = dynamic_ns_cast<NSString>(WTFMove(object));
+        EXPECT_EQ(nil, object.get());
+        EXPECT_EQ(objectPtr, objectCast.get());
+        objectPtr = nil;
+        EXPECT_EQ(1U, [objectCast retainCount]);
+
+        object = adoptNS(reinterpret_cast<NSObject *>([[NSString alloc] initWithFormat:@"%s", "Hello world"]));
+        objectPtr = object.get();
+        auto objectCast2 = dynamic_ns_cast<NSArray>(WTFMove(object));
+        EXPECT_EQ(objectPtr, object.get());
+        EXPECT_EQ(nil, objectCast2.get());
+        objectPtr = nil;
+        EXPECT_EQ(1U, [object retainCount]);
+    }
+
+    {
+        auto object = adoptNS([[NSString alloc] initWithFormat:@"%s", "Hello world"]);
+        id objectPtr = object.get();
+        auto objectCast = dynamic_ns_cast<NSObject>(WTFMove(object));
+        EXPECT_EQ(nil, object.get());
+        EXPECT_EQ(objectPtr, objectCast.get());
+        objectPtr = nil;
+        EXPECT_EQ(1U, [objectCast retainCount]);
+
+        object = adoptNS([[NSString alloc] initWithFormat:@"%s", "Hello world"]);
+        objectPtr = object.get();
+        auto objectCast2 = dynamic_ns_cast<NSArray>(WTFMove(object));
+        EXPECT_EQ(objectPtr, object.get());
+        EXPECT_EQ(nil, objectCast2.get());
+        objectPtr = nil;
+        EXPECT_EQ(1U, [object retainCount]);
+    }
+
+    {
+        auto object = adoptNS(reinterpret_cast<id>([[NSObject alloc] init]));
+        id objectPtr = object.get();
+        auto objectCast = dynamic_ns_cast<NSObject>(WTFMove(object));
+        EXPECT_EQ(nil, object.get());
+        EXPECT_EQ(objectPtr, objectCast.get());
+        objectPtr = nil; // For ARC.
+        EXPECT_EQ(1U, [objectCast retainCount]);
+
+        object = adoptNS(reinterpret_cast<id>([[NSObject alloc] init]));
+        objectPtr = object.get();
+        auto objectCast2 = dynamic_ns_cast<MyObjectSubtype>(WTFMove(object));
+        EXPECT_EQ(objectPtr, object.get());
+        EXPECT_EQ(nil, objectCast2.get());
+        objectPtr = nil; // For ARC.
+        EXPECT_EQ(1U, [object retainCount]);
+    }
+
+    {
+        auto object = adoptNS([[NSObject alloc] init]);
+        id objectPtr = object.get();
+        auto objectCast = dynamic_ns_cast<MyObjectSubtype>(WTFMove(object));
+        EXPECT_EQ(objectPtr, object.get());
+        EXPECT_EQ(nil, objectCast.get());
+        objectPtr = nil; // For ARC.
+        EXPECT_EQ(1U, [object retainCount]);
+    }
+}
+
+} // namespace TestWebKitAPI
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to