51b4f778a74c3103612aa8df0cffecaa8dedcb52
[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         Vector<bool> pagesUsed;
1104         ContentExtensions::DFABytecodeInterpreter interpreter(&combinedBytecode[0], combinedBytecode.size(), pagesUsed);
1105         
1106         EXPECT_EQ(interpreter.interpret("ABBBX", 0).size(), 1ull);
1107         EXPECT_EQ(interpreter.interpret("ACCCX", 0).size(), 1ull);
1108         EXPECT_EQ(interpreter.interpret("ADDDX", 0).size(), 1ull);
1109         EXPECT_EQ(interpreter.interpret("XBBBX", 0).size(), 0ull);
1110         EXPECT_EQ(interpreter.interpret("ABBX", 0).size(), 0ull);
1111         EXPECT_EQ(interpreter.interpret("ACCX", 0).size(), 0ull);
1112         EXPECT_EQ(interpreter.interpret("ADDX", 0).size(), 0ull);
1113     }
1114 }
1115     
1116 TEST_F(ContentExtensionTest, QuantifierInGroup)
1117 {
1118     ContentExtensions::CombinedURLFilters combinedURLFilters;
1119     ContentExtensions::URLFilterParser parser(combinedURLFilters);
1120     
1121     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A+)B)C)", false, 0));
1122     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B+)C)", false, 1));
1123     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B+)C)D", false, 2));
1124     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B)C+)", false, 3));
1125     EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B)C)", false, 4));
1126     
1127     // (((A)B+)C) and (((A)B+)C)D should be in the same NFA.
1128     EXPECT_EQ(4ul, createNFAs(combinedURLFilters).size());
1129 }
1130
1131 static void testPatternStatus(String pattern, ContentExtensions::URLFilterParser::ParseStatus status)
1132 {
1133     ContentExtensions::CombinedURLFilters combinedURLFilters;
1134     ContentExtensions::URLFilterParser parser(combinedURLFilters);
1135     EXPECT_EQ(status, parser.addPattern(pattern, false, 0));
1136 }
1137     
1138 TEST_F(ContentExtensionTest, ParsingFailures)
1139 {
1140     testPatternStatus("a*b?.*.?[a-z]?[a-z]*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1141     testPatternStatus("a*b?.*.?[a-z]?[a-z]+", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1142     testPatternStatus("a*b?.*.?[a-z]?[a-z]", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1143     testPatternStatus(".*?a", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1144     testPatternStatus(".*a", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1145     
1146     testPatternStatus("(?!)", ContentExtensions::URLFilterParser::ParseStatus::Group);
1147     testPatternStatus("(?=)", ContentExtensions::URLFilterParser::ParseStatus::Group);
1148     testPatternStatus("(?!a)", ContentExtensions::URLFilterParser::ParseStatus::Group);
1149     testPatternStatus("(?=a)", ContentExtensions::URLFilterParser::ParseStatus::Group);
1150     testPatternStatus("(regex)", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1151     testPatternStatus("(regex", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1152     testPatternStatus("((regex)", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1153     testPatternStatus("(?:regex)", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1154     testPatternStatus("(?:regex", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1155     testPatternStatus("[^.]+", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1156     
1157     testPatternStatus("a++", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1158     testPatternStatus("[a]++", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1159     testPatternStatus("+", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1160     
1161     testPatternStatus("[", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1162     testPatternStatus("[a}", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
1163     
1164     // FIXME: Look into why these do not cause YARR parsing errors.  They probably should.
1165     testPatternStatus("a]", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1166     testPatternStatus("{", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1167     testPatternStatus("{[a]", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1168     testPatternStatus("{0", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1169     testPatternStatus("{0,", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1170     testPatternStatus("{0,1", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1171     testPatternStatus("a{0,1", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1172     testPatternStatus("a{a,b}", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1173
1174     const char nonASCII[2] = {-1, '\0'};
1175     testPatternStatus(nonASCII, ContentExtensions::URLFilterParser::ParseStatus::NonASCII);
1176     testPatternStatus("\\xff", ContentExtensions::URLFilterParser::ParseStatus::NonASCII);
1177     
1178     testPatternStatus("\\x\\r\\n", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1179     testPatternStatus("\\b", ContentExtensions::URLFilterParser::ParseStatus::WordBoundary);
1180     testPatternStatus("[\\d]", ContentExtensions::URLFilterParser::ParseStatus::AtomCharacter);
1181     testPatternStatus("\\d\\D\\w\\s\\v\\h\\i\\c", ContentExtensions::URLFilterParser::ParseStatus::UnsupportedCharacterClass);
1182     
1183     testPatternStatus("this|that", ContentExtensions::URLFilterParser::ParseStatus::Disjunction);
1184     testPatternStatus("a{0,1}b", ContentExtensions::URLFilterParser::ParseStatus::Ok);
1185     testPatternStatus("a{0,2}b", ContentExtensions::URLFilterParser::ParseStatus::InvalidQuantifier);
1186     testPatternStatus("", ContentExtensions::URLFilterParser::ParseStatus::EmptyPattern);
1187     testPatternStatus("$$", ContentExtensions::URLFilterParser::ParseStatus::MisplacedEndOfLine);
1188     testPatternStatus("a^", ContentExtensions::URLFilterParser::ParseStatus::MisplacedStartOfLine);
1189     testPatternStatus("(^)", ContentExtensions::URLFilterParser::ParseStatus::MisplacedStartOfLine);
1190     
1191     testPatternStatus("(a)\\1", ContentExtensions::URLFilterParser::ParseStatus::Ok); // This should be BackReference, right?
1192 }
1193
1194 TEST_F(ContentExtensionTest, PatternMatchingTheEmptyString)
1195 {
1196     // Simple atoms.
1197     testPatternStatus(".*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1198     testPatternStatus("a*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1199     testPatternStatus(".?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1200     testPatternStatus("a?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1201
1202     // Character sets.
1203     testPatternStatus("[a-z]*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1204     testPatternStatus("[a-z]?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1205
1206     // Groups.
1207     testPatternStatus("(foobar)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1208     testPatternStatus("(foobar)?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1209     testPatternStatus("(.*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1210     testPatternStatus("(a*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1211     testPatternStatus("(.?)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1212     testPatternStatus("(a?)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1213     testPatternStatus("([a-z]*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1214     testPatternStatus("([a-z]?)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1215
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     testPatternStatus("(.?)+", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1222
1223     // Nested groups.
1224     testPatternStatus("((foo)?((.)*)(bar)*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
1225 }
1226
1227 TEST_F(ContentExtensionTest, MinimizingWithMoreFinalStatesThanNonFinalStates)
1228 {
1229     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^h[a-z://]+\"}},"
1230         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://foo.com/\"}},"
1231         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://bar.com/\"}}]");
1232
1233     testRequest(backend, mainDocumentRequest("http://foo.com/"), { ContentExtensions::ActionType::BlockLoad });
1234     testRequest(backend, mainDocumentRequest("http://bar.com/"), { ContentExtensions::ActionType::BlockLoad });
1235     testRequest(backend, mainDocumentRequest("attp://foo.com/"), { });
1236     testRequest(backend, mainDocumentRequest("attp://bar.com/"), { });
1237
1238     testRequest(backend, mainDocumentRequest("http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1239     testRequest(backend, mainDocumentRequest("https://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1240     testRequest(backend, mainDocumentRequest("bttp://webkit.org/"), { });
1241     testRequest(backend, mainDocumentRequest("bttps://webkit.org/"), { });
1242     testRequest(backend, mainDocumentRequest("http://webkit.org/b"), { ContentExtensions::ActionType::BlockLoad });
1243     testRequest(backend, mainDocumentRequest("https://webkit.org/b"), { ContentExtensions::ActionType::BlockLoad });
1244     testRequest(backend, mainDocumentRequest("cttp://webkit.org/B"), { });
1245     testRequest(backend, mainDocumentRequest("cttps://webkit.org/B"), { });
1246 }
1247
1248 TEST_F(ContentExtensionTest, StatesWithDifferentActionsAreNotUnified1)
1249 {
1250     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://www.webkit.org/\"}},"
1251         "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"^https://www.webkit.org/\"}},"
1252         "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"^attps://www.webkit.org/\"}}]");
1253
1254     testRequest(backend, mainDocumentRequest("http://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1255     testRequest(backend, mainDocumentRequest("https://www.webkit.org/"), { ContentExtensions::ActionType::BlockCookies });
1256     testRequest(backend, mainDocumentRequest("attps://www.webkit.org/"), { ContentExtensions::ActionType::BlockCookies });
1257     testRequest(backend, mainDocumentRequest("http://www.webkit.org/a"), { ContentExtensions::ActionType::BlockLoad });
1258     testRequest(backend, mainDocumentRequest("https://www.webkit.org/B"), { ContentExtensions::ActionType::BlockCookies });
1259     testRequest(backend, mainDocumentRequest("attps://www.webkit.org/c"), { ContentExtensions::ActionType::BlockCookies });
1260     testRequest(backend, mainDocumentRequest("http://www.whatwg.org/"), { });
1261     testRequest(backend, mainDocumentRequest("https://www.whatwg.org/"), { });
1262     testRequest(backend, mainDocumentRequest("attps://www.whatwg.org/"), { });
1263 }
1264
1265 TEST_F(ContentExtensionTest, StatesWithDifferentActionsAreNotUnified2)
1266 {
1267     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://www.webkit.org/\"}},"
1268         "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"^https://www.webkit.org/\"}},"
1269         "{\"action\":{\"type\":\"css-display-none\", \"selector\":\"#foo\"},\"trigger\":{\"url-filter\":\"^https://www.webkit.org/\"}}]");
1270
1271     testRequest(backend, mainDocumentRequest("http://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1272     testRequest(backend, mainDocumentRequest("https://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockCookies });
1273     testRequest(backend, mainDocumentRequest("https://www.whatwg.org/"), { });
1274     testRequest(backend, mainDocumentRequest("attps://www.whatwg.org/"), { });
1275 }
1276
1277 // The order in which transitions from the root will be processed is unpredictable.
1278 // To exercises the various options, this test exists in various version exchanging the transition to the final state.
1279 TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge1)
1280 {
1281     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.a\"}},"
1282         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.a\"}},"
1283         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bac\"}},"
1284         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bbc\"}},"
1285         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCC\"}}]");
1286
1287     testRequest(backend, mainDocumentRequest("aza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1288     testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1289     testRequest(backend, mainDocumentRequest("bac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1290     testRequest(backend, mainDocumentRequest("bbc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1291     testRequest(backend, mainDocumentRequest("bcc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1292
1293     testRequest(backend, mainDocumentRequest("aac://www.webkit.org/"), { });
1294     testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { });
1295     testRequest(backend, mainDocumentRequest("acc://www.webkit.org/"), { });
1296
1297     testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1298     testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1299     testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1300 }
1301 TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge2)
1302 {
1303     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bac\"}},"
1304         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bbc\"}},"
1305         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCC\"}},"
1306         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.a\"}},"
1307         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.a\"}}]");
1308
1309     testRequest(backend, mainDocumentRequest("aza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1310     testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1311     testRequest(backend, mainDocumentRequest("bac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1312     testRequest(backend, mainDocumentRequest("bbc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1313     testRequest(backend, mainDocumentRequest("bcc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1314
1315     testRequest(backend, mainDocumentRequest("aac://www.webkit.org/"), { });
1316     testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { });
1317     testRequest(backend, mainDocumentRequest("acc://www.webkit.org/"), { });
1318
1319     testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1320     testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1321     testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
1322 }
1323 TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge3)
1324 {
1325     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.c\"}},"
1326         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.c\"}},"
1327         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^baa\"}},"
1328         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bba\"}},"
1329         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCA\"}}]");
1330
1331     testRequest(backend, mainDocumentRequest("azc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1332     testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1333     testRequest(backend, mainDocumentRequest("baa://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1334     testRequest(backend, mainDocumentRequest("bba://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1335     testRequest(backend, mainDocumentRequest("bca://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1336
1337     testRequest(backend, mainDocumentRequest("aaa://www.webkit.org/"), { });
1338     testRequest(backend, mainDocumentRequest("aba://www.webkit.org/"), { });
1339     testRequest(backend, mainDocumentRequest("aca://www.webkit.org/"), { });
1340
1341     testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1342     testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1343     testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1344 }
1345 TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge4)
1346 {
1347     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^baa\"}},"
1348         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bba\"}},"
1349         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCA\"}},"
1350         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.c\"}},"
1351         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.c\"}}]");
1352
1353     testRequest(backend, mainDocumentRequest("azc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1354     testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1355     testRequest(backend, mainDocumentRequest("baa://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1356     testRequest(backend, mainDocumentRequest("bba://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1357     testRequest(backend, mainDocumentRequest("bca://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1358
1359     testRequest(backend, mainDocumentRequest("aaa://www.webkit.org/"), { });
1360     testRequest(backend, mainDocumentRequest("aba://www.webkit.org/"), { });
1361     testRequest(backend, mainDocumentRequest("aca://www.webkit.org/"), { });
1362
1363     testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1364     testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1365     testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
1366 }
1367
1368 TEST_F(ContentExtensionTest, FallbackTransitionsToOtherNodeInSameGroupDoesNotDifferentiateGroup)
1369 {
1370     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^aac\"}},"
1371         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.c\"}},"
1372         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.c\"}}]");
1373
1374     testRequest(backend, mainDocumentRequest("aac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1375     testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1376     testRequest(backend, mainDocumentRequest("bac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1377     testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1378
1379     testRequest(backend, mainDocumentRequest("aaa://www.webkit.org/"), { });
1380     testRequest(backend, mainDocumentRequest("aca://www.webkit.org/"), { });
1381     testRequest(backend, mainDocumentRequest("baa://www.webkit.org/"), { });
1382 }
1383
1384 TEST_F(ContentExtensionTest, SimpleFallBackTransitionDifferentiator1)
1385 {
1386     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.bc.de\"}},"
1387         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.bd.ef\"}}]");
1388
1389     testRequest(backend, mainDocumentRequest("abbccde://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1390     testRequest(backend, mainDocumentRequest("aabcdde://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1391     testRequest(backend, mainDocumentRequest("aabddef://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1392     testRequest(backend, mainDocumentRequest("aabddef://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1393
1394     testRequest(backend, mainDocumentRequest("abcde://www.webkit.org/"), { });
1395     testRequest(backend, mainDocumentRequest("abdef://www.webkit.org/"), { });
1396 }
1397
1398 TEST_F(ContentExtensionTest, SimpleFallBackTransitionDifferentiator2)
1399 {
1400     auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^cb.\"}},"
1401         "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^db.b\"}}]");
1402
1403     testRequest(backend, mainDocumentRequest("cba://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1404     testRequest(backend, mainDocumentRequest("cbb://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1405     testRequest(backend, mainDocumentRequest("dbab://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1406     testRequest(backend, mainDocumentRequest("dbxb://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1407
1408     testRequest(backend, mainDocumentRequest("cca://www.webkit.org/"), { });
1409     testRequest(backend, mainDocumentRequest("dddd://www.webkit.org/"), { });
1410     testRequest(backend, mainDocumentRequest("bbbb://www.webkit.org/"), { });
1411 }
1412
1413 // *** We have the following ranges intersections: ***
1414 // Full overlap.
1415 // 1)
1416 // A: |-----|
1417 // B:  |---|
1418 // 2)
1419 // A: |-----|
1420 // B:    |
1421 // 3)
1422 // A:  |---|
1423 // B: |-----|
1424 // 4)
1425 // A:    |
1426 // B: |-----|
1427 // One edge in common
1428 // 5)
1429 // A: |-|
1430 // B:   |-|
1431 // 6)
1432 // A: |
1433 // B: |-|
1434 // 7)
1435 // A: |-|
1436 // B:   |
1437 // 8)
1438 // A:   |-|
1439 // B: |-|
1440 // 9)
1441 // A:   |
1442 // B: |-|
1443 // 10)
1444 // A: |-|
1445 // B: |
1446 // B overlap on the left side of A.
1447 // 11)
1448 // A:   |---|
1449 // B: |---|
1450 // 12)
1451 // A:   |---|
1452 // B: |-----|
1453 // A overlap on the left side of B
1454 // 13)
1455 // A: |---|
1456 // B:   |---|
1457 // 14)
1458 // A: |-----|
1459 // B:   |---|
1460 // Equal ranges
1461 // 15)
1462 // A: |---|
1463 // B: |---|
1464 // 16)
1465 // A: |
1466 // B: |
1467
1468 TEST_F(ContentExtensionTest, RangeOverlapCase1)
1469 {
1470     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[a-m]\"}},"
1471         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"^[c-e]\"}}]");
1472
1473     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1474     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1475     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { }, true);
1476     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { }, true);
1477     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { }, true);
1478     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1479     testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1480     testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
1481
1482     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-m]\"}},"
1483         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"[c-e]\"}}]");
1484     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1485     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1486     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { }, true);
1487     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { }, true);
1488     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { }, true);
1489     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1490     testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1491     testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
1492 }
1493
1494 TEST_F(ContentExtensionTest, RangeOverlapCase2)
1495 {
1496     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[a-m]\"}},"
1497         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"^b\"}}]");
1498
1499     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1500     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { }, true);
1501     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1502     testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1503     testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
1504
1505     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-m]\"}},"
1506         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"l\"}}]");
1507     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1508     testRequest(searchBackend, mainDocumentRequest("zzz://www.k.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1509     testRequest(searchBackend, mainDocumentRequest("zzz://www.l.xxx/"), { }, true);
1510     testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1511     testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
1512 }
1513
1514 TEST_F(ContentExtensionTest, RangeOverlapCase3)
1515 {
1516     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[b-d]\"}},"
1517         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[a-m]\"}}]");
1518
1519     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1520     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1521     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1522     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1523     testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1524     testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
1525
1526     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[b-d]\"}},"
1527         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[a-m]\"}}]");
1528     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1529     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1530     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1531     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1532     testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1533     testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
1534 }
1535
1536 TEST_F(ContentExtensionTest, RangeOverlapCase4)
1537 {
1538     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^l\"}},"
1539         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[a-m]\"}}]");
1540
1541     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1542     testRequest(matchBackend, mainDocumentRequest("k://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1543     testRequest(matchBackend, mainDocumentRequest("l://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1544     testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1545     testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
1546
1547     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"l\"}},"
1548         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[a-m]\"}}]");
1549     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1550     testRequest(searchBackend, mainDocumentRequest("zzz://www.k.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1551     testRequest(searchBackend, mainDocumentRequest("zzz://www.l.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1552     testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1553     testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
1554 }
1555
1556 TEST_F(ContentExtensionTest, RangeOverlapCase5)
1557 {
1558     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[a-e]\"}},"
1559         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[e-h]\"}}]");
1560
1561     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1562     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1563     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1564     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1565     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1566     testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
1567
1568     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-e]\"}},"
1569         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[e-h]\"}}]");
1570     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1571     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1572     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1573     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1574     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1575     testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
1576 }
1577
1578 TEST_F(ContentExtensionTest, RangeOverlapCase6)
1579 {
1580     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^e\"}},"
1581         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[e-h]\"}}]");
1582
1583     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
1584     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
1585     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1586     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1587     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1588     testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
1589
1590     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"e\"}},"
1591         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[e-h]\"}}]");
1592     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
1593     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
1594     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1595     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1596     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1597     testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
1598 }
1599
1600 TEST_F(ContentExtensionTest, RangeOverlapCase7)
1601 {
1602     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[a-e]\"}},"
1603         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^e\"}}]");
1604
1605     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1606     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1607     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1608     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { });
1609
1610     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-e]\"}},"
1611         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"e\"}}]");
1612     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1613     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1614     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1615     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { });
1616 }
1617
1618 TEST_F(ContentExtensionTest, RangeOverlapCase8)
1619 {
1620     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[e-h]\"}},"
1621         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[a-e]\"}}]");
1622
1623     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1624     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1625     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1626     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1627     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1628     testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
1629
1630     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[e-h]\"}},"
1631         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[a-e]\"}}]");
1632     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1633     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1634     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1635     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1636     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1637     testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
1638 }
1639
1640 TEST_F(ContentExtensionTest, RangeOverlapCase9)
1641 {
1642     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^e\"}},"
1643         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[a-e]\"}}]");
1644
1645     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1646     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1647     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1648     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { });
1649
1650     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"e\"}},"
1651         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[a-e]\"}}]");
1652     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1653     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1654     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1655     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { });
1656 }
1657
1658 TEST_F(ContentExtensionTest, RangeOverlapCase10)
1659 {
1660     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[e-h]\"}},"
1661         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^e\"}}]");
1662
1663     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
1664     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
1665     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1666     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1667     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1668     testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
1669
1670     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[e-h]\"}},"
1671         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"e\"}}]");
1672     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
1673     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
1674     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1675     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1676     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1677     testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
1678 }
1679
1680 TEST_F(ContentExtensionTest, RangeOverlapCase11)
1681 {
1682     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[e-g]\"}},"
1683         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[d-f]\"}}]");
1684
1685     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { });
1686     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1687     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1688     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1689     testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1690     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
1691
1692     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[e-g]\"}},"
1693         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[d-f]\"}}]");
1694     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { });
1695     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1696     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1697     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1698     testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1699     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
1700 }
1701
1702
1703 TEST_F(ContentExtensionTest, RangeOverlapCase12)
1704 {
1705     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[e-g]\"}},"
1706         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[d-g]\"}}]");
1707
1708     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { });
1709     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1710     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1711     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1712     testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1713     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
1714
1715     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[e-g]\"}},"
1716         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[d-g]\"}}]");
1717     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { });
1718     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1719     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1720     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1721     testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1722     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
1723 }
1724
1725 TEST_F(ContentExtensionTest, RangeOverlapCase13)
1726 {
1727     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[b-d]\"}},"
1728         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[c-e]\"}}]");
1729
1730     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
1731     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1732     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1733     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1734     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1735     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
1736
1737     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[b-d]\"}},"
1738         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[c-e]\"}}]");
1739     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
1740     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1741     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1742     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1743     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1744     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
1745 }
1746
1747 TEST_F(ContentExtensionTest, RangeOverlapCase14)
1748 {
1749     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[b-e]\"}},"
1750         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[c-e]\"}}]");
1751
1752     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
1753     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1754     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1755     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1756     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1757     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
1758
1759     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[b-e]\"}},"
1760         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[c-e]\"}}]");
1761     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
1762     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1763     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1764     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1765     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1766     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
1767 }
1768
1769 TEST_F(ContentExtensionTest, RangeOverlapCase15)
1770 {
1771     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[c-f]\"}},"
1772         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[c-f]\"}}]");
1773
1774     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
1775     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { });
1776     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1777     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1778     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1779     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1780     testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { });
1781
1782     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[c-f]\"}},"
1783         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[c-f]\"}}]");
1784     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
1785     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { });
1786     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1787     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1788     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1789     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1790     testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { });
1791 }
1792
1793 TEST_F(ContentExtensionTest, RangeOverlapCase16)
1794 {
1795     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^c\"}},"
1796         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^c\"}}]");
1797
1798     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
1799     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { });
1800     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1801     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
1802     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { });
1803
1804     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"c\"}},"
1805         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"c\"}}]");
1806     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
1807     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { });
1808     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1809     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
1810     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { });
1811 }
1812
1813 TEST_F(ContentExtensionTest, QuantifiedOneOrMoreRangesCase11And13)
1814 {
1815     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[c-e]+[g-i]+YYY\"}},"
1816         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[b-d]+[h-j]+YYY\"}}]");
1817
1818     // The interesting ranges only match between 'b' and 'k', plus a gap in 'f'.
1819     testRequest(searchBackend, mainDocumentRequest("zzz://www.aayyy.xxx/"), { });
1820     testRequest(searchBackend, mainDocumentRequest("zzz://www.abyyy.xxx/"), { });
1821     testRequest(searchBackend, mainDocumentRequest("zzz://www.acyyy.xxx/"), { });
1822     testRequest(searchBackend, mainDocumentRequest("zzz://www.adyyy.xxx/"), { });
1823     testRequest(searchBackend, mainDocumentRequest("zzz://www.aeyyy.xxx/"), { });
1824     testRequest(searchBackend, mainDocumentRequest("zzz://www.afyyy.xxx/"), { });
1825     testRequest(searchBackend, mainDocumentRequest("zzz://www.agyyy.xxx/"), { });
1826     testRequest(searchBackend, mainDocumentRequest("zzz://www.ahyyy.xxx/"), { });
1827     testRequest(searchBackend, mainDocumentRequest("zzz://www.aiyyy.xxx/"), { });
1828     testRequest(searchBackend, mainDocumentRequest("zzz://www.ajyyy.xxx/"), { });
1829     testRequest(searchBackend, mainDocumentRequest("zzz://www.akyyy.xxx/"), { });
1830
1831     // 'b' is the first character of the second rule.
1832     testRequest(searchBackend, mainDocumentRequest("zzz://www.byyy.xxx/"), { });
1833     testRequest(searchBackend, mainDocumentRequest("zzz://www.bayyy.xxx/"), { });
1834     testRequest(searchBackend, mainDocumentRequest("zzz://www.bbyyy.xxx/"), { });
1835     testRequest(searchBackend, mainDocumentRequest("zzz://www.bcyyy.xxx/"), { });
1836     testRequest(searchBackend, mainDocumentRequest("zzz://www.bdyyy.xxx/"), { });
1837     testRequest(searchBackend, mainDocumentRequest("zzz://www.beyyy.xxx/"), { });
1838     testRequest(searchBackend, mainDocumentRequest("zzz://www.bfyyy.xxx/"), { });
1839     testRequest(searchBackend, mainDocumentRequest("zzz://www.bgyyy.xxx/"), { });
1840     testRequest(searchBackend, mainDocumentRequest("zzz://www.bhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1841     testRequest(searchBackend, mainDocumentRequest("zzz://www.biyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1842     testRequest(searchBackend, mainDocumentRequest("zzz://www.bjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1843     testRequest(searchBackend, mainDocumentRequest("zzz://www.bkyyy.xxx/"), { });
1844
1845     // 'c' is the first character of the first rule, and it overlaps the first character of the second rule.
1846     testRequest(searchBackend, mainDocumentRequest("zzz://www.cyyy.xxx/"), { });
1847     testRequest(searchBackend, mainDocumentRequest("zzz://www.cayyy.xxx/"), { });
1848     testRequest(searchBackend, mainDocumentRequest("zzz://www.cbyyy.xxx/"), { });
1849     testRequest(searchBackend, mainDocumentRequest("zzz://www.ccyyy.xxx/"), { });
1850     testRequest(searchBackend, mainDocumentRequest("zzz://www.cdyyy.xxx/"), { });
1851     testRequest(searchBackend, mainDocumentRequest("zzz://www.ceyyy.xxx/"), { });
1852     testRequest(searchBackend, mainDocumentRequest("zzz://www.cfyyy.xxx/"), { });
1853     testRequest(searchBackend, mainDocumentRequest("zzz://www.cgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1854     testRequest(searchBackend, mainDocumentRequest("zzz://www.chyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1855     testRequest(searchBackend, mainDocumentRequest("zzz://www.ciyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1856     testRequest(searchBackend, mainDocumentRequest("zzz://www.cjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1857     testRequest(searchBackend, mainDocumentRequest("zzz://www.ckyyy.xxx/"), { });
1858
1859     // 'd' is in the first range of both rule. This series cover overlaps between the two rules.
1860     testRequest(searchBackend, mainDocumentRequest("zzz://www.dgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1861     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1862     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1863     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1864     testRequest(searchBackend, mainDocumentRequest("zzz://www.degyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1865     testRequest(searchBackend, mainDocumentRequest("zzz://www.dehyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1866     testRequest(searchBackend, mainDocumentRequest("zzz://www.dfgyyy.xxx/"), { });
1867     testRequest(searchBackend, mainDocumentRequest("zzz://www.dfhyyy.xxx/"), { });
1868     testRequest(searchBackend, mainDocumentRequest("zzz://www.djyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1869     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1870     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1871 }
1872
1873 TEST_F(ContentExtensionTest, QuantifiedOneOrMoreRangesCase11And13InGroups)
1874 {
1875     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"([c-e])+([g-i]+YYY)\"}},"
1876         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[b-d]+[h-j]+YYY\"}}]");
1877
1878     // The interesting ranges only match between 'b' and 'k', plus a gap in 'f'.
1879     testRequest(searchBackend, mainDocumentRequest("zzz://www.aayyy.xxx/"), { });
1880     testRequest(searchBackend, mainDocumentRequest("zzz://www.abyyy.xxx/"), { });
1881     testRequest(searchBackend, mainDocumentRequest("zzz://www.acyyy.xxx/"), { });
1882     testRequest(searchBackend, mainDocumentRequest("zzz://www.adyyy.xxx/"), { });
1883     testRequest(searchBackend, mainDocumentRequest("zzz://www.aeyyy.xxx/"), { });
1884     testRequest(searchBackend, mainDocumentRequest("zzz://www.afyyy.xxx/"), { });
1885     testRequest(searchBackend, mainDocumentRequest("zzz://www.agyyy.xxx/"), { });
1886     testRequest(searchBackend, mainDocumentRequest("zzz://www.ahyyy.xxx/"), { });
1887     testRequest(searchBackend, mainDocumentRequest("zzz://www.aiyyy.xxx/"), { });
1888     testRequest(searchBackend, mainDocumentRequest("zzz://www.ajyyy.xxx/"), { });
1889     testRequest(searchBackend, mainDocumentRequest("zzz://www.akyyy.xxx/"), { });
1890
1891     // 'b' is the first character of the second rule.
1892     testRequest(searchBackend, mainDocumentRequest("zzz://www.byyy.xxx/"), { });
1893     testRequest(searchBackend, mainDocumentRequest("zzz://www.bayyy.xxx/"), { });
1894     testRequest(searchBackend, mainDocumentRequest("zzz://www.bbyyy.xxx/"), { });
1895     testRequest(searchBackend, mainDocumentRequest("zzz://www.bcyyy.xxx/"), { });
1896     testRequest(searchBackend, mainDocumentRequest("zzz://www.bdyyy.xxx/"), { });
1897     testRequest(searchBackend, mainDocumentRequest("zzz://www.beyyy.xxx/"), { });
1898     testRequest(searchBackend, mainDocumentRequest("zzz://www.bfyyy.xxx/"), { });
1899     testRequest(searchBackend, mainDocumentRequest("zzz://www.bgyyy.xxx/"), { });
1900     testRequest(searchBackend, mainDocumentRequest("zzz://www.bhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1901     testRequest(searchBackend, mainDocumentRequest("zzz://www.biyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1902     testRequest(searchBackend, mainDocumentRequest("zzz://www.bjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1903     testRequest(searchBackend, mainDocumentRequest("zzz://www.bkyyy.xxx/"), { });
1904
1905     // 'c' is the first character of the first rule, and it overlaps the first character of the second rule.
1906     testRequest(searchBackend, mainDocumentRequest("zzz://www.cyyy.xxx/"), { });
1907     testRequest(searchBackend, mainDocumentRequest("zzz://www.cayyy.xxx/"), { });
1908     testRequest(searchBackend, mainDocumentRequest("zzz://www.cbyyy.xxx/"), { });
1909     testRequest(searchBackend, mainDocumentRequest("zzz://www.ccyyy.xxx/"), { });
1910     testRequest(searchBackend, mainDocumentRequest("zzz://www.cdyyy.xxx/"), { });
1911     testRequest(searchBackend, mainDocumentRequest("zzz://www.ceyyy.xxx/"), { });
1912     testRequest(searchBackend, mainDocumentRequest("zzz://www.cfyyy.xxx/"), { });
1913     testRequest(searchBackend, mainDocumentRequest("zzz://www.cgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1914     testRequest(searchBackend, mainDocumentRequest("zzz://www.chyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1915     testRequest(searchBackend, mainDocumentRequest("zzz://www.ciyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1916     testRequest(searchBackend, mainDocumentRequest("zzz://www.cjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1917     testRequest(searchBackend, mainDocumentRequest("zzz://www.ckyyy.xxx/"), { });
1918
1919     // 'd' is in the first range of both rule. This series cover overlaps between the two rules.
1920     testRequest(searchBackend, mainDocumentRequest("zzz://www.dgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1921     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1922     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1923     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1924     testRequest(searchBackend, mainDocumentRequest("zzz://www.degyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1925     testRequest(searchBackend, mainDocumentRequest("zzz://www.dehyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1926     testRequest(searchBackend, mainDocumentRequest("zzz://www.dfgyyy.xxx/"), { });
1927     testRequest(searchBackend, mainDocumentRequest("zzz://www.dfhyyy.xxx/"), { });
1928     testRequest(searchBackend, mainDocumentRequest("zzz://www.djyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1929     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1930     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1931 }
1932
1933 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase1)
1934 {
1935     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[a-m]\"}},"
1936         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"^(bar)*[c-e]\"}}]");
1937
1938     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1939     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1940     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { }, true);
1941     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { }, true);
1942     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { }, true);
1943     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1944     testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1945     testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
1946
1947     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[a-m]\"}},"
1948         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"(bar)*[c-e]\"}}]");
1949     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1950     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1951     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { }, true);
1952     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { }, true);
1953     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { }, true);
1954     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1955     testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1956     testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
1957 }
1958
1959
1960 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase2)
1961 {
1962     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[a-m]\"}},"
1963         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"^(bar)*b\"}}]");
1964
1965     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1966     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { }, true);
1967     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1968     testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
1969     testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
1970
1971     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[a-m]\"}},"
1972         "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"(bar)*l\"}}]");
1973     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1974     testRequest(searchBackend, mainDocumentRequest("zzz://www.k.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1975     testRequest(searchBackend, mainDocumentRequest("zzz://www.l.xxx/"), { }, true);
1976     testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::BlockLoad });
1977     testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
1978 }
1979
1980 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase3)
1981 {
1982     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[b-d]\"}},"
1983         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[a-m]\"}}]");
1984
1985     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1986     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1987     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1988     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1989     testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1990     testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
1991
1992     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[b-d]\"}},"
1993         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[a-m]\"}}]");
1994     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1995     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1996     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
1997     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1998     testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
1999     testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
2000 }
2001
2002 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase4)
2003 {
2004     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*l\"}},"
2005         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[a-m]\"}}]");
2006
2007     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2008     testRequest(matchBackend, mainDocumentRequest("k://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2009     testRequest(matchBackend, mainDocumentRequest("l://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2010     testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2011     testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
2012
2013     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*l\"}},"
2014         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[a-m]\"}}]");
2015     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2016     testRequest(searchBackend, mainDocumentRequest("zzz://www.k.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2017     testRequest(searchBackend, mainDocumentRequest("zzz://www.l.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2018     testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2019     testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
2020 }
2021
2022 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase5)
2023 {
2024     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[a-e]\"}},"
2025         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[e-h]\"}}]");
2026
2027     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2028     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2029     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2030     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2031     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2032     testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
2033
2034     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[a-e]\"}},"
2035         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[e-h]\"}}]");
2036     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2037     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2038     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2039     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2040     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2041     testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
2042 }
2043
2044 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase6)
2045 {
2046     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*e\"}},"
2047         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[e-h]\"}}]");
2048
2049     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
2050     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
2051     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2052     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2053     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2054     testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
2055
2056     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*e\"}},"
2057         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[e-h]\"}}]");
2058     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
2059     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
2060     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2061     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2062     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2063     testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
2064 }
2065
2066 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase7)
2067 {
2068     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[a-e]\"}},"
2069         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*e\"}}]");
2070
2071     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2072     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2073     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2074     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { });
2075
2076     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[a-e]\"}},"
2077         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*e\"}}]");
2078     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2079     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2080     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2081     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { });
2082 }
2083
2084 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase8)
2085 {
2086     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[e-h]\"}},"
2087         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[a-e]\"}}]");
2088
2089     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2090     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2091     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2092     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2093     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2094     testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
2095
2096     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[e-h]\"}},"
2097         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[a-e]\"}}]");
2098     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2099     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2100     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2101     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2102     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2103     testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
2104 }
2105
2106 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase9)
2107 {
2108     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*e\"}},"
2109         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[a-e]\"}}]");
2110
2111     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2112     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2113     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2114     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { });
2115
2116     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*e\"}},"
2117         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[a-e]\"}}]");
2118     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2119     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2120     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2121     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { });
2122 }
2123
2124 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase10)
2125 {
2126     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[e-h]\"}},"
2127         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*e\"}}]");
2128
2129     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
2130     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
2131     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2132     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2133     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2134     testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
2135
2136     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[e-h]\"}},"
2137         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*e\"}}]");
2138     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
2139     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
2140     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2141     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2142     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2143     testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
2144 }
2145
2146 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase11)
2147 {
2148     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[e-g]\"}},"
2149         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[d-f]\"}}]");
2150
2151     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { });
2152     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2153     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2154     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2155     testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2156     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
2157
2158     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[e-g]\"}},"
2159         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[d-f]\"}}]");
2160     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { });
2161     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2162     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2163     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2164     testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2165     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
2166 }
2167
2168
2169 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase12)
2170 {
2171     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[e-g]\"}},"
2172         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[d-g]\"}}]");
2173
2174     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { });
2175     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2176     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2177     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2178     testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2179     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
2180
2181     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[e-g]\"}},"
2182         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[d-g]\"}}]");
2183     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { });
2184     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2185     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2186     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2187     testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2188     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
2189 }
2190
2191 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase13)
2192 {
2193     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[b-d]\"}},"
2194         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[c-e]\"}}]");
2195
2196     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
2197     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2198     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2199     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2200     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2201     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
2202
2203     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[b-d]\"}},"
2204         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[c-e]\"}}]");
2205     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
2206     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2207     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2208     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2209     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2210     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
2211 }
2212
2213 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase14)
2214 {
2215     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[b-e]\"}},"
2216         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[c-e]\"}}]");
2217
2218     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
2219     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
2220     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2221     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2222     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2223     testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
2224
2225     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[b-e]\"}},"
2226         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[c-e]\"}}]");
2227     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
2228     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2229     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2230     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2231     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2232     testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
2233 }
2234
2235 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase15)
2236 {
2237     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[c-f]\"}},"
2238         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[c-f]\"}}]");
2239
2240     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
2241     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { });
2242     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2243     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2244     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2245     testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2246     testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { });
2247
2248     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[c-f]\"}},"
2249         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[c-f]\"}}]");
2250     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
2251     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { });
2252     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2253     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2254     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2255     testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2256     testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { });
2257 }
2258
2259 TEST_F(ContentExtensionTest, CombinedRangeOverlapCase16)
2260 {
2261     auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*c\"}},"
2262         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*c\"}}]");
2263
2264     testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
2265     testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { });
2266     testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2267     testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
2268     testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { });
2269
2270     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*c\"}},"
2271         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*c\"}}]");
2272     testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
2273     testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { });
2274     testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2275     testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
2276     testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { });
2277 }
2278
2279 TEST_F(ContentExtensionTest, CombinedQuantifiedOneOrMoreRangesCase11And13)
2280 {
2281     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[c-e]+[g-i]+YYY\"}},"
2282         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[b-d]+[h-j]+YYY\"}}]");
2283
2284     // The interesting ranges only match between 'b' and 'k', plus a gap in 'f'.
2285     testRequest(searchBackend, mainDocumentRequest("zzz://www.aayyy.xxx/"), { });
2286     testRequest(searchBackend, mainDocumentRequest("zzz://www.abyyy.xxx/"), { });
2287     testRequest(searchBackend, mainDocumentRequest("zzz://www.acyyy.xxx/"), { });
2288     testRequest(searchBackend, mainDocumentRequest("zzz://www.adyyy.xxx/"), { });
2289     testRequest(searchBackend, mainDocumentRequest("zzz://www.aeyyy.xxx/"), { });
2290     testRequest(searchBackend, mainDocumentRequest("zzz://www.afyyy.xxx/"), { });
2291     testRequest(searchBackend, mainDocumentRequest("zzz://www.agyyy.xxx/"), { });
2292     testRequest(searchBackend, mainDocumentRequest("zzz://www.ahyyy.xxx/"), { });
2293     testRequest(searchBackend, mainDocumentRequest("zzz://www.aiyyy.xxx/"), { });
2294     testRequest(searchBackend, mainDocumentRequest("zzz://www.ajyyy.xxx/"), { });
2295     testRequest(searchBackend, mainDocumentRequest("zzz://www.akyyy.xxx/"), { });
2296
2297     // 'b' is the first character of the second rule.
2298     testRequest(searchBackend, mainDocumentRequest("zzz://www.byyy.xxx/"), { });
2299     testRequest(searchBackend, mainDocumentRequest("zzz://www.bayyy.xxx/"), { });
2300     testRequest(searchBackend, mainDocumentRequest("zzz://www.bbyyy.xxx/"), { });
2301     testRequest(searchBackend, mainDocumentRequest("zzz://www.bcyyy.xxx/"), { });
2302     testRequest(searchBackend, mainDocumentRequest("zzz://www.bdyyy.xxx/"), { });
2303     testRequest(searchBackend, mainDocumentRequest("zzz://www.beyyy.xxx/"), { });
2304     testRequest(searchBackend, mainDocumentRequest("zzz://www.bfyyy.xxx/"), { });
2305     testRequest(searchBackend, mainDocumentRequest("zzz://www.bgyyy.xxx/"), { });
2306     testRequest(searchBackend, mainDocumentRequest("zzz://www.bhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2307     testRequest(searchBackend, mainDocumentRequest("zzz://www.biyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2308     testRequest(searchBackend, mainDocumentRequest("zzz://www.bjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2309     testRequest(searchBackend, mainDocumentRequest("zzz://www.bkyyy.xxx/"), { });
2310
2311     // 'c' is the first character of the first rule, and it overlaps the first character of the second rule.
2312     testRequest(searchBackend, mainDocumentRequest("zzz://www.cyyy.xxx/"), { });
2313     testRequest(searchBackend, mainDocumentRequest("zzz://www.cayyy.xxx/"), { });
2314     testRequest(searchBackend, mainDocumentRequest("zzz://www.cbyyy.xxx/"), { });
2315     testRequest(searchBackend, mainDocumentRequest("zzz://www.ccyyy.xxx/"), { });
2316     testRequest(searchBackend, mainDocumentRequest("zzz://www.cdyyy.xxx/"), { });
2317     testRequest(searchBackend, mainDocumentRequest("zzz://www.ceyyy.xxx/"), { });
2318     testRequest(searchBackend, mainDocumentRequest("zzz://www.cfyyy.xxx/"), { });
2319     testRequest(searchBackend, mainDocumentRequest("zzz://www.cgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2320     testRequest(searchBackend, mainDocumentRequest("zzz://www.chyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2321     testRequest(searchBackend, mainDocumentRequest("zzz://www.ciyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2322     testRequest(searchBackend, mainDocumentRequest("zzz://www.cjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2323     testRequest(searchBackend, mainDocumentRequest("zzz://www.ckyyy.xxx/"), { });
2324
2325     // 'd' is in the first range of both rule. This series cover overlaps between the two rules.
2326     testRequest(searchBackend, mainDocumentRequest("zzz://www.dgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2327     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2328     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2329     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2330     testRequest(searchBackend, mainDocumentRequest("zzz://www.degyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2331     testRequest(searchBackend, mainDocumentRequest("zzz://www.dehyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2332     testRequest(searchBackend, mainDocumentRequest("zzz://www.dfgyyy.xxx/"), { });
2333     testRequest(searchBackend, mainDocumentRequest("zzz://www.dfhyyy.xxx/"), { });
2334     testRequest(searchBackend, mainDocumentRequest("zzz://www.djyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2335     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2336     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2337 }
2338
2339 TEST_F(ContentExtensionTest, CombinedQuantifiedOneOrMoreRangesCase11And13InGroups)
2340 {
2341     auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*([c-e])+([g-i]+YYY)\"}},"
2342         "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[b-d]+[h-j]+YYY\"}}]");
2343
2344     // The interesting ranges only match between 'b' and 'k', plus a gap in 'f'.
2345     testRequest(searchBackend, mainDocumentRequest("zzz://www.aayyy.xxx/"), { });
2346     testRequest(searchBackend, mainDocumentRequest("zzz://www.abyyy.xxx/"), { });
2347     testRequest(searchBackend, mainDocumentRequest("zzz://www.acyyy.xxx/"), { });
2348     testRequest(searchBackend, mainDocumentRequest("zzz://www.adyyy.xxx/"), { });
2349     testRequest(searchBackend, mainDocumentRequest("zzz://www.aeyyy.xxx/"), { });
2350     testRequest(searchBackend, mainDocumentRequest("zzz://www.afyyy.xxx/"), { });
2351     testRequest(searchBackend, mainDocumentRequest("zzz://www.agyyy.xxx/"), { });
2352     testRequest(searchBackend, mainDocumentRequest("zzz://www.ahyyy.xxx/"), { });
2353     testRequest(searchBackend, mainDocumentRequest("zzz://www.aiyyy.xxx/"), { });
2354     testRequest(searchBackend, mainDocumentRequest("zzz://www.ajyyy.xxx/"), { });
2355     testRequest(searchBackend, mainDocumentRequest("zzz://www.akyyy.xxx/"), { });
2356
2357     // 'b' is the first character of the second rule.
2358     testRequest(searchBackend, mainDocumentRequest("zzz://www.byyy.xxx/"), { });
2359     testRequest(searchBackend, mainDocumentRequest("zzz://www.bayyy.xxx/"), { });
2360     testRequest(searchBackend, mainDocumentRequest("zzz://www.bbyyy.xxx/"), { });
2361     testRequest(searchBackend, mainDocumentRequest("zzz://www.bcyyy.xxx/"), { });
2362     testRequest(searchBackend, mainDocumentRequest("zzz://www.bdyyy.xxx/"), { });
2363     testRequest(searchBackend, mainDocumentRequest("zzz://www.beyyy.xxx/"), { });
2364     testRequest(searchBackend, mainDocumentRequest("zzz://www.bfyyy.xxx/"), { });
2365     testRequest(searchBackend, mainDocumentRequest("zzz://www.bgyyy.xxx/"), { });
2366     testRequest(searchBackend, mainDocumentRequest("zzz://www.bhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2367     testRequest(searchBackend, mainDocumentRequest("zzz://www.biyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2368     testRequest(searchBackend, mainDocumentRequest("zzz://www.bjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2369     testRequest(searchBackend, mainDocumentRequest("zzz://www.bkyyy.xxx/"), { });
2370
2371     // 'c' is the first character of the first rule, and it overlaps the first character of the second rule.
2372     testRequest(searchBackend, mainDocumentRequest("zzz://www.cyyy.xxx/"), { });
2373     testRequest(searchBackend, mainDocumentRequest("zzz://www.cayyy.xxx/"), { });
2374     testRequest(searchBackend, mainDocumentRequest("zzz://www.cbyyy.xxx/"), { });
2375     testRequest(searchBackend, mainDocumentRequest("zzz://www.ccyyy.xxx/"), { });
2376     testRequest(searchBackend, mainDocumentRequest("zzz://www.cdyyy.xxx/"), { });
2377     testRequest(searchBackend, mainDocumentRequest("zzz://www.ceyyy.xxx/"), { });
2378     testRequest(searchBackend, mainDocumentRequest("zzz://www.cfyyy.xxx/"), { });
2379     testRequest(searchBackend, mainDocumentRequest("zzz://www.cgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2380     testRequest(searchBackend, mainDocumentRequest("zzz://www.chyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2381     testRequest(searchBackend, mainDocumentRequest("zzz://www.ciyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2382     testRequest(searchBackend, mainDocumentRequest("zzz://www.cjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2383     testRequest(searchBackend, mainDocumentRequest("zzz://www.ckyyy.xxx/"), { });
2384
2385     // 'd' is in the first range of both rule. This series cover overlaps between the two rules.
2386     testRequest(searchBackend, mainDocumentRequest("zzz://www.dgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2387     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2388     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2389     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
2390     testRequest(searchBackend, mainDocumentRequest("zzz://www.degyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2391     testRequest(searchBackend, mainDocumentRequest("zzz://www.dehyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
2392     testRequest(searchBackend, mainDocumentRequest("zzz://www.dfgyyy.xxx/"), { });
2393     testRequest(searchBackend, mainDocumentRequest("zzz://www.dfhyyy.xxx/"), { });
2394     testRequest(searchBackend, mainDocumentRequest("zzz://www.djyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2395     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2396     testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
2397 }
2398
2399 } // namespace TestWebKitAPI