Changeset 181037 in webkit


Ignore:
Timestamp:
Mar 4, 2015 2:43:35 PM (9 years ago)
Author:
aestes@apple.com
Message:

[Content Filtering] Make it easier to add new content filters
https://bugs.webkit.org/show_bug.cgi?id=142255

Reviewed by Sam Weinig.

ContentFilter was becoming a bit of a mess, with both the WebFilterEvaluator and NEFilterSource implementations
awkwardly living side-by-side. This patch cleans things up by moving these implementations into two separate
classes and turning ContentFilter itself into an abstract interface that each implements. A new class called
ContentFilterCollection, which also inherits from ContentFilter, manages the collection of individual content
filters and is vended to the rest of the system by ContentFilter::createIfNeeded().

This refactoring will make it easier to add a third type of content filter in a follow-on patch, namely a mock
content filter for testing purposes.

  • WebCore.xcodeproj/project.pbxproj:
  • loader/DocumentLoader.cpp:

(WebCore::DocumentLoader::responseReceived): Called ContentFilter::createIfNeeded() instead of instantiating a ContentFilter directly.

  • platform/ContentFilter.h:

(WebCore::ContentFilter::~ContentFilter):

  • platform/cocoa/NetworkExtensionContentFilter.h: Copied from Source/WebCore/platform/ContentFilter.h.
  • platform/cocoa/NetworkExtensionContentFilter.mm: Added.

(WebCore::NetworkExtensionContentFilter::canHandleResponse): Moved NEFilterSource code from ContentFilterMac.mm to here.
(WebCore::NetworkExtensionContentFilter::create): Ditto.
(WebCore::NetworkExtensionContentFilter::NetworkExtensionContentFilter): Ditto.
(WebCore::NetworkExtensionContentFilter::~NetworkExtensionContentFilter): Ditto.
(WebCore::NetworkExtensionContentFilter::addData): Ditto.
(WebCore::NetworkExtensionContentFilter::finishedAddingData): Ditto.
(WebCore::NetworkExtensionContentFilter::needsMoreData): Ditto.
(WebCore::NetworkExtensionContentFilter::didBlockData): Ditto.
(WebCore::NetworkExtensionContentFilter::getReplacementData): Ditto.
(WebCore::NetworkExtensionContentFilter::unblockHandler): Ditto.

  • platform/cocoa/ParentalControlsContentFilter.h: Copied from Source/WebCore/platform/ContentFilter.h.
  • platform/cocoa/ParentalControlsContentFilter.mm: Added.

(WebCore::ParentalControlsContentFilter::canHandleResponse): Moved WebFilterEvaluator code from ContentFilterMac.mm to here.
(WebCore::ParentalControlsContentFilter::create): Ditto.
(WebCore::ParentalControlsContentFilter::ParentalControlsContentFilter): Ditto.
(WebCore::ParentalControlsContentFilter::addData): Ditto.
(WebCore::ParentalControlsContentFilter::finishedAddingData): Ditto.
(WebCore::ParentalControlsContentFilter::needsMoreData): Ditto.
(WebCore::ParentalControlsContentFilter::didBlockData): Ditto.
(WebCore::ParentalControlsContentFilter::getReplacementData): Ditto.
(WebCore::ParentalControlsContentFilter::unblockHandler): Ditto.

  • platform/mac/ContentFilterMac.mm:

(WebCore::contentFilterType): Added a helper function template that creates a new ContentFilterType.
(WebCore::contentFilterTypes): Registered a ContentFilterType for each type of content filter.
(WebCore::ContentFilter::createIfNeeded): Created a ContentFilterCollection containing each content filter that can handle the given response.
(WebCore::ContentFilterCollection::ContentFilterCollection): Constructs a ContentFilterCollection given a Vector of content filters.
(WebCore::ContentFilterCollection::addData): Forwarded the call to each content filter in m_contentFilters.
(WebCore::ContentFilterCollection::finishedAddingData): Ditto.
(WebCore::ContentFilterCollection::needsMoreData): Ditto.
(WebCore::ContentFilterCollection::didBlockData): Ditto.
(WebCore::ContentFilterCollection::getReplacementData): Returned replacement data for the first filter that blocked the load.
If no filter blocked the load, returned the first filter's replacement data.
(WebCore::ContentFilterCollection::unblockHandler): Returned the unblock handler for the first filter that blocked the load.
(WebCore::ContentFilter::ContentFilter): Deleted.
(WebCore::ContentFilter::~ContentFilter): Deleted.
(WebCore::ContentFilter::canHandleResponse): Deleted.
(WebCore::ContentFilter::addData): Deleted.
(WebCore::ContentFilter::finishedAddingData): Deleted.
(WebCore::ContentFilter::needsMoreData): Deleted.
(WebCore::ContentFilter::didBlockData): Deleted.
(WebCore::ContentFilter::getReplacementData): Deleted.
(WebCore::ContentFilter::unblockHandler): Deleted.

