[Content Extensions] Remove memory page reporting
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebCore / ContentExtensions.cpp
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #include "PlatformUtilities.h"
29 #include <JavaScriptCore/InitializeThreading.h>
30 #include <WebCore/CombinedURLFilters.h>
31 #include <WebCore/ContentExtensionCompiler.h>
32 #include <WebCore/ContentExtensionError.h>
33 #include <WebCore/ContentExtensionsBackend.h>
34 #include <WebCore/DFA.h>
35 #include <WebCore/DFABytecodeCompiler.h>
36 #include <WebCore/DFABytecodeInterpreter.h>
37 #include <WebCore/NFA.h>
38 #include <WebCore/NFAToDFA.h>
39 #include <WebCore/ResourceLoadInfo.h>
40 #include <WebCore/URL.h>
41 #include <WebCore/URLFilterParser.h>
42 #include <wtf/MainThread.h>
43 #include <wtf/RunLoop.h>
44 #include <wtf/text/CString.h>
45 #include <wtf/text/StringBuilder.h>
46
47 namespace WebCore {
48 namespace ContentExtensions {
49 inline std::ostream& operator<<(std::ostream& os, const ActionType& action)
50 {
51     switch (action) {
52     case ActionType::BlockLoad:
53         return os << "ContentFilterAction::BlockLoad";
54     case ActionType::BlockCookies:
55         return os << "ContentFilterAction::BlockCookies";
56     case ActionType::CSSDisplayNoneSelector:
57         return os << "ContentFilterAction::CSSDisplayNone";
58     case ActionType::CSSDisplayNoneStyleSheet:
59         return os << "ContentFilterAction::CSSDisplayNoneStyleSheet";
60     case ActionType::IgnorePreviousRules:
61         return os << "ContentFilterAction::IgnorePreviousRules";
62     case ActionType::InvalidAction:
63         return os << "ContentFilterAction::InvalidAction";
64     }
65 }
66 }
67 }
68
69 using namespace WebCore;
70
71 namespace TestWebKitAPI {
72
73 class ContentExtensionTest : public testing::Test {
74 public:
75     virtual void SetUp()
76     {
77         WTF::initializeMainThread();
78         JSC::initializeThreading();
79         RunLoop::initializeMainRunLoop();
80     }
81 };
82
83 struct CompiledContentExtensionData {
84     Vector<ContentExtensions::SerializedActionByte> actions;
85     Vector<ContentExtensions::DFABytecode> filtersWithoutDomains;
86     Vector<ContentExtensions::DFABytecode> filtersWithDomains;
87     Vector<ContentExtensions::DFABytecode> domainFilters;
88 };
89
90 class InMemoryContentExtensionCompilationClient final : public ContentExtensions::ContentExtensionCompilationClient {
91 public:
92     InMemoryContentExtensionCompilationClient(CompiledContentExtensionData& data)
93         : m_data(data)
94     {
95         EXPECT_EQ(data.actions.size(), 0ull);
96         EXPECT_EQ(data.filtersWithoutDomains.size(), 0ull);
97         EXPECT_EQ(data.filtersWithDomains.size(), 0ull);
98         EXPECT_EQ(data.domainFilters.size(), 0ull);
99     }
100
101     virtual void writeActions(Vector<ContentExtensions::SerializedActionByte>&& actions) override
102     {
103         EXPECT_FALSE(finalized);
104         EXPECT_EQ(m_data.actions.size(), 0ull);
105         EXPECT_EQ(m_data.filtersWithoutDomains.size(), 0ull);
106         EXPECT_EQ(m_data.filtersWithDomains.size(), 0ull);
107         EXPECT_EQ(m_data.domainFilters.size(), 0ull);
108         m_data.actions.appendVector(actions);
109     }
110     
111     virtual void writeFiltersWithoutDomainsBytecode(Vector<ContentExtensions::DFABytecode>&& bytecode) override
112     {
113         EXPECT_FALSE(finalized);
114         EXPECT_EQ(m_data.filtersWithDomains.size(), 0ull);
115         EXPECT_EQ(m_data.domainFilters.size(), 0ull);
116         m_data.filtersWithoutDomains.appendVector(bytecode);
117     }
118     
119     virtual void writeFiltersWithDomainsBytecode(Vector<ContentExtensions::DFABytecode>&& bytecode) override
120     {
121         EXPECT_FALSE(finalized);
122         EXPECT_EQ(m_data.domainFilters.size(), 0ull);
123         m_data.filtersWithDomains.appendVector(bytecode);
124     }
125     
126     virtual void writeDomainFiltersBytecode(Vector<ContentExtensions::DFABytecode>&& bytecode) override
127     {
128         EXPECT_FALSE(finalized);
129         m_data.domainFilters.appendVector(bytecode);
130     }
131     
132     virtual void finalize() override
133     {
134         finalized = true;
135     }
136
137 private:
138     CompiledContentExtensionData& m_data;
139     bool finalized { false };
140 };
141
142 class InMemoryCompiledContentExtension : public ContentExtensions::CompiledContentExtension {
143 public:
144     static RefPtr<InMemoryCompiledContentExtension> createFromFilter(String&& filter)
145     {
146         CompiledContentExtensionData extensionData;
147         InMemoryContentExtensionCompilationClient client(extensionData);
148         auto compilerError = ContentExtensions::compileRuleList(client, WTF::move(filter));
149         if (compilerError) {
150             // Compiling should always succeed here. We have other tests for compile failures.
151             EXPECT_TRUE(false);
152             return nullptr;
153         }
154
155         return InMemoryCompiledContentExtension::create(WTF::move(extensionData));
156     }
157
158     static RefPtr<InMemoryCompiledContentExtension> create(CompiledContentExtensionData&& data)
159     {
160         return adoptRef(new InMemoryCompiledContentExtension(WTF::move(data)));
161     }
162
163     virtual ~InMemoryCompiledContentExtension()
164     {
165     }
166
167     virtual const ContentExtensions::SerializedActionByte* actions() const override { return m_data.actions.data(); }
168     virtual unsigned actionsLength() const override { return m_data.actions.size(); }
169     virtual const ContentExtensions::DFABytecode* filtersWithoutDomainsBytecode() const override { return m_data.filtersWithoutDomains.data(); }
170     virtual unsigned filtersWithoutDomainsBytecodeLength() const override { return m_data.filtersWithoutDomains.size(); }
171     virtual const ContentExtensions::DFABytecode* filtersWithDomainsBytecode() const override { return m_data.filtersWithDomains.data(); }
172     virtual unsigned filtersWithDomainsBytecodeLength() const override { return m_data.filtersWithDomains.size(); }
173     virtual const ContentExtensions::DFABytecode* domainFiltersBytecode() const override { return m_data.domainFilters.data(); }
174     virtual unsigned domainFiltersBytecodeLength() const override { return m_data.domainFilters.size(); }
175
176 private:
177     InMemoryCompiledContentExtension(CompiledContentExtensionData&& data)
178         : m_data(WTF::move(data))
179     {
180     }
181
182     CompiledContentExtensionData m_data;
183 };
184
185 void static testRequest(ContentExtensions::ContentExtensionsBackend contentExtensionsBackend, const ResourceLoadInfo& resourceLoadInfo, Vector<ContentExtensions::ActionType> expectedActions, bool ignorePreviousRules = false)
186 {
187     auto actions = contentExtensionsBackend.actionsForResourceLoad(resourceLoadInfo);
188     unsigned expectedSize = actions.size();
189     if (!ignorePreviousRules)
190         expectedSize--; // The last action is applying the compiled stylesheet.
191     
192     EXPECT_EQ(expectedActions.size(), expectedSize);
193     if (expectedActions.size() != expectedSize)
194         return;
195
196     for (unsigned i = 0; i < expectedActions.size(); ++i)
197         EXPECT_EQ(expectedActions[i], actions[i].type());
198     if (!ignorePreviousRules)
199         EXPECT_EQ(actions[actions.size() - 1].type(), ContentExtensions::ActionType::CSSDisplayNoneStyleSheet);
200 }
201
202 static ResourceLoadInfo mainDocumentRequest(const char* url, ResourceType resourceType = ResourceType::Document)
203 {
204     return { URL(URL(), url), URL(URL(), url), resourceType };
205 }
206
207 static ResourceLoadInfo subResourceRequest(const char* url, const char* mainDocumentURL, ResourceType resourceType = ResourceType::Document)
208 {
209     return { URL(URL(), url), URL(URL(), mainDocumentURL), resourceType };
210 }
211
212 ContentExtensions::ContentExtensionsBackend makeBackend(const char* json)
213 {
214     auto extension = InMemoryCompiledContentExtension::createFromFilter(json);
215     ContentExtensions::ContentExtensionsBackend backend;
216     backend.addContentExtension("testFilter", extension);
217     return backend;
218 }
219
220 static Vector<ContentExtensions::NFA> createNFAs(ContentExtensions::CombinedURLFilters& combinedURLFilters)
221 {
222     Vector<ContentExtensions::NFA> nfas;
223
224     combinedURLFilters.processNFAs(std::numeric_limits<size_t>::max(), [&](ContentExtensions::NFA&& nfa) {
225         nfas.append(WTF::move(nfa));
226     });
227
228     return nfas;
229 }
230
231 TEST_F(ContentExtensionTest, Basic)
232 {
233     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\"}}]");
234
235     testRequest(backend, mainDocumentRequest("http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
236 }
237
238 TEST_F(ContentExtensionTest, RangeBasic)
239 {
240     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"w[0-9]c\", \"url-filter-is-case-sensitive\":true}},"
241         "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"[A-H][a-z]cko\", \"url-filter-is-case-sensitive\":true}}]");
242
243     testRequest(backend, mainDocumentRequest("http://w3c.org"), { ContentExtensions::ActionType::BlockLoad });
244     testRequest(backend, mainDocumentRequest("w2c://whatwg.org/"), { ContentExtensions::ActionType::BlockLoad });
245     testRequest(backend, mainDocumentRequest("http://webkit.org/w0c"), { ContentExtensions::ActionType::BlockLoad });
246     testRequest(backend, mainDocumentRequest("http://webkit.org/wac"), { });
247     testRequest(backend, mainDocumentRequest("http://webkit.org/wAc"), { });
248
249     // Note: URL parsing and canonicalization lowercase the scheme and hostname.
250     testRequest(backend, mainDocumentRequest("Aacko://webkit.org"), { });
251     testRequest(backend, mainDocumentRequest("aacko://webkit.org"), { });
252     testRequest(backend, mainDocumentRequest("http://gCcko.org/"), { });
253     testRequest(backend, mainDocumentRequest("http://gccko.org/"), { });
254
255     testRequest(backend, mainDocumentRequest("http://webkit.org/Gecko"), { ContentExtensions::ActionType::BlockCookies });
256     testRequest(backend, mainDocumentRequest("http://webkit.org/gecko"), { });
257     testRequest(backend, mainDocumentRequest("http://webkit.org/GEcko"), { });
258 }
259
260 TEST_F(ContentExtensionTest, RangeExclusionGeneratingUniversalTransition)
261 {
262     // Transition of the type ([^X]X) effictively transition on every input.
263     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[^a]+afoobar\"}}]");
264
265     testRequest(backend, mainDocumentRequest("http://w3c.org"), { });
266
267     testRequest(backend, mainDocumentRequest("http://w3c.org/foobafoobar"), { ContentExtensions::ActionType::BlockLoad });
268     testRequest(backend, mainDocumentRequest("http://w3c.org/foobarfoobar"), { });
269     testRequest(backend, mainDocumentRequest("http://w3c.org/FOOBAFOOBAR"), { ContentExtensions::ActionType::BlockLoad });
270     testRequest(backend, mainDocumentRequest("http://w3c.org/FOOBARFOOBAR"), { });
271
272     // The character before the "a" prefix cannot be another "a".
273     testRequest(backend, mainDocumentRequest("http://w3c.org/aafoobar"), { });
274     testRequest(backend, mainDocumentRequest("http://w3c.org/Aafoobar"), { });
275     testRequest(backend, mainDocumentRequest("http://w3c.org/aAfoobar"), { });
276     testRequest(backend, mainDocumentRequest("http://w3c.org/AAfoobar"), { });
277 }
278
279 TEST_F(ContentExtensionTest, PatternStartingWithGroup)
280 {
281     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(http://whatwg\\\\.org/)?webkit\134\134.org\"}}]");
282
283     testRequest(backend, mainDocumentRequest("http://whatwg.org/webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
284     testRequest(backend, mainDocumentRequest("http://whatwg.org/webkit.org"), { ContentExtensions::ActionType::BlockLoad });
285     testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
286     testRequest(backend, mainDocumentRequest("http://whatwg.org/"), { });
287     testRequest(backend, mainDocumentRequest("http://whatwg.org"), { });
288 }
289
290 TEST_F(ContentExtensionTest, PatternNestedGroups)
291 {
292     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://webkit\\\\.org/(foo(bar)*)+\"}}]");
293
294     testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
295     testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
296     testRequest(backend, mainDocumentRequest("http://webkit.org/foobarbar"), { ContentExtensions::ActionType::BlockLoad });
297     testRequest(backend, mainDocumentRequest("http://webkit.org/foofoobar"), { ContentExtensions::ActionType::BlockLoad });
298     testRequest(backend, mainDocumentRequest("http://webkit.org/foobarfoobar"), { ContentExtensions::ActionType::BlockLoad });
299     testRequest(backend, mainDocumentRequest("http://webkit.org/foob"), { ContentExtensions::ActionType::BlockLoad });
300     testRequest(backend, mainDocumentRequest("http://webkit.org/foor"), { ContentExtensions::ActionType::BlockLoad });
301
302     testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
303     testRequest(backend, mainDocumentRequest("http://webkit.org/bar"), { });
304     testRequest(backend, mainDocumentRequest("http://webkit.org/fobar"), { });
305 }
306
307 TEST_F(ContentExtensionTest, EmptyGroups)
308 {
309     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://webkit\\\\.org/foo()bar\"}},"
310         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://webkit\\\\.org/((me)()(too))\"}}]");
311     testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { });
312     testRequest(backend, mainDocumentRequest("http://webkit.org/bar"), { });
313     testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
314     testRequest(backend, mainDocumentRequest("http://webkit.org/me"), { });
315     testRequest(backend, mainDocumentRequest("http://webkit.org/too"), { });
316     testRequest(backend, mainDocumentRequest("http://webkit.org/metoo"), { ContentExtensions::ActionType::BlockLoad });
317     testRequest(backend, mainDocumentRequest("http://webkit.org/foome"), { });
318     testRequest(backend, mainDocumentRequest("http://webkit.org/foomebar"), { });
319     testRequest(backend, mainDocumentRequest("http://webkit.org/mefoo"), { });
320     testRequest(backend, mainDocumentRequest("http://webkit.org/mefootoo"), { });
321 }
322
323 TEST_F(ContentExtensionTest, QuantifiedEmptyGroups)
324 {
325     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://webkit\\\\.org/foo()+bar\"}},"
326         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://webkit\\\\.org/(()*()?(target)()+)\"}}]");
327     testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { });
328     testRequest(backend, mainDocumentRequest("http://webkit.org/bar"), { });
329     testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
330     testRequest(backend, mainDocumentRequest("http://webkit.org/me"), { });
331     testRequest(backend, mainDocumentRequest("http://webkit.org/too"), { });
332     testRequest(backend, mainDocumentRequest("http://webkit.org/target"), { ContentExtensions::ActionType::BlockLoad });
333     testRequest(backend, mainDocumentRequest("http://webkit.org/foome"), { });
334     testRequest(backend, mainDocumentRequest("http://webkit.org/foomebar"), { });
335     testRequest(backend, mainDocumentRequest("http://webkit.org/mefoo"), { });
336     testRequest(backend, mainDocumentRequest("http://webkit.org/mefootoo"), { });
337 }
338
339 TEST_F(ContentExtensionTest, MatchPastEndOfString)
340 {
341     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".+\"}}]");
342
343     testRequest(backend, mainDocumentRequest("http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
344     testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
345     testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
346     testRequest(backend, mainDocumentRequest("http://webkit.org/foobarbar"), { ContentExtensions::ActionType::BlockLoad });
347     testRequest(backend, mainDocumentRequest("http://webkit.org/foofoobar"), { ContentExtensions::ActionType::BlockLoad });
348     testRequest(backend, mainDocumentRequest("http://webkit.org/foobarfoobar"), { ContentExtensions::ActionType::BlockLoad });
349     testRequest(backend, mainDocumentRequest("http://webkit.org/foob"), { ContentExtensions::ActionType::BlockLoad });
350     testRequest(backend, mainDocumentRequest("http://webkit.org/foor"), { ContentExtensions::ActionType::BlockLoad });
351 }
352
353 TEST_F(ContentExtensionTest, StartOfLineAssertion)
354 {
355     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^foobar\"}}]");
356
357     testRequest(backend, mainDocumentRequest("foobar://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
358     testRequest(backend, mainDocumentRequest("foobars:///foobar"), { ContentExtensions::ActionType::BlockLoad });
359     testRequest(backend, mainDocumentRequest("foobarfoobar:///foobarfoobarfoobar"), { ContentExtensions::ActionType::BlockLoad });
360
361     testRequest(backend, mainDocumentRequest("http://webkit.org/foobarfoo"), { });
362     testRequest(backend, mainDocumentRequest("http://webkit.org/foobarf"), { });
363     testRequest(backend, mainDocumentRequest("http://foobar.org/"), { });
364     testRequest(backend, mainDocumentRequest("http://foobar.org/"), { });
365 }
366
367 TEST_F(ContentExtensionTest, EndOfLineAssertion)
368 {
369     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"foobar$\"}}]");
370
371     testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
372     testRequest(backend, mainDocumentRequest("file:///foobar"), { ContentExtensions::ActionType::BlockLoad });
373     testRequest(backend, mainDocumentRequest("file:///foobarfoobarfoobar"), { ContentExtensions::ActionType::BlockLoad });
374
375     testRequest(backend, mainDocumentRequest("http://webkit.org/foobarfoo"), { });
376     testRequest(backend, mainDocumentRequest("http://webkit.org/foobarf"), { });
377 }
378
379 TEST_F(ContentExtensionTest, EndOfLineAssertionWithInvertedCharacterSet)
380 {
381     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[^y]$\"}}]");
382
383     testRequest(backend, mainDocumentRequest("http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
384     testRequest(backend, mainDocumentRequest("http://webkit.org/a"), { ContentExtensions::ActionType::BlockLoad });
385     testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
386     testRequest(backend, mainDocumentRequest("http://webkit.org/Ya"), { ContentExtensions::ActionType::BlockLoad });
387     testRequest(backend, mainDocumentRequest("http://webkit.org/yFoobar"), { ContentExtensions::ActionType::BlockLoad });
388     testRequest(backend, mainDocumentRequest("http://webkit.org/y"), { });
389     testRequest(backend, mainDocumentRequest("http://webkit.org/Y"), { });
390     testRequest(backend, mainDocumentRequest("http://webkit.org/foobary"), { });
391     testRequest(backend, mainDocumentRequest("http://webkit.org/foobarY"), { });
392 }
393
394 TEST_F(ContentExtensionTest, DotDoesNotIncludeEndOfLine)
395 {
396     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"https://webkit\\\\.org/.\"}}]");
397
398     testRequest(backend, mainDocumentRequest("https://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
399     testRequest(backend, mainDocumentRequest("https://webkit.org/"), { });
400     testRequest(backend, mainDocumentRequest("https://webkit.org/A"), { ContentExtensions::ActionType::BlockLoad });
401     testRequest(backend, mainDocumentRequest("https://webkit.org/z"), { ContentExtensions::ActionType::BlockLoad });
402 }
403
404 TEST_F(ContentExtensionTest, PrefixInfixSuffixExactMatch)
405 {
406     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"infix\"}},"
407         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^prefix\"}},"
408         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"suffix$\"}},"
409         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://exact\\\\.org/$\"}}]");
410
411     testRequest(backend, mainDocumentRequest("infix://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
412     testRequest(backend, mainDocumentRequest("http://infix.org/"), { ContentExtensions::ActionType::BlockLoad });
413     testRequest(backend, mainDocumentRequest("https://webkit.org/infix"), { ContentExtensions::ActionType::BlockLoad });
414
415     testRequest(backend, mainDocumentRequest("prefix://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
416     testRequest(backend, mainDocumentRequest("https://prefix.org/"), { });
417     testRequest(backend, mainDocumentRequest("https://webkit.org/prefix"), { });
418
419     testRequest(backend, mainDocumentRequest("https://webkit.org/suffix"), { ContentExtensions::ActionType::BlockLoad });
420     testRequest(backend, mainDocumentRequest("https://suffix.org/"), { });
421     testRequest(backend, mainDocumentRequest("suffix://webkit.org/"), { });
422
423     testRequest(backend, mainDocumentRequest("http://exact.org/"), { ContentExtensions::ActionType::BlockLoad });
424     testRequest(backend, mainDocumentRequest("http://exact.org/oops"), { });
425 }
426
427 TEST_F(ContentExtensionTest, DuplicatedMatchAllTermsInVariousFormat)
428 {
429     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*.*(.)*(.*)(.+)*(.?)*infix\"}},"
430         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"pre(.?)+(.+)?post\"}}]");
431
432     testRequest(backend, mainDocumentRequest("infix://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
433     testRequest(backend, mainDocumentRequest("http://infix.org/"), { ContentExtensions::ActionType::BlockLoad });
434     testRequest(backend, mainDocumentRequest("https://webkit.org/infix"), { ContentExtensions::ActionType::BlockLoad });
435
436     testRequest(backend, mainDocumentRequest("pre://webkit.org/post"), { ContentExtensions::ActionType::BlockLoad });
437     testRequest(backend, mainDocumentRequest("http://prepost.org/"), { ContentExtensions::ActionType::BlockLoad });
438     testRequest(backend, mainDocumentRequest("https://pre.org/posttail"), { ContentExtensions::ActionType::BlockLoad });
439     testRequest(backend, mainDocumentRequest("https://pre.pre/posttail"), { ContentExtensions::ActionType::BlockLoad });
440     testRequest(backend, mainDocumentRequest("https://pre.org/posttailpost"), { ContentExtensions::ActionType::BlockLoad });
441
442     testRequest(backend, mainDocumentRequest("https://post.org/pre"), { });
443     testRequest(backend, mainDocumentRequest("https://pre.org/pre"), { });
444     testRequest(backend, mainDocumentRequest("https://post.org/post"), { });
445 }
446
447 TEST_F(ContentExtensionTest, DomainTriggers)
448 {
449     auto ifDomainBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"webkit.org\"]}}]");
450     testRequest(ifDomainBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
451     testRequest(ifDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.htm"), { });
452     testRequest(ifDomainBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
453     testRequest(ifDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { });
454     testRequest(ifDomainBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { });
455     testRequest(ifDomainBackend, mainDocumentRequest("http://not_webkit.org/test.htm"), { });
456     testRequest(ifDomainBackend, mainDocumentRequest("http://webkit.organization/test.htm"), { });
457     testRequest(ifDomainBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { });
458     testRequest(ifDomainBackend, mainDocumentRequest("http://webkit.organization/test.html"), { });
459     
460     auto unlessDomainBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"webkit.org\"]}}]");
461     testRequest(unlessDomainBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
462     testRequest(unlessDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.htm"), { });
463     testRequest(unlessDomainBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
464     testRequest(unlessDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
465     testRequest(unlessDomainBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
466     testRequest(unlessDomainBackend, mainDocumentRequest("http://not_webkit.org/test.htm"), { });
467     testRequest(unlessDomainBackend, mainDocumentRequest("http://webkit.organization/test.htm"), { });
468     testRequest(unlessDomainBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
469     testRequest(unlessDomainBackend, mainDocumentRequest("http://webkit.organization/test.html"), { ContentExtensions::ActionType::BlockLoad });
470     
471     auto ifDomainStarBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"*webkit.org\"]}}]");
472     testRequest(ifDomainStarBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
473     testRequest(ifDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.htm"), { });
474     testRequest(ifDomainStarBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
475     testRequest(ifDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
476     testRequest(ifDomainStarBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
477     testRequest(ifDomainStarBackend, mainDocumentRequest("http://not_webkit.org/test.htm"), { });
478     testRequest(ifDomainStarBackend, mainDocumentRequest("http://webkit.organization/test.htm"), { });
479     testRequest(ifDomainStarBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { });
480     testRequest(ifDomainStarBackend, mainDocumentRequest("http://webkit.organization/test.html"), { });
481     
482     auto unlessDomainStarBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"*webkit.org\"]}}]");
483     testRequest(unlessDomainStarBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
484     testRequest(unlessDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.htm"), { });
485     testRequest(unlessDomainStarBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
486     testRequest(unlessDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { });
487     testRequest(unlessDomainStarBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { });
488     testRequest(unlessDomainStarBackend, mainDocumentRequest("http://not_webkit.org/test.htm"), { });
489     testRequest(unlessDomainStarBackend, mainDocumentRequest("http://webkit.organization/test.htm"), { });
490     testRequest(unlessDomainStarBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
491     testRequest(unlessDomainStarBackend, mainDocumentRequest("http://webkit.organization/test.html"), { ContentExtensions::ActionType::BlockLoad });
492
493     auto ifSubDomainBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"sub1.webkit.org\"]}}]");
494     testRequest(ifSubDomainBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
495     testRequest(ifSubDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { });
496     testRequest(ifSubDomainBackend, mainDocumentRequest("http://sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
497     testRequest(ifSubDomainBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { });
498
499     auto ifSubDomainStarBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"*sub1.webkit.org\"]}}]");
500     testRequest(ifSubDomainStarBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
501     testRequest(ifSubDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { });
502     testRequest(ifSubDomainStarBackend, mainDocumentRequest("http://sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
503     testRequest(ifSubDomainStarBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
504
505     auto unlessSubDomainBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"sub1.webkit.org\"]}}]");
506     testRequest(unlessSubDomainBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
507     testRequest(unlessSubDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
508     testRequest(unlessSubDomainBackend, mainDocumentRequest("http://sub1.webkit.org/test.html"), { });
509     testRequest(unlessSubDomainBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
510     
511     auto unlessSubDomainStarBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"*sub1.webkit.org\"]}}]");
512     testRequest(unlessSubDomainStarBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
513     testRequest(unlessSubDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
514     testRequest(unlessSubDomainStarBackend, mainDocumentRequest("http://sub1.webkit.org/test.html"), { });
515     testRequest(unlessSubDomainStarBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { });
516
517     auto combinedBackend1 = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test_block_load\", \"if-domain\":[\"webkit.org\"]}},"
518         "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"test_block_cookies\", \"unless-domain\":[\"webkit.org\"]}}]");
519     testRequest(combinedBackend1, mainDocumentRequest("http://webkit.org"), { });
520     testRequest(combinedBackend1, mainDocumentRequest("http://not_webkit.org"), { });
521     testRequest(combinedBackend1, mainDocumentRequest("http://webkit.org/test_block_load.html"), { ContentExtensions::ActionType::BlockLoad });
522     testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/test_block_load.html", "http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
523     testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/shouldnt_match.html", "http://webkit.org/"), { });
524     testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/test_block_load.html", "http://not_webkit.org/"), { });
525     testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/shouldnt_match.html", "http://not_webkit.org/"), { });
526     testRequest(combinedBackend1, mainDocumentRequest("http://webkit.org/test_block_cookies.html"), { });
527     testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/test_block_cookies.html", "http://webkit.org/"), { });
528     testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/shouldnt_match.html", "http://webkit.org/"), { });
529     testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/test_block_cookies.html", "http://not_webkit.org/path/to/main/document.html"), { ContentExtensions::ActionType::BlockCookies });
530     testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/shouldnt_match.html", "http://not_webkit.org/"), { });
531     
532     auto combinedBackend2 = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test_block_load\\\\.html\", \"if-domain\":[\"webkit.org\"]}},"
533         "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"test_block_cookies\\\\.html\", \"unless-domain\":[\"w3c.org\"]}},"
534         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"test_css\\\\.html\"}}]");
535     testRequest(combinedBackend2, mainDocumentRequest("http://webkit.org/test_css.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
536     testRequest(combinedBackend2, mainDocumentRequest("http://webkit.org/test_css.htm"), { });
537     testRequest(combinedBackend2, mainDocumentRequest("http://webkit.org/test_block_load.html"), { ContentExtensions::ActionType::BlockLoad });
538     testRequest(combinedBackend2, mainDocumentRequest("http://not_webkit.org/test_block_load.html"), { });
539     testRequest(combinedBackend2, mainDocumentRequest("http://not_webkit.org/test_css.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
540     testRequest(combinedBackend2, mainDocumentRequest("http://webkit.org/TEST_CSS.hTmL/test_block_load.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad});
541     testRequest(combinedBackend2, mainDocumentRequest("http://w3c.org/test_css.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
542     testRequest(combinedBackend2, mainDocumentRequest("http://w3c.org/test_block_load.html"), { });
543     testRequest(combinedBackend2, mainDocumentRequest("http://w3c.org/test_block_cookies.html"), { });
544     testRequest(combinedBackend2, mainDocumentRequest("http://w3c.org/test_css.html/test_block_cookies.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
545     testRequest(combinedBackend2, mainDocumentRequest("http://not_w3c.org/test_block_cookies.html"), { ContentExtensions::ActionType::BlockCookies });
546     testRequest(combinedBackend2, mainDocumentRequest("http://not_w3c.org/test_css.html/test_block_cookies.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockCookies });
547
548     auto ifDomainWithFlagsBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\", \"if-domain\":[\"webkit.org\"],\"resource-type\":[\"image\"]}}]");
549     testRequest(ifDomainWithFlagsBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
550     testRequest(ifDomainWithFlagsBackend, mainDocumentRequest("http://webkit.org/test.png", ResourceType::Image), { ContentExtensions::ActionType::BlockLoad });
551     testRequest(ifDomainWithFlagsBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { });
552     testRequest(ifDomainWithFlagsBackend, mainDocumentRequest("http://not_webkit.org/test.png", ResourceType::Image), { });
553
554     auto unlessDomainWithFlagsBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\", \"unless-domain\":[\"webkit.org\"],\"resource-type\":[\"image\"]}}]");
555     testRequest(unlessDomainWithFlagsBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
556     testRequest(unlessDomainWithFlagsBackend, mainDocumentRequest("http://webkit.org/test.png", ResourceType::Image), { });
557     testRequest(unlessDomainWithFlagsBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { });
558     testRequest(unlessDomainWithFlagsBackend, mainDocumentRequest("http://not_webkit.org/test.png", ResourceType::Image), { ContentExtensions::ActionType::BlockLoad });
559
560     // Domains should not be interepted as regular expressions.
561     auto domainRegexBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"we?bkit.org\"]}}]");
562     testRequest(domainRegexBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
563     testRequest(domainRegexBackend, mainDocumentRequest("http://wbkit.org/test.html"), { });
564     
565     auto multipleIfDomainsBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"webkit.org\", \"w3c.org\"]}}]");
566     testRequest(multipleIfDomainsBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
567     testRequest(multipleIfDomainsBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
568     testRequest(multipleIfDomainsBackend, mainDocumentRequest("http://w3c.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
569     testRequest(multipleIfDomainsBackend, mainDocumentRequest("http://whatwg.org/test.html"), { });
570
571     auto multipleUnlessDomainsBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"webkit.org\", \"w3c.org\"]}}]");
572     testRequest(multipleUnlessDomainsBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
573     testRequest(multipleUnlessDomainsBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
574     testRequest(multipleUnlessDomainsBackend, mainDocumentRequest("http://w3c.org/test.html"), { });
575     testRequest(multipleUnlessDomainsBackend, mainDocumentRequest("http://whatwg.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
576
577     // FIXME: Add and test domain-specific popup-only blocking (with layout tests).
578 }
579     
580 TEST_F(ContentExtensionTest, MultipleExtensions)
581 {
582     auto extension1 = InMemoryCompiledContentExtension::createFromFilter("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block_load\"}}]");
583     auto extension2 = InMemoryCompiledContentExtension::createFromFilter("[{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"block_cookies\"}}]");
584     ContentExtensions::ContentExtensionsBackend backend;
585     backend.addContentExtension("testFilter1", extension1);
586     backend.addContentExtension("testFilter2", extension2);
587     
588     // These each have two display:none stylesheets. The second one is implied by using the default parameter ignorePreviousRules = false.
589     testRequest(backend, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet });
590     testRequest(backend, mainDocumentRequest("http://webkit.org/block_load.html"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet, ContentExtensions::ActionType::BlockLoad});
591     testRequest(backend, mainDocumentRequest("http://webkit.org/block_cookies.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet});
592     testRequest(backend, mainDocumentRequest("http://webkit.org/block_load/block_cookies.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet, ContentExtensions::ActionType::BlockLoad });
593     testRequest(backend, mainDocumentRequest("http://webkit.org/block_cookies/block_load.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet, ContentExtensions::ActionType::BlockLoad });
594     
595     auto ignoreExtension1 = InMemoryCompiledContentExtension::createFromFilter("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block_load\"}},"
596         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"ignore1\"}}]");
597     auto ignoreExtension2 = InMemoryCompiledContentExtension::createFromFilter("[{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"block_cookies\"}},"
598         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"ignore2\"}}]");
599     ContentExtensions::ContentExtensionsBackend backendWithIgnore;
600     backendWithIgnore.addContentExtension("testFilter1", ignoreExtension1);
601     backendWithIgnore.addContentExtension("testFilter2", ignoreExtension2);
602     
603     testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet }, true);
604     testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_load/ignore1.html"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet }, true);
605     testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_cookies/ignore1.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet}, true);
606     testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_load/ignore2.html"), { ContentExtensions::ActionType::BlockLoad, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet }, true);
607     testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_cookies/ignore2.html"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet}, true);
608     testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_load/block_cookies/ignore1/ignore2.html"), { }, true);
609 }
610
611 TEST_F(ContentExtensionTest, TermsKnownToMatchAnything)
612 {
613     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre1.*post1$\"}},"
614         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre2(.*)post2$\"}},"
615         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre3(.*)?post3$\"}},"
616         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre4(.*)+post4$\"}},"
617         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre5(.*)*post5$\"}},"
618         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre6(.)*post6$\"}},"
619         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre7(.+)*post7$\"}},"
620         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre8(.?)*post8$\"}},"
621         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre9(.+)?post9$\"}},"
622         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre0(.?)+post0$\"}}]");
623
624     testRequest(backend, mainDocumentRequest("pre1://webkit.org/post1"), { ContentExtensions::ActionType::BlockLoad });
625     testRequest(backend, mainDocumentRequest("pre2://webkit.org/post2"), { ContentExtensions::ActionType::BlockLoad });
626     testRequest(backend, mainDocumentRequest("pre3://webkit.org/post3"), { ContentExtensions::ActionType::BlockLoad });
627     testRequest(backend, mainDocumentRequest("pre4://webkit.org/post4"), { ContentExtensions::ActionType::BlockLoad });
628     testRequest(backend, mainDocumentRequest("pre5://webkit.org/post5"), { ContentExtensions::ActionType::BlockLoad });
629     testRequest(backend, mainDocumentRequest("pre6://webkit.org/post6"), { ContentExtensions::ActionType::BlockLoad });
630     testRequest(backend, mainDocumentRequest("pre7://webkit.org/post7"), { ContentExtensions::ActionType::BlockLoad });
631     testRequest(backend, mainDocumentRequest("pre8://webkit.org/post8"), { ContentExtensions::ActionType::BlockLoad });
632     testRequest(backend, mainDocumentRequest("pre9://webkit.org/post9"), { ContentExtensions::ActionType::BlockLoad });
633     testRequest(backend, mainDocumentRequest("pre0://webkit.org/post0"), { ContentExtensions::ActionType::BlockLoad });
634
635     testRequest(backend, mainDocumentRequest("pre1://webkit.org/post2"), { });
636     testRequest(backend, mainDocumentRequest("pre2://webkit.org/post3"), { });
637     testRequest(backend, mainDocumentRequest("pre3://webkit.org/post4"), { });
638     testRequest(backend, mainDocumentRequest("pre4://webkit.org/post5"), { });
639     testRequest(backend, mainDocumentRequest("pre5://webkit.org/post6"), { });
640     testRequest(backend, mainDocumentRequest("pre6://webkit.org/post7"), { });
641     testRequest(backend, mainDocumentRequest("pre7://webkit.org/post8"), { });
642     testRequest(backend, mainDocumentRequest("pre8://webkit.org/post9"), { });
643     testRequest(backend, mainDocumentRequest("pre9://webkit.org/post0"), { });
644     testRequest(backend, mainDocumentRequest("pre0://webkit.org/post1"), { });
645
646     testRequest(backend, mainDocumentRequest("pre0://webkit.org/post1"), { });
647     testRequest(backend, mainDocumentRequest("pre1://webkit.org/post2"), { });
648     testRequest(backend, mainDocumentRequest("pre2://webkit.org/post3"), { });
649     testRequest(backend, mainDocumentRequest("pre3://webkit.org/post4"), { });
650     testRequest(backend, mainDocumentRequest("pre4://webkit.org/post5"), { });
651     testRequest(backend, mainDocumentRequest("pre5://webkit.org/post6"), { });
652     testRequest(backend, mainDocumentRequest("pre6://webkit.org/post7"), { });
653     testRequest(backend, mainDocumentRequest("pre7://webkit.org/post8"), { });
654     testRequest(backend, mainDocumentRequest("pre8://webkit.org/post9"), { });
655     testRequest(backend, mainDocumentRequest("pre9://webkit.org/post0"), { });
656 }
657
658 TEST_F(ContentExtensionTest, TrailingDotStar)
659 {
660     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"foo.*$\"}},"
661         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"bar(.*)$\"}}]");
662
663     testRequest(backend, mainDocumentRequest("https://webkit.org/"), { });
664
665     testRequest(backend, mainDocumentRequest("foo://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
666     testRequest(backend, mainDocumentRequest("https://foo.org/"), { ContentExtensions::ActionType::BlockLoad });
667     testRequest(backend, mainDocumentRequest("https://webkit.foo/"), { ContentExtensions::ActionType::BlockLoad });
668     testRequest(backend, mainDocumentRequest("https://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
669
670     testRequest(backend, mainDocumentRequest("bar://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
671     testRequest(backend, mainDocumentRequest("https://bar.org/"), { ContentExtensions::ActionType::BlockLoad });
672     testRequest(backend, mainDocumentRequest("https://webkit.bar/"), { ContentExtensions::ActionType::BlockLoad });
673     testRequest(backend, mainDocumentRequest("https://webkit.org/bar"), { ContentExtensions::ActionType::BlockLoad });
674 }
675
676 TEST_F(ContentExtensionTest, TrailingTermsCarryingNoData)
677 {
678     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"foob?a?r?\"}},"
679         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"bazo(ok)?a?$\"}},"
680         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"cats*$\"}}]");
681
682     testRequest(backend, mainDocumentRequest("https://webkit.org/"), { });
683
684     // Anything is fine after foo.
685     testRequest(backend, mainDocumentRequest("https://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
686     testRequest(backend, mainDocumentRequest("https://webkit.org/foob"), { ContentExtensions::ActionType::BlockLoad });
687     testRequest(backend, mainDocumentRequest("https://webkit.org/fooc"), { ContentExtensions::ActionType::BlockLoad });
688     testRequest(backend, mainDocumentRequest("https://webkit.org/fooba"), { ContentExtensions::ActionType::BlockLoad });
689     testRequest(backend, mainDocumentRequest("https://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
690     testRequest(backend, mainDocumentRequest("https://webkit.org/foobar-stuff"), { ContentExtensions::ActionType::BlockLoad });
691
692     // Bazooka has to be at the tail without any character not defined by the filter.
693     testRequest(backend, mainDocumentRequest("https://webkit.org/baz"), { });
694     testRequest(backend, mainDocumentRequest("https://webkit.org/bazo"), { ContentExtensions::ActionType::BlockLoad });
695     testRequest(backend, mainDocumentRequest("https://webkit.org/bazoa"), { ContentExtensions::ActionType::BlockLoad });
696     testRequest(backend, mainDocumentRequest("https://webkit.org/bazob"), { });
697     testRequest(backend, mainDocumentRequest("https://webkit.org/bazoo"), { });
698     testRequest(backend, mainDocumentRequest("https://webkit.org/bazook"), { ContentExtensions::ActionType::BlockLoad });
699     testRequest(backend, mainDocumentRequest("https://webkit.org/bazookb"), { });
700     testRequest(backend, mainDocumentRequest("https://webkit.org/bazooka"), { ContentExtensions::ActionType::BlockLoad });
701     testRequest(backend, mainDocumentRequest("https://webkit.org/bazookaa"), { });
702
703     // The pattern must finish with cat, with any number of 's' following it, but no other character.
704     testRequest(backend, mainDocumentRequest("https://cat.org/"), { });
705     testRequest(backend, mainDocumentRequest("https://cats.org/"), { });
706     testRequest(backend, mainDocumentRequest("https://webkit.org/cat"), { ContentExtensions::ActionType::BlockLoad });
707     testRequest(backend, mainDocumentRequest("https://webkit.org/cats"), { ContentExtensions::ActionType::BlockLoad });
708     testRequest(backend, mainDocumentRequest("https://webkit.org/catss"), { ContentExtensions::ActionType::BlockLoad });
709     testRequest(backend, mainDocumentRequest("https://webkit.org/catsss"), { ContentExtensions::ActionType::BlockLoad });
710     testRequest(backend, mainDocumentRequest("https://webkit.org/catso"), { });
711 }
712
713 TEST_F(ContentExtensionTest, LoadType)
714 {
715     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":[\"third-party\"]}},"
716         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"whatwg.org\",\"load-type\":[\"first-party\"]}},"
717         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"alwaysblock.pdf\"}}]");
718     
719     testRequest(backend, mainDocumentRequest("http://webkit.org"), { });
720     testRequest(backend, {URL(URL(), "http://webkit.org"), URL(URL(), "http://not_webkit.org"), ResourceType::Document}, { ContentExtensions::ActionType::BlockLoad });
721         
722     testRequest(backend, mainDocumentRequest("http://whatwg.org"), { ContentExtensions::ActionType::BlockLoad });
723     testRequest(backend, {URL(URL(), "http://whatwg.org"), URL(URL(), "http://not_whatwg.org"), ResourceType::Document}, { });
724     
725     testRequest(backend, mainDocumentRequest("http://foobar.org/alwaysblock.pdf"), { ContentExtensions::ActionType::BlockLoad });
726     testRequest(backend, {URL(URL(), "http://foobar.org/alwaysblock.pdf"), URL(URL(), "http://not_foobar.org/alwaysblock.pdf"), ResourceType::Document}, { ContentExtensions::ActionType::BlockLoad });
727 }
728
729 TEST_F(ContentExtensionTest, ResourceType)
730 {
731     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block_all_types.org\",\"resource-type\":[\"document\",\"image\",\"style-sheet\",\"script\",\"font\",\"raw\",\"svg-document\",\"media\",\"popup\"]}},"
732         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block_only_images\",\"resource-type\":[\"image\"]}}]");
733
734     testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Document), { ContentExtensions::ActionType::BlockLoad });
735     testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Image), { ContentExtensions::ActionType::BlockLoad });
736     testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::StyleSheet), { ContentExtensions::ActionType::BlockLoad });
737     testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Script), { ContentExtensions::ActionType::BlockLoad });
738     testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Font), { ContentExtensions::ActionType::BlockLoad });
739     testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Raw), { ContentExtensions::ActionType::BlockLoad });
740     testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::SVGDocument), { ContentExtensions::ActionType::BlockLoad });
741     testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Media), { ContentExtensions::ActionType::BlockLoad });
742     testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Popup), { ContentExtensions::ActionType::BlockLoad });
743     testRequest(backend, mainDocumentRequest("http://block_only_images.org", ResourceType::Image), { ContentExtensions::ActionType::BlockLoad });
744     testRequest(backend, mainDocumentRequest("http://block_only_images.org", ResourceType::Document), { });
745 }
746
747 TEST_F(ContentExtensionTest, ResourceAndLoadType)
748 {
749     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"BlockOnlyIfThirdPartyAndScript\",\"resource-type\":[\"script\"],\"load-type\":[\"third-party\"]}}]");
750     
751     testRequest(backend, subResourceRequest("http://webkit.org/BlockOnlyIfThirdPartyAndScript.js", "http://webkit.org", ResourceType::Script), { });
752     testRequest(backend, subResourceRequest("http://webkit.org/BlockOnlyIfThirdPartyAndScript.png", "http://not_webkit.org", ResourceType::Image), { });
753     testRequest(backend, subResourceRequest("http://webkit.org/BlockOnlyIfThirdPartyAndScript.js", "http://not_webkit.org", ResourceType::Script), { ContentExtensions::ActionType::BlockLoad });
754 }
755
756 TEST_F(ContentExtensionTest, ResourceOrLoadTypeMatchingEverything)
757 {
758     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"resource-type\":[\"image\"]}},"
759         "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\".*\",\"load-type\":[\"third-party\"]}},"
760         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\".*\",\"load-type\":[\"first-party\"]}}]");
761     
762     testRequest(backend, mainDocumentRequest("http://webkit.org"), { }, true);
763     testRequest(backend, {URL(URL(), "http://webkit.org"), URL(URL(), "http://not_webkit.org"), ResourceType::Document}, { ContentExtensions::ActionType::BlockCookies });
764     testRequest(backend, {URL(URL(), "http://webkit.org"), URL(URL(), "http://not_webkit.org"), ResourceType::Image}, { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad });
765 }
766     
767 TEST_F(ContentExtensionTest, WideNFA)
768 {
769     // Make an NFA with about 1400 nodes.
770     StringBuilder ruleList;
771     ruleList.append('[');
772     for (char c1 = 'A'; c1 <= 'Z'; ++c1) {
773         for (char c2 = 'A'; c2 <= 'C'; ++c2) {
774             for (char c3 = 'A'; c3 <= 'C'; ++c3) {
775                 if (c1 != 'A' || c2 != 'A' || c3 != 'A')
776                     ruleList.append(',');
777                 ruleList.append("{\"action\":{\"type\":\"");
778                 
779                 // Put an ignore-previous-rules near the middle.
780                 if (c1 == 'L' && c2 == 'A' && c3 == 'A')
781                     ruleList.append("ignore-previous-rules");
782                 else
783                     ruleList.append("block");
784                 
785                 ruleList.append("\"},\"trigger\":{\"url-filter\":\".*");
786                 ruleList.append(c1);
787                 ruleList.append(c2);
788                 ruleList.append(c3);
789                 ruleList.append("\", \"url-filter-is-case-sensitive\":true}}");
790             }
791         }
792     }
793     ruleList.append(']');
794     
795     auto backend = makeBackend(ruleList.toString().utf8().data());
796
797     testRequest(backend, mainDocumentRequest("http://webkit.org/AAA"), { ContentExtensions::ActionType::BlockLoad });
798     testRequest(backend, mainDocumentRequest("http://webkit.org/ZAA"), { ContentExtensions::ActionType::BlockLoad });
799     testRequest(backend, mainDocumentRequest("http://webkit.org/LAA/AAA"), { }, true);
800     testRequest(backend, mainDocumentRequest("http://webkit.org/LAA/MAA"), { ContentExtensions::ActionType::BlockLoad }, true);
801     testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
802 }
803
804 TEST_F(ContentExtensionTest, DeepNFA)
805 {
806     const unsigned size = 100000;
807     
808     ContentExtensions::CombinedURLFilters combinedURLFilters;
809     ContentExtensions::URLFilterParser parser(combinedURLFilters);
810     
811     // FIXME: DFAToNFA::convert takes way too long on these deep NFAs. We should optimize for that case.
812     
813     StringBuilder lotsOfAs;
814     for (unsigned i = 0; i < size; ++i)
815         lotsOfAs.append('A');
816     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern(lotsOfAs.toString().utf8().data(), false, 0));
817     
818     // FIXME: Yarr ought to be able to handle 2MB regular expressions.
819     StringBuilder tooManyAs;
820     for (unsigned i = 0; i < size * 20; ++i)
821         tooManyAs.append('A');
822     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::YarrError, parser.addPattern(tooManyAs.toString().utf8().data(), false, 0));
823     
824     StringBuilder nestedGroups;
825     for (unsigned i = 0; i < size; ++i)
826         nestedGroups.append('(');
827     for (unsigned i = 0; i < size; ++i)
828         nestedGroups.append("B)");
829     // FIXME: Add nestedGroups. Right now it also takes too long. It should be optimized.
830     
831     // This should not crash and not timeout.
832     EXPECT_EQ(1ul, createNFAs(combinedURLFilters).size());
833 }
834
835 void checkCompilerError(const char* json, std::error_code expectedError)
836 {
837     CompiledContentExtensionData extensionData;
838     InMemoryContentExtensionCompilationClient client(extensionData);
839     std::error_code compilerError = ContentExtensions::compileRuleList(client, json);
840     EXPECT_EQ(compilerError.value(), expectedError.value());
841     if (compilerError.value())
842         EXPECT_STREQ(compilerError.category().name(), expectedError.category().name());
843 }
844
845 TEST_F(ContentExtensionTest, MatchesEverything)
846 {
847     // Only css-display-none rules with triggers that match everything, no domain rules, and no flags
848     // should go in the global display:none stylesheet. css-display-none rules with domain rules or flags
849     // are applied separately on pages where they apply.
850     auto backend1 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]");
851     EXPECT_TRUE(nullptr != backend1.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
852     testRequest(backend1, mainDocumentRequest("http://webkit.org"), { }); // Selector is in global stylesheet.
853     
854     auto backend2 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\",\"if-domain\":[\"webkit.org\"]}}]");
855     EXPECT_EQ(nullptr, backend2.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
856     testRequest(backend2, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
857     testRequest(backend2, mainDocumentRequest("http://w3c.org"), { });
858     
859     auto backend3 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\",\"unless-domain\":[\"webkit.org\"]}}]");
860     EXPECT_EQ(nullptr, backend3.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
861     testRequest(backend3, mainDocumentRequest("http://webkit.org"), { });
862     testRequest(backend3, mainDocumentRequest("http://w3c.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
863     
864     auto backend4 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\",\"load-type\":[\"third-party\"]}}]");
865     EXPECT_EQ(nullptr, backend4.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
866     testRequest(backend4, mainDocumentRequest("http://webkit.org"), { });
867     testRequest(backend4, subResourceRequest("http://not_webkit.org", "http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
868
869     // css-display-none rules after ignore-previous-rules should not be put in the default stylesheet.
870     auto backend5 = makeBackend("[{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\".*\"}},"
871         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]");
872     EXPECT_EQ(nullptr, backend5.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
873     testRequest(backend5, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector }, true);
874 }
875     
876 TEST_F(ContentExtensionTest, InvalidJSON)
877 {
878     checkCompilerError("[", ContentExtensions::ContentExtensionError::JSONInvalid);
879     checkCompilerError("123", ContentExtensions::ContentExtensionError::JSONTopLevelStructureNotAnObject);
880     checkCompilerError("{}", ContentExtensions::ContentExtensionError::JSONTopLevelStructureNotAnArray);
881     // FIXME: Add unit test for JSONInvalidRule if that is possible to hit.
882     checkCompilerError("[]", ContentExtensions::ContentExtensionError::JSONContainsNoRules);
883
884     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":5}]",
885         ContentExtensions::ContentExtensionError::JSONInvalidTrigger);
886     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"\"}}]",
887         ContentExtensions::ContentExtensionError::JSONInvalidURLFilterInTrigger);
888     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":{}}}]",
889         ContentExtensions::ContentExtensionError::JSONInvalidURLFilterInTrigger);
890
891     // FIXME: Add unit test for JSONInvalidObjectInTriggerFlagsArray if that is possible to hit.
892     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":{}}}]",
893         ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
894     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":[\"invalid\"]}}]",
895         ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
896     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":[5]}}]",
897         ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
898     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":5}}]",
899         ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
900     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":\"first-party\"}}]",
901         ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
902     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":null}}]",
903         ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
904     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":false}}]",
905         ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
906     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":{}}}]",
907         ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
908     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":[\"invalid\"]}}]",
909         ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
910     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":[5]}}]",
911         ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
912     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":5}}]",
913         ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
914     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":\"document\"}}]",
915         ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
916     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":null}}]",
917         ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
918     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":false}}]",
919         ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
920     
921     StringBuilder rules;
922     rules.append("[");
923     for (unsigned i = 0; i < 49999; ++i)
924         rules.append("{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"a\"}},");
925     String rules50000 = rules.toString();
926     String rules50001 = rules.toString();
927     rules50000.append("{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"a\"}}]");
928     rules50001.append("{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"a\"}},{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"a\"}}]");
929     checkCompilerError(rules50000.utf8().data(), { });
930     checkCompilerError(rules50001.utf8().data(), ContentExtensions::ContentExtensionError::JSONTooManyRules);
931     
932     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":{}}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
933     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[5]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
934     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[\"a\"]}}]", { });
935     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":\"a\"}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
936     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":false}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
937     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":null}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
938     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":{}}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
939     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[5]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
940     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"\"]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
941     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":\"a\"}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
942     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":null}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
943     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":false}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
944     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"A\"]}}]", ContentExtensions::ContentExtensionError::JSONDomainNotLowerCaseASCII);
945     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"\\u00DC\"]}}]", ContentExtensions::ContentExtensionError::JSONDomainNotLowerCaseASCII);
946     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"0\"]}}]", { });
947     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"a\"]}}]", { });
948
949     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[],\"unless-domain\":[\"a\"]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
950     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
951     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":5}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
952     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":5}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
953     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":5,\"unless-domain\":5}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
954     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
955     
956     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[\"a\"],\"unless-domain\":[]}}]", ContentExtensions::ContentExtensionError::JSONUnlessAndIfDomain);
957     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[\"a\"],\"unless-domain\":[\"a\"]}}]", ContentExtensions::ContentExtensionError::JSONUnlessAndIfDomain);
958
959     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\", \"unexpected-identifier-should-be-ignored\":5}}]", { });
960
961     checkCompilerError("[{\"action\":5,\"trigger\":{\"url-filter\":\"webkit.org\"}}]",
962         ContentExtensions::ContentExtensionError::JSONInvalidAction);
963     checkCompilerError("[{\"action\":{\"type\":\"invalid\"},\"trigger\":{\"url-filter\":\"webkit.org\"}}]",
964         ContentExtensions::ContentExtensionError::JSONInvalidActionType);
965     checkCompilerError("[{\"action\":{\"type\":\"css-display-none\"},\"trigger\":{\"url-filter\":\"webkit.org\"}}]",
966         ContentExtensions::ContentExtensionError::JSONInvalidCSSDisplayNoneActionType);
967
968     checkCompilerError("[{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"webkit.org\"}},"
969         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]", { });
970     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"if-domain\":[\"a\"]}}]", { });
971     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"unless-domain\":[\"a\"]}}]", { });
972     checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[\"}}]",
973         ContentExtensions::ContentExtensionError::JSONInvalidRegex);
974 }
975
976 TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines1)
977 {
978     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^.*foo\"}},"
979         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"bar$\"}},"
980         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[ab]+bang\"}}]");
981
982     testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
983     testRequest(backend, mainDocumentRequest("foo://webkit.org/bar"), { ContentExtensions::ActionType::BlockLoad });
984     testRequest(backend, mainDocumentRequest("http://webkit.org/bar"), { ContentExtensions::ActionType::BlockLoad });
985     testRequest(backend, mainDocumentRequest("bar://webkit.org/bar"), { ContentExtensions::ActionType::BlockLoad });
986
987     testRequest(backend, mainDocumentRequest("abang://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
988     testRequest(backend, mainDocumentRequest("bbang://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
989     testRequest(backend, mainDocumentRequest("cbang://webkit.org/"), { });
990     testRequest(backend, mainDocumentRequest("http://webkit.org/bang"), { });
991     testRequest(backend, mainDocumentRequest("bang://webkit.org/"), { });
992 }
993
994 TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines1Partitioning)
995 {
996     ContentExtensions::CombinedURLFilters combinedURLFilters;
997     ContentExtensions::URLFilterParser parser(combinedURLFilters);
998
999     // Those two share a prefix.
1000     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^.*foo", false, 0));
1001     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("bar$", false, 1));
1002
1003     // Not this one.
1004     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^[ab]+bang", false, 0));
1005
1006     EXPECT_EQ(2ul, createNFAs(combinedURLFilters).size());
1007 }
1008
1009 TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines2)
1010 {
1011     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^foo\"}},"
1012         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^.*[a-c]+bar\"}},"
1013         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^webkit:\"}},"
1014         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-c]+b+oom\"}}]");
1015
1016     testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
1017     testRequest(backend, mainDocumentRequest("foo://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1018     testRequest(backend, mainDocumentRequest("webkit://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1019
1020     testRequest(backend, mainDocumentRequest("http://bar.org/"), { });
1021     testRequest(backend, mainDocumentRequest("http://abar.org/"), { ContentExtensions::ActionType::BlockLoad });
1022     testRequest(backend, mainDocumentRequest("http://bbar.org/"), { ContentExtensions::ActionType::BlockLoad });
1023     testRequest(backend, mainDocumentRequest("http://cbar.org/"), { ContentExtensions::ActionType::BlockLoad });
1024     testRequest(backend, mainDocumentRequest("http://abcbar.org/"), { ContentExtensions::ActionType::BlockLoad });
1025     testRequest(backend, mainDocumentRequest("http://dbar.org/"), { });
1026 }
1027
1028 TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines2Partitioning)
1029 {
1030     ContentExtensions::CombinedURLFilters combinedURLFilters;
1031     ContentExtensions::URLFilterParser parser(combinedURLFilters);
1032
1033     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^foo", false, 0));
1034     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^.*[a-c]+bar", false, 1));
1035     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^webkit:", false, 2));
1036     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("[a-c]+b+oom", false, 3));
1037
1038     // "^foo" and "^webkit:" can be grouped, the other two have a variable prefix.
1039     EXPECT_EQ(3ul, createNFAs(combinedURLFilters).size());
1040 }
1041
1042 TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines3)
1043 {
1044     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"A*D\"}},"
1045         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"A*BA+\"}},"
1046         "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"A*BC\"}}]");
1047     
1048     testRequest(backend, mainDocumentRequest("http://webkit.org/D"), { ContentExtensions::ActionType::BlockLoad });
1049     testRequest(backend, mainDocumentRequest("http://webkit.org/AAD"), { ContentExtensions::ActionType::BlockLoad });
1050     testRequest(backend, mainDocumentRequest("http://webkit.org/AB"), { });
1051     testRequest(backend, mainDocumentRequest("http://webkit.org/ABA"), { }, true);
1052     testRequest(backend, mainDocumentRequest("http://webkit.org/ABAD"), { }, true);
1053     testRequest(backend, mainDocumentRequest("http://webkit.org/BC"), { ContentExtensions::ActionType::BlockCookies });
1054     testRequest(backend, mainDocumentRequest("http://webkit.org/ABC"), { ContentExtensions::ActionType::BlockCookies });
1055     testRequest(backend, mainDocumentRequest("http://webkit.org/ABABC"), { ContentExtensions::ActionType::BlockCookies }, true);
1056     testRequest(backend, mainDocumentRequest("http://webkit.org/ABABCAD"), { ContentExtensions::ActionType::BlockCookies }, true);
1057     testRequest(backend, mainDocumentRequest("http://webkit.org/ABCAD"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad });
1058 }
1059     
1060 TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines3Partitioning)
1061 {
1062     ContentExtensions::CombinedURLFilters combinedURLFilters;
1063     ContentExtensions::URLFilterParser parser(combinedURLFilters);
1064     
1065     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A*D", false, 0));
1066     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A*BA+", false, 1));
1067     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A*BC", false, 2));
1068     
1069     // "A*A" and "A*BC" can be grouped, "A*BA+" should not.
1070     EXPECT_EQ(2ul, createNFAs(combinedURLFilters).size());
1071 }
1072
1073 TEST_F(ContentExtensionTest, SplittingLargeNFAs)
1074 {
1075     const size_t expectedNFACounts[16] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1};
1076     
1077     for (size_t i = 0; i < 16; i++) {
1078         ContentExtensions::CombinedURLFilters combinedURLFilters;
1079         ContentExtensions::URLFilterParser parser(combinedURLFilters);
1080         
1081         EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A+BBB", false, 1));
1082         EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A+CCC", false, 2));
1083         EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A+DDD", false, 2));
1084         
1085         Vector<ContentExtensions::NFA> nfas;
1086         combinedURLFilters.processNFAs(i, [&](ContentExtensions::NFA&& nfa) {
1087             nfas.append(WTF::move(nfa));
1088         });
1089         EXPECT_EQ(nfas.size(), expectedNFACounts[i]);
1090         
1091         Vector<ContentExtensions::DFA> dfas;
1092         for (auto& nfa : nfas)
1093             dfas.append(ContentExtensions::NFAToDFA::convert(nfa));
1094         
1095         Vector<ContentExtensions::DFABytecode> combinedBytecode;
1096         for (const auto& dfa : dfas) {
1097             Vector<ContentExtensions::DFABytecode> bytecode;
1098             ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
1099             compiler.compile();
1100             combinedBytecode.appendVector(bytecode);
1101         }
1102         
1103         ContentExtensions::DFABytecodeInterpreter interpreter(&combinedBytecode[0], combinedBytecode.size());
1104         
1105         EXPECT_EQ(interpreter.interpret("ABBBX", 0).size(), 1ull);
1106         EXPECT_EQ(interpreter.interpret("ACCCX", 0).size(), 1ull);
1107         EXPECT_EQ(interpreter.interpret("ADDDX", 0).size(), 1ull);
1108         EXPECT_EQ(interpreter.interpret("XBBBX", 0).size(), 0ull);
1109         EXPECT_EQ(interpreter.interpret("ABBX", 0).size(), 0ull);
1110         EXPECT_EQ(interpreter.interpret("ACCX", 0).size(), 0ull);
1111         EXPECT_EQ(interpreter.interpret("ADDX", 0).size(), 0ull);
1112     }
1113 }
1114     
1115 TEST_F(ContentExtensionTest, QuantifierInGroup)
1116 {
1117     ContentExtensions::CombinedURLFilters combinedURLFilters;
1118     ContentExtensions::URLFilterParser parser(combinedURLFilters);
1119     
1120     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A+)B)C)", false, 0));
1121     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B+)C)", false, 1));
1122     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B+)C)D", false, 2));
1123     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B)C+)", false, 3));
1124     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B)C)", false, 4));
1125     
1126     // (((A)B+)C) and (((A)B+)C)D should be in the same NFA.
1127     EXPECT_EQ(4ul, createNFAs(combinedURLFilters).size());
1128 }
1129
1130 static void testPatternStatus(String pattern, ContentExtensions::URLFilterParser::ParseStatus status)
1131 {
1132     ContentExtensions::CombinedURLFilters combinedURLFilters;
1133     ContentExtensions::URLFilterParser parser(combinedURLFilters);
1134     EXPECT_EQ(status, parser.addPattern(pattern, false, 0));
1135 }
1136     
1137 TEST_F(ContentExtensionTest, ParsingFailures)
1138 {
1139     testPatternStatus("a*b?.*.?[a-z]?[a-z]*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1140     testPatternStatus("a*b?.*.?[a-z]?[a-z]+", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1141     testPatternStatus("a*b?.*.?[a-z]?[a-z]", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1142     testPatternStatus(".*?a", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1143     testPatternStatus(".*a", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1144     
1145     testPatternStatus("(?!)", ContentExtensions::URLFilterParser::ParseStatus::Group);
1146     testPatternStatus("(?=)", ContentExtensions::URLFilterParser::ParseStatus::Group);
1147     testPatternStatus("(?!a)", ContentExtensions::URLFilterParser::ParseStatus::Group);
1148     testPatternStatus("(?=a)", ContentExtensions::URLFilterParser::ParseStatus::Group);
1149     testPatternStatus("(regex)", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1150     testPatternStatus("(regex", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1151     testPatternStatus("((regex)", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1152     testPatternStatus("(?:regex)", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1153     testPatternStatus("(?:regex", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1154     testPatternStatus("[^.]+", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1155     
1156     testPatternStatus("a++", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1157     testPatternStatus("[a]++", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1158     testPatternStatus("+", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1159     
1160     testPatternStatus("[", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1161     testPatternStatus("[a}", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1162     
1163     // FIXME: Look into why these do not cause YARR parsing errors.  They probably should.
1164     testPatternStatus("a]", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1165     testPatternStatus("{", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1166     testPatternStatus("{[a]", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1167     testPatternStatus("{0", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1168     testPatternStatus("{0,", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1169     testPatternStatus("{0,1", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1170     testPatternStatus("a{0,1", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1171     testPatternStatus("a{a,b}", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1172
1173     const char nonASCII[2] = {-1, '\0'};
1174     testPatternStatus(nonASCII, ContentExtensions::URLFilterParser::ParseStatus::NonASCII);
1175     testPatternStatus("\\xff", ContentExtensions::URLFilterParser::ParseStatus::NonASCII);
1176     
1177     testPatternStatus("\\x\\r\\n", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1178     testPatternStatus("\\b", ContentExtensions::URLFilterParser::ParseStatus::WordBoundary);
1179     testPatternStatus("[\\d]", ContentExtensions::URLFilterParser::ParseStatus::AtomCharacter);
1180     testPatternStatus("\\d\\D\\w\\s\\v\\h\\i\\c", ContentExtensions::URLFilterParser::ParseStatus::UnsupportedCharacterClass);
1181     
1182     testPatternStatus("this|that", ContentExtensions::URLFilterParser::ParseStatus::Disjunction);
1183     testPatternStatus("a{0,1}b", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1184     testPatternStatus("a{0,2}b", ContentExtensions::URLFilterParser::ParseStatus::InvalidQuantifier);
1185     testPatternStatus("", ContentExtensions::URLFilterParser::ParseStatus::EmptyPattern);
1186     testPatternStatus("$$", ContentExtensions::URLFilterParser::ParseStatus::MisplacedEndOfLine);
1187     testPatternStatus("a^", ContentExtensions::URLFilterParser::ParseStatus::MisplacedStartOfLine);
1188     testPatternStatus("(^)", ContentExtensions::URLFilterParser::ParseStatus::MisplacedStartOfLine);
1189     
1190     testPatternStatus("(a)\\1", ContentExtensions::URLFilterParser::ParseStatus::Ok); // This should be BackReference, right?
1191 }
1192
1193 TEST_F(ContentExtensionTest, PatternMatchingTheEmptyString)
1194 {
1195     // Simple atoms.
1196     testPatternStatus(".*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1197     testPatternStatus("a*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1198     testPatternStatus(".?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1199     testPatternStatus("a?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1200
1201     // Character sets.
1202     testPatternStatus("[a-z]*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1203     testPatternStatus("[a-z]?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1204
1205     // Groups.
1206     testPatternStatus("(foobar)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1207     testPatternStatus("(foobar)?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1208     testPatternStatus("(.*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1209     testPatternStatus("(a*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1210     testPatternStatus("(.?)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1211     testPatternStatus("(a?)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1212     testPatternStatus("([a-z]*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1213     testPatternStatus("([a-z]?)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1214
1215     testPatternStatus("(.)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1216     testPatternStatus("(.+)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1217     testPatternStatus("(.?)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1218     testPatternStatus("(.*)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1219     testPatternStatus("(.+)?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1220     testPatternStatus("(.?)+", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1221
1222     // Nested groups.
1223     testPatternStatus("((foo)?((.)*)(bar)*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1224 }
1225
1226 TEST_F(ContentExtensionTest, MinimizingWithMoreFinalStatesThanNonFinalStates)
1227 {
1228     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^h[a-z://]+\"}},"
1229         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://foo.com/\"}},"
1230         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://bar.com/\"}}]");
1231
1232     testRequest(backend, mainDocumentRequest("http://foo.com/"), { ContentExtensions::ActionType::BlockLoad });
1233     testRequest(backend, mainDocumentRequest("http://bar.com/"), { ContentExtensions::ActionType::BlockLoad });
1234     testRequest(backend, mainDocumentRequest("attp://foo.com/"), { });
1235     testRequest(backend, mainDocumentRequest("attp://bar.com/"), { });
1236
1237     testRequest(backend, mainDocumentRequest("http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1238     testRequest(backend, mainDocumentRequest("https://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1239     testRequest(backend, mainDocumentRequest("bttp://webkit.org/"), { });
1240     testRequest(backend, mainDocumentRequest("bttps://webkit.org/"), { });
1241     testRequest(backend, mainDocumentRequest("http://webkit.org/b"), { ContentExtensions::ActionType::BlockLoad });
1242     testRequest(backend, mainDocumentRequest("https://webkit.org/b"), { ContentExtensions::ActionType::BlockLoad });
1243     testRequest(backend, mainDocumentRequest("cttp://webkit.org/B"), { });
1244     testRequest(backend, mainDocumentRequest("cttps://webkit.org/B"), { });
1245 }
1246
1247 TEST_F(ContentExtensionTest, StatesWithDifferentActionsAreNotUnified1)
1248 {
1249     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://www.webkit.org/\"}},"
1250         "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"^https://www.webkit.org/\"}},"
1251         "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"^attps://www.webkit.org/\"}}]");
1252
1253     testRequest(backend, mainDocumentRequest("http://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1254     testRequest(backend, mainDocumentRequest("https://www.webkit.org/"), { ContentExtensions::ActionType::BlockCookies });
1255     testRequest(backend, mainDocumentRequest("attps://www.webkit.org/"), { ContentExtensions::ActionType::BlockCookies });
1256     testRequest(backend, mainDocumentRequest("http://www.webkit.org/a"), { ContentExtensions::ActionType::BlockLoad });
1257     testRequest(backend, mainDocumentRequest("https://www.webkit.org/B"), { ContentExtensions::ActionType::BlockCookies });
1258     testRequest(backend, mainDocumentRequest("attps://www.webkit.org/c"), { ContentExtensions::ActionType::BlockCookies });
1259     testRequest(backend, mainDocumentRequest("http://www.whatwg.org/"), { });
1260     testRequest(backend, mainDocumentRequest("https://www.whatwg.org/"), { });
1261     testRequest(backend, mainDocumentRequest("attps://www.whatwg.org/"), { });
1262 }
1263
1264 TEST_F(ContentExtensionTest, StatesWithDifferentActionsAreNotUnified2)
1265 {
1266     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://www.webkit.org/\"}},"
1267         "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"^https://www.webkit.org/\"}},"
1268         "{\"action\":{\"type\":\"css-display-none\", \"selector\":\"#foo\"},\"trigger\":{\"url-filter\":\"^https://www.webkit.org/\"}}]");
1269
1270     testRequest(backend, mainDocumentRequest("http://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1271     testRequest(backend, mainDocumentRequest("https://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockCookies });
1272     testRequest(backend, mainDocumentRequest("https://www.whatwg.org/"), { });
1273     testRequest(backend, mainDocumentRequest("attps://www.whatwg.org/"), { });
1274 }
1275
1276 // The order in which transitions from the root will be processed is unpredictable.
1277 // To exercises the various options, this test exists in various version exchanging the transition to the final state.
1278 TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge1)
1279 {
1280     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.a\"}},"
1281         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.a\"}},"
1282         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bac\"}},"
1283         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bbc\"}},"
1284         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCC\"}}]");
1285
1286     testRequest(backend, mainDocumentRequest("aza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1287     testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1288     testRequest(backend, mainDocumentRequest("bac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1289     testRequest(backend, mainDocumentRequest("bbc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1290     testRequest(backend, mainDocumentRequest("bcc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1291
1292     testRequest(backend, mainDocumentRequest("aac://www.webkit.org/"), { });
1293     testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { });
1294     testRequest(backend, mainDocumentRequest("acc://www.webkit.org/"), { });
1295
1296     testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1297     testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1298     testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1299 }
1300 TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge2)
1301 {
1302     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bac\"}},"
1303         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bbc\"}},"
1304         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCC\"}},"
1305         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.a\"}},"
1306         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.a\"}}]");
1307
1308     testRequest(backend, mainDocumentRequest("aza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1309     testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1310     testRequest(backend, mainDocumentRequest("bac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1311     testRequest(backend, mainDocumentRequest("bbc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1312     testRequest(backend, mainDocumentRequest("bcc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1313
1314     testRequest(backend, mainDocumentRequest("aac://www.webkit.org/"), { });
1315     testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { });
1316     testRequest(backend, mainDocumentRequest("acc://www.webkit.org/"), { });
1317
1318     testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1319     testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1320     testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1321 }
1322 TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge3)
1323 {
1324     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.c\"}},"
1325         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.c\"}},"
1326         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^baa\"}},"
1327         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bba\"}},"
1328         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCA\"}}]");
1329
1330     testRequest(backend, mainDocumentRequest("azc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1331     testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1332     testRequest(backend, mainDocumentRequest("baa://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1333     testRequest(backend, mainDocumentRequest("bba://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1334     testRequest(backend, mainDocumentRequest("bca://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1335
1336     testRequest(backend, mainDocumentRequest("aaa://www.webkit.org/"), { });
1337     testRequest(backend, mainDocumentRequest("aba://www.webkit.org/"), { });
1338     testRequest(backend, mainDocumentRequest("aca://www.webkit.org/"), { });
1339
1340     testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1341     testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1342     testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1343 }
1344 TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge4)
1345 {
1346     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^baa\"}},"
1347         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bba\"}},"
1348         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCA\"}},"
1349         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.c\"}},"
1350         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.c\"}}]");
1351
1352     testRequest(backend, mainDocumentRequest("azc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1353     testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1354     testRequest(backend, mainDocumentRequest("baa://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1355     testRequest(backend, mainDocumentRequest("bba://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1356     testRequest(backend, mainDocumentRequest("bca://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1357
1358     testRequest(backend, mainDocumentRequest("aaa://www.webkit.org/"), { });
1359     testRequest(backend, mainDocumentRequest("aba://www.webkit.org/"), { });
1360     testRequest(backend, mainDocumentRequest("aca://www.webkit.org/"), { });
1361
1362     testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1363     testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1364     testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1365 }
1366
1367 TEST_F(ContentExtensionTest, FallbackTransitionsToOtherNodeInSameGroupDoesNotDifferentiateGroup)
1368 {
1369     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^aac\"}},"
1370         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.c\"}},"
1371         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.c\"}}]");
1372
1373     testRequest(backend, mainDocumentRequest("aac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1374     testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1375     testRequest(backend, mainDocumentRequest("bac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1376     testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1377
1378     testRequest(backend, mainDocumentRequest("aaa://www.webkit.org/"), { });
1379     testRequest(backend, mainDocumentRequest("aca://www.webkit.org/"), { });
1380     testRequest(backend, mainDocumentRequest("baa://www.webkit.org/"), { });
1381 }
1382
1383 TEST_F(ContentExtensionTest, SimpleFallBackTransitionDifferentiator1)
1384 {
1385     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.bc.de\"}},"
1386         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.bd.ef\"}}]");
1387
1388     testRequest(backend, mainDocumentRequest("abbccde://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1389     testRequest(backend, mainDocumentRequest("aabcdde://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1390     testRequest(backend, mainDocumentRequest("aabddef://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1391     testRequest(backend, mainDocumentRequest("aabddef://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1392
1393     testRequest(backend, mainDocumentRequest("abcde://www.webkit.org/"), { });
1394     testRequest(backend, mainDocumentRequest("abdef://www.webkit.org/"), { });
1395 }
1396
1397 TEST_F(ContentExtensionTest, SimpleFallBackTransitionDifferentiator2)
1398 {
1399     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^cb.\"}},"
1400         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^db.b\"}}]");
1401
1402     testRequest(backend, mainDocumentRequest("cba://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1403     testRequest(backend, mainDocumentRequest("cbb://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1404     testRequest(backend, mainDocumentRequest("dbab://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1405     testRequest(backend, mainDocumentRequest("dbxb://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1406
1407     testRequest(backend, mainDocumentRequest("cca://www.webkit.org/"), { });
1408     testRequest(backend, mainDocumentRequest("dddd://www.webkit.org/"), { });
1409     testRequest(backend, mainDocumentRequest("bbbb://www.webkit.org/"), { });
1410 }
1411
1412 // *** We have the following ranges intersections: ***
1413 // Full overlap.
1414 // 1)
1415 // A: |-----|
1416 // B:  |---|
1417 // 2)
1418 // A: |-----|
1419 // B:    |
1420 // 3)
1421 // A:  |---|
1422 // B: |-----|
1423 // 4)
1424 // A:    |
1425 // B: |-----|
1426 // One edge in common
1427 // 5)
1428 // A: |-|
1429 // B:   |-|
1430 // 6)
1431 // A: |
1432 // B: |-|
1433 // 7)
1434 // A: |-|
1435 // B:   |
1436 // 8)
1437 // A:   |-|
1438 // B: |-|
1439 // 9)
1440 // A:   |
1441 // B: |-|
1442 // 10)
1443 // A: |-|
1444 // B: |
1445 // B overlap on the left side of A.
1446 // 11)
1447 // A:   |---|
1448 // B: |---|
1449 // 12)
1450 // A:   |---|
1451 // B: |-----|
1452 // A overlap on the left side of B
1453 // 13)
1454 // A: |---|
1455 // B:   |---|
1456 // 14)
1457 // A: |-----|
1458 // B:   |---|
1459 // Equal ranges
1460 // 15)
1461 // A: |---|
1462 // B: |---|
1463 // 16)
1464 // A: |
1465 // B: |
1466
1467 TEST_F(ContentExtensionTest, RangeOverlapCase1)
1468 {
1469     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[a-m]\"}},"
1470         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"^[c-e]\"}}]");
1471
1472     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1473     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1474     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { }, true);
1475     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { }, true);
1476     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { }, true);
1477     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1478     testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1479     testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
1480
1481     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-m]\"}},"
1482         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"[c-e]\"}}]");
1483     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1484     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1485     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { }, true);
1486     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { }, true);
1487     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { }, true);
1488     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1489     testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1490     testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
1491 }
1492
1493 TEST_F(ContentExtensionTest, RangeOverlapCase2)
1494 {
1495     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[a-m]\"}},"
1496         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"^b\"}}]");
1497
1498     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1499     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { }, true);
1500     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1501     testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1502     testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
1503
1504     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-m]\"}},"
1505         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"l\"}}]");
1506     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1507     testRequest(searchBackend, mainDocumentRequest("zzz://www.k.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1508     testRequest(searchBackend, mainDocumentRequest("zzz://www.l.xxx/"), { }, true);
1509     testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1510     testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
1511 }
1512
1513 TEST_F(ContentExtensionTest, RangeOverlapCase3)
1514 {
1515     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[b-d]\"}},"
1516         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[a-m]\"}}]");
1517
1518     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1519     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1520     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1521     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1522     testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1523     testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
1524
1525     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[b-d]\"}},"
1526         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[a-m]\"}}]");
1527     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1528     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1529     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1530     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1531     testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1532     testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
1533 }
1534
1535 TEST_F(ContentExtensionTest, RangeOverlapCase4)
1536 {
1537     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^l\"}},"
1538         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[a-m]\"}}]");
1539
1540     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1541     testRequest(matchBackend, mainDocumentRequest("k://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1542     testRequest(matchBackend, mainDocumentRequest("l://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1543     testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1544     testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
1545
1546     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"l\"}},"
1547         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[a-m]\"}}]");
1548     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1549     testRequest(searchBackend, mainDocumentRequest("zzz://www.k.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1550     testRequest(searchBackend, mainDocumentRequest("zzz://www.l.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1551     testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1552     testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
1553 }
1554
1555 TEST_F(ContentExtensionTest, RangeOverlapCase5)
1556 {
1557     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[a-e]\"}},"
1558         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[e-h]\"}}]");
1559
1560     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1561     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1562     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1563     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1564     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1565     testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
1566
1567     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-e]\"}},"
1568         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[e-h]\"}}]");
1569     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1570     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1571     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1572     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1573     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1574     testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
1575 }
1576
1577 TEST_F(ContentExtensionTest, RangeOverlapCase6)
1578 {
1579     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^e\"}},"
1580         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[e-h]\"}}]");
1581
1582     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
1583     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
1584     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1585     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1586     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1587     testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
1588
1589     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"e\"}},"
1590         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[e-h]\"}}]");
1591     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
1592     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
1593     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1594     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1595     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1596     testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
1597 }
1598
1599 TEST_F(ContentExtensionTest, RangeOverlapCase7)
1600 {
1601     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[a-e]\"}},"
1602         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^e\"}}]");
1603
1604     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1605     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1606     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1607     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { });
1608
1609     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-e]\"}},"
1610         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"e\"}}]");
1611     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1612     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1613     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1614     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { });
1615 }
1616
1617 TEST_F(ContentExtensionTest, RangeOverlapCase8)
1618 {
1619     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[e-h]\"}},"
1620         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[a-e]\"}}]");
1621
1622     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1623     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1624     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1625     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1626     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1627     testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
1628
1629     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[e-h]\"}},"
1630         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[a-e]\"}}]");
1631     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1632     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1633     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1634     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1635     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1636     testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
1637 }
1638
1639 TEST_F(ContentExtensionTest, RangeOverlapCase9)
1640 {
1641     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^e\"}},"
1642         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[a-e]\"}}]");
1643
1644     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1645     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1646     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1647     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { });
1648
1649     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"e\"}},"
1650         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[a-e]\"}}]");
1651     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1652     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1653     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1654     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { });
1655 }
1656
1657 TEST_F(ContentExtensionTest, RangeOverlapCase10)
1658 {
1659     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[e-h]\"}},"
1660         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^e\"}}]");
1661
1662     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
1663     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
1664     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1665     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1666     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1667     testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
1668
1669     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[e-h]\"}},"
1670         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"e\"}}]");
1671     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
1672     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
1673     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1674     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1675     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1676     testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
1677 }
1678
1679 TEST_F(ContentExtensionTest, RangeOverlapCase11)
1680 {
1681     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[e-g]\"}},"
1682         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[d-f]\"}}]");
1683
1684     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { });
1685     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1686     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1687     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1688     testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1689     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
1690
1691     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[e-g]\"}},"
1692         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[d-f]\"}}]");
1693     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { });
1694     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1695     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1696     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1697     testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1698     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
1699 }
1700
1701
1702 TEST_F(ContentExtensionTest, RangeOverlapCase12)
1703 {
1704     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[e-g]\"}},"
1705         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[d-g]\"}}]");
1706
1707     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { });
1708     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1709     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1710     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1711     testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1712     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
1713
1714     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[e-g]\"}},"
1715         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[d-g]\"}}]");
1716     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { });
1717     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1718     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1719     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1720     testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1721     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
1722 }
1723
1724 TEST_F(ContentExtensionTest, RangeOverlapCase13)
1725 {
1726     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[b-d]\"}},"
1727         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[c-e]\"}}]");
1728
1729     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
1730     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1731     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1732     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1733     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1734     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
1735
1736     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[b-d]\"}},"
1737         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[c-e]\"}}]");
1738     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
1739     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1740     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1741     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1742     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1743     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
1744 }
1745
1746 TEST_F(ContentExtensionTest, RangeOverlapCase14)
1747 {
1748     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[b-e]\"}},"
1749         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[c-e]\"}}]");
1750
1751     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
1752     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1753     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1754     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1755     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1756     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
1757
1758     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[b-e]\"}},"
1759         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[c-e]\"}}]");
1760     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
1761     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1762     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1763     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1764     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1765     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
1766 }
1767
1768 TEST_F(ContentExtensionTest, RangeOverlapCase15)
1769 {
1770     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[c-f]\"}},"
1771         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[c-f]\"}}]");
1772
1773     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
1774     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { });
1775     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1776     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1777     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1778     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1779     testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { });
1780
1781     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[c-f]\"}},"
1782         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[c-f]\"}}]");
1783     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
1784     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { });
1785     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1786     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1787     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1788     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1789     testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { });
1790 }
1791
1792 TEST_F(ContentExtensionTest, RangeOverlapCase16)
1793 {
1794     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^c\"}},"
1795         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^c\"}}]");
1796
1797     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
1798     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { });
1799     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1800     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
1801     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { });
1802
1803     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"c\"}},"
1804         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"c\"}}]");
1805     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
1806     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { });
1807     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1808     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
1809     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { });
1810 }
1811
1812 TEST_F(ContentExtensionTest, QuantifiedOneOrMoreRangesCase11And13)
1813 {
1814     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[c-e]+[g-i]+YYY\"}},"
1815         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[b-d]+[h-j]+YYY\"}}]");
1816
1817     // The interesting ranges only match between 'b' and 'k', plus a gap in 'f'.
1818     testRequest(searchBackend, mainDocumentRequest("zzz://www.aayyy.xxx/"), { });
1819     testRequest(searchBackend, mainDocumentRequest("zzz://www.abyyy.xxx/"), { });
1820     testRequest(searchBackend, mainDocumentRequest("zzz://www.acyyy.xxx/"), { });
1821     testRequest(searchBackend, mainDocumentRequest("zzz://www.adyyy.xxx/"), { });
1822     testRequest(searchBackend, mainDocumentRequest("zzz://www.aeyyy.xxx/"), { });
1823     testRequest(searchBackend, mainDocumentRequest("zzz://www.afyyy.xxx/"), { });
1824     testRequest(searchBackend, mainDocumentRequest("zzz://www.agyyy.xxx/"), { });
1825     testRequest(searchBackend, mainDocumentRequest("zzz://www.ahyyy.xxx/"), { });
1826     testRequest(searchBackend, mainDocumentRequest("zzz://www.aiyyy.xxx/"), { });
1827     testRequest(searchBackend, mainDocumentRequest("zzz://www.ajyyy.xxx/"), { });
1828     testRequest(searchBackend, mainDocumentRequest("zzz://www.akyyy.xxx/"), { });
1829
1830     // 'b' is the first character of the second rule.
1831     testRequest(searchBackend, mainDocumentRequest("zzz://www.byyy.xxx/"), { });
1832     testRequest(searchBackend, mainDocumentRequest("zzz://www.bayyy.xxx/"), { });
1833     testRequest(searchBackend, mainDocumentRequest("zzz://www.bbyyy.xxx/"), { });
1834     testRequest(searchBackend, mainDocumentRequest("zzz://www.bcyyy.xxx/"), { });
1835     testRequest(searchBackend, mainDocumentRequest("zzz://www.bdyyy.xxx/"), { });
1836     testRequest(searchBackend, mainDocumentRequest("zzz://www.beyyy.xxx/"), { });
1837     testRequest(searchBackend, mainDocumentRequest("zzz://www.bfyyy.xxx/"), { });
1838     testRequest(searchBackend, mainDocumentRequest("zzz://www.bgyyy.xxx/"), { });
1839     testRequest(searchBackend, mainDocumentRequest("zzz://www.bhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1840     testRequest(searchBackend, mainDocumentRequest("zzz://www.biyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1841     testRequest(searchBackend, mainDocumentRequest("zzz://www.bjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1842     testRequest(searchBackend, mainDocumentRequest("zzz://www.bkyyy.xxx/"), { });
1843
1844     // 'c' is the first character of the first rule, and it overlaps the first character of the second rule.
1845     testRequest(searchBackend, mainDocumentRequest("zzz://www.cyyy.xxx/"), { });
1846     testRequest(searchBackend, mainDocumentRequest("zzz://www.cayyy.xxx/"), { });
1847     testRequest(searchBackend, mainDocumentRequest("zzz://www.cbyyy.xxx/"), { });
1848     testRequest(searchBackend, mainDocumentRequest("zzz://www.ccyyy.xxx/"), { });
1849     testRequest(searchBackend, mainDocumentRequest("zzz://www.cdyyy.xxx/"), { });
1850     testRequest(searchBackend, mainDocumentRequest("zzz://www.ceyyy.xxx/"), { });
1851     testRequest(searchBackend, mainDocumentRequest("zzz://www.cfyyy.xxx/"), { });
1852     testRequest(searchBackend, mainDocumentRequest("zzz://www.cgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1853     testRequest(searchBackend, mainDocumentRequest("zzz://www.chyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1854     testRequest(searchBackend, mainDocumentRequest("zzz://www.ciyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1855     testRequest(searchBackend, mainDocumentRequest("zzz://www.cjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1856     testRequest(searchBackend, mainDocumentRequest("zzz://www.ckyyy.xxx/"), { });
1857
1858     // 'd' is in the first range of both rule. This series cover overlaps between the two rules.
1859     testRequest(searchBackend, mainDocumentRequest("zzz://www.dgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1860     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1861     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1862     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1863     testRequest(searchBackend, mainDocumentRequest("zzz://www.degyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1864     testRequest(searchBackend, mainDocumentRequest("zzz://www.dehyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1865     testRequest(searchBackend, mainDocumentRequest("zzz://www.dfgyyy.xxx/"), { });
1866     testRequest(searchBackend, mainDocumentRequest("zzz://www.dfhyyy.xxx/"), { });
1867     testRequest(searchBackend, mainDocumentRequest("zzz://www.djyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1868     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1869     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1870 }
1871
1872 TEST_F(ContentExtensionTest, QuantifiedOneOrMoreRangesCase11And13InGroups)
1873 {
1874     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"([c-e])+([g-i]+YYY)\"}},"
1875         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[b-d]+[h-j]+YYY\"}}]");
1876
1877     // The interesting ranges only match between 'b' and 'k', plus a gap in 'f'.
1878     testRequest(searchBackend, mainDocumentRequest("zzz://www.aayyy.xxx/"), { });
1879     testRequest(searchBackend, mainDocumentRequest("zzz://www.abyyy.xxx/"), { });
1880     testRequest(searchBackend, mainDocumentRequest("zzz://www.acyyy.xxx/"), { });
1881     testRequest(searchBackend, mainDocumentRequest("zzz://www.adyyy.xxx/"), { });
1882     testRequest(searchBackend, mainDocumentRequest("zzz://www.aeyyy.xxx/"), { });
1883     testRequest(searchBackend, mainDocumentRequest("zzz://www.afyyy.xxx/"), { });
1884     testRequest(searchBackend, mainDocumentRequest("zzz://www.agyyy.xxx/"), { });
1885     testRequest(searchBackend, mainDocumentRequest("zzz://www.ahyyy.xxx/"), { });
1886     testRequest(searchBackend, mainDocumentRequest("zzz://www.aiyyy.xxx/"), { });
1887     testRequest(searchBackend, mainDocumentRequest("zzz://www.ajyyy.xxx/"), { });
1888     testRequest(searchBackend, mainDocumentRequest("zzz://www.akyyy.xxx/"), { });
1889
1890     // 'b' is the first character of the second rule.
1891     testRequest(searchBackend, mainDocumentRequest("zzz://www.byyy.xxx/"), { });
1892     testRequest(searchBackend, mainDocumentRequest("zzz://www.bayyy.xxx/"), { });
1893     testRequest(searchBackend, mainDocumentRequest("zzz://www.bbyyy.xxx/"), { });
1894     testRequest(searchBackend, mainDocumentRequest("zzz://www.bcyyy.xxx/"), { });
1895     testRequest(searchBackend, mainDocumentRequest("zzz://www.bdyyy.xxx/"), { });
1896     testRequest(searchBackend, mainDocumentRequest("zzz://www.beyyy.xxx/"), { });
1897     testRequest(searchBackend, mainDocumentRequest("zzz://www.bfyyy.xxx/"), { });
1898     testRequest(searchBackend, mainDocumentRequest("zzz://www.bgyyy.xxx/"), { });
1899     testRequest(searchBackend, mainDocumentRequest("zzz://www.bhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1900     testRequest(searchBackend, mainDocumentRequest("zzz://www.biyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1901     testRequest(searchBackend, mainDocumentRequest("zzz://www.bjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1902     testRequest(searchBackend, mainDocumentRequest("zzz://www.bkyyy.xxx/"), { });
1903
1904     // 'c' is the first character of the first rule, and it overlaps the first character of the second rule.
1905     testRequest(searchBackend, mainDocumentRequest("zzz://www.cyyy.xxx/"), { });
1906     testRequest(searchBackend, mainDocumentRequest("zzz://www.cayyy.xxx/"), { });
1907     testRequest(searchBackend, mainDocumentRequest("zzz://www.cbyyy.xxx/"), { });
1908     testRequest(searchBackend, mainDocumentRequest("zzz://www.ccyyy.xxx/"), { });
1909     testRequest(searchBackend, mainDocumentRequest("zzz://www.cdyyy.xxx/"), { });
1910     testRequest(searchBackend, mainDocumentRequest("zzz://www.ceyyy.xxx/"), { });
1911     testRequest(searchBackend, mainDocumentRequest("zzz://www.cfyyy.xxx/"), { });
1912     testRequest(searchBackend, mainDocumentRequest("zzz://www.cgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1913     testRequest(searchBackend, mainDocumentRequest("zzz://www.chyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1914     testRequest(searchBackend, mainDocumentRequest("zzz://www.ciyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1915     testRequest(searchBackend, mainDocumentRequest("zzz://www.cjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1916     testRequest(searchBackend, mainDocumentRequest("zzz://www.ckyyy.xxx/"), { });
1917
1918     // 'd' is in the first range of both rule. This series cover overlaps between the two rules.
1919     testRequest(searchBackend, mainDocumentRequest("zzz://www.dgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1920     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1921     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1922     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1923     testRequest(searchBackend, mainDocumentRequest("zzz://www.degyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1924     testRequest(searchBackend, mainDocumentRequest("zzz://www.dehyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1925     testRequest(searchBackend, mainDocumentRequest("zzz://www.dfgyyy.xxx/"), { });
1926     testRequest(searchBackend, mainDocumentRequest("zzz://www.dfhyyy.xxx/"), { });
1927     testRequest(searchBackend, mainDocumentRequest("zzz://www.djyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1928     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1929     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1930 }
1931
1932 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase1)
1933 {
1934     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[a-m]\"}},"
1935         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"^(bar)*[c-e]\"}}]");
1936
1937     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1938     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1939     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { }, true);
1940     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { }, true);
1941     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { }, true);
1942     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1943     testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1944     testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
1945
1946     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[a-m]\"}},"
1947         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"(bar)*[c-e]\"}}]");
1948     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1949     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1950     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { }, true);
1951     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { }, true);
1952     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { }, true);
1953     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1954     testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1955     testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
1956 }
1957
1958
1959 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase2)
1960 {
1961     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[a-m]\"}},"
1962         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"^(bar)*b\"}}]");
1963
1964     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1965     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { }, true);
1966     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1967     testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1968     testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
1969
1970     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[a-m]\"}},"
1971         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"(bar)*l\"}}]");
1972     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1973     testRequest(searchBackend, mainDocumentRequest("zzz://www.k.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1974     testRequest(searchBackend, mainDocumentRequest("zzz://www.l.xxx/"), { }, true);
1975     testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1976     testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
1977 }
1978
1979 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase3)
1980 {
1981     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[b-d]\"}},"
1982         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[a-m]\"}}]");
1983
1984     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1985     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1986     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1987     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1988     testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1989     testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
1990
1991     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[b-d]\"}},"
1992         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[a-m]\"}}]");
1993     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1994     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1995     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1996     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1997     testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1998     testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
1999 }
2000
2001 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase4)
2002 {
2003     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*l\"}},"
2004         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[a-m]\"}}]");
2005
2006     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2007     testRequest(matchBackend, mainDocumentRequest("k://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2008     testRequest(matchBackend, mainDocumentRequest("l://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2009     testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2010     testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
2011
2012     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*l\"}},"
2013         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[a-m]\"}}]");
2014     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2015     testRequest(searchBackend, mainDocumentRequest("zzz://www.k.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2016     testRequest(searchBackend, mainDocumentRequest("zzz://www.l.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2017     testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2018     testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
2019 }
2020
2021 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase5)
2022 {
2023     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[a-e]\"}},"
2024         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[e-h]\"}}]");
2025
2026     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2027     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2028     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2029     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2030     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2031     testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
2032
2033     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[a-e]\"}},"
2034         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[e-h]\"}}]");
2035     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2036     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2037     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2038     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2039     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2040     testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
2041 }
2042
2043 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase6)
2044 {
2045     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*e\"}},"
2046         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[e-h]\"}}]");
2047
2048     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
2049     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
2050     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2051     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2052     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2053     testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
2054
2055     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*e\"}},"
2056         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[e-h]\"}}]");
2057     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
2058     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
2059     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2060     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2061     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2062     testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
2063 }
2064
2065 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase7)
2066 {
2067     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[a-e]\"}},"
2068         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*e\"}}]");
2069
2070     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2071     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2072     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2073     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { });
2074
2075     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[a-e]\"}},"
2076         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*e\"}}]");
2077     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2078     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2079     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2080     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { });
2081 }
2082
2083 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase8)
2084 {
2085     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[e-h]\"}},"
2086         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[a-e]\"}}]");
2087
2088     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2089     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2090     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2091     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2092     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2093     testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
2094
2095     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[e-h]\"}},"
2096         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[a-e]\"}}]");
2097     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2098     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2099     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2100     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2101     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2102     testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
2103 }
2104
2105 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase9)
2106 {
2107     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*e\"}},"
2108         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[a-e]\"}}]");
2109
2110     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2111     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2112     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2113     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { });
2114
2115     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*e\"}},"
2116         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[a-e]\"}}]");
2117     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2118     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2119     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2120     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { });
2121 }
2122
2123 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase10)
2124 {
2125     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[e-h]\"}},"
2126         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*e\"}}]");
2127
2128     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
2129     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
2130     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2131     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2132     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2133     testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
2134
2135     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[e-h]\"}},"
2136         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*e\"}}]");
2137     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
2138     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
2139     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2140     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2141     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2142     testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
2143 }
2144
2145 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase11)
2146 {
2147     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[e-g]\"}},"
2148         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[d-f]\"}}]");
2149
2150     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { });
2151     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2152     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2153     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2154     testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2155     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
2156
2157     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[e-g]\"}},"
2158         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[d-f]\"}}]");
2159     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { });
2160     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2161     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2162     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2163     testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2164     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
2165 }
2166
2167
2168 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase12)
2169 {
2170     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[e-g]\"}},"
2171         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[d-g]\"}}]");
2172
2173     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { });
2174     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2175     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2176     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2177     testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2178     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
2179
2180     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[e-g]\"}},"
2181         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[d-g]\"}}]");
2182     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { });
2183     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2184     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2185     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2186     testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2187     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
2188 }
2189
2190 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase13)
2191 {
2192     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[b-d]\"}},"
2193         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[c-e]\"}}]");
2194
2195     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
2196     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2197     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2198     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2199     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2200     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
2201
2202     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[b-d]\"}},"
2203         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[c-e]\"}}]");
2204     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
2205     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2206     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2207     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2208     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2209     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
2210 }
2211
2212 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase14)
2213 {
2214     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[b-e]\"}},"
2215         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[c-e]\"}}]");
2216
2217     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
2218     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2219     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2220     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2221     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2222     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
2223
2224     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[b-e]\"}},"
2225         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[c-e]\"}}]");
2226     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
2227     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2228     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2229     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2230     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2231     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
2232 }
2233
2234 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase15)
2235 {
2236     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[c-f]\"}},"
2237         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[c-f]\"}}]");
2238
2239     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
2240     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { });
2241     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2242     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2243     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2244     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2245     testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { });
2246
2247     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[c-f]\"}},"
2248         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[c-f]\"}}]");
2249     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
2250     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { });
2251     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2252     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2253     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2254     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2255     testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { });
2256 }
2257
2258 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase16)
2259 {
2260     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*c\"}},"
2261         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*c\"}}]");
2262
2263     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
2264     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { });
2265     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2266     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
2267     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { });
2268
2269     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*c\"}},"
2270         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*c\"}}]");
2271     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
2272     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { });
2273     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2274     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
2275     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { });
2276 }
2277
2278 TEST_F(ContentExtensionTest, CombinedQuantifiedOneOrMoreRangesCase11And13)
2279 {
2280     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[c-e]+[g-i]+YYY\"}},"
2281         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[b-d]+[h-j]+YYY\"}}]");
2282
2283     // The interesting ranges only match between 'b' and 'k', plus a gap in 'f'.
2284     testRequest(searchBackend, mainDocumentRequest("zzz://www.aayyy.xxx/"), { });
2285     testRequest(searchBackend, mainDocumentRequest("zzz://www.abyyy.xxx/"), { });
2286     testRequest(searchBackend, mainDocumentRequest("zzz://www.acyyy.xxx/"), { });
2287     testRequest(searchBackend, mainDocumentRequest("zzz://www.adyyy.xxx/"), { });
2288     testRequest(searchBackend, mainDocumentRequest("zzz://www.aeyyy.xxx/"), { });
2289     testRequest(searchBackend, mainDocumentRequest("zzz://www.afyyy.xxx/"), { });
2290     testRequest(searchBackend, mainDocumentRequest("zzz://www.agyyy.xxx/"), { });
2291     testRequest(searchBackend, mainDocumentRequest("zzz://www.ahyyy.xxx/"), { });
2292     testRequest(searchBackend, mainDocumentRequest("zzz://www.aiyyy.xxx/"), { });
2293     testRequest(searchBackend, mainDocumentRequest("zzz://www.ajyyy.xxx/"), { });
2294     testRequest(searchBackend, mainDocumentRequest("zzz://www.akyyy.xxx/"), { });
2295
2296     // 'b' is the first character of the second rule.
2297     testRequest(searchBackend, mainDocumentRequest("zzz://www.byyy.xxx/"), { });
2298     testRequest(searchBackend, mainDocumentRequest("zzz://www.bayyy.xxx/"), { });
2299     testRequest(searchBackend, mainDocumentRequest("zzz://www.bbyyy.xxx/"), { });
2300     testRequest(searchBackend, mainDocumentRequest("zzz://www.bcyyy.xxx/"), { });
2301     testRequest(searchBackend, mainDocumentRequest("zzz://www.bdyyy.xxx/"), { });
2302     testRequest(searchBackend, mainDocumentRequest("zzz://www.beyyy.xxx/"), { });
2303     testRequest(searchBackend, mainDocumentRequest("zzz://www.bfyyy.xxx/"), { });
2304     testRequest(searchBackend, mainDocumentRequest("zzz://www.bgyyy.xxx/"), { });
2305     testRequest(searchBackend, mainDocumentRequest("zzz://www.bhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2306     testRequest(searchBackend, mainDocumentRequest("zzz://www.biyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2307     testRequest(searchBackend, mainDocumentRequest("zzz://www.bjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2308     testRequest(searchBackend, mainDocumentRequest("zzz://www.bkyyy.xxx/"), { });
2309
2310     // 'c' is the first character of the first rule, and it overlaps the first character of the second rule.
2311     testRequest(searchBackend, mainDocumentRequest("zzz://www.cyyy.xxx/"), { });
2312     testRequest(searchBackend, mainDocumentRequest("zzz://www.cayyy.xxx/"), { });
2313     testRequest(searchBackend, mainDocumentRequest("zzz://www.cbyyy.xxx/"), { });
2314     testRequest(searchBackend, mainDocumentRequest("zzz://www.ccyyy.xxx/"), { });
2315     testRequest(searchBackend, mainDocumentRequest("zzz://www.cdyyy.xxx/"), { });
2316     testRequest(searchBackend, mainDocumentRequest("zzz://www.ceyyy.xxx/"), { });
2317     testRequest(searchBackend, mainDocumentRequest("zzz://www.cfyyy.xxx/"), { });
2318     testRequest(searchBackend, mainDocumentRequest("zzz://www.cgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2319     testRequest(searchBackend, mainDocumentRequest("zzz://www.chyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2320     testRequest(searchBackend, mainDocumentRequest("zzz://www.ciyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2321     testRequest(searchBackend, mainDocumentRequest("zzz://www.cjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2322     testRequest(searchBackend, mainDocumentRequest("zzz://www.ckyyy.xxx/"), { });
2323
2324     // 'd' is in the first range of both rule. This series cover overlaps between the two rules.
2325     testRequest(searchBackend, mainDocumentRequest("zzz://www.dgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2326     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2327     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2328     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2329     testRequest(searchBackend, mainDocumentRequest("zzz://www.degyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2330     testRequest(searchBackend, mainDocumentRequest("zzz://www.dehyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2331     testRequest(searchBackend, mainDocumentRequest("zzz://www.dfgyyy.xxx/"), { });
2332     testRequest(searchBackend, mainDocumentRequest("zzz://www.dfhyyy.xxx/"), { });
2333     testRequest(searchBackend, mainDocumentRequest("zzz://www.djyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2334     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2335     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2336 }
2337
2338 TEST_F(ContentExtensionTest, CombinedQuantifiedOneOrMoreRangesCase11And13InGroups)
2339 {
2340     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*([c-e])+([g-i]+YYY)\"}},"
2341         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[b-d]+[h-j]+YYY\"}}]");
2342
2343     // The interesting ranges only match between 'b' and 'k', plus a gap in 'f'.
2344     testRequest(searchBackend, mainDocumentRequest("zzz://www.aayyy.xxx/"), { });
2345     testRequest(searchBackend, mainDocumentRequest("zzz://www.abyyy.xxx/"), { });
2346     testRequest(searchBackend, mainDocumentRequest("zzz://www.acyyy.xxx/"), { });
2347     testRequest(searchBackend, mainDocumentRequest("zzz://www.adyyy.xxx/"), { });
2348     testRequest(searchBackend, mainDocumentRequest("zzz://www.aeyyy.xxx/"), { });
2349     testRequest(searchBackend, mainDocumentRequest("zzz://www.afyyy.xxx/"), { });
2350     testRequest(searchBackend, mainDocumentRequest("zzz://www.agyyy.xxx/"), { });
2351     testRequest(searchBackend, mainDocumentRequest("zzz://www.ahyyy.xxx/"), { });
2352     testRequest(searchBackend, mainDocumentRequest("zzz://www.aiyyy.xxx/"), { });
2353     testRequest(searchBackend, mainDocumentRequest("zzz://www.ajyyy.xxx/"), { });
2354     testRequest(searchBackend, mainDocumentRequest("zzz://www.akyyy.xxx/"), { });
2355
2356     // 'b' is the first character of the second rule.
2357     testRequest(searchBackend, mainDocumentRequest("zzz://www.byyy.xxx/"), { });
2358     testRequest(searchBackend, mainDocumentRequest("zzz://www.bayyy.xxx/"), { });
2359     testRequest(searchBackend, mainDocumentRequest("zzz://www.bbyyy.xxx/"), { });
2360     testRequest(searchBackend, mainDocumentRequest("zzz://www.bcyyy.xxx/"), { });
2361     testRequest(searchBackend, mainDocumentRequest("zzz://www.bdyyy.xxx/"), { });
2362     testRequest(searchBackend, mainDocumentRequest("zzz://www.beyyy.xxx/"), { });
2363     testRequest(searchBackend, mainDocumentRequest("zzz://www.bfyyy.xxx/"), { });
2364     testRequest(searchBackend, mainDocumentRequest("zzz://www.bgyyy.xxx/"), { });
2365     testRequest(searchBackend, mainDocumentRequest("zzz://www.bhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2366     testRequest(searchBackend, mainDocumentRequest("zzz://www.biyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2367     testRequest(searchBackend, mainDocumentRequest("zzz://www.bjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2368     testRequest(searchBackend, mainDocumentRequest("zzz://www.bkyyy.xxx/"), { });
2369
2370     // 'c' is the first character of the first rule, and it overlaps the first character of the second rule.
2371     testRequest(searchBackend, mainDocumentRequest("zzz://www.cyyy.xxx/"), { });
2372     testRequest(searchBackend, mainDocumentRequest("zzz://www.cayyy.xxx/"), { });
2373     testRequest(searchBackend, mainDocumentRequest("zzz://www.cbyyy.xxx/"), { });
2374     testRequest(searchBackend, mainDocumentRequest("zzz://www.ccyyy.xxx/"), { });
2375     testRequest(searchBackend, mainDocumentRequest("zzz://www.cdyyy.xxx/"), { });
2376     testRequest(searchBackend, mainDocumentRequest("zzz://www.ceyyy.xxx/"), { });
2377     testRequest(searchBackend, mainDocumentRequest("zzz://www.cfyyy.xxx/"), { });
2378     testRequest(searchBackend, mainDocumentRequest("zzz://www.cgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2379     testRequest(searchBackend, mainDocumentRequest("zzz://www.chyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2380     testRequest(searchBackend, mainDocumentRequest("zzz://www.ciyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2381     testRequest(searchBackend, mainDocumentRequest("zzz://www.cjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2382     testRequest(searchBackend, mainDocumentRequest("zzz://www.ckyyy.xxx/"), { });
2383
2384     // 'd' is in the first range of both rule. This series cover overlaps between the two rules.
2385     testRequest(searchBackend, mainDocumentRequest("zzz://www.dgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2386     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2387     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2388     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2389     testRequest(searchBackend, mainDocumentRequest("zzz://www.degyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2390     testRequest(searchBackend, mainDocumentRequest("zzz://www.dehyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2391     testRequest(searchBackend, mainDocumentRequest("zzz://www.dfgyyy.xxx/"), { });
2392     testRequest(searchBackend, mainDocumentRequest("zzz://www.dfhyyy.xxx/"), { });
2393     testRequest(searchBackend, mainDocumentRequest("zzz://www.djyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2394     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2395     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2396 }
2397
2398 } // namespace TestWebKitAPI