<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[181523] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/181523">181523</a></dd>
<dt>Author</dt> <dd>aestes@apple.com</dd>
<dt>Date</dt> <dd>2015-03-15 22:44:03 -0700 (Sun, 15 Mar 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[Content Filtering] Adopt new NEFilterSource SPI
https://bugs.webkit.org/show_bug.cgi?id=142710
rdar://problem/19023855

Reviewed by Dan Bernstein.

Teach NetworkExtensionContentFilter to use a new, alternate NEFilterSource SPI on platforms where it is available.

* platform/ContentFilter.cpp:
(WebCore::ContentFilter::types): Renamed HAVE(NE_FILTER_SOURCE) to HAVE(NETWORK_EXTENSION).
* platform/cocoa/NetworkExtensionContentFilter.h: Renamed member variables to remove redundancy, forward-declared NEFilterSourceStatus,
added a dispatch_semaphore member variable to avoid creating and destroying multiple semaphores, and made m_originalData a SharedBuffer.
* platform/cocoa/NetworkExtensionContentFilter.mm:
(decisionInfoReplacementData): Returned the replacement data from a decision handler info dictionary.
(WebCore::createNEFilterSource): Created either an old-style or new-style NEFilterSource object.
(WebCore::NetworkExtensionContentFilter::NetworkExtensionContentFilter): Called receivedResponse:decisionHandler: when using the new SPI.
(WebCore::NetworkExtensionContentFilter::~NetworkExtensionContentFilter): Released the dispatch_semaphore.
(WebCore::NetworkExtensionContentFilter::addData): Appended the copied NSData to m_originalData, avoiding an additional copy previously
being made by NSMutableData. Used the new receivedData:decisionHandler: SPI when appropriate.
(WebCore::NetworkExtensionContentFilter::finishedAddingData): Used the new finishedLoadingWithDecisionHandler: SPI when appropriate.
(WebCore::NetworkExtensionContentFilter::needsMoreData): Changed m_neFilterSourceStatus to m_status.
(WebCore::NetworkExtensionContentFilter::didBlockData): Ditto.
(WebCore::NetworkExtensionContentFilter::getReplacementData): Returned the replacement data from NEFilterSource if the load was blocked.
Otherwise, returned the original data.
(WebCore::NetworkExtensionContentFilter::handleDecision): Added a helper to set m_status and m_replacementData, and to signal m_semaphore.
* platform/spi/cocoa/NEFilterSourceSPI.h: Declared the new NEFilterSource SPI on platforms that support it.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformContentFiltercpp">trunk/Source/WebCore/platform/ContentFilter.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformcocoaNetworkExtensionContentFilterh">trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.h</a></li>
<li><a href="#trunkSourceWebCoreplatformcocoaNetworkExtensionContentFiltermm">trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformspicocoaNEFilterSourceSPIh">trunk/Source/WebCore/platform/spi/cocoa/NEFilterSourceSPI.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (181522 => 181523)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-03-16 05:34:27 UTC (rev 181522)
+++ trunk/Source/WebCore/ChangeLog        2015-03-16 05:44:03 UTC (rev 181523)
</span><span class="lines">@@ -1,3 +1,32 @@
</span><ins>+2015-03-15  Andy Estes  &lt;aestes@apple.com&gt;
+
+        [Content Filtering] Adopt new NEFilterSource SPI
+        https://bugs.webkit.org/show_bug.cgi?id=142710
+        rdar://problem/19023855
+
+        Reviewed by Dan Bernstein.
+
+        Teach NetworkExtensionContentFilter to use a new, alternate NEFilterSource SPI on platforms where it is available.
+
+        * platform/ContentFilter.cpp:
+        (WebCore::ContentFilter::types): Renamed HAVE(NE_FILTER_SOURCE) to HAVE(NETWORK_EXTENSION).
+        * platform/cocoa/NetworkExtensionContentFilter.h: Renamed member variables to remove redundancy, forward-declared NEFilterSourceStatus,
+        added a dispatch_semaphore member variable to avoid creating and destroying multiple semaphores, and made m_originalData a SharedBuffer.
+        * platform/cocoa/NetworkExtensionContentFilter.mm:
+        (decisionInfoReplacementData): Returned the replacement data from a decision handler info dictionary.
+        (WebCore::createNEFilterSource): Created either an old-style or new-style NEFilterSource object.
+        (WebCore::NetworkExtensionContentFilter::NetworkExtensionContentFilter): Called receivedResponse:decisionHandler: when using the new SPI.
+        (WebCore::NetworkExtensionContentFilter::~NetworkExtensionContentFilter): Released the dispatch_semaphore.
+        (WebCore::NetworkExtensionContentFilter::addData): Appended the copied NSData to m_originalData, avoiding an additional copy previously
+        being made by NSMutableData. Used the new receivedData:decisionHandler: SPI when appropriate.
+        (WebCore::NetworkExtensionContentFilter::finishedAddingData): Used the new finishedLoadingWithDecisionHandler: SPI when appropriate.
+        (WebCore::NetworkExtensionContentFilter::needsMoreData): Changed m_neFilterSourceStatus to m_status.
+        (WebCore::NetworkExtensionContentFilter::didBlockData): Ditto.
+        (WebCore::NetworkExtensionContentFilter::getReplacementData): Returned the replacement data from NEFilterSource if the load was blocked.
+        Otherwise, returned the original data.
+        (WebCore::NetworkExtensionContentFilter::handleDecision): Added a helper to set m_status and m_replacementData, and to signal m_semaphore.
+        * platform/spi/cocoa/NEFilterSourceSPI.h: Declared the new NEFilterSource SPI on platforms that support it.
+
</ins><span class="cx"> 2015-03-15  Brent Fulgham  &lt;bfulgham@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Scroll snap points are not supported on iframe content
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformContentFiltercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/ContentFilter.cpp (181522 => 181523)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/ContentFilter.cpp        2015-03-16 05:34:27 UTC (rev 181522)
+++ trunk/Source/WebCore/platform/ContentFilter.cpp        2015-03-16 05:44:03 UTC (rev 181523)
</span><span class="lines">@@ -40,7 +40,7 @@
</span><span class="cx">     static NeverDestroyed&lt;Vector&lt;ContentFilter::Type&gt;&gt; types {
</span><span class="cx">         Vector&lt;ContentFilter::Type&gt; {
</span><span class="cx">             type&lt;ParentalControlsContentFilter&gt;(),
</span><del>-#if HAVE(NE_FILTER_SOURCE)
</del><ins>+#if HAVE(NETWORK_EXTENSION)
</ins><span class="cx">             type&lt;NetworkExtensionContentFilter&gt;()
</span><span class="cx"> #endif
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformcocoaNetworkExtensionContentFilterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.h (181522 => 181523)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.h        2015-03-16 05:34:27 UTC (rev 181522)
+++ trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.h        2015-03-16 05:44:03 UTC (rev 181523)
</span><span class="lines">@@ -27,12 +27,20 @@
</span><span class="cx"> #define NetworkExtensionContentFilter_h
</span><span class="cx"> 
</span><span class="cx"> #include &quot;ContentFilter.h&quot;
</span><ins>+#include &quot;SharedBuffer.h&quot;
+#include &lt;objc/NSObjCRuntime.h&gt;
</ins><span class="cx"> #include &lt;wtf/Compiler.h&gt;
</span><ins>+#include &lt;wtf/OSObjectPtr.h&gt;
+#include &lt;wtf/Ref.h&gt;
</ins><span class="cx"> #include &lt;wtf/RetainPtr.h&gt;
</span><span class="cx"> 
</span><del>-#define HAVE_NE_FILTER_SOURCE TARGET_OS_EMBEDDED || (!TARGET_OS_IPHONE &amp;&amp; __MAC_OS_X_VERSION_MIN_REQUIRED &gt;= 101000 &amp;&amp; CPU(X86_64))
</del><ins>+#define HAVE_NETWORK_EXTENSION PLATFORM(IOS) || (PLATFORM(MAC) &amp;&amp; __MAC_OS_X_VERSION_MIN_REQUIRED &gt;= 101000 &amp;&amp; CPU(X86_64))
</ins><span class="cx"> 
</span><ins>+enum NEFilterSourceStatus : NSInteger;
+
</ins><span class="cx"> OBJC_CLASS NEFilterSource;
</span><ins>+OBJC_CLASS NSData;
+OBJC_CLASS NSDictionary;
</ins><span class="cx"> OBJC_CLASS NSMutableData;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -46,7 +54,6 @@
</span><span class="cx">     static bool canHandleResponse(const ResourceResponse&amp;);
</span><span class="cx">     static std::unique_ptr&lt;NetworkExtensionContentFilter&gt; create(const ResourceResponse&amp;);
</span><span class="cx"> 
</span><del>-    ~NetworkExtensionContentFilter() override;
</del><span class="cx">     void addData(const char* data, int length) override;
</span><span class="cx">     void finishedAddingData() override;
</span><span class="cx">     bool needsMoreData() const override;
</span><span class="lines">@@ -56,11 +63,14 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     explicit NetworkExtensionContentFilter(const ResourceResponse&amp;);
</span><ins>+    void handleDecision(NEFilterSourceStatus, NSData *replacementData);
</ins><span class="cx"> 
</span><del>-    long m_neFilterSourceStatus;
</del><ins>+    NEFilterSourceStatus m_status;
+    OSObjectPtr&lt;dispatch_queue_t&gt; m_queue;
+    OSObjectPtr&lt;dispatch_semaphore_t&gt; m_semaphore;
+    Ref&lt;SharedBuffer&gt; m_originalData;
+    RetainPtr&lt;NSData&gt; m_replacementData;
</ins><span class="cx">     RetainPtr&lt;NEFilterSource&gt; m_neFilterSource;
</span><del>-    dispatch_queue_t m_neFilterSourceQueue;
-    RetainPtr&lt;NSMutableData&gt; m_originalData;
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformcocoaNetworkExtensionContentFiltermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.mm (181522 => 181523)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.mm        2015-03-16 05:34:27 UTC (rev 181522)
+++ trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.mm        2015-03-16 05:44:03 UTC (rev 181523)
</span><span class="lines">@@ -26,7 +26,7 @@
</span><span class="cx"> #import &quot;config.h&quot;
</span><span class="cx"> #import &quot;NetworkExtensionContentFilter.h&quot;
</span><span class="cx"> 
</span><del>-#if HAVE(NE_FILTER_SOURCE)
</del><ins>+#if HAVE(NETWORK_EXTENSION)
</ins><span class="cx"> 
</span><span class="cx"> #import &quot;NEFilterSourceSPI.h&quot;
</span><span class="cx"> #import &quot;ResourceResponse.h&quot;
</span><span class="lines">@@ -36,6 +36,18 @@
</span><span class="cx"> SOFT_LINK_FRAMEWORK(NetworkExtension);
</span><span class="cx"> SOFT_LINK_CLASS(NetworkExtension, NEFilterSource);
</span><span class="cx"> 
</span><ins>+#if HAVE(MODERN_NE_FILTER_SOURCE)
+// FIXME: &lt;rdar://problem/20165664&gt; Expose decisionHandler dictionary keys as NSString constants in NEFilterSource.h
+static NSString * const optionsPageData = @&quot;PageData&quot;;
+
+static inline NSData *replacementDataFromDecisionInfo(NSDictionary *decisionInfo)
+{
+    id replacementData = decisionInfo[optionsPageData];
+    ASSERT(!replacementData || [replacementData isKindOfClass:[NSData class]]);
+    return replacementData;
+}
+#endif
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> bool NetworkExtensionContentFilter::canHandleResponse(const ResourceResponse&amp; response)
</span><span class="lines">@@ -48,80 +60,103 @@
</span><span class="cx">     return std::make_unique&lt;NetworkExtensionContentFilter&gt;(response);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static inline RetainPtr&lt;NEFilterSource&gt; createNEFilterSource(const URL&amp; url, dispatch_queue_t decisionQueue)
+{
+#if HAVE(MODERN_NE_FILTER_SOURCE)
+    UNUSED_PARAM(url);
+    return adoptNS([allocNEFilterSourceInstance() initWithDecisionQueue:decisionQueue]);
+#else
+    UNUSED_PARAM(decisionQueue);
+    return adoptNS([allocNEFilterSourceInstance() initWithURL:url direction:NEFilterSourceDirectionInbound socketIdentifier:0]);
+#endif
+}
+
</ins><span class="cx"> NetworkExtensionContentFilter::NetworkExtensionContentFilter(const ResourceResponse&amp; response)
</span><del>-    : m_neFilterSourceStatus { NEFilterSourceStatusNeedsMoreData }
-    , m_neFilterSource { adoptNS([allocNEFilterSourceInstance() initWithURL:[response.nsURLResponse() URL] direction:NEFilterSourceDirectionInbound socketIdentifier:0]) }
-    , m_neFilterSourceQueue { dispatch_queue_create(&quot;com.apple.WebCore.NEFilterSourceQueue&quot;, DISPATCH_QUEUE_SERIAL) }
</del><ins>+    : m_status { NEFilterSourceStatusNeedsMoreData }
+    , m_queue { adoptOSObject(dispatch_queue_create(&quot;com.apple.WebCore.NEFilterSourceQueue&quot;, DISPATCH_QUEUE_SERIAL)) }
+    , m_semaphore { adoptOSObject(dispatch_semaphore_create(0)) }
+    , m_originalData { *SharedBuffer::create() }
+    , m_neFilterSource { createNEFilterSource(response.url(), m_queue.get()) }
</ins><span class="cx"> {
</span><span class="cx">     ASSERT([getNEFilterSourceClass() filterRequired]);
</span><span class="cx"> 
</span><del>-    long long expectedContentSize = [response.nsURLResponse() expectedContentLength];
-    if (expectedContentSize &lt; 0)
-        m_originalData = adoptNS([[NSMutableData alloc] init]);
-    else
-        m_originalData = adoptNS([[NSMutableData alloc] initWithCapacity:(NSUInteger)expectedContentSize]);
-}
</del><ins>+#if HAVE(MODERN_NE_FILTER_SOURCE)
+    [m_neFilterSource receivedResponse:response.nsURLResponse() decisionHandler:[this](NEFilterSourceStatus status, NSDictionary *decisionInfo) {
+        handleDecision(status, replacementDataFromDecisionInfo(decisionInfo));
+    }];
</ins><span class="cx"> 
</span><del>-NetworkExtensionContentFilter::~NetworkExtensionContentFilter()
-{
-    dispatch_release(m_neFilterSourceQueue);
</del><ins>+    // FIXME: We have to block here since DocumentLoader expects to have a
+    // blocked/not blocked answer from the filter immediately after calling
+    // addData(). We should find a way to make this asynchronous.
+    dispatch_semaphore_wait(m_semaphore.get(), DISPATCH_TIME_FOREVER);
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void NetworkExtensionContentFilter::addData(const char* data, int length)
</span><span class="cx"> {
</span><ins>+    RetainPtr&lt;NSData&gt; copiedData { [NSData dataWithBytes:(void*)data length:length] };
+
</ins><span class="cx">     // FIXME: NEFilterSource doesn't buffer data like WebFilterEvaluator does,
</span><span class="cx">     // so we need to do it ourselves so getReplacementData() can return the
</span><span class="cx">     // original bytes back to the loader. We should find a way to remove this
</span><span class="cx">     // additional copy.
</span><del>-    [m_originalData appendBytes:data length:length];
</del><ins>+    m_originalData-&gt;append((CFDataRef)copiedData.get());
</ins><span class="cx"> 
</span><del>-    dispatch_semaphore_t neFilterSourceSemaphore = dispatch_semaphore_create(0);
-    [m_neFilterSource addData:[NSData dataWithBytes:(void*)data length:length] withCompletionQueue:m_neFilterSourceQueue completionHandler:^(NEFilterSourceStatus status, NSData *) {
-        m_neFilterSourceStatus = status;
-        dispatch_semaphore_signal(neFilterSourceSemaphore);
</del><ins>+#if HAVE(MODERN_NE_FILTER_SOURCE)
+    [m_neFilterSource receivedData:copiedData.get() decisionHandler:[this](NEFilterSourceStatus status, NSDictionary *decisionInfo) {
+        handleDecision(status, replacementDataFromDecisionInfo(decisionInfo));
</ins><span class="cx">     }];
</span><ins>+#else
+    [m_neFilterSource addData:copiedData.get() withCompletionQueue:m_queue.get() completionHandler:[this](NEFilterSourceStatus status, NSData *replacementData) {
+        ASSERT(!replacementData);
+        handleDecision(status, replacementData);
+    }];
+#endif
</ins><span class="cx"> 
</span><span class="cx">     // FIXME: We have to block here since DocumentLoader expects to have a
</span><span class="cx">     // blocked/not blocked answer from the filter immediately after calling
</span><span class="cx">     // addData(). We should find a way to make this asynchronous.
</span><del>-    dispatch_semaphore_wait(neFilterSourceSemaphore, DISPATCH_TIME_FOREVER);
-    dispatch_release(neFilterSourceSemaphore);
</del><ins>+    dispatch_semaphore_wait(m_semaphore.get(), DISPATCH_TIME_FOREVER);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void NetworkExtensionContentFilter::finishedAddingData()
</span><span class="cx"> {
</span><del>-    dispatch_semaphore_t neFilterSourceSemaphore = dispatch_semaphore_create(0);
-    [m_neFilterSource dataCompleteWithCompletionQueue:m_neFilterSourceQueue completionHandler:^(NEFilterSourceStatus status, NSData *) {
-        m_neFilterSourceStatus = status;
-        dispatch_semaphore_signal(neFilterSourceSemaphore);
</del><ins>+#if HAVE(MODERN_NE_FILTER_SOURCE)
+    [m_neFilterSource finishedLoadingWithDecisionHandler:[this](NEFilterSourceStatus status, NSDictionary *decisionInfo) {
+        handleDecision(status, replacementDataFromDecisionInfo(decisionInfo));
</ins><span class="cx">     }];
</span><ins>+#else
+    [m_neFilterSource dataCompleteWithCompletionQueue:m_queue.get() completionHandler:[this](NEFilterSourceStatus status, NSData *replacementData) {
+        ASSERT(!replacementData);
+        handleDecision(status, replacementData);
+    }];
+#endif
</ins><span class="cx"> 
</span><span class="cx">     // FIXME: We have to block here since DocumentLoader expects to have a
</span><span class="cx">     // blocked/not blocked answer from the filter immediately after calling
</span><span class="cx">     // finishedAddingData(). We should find a way to make this asynchronous.
</span><del>-    dispatch_semaphore_wait(neFilterSourceSemaphore, DISPATCH_TIME_FOREVER);
-    dispatch_release(neFilterSourceSemaphore);
</del><ins>+    dispatch_semaphore_wait(m_semaphore.get(), DISPATCH_TIME_FOREVER);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool NetworkExtensionContentFilter::needsMoreData() const
</span><span class="cx"> {
</span><del>-    return m_neFilterSourceStatus == NEFilterSourceStatusNeedsMoreData;
</del><ins>+    return m_status == NEFilterSourceStatusNeedsMoreData;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool NetworkExtensionContentFilter::didBlockData() const
</span><span class="cx"> {
</span><del>-    return m_neFilterSourceStatus == NEFilterSourceStatusBlock;
</del><ins>+    return m_status == NEFilterSourceStatusBlock;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> const char* NetworkExtensionContentFilter::getReplacementData(int&amp; length) const
</span><span class="cx"> {
</span><span class="cx">     if (didBlockData()) {
</span><del>-        length = 0;
-        return nullptr;
</del><ins>+        length = [m_replacementData length];
+        return static_cast&lt;const char*&gt;([m_replacementData bytes]);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    length = [m_originalData length];
-    return static_cast&lt;const char*&gt;([m_originalData bytes]);
</del><ins>+    length = m_originalData-&gt;size();
+    return m_originalData-&gt;data();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> ContentFilterUnblockHandler NetworkExtensionContentFilter::unblockHandler() const
</span><span class="lines">@@ -129,6 +164,14 @@
</span><span class="cx">     return { };
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void NetworkExtensionContentFilter::handleDecision(NEFilterSourceStatus status, NSData *replacementData)
+{
+    m_status = status;
+    if (status == NEFilterSourceStatusBlock)
+        m_replacementData = replacementData;
+    dispatch_semaphore_signal(m_semaphore.get());
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><del>-#endif // HAVE(NE_FILTER_SOURCE)
</del><ins>+#endif // HAVE(NETWORK_EXTENSION)
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformspicocoaNEFilterSourceSPIh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/spi/cocoa/NEFilterSourceSPI.h (181522 => 181523)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/spi/cocoa/NEFilterSourceSPI.h        2015-03-16 05:34:27 UTC (rev 181522)
+++ trunk/Source/WebCore/platform/spi/cocoa/NEFilterSourceSPI.h        2015-03-16 05:44:03 UTC (rev 181523)
</span><span class="lines">@@ -23,6 +23,8 @@
</span><span class="cx">  * THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><ins>+#define HAVE_MODERN_NE_FILTER_SOURCE (PLATFORM(MAC) &amp;&amp; __MAC_OS_X_VERSION_MIN_REQUIRED &gt;= 101100) || (PLATFORM(IOS) &amp;&amp; __IPHONE_OS_VERSION_MIN_REQUIRED &gt;= 90000)
+
</ins><span class="cx"> #if USE(APPLE_INTERNAL_SDK)
</span><span class="cx"> 
</span><span class="cx"> #import &lt;NetworkExtension/NEFilterSource.h&gt;
</span><span class="lines">@@ -44,7 +46,7 @@
</span><span class="cx"> @interface NEFilterSource : NSObject
</span><span class="cx"> @end
</span><span class="cx"> 
</span><del>-@interface NEFilterSource (Details)
</del><ins>+@interface NEFilterSource (WKLegacyDetails)
</ins><span class="cx"> + (BOOL)filterRequired;
</span><span class="cx"> - (id)initWithURL:(NSURL *)url direction:(NEFilterSourceDirection)direction socketIdentifier:(uint64_t)socketIdentifier;
</span><span class="cx"> - (void)addData:(NSData *)data withCompletionQueue:(dispatch_queue_t)queue completionHandler:(void (^)(NEFilterSourceStatus, NSData *))completionHandler;
</span><span class="lines">@@ -55,4 +57,17 @@
</span><span class="cx"> @property (readonly) uint64_t socketIdentifier;
</span><span class="cx"> @end
</span><span class="cx"> 
</span><ins>+#if HAVE(MODERN_NE_FILTER_SOURCE)
+typedef void (^NEFilterSourceDecisionHandler)(NEFilterSourceStatus, NSDictionary *);
+
+@interface NEFilterSource (WKModernDetails)
+- (id)initWithDecisionQueue:(dispatch_queue_t)queue;
+- (void)willSendRequest:(NSURLRequest *)request decisionHandler:(NEFilterSourceDecisionHandler)decisionHandler;
+- (void)receivedResponse:(NSURLResponse *)response decisionHandler:(NEFilterSourceDecisionHandler)decisionHandler;
+- (void)receivedData:(NSData *)data decisionHandler:(NEFilterSourceDecisionHandler)decisionHandler;
+- (void)finishedLoadingWithDecisionHandler:(NEFilterSourceDecisionHandler)decisionHandler;
+- (void)remediateWithDecisionHandler:(NEFilterSourceDecisionHandler)decisionHandler;
+@end
</ins><span class="cx"> #endif
</span><ins>+
+#endif
</ins></span></pre>
</div>
</div>

</body>
</html>