Location:
trunk/Source/WebCore
Files:
2 added
5 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r181036 r181037  
     12015-03-03  Andy Estes  <aestes@apple.com>
     2
     3        [Content Filtering] Make it easier to add new content filters
     4        https://bugs.webkit.org/show_bug.cgi?id=142255
     5
     6        Reviewed by Sam Weinig.
     7
     8        ContentFilter was becoming a bit of a mess, with both the WebFilterEvaluator and NEFilterSource implementations
     9        awkwardly living side-by-side. This patch cleans things up by moving these implementations into two separate
     10        classes and turning ContentFilter itself into an abstract interface that each implements. A new class called
     11        ContentFilterCollection, which also inherits from ContentFilter, manages the collection of individual content
     12        filters and is vended to the rest of the system by ContentFilter::createIfNeeded().
     13
     14        This refactoring will make it easier to add a third type of content filter in a follow-on patch, namely a mock
     15        content filter for testing purposes.
     16
     17        * WebCore.xcodeproj/project.pbxproj:
     18        * loader/DocumentLoader.cpp:
     19        (WebCore::DocumentLoader::responseReceived): Called ContentFilter::createIfNeeded() instead of instantiating a ContentFilter directly.
     20        * platform/ContentFilter.h:
     21        (WebCore::ContentFilter::~ContentFilter):
     22        * platform/cocoa/NetworkExtensionContentFilter.h: Copied from Source/WebCore/platform/ContentFilter.h.
     23        * platform/cocoa/NetworkExtensionContentFilter.mm: Added.
     24        (WebCore::NetworkExtensionContentFilter::canHandleResponse): Moved NEFilterSource code from ContentFilterMac.mm to here.
     25        (WebCore::NetworkExtensionContentFilter::create): Ditto.
     26        (WebCore::NetworkExtensionContentFilter::NetworkExtensionContentFilter): Ditto.
     27        (WebCore::NetworkExtensionContentFilter::~NetworkExtensionContentFilter): Ditto.
     28        (WebCore::NetworkExtensionContentFilter::addData): Ditto.
     29        (WebCore::NetworkExtensionContentFilter::finishedAddingData): Ditto.
     30        (WebCore::NetworkExtensionContentFilter::needsMoreData): Ditto.
     31        (WebCore::NetworkExtensionContentFilter::didBlockData): Ditto.
     32        (WebCore::NetworkExtensionContentFilter::getReplacementData): Ditto.
     33        (WebCore::NetworkExtensionContentFilter::unblockHandler): Ditto.
     34        * platform/cocoa/ParentalControlsContentFilter.h: Copied from Source/WebCore/platform/ContentFilter.h.
     35        * platform/cocoa/ParentalControlsContentFilter.mm: Added.
     36        (WebCore::ParentalControlsContentFilter::canHandleResponse): Moved WebFilterEvaluator code from ContentFilterMac.mm to here.
     37        (WebCore::ParentalControlsContentFilter::create): Ditto.
     38        (WebCore::ParentalControlsContentFilter::ParentalControlsContentFilter): Ditto.
     39        (WebCore::ParentalControlsContentFilter::addData): Ditto.
     40        (WebCore::ParentalControlsContentFilter::finishedAddingData): Ditto.
     41        (WebCore::ParentalControlsContentFilter::needsMoreData): Ditto.
     42        (WebCore::ParentalControlsContentFilter::didBlockData): Ditto.
     43        (WebCore::ParentalControlsContentFilter::getReplacementData): Ditto.
     44        (WebCore::ParentalControlsContentFilter::unblockHandler): Ditto.
     45        * platform/mac/ContentFilterMac.mm:
     46        (WebCore::contentFilterType): Added a helper function template that creates a new ContentFilterType.
     47        (WebCore::contentFilterTypes): Registered a ContentFilterType for each type of content filter.
     48        (WebCore::ContentFilter::createIfNeeded): Created a ContentFilterCollection containing each content filter that can handle the given response.
     49        (WebCore::ContentFilterCollection::ContentFilterCollection): Constructs a ContentFilterCollection given a Vector of content filters.
     50        (WebCore::ContentFilterCollection::addData): Forwarded the call to each content filter in m_contentFilters.
     51        (WebCore::ContentFilterCollection::finishedAddingData): Ditto.
     52        (WebCore::ContentFilterCollection::needsMoreData): Ditto.
     53        (WebCore::ContentFilterCollection::didBlockData): Ditto.
     54        (WebCore::ContentFilterCollection::getReplacementData): Returned replacement data for the first filter that blocked the load.
     55        If no filter blocked the load, returned the first filter's replacement data.
     56        (WebCore::ContentFilterCollection::unblockHandler): Returned the unblock handler for the first filter that blocked the load.
     57        (WebCore::ContentFilter::ContentFilter): Deleted.
     58        (WebCore::ContentFilter::~ContentFilter): Deleted.
     59        (WebCore::ContentFilter::canHandleResponse): Deleted.
     60        (WebCore::ContentFilter::addData): Deleted.
     61        (WebCore::ContentFilter::finishedAddingData): Deleted.
     62        (WebCore::ContentFilter::needsMoreData): Deleted.
     63        (WebCore::ContentFilter::didBlockData): Deleted.
     64        (WebCore::ContentFilter::getReplacementData): Deleted.
     65        (WebCore::ContentFilter::unblockHandler): Deleted.
     66
    1672015-03-04  David Kilzer  <ddkilzer@apple.com>
    268
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r181000 r181037  
    38053805                A17C81220F2A5CF7005DAAEB /* HTMLElementFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A17C81200F2A5CF7005DAAEB /* HTMLElementFactory.cpp */; };
    38063806                A17C81230F2A5CF7005DAAEB /* HTMLElementFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = A17C81210F2A5CF7005DAAEB /* HTMLElementFactory.h */; };
     3807                A18890AE1AA13F250026C301 /* ParentalControlsContentFilter.mm in Sources */ = {isa = PBXBuildFile; fileRef = A18890AC1AA13F250026C301 /* ParentalControlsContentFilter.mm */; };
     3808                A18890AF1AA13F250026C301 /* ParentalControlsContentFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = A18890AD1AA13F250026C301 /* ParentalControlsContentFilter.h */; };
    38073809                A19D93461A9FEC7200B46C24 /* NEFilterSourceSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = A19D93441A9FEC7200B46C24 /* NEFilterSourceSPI.h */; };
    38083810                A19D93471A9FEC7200B46C24 /* WebFilterEvaluatorSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = A19D93451A9FEC7200B46C24 /* WebFilterEvaluatorSPI.h */; };
     3811                A19D934A1AA11B1E00B46C24 /* NetworkExtensionContentFilter.mm in Sources */ = {isa = PBXBuildFile; fileRef = A19D93481AA11B1E00B46C24 /* NetworkExtensionContentFilter.mm */; };
     3812                A19D934B1AA11B1E00B46C24 /* NetworkExtensionContentFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = A19D93491AA11B1E00B46C24 /* NetworkExtensionContentFilter.h */; };
    38093813                A1C797181883DD82000F5E1F /* DOMGestureEvent.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 0F54DCDD1880F901003EEDBB /* DOMGestureEvent.h */; };
    38103814                A1C797191883DDED000F5E1F /* DOMTouch.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 0F54DCCD1880F867003EEDBB /* DOMTouch.h */; };
     
    1103411038                A17C81200F2A5CF7005DAAEB /* HTMLElementFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLElementFactory.cpp; sourceTree = "<group>"; };
    1103511039                A17C81210F2A5CF7005DAAEB /* HTMLElementFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLElementFactory.h; sourceTree = "<group>"; };
     11040                A18890AC1AA13F250026C301 /* ParentalControlsContentFilter.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ParentalControlsContentFilter.mm; sourceTree = "<group>"; };
     11041                A18890AD1AA13F250026C301 /* ParentalControlsContentFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParentalControlsContentFilter.h; sourceTree = "<group>"; };
    1103611042                A19D93441A9FEC7200B46C24 /* NEFilterSourceSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NEFilterSourceSPI.h; sourceTree = "<group>"; };
    1103711043                A19D93451A9FEC7200B46C24 /* WebFilterEvaluatorSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebFilterEvaluatorSPI.h; sourceTree = "<group>"; };
     11044                A19D93481AA11B1E00B46C24 /* NetworkExtensionContentFilter.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkExtensionContentFilter.mm; sourceTree = "<group>"; };
     11045                A19D93491AA11B1E00B46C24 /* NetworkExtensionContentFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkExtensionContentFilter.h; sourceTree = "<group>"; };
    1103811046                A1C7971C1883E51F000F5E1F /* DOMHTMLTextAreaElementPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMHTMLTextAreaElementPrivate.h; sourceTree = "<group>"; };
    1103911047                A1C7FAA1133A5D3500D6732D /* JSXPathResultCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSXPathResultCustom.cpp; sourceTree = "<group>"; };
     
    1872418732                                1A0409DB1A4360B5009E47F3 /* MachSendRight.h */,
    1872518733                                ADB6B29718FB90240081963E /* MemoryPressureHandlerCocoa.mm */,
     18734                                A19D93491AA11B1E00B46C24 /* NetworkExtensionContentFilter.h */,
     18735                                A19D93481AA11B1E00B46C24 /* NetworkExtensionContentFilter.mm */,
     18736                                A18890AD1AA13F250026C301 /* ParentalControlsContentFilter.h */,
     18737                                A18890AC1AA13F250026C301 /* ParentalControlsContentFilter.mm */,
    1872618738                                1AA84F03143BA7BD0051D153 /* ScrollController.h */,
    1872718739                                1AA84F02143BA7BD0051D153 /* ScrollController.mm */,
     
    2465324665                                A871DE2A0A152AC800B12A68 /* HTMLIFrameElement.h in Headers */,
    2465424666                                A8EA7D2D0A19385500A8EF5F /* HTMLImageElement.h in Headers */,
     24667                                A19D934B1AA11B1E00B46C24 /* NetworkExtensionContentFilter.h in Headers */,
    2465524668                                A8EA7D2B0A19385500A8EF5F /* HTMLImageLoader.h in Headers */,
    2465624669                                A81369CC097374F600D74463 /* HTMLInputElement.h in Headers */,
     
    2653426547                                B2227A970D00BF220071B782 /* SVGPreserveAspectRatio.h in Headers */,
    2653526548                                088A0E0A126EF1DB00978F7A /* SVGProperty.h in Headers */,
     26549                                A18890AF1AA13F250026C301 /* ParentalControlsContentFilter.h in Headers */,
    2653626550                                081DD49C13BA1A6000DC7627 /* SVGPropertyInfo.h in Headers */,
    2653726551                                088A0E0B126EF1DB00978F7A /* SVGPropertyTearOff.h in Headers */,
     
    2965429668                                93309E11099E64920056E581 /* SplitElementCommand.cpp in Sources */,
    2965529669                                93309E13099E64920056E581 /* SplitTextNodeCommand.cpp in Sources */,
     29670                                A19D934A1AA11B1E00B46C24 /* NetworkExtensionContentFilter.mm in Sources */,
    2965629671                                93309E15099E64920056E581 /* SplitTextNodeContainingElementCommand.cpp in Sources */,
    2965729672                                A1E1154813015C5D0054AC8C /* SpotLightSource.cpp in Sources */,
     
    2974529760                                431A2FD713B7707A007791E4 /* SVGAnimatedLengthList.cpp in Sources */,
    2974629761                                43A0F0B113AC7D6D00A5F0A7 /* SVGAnimatedNumber.cpp in Sources */,
     29762                                A18890AE1AA13F250026C301 /* ParentalControlsContentFilter.mm in Sources */,
    2974729763                                4331AC7813B6870000A9E5AE /* SVGAnimatedNumberList.cpp in Sources */,
    2974829764                                431A2F9D13B6F2B0007791E4 /* SVGAnimatedNumberOptionalNumber.cpp in Sources */,
  • trunk/Source/WebCore/loader/DocumentLoader.cpp

    r180985 r181037  
    667667
    668668#if ENABLE(CONTENT_FILTERING)
    669     if (ContentFilter::canHandleResponse(response))
    670         m_contentFilter = std::make_unique<ContentFilter>(response);
     669    m_contentFilter = ContentFilter::createIfNeeded(response);
    671670#endif
    672671
  • trunk/Source/WebCore/platform/ContentFilter.h

    r180985 r181037  
    3030
    3131#include "ContentFilterUnblockHandler.h"
    32 #include <wtf/PassRefPtr.h>
    33 #include <wtf/RetainPtr.h>
    34 
    35 #if PLATFORM(COCOA)
    36 OBJC_CLASS NSData;
    37 OBJC_CLASS WebFilterEvaluator;
    38 #endif
    3932
    4033#define HAVE_NE_FILTER_SOURCE TARGET_OS_EMBEDDED || (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000 && CPU(X86_64))
    4134
    42 #if HAVE(NE_FILTER_SOURCE)
    43 #import <dispatch/dispatch.h>
    44 OBJC_CLASS NEFilterSource;
    45 OBJC_CLASS NSMutableData;
    46 #endif
    47 
    4835namespace WebCore {
    4936
    50 class ResourceRequest;
    5137class ResourceResponse;
    5238
    5339class ContentFilter {
    5440public:
    55     static bool canHandleResponse(const ResourceResponse&);
     41    static std::unique_ptr<ContentFilter> createIfNeeded(const ResourceResponse&);
    5642
    57     explicit ContentFilter(const ResourceResponse&);
    58     WEBCORE_EXPORT ~ContentFilter();
     43    virtual ~ContentFilter() { }
    5944
    60     void addData(const char* data, int length);
    61     void finishedAddingData();
    62     bool needsMoreData() const;
    63     bool didBlockData() const;
    64     const char* getReplacementData(int& length) const;
    65     ContentFilterUnblockHandler unblockHandler() const;
    66 
    67 private:
    68 #if PLATFORM(COCOA)
    69     RetainPtr<WebFilterEvaluator> m_platformContentFilter;
    70     RetainPtr<NSData> m_replacementData;
    71 #endif
    72 
    73 #if HAVE(NE_FILTER_SOURCE)
    74     long m_neFilterSourceStatus;
    75     RetainPtr<NEFilterSource> m_neFilterSource;
    76     dispatch_queue_t m_neFilterSourceQueue;
    77     RetainPtr<NSMutableData> m_originalData;
    78 #endif
     45    virtual void addData(const char* data, int length) = 0;
     46    virtual void finishedAddingData() = 0;
     47    virtual bool needsMoreData() const = 0;
     48    virtual bool didBlockData() const = 0;
     49    virtual const char* getReplacementData(int& length) const = 0;
     50    virtual ContentFilterUnblockHandler unblockHandler() const = 0;
    7951};
    8052
  • trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.h

    r181036 r181037  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 #ifndef ContentFilter_h
    27 #define ContentFilter_h
     26#ifndef NetworkExtensionContentFilter_h
     27#define NetworkExtensionContentFilter_h
    2828
    29 #if ENABLE(CONTENT_FILTERING)
    30 
    31 #include "ContentFilterUnblockHandler.h"
    32 #include <wtf/PassRefPtr.h>
     29#include "ContentFilter.h"
     30#include <wtf/Compiler.h>
    3331#include <wtf/RetainPtr.h>
    3432
    35 #if PLATFORM(COCOA)
    36 OBJC_CLASS NSData;
    37 OBJC_CLASS WebFilterEvaluator;
    38 #endif
    39 
    40 #define HAVE_NE_FILTER_SOURCE TARGET_OS_EMBEDDED || (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000 && CPU(X86_64))
    41 
    42 #if HAVE(NE_FILTER_SOURCE)
    43 #import <dispatch/dispatch.h>
    4433OBJC_CLASS NEFilterSource;
    4534OBJC_CLASS NSMutableData;
    46 #endif
    4735
    4836namespace WebCore {
    4937
    50 class ResourceRequest;
    51 class ResourceResponse;
    52 
    53 class ContentFilter {
     38class NetworkExtensionContentFilter final : public ContentFilter {
    5439public:
    5540    static bool canHandleResponse(const ResourceResponse&);
     41    static std::unique_ptr<NetworkExtensionContentFilter> create(const ResourceResponse&);
    5642
    57     explicit ContentFilter(const ResourceResponse&);
    58     WEBCORE_EXPORT ~ContentFilter();
     43    explicit NetworkExtensionContentFilter(const ResourceResponse&);
     44    ~NetworkExtensionContentFilter() override;
    5945
    60     void addData(const char* data, int length);
    61     void finishedAddingData();
    62     bool needsMoreData() const;
    63     bool didBlockData() const;
    64     const char* getReplacementData(int& length) const;
    65     ContentFilterUnblockHandler unblockHandler() const;
     46    void addData(const char* data, int length) override;
     47    void finishedAddingData() override;
     48    bool needsMoreData() const override;
     49    bool didBlockData() const override;
     50    const char* getReplacementData(int& length) const override;
     51    ContentFilterUnblockHandler unblockHandler() const override;
    6652
    6753private:
    68 #if PLATFORM(COCOA)
    69     RetainPtr<WebFilterEvaluator> m_platformContentFilter;
    70     RetainPtr<NSData> m_replacementData;
    71 #endif
    72 
    73 #if HAVE(NE_FILTER_SOURCE)
    74     long m_neFilterSourceStatus;
     54    NSInteger m_neFilterSourceStatus;
    7555    RetainPtr<NEFilterSource> m_neFilterSource;
    7656    dispatch_queue_t m_neFilterSourceQueue;
    7757    RetainPtr<NSMutableData> m_originalData;
    78 #endif
    7958};
    8059
    8160} // namespace WebCore
    8261
    83 #endif // ENABLE(CONTENT_FILTERING)
    84 
    85 #endif // ContentFilter_h
     62#endif // NetworkExtensionContentFilter_h
  • trunk/Source/WebCore/platform/cocoa/ParentalControlsContentFilter.h

    r181036 r181037  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 #ifndef ContentFilter_h
    27 #define ContentFilter_h
     26#ifndef ParentalControlsContentFilter_h
     27#define ParentalControlsContentFilter_h
    2828
    29 #if ENABLE(CONTENT_FILTERING)
    30 
    31 #include "ContentFilterUnblockHandler.h"
    32 #include <wtf/PassRefPtr.h>
     29#include "ContentFilter.h"
     30#include <wtf/Compiler.h>
    3331#include <wtf/RetainPtr.h>
    3432
    35 #if PLATFORM(COCOA)
    3633OBJC_CLASS NSData;
    3734OBJC_CLASS WebFilterEvaluator;
    38 #endif
    39 
    40 #define HAVE_NE_FILTER_SOURCE TARGET_OS_EMBEDDED || (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000 && CPU(X86_64))
    41 
    42 #if HAVE(NE_FILTER_SOURCE)
    43 #import <dispatch/dispatch.h>
    44 OBJC_CLASS NEFilterSource;
    45 OBJC_CLASS NSMutableData;
    46 #endif
    4735
    4836namespace WebCore {
    4937
    50 class ResourceRequest;
    51 class ResourceResponse;
    52 
    53 class ContentFilter {
     38class ParentalControlsContentFilter final : public ContentFilter {
    5439public:
    5540    static bool canHandleResponse(const ResourceResponse&);
     41    static std::unique_ptr<ParentalControlsContentFilter> create(const ResourceResponse&);
    5642
    57     explicit ContentFilter(const ResourceResponse&);
    58     WEBCORE_EXPORT ~ContentFilter();
     43    explicit ParentalControlsContentFilter(const ResourceResponse&);
    5944
    60     void addData(const char* data, int length);
    61     void finishedAddingData();
    62     bool needsMoreData() const;
    63     bool didBlockData() const;
    64     const char* getReplacementData(int& length) const;
    65     ContentFilterUnblockHandler unblockHandler() const;
     45    void addData(const char* data, int length) override;
     46    void finishedAddingData() override;
     47    bool needsMoreData() const override;
     48    bool didBlockData() const override;
     49    const char* getReplacementData(int& length) const override;
     50    ContentFilterUnblockHandler unblockHandler() const override;
    6651
    6752private:
    68 #if PLATFORM(COCOA)
    69     RetainPtr<WebFilterEvaluator> m_platformContentFilter;
     53    RetainPtr<WebFilterEvaluator> m_webFilterEvaluator;
    7054    RetainPtr<NSData> m_replacementData;
    71 #endif
    72 
    73 #if HAVE(NE_FILTER_SOURCE)
    74     long m_neFilterSourceStatus;
    75     RetainPtr<NEFilterSource> m_neFilterSource;
    76     dispatch_queue_t m_neFilterSourceQueue;
    77     RetainPtr<NSMutableData> m_originalData;
    78 #endif
    7955};
    80 
     56   
    8157} // namespace WebCore
    8258
    83 #endif // ENABLE(CONTENT_FILTERING)
    84 
    85 #endif // ContentFilter_h
     59#endif // ParentalControlsContentFilter_h
  • trunk/Source/WebCore/platform/mac/ContentFilterMac.mm

    r180985 r181037  
    2424 */
    2525
     26// FIXME: Rename to ContentFilter.cpp and move to platform/.
     27
    2628#import "config.h"
    2729#import "ContentFilter.h"
     
    2931#if ENABLE(CONTENT_FILTERING)
    3032
    31 #import "ResourceResponse.h"
    32 #import "SoftLinking.h"
    33 #import "WebFilterEvaluatorSPI.h"
    34 #import <objc/runtime.h>
    35 
    36 #if HAVE(NE_FILTER_SOURCE)
    37 #import "NEFilterSourceSPI.h"
    38 SOFT_LINK_FRAMEWORK(NetworkExtension);
    39 SOFT_LINK_CLASS(NetworkExtension, NEFilterSource);
    40 #endif
    41 
    42 SOFT_LINK_PRIVATE_FRAMEWORK(WebContentAnalysis);
    43 SOFT_LINK_CLASS(WebContentAnalysis, WebFilterEvaluator);
     33#import "NetworkExtensionContentFilter.h"
     34#import "ParentalControlsContentFilter.h"
     35#import <wtf/NeverDestroyed.h>
     36#import <wtf/Vector.h>
    4437
    4538namespace WebCore {
    4639
    47 ContentFilter::ContentFilter(const ResourceResponse& response)
    48 #if HAVE(NE_FILTER_SOURCE)
    49     : m_neFilterSourceStatus(NEFilterSourceStatusNeedsMoreData)
    50     , m_neFilterSourceQueue(0)
    51 #endif
     40struct ContentFilterType {
     41    const std::function<bool(const ResourceResponse&)> canHandleResponse;
     42    const std::function<std::unique_ptr<ContentFilter>(const ResourceResponse&)> create;
     43};
     44
     45template <typename T>
     46static inline ContentFilterType contentFilterType()
    5247{
    53     if ([getWebFilterEvaluatorClass() isManagedSession])
    54         m_platformContentFilter = adoptNS([allocWebFilterEvaluatorInstance() initWithResponse:response.nsURLResponse()]);
    55 
    56 #if HAVE(NE_FILTER_SOURCE)
    57     if ([getNEFilterSourceClass() filterRequired]) {
    58         m_neFilterSource = adoptNS([allocNEFilterSourceInstance() initWithURL:[response.nsURLResponse() URL] direction:NEFilterSourceDirectionInbound socketIdentifier:0]);
    59         m_neFilterSourceQueue = dispatch_queue_create("com.apple.WebCore.NEFilterSourceQueue", DISPATCH_QUEUE_SERIAL);
    60        
    61         long long expectedContentSize = [response.nsURLResponse() expectedContentLength];
    62         if (expectedContentSize < 0)
    63             m_originalData = adoptNS([[NSMutableData alloc] init]);
    64         else
    65             m_originalData = adoptNS([[NSMutableData alloc] initWithCapacity:(NSUInteger)expectedContentSize]);
    66     }
    67 #endif
     48    return { T::canHandleResponse, T::create };
    6849}
    6950
    70 ContentFilter::~ContentFilter()
     51static const Vector<ContentFilterType>& contentFilterTypes()
    7152{
     53    static NeverDestroyed<Vector<ContentFilterType>> types(
     54        Vector<ContentFilterType>({
     55            contentFilterType<ParentalControlsContentFilter>(),
    7256#if HAVE(NE_FILTER_SOURCE)
    73     if (m_neFilterSourceQueue)
    74         dispatch_release(m_neFilterSourceQueue);
     57            contentFilterType<NetworkExtensionContentFilter>()
    7558#endif
     59        })
     60    );
     61    return types;
    7662}
    7763
    78 bool ContentFilter::canHandleResponse(const ResourceResponse& response)
     64class ContentFilterCollection final : public ContentFilter {
     65public:
     66    using Container = Vector<std::unique_ptr<ContentFilter>>;
     67
     68    explicit ContentFilterCollection(Container);
     69
     70    void addData(const char* data, int length) override;
     71    void finishedAddingData() override;
     72    bool needsMoreData() const override;
     73    bool didBlockData() const override;
     74    const char* getReplacementData(int& length) const override;
     75    ContentFilterUnblockHandler unblockHandler() const override;
     76
     77private:
     78    Container m_contentFilters;
     79};
     80
     81std::unique_ptr<ContentFilter> ContentFilter::createIfNeeded(const ResourceResponse& response)
    7982{
    80     if (!response.url().protocolIsInHTTPFamily())
    81         return false;
    82 
    83     if ([getWebFilterEvaluatorClass() isManagedSession]) {
    84 #if PLATFORM(MAC)
    85         if (response.url().protocolIs("https"))
    86 #endif
    87             return true;
     83    ContentFilterCollection::Container filters;
     84    for (auto& type : contentFilterTypes()) {
     85        if (type.canHandleResponse(response))
     86            filters.append(type.create(response));
    8887    }
    8988
    90 #if HAVE(NE_FILTER_SOURCE)
    91     return [getNEFilterSourceClass() filterRequired];
    92 #else
    93     return false;
    94 #endif
     89    if (filters.isEmpty())
     90        return nullptr;
     91
     92    return std::make_unique<ContentFilterCollection>(WTF::move(filters));
    9593}
    9694
    97 void ContentFilter::addData(const char* data, int length)
     95ContentFilterCollection::ContentFilterCollection(Container contentFilters)
     96    : m_contentFilters { WTF::move(contentFilters) }
     97{
     98    ASSERT(!m_contentFilters.isEmpty());
     99}
     100
     101void ContentFilterCollection::addData(const char* data, int length)
    98102{
    99103    ASSERT(needsMoreData());
    100104
    101     if (m_platformContentFilter) {
    102         ASSERT(![m_replacementData.get() length]);
    103         m_replacementData = [m_platformContentFilter addData:[NSData dataWithBytesNoCopy:(void*)data length:length freeWhenDone:NO]];
    104         ASSERT(needsMoreData() || [m_replacementData.get() length]);
    105     }
    106 
    107 #if HAVE(NE_FILTER_SOURCE)
    108     if (!m_neFilterSource)
    109         return;
    110 
    111     // FIXME: NEFilterSource doesn't buffer data like WebFilterEvaluator does,
    112     // so we need to do it ourselves so getReplacementData() can return the
    113     // original bytes back to the loader. We should find a way to remove this
    114     // additional copy.
    115     [m_originalData appendBytes:data length:length];
    116 
    117     dispatch_semaphore_t neFilterSourceSemaphore = dispatch_semaphore_create(0);
    118     [m_neFilterSource addData:[NSData dataWithBytes:(void*)data length:length] withCompletionQueue:m_neFilterSourceQueue completionHandler:^(NEFilterSourceStatus status, NSData *) {
    119         m_neFilterSourceStatus = status;
    120         dispatch_semaphore_signal(neFilterSourceSemaphore);
    121     }];
    122 
    123     // FIXME: We have to block here since DocumentLoader expects to have a
    124     // blocked/not blocked answer from the filter immediately after calling
    125     // addData(). We should find a way to make this asynchronous.
    126     dispatch_semaphore_wait(neFilterSourceSemaphore, DISPATCH_TIME_FOREVER);
    127     dispatch_release(neFilterSourceSemaphore);
    128 #endif
     105    for (auto& contentFilter : m_contentFilters)
     106        contentFilter->addData(data, length);
    129107}
    130108   
    131 void ContentFilter::finishedAddingData()
     109void ContentFilterCollection::finishedAddingData()
    132110{
    133111    ASSERT(needsMoreData());
    134112
    135     if (m_platformContentFilter) {
    136         ASSERT(![m_replacementData.get() length]);
    137         m_replacementData = [m_platformContentFilter dataComplete];
    138     }
    139 
    140 #if HAVE(NE_FILTER_SOURCE)
    141     if (!m_neFilterSource)
    142         return;
    143 
    144     dispatch_semaphore_t neFilterSourceSemaphore = dispatch_semaphore_create(0);
    145     [m_neFilterSource dataCompleteWithCompletionQueue:m_neFilterSourceQueue completionHandler:^(NEFilterSourceStatus status, NSData *) {
    146         m_neFilterSourceStatus = status;
    147         dispatch_semaphore_signal(neFilterSourceSemaphore);
    148     }];
    149 
    150     // FIXME: We have to block here since DocumentLoader expects to have a
    151     // blocked/not blocked answer from the filter immediately after calling
    152     // finishedAddingData(). We should find a way to make this asynchronous.
    153     dispatch_semaphore_wait(neFilterSourceSemaphore, DISPATCH_TIME_FOREVER);
    154     dispatch_release(neFilterSourceSemaphore);
    155 #endif
     113    for (auto& contentFilter : m_contentFilters)
     114        contentFilter->finishedAddingData();
    156115
    157116    ASSERT(!needsMoreData());
    158117}
    159118
    160 bool ContentFilter::needsMoreData() const
     119bool ContentFilterCollection::needsMoreData() const
    161120{
    162     return [m_platformContentFilter filterState] == kWFEStateBuffering
    163 #if HAVE(NE_FILTER_SOURCE)
    164         || (m_neFilterSource && m_neFilterSourceStatus == NEFilterSourceStatusNeedsMoreData)
    165 #endif
    166     ;
     121    for (auto& contentFilter : m_contentFilters) {
     122        if (contentFilter->needsMoreData())
     123            return true;
     124    }
     125
     126    return false;
    167127}
    168128
    169 bool ContentFilter::didBlockData() const
     129bool ContentFilterCollection::didBlockData() const
    170130{
    171     return [m_platformContentFilter wasBlocked]
    172 #if HAVE(NE_FILTER_SOURCE)
    173         || (m_neFilterSource && m_neFilterSourceStatus == NEFilterSourceStatusBlock)
    174 #endif
    175     ;
     131    for (auto& contentFilter : m_contentFilters) {
     132        if (contentFilter->didBlockData())
     133            return true;
     134    }
     135
     136    return false;
    176137}
    177138
    178 const char* ContentFilter::getReplacementData(int& length) const
     139const char* ContentFilterCollection::getReplacementData(int& length) const
    179140{
    180141    ASSERT(!needsMoreData());
    181142
    182     if (didBlockData()) {
    183         length = [m_replacementData length];
    184         return static_cast<const char*>([m_replacementData bytes]);
     143    for (auto& contentFilter : m_contentFilters) {
     144        if (contentFilter->didBlockData())
     145            return contentFilter->getReplacementData(length);
    185146    }
    186147
    187     NSData *originalData = m_replacementData.get();
    188 #if HAVE(NE_FILTER_SOURCE)
    189     if (!originalData)
    190         originalData = m_originalData.get();
    191 #endif
    192 
    193     length = [originalData length];
    194     return static_cast<const char*>([originalData bytes]);
     148    return m_contentFilters[0]->getReplacementData(length);
    195149}
    196150
    197 ContentFilterUnblockHandler ContentFilter::unblockHandler() const
     151ContentFilterUnblockHandler ContentFilterCollection::unblockHandler() const
    198152{
    199     return ContentFilterUnblockHandler { m_platformContentFilter.get() };
     153    ASSERT(didBlockData());
     154
     155    for (auto& contentFilter : m_contentFilters) {
     156        if (contentFilter->didBlockData())
     157            return contentFilter->unblockHandler();
     158    }
     159
     160    ASSERT_NOT_REACHED();
     161    return { };
    200162}
    201163
Note: See TracChangeset for help on using the changeset viewer.