Title: [163226] trunk/Source/WebCore
Revision
163226
Author
[email protected]
Date
2014-01-31 17:40:44 -0800 (Fri, 31 Jan 2014)

Log Message

[Cocoa] Add NEFilterSource support to ContentFilterMac
https://bugs.webkit.org/show_bug.cgi?id=127979

Reviewed by Sam Weinig.

Update ContentFilterMac to work with both WebFilterEvaluator and
NEFilterSource, if enabled.

* platform/ContentFilter.h: Set HAVE_NE_FILTER_SOURCE based on platform
conditionals, and forward-declare NEFilterSource.
* platform/mac/ContentFilterMac.mm: Included NEFilterSource.h if the SDK
has it; declared the class directly if not. Also soft-linked
NetworkExtension.framework.
(WebCore::ContentFilter::ContentFilter): Initialized
m_neFilterSourceStatus to NEFilterSourceStatusNeedsMoreData and created
m_platformContentFilter and m_neFilterSource objects if their
respective filters were enabled.
(WebCore::ContentFilter::isEnabled): Returned true if either filter is
enabled.
(WebCore::ContentFilter::addData): Added incoming data to each filter
that is enabled.
(WebCore::ContentFilter::finishedAddingData): Notified each enabled
filter that we are finished adding data.
(WebCore::ContentFilter::needsMoreData): Returned true if either filter
needs more data.
(WebCore::ContentFilter::didBlockData): Returned true if either filter
blocked data.
(WebCore::ContentFilter::getReplacementData): Returned
m_replacementData. Commented that this will currently return a null
string if NEFilterSource blocked the load.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (163225 => 163226)


--- trunk/Source/WebCore/ChangeLog	2014-02-01 01:37:59 UTC (rev 163225)
+++ trunk/Source/WebCore/ChangeLog	2014-02-01 01:40:44 UTC (rev 163226)
@@ -1,3 +1,36 @@
+2014-01-30  Andy Estes  <[email protected]>
+
+        [Cocoa] Add NEFilterSource support to ContentFilterMac
+        https://bugs.webkit.org/show_bug.cgi?id=127979
+
+        Reviewed by Sam Weinig.
+
+        Update ContentFilterMac to work with both WebFilterEvaluator and
+        NEFilterSource, if enabled.
+
+        * platform/ContentFilter.h: Set HAVE_NE_FILTER_SOURCE based on platform
+        conditionals, and forward-declare NEFilterSource.
+        * platform/mac/ContentFilterMac.mm: Included NEFilterSource.h if the SDK
+        has it; declared the class directly if not. Also soft-linked
+        NetworkExtension.framework.
+        (WebCore::ContentFilter::ContentFilter): Initialized
+        m_neFilterSourceStatus to NEFilterSourceStatusNeedsMoreData and created
+        m_platformContentFilter and m_neFilterSource objects if their
+        respective filters were enabled.
+        (WebCore::ContentFilter::isEnabled): Returned true if either filter is
+        enabled.
+        (WebCore::ContentFilter::addData): Added incoming data to each filter
+        that is enabled.
+        (WebCore::ContentFilter::finishedAddingData): Notified each enabled
+        filter that we are finished adding data.
+        (WebCore::ContentFilter::needsMoreData): Returned true if either filter
+        needs more data.
+        (WebCore::ContentFilter::didBlockData): Returned true if either filter
+        blocked data.
+        (WebCore::ContentFilter::getReplacementData): Returned
+        m_replacementData. Commented that this will currently return a null
+        string if NEFilterSource blocked the load.
+
 2014-01-31  Oliver Hunt  <[email protected]>
 
         Rollout r163195 and related patches

Modified: trunk/Source/WebCore/platform/ContentFilter.h (163225 => 163226)


--- trunk/Source/WebCore/platform/ContentFilter.h	2014-02-01 01:37:59 UTC (rev 163225)
+++ trunk/Source/WebCore/platform/ContentFilter.h	2014-02-01 01:40:44 UTC (rev 163226)
@@ -29,8 +29,8 @@
 #if USE(CONTENT_FILTERING)
 
 #include <wtf/PassRefPtr.h>
-#include <wtf/RefCounted.h>
 #include <wtf/RetainPtr.h>
+#include <wtf/ThreadSafeRefCounted.h>
 
 #if PLATFORM(IOS)
 #include <wtf/Functional.h>
@@ -40,15 +40,25 @@
 OBJC_CLASS WebFilterEvaluator;
 #endif
 
