[Content Extensions] Support domain-specific rules and exceptions.
https://bugs.webkit.org/show_bug.cgi?id=144833

Patch by Alex Christensen <achristensen@webkit.org> on 2015-05-11
Reviewed by Darin Adler.

Source/WebCore:

Test: http/tests/contentextensions/domain-rules.html
(And lots of API tests)

This patch adds if-domain and unless-domain to the trigger in the JSON format.
if-domain makes the rule apply only to domains in the list.
unless-domain makes the rule apply to domains that are not in the list.

All rules without if-domain or unless-domain are compiled into a set of DFAs.  This behavior is unchanged.
All rules with if-domain or unless-domain are compiled into a separate set of DFAs.
The domains are also compiled into another set of DFAs.  This makes 3 arrays of DFA bytecode instead of 1.

If there are no domain specific rules, there is no change in behavior.
If there are domain specific rules, the URL will be checked for matches in both
filtersWithoutDomainsBytecode and filtersWithDomainsBytecode.  If there are matches from
filtersWithDomainsBytecode then the domain of the main document will be checked with
domainFiltersBytecode to see which of the matches applies to this domain.

* contentextensions/CombinedURLFilters.cpp:
(WebCore::ContentExtensions::CombinedURLFilters::isEmpty):
(WebCore::ContentExtensions::CombinedURLFilters::addDomain):
* contentextensions/CombinedURLFilters.h:
Added addDomain, which adds characters from a domain to the prefix tree directly without using YARR.
* contentextensions/CompiledContentExtension.cpp:
(WebCore::ContentExtensions::CompiledContentExtension::globalDisplayNoneSelectors):
* contentextensions/CompiledContentExtension.h:
* contentextensions/ContentExtensionCompiler.cpp:
(WebCore::ContentExtensions::serializeActions):
(WebCore::ContentExtensions::compileRuleList):
Separate the rules into rules with domains and rules without domains and compile to bytecode.
* contentextensions/ContentExtensionCompiler.h:
Updated compiler interface to reflect the slightly more complicated structure.
* contentextensions/ContentExtensionError.cpp:
(WebCore::ContentExtensions::contentExtensionErrorCategory):
* contentextensions/ContentExtensionError.h:
Added new parsing errors.
* contentextensions/ContentExtensionParser.cpp:
(WebCore::ContentExtensions::getDomainList):
(WebCore::ContentExtensions::loadTrigger):
(WebCore::ContentExtensions::loadEncodedRules):
* contentextensions/ContentExtensionRule.h:
(WebCore::ContentExtensions::Trigger::operator==):
Parse the new domain structures from JSON into the Trigger structure.
* contentextensions/ContentExtensionsBackend.cpp:
(WebCore::ContentExtensions::ContentExtensionsBackend::actionsForResourceLoad):
Interpret as much bytecode as necessary to determine which rules apply to this URL and domain.
* contentextensions/DFABytecode.h:
(WebCore::ContentExtensions::instructionSizeWithArguments):
* contentextensions/DFABytecodeCompiler.cpp:
(WebCore::ContentExtensions::DFABytecodeCompiler::emitAppendAction):
(WebCore::ContentExtensions::DFABytecodeCompiler::emitTestFlagsAndAppendAction):
(WebCore::ContentExtensions::DFABytecodeCompiler::compileNode):
* contentextensions/DFABytecodeCompiler.h:
* contentextensions/DFABytecodeInterpreter.cpp:
(WebCore::ContentExtensions::DFABytecodeInterpreter::interpretAppendAction):
(WebCore::ContentExtensions::DFABytecodeInterpreter::interpretTestFlagsAndAppendAction):
(WebCore::ContentExtensions::DFABytecodeInterpreter::actionsFromDFARoot):
(WebCore::ContentExtensions::DFABytecodeInterpreter::interpret):
* contentextensions/DFABytecodeInterpreter.h:
* loader/ResourceLoadInfo.h:
Keep track of which actions have an if-domain trigger.  If an action is in the
filtersWithDomainsBytecode, then it either has an if-domain or an unless-domain in its trigger.
This requires additional information in the bytecode, so there are two new bytecode types.

Source/WebKit2:

* Shared/WebCompiledContentExtension.cpp:
(WebKit::WebCompiledContentExtension::filtersWithoutDomainsBytecode):
(WebKit::WebCompiledContentExtension::filtersWithoutDomainsBytecodeLength):
(WebKit::WebCompiledContentExtension::filtersWithDomainsBytecode):
(WebKit::WebCompiledContentExtension::filtersWithDomainsBytecodeLength):
(WebKit::WebCompiledContentExtension::domainFiltersBytecode):
(WebKit::WebCompiledContentExtension::domainFiltersBytecodeLength):
(WebKit::WebCompiledContentExtension::bytecode): Deleted.
(WebKit::WebCompiledContentExtension::bytecodeLength): Deleted.
* Shared/WebCompiledContentExtension.h:
* Shared/WebCompiledContentExtensionData.cpp:
(WebKit::WebCompiledContentExtensionData::encode):
(WebKit::WebCompiledContentExtensionData::decode):
* Shared/WebCompiledContentExtensionData.h:
(WebKit::WebCompiledContentExtensionData::WebCompiledContentExtensionData):
* UIProcess/API/APIUserContentExtensionStore.cpp:
(API::ContentExtensionMetaData::fileSize):
(API::encodeContentExtensionMetaData):
(API::decodeContentExtensionMetaData):
(API::compiledToFile):
(API::createExtension):
Keep track of 3 different types of bytecode to be able to handle domain-specific rules.

Tools:

* TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp:
(TestWebKitAPI::InMemoryCompiledContentExtension::createFromFilter):
(TestWebKitAPI::InMemoryCompiledContentExtension::create):
(TestWebKitAPI::InMemoryCompiledContentExtension::InMemoryCompiledContentExtension):
Moved CompiledContentExtensionData from ContentExtensionCompiler.h because it is only used for testing.
(TestWebKitAPI::mainDocumentRequest):
(TestWebKitAPI::subResourceRequest):
(TestWebKitAPI::TEST_F):
(TestWebKitAPI::checkCompilerError):
Added tests for parsing and functionality of if-domain and unless-domain.

LayoutTests:

* http/tests/contentextensions/domain-rules-expected.txt: Added.
* http/tests/contentextensions/domain-rules.html: Added.
* http/tests/contentextensions/domain-rules.html.json: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@184116 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebKit2/Shared/WebCompiledContentExtensionData.h b/Source/WebKit2/Shared/WebCompiledContentExtensionData.h
index 40085a3..bd5137b 100644
--- a/Source/WebKit2/Shared/WebCompiledContentExtensionData.h
+++ b/Source/WebKit2/Shared/WebCompiledContentExtensionData.h
@@ -45,13 +45,17 @@
     {
     }
     
-    WebCompiledContentExtensionData(RefPtr<SharedMemory>&& data, NetworkCache::Data fileData, unsigned actionsOffset, unsigned actionsSize, unsigned bytecodeOffset, unsigned bytecodeSize)
+    WebCompiledContentExtensionData(RefPtr<SharedMemory>&& data, NetworkCache::Data fileData, unsigned actionsOffset, unsigned actionsSize, unsigned filtersWithoutDomainsBytecodeOffset, unsigned filtersWithoutDomainsBytecodeSize, unsigned filtersWithDomainsBytecodeOffset, unsigned filtersWithDomainsBytecodeSize, unsigned domainFiltersBytecodeOffset, unsigned domainFiltersBytecodeSize)
         : data(WTF::move(data))
         , fileData(fileData)
         , actionsOffset(actionsOffset)
         , actionsSize(actionsSize)
-        , bytecodeOffset(bytecodeOffset)
-        , bytecodeSize(bytecodeSize)
+        , filtersWithoutDomainsBytecodeOffset(filtersWithoutDomainsBytecodeOffset)
+        , filtersWithoutDomainsBytecodeSize(filtersWithoutDomainsBytecodeSize)
+        , filtersWithDomainsBytecodeOffset(filtersWithDomainsBytecodeOffset)
+        , filtersWithDomainsBytecodeSize(filtersWithDomainsBytecodeSize)
+        , domainFiltersBytecodeOffset(domainFiltersBytecodeOffset)
+        , domainFiltersBytecodeSize(domainFiltersBytecodeSize)
     {
     }
 
@@ -62,8 +66,12 @@
     NetworkCache::Data fileData;
     unsigned actionsOffset { 0 };
     unsigned actionsSize { 0 };
-    unsigned bytecodeOffset { 0 };
-    unsigned bytecodeSize { 0 };
+    unsigned filtersWithoutDomainsBytecodeOffset { 0 };
+    unsigned filtersWithoutDomainsBytecodeSize { 0 };
+    unsigned filtersWithDomainsBytecodeOffset { 0 };
+    unsigned filtersWithDomainsBytecodeSize { 0 };
+    unsigned domainFiltersBytecodeOffset { 0 };
+    unsigned domainFiltersBytecodeSize { 0 };
 };
 
 }