[Content Extensions] Split parsing and compiling of content extensions into their...
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 4 Mar 2015 16:41:31 +0000 (16:41 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 4 Mar 2015 16:41:31 +0000 (16:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=142259

Reviewed by Anders Carlsson.

Source/WebCore:

Added new unit test:
    ContentFilterTest.Basic

* WebCore.xcodeproj/project.pbxproj:
Add new files (CompiledContentExtension.h/cpp, ContentExtensionCompiler.h/cpp, and ContentExtensionParser.h/cpp)

* contentextensions/CompiledContentExtension.cpp: Added.
* contentextensions/CompiledContentExtension.h: Added.
Add new class for holding onto the compiled content extension itself. Make it ThreadSafeRefCounted so it is easy
to move between threads which will be important in a subsequent patch where we enable compilation on a background
thread.

* contentextensions/ContentExtensionCompiler.cpp: Added.
(WebCore::ContentExtensions::serializeActions):
(WebCore::ContentExtensions::compileRuleList):
* contentextensions/ContentExtensionCompiler.h: Added.
Moving compilation to its own file. Was previously in ContentExtensionsBackend. This is necessary because
we will want to be able to compile without the need of a backend.

* contentextensions/ContentExtensionParser.cpp: Copied from contentextensions/ContentExtensionsManager.cpp.
* contentextensions/ContentExtensionParser.h: Copied from contentextensions/ContentExtensionsManager.h.
Renamed ContentExtensionsManager to ContentExtensionParser, since that is all it is doing.

* contentextensions/ContentExtensionsBackend.cpp:
(WebCore::ContentExtensions::ContentExtensionsBackend::addContentExtension):
(WebCore::ContentExtensions::ContentExtensionsBackend::removeContentExtension):
(WebCore::ContentExtensions::ContentExtensionsBackend::removeAllContentExtensions):
(WebCore::ContentExtensions::ContentExtensionsBackend::actionsForURL):
(WebCore::ContentExtensions::ContentExtensionsBackend::serializeActions): Deleted.
(WebCore::ContentExtensions::ContentExtensionsBackend::setRuleList): Deleted.
(WebCore::ContentExtensions::ContentExtensionsBackend::removeRuleList): Deleted.
(WebCore::ContentExtensions::ContentExtensionsBackend::removeAllRuleLists): Deleted.
* contentextensions/ContentExtensionsBackend.h:
Change the backend to use the new CompiledContentExtension and change the terminology to
reference content extensions, rather than rule lists.

* page/UserContentController.cpp:
(WebCore::UserContentController::addUserContentFilter):
(WebCore::UserContentController::removeUserContentFilter):
(WebCore::UserContentController::removeAllUserContentFilters):
Update for new names and change addUserContentFilter to explicitly compile the JSON
rule list before handing it to the backend. In subsequent changes, addUserContentFilter
should be changed to take the compiled content extension, and it should become the responsibility
of the called (WebKit) to create them.

Tools:

Add basic unit test for the content filter compiler.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebCore/ContentFilter.cpp: Added.
(WebCore::ContentExtensions::operator<<):
(TestWebKitAPI::ContentFilterTest::SetUp):
(TestWebKitAPI::TEST_F):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@181000 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/contentextensions/CompiledContentExtension.cpp [new file with mode: 0644]
Source/WebCore/contentextensions/CompiledContentExtension.h [new file with mode: 0644]
Source/WebCore/contentextensions/ContentExtensionCompiler.cpp [new file with mode: 0644]
Source/WebCore/contentextensions/ContentExtensionCompiler.h [new file with mode: 0644]
Source/WebCore/contentextensions/ContentExtensionParser.cpp [moved from Source/WebCore/contentextensions/ContentExtensionsManager.cpp with 97% similarity]
Source/WebCore/contentextensions/ContentExtensionParser.h [moved from Source/WebCore/contentextensions/ContentExtensionsManager.h with 83% similarity]
Source/WebCore/contentextensions/ContentExtensionsBackend.cpp
Source/WebCore/contentextensions/ContentExtensionsBackend.h
Source/WebCore/page/UserContentController.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebCore/ContentFilter.cpp [new file with mode: 0644]

index 2a49e20..4d444cc 100644 (file)
@@ -1,3 +1,55 @@
+2015-03-03  Sam Weinig  <sam@webkit.org>
+
+        [Content Extensions] Split parsing and compiling of content extensions into their own files
+        https://bugs.webkit.org/show_bug.cgi?id=142259
+
+        Reviewed by Anders Carlsson.
+
+        Added new unit test:
+            ContentFilterTest.Basic
+
+        * WebCore.xcodeproj/project.pbxproj:
+        Add new files (CompiledContentExtension.h/cpp, ContentExtensionCompiler.h/cpp, and ContentExtensionParser.h/cpp)
+
+        * contentextensions/CompiledContentExtension.cpp: Added.
+        * contentextensions/CompiledContentExtension.h: Added.
+        Add new class for holding onto the compiled content extension itself. Make it ThreadSafeRefCounted so it is easy
+        to move between threads which will be important in a subsequent patch where we enable compilation on a background
+        thread.
+
+        * contentextensions/ContentExtensionCompiler.cpp: Added.
+        (WebCore::ContentExtensions::serializeActions):
+        (WebCore::ContentExtensions::compileRuleList):
+        * contentextensions/ContentExtensionCompiler.h: Added.
+        Moving compilation to its own file. Was previously in ContentExtensionsBackend. This is necessary because
+        we will want to be able to compile without the need of a backend.
+
+        * contentextensions/ContentExtensionParser.cpp: Copied from contentextensions/ContentExtensionsManager.cpp.
+        * contentextensions/ContentExtensionParser.h: Copied from contentextensions/ContentExtensionsManager.h.
+        Renamed ContentExtensionsManager to ContentExtensionParser, since that is all it is doing.
+
+        * contentextensions/ContentExtensionsBackend.cpp:
+        (WebCore::ContentExtensions::ContentExtensionsBackend::addContentExtension):
+        (WebCore::ContentExtensions::ContentExtensionsBackend::removeContentExtension):
+        (WebCore::ContentExtensions::ContentExtensionsBackend::removeAllContentExtensions):
+        (WebCore::ContentExtensions::ContentExtensionsBackend::actionsForURL):
+        (WebCore::ContentExtensions::ContentExtensionsBackend::serializeActions): Deleted.
+        (WebCore::ContentExtensions::ContentExtensionsBackend::setRuleList): Deleted.
+        (WebCore::ContentExtensions::ContentExtensionsBackend::removeRuleList): Deleted.
+        (WebCore::ContentExtensions::ContentExtensionsBackend::removeAllRuleLists): Deleted.
+        * contentextensions/ContentExtensionsBackend.h:
+        Change the backend to use the new CompiledContentExtension and change the terminology to
+        reference content extensions, rather than rule lists.
+
+        * page/UserContentController.cpp:
+        (WebCore::UserContentController::addUserContentFilter):
+        (WebCore::UserContentController::removeUserContentFilter):
+        (WebCore::UserContentController::removeAllUserContentFilters):
+        Update for new names and change addUserContentFilter to explicitly compile the JSON
+        rule list before handing it to the backend. In subsequent changes, addUserContentFilter
+        should be changed to take the compiled content extension, and it should become the responsibility
+        of the called (WebKit) to create them.
+
 2015-03-04  Philippe Normand  <pnormand@igalia.com>
 
         [GStreamer] the GST_SCHEDULING_FLAG_BANDWIDTH_LIMITED should be wrapped by a ifdef
index 8a9cf50..b859e78 100644 (file)
                26C17A3E1491D2D400D12BA2 /* FileSystemIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 26C17A3C1491D2D400D12BA2 /* FileSystemIOS.h */; settings = {ATTRIBUTES = (Private, ); }; };
                26C17A3F1491D2D400D12BA2 /* FileSystemIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 26C17A3D1491D2D400D12BA2 /* FileSystemIOS.mm */; };
                26E98A10130A9FCA008EB7B2 /* TextCodecASCIIFastPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 26E98A0F130A9FCA008EB7B2 /* TextCodecASCIIFastPath.h */; };
