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

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

<h3>Log Message</h3>
<pre>[Content Extensions] Cache domain actions
https://bugs.webkit.org/show_bug.cgi?id=146817

Reviewed by Benjamin Poulain.

Source/WebCore:

Right now we run regular expressions on the domain every time we have any rules that match with if-domain or unless-domain.  
This caches the results of running regular expressions on the domain of the main document's url so we only need to 
run those regular expressions when the main document changes domain.  We also spend less time adding unused actions into HashSets.

All behavior is covered by existing api tests, but I added some to explicitly test if-domain and unless-domain with multiple load types.

* contentextensions/ContentExtension.cpp:
(WebCore::ContentExtensions::ContentExtension::globalDisplayNoneStyleSheet):
(WebCore::ContentExtensions::ContentExtension::cachedDomainActions):
* contentextensions/ContentExtension.h:
(WebCore::ContentExtensions::ContentExtension::identifier):
(WebCore::ContentExtensions::ContentExtension::compiledExtension):
* contentextensions/ContentExtensionsBackend.cpp:
(WebCore::ContentExtensions::ContentExtensionsBackend::actionsForResourceLoad):
* contentextensions/DFABytecodeInterpreter.cpp:
(WebCore::ContentExtensions::getJumpDistance):
(WebCore::ContentExtensions::matchesDomain):
(WebCore::ContentExtensions::DFABytecodeInterpreter::interpretAppendAction):
(WebCore::ContentExtensions::DFABytecodeInterpreter::interpretTestFlagsAndAppendAction):
(WebCore::ContentExtensions::DFABytecodeInterpreter::actionsForDefaultStylesheetFromDFARoot):
(WebCore::ContentExtensions::DFABytecodeInterpreter::interpretWithDomains):
(WebCore::ContentExtensions::DFABytecodeInterpreter::interpret):
* contentextensions/DFABytecodeInterpreter.h:

Tools:

* TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp:
(TestWebKitAPI::TEST_F):
Test if-domain and unless-domain with multiple load types.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorecontentextensionsContentExtensioncpp">trunk/Source/WebCore/contentextensions/ContentExtension.cpp</a></li>
<li><a href="#trunkSourceWebCorecontentextensionsContentExtensionh">trunk/Source/WebCore/contentextensions/ContentExtension.h</a></li>
<li><a href="#trunkSourceWebCorecontentextensionsContentExtensionsBackendcpp">trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp</a></li>
<li><a href="#trunkSourceWebCorecontentextensionsDFABytecodeInterpretercpp">trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp</a></li>
<li><a href="#trunkSourceWebCorecontentextensionsDFABytecodeInterpreterh">trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.h</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebCoreContentExtensionscpp">trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (186911 => 186912)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-07-16 21:54:06 UTC (rev 186911)
+++ trunk/Source/WebCore/ChangeLog        2015-07-16 22:08:19 UTC (rev 186912)
</span><span class="lines">@@ -1,3 +1,34 @@
</span><ins>+2015-07-16  Alex Christensen  &lt;achristensen@webkit.org&gt;
+
+        [Content Extensions] Cache domain actions
+        https://bugs.webkit.org/show_bug.cgi?id=146817
+
+        Reviewed by Benjamin Poulain.
+
+        Right now we run regular expressions on the domain every time we have any rules that match with if-domain or unless-domain.  
+        This caches the results of running regular expressions on the domain of the main document's url so we only need to 
+        run those regular expressions when the main document changes domain.  We also spend less time adding unused actions into HashSets.
+
+        All behavior is covered by existing api tests, but I added some to explicitly test if-domain and unless-domain with multiple load types.
+
+        * contentextensions/ContentExtension.cpp:
+        (WebCore::ContentExtensions::ContentExtension::globalDisplayNoneStyleSheet):
+        (WebCore::ContentExtensions::ContentExtension::cachedDomainActions):
+        * contentextensions/ContentExtension.h:
+        (WebCore::ContentExtensions::ContentExtension::identifier):
+        (WebCore::ContentExtensions::ContentExtension::compiledExtension):
+        * contentextensions/ContentExtensionsBackend.cpp:
+        (WebCore::ContentExtensions::ContentExtensionsBackend::actionsForResourceLoad):
+        * contentextensions/DFABytecodeInterpreter.cpp:
+        (WebCore::ContentExtensions::getJumpDistance):
+        (WebCore::ContentExtensions::matchesDomain):
+        (WebCore::ContentExtensions::DFABytecodeInterpreter::interpretAppendAction):
+        (WebCore::ContentExtensions::DFABytecodeInterpreter::interpretTestFlagsAndAppendAction):
+        (WebCore::ContentExtensions::DFABytecodeInterpreter::actionsForDefaultStylesheetFromDFARoot):
+        (WebCore::ContentExtensions::DFABytecodeInterpreter::interpretWithDomains):
+        (WebCore::ContentExtensions::DFABytecodeInterpreter::interpret):
+        * contentextensions/DFABytecodeInterpreter.h:
+
</ins><span class="cx"> 2015-07-16  Simon Fraser  &lt;simon.fraser@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Fix disappearing position:fixed elements in fixed layout mode
</span></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsContentExtensioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/contentextensions/ContentExtension.cpp (186911 => 186912)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/ContentExtension.cpp        2015-07-16 21:54:06 UTC (rev 186911)
+++ trunk/Source/WebCore/contentextensions/ContentExtension.cpp        2015-07-16 22:08:19 UTC (rev 186912)
</span><span class="lines">@@ -75,6 +75,21 @@
</span><span class="cx">     return m_globalDisplayNoneStyleSheet.get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+const DFABytecodeInterpreter::Actions&amp; ContentExtension::cachedDomainActions(const String&amp; domain)
+{
+    if (m_cachedDomain != domain) {
+        DFABytecodeInterpreter interpreter(m_compiledExtension-&gt;domainFiltersBytecode(), m_compiledExtension-&gt;domainFiltersBytecodeLength());
+        const uint16_t allLoadTypesAndResourceTypes = LoadTypeMask | ResourceTypeMask;
+        auto domainActions = interpreter.interpret(domain.utf8(), allLoadTypesAndResourceTypes);
+        
+        m_cachedDomainActions.clear();
+        for (uint64_t action : domainActions)
+            m_cachedDomainActions.add(action);
+        m_cachedDomain = domain;
+    }
+    return m_cachedDomainActions;
+}
+    
</ins><span class="cx"> } // namespace ContentExtensions
</span><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsContentExtensionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/contentextensions/ContentExtension.h (186911 => 186912)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/ContentExtension.h        2015-07-16 21:54:06 UTC (rev 186911)
+++ trunk/Source/WebCore/contentextensions/ContentExtension.h        2015-07-16 22:08:19 UTC (rev 186912)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(CONTENT_EXTENSIONS)
</span><span class="cx"> 
</span><ins>+#include &quot;DFABytecodeInterpreter.h&quot;
</ins><span class="cx"> #include &quot;StyleSheetContents.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -47,6 +48,7 @@
</span><span class="cx">     const String&amp; identifier() const { return m_identifier; }
</span><span class="cx">     const CompiledContentExtension&amp; compiledExtension() const { return m_compiledExtension.get(); }
</span><span class="cx">     StyleSheetContents* globalDisplayNoneStyleSheet();
</span><ins>+    const DFABytecodeInterpreter::Actions&amp; cachedDomainActions(const String&amp; domain);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     ContentExtension(const String&amp; identifier, Ref&lt;CompiledContentExtension&gt;&amp;&amp;);
</span><span class="lines">@@ -55,6 +57,9 @@
</span><span class="cx">     Ref&lt;CompiledContentExtension&gt; m_compiledExtension;
</span><span class="cx">     RefPtr&lt;StyleSheetContents&gt; m_globalDisplayNoneStyleSheet;
</span><span class="cx">     bool m_parsedGlobalDisplayNoneStyleSheet;
</span><ins>+    
+    String m_cachedDomain;
+    DFABytecodeInterpreter::Actions m_cachedDomainActions;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace ContentExtensions
</span></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsContentExtensionsBackendcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp (186911 => 186912)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp        2015-07-16 21:54:06 UTC (rev 186911)
+++ trunk/Source/WebCore/contentextensions/ContentExtensionsBackend.cpp        2015-07-16 22:08:19 UTC (rev 186912)
</span><span class="lines">@@ -90,47 +90,22 @@
</span><span class="cx">         const CompiledContentExtension&amp; compiledExtension = contentExtension-&gt;compiledExtension();
</span><span class="cx">         
</span><span class="cx">         DFABytecodeInterpreter withoutDomainsInterpreter(compiledExtension.filtersWithoutDomainsBytecode(), compiledExtension.filtersWithoutDomainsBytecodeLength());
</span><del>-        DFABytecodeInterpreter::Actions triggeredActions = withoutDomainsInterpreter.interpret(urlCString, flags);
</del><ins>+        DFABytecodeInterpreter::Actions withoutDomainsActions = withoutDomainsInterpreter.interpret(urlCString, flags);
</ins><span class="cx">         
</span><del>-        // Check to see if there are any actions triggered with if- or unless-domain and check the domain if there are.
</del><span class="cx">         DFABytecodeInterpreter withDomainsInterpreter(compiledExtension.filtersWithDomainsBytecode(), compiledExtension.filtersWithDomainsBytecodeLength());
</span><ins>+        DFABytecodeInterpreter::Actions withDomainsActions = withDomainsInterpreter.interpretWithDomains(urlCString, flags, contentExtension-&gt;cachedDomainActions(resourceLoadInfo.mainDocumentURL.host()));
</ins><span class="cx">         
</span><del>-        DFABytecodeInterpreter::Actions withDomainsPossibleActions = withDomainsInterpreter.interpret(urlCString, flags);
-        if (!withDomainsPossibleActions.isEmpty()) {
-            DFABytecodeInterpreter domainsInterpreter(compiledExtension.domainFiltersBytecode(), compiledExtension.domainFiltersBytecodeLength());
-            DFABytecodeInterpreter::Actions domainsActions = domainsInterpreter.interpret(resourceLoadInfo.mainDocumentURL.host().utf8(), flags);
-            
-            DFABytecodeInterpreter::Actions ifDomainActions;
-            DFABytecodeInterpreter::Actions unlessDomainActions;
-            for (uint64_t action : domainsActions) {
-                if (action &amp; IfDomainFlag)
-                    ifDomainActions.add(action);
-                else
-                    unlessDomainActions.add(action);
-            }
-            
-            for (uint64_t action : withDomainsPossibleActions) {
-                if (ifDomainActions.contains(action)) {
-                    // If an if-domain trigger matches, add the action.
-                    ASSERT(action &amp; IfDomainFlag);
-                    triggeredActions.add(action &amp; ~IfDomainFlag);
-                } else if (!(action &amp; IfDomainFlag) &amp;&amp; !unlessDomainActions.contains(action)) {
-                    // If this action did not need an if-domain, it must have been an unless-domain rule.
-                    // Add the action unless it matched an unless-domain trigger.
-                    triggeredActions.add(action);
-                }
-            }
-        }
-        
</del><span class="cx">         const SerializedActionByte* actions = compiledExtension.actions();
</span><span class="cx">         const unsigned actionsLength = compiledExtension.actionsLength();
</span><span class="cx">         
</span><span class="cx">         bool sawIgnorePreviousRules = false;
</span><del>-        if (!triggeredActions.isEmpty()) {
-            Vector&lt;unsigned&gt; actionLocations;
-            actionLocations.reserveInitialCapacity(triggeredActions.size());
-            for (auto actionLocation : triggeredActions)
-                actionLocations.append(static_cast&lt;unsigned&gt;(actionLocation));
</del><ins>+        if (!withoutDomainsActions.isEmpty() || !withDomainsActions.isEmpty()) {
+            Vector&lt;uint32_t&gt; actionLocations;
+            actionLocations.reserveInitialCapacity(withoutDomainsActions.size() + withDomainsActions.size());
+            for (uint64_t actionLocation : withoutDomainsActions)
+                actionLocations.uncheckedAppend(static_cast&lt;uint32_t&gt;(actionLocation));
+            for (uint64_t actionLocation : withDomainsActions)
+                actionLocations.uncheckedAppend(static_cast&lt;uint32_t&gt;(actionLocation));
</ins><span class="cx">             std::sort(actionLocations.begin(), actionLocations.end());
</span><span class="cx"> 
</span><span class="cx">             // Add actions in reverse order to properly deal with IgnorePreviousRules.
</span></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsDFABytecodeInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp (186911 => 186912)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp        2015-07-16 21:54:06 UTC (rev 186911)
+++ trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.cpp        2015-07-16 22:08:19 UTC (rev 186912)
</span><span class="lines">@@ -86,12 +86,22 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static inline bool matchesDomain(uint64_t actionAndFlags, const DFABytecodeInterpreter::Actions&amp; domainActions)
+{
+    bool ifDomain = actionAndFlags &amp; IfDomainFlag;
+    bool domain = domainActions.contains(actionAndFlags);
+    return ifDomain == domain;
+}
+
</ins><span class="cx"> void DFABytecodeInterpreter::interpretAppendAction(uint32_t&amp; programCounter, Actions&amp; actions, bool ifDomain)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(getInstruction(m_bytecode, m_bytecodeLength, programCounter) == DFABytecodeInstruction::AppendAction
</span><span class="cx">         || getInstruction(m_bytecode, m_bytecodeLength, programCounter) == DFABytecodeInstruction::AppendActionWithIfDomain
</span><span class="cx">         || getInstruction(m_bytecode, m_bytecodeLength, programCounter) == DFABytecodeInstruction::AppendActionDefaultStylesheet);
</span><del>-    actions.add((ifDomain ? IfDomainFlag : 0) | static_cast&lt;uint64_t&gt;(getBits&lt;uint32_t&gt;(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction))));
</del><ins>+    uint64_t action = (ifDomain ? IfDomainFlag : 0) | static_cast&lt;uint64_t&gt;(getBits&lt;uint32_t&gt;(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction)));
+    if (!m_domainActions || matchesDomain(action, *m_domainActions))
+        actions.add(action);
+    
</ins><span class="cx">     programCounter += instructionSizeWithArguments(DFABytecodeInstruction::AppendAction);
</span><span class="cx">     ASSERT(instructionSizeWithArguments(DFABytecodeInstruction::AppendAction) == instructionSizeWithArguments(DFABytecodeInstruction::AppendActionWithIfDomain));
</span><span class="cx">     ASSERT(instructionSizeWithArguments(DFABytecodeInstruction::AppendAction) == instructionSizeWithArguments(DFABytecodeInstruction::AppendActionDefaultStylesheet));
</span><span class="lines">@@ -104,13 +114,16 @@
</span><span class="cx">     uint16_t flagsToCheck = getBits&lt;uint16_t&gt;(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction));
</span><span class="cx"> 
</span><span class="cx">     uint16_t loadTypeFlags = flagsToCheck &amp; LoadTypeMask;
</span><del>-    uint16_t ressourceTypeFlags = flagsToCheck &amp; ResourceTypeMask;
</del><ins>+    uint16_t resourceTypeFlags = flagsToCheck &amp; ResourceTypeMask;
</ins><span class="cx">     
</span><span class="cx">     bool loadTypeMatches = loadTypeFlags ? (loadTypeFlags &amp; flags) : true;
</span><del>-    bool ressourceTypeMatches = ressourceTypeFlags ? (ressourceTypeFlags &amp; flags) : true;
</del><ins>+    bool resourceTypeMatches = resourceTypeFlags ? (resourceTypeFlags &amp; flags) : true;
</ins><span class="cx">     
</span><del>-    if (loadTypeMatches &amp;&amp; ressourceTypeMatches)
-        actions.add((ifDomain ? IfDomainFlag : 0) | static_cast&lt;uint64_t&gt;(getBits&lt;uint32_t&gt;(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint16_t))));
</del><ins>+    if (loadTypeMatches &amp;&amp; resourceTypeMatches) {
+        uint64_t actionAndFlags = (ifDomain ? IfDomainFlag : 0) | (static_cast&lt;uint64_t&gt;(flagsToCheck) &lt;&lt; 32) | static_cast&lt;uint64_t&gt;(getBits&lt;uint32_t&gt;(m_bytecode, m_bytecodeLength, programCounter + sizeof(DFABytecodeInstruction) + sizeof(uint16_t)));
+        if (!m_domainActions || matchesDomain(actionAndFlags, *m_domainActions))
+            actions.add(actionAndFlags);
+    }
</ins><span class="cx">     programCounter += instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendAction);
</span><span class="cx">     ASSERT(instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendAction) == instructionSizeWithArguments(DFABytecodeInstruction::TestFlagsAndAppendActionWithIfDomain));
</span><span class="cx"> }
</span><span class="lines">@@ -142,6 +155,15 @@
</span><span class="cx">     return actions;
</span><span class="cx"> }
</span><span class="cx">     
</span><ins>+DFABytecodeInterpreter::Actions DFABytecodeInterpreter::interpretWithDomains(const CString&amp; urlCString, uint16_t flags, const DFABytecodeInterpreter::Actions&amp; domainActions)
+{
+    ASSERT(!m_domainActions);
+    m_domainActions = &amp;domainActions;
+    DFABytecodeInterpreter::Actions actions = interpret(urlCString, flags);
+    m_domainActions = nullptr;
+    return actions;
+}
+
</ins><span class="cx"> DFABytecodeInterpreter::Actions DFABytecodeInterpreter::interpret(const CString&amp; urlCString, uint16_t flags)
</span><span class="cx"> {
</span><span class="cx">     const char* url = urlCString.data();
</span></span></pre></div>
<a id="trunkSourceWebCorecontentextensionsDFABytecodeInterpreterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.h (186911 => 186912)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.h        2015-07-16 21:54:06 UTC (rev 186911)
+++ trunk/Source/WebCore/contentextensions/DFABytecodeInterpreter.h        2015-07-16 22:08:19 UTC (rev 186912)
</span><span class="lines">@@ -50,6 +50,7 @@
</span><span class="cx">     typedef HashSet&lt;uint64_t, DefaultHash&lt;uint64_t&gt;::Hash, WTF::UnsignedWithZeroKeyHashTraits&lt;uint64_t&gt;&gt; Actions;
</span><span class="cx">     
</span><span class="cx">     Actions interpret(const CString&amp;, uint16_t flags);
</span><ins>+    Actions interpretWithDomains(const CString&amp;, uint16_t flags, const DFABytecodeInterpreter::Actions&amp; domainActions);
</ins><span class="cx">     Actions actionsForDefaultStylesheetFromDFARoot();
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="lines">@@ -57,6 +58,7 @@
</span><span class="cx">     void interpretTestFlagsAndAppendAction(unsigned&amp; programCounter, uint16_t flags, Actions&amp;, bool ifDomain);
</span><span class="cx">     const DFABytecode* m_bytecode;
</span><span class="cx">     const unsigned m_bytecodeLength;
</span><ins>+    const DFABytecodeInterpreter::Actions* m_domainActions { nullptr };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace ContentExtensions
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (186911 => 186912)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2015-07-16 21:54:06 UTC (rev 186911)
+++ trunk/Tools/ChangeLog        2015-07-16 22:08:19 UTC (rev 186912)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2015-07-16  Alex Christensen  &lt;achristensen@webkit.org&gt;
+
+        [Content Extensions] Cache domain actions
+        https://bugs.webkit.org/show_bug.cgi?id=146817
+
+        Reviewed by Benjamin Poulain.
+
+        * TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp:
+        (TestWebKitAPI::TEST_F):
+        Test if-domain and unless-domain with multiple load types.
+
</ins><span class="cx"> 2015-07-16  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Content extensions] Combine suffixes when generating NFAs
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebCoreContentExtensionscpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp (186911 => 186912)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp        2015-07-16 21:54:06 UTC (rev 186911)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp        2015-07-16 22:08:19 UTC (rev 186912)
</span><span class="lines">@@ -1204,6 +1204,38 @@
</span><span class="cx">         &quot;{\&quot;action\&quot;:{\&quot;type\&quot;:\&quot;css-display-none\&quot;,\&quot;selector\&quot;:\&quot;.hidden\&quot;},\&quot;trigger\&quot;:{\&quot;url-filter\&quot;:\&quot;.*\&quot;}}]&quot;);
</span><span class="cx">     EXPECT_EQ(nullptr, backend5.globalDisplayNoneStyleSheet(ASCIILiteral(&quot;testFilter&quot;)));
</span><span class="cx">     testRequest(backend5, mainDocumentRequest(&quot;http://webkit.org&quot;), { ContentExtensions::ActionType::CSSDisplayNoneSelector }, true);
</span><ins>+    
+    auto backend6 = makeBackend(&quot;[{\&quot;action\&quot;:{\&quot;type\&quot;:\&quot;block\&quot;},\&quot;trigger\&quot;:{\&quot;url-filter\&quot;:\&quot;.*\&quot;,\&quot;if-domain\&quot;:[\&quot;webkit.org\&quot;,\&quot;*w3c.org\&quot;],\&quot;resource-type\&quot;:[\&quot;document\&quot;,\&quot;script\&quot;]}},&quot;
+        &quot;{\&quot;action\&quot;:{\&quot;type\&quot;:\&quot;ignore-previous-rules\&quot;},\&quot;trigger\&quot;:{\&quot;url-filter\&quot;:\&quot;ignore\&quot;,\&quot;if-domain\&quot;:[\&quot;*webkit.org\&quot;,\&quot;w3c.org\&quot;]}},&quot;
+        &quot;{\&quot;action\&quot;:{\&quot;type\&quot;:\&quot;block-cookies\&quot;},\&quot;trigger\&quot;:{\&quot;url-filter\&quot;:\&quot;.*\&quot;,\&quot;unless-domain\&quot;:[\&quot;webkit.org\&quot;,\&quot;whatwg.org\&quot;],\&quot;resource-type\&quot;:[\&quot;script\&quot;,\&quot;image\&quot;],\&quot;load-type\&quot;:[\&quot;third-party\&quot;]}}]&quot;);
+    EXPECT_EQ(nullptr, backend6.globalDisplayNoneStyleSheet(ASCIILiteral(&quot;testFilter&quot;)));
+    testRequest(backend6, mainDocumentRequest(&quot;http://webkit.org&quot;), { ContentExtensions::ActionType::BlockLoad });
+    testRequest(backend6, mainDocumentRequest(&quot;http://w3c.org&quot;), { ContentExtensions::ActionType::BlockLoad });
+    testRequest(backend6, mainDocumentRequest(&quot;http://whatwg.org&quot;), { });
+    testRequest(backend6, mainDocumentRequest(&quot;http://sub.webkit.org&quot;), { });
+    testRequest(backend6, mainDocumentRequest(&quot;http://sub.w3c.org&quot;), { ContentExtensions::ActionType::BlockLoad });
+    testRequest(backend6, mainDocumentRequest(&quot;http://sub.whatwg.org&quot;), { });
+    testRequest(backend6, mainDocumentRequest(&quot;http://webkit.org/ignore&quot;), { }, true);
+    testRequest(backend6, mainDocumentRequest(&quot;http://w3c.org/ignore&quot;), { }, true);
+    testRequest(backend6, mainDocumentRequest(&quot;http://whatwg.org/ignore&quot;), { });
+    testRequest(backend6, mainDocumentRequest(&quot;http://sub.webkit.org/ignore&quot;), { }, true);
+    testRequest(backend6, mainDocumentRequest(&quot;http://sub.w3c.org/ignore&quot;), { ContentExtensions::ActionType::BlockLoad });
+    testRequest(backend6, mainDocumentRequest(&quot;http://sub.whatwg.org/ignore&quot;), { });
+    testRequest(backend6, subResourceRequest(&quot;http://example.com/image.png&quot;, &quot;http://webkit.org/&quot;, ResourceType::Image), { });
+    testRequest(backend6, subResourceRequest(&quot;http://example.com/image.png&quot;, &quot;http://w3c.org/&quot;, ResourceType::Image), { ContentExtensions::ActionType::BlockCookies });
+    testRequest(backend6, subResourceRequest(&quot;http://example.com/doc.html&quot;, &quot;http://webkit.org/&quot;, ResourceType::Document), { ContentExtensions::ActionType::BlockLoad });
+    testRequest(backend6, subResourceRequest(&quot;http://example.com/script.js&quot;, &quot;http://webkit.org/&quot;, ResourceType::Script), { ContentExtensions::ActionType::BlockLoad });
+    testRequest(backend6, subResourceRequest(&quot;http://example.com/script.js&quot;, &quot;http://w3c.org/&quot;, ResourceType::Script), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad });
+    testRequest(backend6, subResourceRequest(&quot;http://example.com/script.js&quot;, &quot;http://example.com/&quot;, ResourceType::Script), { });
+    testRequest(backend6, subResourceRequest(&quot;http://example.com/ignore/image.png&quot;, &quot;http://webkit.org/&quot;, ResourceType::Image), { }, true);
+    testRequest(backend6, subResourceRequest(&quot;http://example.com/ignore/image.png&quot;, &quot;http://example.com/&quot;, ResourceType::Image), { });
+    testRequest(backend6, subResourceRequest(&quot;http://example.com/ignore/image.png&quot;, &quot;http://example.org/&quot;, ResourceType::Image), { ContentExtensions::ActionType::BlockCookies });
+    testRequest(backend6, subResourceRequest(&quot;http://example.com/doc.html&quot;, &quot;http://example.org/&quot;, ResourceType::Document), { });
+    testRequest(backend6, subResourceRequest(&quot;http://example.com/&quot;, &quot;http://example.com/&quot;, ResourceType::Font), { });
+    testRequest(backend6, subResourceRequest(&quot;http://example.com/ignore&quot;, &quot;http://webkit.org/&quot;, ResourceType::Image), { }, true);
+    testRequest(backend6, subResourceRequest(&quot;http://example.com/ignore&quot;, &quot;http://webkit.org/&quot;, ResourceType::Font), { }, true);
+    testRequest(backend6, subResourceRequest(&quot;http://example.com/&quot;, &quot;http://example.com/&quot;, ResourceType::Script), { });
+    testRequest(backend6, subResourceRequest(&quot;http://example.com/ignore&quot;, &quot;http://example.com/&quot;, ResourceType::Script), { });
</ins><span class="cx"> }
</span><span class="cx">     
</span><span class="cx"> TEST_F(ContentExtensionTest, InvalidJSON)
</span></span></pre>
</div>
</div>

</body>
</html>