Changeset 181037 in webkit
- Timestamp:
- Mar 4, 2015 2:43:35 PM (9 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 2 added
- 5 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r181036 r181037 1 2015-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 1 67 2015-03-04 David Kilzer <ddkilzer@apple.com> 2 68 -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r181000 r181037 3805 3805 A17C81220F2A5CF7005DAAEB /* HTMLElementFactory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A17C81200F2A5CF7005DAAEB /* HTMLElementFactory.cpp */; }; 3806 3806 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 */; }; 3807 3809 A19D93461A9FEC7200B46C24 /* NEFilterSourceSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = A19D93441A9FEC7200B46C24 /* NEFilterSourceSPI.h */; }; 3808 3810 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 */; }; 3809 3813 A1C797181883DD82000F5E1F /* DOMGestureEvent.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 0F54DCDD1880F901003EEDBB /* DOMGestureEvent.h */; }; 3810 3814 A1C797191883DDED000F5E1F /* DOMTouch.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 0F54DCCD1880F867003EEDBB /* DOMTouch.h */; }; … … 11034 11038 A17C81200F2A5CF7005DAAEB /* HTMLElementFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLElementFactory.cpp; sourceTree = "<group>"; }; 11035 11039 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>"; }; 11036 11042 A19D93441A9FEC7200B46C24 /* NEFilterSourceSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NEFilterSourceSPI.h; sourceTree = "<group>"; }; 11037 11043 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>"; }; 11038 11046 A1C7971C1883E51F000F5E1F /* DOMHTMLTextAreaElementPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMHTMLTextAreaElementPrivate.h; sourceTree = "<group>"; }; 11039 11047 A1C7FAA1133A5D3500D6732D /* JSXPathResultCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSXPathResultCustom.cpp; sourceTree = "<group>"; }; … … 18724 18732 1A0409DB1A4360B5009E47F3 /* MachSendRight.h */, 18725 18733 ADB6B29718FB90240081963E /* MemoryPressureHandlerCocoa.mm */, 18734 A19D93491AA11B1E00B46C24 /* NetworkExtensionContentFilter.h */, 18735 A19D93481AA11B1E00B46C24 /* NetworkExtensionContentFilter.mm */, 18736 A18890AD1AA13F250026C301 /* ParentalControlsContentFilter.h */, 18737 A18890AC1AA13F250026C301 /* ParentalControlsContentFilter.mm */, 18726 18738 1AA84F03143BA7BD0051D153 /* ScrollController.h */, 18727 18739 1AA84F02143BA7BD0051D153 /* ScrollController.mm */, … … 24653 24665 A871DE2A0A152AC800B12A68 /* HTMLIFrameElement.h in Headers */, 24654 24666 A8EA7D2D0A19385500A8EF5F /* HTMLImageElement.h in Headers */, 24667 A19D934B1AA11B1E00B46C24 /* NetworkExtensionContentFilter.h in Headers */, 24655 24668 A8EA7D2B0A19385500A8EF5F /* HTMLImageLoader.h in Headers */, 24656 24669 A81369CC097374F600D74463 /* HTMLInputElement.h in Headers */, … … 26534 26547 B2227A970D00BF220071B782 /* SVGPreserveAspectRatio.h in Headers */, 26535 26548 088A0E0A126EF1DB00978F7A /* SVGProperty.h in Headers */, 26549 A18890AF1AA13F250026C301 /* ParentalControlsContentFilter.h in Headers */, 26536 26550 081DD49C13BA1A6000DC7627 /* SVGPropertyInfo.h in Headers */, 26537 26551 088A0E0B126EF1DB00978F7A /* SVGPropertyTearOff.h in Headers */, … … 29654 29668 93309E11099E64920056E581 /* SplitElementCommand.cpp in Sources */, 29655 29669 93309E13099E64920056E581 /* SplitTextNodeCommand.cpp in Sources */, 29670 A19D934A1AA11B1E00B46C24 /* NetworkExtensionContentFilter.mm in Sources */, 29656 29671 93309E15099E64920056E581 /* SplitTextNodeContainingElementCommand.cpp in Sources */, 29657 29672 A1E1154813015C5D0054AC8C /* SpotLightSource.cpp in Sources */, … … 29745 29760 431A2FD713B7707A007791E4 /* SVGAnimatedLengthList.cpp in Sources */, 29746 29761 43A0F0B113AC7D6D00A5F0A7 /* SVGAnimatedNumber.cpp in Sources */, 29762 A18890AE1AA13F250026C301 /* ParentalControlsContentFilter.mm in Sources */, 29747 29763 4331AC7813B6870000A9E5AE /* SVGAnimatedNumberList.cpp in Sources */, 29748 29764 431A2F9D13B6F2B0007791E4 /* SVGAnimatedNumberOptionalNumber.cpp in Sources */, -
trunk/Source/WebCore/loader/DocumentLoader.cpp
r180985 r181037 667 667 668 668 #if ENABLE(CONTENT_FILTERING) 669 if (ContentFilter::canHandleResponse(response)) 670 m_contentFilter = std::make_unique<ContentFilter>(response); 669 m_contentFilter = ContentFilter::createIfNeeded(response); 671 670 #endif 672 671 -
trunk/Source/WebCore/platform/ContentFilter.h
r180985 r181037 30 30 31 31 #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 #endif39 32 40 33 #define HAVE_NE_FILTER_SOURCE TARGET_OS_EMBEDDED || (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000 && CPU(X86_64)) 41 34 42 #if HAVE(NE_FILTER_SOURCE)43 #import <dispatch/dispatch.h>44 OBJC_CLASS NEFilterSource;45 OBJC_CLASS NSMutableData;46 #endif47 48 35 namespace WebCore { 49 36 50 class ResourceRequest;51 37 class ResourceResponse; 52 38 53 39 class ContentFilter { 54 40 public: 55 static bool canHandleResponse(const ResourceResponse&);41 static std::unique_ptr<ContentFilter> createIfNeeded(const ResourceResponse&); 56 42 57 explicit ContentFilter(const ResourceResponse&); 58 WEBCORE_EXPORT ~ContentFilter(); 43 virtual ~ContentFilter() { } 59 44 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; 79 51 }; 80 52 -
trunk/Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.h
r181036 r181037 1 1 /* 2 * Copyright (C) 201 3Apple Inc. All rights reserved.2 * Copyright (C) 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 24 24 */ 25 25 26 #ifndef ContentFilter_h27 #define ContentFilter_h26 #ifndef NetworkExtensionContentFilter_h 27 #define NetworkExtensionContentFilter_h 28 28 29 #if ENABLE(CONTENT_FILTERING) 30 31 #include "ContentFilterUnblockHandler.h" 32 #include <wtf/PassRefPtr.h> 29 #include "ContentFilter.h" 30 #include <wtf/Compiler.h> 33 31 #include <wtf/RetainPtr.h> 34 32 35 #if PLATFORM(COCOA)36 OBJC_CLASS NSData;37 OBJC_CLASS WebFilterEvaluator;38 #endif39 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 33 OBJC_CLASS NEFilterSource; 45 34 OBJC_CLASS NSMutableData; 46 #endif47 35 48 36 namespace WebCore { 49 37 50 class ResourceRequest; 51 class ResourceResponse; 52 53 class ContentFilter { 38 class NetworkExtensionContentFilter final : public ContentFilter { 54 39 public: 55 40 static bool canHandleResponse(const ResourceResponse&); 41 static std::unique_ptr<NetworkExtensionContentFilter> create(const ResourceResponse&); 56 42 57 explicit ContentFilter(const ResourceResponse&);58 WEBCORE_EXPORT ~ContentFilter();43 explicit NetworkExtensionContentFilter(const ResourceResponse&); 44 ~NetworkExtensionContentFilter() override; 59 45 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; 66 52 67 53 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; 54 NSInteger m_neFilterSourceStatus; 75 55 RetainPtr<NEFilterSource> m_neFilterSource; 76 56 dispatch_queue_t m_neFilterSourceQueue; 77 57 RetainPtr<NSMutableData> m_originalData; 78 #endif79 58 }; 80 59 81 60 } // namespace WebCore 82 61 83 #endif // ENABLE(CONTENT_FILTERING) 84 85 #endif // ContentFilter_h 62 #endif // NetworkExtensionContentFilter_h -
trunk/Source/WebCore/platform/cocoa/ParentalControlsContentFilter.h
r181036 r181037 1 1 /* 2 * Copyright (C) 201 3Apple Inc. All rights reserved.2 * Copyright (C) 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 24 24 */ 25 25 26 #ifndef ContentFilter_h27 #define ContentFilter_h26 #ifndef ParentalControlsContentFilter_h 27 #define ParentalControlsContentFilter_h 28 28 29 #if ENABLE(CONTENT_FILTERING) 30 31 #include "ContentFilterUnblockHandler.h" 32 #include <wtf/PassRefPtr.h> 29 #include "ContentFilter.h" 30 #include <wtf/Compiler.h> 33 31 #include <wtf/RetainPtr.h> 34 32 35 #if PLATFORM(COCOA)36 33 OBJC_CLASS NSData; 37 34 OBJC_CLASS WebFilterEvaluator; 38 #endif39 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 #endif47 35 48 36 namespace WebCore { 49 37 50 class ResourceRequest; 51 class ResourceResponse; 52 53 class ContentFilter { 38 class ParentalControlsContentFilter final : public ContentFilter { 54 39 public: 55 40 static bool canHandleResponse(const ResourceResponse&); 41 static std::unique_ptr<ParentalControlsContentFilter> create(const ResourceResponse&); 56 42 57 explicit ContentFilter(const ResourceResponse&); 58 WEBCORE_EXPORT ~ContentFilter(); 43 explicit ParentalControlsContentFilter(const ResourceResponse&); 59 44 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; 66 51 67 52 private: 68 #if PLATFORM(COCOA) 69 RetainPtr<WebFilterEvaluator> m_platformContentFilter; 53 RetainPtr<WebFilterEvaluator> m_webFilterEvaluator; 70 54 RetainPtr<NSData> m_replacementData; 71 #endif72 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 #endif79 55 }; 80 56 81 57 } // namespace WebCore 82 58 83 #endif // ENABLE(CONTENT_FILTERING) 84 85 #endif // ContentFilter_h 59 #endif // ParentalControlsContentFilter_h -
trunk/Source/WebCore/platform/mac/ContentFilterMac.mm
r180985 r181037 24 24 */ 25 25 26 // FIXME: Rename to ContentFilter.cpp and move to platform/. 27 26 28 #import "config.h" 27 29 #import "ContentFilter.h" … … 29 31 #if ENABLE(CONTENT_FILTERING) 30 32 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> 44 37 45 38 namespace WebCore { 46 39 47 ContentFilter::ContentFilter(const ResourceResponse& response) 48 #if HAVE(NE_FILTER_SOURCE) 49 : m_neFilterSourceStatus(NEFilterSourceStatusNeedsMoreData) 50 , m_neFilterSourceQueue(0) 51 #endif 40 struct ContentFilterType { 41 const std::function<bool(const ResourceResponse&)> canHandleResponse; 42 const std::function<std::unique_ptr<ContentFilter>(const ResourceResponse&)> create; 43 }; 44 45 template <typename T> 46 static inline ContentFilterType contentFilterType() 52 47 { 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 }; 68 49 } 69 50 70 ContentFilter::~ContentFilter()51 static const Vector<ContentFilterType>& contentFilterTypes() 71 52 { 53 static NeverDestroyed<Vector<ContentFilterType>> types( 54 Vector<ContentFilterType>({ 55 contentFilterType<ParentalControlsContentFilter>(), 72 56 #if HAVE(NE_FILTER_SOURCE) 73 if (m_neFilterSourceQueue) 74 dispatch_release(m_neFilterSourceQueue); 57 contentFilterType<NetworkExtensionContentFilter>() 75 58 #endif 59 }) 60 ); 61 return types; 76 62 } 77 63 78 bool ContentFilter::canHandleResponse(const ResourceResponse& response) 64 class ContentFilterCollection final : public ContentFilter { 65 public: 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 77 private: 78 Container m_contentFilters; 79 }; 80 81 std::unique_ptr<ContentFilter> ContentFilter::createIfNeeded(const ResourceResponse& response) 79 82 { 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)); 88 87 } 89 88 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)); 95 93 } 96 94 97 void ContentFilter::addData(const char* data, int length) 95 ContentFilterCollection::ContentFilterCollection(Container contentFilters) 96 : m_contentFilters { WTF::move(contentFilters) } 97 { 98 ASSERT(!m_contentFilters.isEmpty()); 99 } 100 101 void ContentFilterCollection::addData(const char* data, int length) 98 102 { 99 103 ASSERT(needsMoreData()); 100 104 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); 129 107 } 130 108 131 void ContentFilter ::finishedAddingData()109 void ContentFilterCollection::finishedAddingData() 132 110 { 133 111 ASSERT(needsMoreData()); 134 112 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(); 156 115 157 116 ASSERT(!needsMoreData()); 158 117 } 159 118 160 bool ContentFilter ::needsMoreData() const119 bool ContentFilterCollection::needsMoreData() const 161 120 { 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; 167 127 } 168 128 169 bool ContentFilter ::didBlockData() const129 bool ContentFilterCollection::didBlockData() const 170 130 { 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; 176 137 } 177 138 178 const char* ContentFilter ::getReplacementData(int& length) const139 const char* ContentFilterCollection::getReplacementData(int& length) const 179 140 { 180 141 ASSERT(!needsMoreData()); 181 142 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); 185 146 } 186 147 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); 195 149 } 196 150 197 ContentFilterUnblockHandler ContentFilter ::unblockHandler() const151 ContentFilterUnblockHandler ContentFilterCollection::unblockHandler() const 198 152 { 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 { }; 200 162 } 201 163
Note: See TracChangeset
for help on using the changeset viewer.