-               26F0C8971A2E724B002794F8 /* ContentExtensionsManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F0C8951A2E724B002794F8 /* ContentExtensionsManager.cpp */; };
-               26F0C8981A2E724B002794F8 /* ContentExtensionsManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 26F0C8961A2E724B002794F8 /* ContentExtensionsManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               26F0C8971A2E724B002794F8 /* ContentExtensionParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F0C8951A2E724B002794F8 /* ContentExtensionParser.cpp */; };
+               26F0C8981A2E724B002794F8 /* ContentExtensionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 26F0C8961A2E724B002794F8 /* ContentExtensionParser.h */; settings = {ATTRIBUTES = (Private, ); }; };
                26F0C89B1A2EC110002794F8 /* ContentExtensionRule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F0C8991A2EC110002794F8 /* ContentExtensionRule.cpp */; };
-               26F0C89C1A2EC110002794F8 /* ContentExtensionRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 26F0C89A1A2EC110002794F8 /* ContentExtensionRule.h */; };
+               26F0C89C1A2EC110002794F8 /* ContentExtensionRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 26F0C89A1A2EC110002794F8 /* ContentExtensionRule.h */; settings = {ATTRIBUTES = (Private, ); }; };
                26F0C89F1A2EC3BE002794F8 /* ContentExtensionsBackend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F0C89D1A2EC3BE002794F8 /* ContentExtensionsBackend.cpp */; };
-               26F0C8A01A2EC3BE002794F8 /* ContentExtensionsBackend.h in Headers */ = {isa = PBXBuildFile; fileRef = 26F0C89E1A2EC3BE002794F8 /* ContentExtensionsBackend.h */; };
+               26F0C8A01A2EC3BE002794F8 /* ContentExtensionsBackend.h in Headers */ = {isa = PBXBuildFile; fileRef = 26F0C89E1A2EC3BE002794F8 /* ContentExtensionsBackend.h */; settings = {ATTRIBUTES = (Private, ); }; };
                26F40D4A14904A6300CA67C4 /* EventLoopIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 26F40D4914904A6300CA67C4 /* EventLoopIOS.mm */; };
                26F9A83818A046AC00AEB88A /* ViewportConfiguration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F9A83618A046AC00AEB88A /* ViewportConfiguration.cpp */; };
                26F9A83918A046AC00AEB88A /* ViewportConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 26F9A83718A046AC00AEB88A /* ViewportConfiguration.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5C4304B6191AEF46000E2BC0 /* JSEXTShaderTextureLOD.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C4304B4191AEF46000E2BC0 /* JSEXTShaderTextureLOD.h */; };
                5C9A7A751AA0F6EA00958ACF /* DFABytecodeCompiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C39305E1AA0F6A90029C816 /* DFABytecodeCompiler.cpp */; };
                5C9A7A761AA0F6ED00958ACF /* DFABytecodeInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C3930601AA0F6A90029C816 /* DFABytecodeInterpreter.cpp */; };
-               5CD9F5661AA0F73C00DA45FF /* DFABytecode.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C39305D1AA0F6A90029C816 /* DFABytecode.h */; };
+               5CD9F5661AA0F73C00DA45FF /* DFABytecode.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C39305D1AA0F6A90029C816 /* DFABytecode.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5CD9F5671AA0F74200DA45FF /* DFABytecodeCompiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C39305F1AA0F6A90029C816 /* DFABytecodeCompiler.h */; };
                5CD9F5681AA0F74600DA45FF /* DFABytecodeInterpreter.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C3930611AA0F6A90029C816 /* DFABytecodeInterpreter.h */; };
-               5CDFA6C81AA4F2DA00EA8746 /* ContentExtensionActions.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CDFA6C71AA4F2DA00EA8746 /* ContentExtensionActions.h */; };
+               5CDFA6C81AA4F2DA00EA8746 /* ContentExtensionActions.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CDFA6C71AA4F2DA00EA8746 /* ContentExtensionActions.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5CFC4350192409E300A0D3B5 /* PointerLockController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5CFC434E192406A900A0D3B5 /* PointerLockController.cpp */; };
                5D21A80213ECE5DF00BB7064 /* WebVTTParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5D21A80013ECE5DF00BB7064 /* WebVTTParser.cpp */; };
                5D21A80313ECE5DF00BB7064 /* WebVTTParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D21A80113ECE5DF00BB7064 /* WebVTTParser.h */; };
                7C74D43818823B1900E5ED57 /* UTextProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C74D43618823B1900E5ED57 /* UTextProvider.h */; };
                7C74D43B1882400400E5ED57 /* UTextProviderUTF16.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C74D4391882400400E5ED57 /* UTextProviderUTF16.cpp */; };
                7C74D43C1882400400E5ED57 /* UTextProviderUTF16.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C74D43A1882400400E5ED57 /* UTextProviderUTF16.h */; };