+#define HAVE_NE_FILTER_SOURCE TARGET_OS_EMBEDDED || (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 10100)
+
+#if HAVE(NE_FILTER_SOURCE)
+#import <atomic>
+#import <dispatch/dispatch.h>
+OBJC_CLASS NEFilterSource;
+#endif
+
 namespace WebCore {
 
 class ResourceResponse;
 
-class ContentFilter : public RefCounted<ContentFilter> {
+class ContentFilter : public ThreadSafeRefCounted<ContentFilter> {
 public:
     static PassRefPtr<ContentFilter> create(const ResourceResponse&);
     static bool isEnabled();
-    
+
+    virtual ~ContentFilter();
+
     void addData(const char* data, int length);
     void finishedAddingData();
     bool needsMoreData() const;
@@ -67,6 +77,13 @@
     RetainPtr<WebFilterEvaluator> m_platformContentFilter;
     RetainPtr<NSData> m_replacementData;
 #endif
+
+#if HAVE(NE_FILTER_SOURCE)
+    std::atomic<long> m_neFilterSourceStatus;
+    RetainPtr<NEFilterSource> m_neFilterSource;
+    dispatch_queue_t m_neFilterSourceQueue;
+    dispatch_semaphore_t m_neFilterSourceSemaphore;
+#endif
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/mac/ContentFilterMac.mm (163225 => 163226)


--- trunk/Source/WebCore/platform/mac/ContentFilterMac.mm	2014-02-01 01:37:59 UTC (rev 163225)
+++ trunk/Source/WebCore/platform/mac/ContentFilterMac.mm	2014-02-01 01:40:44 UTC (rev 163226)
@@ -49,6 +49,40 @@
 SOFT_LINK_PRIVATE_FRAMEWORK(WebContentAnalysis);
 SOFT_LINK_CLASS(WebContentAnalysis, WebFilterEvaluator);
 
+#if HAVE(NE_FILTER_SOURCE)
+
+#if defined(__has_include) && __has_include(<NetworkExtension/NEFilterSource.h>)
+#import <NetworkExtension/NEFilterSource.h>
+#else
+typedef NS_ENUM(NSInteger, NEFilterSourceStatus) {
+    NEFilterSourceStatusPass = 1,
+    NEFilterSourceStatusBlock = 2,
+    NEFilterSourceStatusNeedsMoreData = 3,
+    NEFilterSourceStatusError = 4,
+};
+
+typedef NS_ENUM(NSInteger, NEFilterSourceDirection) {
+    NEFilterSourceDirectionOutbound = 1,
+    NEFilterSourceDirectionInbound = 2,
+};
+
+@interface NEFilterSource : NSObject
++ (BOOL)filterRequired;
+- (id)initWithURL:(NSURL *)url direction:(NEFilterSourceDirection)direction socketIdentifier:(uint64_t)socketIdentifier;
+- (void)addData:(NSData *)data withCompletionQueue:(dispatch_queue_t)queue completionHandler:(void (^)(NEFilterSourceStatus, NSData *))completionHandler;
+- (void)dataCompleteWithCompletionQueue:(dispatch_queue_t)queue completionHandler:(void (^)(NEFilterSourceStatus, NSData *))completionHandler;
+@property (readonly) NEFilterSourceStatus status;
+@property (readonly) NSURL *url;
+@property (readonly) NEFilterSourceDirection direction;
+@property (readonly) uint64_t socketIdentifier;
+@end
+#endif
+
+SOFT_LINK_FRAMEWORK(NetworkExtension);
+SOFT_LINK_CLASS(NetworkExtension, NEFilterSource);
+
+#endif // HAVE(NE_FILTER_SOURCE)
+
 namespace WebCore {
 
 PassRefPtr<ContentFilter> ContentFilter::create(const ResourceResponse& response)
@@ -57,47 +91,116 @@
 }
 
 ContentFilter::ContentFilter(const ResourceResponse& response)
-    : m_platformContentFilter(adoptNS([[getWebFilterEvaluatorClass() alloc] initWithResponse:response.nsURLResponse()]))
+#if HAVE(NE_FILTER_SOURCE)
+    : m_neFilterSourceStatus(NEFilterSourceStatusNeedsMoreData)
+#endif
 {
-    ASSERT(m_platformContentFilter);
+    if ([getWebFilterEvaluatorClass() isManagedSession])
+        m_platformContentFilter = adoptNS([[getWebFilterEvaluatorClass() alloc] initWithResponse:response.nsURLResponse()]);
+
+#if HAVE(NE_FILTER_SOURCE)
+    if ([getNEFilterSourceClass() filterRequired]) {
+        m_neFilterSource = adoptNS([[getNEFilterSourceClass() alloc] initWithURL:[response.nsURLResponse() URL] direction:NEFilterSourceDirectionInbound socketIdentifier:0]);
+        m_neFilterSourceQueue = dispatch_queue_create("com.apple.WebCore.NEFilterSourceQueue", DISPATCH_QUEUE_SERIAL);
+    }
+#endif
 }
 
+ContentFilter::~ContentFilter()
+{
+#if HAVE(NE_FILTER_SOURCE)
+    dispatch_release(m_neFilterSourceQueue);
+#endif
+}
+
 bool ContentFilter::isEnabled()
 {
-    return [getWebFilterEvaluatorClass() isManagedSession];
+    return [getWebFilterEvaluatorClass() isManagedSession]
+#if HAVE(NE_FILTER_SOURCE)
+        || [getNEFilterSourceClass() filterRequired]
+#endif
+    ;
 }
 
 void ContentFilter::addData(const char* data, int length)
 {
     ASSERT(needsMoreData());
-    ASSERT(![m_replacementData.get() length]);
-    m_replacementData = [m_platformContentFilter addData:[NSData dataWithBytesNoCopy:(void*)data length:length freeWhenDone:NO]];
-    ASSERT(needsMoreData() || [m_replacementData.get() length]);
+
+    if (m_platformContentFilter) {
+        ASSERT(![m_replacementData.get() length]);
+        m_replacementData = [m_platformContentFilter addData:[NSData dataWithBytesNoCopy:(void*)data length:length freeWhenDone:NO]];
+        ASSERT(needsMoreData() || [m_replacementData.get() length]);
+    }
+
+#if HAVE(NE_FILTER_SOURCE)
+    if (!m_neFilterSource)
+        return;
+
+    ref();
+    [m_neFilterSource addData:[NSData dataWithBytesNoCopy:(void*)data length:length freeWhenDone:NO] withCompletionQueue:m_neFilterSourceQueue completionHandler:^(NEFilterSourceStatus status, NSData *) {
+       m_neFilterSourceStatus = status;
+       deref();
+    }];
+#endif
 }
     
 void ContentFilter::finishedAddingData()
 {
     ASSERT(needsMoreData());
-    ASSERT(![m_replacementData.get() length]);
-    m_replacementData = [m_platformContentFilter dataComplete];
+
+    if (m_platformContentFilter) {
+        ASSERT(![m_replacementData.get() length]);
+        m_replacementData = [m_platformContentFilter dataComplete];
+    }
+
+#if HAVE(NE_FILTER_SOURCE)
+    if (!m_neFilterSource)
+        return;
+
+    ref();
+    m_neFilterSourceSemaphore = dispatch_semaphore_create(0);
+    [m_neFilterSource dataCompleteWithCompletionQueue:m_neFilterSourceQueue completionHandler:^(NEFilterSourceStatus status, NSData *) {
+        m_neFilterSourceStatus = status;
+        deref();
+
+        dispatch_semaphore_signal(m_neFilterSourceSemaphore);
+    }];
+    
+    // FIXME: We have to block here since DocumentLoader expects to have a
+    // blocked/not blocked answer from the filter immediately after calling
+    // finishedAddingData(). We should find a way to make this asynchronous.
+    dispatch_semaphore_wait(m_neFilterSourceSemaphore, DISPATCH_TIME_FOREVER);
+    dispatch_release(m_neFilterSourceSemaphore);
+#endif
+
     ASSERT(!needsMoreData());
 }
 
 bool ContentFilter::needsMoreData() const
 {
-    return [m_platformContentFilter filterState] == kWFEStateBuffering;
+    return [m_platformContentFilter filterState] == kWFEStateBuffering
+#if HAVE(NE_FILTER_SOURCE)
+        || m_neFilterSourceStatus == NEFilterSourceStatusNeedsMoreData
+#endif
+    ;
 }
 
 bool ContentFilter::didBlockData() const
 {
-    return [m_platformContentFilter wasBlocked];
+    return [m_platformContentFilter wasBlocked]
+#if HAVE(NE_FILTER_SOURCE)
+        || m_neFilterSourceStatus == NEFilterSourceStatusBlock
+#endif
+    ;
 }
 
 const char* ContentFilter::getReplacementData(int& length) const
 {
+    // FIXME: This will return a null pointer with length 0 when using
+    // NEFilterSource. We need to show a proper error page instead.
     ASSERT(!needsMoreData());
-    length = [m_replacementData.get() length];
-    return static_cast<const char*>([m_replacementData.get() bytes]);
+    length = [m_replacementData length];
+    return static_cast<const char*>([m_replacementData bytes]);
 }
 
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to