+               7C93F3491AA6BA5E00A98BAB /* CompiledContentExtension.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C93F3471AA6BA5E00A98BAB /* CompiledContentExtension.cpp */; };
+               7C93F34A1AA6BA5E00A98BAB /* CompiledContentExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C93F3481AA6BA5E00A98BAB /* CompiledContentExtension.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               7C93F34D1AA6BF0700A98BAB /* ContentExtensionCompiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C93F34B1AA6BF0700A98BAB /* ContentExtensionCompiler.cpp */; };
+               7C93F34E1AA6BF0700A98BAB /* ContentExtensionCompiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C93F34C1AA6BF0700A98BAB /* ContentExtensionCompiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7C9DBFED1A9C49B1000D6B25 /* JSHTMLAttachmentElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C9DBFEB1A9C49B1000D6B25 /* JSHTMLAttachmentElement.cpp */; };
                7C9DBFEE1A9C49B1000D6B25 /* JSHTMLAttachmentElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9DBFEC1A9C49B1000D6B25 /* JSHTMLAttachmentElement.h */; };
                7CC289DF1AA0FE5D009A9CE3 /* URLRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = CDEE393817974274001D7580 /* URLRegistry.h */; settings = {ATTRIBUTES = (Private, ); }; };
                26C17A3C1491D2D400D12BA2 /* FileSystemIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileSystemIOS.h; path = ios/FileSystemIOS.h; sourceTree = "<group>"; };
                26C17A3D1491D2D400D12BA2 /* FileSystemIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = FileSystemIOS.mm; path = ios/FileSystemIOS.mm; sourceTree = "<group>"; };
                26E98A0F130A9FCA008EB7B2 /* TextCodecASCIIFastPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextCodecASCIIFastPath.h; sourceTree = "<group>"; };
-               26F0C8951A2E724B002794F8 /* ContentExtensionsManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContentExtensionsManager.cpp; sourceTree = "<group>"; };
-               26F0C8961A2E724B002794F8 /* ContentExtensionsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContentExtensionsManager.h; sourceTree = "<group>"; };
+               26F0C8951A2E724B002794F8 /* ContentExtensionParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContentExtensionParser.cpp; sourceTree = "<group>"; };
+               26F0C8961A2E724B002794F8 /* ContentExtensionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContentExtensionParser.h; sourceTree = "<group>"; };
                26F0C8991A2EC110002794F8 /* ContentExtensionRule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContentExtensionRule.cpp; sourceTree = "<group>"; };
                26F0C89A1A2EC110002794F8 /* ContentExtensionRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContentExtensionRule.h; sourceTree = "<group>"; };
                26F0C89D1A2EC3BE002794F8 /* ContentExtensionsBackend.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContentExtensionsBackend.cpp; sourceTree = "<group>"; };
                7C74D43618823B1900E5ED57 /* UTextProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UTextProvider.h; sourceTree = "<group>"; };
                7C74D4391882400400E5ED57 /* UTextProviderUTF16.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UTextProviderUTF16.cpp; sourceTree = "<group>"; };
                7C74D43A1882400400E5ED57 /* UTextProviderUTF16.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UTextProviderUTF16.h; sourceTree = "<group>"; };
+               7C93F3471AA6BA5E00A98BAB /* CompiledContentExtension.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompiledContentExtension.cpp; sourceTree = "<group>"; };
+               7C93F3481AA6BA5E00A98BAB /* CompiledContentExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompiledContentExtension.h; sourceTree = "<group>"; };
+               7C93F34B1AA6BF0700A98BAB /* ContentExtensionCompiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContentExtensionCompiler.cpp; sourceTree = "<group>"; };
+               7C93F34C1AA6BF0700A98BAB /* ContentExtensionCompiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContentExtensionCompiler.h; sourceTree = "<group>"; };
                7C9DBFEA1A9C489F000D6B25 /* HTMLAttachmentElement.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = HTMLAttachmentElement.idl; sourceTree = "<group>"; };
                7C9DBFEB1A9C49B1000D6B25 /* JSHTMLAttachmentElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLAttachmentElement.cpp; sourceTree = "<group>"; };
                7C9DBFEC1A9C49B1000D6B25 /* JSHTMLAttachmentElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSHTMLAttachmentElement.h; sourceTree = "<group>"; };
                26F0C8901A2D79CB002794F8 /* contentextensions */ = {
                        isa = PBXGroup;
                        children = (
+                               7C93F3471AA6BA5E00A98BAB /* CompiledContentExtension.cpp */,
+                               7C93F3481AA6BA5E00A98BAB /* CompiledContentExtension.h */,
                                5CDFA6C71AA4F2DA00EA8746 /* ContentExtensionActions.h */,
+                               7C93F34B1AA6BF0700A98BAB /* ContentExtensionCompiler.cpp */,
+                               7C93F34C1AA6BF0700A98BAB /* ContentExtensionCompiler.h */,
+                               26F0C8951A2E724B002794F8 /* ContentExtensionParser.cpp */,
+                               26F0C8961A2E724B002794F8 /* ContentExtensionParser.h */,
                                26F0C8991A2EC110002794F8 /* ContentExtensionRule.cpp */,
                                26F0C89A1A2EC110002794F8 /* ContentExtensionRule.h */,
                                26F0C89D1A2EC3BE002794F8 /* ContentExtensionsBackend.cpp */,
                                26F0C89E1A2EC3BE002794F8 /* ContentExtensionsBackend.h */,
                                262391351A648CEE007251A3 /* ContentExtensionsDebugging.h */,
-                               26F0C8951A2E724B002794F8 /* ContentExtensionsManager.cpp */,
-                               26F0C8961A2E724B002794F8 /* ContentExtensionsManager.h */,
                                267725F61A5B3AD9003C24DD /* DFA.cpp */,
                                267725F71A5B3AD9003C24DD /* DFA.h */,
                                5C39305D1AA0F6A90029C816 /* DFABytecode.h */,
                                B2FA3D570AB75A6F000E5AC4 /* JSSVGAnimationElement.h in Headers */,
                                B2FA3D590AB75A6F000E5AC4 /* JSSVGCircleElement.h in Headers */,
                                B2FA3D5B0AB75A6F000E5AC4 /* JSSVGClipPathElement.h in Headers */,
-                               26F0C8981A2E724B002794F8 /* ContentExtensionsManager.h in Headers */,
+                               26F0C8981A2E724B002794F8 /* ContentExtensionParser.h in Headers */,
                                B2FA3D5D0AB75A6F000E5AC4 /* JSSVGColor.h in Headers */,
                                B2FA3D5F0AB75A6F000E5AC4 /* JSSVGComponentTransferFunctionElement.h in Headers */,
                                B2FA3D610AB75A6F000E5AC4 /* JSSVGCursorElement.h in Headers */,
                                0854B0211255E4E600B9CDD0 /* SVGInlineTextBox.h in Headers */,
                                B2227A300D00BF220071B782 /* SVGLangSpace.h in Headers */,
                                B2227A330D00BF220071B782 /* SVGLength.h in Headers */,
+                               7C93F34A1AA6BA5E00A98BAB /* CompiledContentExtension.h in Headers */,
                                7134496E146941B300720312 /* SVGLengthContext.h in Headers */,
                                B2227A360D00BF220071B782 /* SVGLengthList.h in Headers */,
                                B2227A390D00BF220071B782 /* SVGLinearGradientElement.h in Headers */,
                                8419D2BA120E0C7600141F8F /* SVGPathStringBuilder.h in Headers */,
                                84300BD6120C9AAC0021954A /* SVGPathStringSource.h in Headers */,
                                84C5B2FB1216DC810088B53A /* SVGPathTraversalStateBuilder.h in Headers */,
+                               7C93F34E1AA6BF0700A98BAB /* ContentExtensionCompiler.h in Headers */,
                                71A57DF2154BE25C0009D120 /* SVGPathUtilities.h in Headers */,
                                B2227A880D00BF220071B782 /* SVGPatternElement.h in Headers */,
                                B2227A8C0D00BF220071B782 /* SVGPointList.h in Headers */,
                                1ACE53DF0A8D18810022947D /* JSDOMParser.cpp in Sources */,
                                FB91392B16AE4FC0001FE682 /* JSDOMPath.cpp in Sources */,
                                A9D247FE0D757E6900FDF959 /* JSDOMPlugin.cpp in Sources */,
-                               26F0C8971A2E724B002794F8 /* ContentExtensionsManager.cpp in Sources */,
+                               26F0C8971A2E724B002794F8 /* ContentExtensionParser.cpp in Sources */,
                                A9D248000D757E6900FDF959 /* JSDOMPluginArray.cpp in Sources */,
                                A9C6E64C0D7465E7006442E9 /* JSDOMPluginArrayCustom.cpp in Sources */,
                                A9C6E64D0D7465E7006442E9 /* JSDOMPluginCustom.cpp in Sources */,
                                B2FA3E160AB75A6F000E5AC4 /* JSSVGViewElement.cpp in Sources */,
                                7118FED415685CC60030B79A /* JSSVGViewSpec.cpp in Sources */,
                                8485227D1190162C006EDC7F /* JSSVGVKernElement.cpp in Sources */,
+                               7C93F3491AA6BA5E00A98BAB /* CompiledContentExtension.cpp in Sources */,
                                71DCB7011568197600862271 /* JSSVGZoomAndPan.cpp in Sources */,
                                B2FA3E180AB75A6F000E5AC4 /* JSSVGZoomEvent.cpp in Sources */,
                                65DF320309D1CC60000BE325 /* JSText.cpp in Sources */,
                                CD1B4A65160786AE00282DF9 /* MediaKeyNeededEvent.cpp in Sources */,
                                6C568CB019DAFEA000430CA2 /* MaskImageOperation.cpp in Sources */,
                                CDA98E0D1603FE4A00FEA3B1 /* MediaKeys.cpp in Sources */,
+                               7C93F34D1AA6BF0700A98BAB /* ContentExtensionCompiler.cpp in Sources */,
                                CDA98E0E1603FE5800FEA3B1 /* MediaKeySession.cpp in Sources */,
                                A8EA80090A19516E00A8EF5F /* MediaList.cpp in Sources */,
                                E44613E30CD6819F00FADA75 /* MediaPlayer.cpp in Sources */,
diff --git a/Source/WebCore/contentextensions/CompiledContentExtension.cpp b/Source/WebCore/contentextensions/CompiledContentExtension.cpp
new file mode 100644 (file)
index 0000000..7af61b2
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CompiledContentExtension.h"
+
+#if ENABLE(CONTENT_EXTENSIONS)
+
+namespace WebCore {
+namespace ContentExtensions {
+
+Ref<CompiledContentExtension> CompiledContentExtension::create(Vector<DFABytecode>&& bytecode, Vector<SerializedActionByte>&& actions)
+{
+    return WTF::adoptRef(*new CompiledContentExtension(WTF::move(bytecode), WTF::move(actions)));
+}
+
+CompiledContentExtension::CompiledContentExtension(Vector<DFABytecode>&& bytecode, Vector<SerializedActionByte>&& actions)
+    : m_bytecode(WTF::move(bytecode))
+    , m_actions(WTF::move(actions))
+{
+}
+
+} // namespace ContentExtensions
+} // namespace WebCore
+
+#endif // ENABLE(CONTENT_EXTENSIONS)
diff --git a/Source/WebCore/contentextensions/CompiledContentExtension.h b/Source/WebCore/contentextensions/CompiledContentExtension.h
new file mode 100644 (file)
index 0000000..e7091e6
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CompiledContentExtension_h
+#define CompiledContentExtension_h
+
+#if ENABLE(CONTENT_EXTENSIONS)
+
+#include "ContentExtensionRule.h"
+#include "DFABytecode.h"
+#include <wtf/ThreadSafeRefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+namespace ContentExtensions {
+
+class CompiledContentExtension : public ThreadSafeRefCounted<CompiledContentExtension> {
+public:
+    static Ref<CompiledContentExtension> create(Vector<DFABytecode>&&, Vector<SerializedActionByte>&&);
+
+    const Vector<DFABytecode>& bytecode() const { return m_bytecode; }
+    const Vector<SerializedActionByte>& actions() const { return m_actions; }
+
+private:
+    CompiledContentExtension(Vector<DFABytecode>&&, Vector<SerializedActionByte>&&);
+
+    Vector<DFABytecode> m_bytecode;
+    Vector<SerializedActionByte> m_actions;
+};
+
+} // namespace ContentExtensions
+
+} // namespace WebCore
+
+#endif // ENABLE(CONTENT_EXTENSIONS)
+#endif // CompiledContentExtension_h
diff --git a/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp b/Source/WebCore/contentextensions/ContentExtensionCompiler.cpp
new file mode 100644 (file)
index 0000000..eb6b2f4
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ContentExtensionCompiler.h"
+
+#if ENABLE(CONTENT_EXTENSIONS)
+
+#include "CompiledContentExtension.h"
+#include "ContentExtensionActions.h"
+#include "ContentExtensionParser.h"
+#include "ContentExtensionRule.h"
+#include "ContentExtensionsDebugging.h"
+#include "DFABytecodeCompiler.h"
+#include "NFA.h"
+#include "NFAToDFA.h"
+#include "URLFilterParser.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/DataLog.h>
+#include <wtf/text/CString.h>
+
+namespace WebCore {
+namespace ContentExtensions {
+
+static Vector<unsigned> serializeActions(const Vector<ContentExtensionRule>& ruleList, Vector<SerializedActionByte>& actions)
+{
+    ASSERT(!actions.size());
+    
+    Vector<unsigned> actionLocations;
+        
+    for (unsigned ruleIndex = 0; ruleIndex < ruleList.size(); ++ruleIndex) {
+        const ContentExtensionRule& rule = ruleList[ruleIndex];
+        actionLocations.append(actions.size());
+        
+        switch (rule.action().type()) {
+        case ActionType::InvalidAction:
+            RELEASE_ASSERT_NOT_REACHED();
+
+        case ActionType::BlockLoad:
+        case ActionType::BlockCookies:
+        case ActionType::IgnorePreviousRules:
+            actions.append(static_cast<SerializedActionByte>(rule.action().type()));
+            break;
+
+        case ActionType::CSSDisplayNone: {
+            const String& selector = rule.action().cssSelector();
+            // Append action type (1 byte).
+            actions.append(static_cast<SerializedActionByte>(ActionType::CSSDisplayNone));
+            // Append Selector length (4 bytes).
+            unsigned selectorLength = selector.length();
+            actions.resize(actions.size() + sizeof(unsigned));
+            *reinterpret_cast<unsigned*>(&actions[actions.size() - sizeof(unsigned)]) = selectorLength;
+            bool wideCharacters = !selector.is8Bit();
+            actions.append(wideCharacters);
+            // Append Selector.
+            if (wideCharacters) {
+                for (unsigned i = 0; i < selectorLength; i++) {
+                    actions.resize(actions.size() + sizeof(UChar));
+                    *reinterpret_cast<UChar*>(&actions[actions.size() - sizeof(UChar)]) = selector[i];
+                }
+            } else {
+                for (unsigned i = 0; i < selectorLength; i++)
+                    actions.append(selector[i]);
+            }
+            break;
+        }
+        }
+    }
+    return actionLocations;
+}
+
+
+Ref<CompiledContentExtension> compileRuleList(const String& ruleList)
+{
+    auto parsedRuleList = parseRuleList(ruleList);
+
+#if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
+    double nfaBuildTimeStart = monotonicallyIncreasingTime();
+#endif
+
+    Vector<SerializedActionByte> actions;
+    Vector<unsigned> actionLocations = serializeActions(parsedRuleList, actions);
+
+    NFA nfa;
+    URLFilterParser urlFilterParser(nfa);
+    for (unsigned ruleIndex = 0; ruleIndex < parsedRuleList.size(); ++ruleIndex) {
+        const ContentExtensionRule& contentExtensionRule = parsedRuleList[ruleIndex];
+        const Trigger& trigger = contentExtensionRule.trigger();
+        ASSERT(trigger.urlFilter.length());
+
+        String error = urlFilterParser.addPattern(trigger.urlFilter, trigger.urlFilterIsCaseSensitive, actionLocations[ruleIndex]);
+
+        if (!error.isNull()) {
+            dataLogF("Error while parsing %s: %s\n", trigger.urlFilter.utf8().data(), error.utf8().data());
+            continue;
+        }
+    }
+
+#if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
+    double nfaBuildTimeEnd = monotonicallyIncreasingTime();
+    dataLogF("    Time spent building the NFA: %f\n", (nfaBuildTimeEnd - nfaBuildTimeStart));
+#endif
+
+#if CONTENT_EXTENSIONS_STATE_MACHINE_DEBUGGING
+    nfa.debugPrintDot();
+#endif
+
+#if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
+    double dfaBuildTimeStart = monotonicallyIncreasingTime();
+#endif
+
+    const DFA dfa = NFAToDFA::convert(nfa);
+
+#if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
+    double dfaBuildTimeEnd = monotonicallyIncreasingTime();
+    dataLogF("    Time spent building the DFA: %f\n", (dfaBuildTimeEnd - dfaBuildTimeStart));
+#endif
+
+    // FIXME: never add a DFA that only matches the empty set.
+
+#if CONTENT_EXTENSIONS_STATE_MACHINE_DEBUGGING
+    dfa.debugPrintDot();
+#endif
+
+    Vector<DFABytecode> bytecode;
+    DFABytecodeCompiler compiler(dfa, bytecode);
+    compiler.compile();
+
+    return CompiledContentExtension::create(WTF::move(bytecode), WTF::move(actions));
+}
+
+} // namespace ContentExtensions
+} // namespace WebCore
+
+#endif // ENABLE(CONTENT_EXTENSIONS)
diff --git a/Source/WebCore/contentextensions/ContentExtensionCompiler.h b/Source/WebCore/contentextensions/ContentExtensionCompiler.h
new file mode 100644 (file)
index 0000000..a6c2e16
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ContentExtensionCompiler_h
+#define ContentExtensionCompiler_h
+
+#if ENABLE(CONTENT_EXTENSIONS)
+
+#include "CompiledContentExtension.h"
+#include <wtf/Forward.h>
+#include <wtf/Ref.h>
+
+namespace WebCore {
+namespace ContentExtensions {
+
+WEBCORE_EXPORT Ref<CompiledContentExtension> compileRuleList(const String&);
+
+} // namespace ContentExtensions
+} // namespace WebCore
+
+#endif // ENABLE(CONTENT_EXTENSIONS)
+#endif // ContentExtensionCompiler_h
@@ -24,7 +24,7 @@
  */
 
 #include "config.h"
-#include "ContentExtensionsManager.h"
+#include "ContentExtensionParser.h"
 
 #if ENABLE(CONTENT_EXTENSIONS)
 
@@ -46,8 +46,6 @@ namespace WebCore {
 
 namespace ContentExtensions {
 
-namespace ExtensionsManager {
-
 static bool loadTrigger(ExecState& exec, JSObject& ruleObject, Trigger& trigger)
 {
     JSValue triggerObject = ruleObject.get(&exec, Identifier(&exec, "trigger"));
@@ -170,7 +168,7 @@ static Vector<ContentExtensionRule> loadEncodedRules(ExecState& exec, const Stri
     return Vector<ContentExtensionRule>();
 }
 
-Vector<ContentExtensionRule> createRuleList(const String& rules)
+Vector<ContentExtensionRule> parseRuleList(const String& rules)
 {
 #if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
     double loadExtensionStartTime = monotonicallyIncreasingTime();
@@ -196,7 +194,6 @@ Vector<ContentExtensionRule> createRuleList(const String& rules)
     return ruleList;
 }
 
-} // namespace ExtensionsManager
 } // namespace ContentExtensions
 } // namespace WebCore
 
@@ -23,8 +23,8 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef ContentExtensionsManager_h
-#define ContentExtensionsManager_h
+#ifndef ContentExtensionParser_h
+#define ContentExtensionParser_h
 
 #if ENABLE(CONTENT_EXTENSIONS)
 
@@ -37,16 +37,11 @@ namespace ContentExtensions {
 
 class ContentExtensionRule;
 
-// The ExtensionsManager loads serialized content extension rules directly into WebCore.
-namespace ExtensionsManager {
-
-Vector<ContentExtensionRule> createRuleList(const String& rules);
-
-} // namespace ExtensionsManager
+Vector<ContentExtensionRule> parseRuleList(const String& rules);
 
 } // namespace ContentExtensions
 } // namespace WebCore
 
 #endif // ENABLE(CONTENT_EXTENSIONS)
 
-#endif // ContentExtensionsManager_h
+#endif // ContentExtensionParser_h
index 565809a..37d4478 100644 (file)
 
 #if ENABLE(CONTENT_EXTENSIONS)
 
-#include "ContentExtensionsDebugging.h"
-#include "DFABytecodeCompiler.h"
+#include "CompiledContentExtension.h"
 #include "DFABytecodeInterpreter.h"
-#include "NFA.h"
-#include "NFAToDFA.h"
 #include "URL.h"
-#include "URLFilterParser.h"
-#include <wtf/CurrentTime.h>
-#include <wtf/DataLog.h>
-#include <wtf/NeverDestroyed.h>
 #include <wtf/text/CString.h>
 
 namespace WebCore {
 
 namespace ContentExtensions {
     
-Vector<unsigned> ContentExtensionsBackend::serializeActions(const Vector<ContentExtensionRule>& ruleList, Vector<SerializedActionByte>& actions)
-{
-    ASSERT(!actions.size());
-    
-    Vector<unsigned> actionLocations;
-        
-    for (unsigned ruleIndex = 0; ruleIndex < ruleList.size(); ++ruleIndex) {
-        const ContentExtensionRule& rule = ruleList[ruleIndex];
-        actionLocations.append(actions.size());
-        
-        switch (rule.action().type()) {
-        case ActionType::InvalidAction:
-            RELEASE_ASSERT_NOT_REACHED();
-
-        case ActionType::BlockLoad:
-        case ActionType::BlockCookies:
-        case ActionType::IgnorePreviousRules:
-            actions.append(static_cast<SerializedActionByte>(rule.action().type()));
-            break;
-
-        case ActionType::CSSDisplayNone: {
-            const String& selector = rule.action().cssSelector();
-            // Append action type (1 byte).
-            actions.append(static_cast<SerializedActionByte>(ActionType::CSSDisplayNone));
-            // Append Selector length (4 bytes).
-            unsigned selectorLength = selector.length();
-            actions.resize(actions.size() + sizeof(unsigned));
-            *reinterpret_cast<unsigned*>(&actions[actions.size() - sizeof(unsigned)]) = selectorLength;
-            bool wideCharacters = !selector.is8Bit();
-            actions.append(wideCharacters);
-            // Append Selector.
-            if (wideCharacters) {
-                for (unsigned i = 0; i < selectorLength; i++) {
-                    actions.resize(actions.size() + sizeof(UChar));
-                    *reinterpret_cast<UChar*>(&actions[actions.size() - sizeof(UChar)]) = selector[i];
-                }
-            } else {
-                for (unsigned i = 0; i < selectorLength; i++)
-                    actions.append(selector[i]);
-            }
-            break;
-        }
-        }
-    }
-    return actionLocations;
-}
-
-void ContentExtensionsBackend::setRuleList(const String& identifier, const Vector<ContentExtensionRule>& ruleList)
+void ContentExtensionsBackend::addContentExtension(const String& identifier, RefPtr<CompiledContentExtension> compiledContentExtension)
 {
     ASSERT(!identifier.isEmpty());
     if (identifier.isEmpty())
         return;
 
-    if (ruleList.isEmpty()) {
-        removeRuleList(identifier);
+    if (!compiledContentExtension) {
+        removeContentExtension(identifier);
         return;
     }
 
-#if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
-    double nfaBuildTimeStart = monotonicallyIncreasingTime();
-#endif
-
-    Vector<SerializedActionByte> actions;
-    Vector<unsigned> actionLocations = serializeActions(ruleList, actions);
-
-    NFA nfa;
-    URLFilterParser urlFilterParser(nfa);
-    for (unsigned ruleIndex = 0; ruleIndex < ruleList.size(); ++ruleIndex) {
-        const ContentExtensionRule& contentExtensionRule = ruleList[ruleIndex];
-        const Trigger& trigger = contentExtensionRule.trigger();
-        ASSERT(trigger.urlFilter.length());
-
-        String error = urlFilterParser.addPattern(trigger.urlFilter, trigger.urlFilterIsCaseSensitive, actionLocations[ruleIndex]);
-
-        if (!error.isNull()) {
-            dataLogF("Error while parsing %s: %s\n", trigger.urlFilter.utf8().data(), error.utf8().data());
-            continue;
-        }
-    }
-
-#if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
-    double nfaBuildTimeEnd = monotonicallyIncreasingTime();
-    dataLogF("    Time spent building the NFA: %f\n", (nfaBuildTimeEnd - nfaBuildTimeStart));
-#endif
-
-#if CONTENT_EXTENSIONS_STATE_MACHINE_DEBUGGING
-    nfa.debugPrintDot();
-#endif
-
-#if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
-    double dfaBuildTimeStart = monotonicallyIncreasingTime();
-#endif
-
-    const DFA dfa = NFAToDFA::convert(nfa);
-
-#if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
-    double dfaBuildTimeEnd = monotonicallyIncreasingTime();
-    dataLogF("    Time spent building the DFA: %f\n", (dfaBuildTimeEnd - dfaBuildTimeStart));
-#endif
-
-    // FIXME: never add a DFA that only matches the empty set.
-
-#if CONTENT_EXTENSIONS_STATE_MACHINE_DEBUGGING
-    dfa.debugPrintDot();
-#endif
-
-    Vector<DFABytecode> bytecode;
-    DFABytecodeCompiler compiler(dfa, bytecode);
-    compiler.compile();
-    CompiledContentExtension compiledContentExtension = { bytecode, actions };
-    m_ruleLists.set(identifier, compiledContentExtension);
+    m_contentExtensions.set(identifier, compiledContentExtension);
 }
 
-void ContentExtensionsBackend::removeRuleList(const String& identifier)
+void ContentExtensionsBackend::removeContentExtension(const String& identifier)
 {
-    m_ruleLists.remove(identifier);
+    m_contentExtensions.remove(identifier);
 }
 
-void ContentExtensionsBackend::removeAllRuleLists()
+void ContentExtensionsBackend::removeAllContentExtensions()
 {
-    m_ruleLists.clear();
+    m_contentExtensions.clear();
 }
 
 Vector<Action> ContentExtensionsBackend::actionsForURL(const URL& url)
@@ -174,9 +68,8 @@ Vector<Action> ContentExtensionsBackend::actionsForURL(const URL& url)
     const CString& urlCString = urlString.utf8();
 
     Vector<Action> actions;
-    for (auto& ruleListSlot : m_ruleLists) {
-        const CompiledContentExtension& compiledContentExtension = ruleListSlot.value;
-        DFABytecodeInterpreter interpreter(compiledContentExtension.bytecode);
+    for (auto& compiledContentExtension : m_contentExtensions.values()) {
+        DFABytecodeInterpreter interpreter(compiledContentExtension->bytecode());
         DFABytecodeInterpreter::Actions triggeredActions = interpreter.interpret(urlCString);
         
         if (!triggeredActions.isEmpty()) {
@@ -188,7 +81,7 @@ Vector<Action> ContentExtensionsBackend::actionsForURL(const URL& url)
             
             // Add actions in reverse order to properly deal with IgnorePreviousRules.
             for (unsigned i = actionLocations.size(); i; i--) {
-                Action action = Action::deserialize(ruleListSlot.value.actions, actionLocations[i - 1]);
+                Action action = Action::deserialize(compiledContentExtension->actions(), actionLocations[i - 1]);
                 if (action.type() == ActionType::IgnorePreviousRules)
                     break;
                 actions.append(action);
index a667330..eaf9bd7 100644 (file)
@@ -29,9 +29,6 @@
 #if ENABLE(CONTENT_EXTENSIONS)
 
 #include "ContentExtensionRule.h"
-#include "DFA.h"
-#include "DFABytecode.h"
-#include "UserContentController.h"
 #include <wtf/HashMap.h>
 #include <wtf/text/StringHash.h>
 #include <wtf/text/WTFString.h>
@@ -42,6 +39,8 @@ class URL;
 
 namespace ContentExtensions {
 
+class CompiledContentExtension;
+
 // The ContentExtensionsBackend is the internal model of all the content extensions.
 //
 // It provides two services:
@@ -53,22 +52,15 @@ public:
 
     // Set a list of rules for a given name. If there were existing rules for the name, they are overriden.
     // The identifier cannot be empty.
-    void setRuleList(const String& identifier, const Vector<ContentExtensionRule>&);
-    void removeRuleList(const String& identifier);
-    void removeAllRuleLists();
+    WEBCORE_EXPORT void addContentExtension(const String& identifier, RefPtr<CompiledContentExtension>);
+    WEBCORE_EXPORT void removeContentExtension(const String& identifier);
+    WEBCORE_EXPORT void removeAllContentExtensions();
 
     // - Internal WebCore Interface.
-    Vector<Action> actionsForURL(const URL&);
+    WEBCORE_EXPORT Vector<Action> actionsForURL(const URL&);
 
 private:
-    struct CompiledContentExtension {
-        Vector<DFABytecode> bytecode;
-        Vector<SerializedActionByte> actions;
-    };
-
-    Vector<unsigned> serializeActions(const Vector<ContentExtensionRule>& ruleList, Vector<SerializedActionByte>& actions);
-
-    HashMap<String, CompiledContentExtension> m_ruleLists;
+    HashMap<String, RefPtr<CompiledContentExtension>> m_contentExtensions;
 };
 
 } // namespace ContentExtensions
index 08ec596..17f7040 100644 (file)
@@ -38,8 +38,8 @@
 #endif
 
 #if ENABLE(CONTENT_EXTENSIONS)
+#include "ContentExtensionCompiler.h"
 #include "ContentExtensionsBackend.h"
-#include "ContentExtensionsManager.h"
 #endif
 
 namespace WebCore {
@@ -184,7 +184,7 @@ void UserContentController::addUserContentFilter(const String& name, const Strin
     if (!m_contentExtensionBackend)
         m_contentExtensionBackend = std::make_unique<ContentExtensions::ContentExtensionsBackend>();
     
-    m_contentExtensionBackend->setRuleList(name, ContentExtensions::ExtensionsManager::createRuleList(ruleList));
+    m_contentExtensionBackend->addContentExtension(name, ContentExtensions::compileRuleList(ruleList));
 }
 
 void UserContentController::removeUserContentFilter(const String& name)
@@ -192,7 +192,7 @@ void UserContentController::removeUserContentFilter(const String& name)
     if (!m_contentExtensionBackend)
         return;
 
-    m_contentExtensionBackend->removeRuleList(name);
+    m_contentExtensionBackend->removeContentExtension(name);
 }
 
 void UserContentController::removeAllUserContentFilters()
@@ -200,7 +200,7 @@ void UserContentController::removeAllUserContentFilters()
     if (!m_contentExtensionBackend)
         return;
 
-    m_contentExtensionBackend->removeAllRuleLists();
+    m_contentExtensionBackend->removeAllContentExtensions();
 }
 
 Vector<ContentExtensions::Action> UserContentController::actionsForURL(const URL& url)
index 5618b5e..46fad66 100644 (file)
@@ -1,3 +1,18 @@
+2015-03-03  Sam Weinig  <sam@webkit.org>
+
+        [Content Extensions] Split parsing and compiling of content extensions into their own files
+        https://bugs.webkit.org/show_bug.cgi?id=142259
+
+        Reviewed by Anders Carlsson.
+
+        Add basic unit test for the content filter compiler.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebCore/ContentFilter.cpp: Added.
+        (WebCore::ContentExtensions::operator<<):
+        (TestWebKitAPI::ContentFilterTest::SetUp):
+        (TestWebKitAPI::TEST_F):
+
 2015-03-04  Matthew Mirman  <mmirman@apple.com>
 
         Cleaned up BuildAndTestFactory to not be a near duplicate of TestFactory
index 7ae978b..d2a4aa9 100644 (file)
@@ -61,6 +61,7 @@
                7C54A4C11AA11CE400380F78 /* WKBundleFileHandle_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C54A4BF1AA11CE400380F78 /* WKBundleFileHandle_Bundle.cpp */; };
                7C89D2AC1A69B80D003A5FDE /* WKPageConfiguration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C89D2AA1A69B80D003A5FDE /* WKPageConfiguration.cpp */; };
                7C9ED98B17A19F4B00E4DC33 /* attributedStringStrikethrough.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 7C9ED98A17A19D0600E4DC33 /* attributedStringStrikethrough.html */; };
+               7CB184C61AA3F2100066EDFD /* ContentFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CB184C41AA3F2100066EDFD /* ContentFilter.cpp */; };
                7CCE7EA41A4119F300447C4C /* InstanceMethodSwizzler.mm in Sources */ = {isa = PBXBuildFile; fileRef = C08587FF13FEC3A6001EF4E5 /* InstanceMethodSwizzler.mm */; };
                7CCE7EA51A411A0800447C4C /* JavaScriptTestMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = C081224013FC172400DC39AE /* JavaScriptTestMac.mm */; };
                7CCE7EA61A411A0F00447C4C /* PlatformUtilitiesMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC131884117114B600B69727 /* PlatformUtilitiesMac.mm */; };
                7C89D2AA1A69B80D003A5FDE /* WKPageConfiguration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKPageConfiguration.cpp; sourceTree = "<group>"; };
                7C8DDAA91735DE1D00EA5AC0 /* CloseThenTerminate.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CloseThenTerminate.cpp; sourceTree = "<group>"; };
                7C9ED98A17A19D0600E4DC33 /* attributedStringStrikethrough.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = attributedStringStrikethrough.html; sourceTree = "<group>"; };
+               7CB184C41AA3F2100066EDFD /* ContentFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ContentFilter.cpp; sourceTree = "<group>"; };
                7CBBA07619BB8A9100BBF025 /* OSObjectPtr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSObjectPtr.cpp; sourceTree = "<group>"; };
                7CC3E1FA197E234100BE6252 /* UserContentController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UserContentController.mm; sourceTree = "<group>"; };
                7CCE7E8C1A41144E00447C4C /* libTestWebKitAPI.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTestWebKitAPI.a; sourceTree = BUILT_PRODUCTS_DIR; };
                                14464012167A8305000BD218 /* LayoutUnit.cpp */,
                                CDC2C7141797089D00E627FB /* TimeRanges.cpp */,
                                440A1D3814A0103A008A66F2 /* URL.cpp */,
+                               7CB184C41AA3F2100066EDFD /* ContentFilter.cpp */,
                        );
                        path = WebCore;
                        sourceTree = "<group>";
                                7CCE7ECE1A411A7E00447C4C /* StopLoadingFromDidFinishLoading.mm in Sources */,
                                7CCE7ECF1A411A7E00447C4C /* StopLoadingFromDidReceiveResponse.mm in Sources */,
                                7CCE7F441A411B8E00447C4C /* StringBuilder.cpp in Sources */,
+                               7CB184C61AA3F2100066EDFD /* ContentFilter.cpp in Sources */,
                                7CCE7ED01A411A7E00447C4C /* StringByEvaluatingJavaScriptFromString.mm in Sources */,
                                7CCE7F451A411B8E00447C4C /* StringHasher.cpp in Sources */,
                                7CCE7F461A411B8E00447C4C /* StringImpl.cpp in Sources */,
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/ContentFilter.cpp b/Tools/TestWebKitAPI/Tests/WebCore/ContentFilter.cpp
new file mode 100644 (file)
index 0000000..0c15b64
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include "PlatformUtilities.h"
+#include <JavaScriptCore/InitializeThreading.h>
+#include <WebCore/ContentExtensionCompiler.h>
+#include <WebCore/ContentExtensionsBackend.h>
+#include <WebCore/URL.h>
+#include <wtf/MainThread.h>
+#include <wtf/RunLoop.h>
+
+namespace WebCore {
+namespace ContentExtensions {
+inline std::ostream& operator<<(std::ostream& os, const ActionType& action)
+{
+    switch (action) {
+    case ActionType::BlockLoad:
+        return os << "ContentFilterAction::BlockLoad";
+    case ActionType::BlockCookies:
+        return os << "ContentFilterAction::BlockCookies";
+    case ActionType::CSSDisplayNone:
+        return os << "ContentFilterAction::CSSDisplayNone";
+    case ActionType::IgnorePreviousRules:
+        return os << "ContentFilterAction::IgnorePreviousRules";
+    case ActionType::InvalidAction:
+        return os << "ContentFilterAction::InvalidAction";
+    }
+}
+}
+}
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+class ContentFilterTest : public testing::Test {
+public:
+    virtual void SetUp()
+    {
+        WTF::initializeMainThread();
+        JSC::initializeThreading();
+        RunLoop::initializeMainRunLoop();
+    }
+};
+
+const char* basicFilter = "[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*webkit.org\"}}]";
+
+TEST_F(ContentFilterTest, Basic)
+{
+    RefPtr<ContentExtensions::CompiledContentExtension> extension = ContentExtensions::compileRuleList(basicFilter);
+
+    ContentExtensions::ContentExtensionsBackend backend;
+    backend.addContentExtension("testFilter", extension);
+    
+    auto actions = backend.actionsForURL(URL(ParsedURLString, "http://webkit.org/"));
+    EXPECT_EQ(1u, actions.size());
+    EXPECT_EQ(ContentExtensions::ActionType::BlockLoad, actions[0].type());
+}
+
+} // namespace TestWebKitAPI